summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/wmi.c
diff options
context:
space:
mode:
authorArmin Wolf <W_Armin@gmx.de>2024-09-01 05:10:52 +0200
committerHans de Goede <hdegoede@redhat.com>2024-09-05 17:21:59 +0200
commite04e2b760ddbe3d7b283a05898c3a029085cd8cd (patch)
treea117f11681ed87f6aad05a70e3570283c3d9edf5 /drivers/platform/x86/wmi.c
parent56d8b784c56588cd40f98e4b1d4f6e29e3cb02b8 (diff)
platform/x86: wmi: Pass event data directly to legacy notify handlers
The current legacy WMI handlers are susceptible to picking up wrong WMI event data on systems where different WMI devices share some notification IDs. Prevent this by letting the WMI driver core taking care of retrieving the event data. This also simplifies the legacy WMI handlers and their implementation inside the WMI driver core. Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20240901031055.3030-3-W_Armin@gmx.de Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'drivers/platform/x86/wmi.c')
-rw-r--r--drivers/platform/x86/wmi.c43
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 1d0b2d6040d1..6ab181dd94ab 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -1227,40 +1227,33 @@ static int wmi_notify_device(struct device *dev, void *data)
if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event))
return 0;
+ /* The ACPI WMI specification says that _WED should be
+ * evaluated every time an notification is received, even
+ * if no consumers are present.
+ *
+ * Some firmware implementations actually depend on this
+ * by using a queue for events which will fill up if the
+ * WMI driver core stops evaluating _WED due to missing
+ * WMI event consumers.
+ */
+ ret = wmi_get_notify_data(wblock, &obj);
+ if (ret < 0)
+ return -EIO;
+
down_read(&wblock->notify_lock);
/* The WMI driver notify handler conflicts with the legacy WMI handler.
* Because of this the WMI driver notify handler takes precedence.
*/
if (wblock->dev.dev.driver && wblock->driver_ready) {
- ret = wmi_get_notify_data(wblock, &obj);
- if (ret >= 0) {
- wmi_notify_driver(wblock, obj);
- kfree(obj);
- }
+ wmi_notify_driver(wblock, obj);
} else {
- if (wblock->handler) {
- wblock->handler(*event, wblock->handler_data);
- } else {
- /* The ACPI WMI specification says that _WED should be
- * evaluated every time an notification is received, even
- * if no consumers are present.
- *
- * Some firmware implementations actually depend on this
- * by using a queue for events which will fill up if the
- * WMI driver core stops evaluating _WED due to missing
- * WMI event consumers.
- *
- * Because of this we need this seemingly useless call to
- * wmi_get_notify_data() which in turn evaluates _WED.
- */
- ret = wmi_get_notify_data(wblock, &obj);
- if (ret >= 0)
- kfree(obj);
- }
-
+ if (wblock->handler)
+ wblock->handler(obj, wblock->handler_data);
}
up_read(&wblock->notify_lock);
+ kfree(obj);
+
acpi_bus_generate_netlink_event("wmi", acpi_dev_name(wblock->acpi_device), *event, 0);
return -EBUSY;