Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 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>

authored by

Armin Wolf and committed by
Ilpo Järvinen
2e2a3914 1aeded2f

+29 -16
+5 -3
Documentation/wmi/driver-development-guide.rst
··· 71 71 .remove = foo_remove, /* optional, devres is preferred */ 72 72 .shutdown = foo_shutdown, /* optional, called during shutdown */ 73 73 .notify_new = foo_notify, /* optional, for event handling */ 74 - .no_notify_data = true, /* optional, enables events containing no additional data */ 74 + .min_event_size = X, /* optional, simplifies event payload size verification */ 75 75 .no_singleton = true, /* required for new WMI drivers */ 76 76 }; 77 77 module_wmi_driver(foo_driver); ··· 142 142 However WMI driver developers should be aware that multiple WMI events can be received concurrently, 143 143 so any locking (if necessary) needs to be provided by the WMI driver itself. 144 144 145 - In order to be able to receive WMI events containing no additional event data, 146 - the ``no_notify_data`` flag inside struct wmi_driver should be set to ``true``. 145 + The WMI driver can furthermore instruct the WMI driver core to automatically reject WMI events 146 + that contain a undersized event payload by populating the ``min_event_size`` field inside 147 + struct wmi_driver. Setting this field to 0 will thus enable the WMI driver to receive WMI events 148 + without any event payload. 147 149 148 150 Take a look at drivers/platform/x86/xiaomi-wmi.c for an example WMI event driver. 149 151
+8 -4
drivers/platform/wmi/core.c
··· 1040 1040 } 1041 1041 1042 1042 if (wdriver->notify || wdriver->notify_new) { 1043 - if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && !wdriver->no_notify_data) 1043 + if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && wdriver->min_event_size) 1044 1044 return -ENODEV; 1045 1045 } 1046 1046 ··· 1398 1398 static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj) 1399 1399 { 1400 1400 struct wmi_driver *driver = to_wmi_driver(wblock->dev.dev.driver); 1401 + struct wmi_buffer dummy = { 1402 + .length = 0, 1403 + .data = ZERO_SIZE_PTR, 1404 + }; 1401 1405 struct wmi_buffer buffer; 1402 1406 int ret; 1403 1407 1404 - if (!obj && !driver->no_notify_data) { 1408 + if (!obj && driver->min_event_size) { 1405 1409 dev_warn(&wblock->dev.dev, "Event contains no event data\n"); 1406 1410 return; 1407 1411 } ··· 1415 1411 1416 1412 if (driver->notify_new) { 1417 1413 if (!obj) { 1418 - driver->notify_new(&wblock->dev, NULL); 1414 + driver->notify_new(&wblock->dev, &dummy); 1419 1415 return; 1420 1416 } 1421 1417 1422 - ret = wmi_unmarshal_acpi_object(obj, &buffer, 0); 1418 + ret = wmi_unmarshal_acpi_object(obj, &buffer, driver->min_event_size); 1423 1419 if (ret < 0) { 1424 1420 dev_warn(&wblock->dev.dev, "Failed to unmarshal event data: %d\n", ret); 1425 1421 return;
+2 -6
drivers/platform/x86/bitland-mifs-wmi.c
··· 734 734 const struct wmi_buffer *buffer) 735 735 { 736 736 struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev); 737 - const struct bitland_mifs_event *event; 737 + const struct bitland_mifs_event *event = buffer->data; 738 738 struct bitland_fan_notify_data fan_data; 739 739 u8 brightness; 740 - 741 - if (buffer->length < sizeof(*event)) 742 - return; 743 - 744 - event = buffer->data; 745 740 746 741 /* Validate event type */ 747 742 if (event->event_type != WMI_EVENT_TYPE_HOTKEY) ··· 825 830 .pm = pm_sleep_ptr(&bitland_mifs_wmi_pm_ops), 826 831 }, 827 832 .id_table = bitland_mifs_wmi_id_table, 833 + .min_event_size = sizeof(struct bitland_mifs_event), 828 834 .probe = bitland_mifs_wmi_probe, 829 835 .notify_new = bitland_mifs_wmi_notify, 830 836 };
+1
drivers/platform/x86/dell/dell-wmi-base.c
··· 825 825 .name = "dell-wmi", 826 826 }, 827 827 .id_table = dell_wmi_id_table, 828 + .min_event_size = sizeof(u16), 828 829 .probe = dell_wmi_probe, 829 830 .remove = dell_wmi_remove, 830 831 .notify = dell_wmi_notify,
+1
drivers/platform/x86/lenovo/ideapad-laptop.c
··· 2340 2340 .name = "ideapad_wmi", 2341 2341 }, 2342 2342 .id_table = ideapad_wmi_ids, 2343 + .min_event_size = sizeof(u32), 2343 2344 .probe = ideapad_wmi_probe, 2344 2345 .notify = ideapad_wmi_notify, 2345 2346 };
+1
drivers/platform/x86/lenovo/wmi-camera.c
··· 134 134 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 135 135 }, 136 136 .id_table = lenovo_wmi_id_table, 137 + .min_event_size = sizeof(u8), 137 138 .no_singleton = true, 138 139 .probe = lenovo_wmi_probe, 139 140 .notify = lenovo_wmi_notify,
+1
drivers/platform/x86/lenovo/wmi-events.c
··· 183 183 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 184 184 }, 185 185 .id_table = lwmi_events_id_table, 186 + .min_event_size = sizeof(u32), 186 187 .probe = lwmi_events_probe, 187 188 .notify = lwmi_events_notify, 188 189 .no_singleton = true,
+1
drivers/platform/x86/lenovo/ymc.c
··· 153 153 .name = "lenovo-ymc", 154 154 }, 155 155 .id_table = lenovo_ymc_wmi_id_table, 156 + .min_event_size = sizeof(u32), 156 157 .probe = lenovo_ymc_probe, 157 158 .notify = lenovo_ymc_notify, 158 159 };
+1 -1
drivers/platform/x86/lenovo/yogabook.c
··· 411 411 .name = "yogabook-wmi", 412 412 .pm = pm_sleep_ptr(&yogabook_pm_ops), 413 413 }, 414 - .no_notify_data = true, 415 414 .id_table = yogabook_wmi_id_table, 415 + .min_event_size = 0, 416 416 .probe = yogabook_wmi_probe, 417 417 .remove = yogabook_wmi_remove, 418 418 .notify = yogabook_wmi_notify,
+1
drivers/platform/x86/redmi-wmi.c
··· 141 141 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 142 142 }, 143 143 .id_table = redmi_wmi_id_table, 144 + .min_event_size = 32, 144 145 .probe = redmi_wmi_probe, 145 146 .notify = redmi_wmi_notify, 146 147 .no_singleton = true,
+1
drivers/platform/x86/uniwill/uniwill-wmi.c
··· 77 77 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 78 78 }, 79 79 .id_table = uniwill_wmi_id_table, 80 + .min_event_size = sizeof(u32), 80 81 .notify = uniwill_wmi_notify, 81 82 .no_singleton = true, 82 83 };
+1
drivers/platform/x86/xiaomi-wmi.c
··· 83 83 .name = "xiaomi-wmi", 84 84 }, 85 85 .id_table = xiaomi_wmi_id_table, 86 + .min_event_size = 0, 86 87 .probe = xiaomi_wmi_probe, 87 88 .notify_new = xiaomi_wmi_notify, 88 89 .no_singleton = true,
+5 -2
include/linux/wmi.h
··· 91 91 * struct wmi_driver - WMI driver structure 92 92 * @driver: Driver model structure 93 93 * @id_table: List of WMI GUIDs supported by this driver 94 - * @no_notify_data: Driver supports WMI events which provide no event data 94 + * @min_event_size: Minimum event payload size supported by this driver 95 95 * @no_singleton: Driver can be instantiated multiple times 96 96 * @probe: Callback for device binding 97 97 * @remove: Callback for device unbinding ··· 101 101 * 102 102 * This represents WMI drivers which handle WMI devices. The data inside the buffer 103 103 * passed to the @notify_new callback is guaranteed to be aligned on a 8-byte boundary. 104 + * The minimum supported size for said buffer can be specified using @min_event_size. 105 + * WMI drivers that still use the deprecated @notify callback can still set @min_event_size 106 + * to 0 in order to signal that they support WMI events which provide no event data. 104 107 */ 105 108 struct wmi_driver { 106 109 struct device_driver driver; 107 110 const struct wmi_device_id *id_table; 108 - bool no_notify_data; 111 + size_t min_event_size; 109 112 bool no_singleton; 110 113 111 114 int (*probe)(struct wmi_device *wdev, const void *context);