diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 9ef4e989afc4..1e125b56c9a9 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -1282,7 +1282,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) | |||
1282 | /** | 1282 | /** |
1283 | * acpiphp_eject_slot - physically eject the slot | 1283 | * acpiphp_eject_slot - physically eject the slot |
1284 | */ | 1284 | */ |
1285 | static int acpiphp_eject_slot(struct acpiphp_slot *slot) | 1285 | int acpiphp_eject_slot(struct acpiphp_slot *slot) |
1286 | { | 1286 | { |
1287 | acpi_status status; | 1287 | acpi_status status; |
1288 | struct acpiphp_func *func; | 1288 | struct acpiphp_func *func; |
@@ -1368,6 +1368,9 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) | |||
1368 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | 1368 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) |
1369 | return; | 1369 | return; |
1370 | 1370 | ||
1371 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
1372 | return; | ||
1373 | |||
1371 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, | 1374 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, |
1372 | bridge->hpp.t0->cache_line_size); | 1375 | bridge->hpp.t0->cache_line_size); |
1373 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, | 1376 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, |
@@ -1502,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type) | |||
1502 | * ACPI event handlers | 1505 | * ACPI event handlers |
1503 | */ | 1506 | */ |
1504 | 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 | |||
1505 | /** | 1539 | /** |
1506 | * handle_hotplug_event_bridge - handle ACPI event on bridges | 1540 | * handle_hotplug_event_bridge - handle ACPI event on bridges |
1507 | * | 1541 | * |
@@ -1519,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1519 | struct acpi_buffer buffer = { .length = sizeof(objname), | 1553 | struct acpi_buffer buffer = { .length = sizeof(objname), |
1520 | .pointer = objname }; | 1554 | .pointer = objname }; |
1521 | struct acpi_device *device; | 1555 | struct acpi_device *device; |
1556 | int num_sub_bridges = 0; | ||
1522 | 1557 | ||
1523 | if (acpi_bus_get_device(handle, &device)) { | 1558 | if (acpi_bus_get_device(handle, &device)) { |
1524 | /* This bridge must have just been physically inserted */ | 1559 | /* This bridge must have just been physically inserted */ |
@@ -1527,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1527 | } | 1562 | } |
1528 | 1563 | ||
1529 | bridge = acpiphp_handle_to_bridge(handle); | 1564 | bridge = acpiphp_handle_to_bridge(handle); |
1530 | 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) { | ||
1531 | err("cannot get bridge info\n"); | 1571 | err("cannot get bridge info\n"); |
1532 | return; | 1572 | return; |
1533 | } | 1573 | } |
@@ -1538,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont | |||
1538 | case ACPI_NOTIFY_BUS_CHECK: | 1578 | case ACPI_NOTIFY_BUS_CHECK: |
1539 | /* bus re-enumerate */ | 1579 | /* bus re-enumerate */ |
1540 | dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); | 1580 | dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); |
1541 | 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); | ||
1542 | break; | 1589 | break; |
1543 | 1590 | ||
1544 | case ACPI_NOTIFY_DEVICE_CHECK: | 1591 | case ACPI_NOTIFY_DEVICE_CHECK: |