platform/x86: wmi: Decouple ACPI notify handler from wmi_block_list

Currently, the ACPI notify handler searches all WMI devices for
a matching WMI event device. This is inefficient since only WMI devices
associated with the notified ACPI device need to be searched.
Use the WMI bus device and device_for_each_child() to search for
a matching WMI event device instead.

Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20231218192420.305411-6-W_Armin@gmx.de
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Armin Wolf 2023-12-18 20:24:19 +01:00 committed by Hans de Goede
parent 095fa72a19
commit 2c933755ea

View file

@ -1176,24 +1176,13 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
}
}
static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
void *context)
static int wmi_notify_device(struct device *dev, void *data)
{
struct wmi_block *wblock = NULL, *iter;
struct wmi_block *wblock = dev_to_wblock(dev);
u32 *event = data;
list_for_each_entry(iter, &wmi_block_list, list) {
struct guid_block *block = &iter->gblock;
if (iter->acpi_device->handle == handle &&
(block->flags & ACPI_WMI_EVENT) &&
(block->notify_id == event)) {
wblock = iter;
break;
}
}
if (!wblock)
return;
if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event))
return 0;
/* If a driver is bound, then notify the driver. */
if (test_bit(WMI_PROBED, &wblock->flags) && wblock->dev.dev.driver) {
@ -1205,7 +1194,7 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
status = get_event_data(wblock, &evdata);
if (ACPI_FAILURE(status)) {
dev_warn(&wblock->dev.dev, "failed to get event data\n");
return;
return -EIO;
}
}
@ -1215,13 +1204,20 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
kfree(evdata.pointer);
} else if (wblock->handler) {
/* Legacy handler */
wblock->handler(event, wblock->handler_data);
wblock->handler(*event, wblock->handler_data);
}
acpi_bus_generate_netlink_event(
wblock->acpi_device->pnp.device_class,
dev_name(&wblock->dev.dev),
event, 0);
acpi_bus_generate_netlink_event(wblock->acpi_device->pnp.device_class,
dev_name(&wblock->dev.dev), *event, 0);
return -EBUSY;
}
static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, void *context)
{
struct device *wmi_bus_dev = context;
device_for_each_child(wmi_bus_dev, &event, wmi_notify_device);
}
static int wmi_remove_device(struct device *dev, void *data)
@ -1300,10 +1296,8 @@ static int acpi_wmi_probe(struct platform_device *device)
if (error < 0)
return error;
status = acpi_install_notify_handler(acpi_device->handle,
ACPI_ALL_NOTIFY,
acpi_wmi_notify_handler,
NULL);
status = acpi_install_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY,
acpi_wmi_notify_handler, wmi_bus_dev);
if (ACPI_FAILURE(status)) {
dev_err(&device->dev, "Error installing notify handler\n");
return -ENODEV;