Skip to content

Commit

Permalink
platform/x86: xiaomi-wmi: Fix race condition when reporting key events
Browse files Browse the repository at this point in the history
Multiple WMI events can be received concurrently, so multiple instances
of xiaomi_wmi_notify() can be active at the same time. Since the input
device is shared between those handlers, the key input sequence can be
disturbed.

Fix this by protecting the key input sequence with a mutex.

Compile-tested only.

Fixes: edb73f4 ("platform/x86: wmi: add Xiaomi WMI key driver")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20240402143059.8456-2-W_Armin@gmx.de
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
Wer-Wolf authored and jwrdegoede committed Apr 8, 2024
1 parent c347fd4 commit 290680c
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions drivers/platform/x86/xiaomi-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
/* WMI driver for Xiaomi Laptops */

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/wmi.h>

#include <uapi/linux/input-event-codes.h>
Expand All @@ -20,12 +22,21 @@

struct xiaomi_wmi {
struct input_dev *input_dev;
struct mutex key_lock; /* Protects the key event sequence */
unsigned int key_code;
};

static void xiaomi_mutex_destroy(void *data)
{
struct mutex *lock = data;

mutex_destroy(lock);
}

static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct xiaomi_wmi *data;
int ret;

if (wdev == NULL || context == NULL)
return -EINVAL;
Expand All @@ -35,6 +46,11 @@ static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
return -ENOMEM;
dev_set_drvdata(&wdev->dev, data);

mutex_init(&data->key_lock);
ret = devm_add_action_or_reset(&wdev->dev, xiaomi_mutex_destroy, &data->key_lock);
if (ret < 0)
return ret;

data->input_dev = devm_input_allocate_device(&wdev->dev);
if (data->input_dev == NULL)
return -ENOMEM;
Expand All @@ -59,10 +75,12 @@ static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
if (data == NULL)
return;

mutex_lock(&data->key_lock);
input_report_key(data->input_dev, data->key_code, 1);
input_sync(data->input_dev);
input_report_key(data->input_dev, data->key_code, 0);
input_sync(data->input_dev);
mutex_unlock(&data->key_lock);
}

static const struct wmi_device_id xiaomi_wmi_id_table[] = {
Expand Down

0 comments on commit 290680c

Please sign in to comment.