From: Armin Wolf <W_Armin@gmx.de>
To: corentin.chary@gmail.com, luke@ljones.dev
Cc: hdegoede@redhat.com, ilpo.jarvinen@linux.intel.com,
platform-driver-x86@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 3/5] platform/x86: wmi: Always evaluate _WED when receiving an event
Date: Mon, 19 Feb 2024 12:59:17 +0100 [thread overview]
Message-ID: <20240219115919.16526-4-W_Armin@gmx.de> (raw)
In-Reply-To: <20240219115919.16526-1-W_Armin@gmx.de>
The ACPI WMI specification states:
"The _WED control method is evaluated by the mapper in
response to receiving a notification from a control
method."
This means that _WED should be evaluated unconditionally even
if no WMI event consumers are present.
Some firmware implementations actually depend on this behavior
by storing the event data inside a queue which will fill up if
the WMI core stops retrieving event data items due to no
consumers being present
Fix this by always evaluating _WED even if no WMI event consumers
are present.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/platform/x86/wmi.c | 67 ++++++++++++++++++++++++++++----------
1 file changed, 49 insertions(+), 18 deletions(-)
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index d0fe8153f803..abd0183c4107 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -1206,37 +1206,46 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
}
}
-static void wmi_notify_driver(struct wmi_block *wblock)
+static int wmi_get_notify_data(struct wmi_block *wblock, union acpi_object **obj)
{
- struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver);
struct acpi_buffer data = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *obj = NULL;
acpi_status status;
- if (!driver->no_notify_data) {
- status = get_event_data(wblock, &data);
- if (ACPI_FAILURE(status)) {
- dev_warn(&wblock->dev.dev, "Failed to get event data\n");
- return;
- }
+ if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags)) {
+ *obj = NULL;
+ return 0;
+ }
- obj = data.pointer;
- if (!obj) {
- dev_warn(&wblock->dev.dev, "Event contains not event data\n");
- return;
- }
+ status = get_event_data(wblock, &data);
+ if (ACPI_FAILURE(status)) {
+ dev_warn(&wblock->dev.dev, "Failed to get event data\n");
+ return -EIO;
+ }
+
+ *obj = data.pointer;
+
+ return 0;
+}
+
+static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)
+{
+ struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver);
+
+ if (!obj && !driver->no_notify_data) {
+ dev_warn(&wblock->dev.dev, "Event contains no event data\n");
+ return;
}
if (driver->notify)
driver->notify(&wblock->dev, obj);
-
- kfree(obj);
}
static int wmi_notify_device(struct device *dev, void *data)
{
struct wmi_block *wblock = dev_to_wblock(dev);
+ union acpi_object *obj;
u32 *event = data;
+ int ret;
if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event))
return 0;
@@ -1246,10 +1255,32 @@ static int wmi_notify_device(struct device *dev, void *data)
* Because of this the WMI driver notify handler takes precedence.
*/
if (wblock->dev.dev.driver && wblock->driver_ready) {
- wmi_notify_driver(wblock);
+ ret = wmi_get_notify_data(wblock, &obj);
+ if (ret >= 0) {
+ wmi_notify_driver(wblock, obj);
+ kfree(obj);
+ }
} else {
- if (wblock->handler)
+ 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);
+ }
+
}
up_read(&wblock->notify_lock);
--
2.39.2
next prev parent reply other threads:[~2024-02-19 11:59 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-19 11:59 [PATCH v2 0/5] platform/x86: wmi: Fixes for event data handling Armin Wolf
2024-02-19 11:59 ` [PATCH v2 1/5] platform/x86: wmi: Prevent incompatible event driver from probing Armin Wolf
2024-02-19 11:59 ` [PATCH v2 2/5] platform/x86: wmi: Check if event data is not NULL Armin Wolf
2024-02-20 0:59 ` Armin Wolf
2024-02-20 9:19 ` Ilpo Järvinen
2024-02-21 3:21 ` Armin Wolf
2024-02-19 11:59 ` Armin Wolf [this message]
2024-02-19 11:59 ` [PATCH v2 4/5] platform/x86: wmi: Update documentation regarding _WED Armin Wolf
2024-02-19 11:59 ` [PATCH v2 5/5] Revert "platform/x86: asus-wmi: Support WMI event queue" Armin Wolf
2024-02-19 12:06 ` [PATCH v2 0/5] platform/x86: wmi: Fixes for event data handling Ilpo Järvinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240219115919.16526-4-W_Armin@gmx.de \
--to=w_armin@gmx.de \
--cc=corentin.chary@gmail.com \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®