diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-04-28 02:20:16 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-04-28 02:22:01 -0400 |
commit | e490ebdc3ce1a58e66aeacc485294a45710067f5 (patch) | |
tree | 56ac678bc0dfcbde51dd49bbd5e5668067771248 /drivers/input | |
parent | 34abeeb23575c9c25b8c582d582e5bcfcd1cf338 (diff) |
Input: input-polldev - use system-wide freezable workqueue
With introduction of concurrency-managed work queues there is rarely
a point in creating private workqueues.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/input-polldev.c | 56 |
1 files changed, 3 insertions, 53 deletions
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 3037842a60d8..b1aabde87523 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/jiffies.h> | 13 | #include <linux/jiffies.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
16 | #include <linux/workqueue.h> | ||
16 | #include <linux/input-polldev.h> | 17 | #include <linux/input-polldev.h> |
17 | 18 | ||
18 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | 19 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); |
@@ -20,44 +21,6 @@ MODULE_DESCRIPTION("Generic implementation of a polled input device"); | |||
20 | MODULE_LICENSE("GPL v2"); | 21 | MODULE_LICENSE("GPL v2"); |
21 | MODULE_VERSION("0.1"); | 22 | MODULE_VERSION("0.1"); |
22 | 23 | ||
23 | static DEFINE_MUTEX(polldev_mutex); | ||
24 | static int polldev_users; | ||
25 | static struct workqueue_struct *polldev_wq; | ||
26 | |||
27 | static int input_polldev_start_workqueue(void) | ||
28 | { | ||
29 | int retval; | ||
30 | |||
31 | retval = mutex_lock_interruptible(&polldev_mutex); | ||
32 | if (retval) | ||
33 | return retval; | ||
34 | |||
35 | if (!polldev_users) { | ||
36 | polldev_wq = create_singlethread_workqueue("ipolldevd"); | ||
37 | if (!polldev_wq) { | ||
38 | pr_err("failed to create ipolldevd workqueue\n"); | ||
39 | retval = -ENOMEM; | ||
40 | goto out; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | polldev_users++; | ||
45 | |||
46 | out: | ||
47 | mutex_unlock(&polldev_mutex); | ||
48 | return retval; | ||
49 | } | ||
50 | |||
51 | static void input_polldev_stop_workqueue(void) | ||
52 | { | ||
53 | mutex_lock(&polldev_mutex); | ||
54 | |||
55 | if (!--polldev_users) | ||
56 | destroy_workqueue(polldev_wq); | ||
57 | |||
58 | mutex_unlock(&polldev_mutex); | ||
59 | } | ||
60 | |||
61 | static void input_polldev_queue_work(struct input_polled_dev *dev) | 24 | static void input_polldev_queue_work(struct input_polled_dev *dev) |
62 | { | 25 | { |
63 | unsigned long delay; | 26 | unsigned long delay; |
@@ -66,7 +29,7 @@ static void input_polldev_queue_work(struct input_polled_dev *dev) | |||
66 | if (delay >= HZ) | 29 | if (delay >= HZ) |
67 | delay = round_jiffies_relative(delay); | 30 | delay = round_jiffies_relative(delay); |
68 | 31 | ||
69 | queue_delayed_work(polldev_wq, &dev->work, delay); | 32 | queue_delayed_work(system_freezable_wq, &dev->work, delay); |
70 | } | 33 | } |
71 | 34 | ||
72 | static void input_polled_device_work(struct work_struct *work) | 35 | static void input_polled_device_work(struct work_struct *work) |
@@ -81,18 +44,13 @@ static void input_polled_device_work(struct work_struct *work) | |||
81 | static int input_open_polled_device(struct input_dev *input) | 44 | static int input_open_polled_device(struct input_dev *input) |
82 | { | 45 | { |
83 | struct input_polled_dev *dev = input_get_drvdata(input); | 46 | struct input_polled_dev *dev = input_get_drvdata(input); |
84 | int error; | ||
85 | |||
86 | error = input_polldev_start_workqueue(); | ||
87 | if (error) | ||
88 | return error; | ||
89 | 47 | ||
90 | if (dev->open) | 48 | if (dev->open) |
91 | dev->open(dev); | 49 | dev->open(dev); |
92 | 50 | ||
93 | /* Only start polling if polling is enabled */ | 51 | /* Only start polling if polling is enabled */ |
94 | if (dev->poll_interval > 0) | 52 | if (dev->poll_interval > 0) |
95 | queue_delayed_work(polldev_wq, &dev->work, 0); | 53 | queue_delayed_work(system_freezable_wq, &dev->work, 0); |
96 | 54 | ||
97 | return 0; | 55 | return 0; |
98 | } | 56 | } |
@@ -102,13 +60,6 @@ static void input_close_polled_device(struct input_dev *input) | |||
102 | struct input_polled_dev *dev = input_get_drvdata(input); | 60 | struct input_polled_dev *dev = input_get_drvdata(input); |
103 | 61 | ||
104 | cancel_delayed_work_sync(&dev->work); | 62 | cancel_delayed_work_sync(&dev->work); |
105 | /* | ||
106 | * Clean up work struct to remove references to the workqueue. | ||
107 | * It may be destroyed by the next call. This causes problems | ||
108 | * at next device open-close in case of poll_interval == 0. | ||
109 | */ | ||
110 | INIT_DELAYED_WORK(&dev->work, dev->work.work.func); | ||
111 | input_polldev_stop_workqueue(); | ||
112 | 63 | ||
113 | if (dev->close) | 64 | if (dev->close) |
114 | dev->close(dev); | 65 | dev->close(dev); |
@@ -295,4 +246,3 @@ void input_unregister_polled_device(struct input_polled_dev *dev) | |||
295 | input_unregister_device(dev->input); | 246 | input_unregister_device(dev->input); |
296 | } | 247 | } |
297 | EXPORT_SYMBOL(input_unregister_polled_device); | 248 | EXPORT_SYMBOL(input_unregister_polled_device); |
298 | |||