From 29d76076b2a343232fa52e07dddb8c4cf09f1aaf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 6 Apr 2015 19:20:15 +0000 Subject: [PATCH] HID: thingm: fix workqueue race on remove (Closes: #780055) svn path=/dists/sid/linux/; revision=22482 --- ...-thingm-fix-workqueue-race-on-remove.patch | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 debian/patches/bugfix/all/hid-thingm-fix-workqueue-race-on-remove.patch diff --git a/debian/patches/bugfix/all/hid-thingm-fix-workqueue-race-on-remove.patch b/debian/patches/bugfix/all/hid-thingm-fix-workqueue-race-on-remove.patch new file mode 100644 index 000000000..c4a3d98e5 --- /dev/null +++ b/debian/patches/bugfix/all/hid-thingm-fix-workqueue-race-on-remove.patch @@ -0,0 +1,50 @@ +From: Jiri Kosina +Date: Thu, 4 Sep 2014 08:56:06 +0200 +Subject: HID: thingm: fix workqueue race on remove +Origin: https://git.kernel.org/linus/67a97845830f79584c9db8849ac723e5d2d57f65 + +thingm_remove_rgb() needs to flush the workqueue after all the LED classes +have been unregistered, otherwise the removal might race with another LED +event coming, causing thingm_led_set() to schedule additional work after +thingm_remove_rgb() has flushed it. This obviously causes oops later, as +the scheduled work has been freed in the meantime. + +In addition to that, move the hid_hw_stop() to an earlier place, so that +dmesg is not polluted by failure messages about not being able to write +the LED while the device is being shut down. + +Reported-and-tested-by: Dylan Alex Simon +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-thingm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c +index 134be89..f206398 100644 +--- a/drivers/hid/hid-thingm.c ++++ b/drivers/hid/hid-thingm.c +@@ -208,10 +208,10 @@ unregister_red: + + static void thingm_remove_rgb(struct thingm_rgb *rgb) + { +- flush_work(&rgb->work); + led_classdev_unregister(&rgb->red.ldev); + led_classdev_unregister(&rgb->green.ldev); + led_classdev_unregister(&rgb->blue.ldev); ++ flush_work(&rgb->work); + } + + static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) +@@ -286,10 +286,10 @@ static void thingm_remove(struct hid_device *hdev) + struct thingm_device *tdev = hid_get_drvdata(hdev); + int i; + ++ hid_hw_stop(hdev); ++ + for (i = 0; i < tdev->fwinfo->numrgb; ++i) + thingm_remove_rgb(tdev->rgb + i); +- +- hid_hw_stop(hdev); + } + + static const struct hid_device_id thingm_table[] = {