From: Michal Schmidt <mschmidt@redhat.com> Date: Mon, 14 Sep 2009 16:25:43 +0200 Subject: [pci] pciehp: fix PCIe hotplug slot detection Message-id: 20090914162543.2f1ba5ae@brian.englab.brq.redhat.com O-Subject: [RHEL5.5 PATCH] pciehp: fix PCIe hotplug slot detection Bugzilla: 521731 RH-Acked-by: Stefan Assmann <sassmann@redhat.com> RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com> BZ: https://bugzilla.redhat.com/show_bug.cgi?id=521731 Description (from Kenji Kaneshige): OS native hotplug drivers (pciehp, shpchp, etc.) need to get hotplug control from firmware using ACPI _OSC or OSHP method. For this, the pciehp driver is doing as follows. (1) Scan PCI buses from hotplug slot to root until the PCI bridge that has corresponding ACPI device object is found. (2) Scan ACPI device object from the object obtained by step (1) to ACPI PCI root bridge object until ACPI device object that has _OSC or OSHP is found. (3) Run _OSC or OSHP method. The pciehp driver in RHEL5.x has a bug in step (1). It needs to scan parent buses, but it actually scans grand-parents. Because of this PCI device that has corresponding ACPI device object is not found on some platforms, and _OSC/OSHP evaluation fails as a result. Here is an example. root bus bus(a) bus(b) bus(c) | | | | |- bridge(a)- | - bridge(b) - | - bridge(c) - | - slot In this case, the pciehp driver needs to scan the buses/bridges as follows. bus(c)/bridge(c) -> bus(b)/bridge(b) -> bus(a)/bridge(a) -> root bus But it actually does as follows. bus(c)/bridge(c) -> bus(a)/bridge(a) Brew scratch build: https://brewweb.devel.redhat.com/taskinfo?taskID=1975407 Tested by the customer with success. Upstream status: Fixed in v2.6.30 as a side-effect of commit d391f00f0e7fb6d883c6724b31a1799e19a584c5. The proposed RHEL patch is a minimal fix for this issue. diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index a47ce33..ccc5855 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1308,9 +1308,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) * This hotplug controller was not listed in the ACPI name * space at all. Try to get acpi handle of parent pci bus. */ - if (!pdev || !pdev->bus->parent) + if (!pdev) break; - parent = pdev->bus->parent; + parent = pdev->bus; dbg("Could not find %s in acpi namespace, trying parent\n", pci_name(pdev)); if (!parent->self)