Re: [PATCH] PCIe hotplug: decline to manage slots under HP PCIe host bridge

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Bjorn Helgaas wrote:
This patch prevents the use of PCIe native hotplug on slots below certain
HP PCIe host bridges.

A silicon defect in these host bridges causes a machine check after
powering on certain devices.  The ACPI hotplug methods contain workarounds
for the defect, so ACPI hotplug works correctly.

The pciehp driver requests permission to use PCI Express native hotplug by
using _OSC; I think the firmware should have refused that request.  Since
firmware grants the request, we have to work around it by hand.

See HP internal defect RS1899.  MCA observed with a QLogic ISP2432 4Gb HBA
(firmware 4.00.70) in slot 5 of an HP rx3600 (system firmware 04.11) with
a PCIe backplane.  Slot 5 is directly connected to the PCIe host bridge.
The MCA does not occur with the QLogic HBA in slot 3, which has an IDT
switch between the host bridge and the HBA.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@xxxxxx>
---
 drivers/pci/hotplug/acpi_pcihp.c |   22 +++++++++++++++++++++-
 1 files changed, 21 insertions(+), 1 deletions(-)

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;
+}
+

The acpi_pcihp.c is not pciehp specific. So I think non pciehp
specific function name is better.

 /**
  * 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;


I think we need this kind of quirk before calling acpi_pci_osc_control_set()
because firmware might change its behavior after _OSC evaluation.

Thanks,
Kenji Kaneshige


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux