summaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2023-04-30 18:57:50 +0200
committerHans de Goede <hdegoede@redhat.com>2023-05-09 12:29:50 +0200
commit9148cd2eb4450a8e9c49c8a14201fb82f651128f (patch)
tree289f89055ea5873d809016407b4f6279fa2dbc74 /drivers/platform/x86
parent6f37c034313701a0d5a4255ad4e7c38db2d50844 (diff)
downloadlinux-stable-9148cd2eb4450a8e9c49c8a14201fb82f651128f.tar.gz
linux-stable-9148cd2eb4450a8e9c49c8a14201fb82f651128f.tar.bz2
linux-stable-9148cd2eb4450a8e9c49c8a14201fb82f651128f.zip
platform/x86: lenovo-yogabook: Fix work race on remove()
When yogabook_wmi_remove() runs yogabook_wmi_work might still be running and using the devices which yogabook_wmi_remove() puts. To avoid this move to explicitly cancelling the work rather then using devm_work_autocancel(). This requires also making the yogabook_backside_hall_irq handler non devm managed, so that it cannot re-queue the work while yogabook_wmi_remove() runs. Fixes: c0549b72d99d ("platform/x86: lenovo-yogabook-wmi: Add driver for Lenovo Yoga Book") Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20230430165807.472798-3-hdegoede@redhat.com
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/lenovo-yogabook-wmi.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/drivers/platform/x86/lenovo-yogabook-wmi.c b/drivers/platform/x86/lenovo-yogabook-wmi.c
index 5f4bd1eec38a..3a6de4ab74a4 100644
--- a/drivers/platform/x86/lenovo-yogabook-wmi.c
+++ b/drivers/platform/x86/lenovo-yogabook-wmi.c
@@ -2,7 +2,6 @@
/* WMI driver for Lenovo Yoga Book YB1-X90* / -X91* tablets */
#include <linux/acpi.h>
-#include <linux/devm-helpers.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/interrupt.h>
@@ -248,10 +247,7 @@ static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context)
data->brightness = YB_KBD_BL_DEFAULT;
set_bit(YB_KBD_IS_ON, &data->flags);
set_bit(YB_DIGITIZER_IS_ON, &data->flags);
-
- r = devm_work_autocancel(&wdev->dev, &data->work, yogabook_wmi_work);
- if (r)
- return r;
+ INIT_WORK(&data->work, yogabook_wmi_work);
data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1);
if (!data->kbd_adev) {
@@ -299,10 +295,9 @@ static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context)
}
data->backside_hall_irq = r;
- r = devm_request_irq(&wdev->dev, data->backside_hall_irq,
- yogabook_backside_hall_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "backside_hall_sw", data);
+ r = request_irq(data->backside_hall_irq, yogabook_backside_hall_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "backside_hall_sw", data);
if (r) {
dev_err_probe(&wdev->dev, r, "Requesting backside_hall_sw IRQ\n");
goto error_put_devs;
@@ -318,11 +313,14 @@ static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context)
r = devm_led_classdev_register(&wdev->dev, &data->kbd_bl_led);
if (r < 0) {
dev_err_probe(&wdev->dev, r, "Registering backlight LED device\n");
- goto error_put_devs;
+ goto error_free_irq;
}
return 0;
+error_free_irq:
+ free_irq(data->backside_hall_irq, data);
+ cancel_work_sync(&data->work);
error_put_devs:
put_device(data->dig_dev);
put_device(data->kbd_dev);
@@ -335,6 +333,8 @@ static void yogabook_wmi_remove(struct wmi_device *wdev)
{
struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev);
+ free_irq(data->backside_hall_irq, data);
+ cancel_work_sync(&data->work);
put_device(data->dig_dev);
put_device(data->kbd_dev);
acpi_dev_put(data->dig_adev);