aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input-polldev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input-polldev.c')
-rw-r--r--drivers/input/input-polldev.c63
1 files changed, 7 insertions, 56 deletions
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 10c9b0a845f0..b1aabde87523 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -8,9 +8,12 @@
8 * the Free Software Foundation. 8 * the Free Software Foundation.
9 */ 9 */
10 10
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
11#include <linux/jiffies.h> 13#include <linux/jiffies.h>
12#include <linux/slab.h> 14#include <linux/slab.h>
13#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <linux/workqueue.h>
14#include <linux/input-polldev.h> 17#include <linux/input-polldev.h>
15 18
16MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); 19MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
@@ -18,45 +21,6 @@ MODULE_DESCRIPTION("Generic implementation of a polled input device");
18MODULE_LICENSE("GPL v2"); 21MODULE_LICENSE("GPL v2");
19MODULE_VERSION("0.1"); 22MODULE_VERSION("0.1");
20 23
21static DEFINE_MUTEX(polldev_mutex);
22static int polldev_users;
23static struct workqueue_struct *polldev_wq;
24
25static int input_polldev_start_workqueue(void)
26{
27 int retval;
28
29 retval = mutex_lock_interruptible(&polldev_mutex);
30 if (retval)
31 return retval;
32
33 if (!polldev_users) {
34 polldev_wq = create_singlethread_workqueue("ipolldevd");
35 if (!polldev_wq) {
36 printk(KERN_ERR "input-polldev: failed to create "
37 "ipolldevd workqueue\n");
38 retval = -ENOMEM;
39 goto out;
40 }
41 }
42
43 polldev_users++;
44
45 out:
46 mutex_unlock(&polldev_mutex);
47 return retval;
48}
49
50static void input_polldev_stop_workqueue(void)
51{
52 mutex_lock(&polldev_mutex);
53
54 if (!--polldev_users)
55 destroy_workqueue(polldev_wq);
56
57 mutex_unlock(&polldev_mutex);
58}
59
60static void input_polldev_queue_work(struct input_polled_dev *dev) 24static void input_polldev_queue_work(struct input_polled_dev *dev)
61{ 25{
62 unsigned long delay; 26 unsigned long delay;
@@ -65,7 +29,7 @@ static void input_polldev_queue_work(struct input_polled_dev *dev)
65 if (delay >= HZ) 29 if (delay >= HZ)
66 delay = round_jiffies_relative(delay); 30 delay = round_jiffies_relative(delay);
67 31
68 queue_delayed_work(polldev_wq, &dev->work, delay); 32 queue_delayed_work(system_freezable_wq, &dev->work, delay);
69} 33}
70 34
71static void input_polled_device_work(struct work_struct *work) 35static void input_polled_device_work(struct work_struct *work)
@@ -80,18 +44,13 @@ static void input_polled_device_work(struct work_struct *work)
80static int input_open_polled_device(struct input_dev *input) 44static int input_open_polled_device(struct input_dev *input)
81{ 45{
82 struct input_polled_dev *dev = input_get_drvdata(input); 46 struct input_polled_dev *dev = input_get_drvdata(input);
83 int error;
84
85 error = input_polldev_start_workqueue();
86 if (error)
87 return error;
88 47
89 if (dev->open) 48 if (dev->open)
90 dev->open(dev); 49 dev->open(dev);
91 50
92 /* Only start polling if polling is enabled */ 51 /* Only start polling if polling is enabled */
93 if (dev->poll_interval > 0) 52 if (dev->poll_interval > 0)
94 queue_delayed_work(polldev_wq, &dev->work, 0); 53 queue_delayed_work(system_freezable_wq, &dev->work, 0);
95 54
96 return 0; 55 return 0;
97} 56}
@@ -101,13 +60,6 @@ static void input_close_polled_device(struct input_dev *input)
101 struct input_polled_dev *dev = input_get_drvdata(input); 60 struct input_polled_dev *dev = input_get_drvdata(input);
102 61
103 cancel_delayed_work_sync(&dev->work); 62 cancel_delayed_work_sync(&dev->work);
104 /*
105 * Clean up work struct to remove references to the workqueue.
106 * It may be destroyed by the next call. This causes problems
107 * at next device open-close in case of poll_interval == 0.
108 */
109 INIT_DELAYED_WORK(&dev->work, dev->work.work.func);
110 input_polldev_stop_workqueue();
111 63
112 if (dev->close) 64 if (dev->close)
113 dev->close(dev); 65 dev->close(dev);
@@ -191,7 +143,7 @@ static struct attribute_group input_polldev_attribute_group = {
191}; 143};
192 144
193/** 145/**
194 * input_allocate_polled_device - allocated memory polled device 146 * input_allocate_polled_device - allocate memory for polled device
195 * 147 *
196 * The function allocates memory for a polled device and also 148 * The function allocates memory for a polled device and also
197 * for an input device associated with this polled device. 149 * for an input device associated with this polled device.
@@ -238,7 +190,7 @@ EXPORT_SYMBOL(input_free_polled_device);
238 * with input layer. The device should be allocated with call to 190 * with input layer. The device should be allocated with call to
239 * input_allocate_polled_device(). Callers should also set up poll() 191 * input_allocate_polled_device(). Callers should also set up poll()
240 * method and set up capabilities (id, name, phys, bits) of the 192 * method and set up capabilities (id, name, phys, bits) of the
241 * corresponing input_dev structure. 193 * corresponding input_dev structure.
242 */ 194 */
243int input_register_polled_device(struct input_polled_dev *dev) 195int input_register_polled_device(struct input_polled_dev *dev)
244{ 196{
@@ -294,4 +246,3 @@ void input_unregister_polled_device(struct input_polled_dev *dev)
294 input_unregister_device(dev->input); 246 input_unregister_device(dev->input);
295} 247}
296EXPORT_SYMBOL(input_unregister_polled_device); 248EXPORT_SYMBOL(input_unregister_polled_device);
297