Commit 10eba55f authored by Armin Wolf's avatar Armin Wolf Committed by Hans de Goede

platform/x86: quickstart: Fix race condition when reporting input event

Since commit e2ffcda1 ("ACPI: OSL: Allow Notify () handlers to run
on all CPUs"), the ACPI core allows multiple notify calls to be active
at the same time. This means that two instances of quickstart_notify()
running at the same time can mess which each others input sequences.

Fix this by protecting the input sequence with a mutex.

Compile-tested only.

Fixes: afd66f2a739e ("platform/x86: Add ACPI quickstart button (PNP0C32) driver")
Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20240327214524.123935-1-W_Armin@gmx.deReviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 83cfe6d8
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/input/sparse-keymap.h> #include <linux/input/sparse-keymap.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_wakeup.h> #include <linux/pm_wakeup.h>
#include <linux/printk.h> #include <linux/printk.h>
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
struct quickstart_data { struct quickstart_data {
struct device *dev; struct device *dev;
struct mutex input_lock; /* Protects input sequence during notify */
struct input_dev *input_device; struct input_dev *input_device;
char input_name[32]; char input_name[32];
char phys[32]; char phys[32];
...@@ -76,7 +78,10 @@ static void quickstart_notify(acpi_handle handle, u32 event, void *context) ...@@ -76,7 +78,10 @@ static void quickstart_notify(acpi_handle handle, u32 event, void *context)
switch (event) { switch (event) {
case QUICKSTART_EVENT_RUNTIME: case QUICKSTART_EVENT_RUNTIME:
mutex_lock(&data->input_lock);
sparse_keymap_report_event(data->input_device, 0x1, 1, true); sparse_keymap_report_event(data->input_device, 0x1, 1, true);
mutex_unlock(&data->input_lock);
acpi_bus_generate_netlink_event(DRIVER_NAME, dev_name(data->dev), event, 0); acpi_bus_generate_netlink_event(DRIVER_NAME, dev_name(data->dev), event, 0);
break; break;
default: default:
...@@ -150,6 +155,13 @@ static void quickstart_notify_remove(void *context) ...@@ -150,6 +155,13 @@ static void quickstart_notify_remove(void *context)
acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, quickstart_notify); acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, quickstart_notify);
} }
static void quickstart_mutex_destroy(void *data)
{
struct mutex *lock = data;
mutex_destroy(lock);
}
static int quickstart_probe(struct platform_device *pdev) static int quickstart_probe(struct platform_device *pdev)
{ {
struct quickstart_data *data; struct quickstart_data *data;
...@@ -168,6 +180,11 @@ static int quickstart_probe(struct platform_device *pdev) ...@@ -168,6 +180,11 @@ static int quickstart_probe(struct platform_device *pdev)
data->dev = &pdev->dev; data->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, data); dev_set_drvdata(&pdev->dev, data);
mutex_init(&data->input_lock);
ret = devm_add_action_or_reset(&pdev->dev, quickstart_mutex_destroy, &data->input_lock);
if (ret < 0)
return ret;
/* /*
* We have to initialize the device wakeup before evaluating GHID because * We have to initialize the device wakeup before evaluating GHID because
* doing so will notify the device if the button was used to wake the machine * doing so will notify the device if the button was used to wake the machine
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment