|
@@ -1505,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
|
|
* ACPI event handlers
|
|
* 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
|
|
* handle_hotplug_event_bridge - handle ACPI event on bridges
|
|
*
|
|
*
|
|
@@ -1522,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
|
|
struct acpi_buffer buffer = { .length = sizeof(objname),
|
|
struct acpi_buffer buffer = { .length = sizeof(objname),
|
|
.pointer = objname };
|
|
.pointer = objname };
|
|
struct acpi_device *device;
|
|
struct acpi_device *device;
|
|
|
|
+ int num_sub_bridges = 0;
|
|
|
|
|
|
if (acpi_bus_get_device(handle, &device)) {
|
|
if (acpi_bus_get_device(handle, &device)) {
|
|
/* This bridge must have just been physically inserted */
|
|
/* 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
|
|
}
|
|
}
|
|
|
|
|
|
bridge = acpiphp_handle_to_bridge(handle);
|
|
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");
|
|
err("cannot get bridge info\n");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1541,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
|
|
case ACPI_NOTIFY_BUS_CHECK:
|
|
case ACPI_NOTIFY_BUS_CHECK:
|
|
/* bus re-enumerate */
|
|
/* bus re-enumerate */
|
|
dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
|
|
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;
|
|
break;
|
|
|
|
|
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
|
case ACPI_NOTIFY_DEVICE_CHECK:
|