mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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>
This commit is contained in:
parent
1aeded2f55
commit
2e2a39149f
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user