Commit 2c933755 authored by Armin Wolf's avatar Armin Wolf Committed by Hans de Goede
Browse files

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20231218192420.305411-6-W_Armin@gmx.de


Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 095fa72a
Loading
Loading
Loading
Loading
+20 −26
Original line number Diff line number Diff line
@@ -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;

	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;
		}
	}
	struct wmi_block *wblock = dev_to_wblock(dev);
	u32 *event = data;

	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);

	return -EBUSY;
}

	acpi_bus_generate_netlink_event(
		wblock->acpi_device->pnp.device_class,
		dev_name(&wblock->dev.dev),
		event, 0);
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;