]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
platform/wmi: Replace .no_notify_data with .min_event_size
authorArmin Wolf <W_Armin@gmx.de>
Mon, 6 Apr 2026 20:32:37 +0000 (22:32 +0200)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 13 Apr 2026 11:11:27 +0000 (14:11 +0300)
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: Armin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260406203237.2970-7-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
13 files changed:
Documentation/wmi/driver-development-guide.rst
drivers/platform/wmi/core.c
drivers/platform/x86/bitland-mifs-wmi.c
drivers/platform/x86/dell/dell-wmi-base.c
drivers/platform/x86/lenovo/ideapad-laptop.c
drivers/platform/x86/lenovo/wmi-camera.c
drivers/platform/x86/lenovo/wmi-events.c
drivers/platform/x86/lenovo/ymc.c
drivers/platform/x86/lenovo/yogabook.c
drivers/platform/x86/redmi-wmi.c
drivers/platform/x86/uniwill/uniwill-wmi.c
drivers/platform/x86/xiaomi-wmi.c
include/linux/wmi.h

index 5b94402874c4f5c6bc79865a32cedc02d94a62bb..387f508d57ad8955602a3a608b78285e0a35227f 100644 (file)
@@ -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.
 
index 87b0e54dde5a6d5aefefc7b6db6602c7e7528d16..7df50c8238e58bcc4a6fd200b195ac2935ca6576 100644 (file)
@@ -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;
index 78639407d67eb842c00769719e10b5afaa856c58..b0d06a80e89ef00827872e71339b23f98ca30c25 100644 (file)
@@ -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,
 };
index e7a411ae9ca1279cc76e247507ece4b0370c898b..2a5804efd3ea89c56bbeab741561e4f80f9a3e90 100644 (file)
@@ -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,
index ae1ebb071fab0be0d328a5a2b6f7177e6777a0e0..4fbc904f1fc390aa1d6ffacbd2d5b1dfcc2fb57b 100644 (file)
@@ -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,
 };
index eb60fb9a5b3fc64957d55da81450eba6ccd866a7..89ecbce60bf4f79310158864983ea1dba0c231cc 100644 (file)
@@ -134,6 +134,7 @@ static struct wmi_driver lenovo_wmi_driver = {
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .id_table = lenovo_wmi_id_table,
+       .min_event_size = sizeof(u8),
        .no_singleton = true,
        .probe = lenovo_wmi_probe,
        .notify = lenovo_wmi_notify,
index 0994cd7dd504cdbf4d786a2249b21418e5882d22..4a6a2c82413acf24487a554ee23c4a99638861aa 100644 (file)
@@ -183,6 +183,7 @@ static struct wmi_driver lwmi_events_driver = {
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .id_table = lwmi_events_id_table,
+       .min_event_size = sizeof(u32),
        .probe = lwmi_events_probe,
        .notify = lwmi_events_notify,
        .no_singleton = true,
index 470d53e3c9d299f9a49e9da1f1ffb4c8fd51109e..1b73a55f1b89c7423db1c5baaea5ae46fc14b220 100644 (file)
@@ -153,6 +153,7 @@ static struct wmi_driver lenovo_ymc_driver = {
                .name = "lenovo-ymc",
        },
        .id_table = lenovo_ymc_wmi_id_table,
+       .min_event_size = sizeof(u32),
        .probe = lenovo_ymc_probe,
        .notify = lenovo_ymc_notify,
 };
index 69887de36c9b9018c8ada9dcdcd69cea3ab98d60..1a4b2ab1f35d6635d5afacd8213a3232a37d9b05 100644 (file)
@@ -411,8 +411,8 @@ static struct wmi_driver yogabook_wmi_driver = {
                .name = "yogabook-wmi",
                .pm = pm_sleep_ptr(&yogabook_pm_ops),
        },
-       .no_notify_data = true,
        .id_table = yogabook_wmi_id_table,
+       .min_event_size = 0,
        .probe = yogabook_wmi_probe,
        .remove = yogabook_wmi_remove,
        .notify = yogabook_wmi_notify,
index e5cb348e3a39a3e17abe6b729c79a9f3220eebd6..58898630eda606828b982ec6fa37c9c95fd68d21 100644 (file)
@@ -141,6 +141,7 @@ static struct wmi_driver redmi_wmi_driver = {
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .id_table = redmi_wmi_id_table,
+       .min_event_size = 32,
        .probe = redmi_wmi_probe,
        .notify = redmi_wmi_notify,
        .no_singleton = true,
index 31d9c39f14ab4568a3ba3320ffb845454a094c3d..097882f10b1e363fa06160c90124a46f2c1d76e7 100644 (file)
@@ -77,6 +77,7 @@ static struct wmi_driver uniwill_wmi_driver = {
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .id_table = uniwill_wmi_id_table,
+       .min_event_size = sizeof(u32),
        .notify = uniwill_wmi_notify,
        .no_singleton = true,
 };
index badf9e42e015fa93cda3f1f887363d53337ef397..3874f3336a0dc13785a4ce250f44fb397e0c2310 100644 (file)
@@ -83,6 +83,7 @@ static struct wmi_driver xiaomi_wmi_driver = {
                .name = "xiaomi-wmi",
        },
        .id_table = xiaomi_wmi_id_table,
+       .min_event_size = 0,
        .probe = xiaomi_wmi_probe,
        .notify_new = xiaomi_wmi_notify,
        .no_singleton = true,
index da94580572a91b12ff9fb7f1c3fd967a927450ee..2d242575a8b3778e75a02f69a45375afb67c70e2 100644 (file)
@@ -91,7 +91,7 @@ u8 wmidev_instance_count(struct wmi_device *wdev);
  * struct wmi_driver - WMI driver structure
  * @driver: Driver model structure
  * @id_table: List of WMI GUIDs supported by this driver
- * @no_notify_data: Driver supports WMI events which provide no event data
+ * @min_event_size: Minimum event payload size supported by this driver
  * @no_singleton: Driver can be instantiated multiple times
  * @probe: Callback for device binding
  * @remove: Callback for device unbinding
@@ -101,11 +101,14 @@ u8 wmidev_instance_count(struct wmi_device *wdev);
  *
  * This represents WMI drivers which handle WMI devices. The data inside the buffer
  * passed to the @notify_new callback is guaranteed to be aligned on a 8-byte boundary.
+ * The minimum supported size for said buffer can be specified using @min_event_size.
+ * WMI drivers that still use the deprecated @notify callback can still set @min_event_size
+ * to 0 in order to signal that they support WMI events which provide no event data.
  */
 struct wmi_driver {
        struct device_driver driver;
        const struct wmi_device_id *id_table;
-       bool no_notify_data;
+       size_t min_event_size;
        bool no_singleton;
 
        int (*probe)(struct wmi_device *wdev, const void *context);