|
@@ -1703,24 +1703,47 @@ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
|
|
|
+ const struct acpi_device_id **matchid)
|
|
|
+{
|
|
|
+ struct acpi_scan_handler *handler;
|
|
|
+
|
|
|
+ list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
|
|
|
+ if (acpi_scan_handler_matching(handler, idstr, matchid))
|
|
|
+ return handler;
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
static acpi_status acpi_scan_hotplug_modify(acpi_handle handle,
|
|
|
u32 lvl_not_used, void *data,
|
|
|
void **ret_not_used)
|
|
|
{
|
|
|
- struct acpi_scan_handler *handler = data;
|
|
|
- struct acpi_device_info *info;
|
|
|
+ struct acpi_device_pnp pnp = {};
|
|
|
+ struct acpi_scan_handler *tgt_handler = data, *handler;
|
|
|
+ struct acpi_hardware_id *hwid;
|
|
|
+ unsigned long long sta_not_used;
|
|
|
+ int type;
|
|
|
bool match = false;
|
|
|
|
|
|
- if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
|
|
|
+ if (acpi_bus_type_and_status(handle, &type, &sta_not_used))
|
|
|
+ return AE_OK;
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&pnp.ids);
|
|
|
+ acpi_set_pnp_ids(handle, &pnp, type);
|
|
|
+
|
|
|
+ if (!pnp.type.hardware_id)
|
|
|
return AE_OK;
|
|
|
|
|
|
- if (info->valid & ACPI_VALID_HID) {
|
|
|
- char *idstr = info->hardware_id.string;
|
|
|
- match = acpi_scan_handler_matching(handler, idstr, NULL);
|
|
|
+ list_for_each_entry(hwid, &pnp.ids, list) {
|
|
|
+ handler = acpi_scan_match_handler(hwid->id, NULL);
|
|
|
+ if (handler && handler == tgt_handler) {
|
|
|
+ match = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- kfree(info);
|
|
|
if (!match)
|
|
|
- return AE_OK;
|
|
|
+ goto out;
|
|
|
|
|
|
if (handler->hotplug.enabled)
|
|
|
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
|
@@ -1729,6 +1752,8 @@ static acpi_status acpi_scan_hotplug_modify(acpi_handle handle,
|
|
|
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
|
|
acpi_hotplug_notify_cb);
|
|
|
|
|
|
+out:
|
|
|
+ acpi_free_pnp_ids(&pnp);
|
|
|
return AE_OK;
|
|
|
}
|
|
|
|
|
@@ -1749,40 +1774,34 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
|
|
|
mutex_unlock(&acpi_scan_lock);
|
|
|
}
|
|
|
|
|
|
-static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
|
|
|
- const struct acpi_device_id **matchid)
|
|
|
-{
|
|
|
- struct acpi_scan_handler *handler;
|
|
|
-
|
|
|
- list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
|
|
|
- if (acpi_scan_handler_matching(handler, idstr, matchid))
|
|
|
- return handler;
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-static void acpi_scan_init_hotplug(acpi_handle handle)
|
|
|
+static void acpi_scan_init_hotplug(acpi_handle handle, int type)
|
|
|
{
|
|
|
- struct acpi_device_info *info;
|
|
|
+ struct acpi_device_pnp pnp = {};
|
|
|
+ struct acpi_hardware_id *hwid;
|
|
|
struct acpi_scan_handler *handler;
|
|
|
|
|
|
- if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
|
|
|
- return;
|
|
|
+ INIT_LIST_HEAD(&pnp.ids);
|
|
|
+ acpi_set_pnp_ids(handle, &pnp, type);
|
|
|
|
|
|
- if (!(info->valid & ACPI_VALID_HID)) {
|
|
|
- kfree(info);
|
|
|
+ if (!pnp.type.hardware_id)
|
|
|
return;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* This relies on the fact that acpi_install_notify_handler() will not
|
|
|
* install the same notify handler routine twice for the same handle.
|
|
|
*/
|
|
|
- handler = acpi_scan_match_handler(info->hardware_id.string, NULL);
|
|
|
- kfree(info);
|
|
|
- if (handler && handler->hotplug.enabled)
|
|
|
- acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
|
|
- acpi_hotplug_notify_cb, NULL);
|
|
|
+ list_for_each_entry(hwid, &pnp.ids, list) {
|
|
|
+ handler = acpi_scan_match_handler(hwid->id, NULL);
|
|
|
+ if (handler) {
|
|
|
+ if (handler->hotplug.enabled)
|
|
|
+ acpi_install_notify_handler(handle,
|
|
|
+ ACPI_SYSTEM_NOTIFY,
|
|
|
+ acpi_hotplug_notify_cb, NULL);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ acpi_free_pnp_ids(&pnp);
|
|
|
}
|
|
|
|
|
|
static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
|
@@ -1807,7 +1826,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
|
|
|
return AE_OK;
|
|
|
}
|
|
|
|
|
|
- acpi_scan_init_hotplug(handle);
|
|
|
+ acpi_scan_init_hotplug(handle, type);
|
|
|
|
|
|
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
|
|
|
!(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
|