@@ -324,6 +324,26 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
}
EXPORT_SYMBOL_GPL(pci_get_hp_params);
+static int pciehp_quirk(struct pci_dev *pdev, u32 flags)
+{
+ if (!(flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
+ return 0;
+
+ /*
+ * Some HP PCIe host bridges have defects in hotplug support. Firmware
+ * should decline to grant control, but it is also defective.
+ */
+ while (pdev) {
+ if (pdev->vendor == PCI_VENDOR_ID_HP &&
+ pdev->device == 0x403b) {
+ dev_info(&pdev->dev, "slot doesn't support PCIe native hotplug\n");
+ return -ENODEV;
+ }
+ pdev = pdev->bus->parent->self;
+ }
+ return 0;
+}
+
/**
* acpi_get_hp_hw_control_from_firmware
* @dev: the pci_dev of the bridge that has a hotplug controller
@@ -360,7 +380,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
dbg("Trying to get hotplug control for %s\n",
(char *)string.pointer);
status = acpi_pci_osc_control_set(handle, flags);
- if (ACPI_SUCCESS(status))
+ if (ACPI_SUCCESS(status) && !pciehp_quirk(pdev, flags))
goto got_one;
kfree(string.pointer);
string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };