aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input-polldev.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-04-28 02:20:16 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-04-28 02:22:01 -0400
commite490ebdc3ce1a58e66aeacc485294a45710067f5 (patch)
tree56ac678bc0dfcbde51dd49bbd5e5668067771248 /drivers/input/input-polldev.c
parent34abeeb23575c9c25b8c582d582e5bcfcd1cf338 (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/input-polldev.c')
-rw-r--r--drivers/input/input-polldev.c56
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
18MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); 19MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
@@ -20,44 +21,6 @@ MODULE_DESCRIPTION("Generic implementation of a polled input device");
20MODULE_LICENSE("GPL v2"); 21MODULE_LICENSE("GPL v2");
21MODULE_VERSION("0.1"); 22MODULE_VERSION("0.1");
22 23
23static DEFINE_MUTEX(polldev_mutex);
24static int polldev_users;
25static struct workqueue_struct *polldev_wq;
26
27static 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
51static 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
61static void input_polldev_queue_work(struct input_polled_dev *dev) 24static 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
72static void input_polled_device_work(struct work_struct *work) 35static void input_polled_device_work(struct work_struct *work)
@@ -81,18 +44,13 @@ static void input_polled_device_work(struct work_struct *work)
81static int input_open_polled_device(struct input_dev *input) 44static 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}
297EXPORT_SYMBOL(input_unregister_polled_device); 248EXPORT_SYMBOL(input_unregister_polled_device);
298