aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/gpio_keys.c
diff options
context:
space:
mode:
authorJani Nikula <ext-jani.1.nikula@nokia.com>2009-06-29 01:38:56 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-06-29 02:59:23 -0400
commitda0d03fe6cecde837f113a8a587f5a872d0fade0 (patch)
tree18d08af5bae7bc55ed2f02bf4376f26fcd2f1dfe /drivers/input/keyboard/gpio_keys.c
parentca865a77b5949f5c403e0f13de5a5a9cd499a11e (diff)
Input: gpio-keys - avoid possibility of sleeping in timer function
The gpio_get_value function may sleep, so it should not be called in a timer function. Move gpio_get_value calls to workqueue. Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
-rw-r--r--drivers/input/keyboard/gpio_keys.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 9767213b6c8f..efed0c9e242e 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -22,6 +22,7 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/input.h> 23#include <linux/input.h>
24#include <linux/gpio_keys.h> 24#include <linux/gpio_keys.h>
25#include <linux/workqueue.h>
25 26
26#include <asm/gpio.h> 27#include <asm/gpio.h>
27 28
@@ -29,6 +30,7 @@ struct gpio_button_data {
29 struct gpio_keys_button *button; 30 struct gpio_keys_button *button;
30 struct input_dev *input; 31 struct input_dev *input;
31 struct timer_list timer; 32 struct timer_list timer;
33 struct work_struct work;
32}; 34};
33 35
34struct gpio_keys_drvdata { 36struct gpio_keys_drvdata {
@@ -36,8 +38,10 @@ struct gpio_keys_drvdata {
36 struct gpio_button_data data[0]; 38 struct gpio_button_data data[0];
37}; 39};
38 40
39static void gpio_keys_report_event(struct gpio_button_data *bdata) 41static void gpio_keys_report_event(struct work_struct *work)
40{ 42{
43 struct gpio_button_data *bdata =
44 container_of(work, struct gpio_button_data, work);
41 struct gpio_keys_button *button = bdata->button; 45 struct gpio_keys_button *button = bdata->button;
42 struct input_dev *input = bdata->input; 46 struct input_dev *input = bdata->input;
43 unsigned int type = button->type ?: EV_KEY; 47 unsigned int type = button->type ?: EV_KEY;
@@ -47,11 +51,11 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata)
47 input_sync(input); 51 input_sync(input);
48} 52}
49 53
50static void gpio_check_button(unsigned long _data) 54static void gpio_keys_timer(unsigned long _data)
51{ 55{
52 struct gpio_button_data *data = (struct gpio_button_data *)_data; 56 struct gpio_button_data *data = (struct gpio_button_data *)_data;
53 57
54 gpio_keys_report_event(data); 58 schedule_work(&data->work);
55} 59}
56 60
57static irqreturn_t gpio_keys_isr(int irq, void *dev_id) 61static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
@@ -65,7 +69,7 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
65 mod_timer(&bdata->timer, 69 mod_timer(&bdata->timer,
66 jiffies + msecs_to_jiffies(button->debounce_interval)); 70 jiffies + msecs_to_jiffies(button->debounce_interval));
67 else 71 else
68 gpio_keys_report_event(bdata); 72 schedule_work(&bdata->work);
69 73
70 return IRQ_HANDLED; 74 return IRQ_HANDLED;
71} 75}
@@ -113,7 +117,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
113 bdata->input = input; 117 bdata->input = input;
114 bdata->button = button; 118 bdata->button = button;
115 setup_timer(&bdata->timer, 119 setup_timer(&bdata->timer,
116 gpio_check_button, (unsigned long)bdata); 120 gpio_keys_timer, (unsigned long)bdata);
121 INIT_WORK(&bdata->work, gpio_keys_report_event);
117 122
118 error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); 123 error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
119 if (error < 0) { 124 if (error < 0) {
@@ -174,6 +179,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
174 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); 179 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
175 if (pdata->buttons[i].debounce_interval) 180 if (pdata->buttons[i].debounce_interval)
176 del_timer_sync(&ddata->data[i].timer); 181 del_timer_sync(&ddata->data[i].timer);
182 cancel_work_sync(&ddata->data[i].work);
177 gpio_free(pdata->buttons[i].gpio); 183 gpio_free(pdata->buttons[i].gpio);
178 } 184 }
179 185
@@ -199,6 +205,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
199 free_irq(irq, &ddata->data[i]); 205 free_irq(irq, &ddata->data[i]);
200 if (pdata->buttons[i].debounce_interval) 206 if (pdata->buttons[i].debounce_interval)
201 del_timer_sync(&ddata->data[i].timer); 207 del_timer_sync(&ddata->data[i].timer);
208 cancel_work_sync(&ddata->data[i].work);
202 gpio_free(pdata->buttons[i].gpio); 209 gpio_free(pdata->buttons[i].gpio);
203 } 210 }
204 211