Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1408

kernel-2.6.18-238.el5.src.rpm

From: Konrad Rzeszutek <konradr@redhat.com>
Date: Thu, 19 Jul 2007 12:20:15 -0400
Subject: [hotplug] acpiphp: 'cannot get bridge info' with PCIe
Message-id: 20070719162015.GA24616@mars.boston.redhat.com
O-Subject: [RHEL5 U1 PATCH] RHBZ #248571: LTC36136-acpiphp 'cannot get bridge info' hotplug failure with PCIe adapter on x3850
Bugzilla: 248571

RHBZ#:
------
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=248571

Description:
------------
A hot-add operation involving a PCIe adapter fails on the
x3850 with the ACPI PCI hotplug driver 'acpiphp' message
"acpiphp_glue: cannot get bridge info".

Root cause:
 On the x3850 the ACPI bus check event generated when a
 PCIe adapter is inserted/latched references the ACPI object
 for the PCI host bridge that is higher in the ACPI hierarchy
 than the PCI-to-PCI bridge immediately above slot receiving
 the adapter.  This is allowed by the ACPI spec but the current
 'acpiphp' code expects the bus check event to always reference
 the bridge immediately above the slot.  If there are no slots
 immediately below the bridge against which the event was
 received the code does not currently explore below this bridge
 and re-enumerate slots that may be located under lower level
 PCI-to-PCI bridge(s).

RHEL Version Found:
------------------
RHEL5 U1

kABI status:
------------
No symbols changed/deleted or added.

Brew build:
-----------
Built on all platforms (scratch build: 878512).

Upstream Status:
----------------
The proposed fix has been signed off by Kristen Carlson Accardi and Greg
Kroah-Hartman and is now in Greg's 2.6 tree.
tree:
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/
file:
pci-hotplug-acpiphp-avoid-acpiphp-cannot-get-bridge-info-pci-hotplug-failure.patch

Test Status:
------------
Tested on IBM x3850 in Westford, MA. Without the patch the PCI-E hotplug
doesn't work. With the patch the cards get their driver loaded. I would like
to test this on other non-IBM boxes that have PCI-E hotplug capability
- anybody know specifically which machines can do this?

Proposed Patch:
---------------
This patch builds/applies cleanly on top of 2.6.18-34.

Signed-off-by: Gary Hade <garyhade@us.ibm.com>

Acked-by: Pete Zaitcev <zaitcev@redhat.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   48 ++++++++++++++++++++++++++++++++++-
 1 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 8930f8e..a67702f 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1503,6 +1503,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
  * ACPI event handlers
  */
 
+static acpi_status
+count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	int *count = (int *)context;
+	struct acpiphp_bridge *bridge;
+
+	bridge = acpiphp_handle_to_bridge(handle);
+	if (bridge)
+		(*count)++;
+	return AE_OK ;
+}
+
+static acpi_status
+check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	struct acpiphp_bridge *bridge;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+
+	bridge = acpiphp_handle_to_bridge(handle);
+	if (bridge) {
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+		dbg("%s: re-enumerating slots under %s\n",
+			__FUNCTION__, objname);
+		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+		acpiphp_check_bridge(bridge);
+	}
+	return AE_OK ;
+}
+
 /**
  * handle_hotplug_event_bridge - handle ACPI event on bridges
  *
@@ -1520,6 +1551,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
 	struct acpi_buffer buffer = { .length = sizeof(objname),
 				      .pointer = objname };
 	struct acpi_device *device;
+	int num_sub_bridges = 0;
 
 	if (acpi_bus_get_device(handle, &device)) {
 		/* This bridge must have just been physically inserted */
@@ -1528,7 +1560,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
 	}
 
 	bridge = acpiphp_handle_to_bridge(handle);
-	if (!bridge) {
+	if (type == ACPI_NOTIFY_BUS_CHECK) {
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
+			count_sub_bridges, &num_sub_bridges, NULL);
+	}
+
+	if (!bridge && !num_sub_bridges) {
 		err("cannot get bridge info\n");
 		return;
 	}
@@ -1539,7 +1576,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
 		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-		acpiphp_check_bridge(bridge);
+		if (bridge) {
+			dbg("%s: re-enumerating slots under %s\n",
+				__FUNCTION__, objname);
+			acpiphp_check_bridge(bridge);
+		}
+		if (num_sub_bridges)
+			acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+				ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-- 
1.5.3.5.645.gbb47