aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGary Hade <garyhade@us.ibm.com>2007-07-05 14:10:48 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-11 19:02:13 -0400
commit0bbd6424c55f0ab9e7fcd6a851bc49e265259ff5 (patch)
treead6f926e5dbee6af857fd047860571deccbb9b8c /drivers
parent9ef2241b18266d75319e7d66156243bd9010be44 (diff)
PCI: hotplug: acpiphp: avoid acpiphp "cannot get bridge info" PCI hotplug failure
On some systems, the ACPI bus check event can reference a bridge that is higher in the ACPI hierarchy than the bridge immediately above the hotplug PCI slot into which an adapter was just inserted. The current 'acpiphp' code expects the bus check event to reference the bridge immediately above the slot that received the adapter so the hotplug operation can fail on these systems with the message "acpiphp_glue: cannot get bridge info". This change fixes the problem by re-enumerating all slots that lie below the bridge referenced by the bus check event, including those slots that may be located under lower level PCI-to-PCI bridge(s). Signed-off-by: Gary Hade <garyhade@us.ibm.com> Cc: <lcm@us.ibm.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 72ec4a29a402..1e125b56c9a9 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1505,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
1505 * ACPI event handlers 1505 * ACPI event handlers
1506 */ 1506 */
1507 1507
1508static acpi_status
1509count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1510{
1511 int *count = (int *)context;
1512 struct acpiphp_bridge *bridge;
1513
1514 bridge = acpiphp_handle_to_bridge(handle);
1515 if (bridge)
1516 (*count)++;
1517 return AE_OK ;
1518}
1519
1520static acpi_status
1521check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1522{
1523 struct acpiphp_bridge *bridge;
1524 char objname[64];
1525 struct acpi_buffer buffer = { .length = sizeof(objname),
1526 .pointer = objname };
1527
1528 bridge = acpiphp_handle_to_bridge(handle);
1529 if (bridge) {
1530 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1531 dbg("%s: re-enumerating slots under %s\n",
1532 __FUNCTION__, objname);
1533 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1534 acpiphp_check_bridge(bridge);
1535 }
1536 return AE_OK ;
1537}
1538
1508/** 1539/**
1509 * handle_hotplug_event_bridge - handle ACPI event on bridges 1540 * handle_hotplug_event_bridge - handle ACPI event on bridges
1510 * 1541 *
@@ -1522,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1522 struct acpi_buffer buffer = { .length = sizeof(objname), 1553 struct acpi_buffer buffer = { .length = sizeof(objname),
1523 .pointer = objname }; 1554 .pointer = objname };
1524 struct acpi_device *device; 1555 struct acpi_device *device;
1556 int num_sub_bridges = 0;
1525 1557
1526 if (acpi_bus_get_device(handle, &device)) { 1558 if (acpi_bus_get_device(handle, &device)) {
1527 /* This bridge must have just been physically inserted */ 1559 /* This bridge must have just been physically inserted */
@@ -1530,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1530 } 1562 }
1531 1563
1532 bridge = acpiphp_handle_to_bridge(handle); 1564 bridge = acpiphp_handle_to_bridge(handle);
1533 if (!bridge) { 1565 if (type == ACPI_NOTIFY_BUS_CHECK) {
1566 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
1567 count_sub_bridges, &num_sub_bridges, NULL);
1568 }
1569
1570 if (!bridge && !num_sub_bridges) {
1534 err("cannot get bridge info\n"); 1571 err("cannot get bridge info\n");
1535 return; 1572 return;
1536 } 1573 }
@@ -1541,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1541 case ACPI_NOTIFY_BUS_CHECK: 1578 case ACPI_NOTIFY_BUS_CHECK:
1542 /* bus re-enumerate */ 1579 /* bus re-enumerate */
1543 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); 1580 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1544 acpiphp_check_bridge(bridge); 1581 if (bridge) {
1582 dbg("%s: re-enumerating slots under %s\n",
1583 __FUNCTION__, objname);
1584 acpiphp_check_bridge(bridge);
1585 }
1586 if (num_sub_bridges)
1587 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
1588 ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
1545 break; 1589 break;
1546 1590
1547 case ACPI_NOTIFY_DEVICE_CHECK: 1591 case ACPI_NOTIFY_DEVICE_CHECK: