Input: gpio_keys - report a wakeup_event for a button press
authorNeilBrown <neilb@suse.de>
Mon, 30 Jul 2012 05:18:47 +0000 (22:18 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 22 Aug 2012 05:29:48 +0000 (22:29 -0700)
In order to avoid races with suspend, a wakeup event must register as
such by calling pm_wakeup_event() or pm_stay_awake().  This will ensure
that the current suspend cycle aborts.

When the user-space visible event is created in the interrupt handler
(gpio_keys_irq_isr), a simple pm_wakeup_event() with no delay is
sufficient as suspend will synchronise with all interrupt delivery.

When the user-space visible event is created later
(gpio_keys_gpio_isr), we need to bracket the event with
pm_stay_awake() and pm_relax().

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/keyboard/gpio_keys.c

index b890231debd8e028d51ddf28321a9e9bdb3d2099..6a68041c261db45eafe9f4cadea39f1b032edb51 100644 (file)
@@ -344,6 +344,9 @@ static void gpio_keys_gpio_work_func(struct work_struct *work)
                container_of(work, struct gpio_button_data, work);
 
        gpio_keys_gpio_report_event(bdata);
+
+       if (bdata->button->wakeup)
+               pm_relax(bdata->input->dev.parent);
 }
 
 static void gpio_keys_gpio_timer(unsigned long _data)
@@ -359,6 +362,8 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
 
        BUG_ON(irq != bdata->irq);
 
+       if (bdata->button->wakeup)
+               pm_stay_awake(bdata->input->dev.parent);
        if (bdata->timer_debounce)
                mod_timer(&bdata->timer,
                        jiffies + msecs_to_jiffies(bdata->timer_debounce));
@@ -395,6 +400,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
        spin_lock_irqsave(&bdata->lock, flags);
 
        if (!bdata->key_pressed) {
+               if (bdata->button->wakeup)
+                       pm_wakeup_event(bdata->input->dev.parent, 0);
+
                input_event(input, EV_KEY, button->code, 1);
                input_sync(input);