aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlek Du <alek.du@intel.com>2009-06-11 05:00:35 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-06-11 05:08:50 -0400
commit0b346838c5862bfe911432956a106d602535d030 (patch)
tree0719e9f8904348d5abc1e2e3d8247788b5fc5e22 /drivers
parentc57c0a2a0d019aa8108f1155f99098ea7e7e1ab3 (diff)
Input: gpio-keys - change timer to workqueue
The gpio_get_value function of I2C/SPI GPIO expander may sleep thus this function call can not be called in a timer function. Signed-off-by: Alek Du <alek.du@intel.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/gpio_keys.c32
1 files changed, 12 insertions, 20 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 9767213b6c8f..2157cd7de00c 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -22,13 +22,14 @@
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
28struct gpio_button_data { 29struct 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 delayed_work work;
32}; 33};
33 34
34struct gpio_keys_drvdata { 35struct gpio_keys_drvdata {
@@ -36,8 +37,10 @@ struct gpio_keys_drvdata {
36 struct gpio_button_data data[0]; 37 struct gpio_button_data data[0];
37}; 38};
38 39
39static void gpio_keys_report_event(struct gpio_button_data *bdata) 40static void gpio_keys_report_event(struct work_struct *work)
40{ 41{
42 struct gpio_button_data *bdata =
43 container_of(work, struct gpio_button_data, work.work);
41 struct gpio_keys_button *button = bdata->button; 44 struct gpio_keys_button *button = bdata->button;
42 struct input_dev *input = bdata->input; 45 struct input_dev *input = bdata->input;
43 unsigned int type = button->type ?: EV_KEY; 46 unsigned int type = button->type ?: EV_KEY;
@@ -47,25 +50,17 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata)
47 input_sync(input); 50 input_sync(input);
48} 51}
49 52
50static void gpio_check_button(unsigned long _data)
51{
52 struct gpio_button_data *data = (struct gpio_button_data *)_data;
53
54 gpio_keys_report_event(data);
55}
56
57static irqreturn_t gpio_keys_isr(int irq, void *dev_id) 53static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
58{ 54{
59 struct gpio_button_data *bdata = dev_id; 55 struct gpio_button_data *bdata = dev_id;
60 struct gpio_keys_button *button = bdata->button; 56 struct gpio_keys_button *button = bdata->button;
57 unsigned long delay;
61 58
62 BUG_ON(irq != gpio_to_irq(button->gpio)); 59 BUG_ON(irq != gpio_to_irq(button->gpio));
63 60
64 if (button->debounce_interval) 61 delay = button->debounce_interval ?
65 mod_timer(&bdata->timer, 62 msecs_to_jiffies(button->debounce_interval) : 0;
66 jiffies + msecs_to_jiffies(button->debounce_interval)); 63 schedule_delayed_work(&bdata->work, delay);
67 else
68 gpio_keys_report_event(bdata);
69 64
70 return IRQ_HANDLED; 65 return IRQ_HANDLED;
71} 66}
@@ -112,8 +107,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
112 107
113 bdata->input = input; 108 bdata->input = input;
114 bdata->button = button; 109 bdata->button = button;
115 setup_timer(&bdata->timer, 110 INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event);
116 gpio_check_button, (unsigned long)bdata);
117 111
118 error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); 112 error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
119 if (error < 0) { 113 if (error < 0) {
@@ -172,8 +166,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
172 fail2: 166 fail2:
173 while (--i >= 0) { 167 while (--i >= 0) {
174 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); 168 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
175 if (pdata->buttons[i].debounce_interval) 169 cancel_delayed_work_sync(&ddata->data[i].work);
176 del_timer_sync(&ddata->data[i].timer);
177 gpio_free(pdata->buttons[i].gpio); 170 gpio_free(pdata->buttons[i].gpio);
178 } 171 }
179 172
@@ -197,8 +190,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
197 for (i = 0; i < pdata->nbuttons; i++) { 190 for (i = 0; i < pdata->nbuttons; i++) {
198 int irq = gpio_to_irq(pdata->buttons[i].gpio); 191 int irq = gpio_to_irq(pdata->buttons[i].gpio);
199 free_irq(irq, &ddata->data[i]); 192 free_irq(irq, &ddata->data[i]);
200 if (pdata->buttons[i].debounce_interval) 193 cancel_delayed_work_sync(&ddata->data[i].work);
201 del_timer_sync(&ddata->data[i].timer);
202 gpio_free(pdata->buttons[i].gpio); 194 gpio_free(pdata->buttons[i].gpio);
203 } 195 }
204 196