Unverified Commit 2e2a3914 authored by Armin Wolf's avatar Armin Wolf Committed by Ilpo Järvinen
Browse files

platform/wmi: Replace .no_notify_data with .min_event_size



WMI drivers using the buffer-based WMI API are expected to reject
undersized event payloads. Extend the WMI driver core to allow
such drivers to specify their minimum supported event payload size.
Also remove the now redundant .no_notify_data field.

Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260406203237.2970-7-W_Armin@gmx.de


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
parent 1aeded2f
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ to matching WMI devices using a struct wmi_device_id table:
        .remove = foo_remove,         /* optional, devres is preferred */
        .shutdown = foo_shutdown,     /* optional, called during shutdown */
        .notify_new = foo_notify,     /* optional, for event handling */
        .no_notify_data = true,       /* optional, enables events containing no additional data */
        .min_event_size = X,          /* optional, simplifies event payload size verification */
        .no_singleton = true,         /* required for new WMI drivers */
  };
  module_wmi_driver(foo_driver);
@@ -142,8 +142,10 @@ right before and after calling its remove() or shutdown() callback.
However WMI driver developers should be aware that multiple WMI events can be received concurrently,
so any locking (if necessary) needs to be provided by the WMI driver itself.

In order to be able to receive WMI events containing no additional event data,
the ``no_notify_data`` flag inside struct wmi_driver should be set to ``true``.
The WMI driver can furthermore instruct the WMI driver core to automatically reject WMI events
that contain a undersized event payload by populating the ``min_event_size`` field inside
struct wmi_driver. Setting this field to 0 will thus enable the WMI driver to receive WMI events
without any event payload.

Take a look at drivers/platform/x86/xiaomi-wmi.c for an example WMI event driver.

+8 −4
Original line number Diff line number Diff line
@@ -1040,7 +1040,7 @@ static int wmi_dev_probe(struct device *dev)
	}

	if (wdriver->notify || wdriver->notify_new) {
		if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && !wdriver->no_notify_data)
		if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && wdriver->min_event_size)
			return -ENODEV;
	}

@@ -1398,10 +1398,14 @@ static int wmi_get_notify_data(struct wmi_block *wblock, union acpi_object **obj
static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)
{
	struct wmi_driver *driver = to_wmi_driver(wblock->dev.dev.driver);
	struct wmi_buffer dummy = {
		.length = 0,
		.data = ZERO_SIZE_PTR,
	};
	struct wmi_buffer buffer;
	int ret;

	if (!obj && !driver->no_notify_data) {
	if (!obj && driver->min_event_size) {
		dev_warn(&wblock->dev.dev, "Event contains no event data\n");
		return;
	}
@@ -1411,11 +1415,11 @@ static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)

	if (driver->notify_new) {
		if (!obj) {
			driver->notify_new(&wblock->dev, NULL);
			driver->notify_new(&wblock->dev, &dummy);
			return;
		}

		ret = wmi_unmarshal_acpi_object(obj, &buffer, 0);
		ret = wmi_unmarshal_acpi_object(obj, &buffer, driver->min_event_size);
		if (ret < 0) {
			dev_warn(&wblock->dev.dev, "Failed to unmarshal event data: %d\n", ret);
			return;
+2 −6
Original line number Diff line number Diff line
@@ -734,15 +734,10 @@ static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
				    const struct wmi_buffer *buffer)
{
	struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev);
	const struct bitland_mifs_event *event;
	const struct bitland_mifs_event *event = buffer->data;
	struct bitland_fan_notify_data fan_data;
	u8 brightness;

	if (buffer->length < sizeof(*event))
		return;

	event = buffer->data;

	/* Validate event type */
	if (event->event_type != WMI_EVENT_TYPE_HOTKEY)
		return;
@@ -830,6 +825,7 @@ static struct wmi_driver bitland_mifs_wmi_driver = {
		.pm = pm_sleep_ptr(&bitland_mifs_wmi_pm_ops),
	},
	.id_table = bitland_mifs_wmi_id_table,
	.min_event_size = sizeof(struct bitland_mifs_event),
	.probe = bitland_mifs_wmi_probe,
	.notify_new = bitland_mifs_wmi_notify,
};
+1 −0
Original line number Diff line number Diff line
@@ -825,6 +825,7 @@ static struct wmi_driver dell_wmi_driver = {
		.name = "dell-wmi",
	},
	.id_table = dell_wmi_id_table,
	.min_event_size = sizeof(u16),
	.probe = dell_wmi_probe,
	.remove = dell_wmi_remove,
	.notify = dell_wmi_notify,
+1 −0
Original line number Diff line number Diff line
@@ -2340,6 +2340,7 @@ static struct wmi_driver ideapad_wmi_driver = {
		.name = "ideapad_wmi",
	},
	.id_table = ideapad_wmi_ids,
	.min_event_size = sizeof(u32),
	.probe = ideapad_wmi_probe,
	.notify = ideapad_wmi_notify,
};
Loading