summaryrefslogtreecommitdiff
path: root/drivers/input/input-polldev.c
diff options
context:
space:
mode:
authorSamu Onkalo <samu.p.onkalo@nokia.com>2010-02-20 07:17:58 (GMT)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-02-20 09:23:55 (GMT)
commitd9c4f846997c6d37e4f56907d93f1be022c17c6b (patch)
treec8565964e0d4566d1b5ef912c12c64b773b00e70 /drivers/input/input-polldev.c
parent3b77fd8ee6a8ae34e349651e9d5f5000d1cc206e (diff)
downloadlinux-d9c4f846997c6d37e4f56907d93f1be022c17c6b.tar.xz
Input: polldev can cause crash in case when polling disabled
When polled input device is opened and closed and there are no other users of polled device, the workqueue is created and destroyed in every open / close operation. It is probable that at some point dynamic allocation of internal parts of the workqueue cause changes to the workqueue. When a work is queued to the workqueue the work struct contains pointers to the workqueue data. If the workqueue has been changed and the work has never been queued to the new workqueue, work-struct contains pointers to the non-existing workqueue. This will cause crash at the work cancellation during device close since cancellation of a work assumes that the workqueue exists. To prevent that, work struct is cleaned up at device close. This keeps work struct clean for the next use. Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/input-polldev.c')
-rw-r--r--drivers/input/input-polldev.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index aa6713b..291d939 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -100,6 +100,12 @@ static void input_close_polled_device(struct input_dev *input)
struct input_polled_dev *dev = input_get_drvdata(input);
cancel_delayed_work_sync(&dev->work);
+ /*
+ * Clean up work struct to remove references to the workqueue.
+ * It may be destroyed by the next call. This causes problems
+ * at next device open-close in case of poll_interval == 0.
+ */
+ INIT_DELAYED_WORK(&dev->work, dev->work.work.func);
input_polldev_stop_workqueue();
if (dev->close)