2024-02-14 07:06:07

by Armin Wolf

[permalink] [raw]
Subject: [PATCH 0/5] platform/x86: wmi: Fixes for event data handling

This patch series contains fixes for the handling of WMI event data
when receiving WMI events.

The first patch aims to prevent WMI event drivers depending on WMI
event data support from binding to a WMI device which does not
support the retrieval of additional WMI event data.

The second patch makes sure that the WMI core not only checks that
evaluating the ACPI control method used for retrieving additional
event data (_WED) succeeded, but that it also returned any data.

The third patch fixes an compatibility issue with the ACPI firmware
of some ASUS notebooks. This issue was "fixed" inside asus-wmi by
manually retrieving event data items, sidestepping the WMI core.

The last patch reverts this hacky fixup, as the underlying issue is
now handled inside the WMI core itself.

All patches where tested on a Dell Inspiron 3505 and a ASUS Prime
B650-Plus motherboard. However the last patch should be tested on an
actual ASUS notebook which is affected by the workaround.

Armin Wolf (5):
platform/x86: wmi: Prevent incompatible event driver from probing
platform/x86: wmi: Check if event data is not NULL
platform/x86: wmi: Always evaluate _WED when receiving an event
platform/x86: wmi: Update documentation regarding _WED
Revert "platform/x86: asus-wmi: Support WMI event queue"

Documentation/wmi/acpi-interface.rst | 5 +-
drivers/platform/x86/asus-wmi.c | 71 ++------------------------
drivers/platform/x86/wmi.c | 74 +++++++++++++++++++++++-----
include/linux/wmi.h | 2 +-
4 files changed, 71 insertions(+), 81 deletions(-)

--
2.39.2



2024-02-14 07:06:30

by Armin Wolf

[permalink] [raw]
Subject: [PATCH 5/5] Revert "platform/x86: asus-wmi: Support WMI event queue"

This reverts commit 1a373d15e283937b51eaf5debf4fc31474c31436.

The WMI core now takes care of draining the event queue if asus-wmi
is not loaded, so the hacky event queue handling code is not needed
anymore.

Signed-off-by: Armin Wolf <[email protected]>
---
drivers/platform/x86/asus-wmi.c | 71 +++------------------------------
1 file changed, 5 insertions(+), 66 deletions(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 21dee425ea6f..2865af89e95c 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -101,13 +101,6 @@ module_param(fnlock_default, bool, 0444);
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31

#define ASUS_ACPI_UID_ASUSWMI "ASUSWMI"
-#define ASUS_ACPI_UID_ATK "ATK"
-
-#define WMI_EVENT_QUEUE_SIZE 0x10
-#define WMI_EVENT_QUEUE_END 0x1
-#define WMI_EVENT_MASK 0xFFFF
-/* The WMI hotkey event value is always the same. */
-#define WMI_EVENT_VALUE_ATK 0xFF

#define WMI_EVENT_MASK 0xFFFF

@@ -219,7 +212,6 @@ struct asus_wmi {
int dsts_id;
int spec;
int sfun;
- bool wmi_event_queue;

struct input_dev *inputdev;
struct backlight_device *backlight_device;
@@ -4019,50 +4011,14 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
static void asus_wmi_notify(u32 value, void *context)
{
struct asus_wmi *asus = context;
- int code;
- int i;
-
- for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) {
- code = asus_wmi_get_event_code(value);
- if (code < 0) {
- pr_warn("Failed to get notify code: %d\n", code);
- return;
- }
-
- if (code == WMI_EVENT_QUEUE_END || code == WMI_EVENT_MASK)
- return;
-
- asus_wmi_handle_event_code(code, asus);
-
- /*
- * Double check that queue is present:
- * ATK (with queue) uses 0xff, ASUSWMI (without) 0xd2.
- */
- if (!asus->wmi_event_queue || value != WMI_EVENT_VALUE_ATK)
- return;
- }
+ int code = asus_wmi_get_event_code(value);

- pr_warn("Failed to process event queue, last code: 0x%x\n", code);
-}
-
-static int asus_wmi_notify_queue_flush(struct asus_wmi *asus)
-{
- int code;
- int i;
-
- for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) {
- code = asus_wmi_get_event_code(WMI_EVENT_VALUE_ATK);
- if (code < 0) {
- pr_warn("Failed to get event during flush: %d\n", code);
- return code;
- }
-
- if (code == WMI_EVENT_QUEUE_END || code == WMI_EVENT_MASK)
- return 0;
+ if (code < 0) {
+ pr_warn("Failed to get notify code: %d\n", code);
+ return;
}

- pr_warn("Failed to flush event queue\n");
- return -EIO;
+ asus_wmi_handle_event_code(code, asus);
}

/* Sysfs **********************************************************************/
@@ -4302,23 +4258,6 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
asus->dsts_id = ASUS_WMI_METHODID_DSTS;
}

- /*
- * Some devices can have multiple event codes stored in a queue before
- * the module load if it was unloaded intermittently after calling
- * the INIT method (enables event handling). The WMI notify handler is
- * expected to retrieve all event codes until a retrieved code equals
- * queue end marker (One or Ones). Old codes are flushed from the queue
- * upon module load. Not enabling this when it should be has minimal
- * visible impact so fall back if anything goes wrong.
- */
- wmi_uid = wmi_get_acpi_device_uid(asus->driver->event_guid);
- if (wmi_uid && !strcmp(wmi_uid, ASUS_ACPI_UID_ATK)) {
- dev_info(dev, "Detected ATK, enable event queue\n");
-
- if (!asus_wmi_notify_queue_flush(asus))
- asus->wmi_event_queue = true;
- }
-
/* CWAP allow to define the behavior of the Fn+F2 key,
* this method doesn't seems to be present on Eee PCs */
if (asus->driver->quirks->wapf >= 0)
--
2.39.2