aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c85
1 files changed, 52 insertions, 33 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e9a71ed9954..3f6ec0dd4fb 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -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)) {