diff mbox

PCIe hotplug: decline to manage slots under HP PCIe host bridge

Message ID 20090930205039.26785.59632.stgit@bob.kio (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Bjorn Helgaas Sept. 30, 2009, 8:50 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index a73028e..24e6687 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -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 };