diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | 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 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 | ||
1508 | static acpi_status | ||
1509 | count_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 | |||
1520 | static acpi_status | ||
1521 | check_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: |