Input: matrix-keypad - handle cases when GPIOs can't be wakeup sources
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 25 Dec 2009 06:50:23 +0000 (22:50 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 25 Dec 2009 06:50:55 +0000 (22:50 -0800)
On certain boards not all GPIOs may be used as wakeup sources, in which
case some of enable_irq_wake() calls will fail. On resume calling
disable_irq_wake() will warn about unbalanced IRQ wake disable.

Solve this by checking whether enable_irq_wake() succeeded or not and
no not call disable_irq_wake() for these GPIOs/IRQs that have not been
enabled.

Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/keyboard/matrix_keypad.c

index 34f4a29..d3c8b61 100644 (file)
@@ -29,11 +29,13 @@ struct matrix_keypad {
        unsigned short *keycodes;
        unsigned int row_shift;
 
+       DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
+
        uint32_t last_key_state[MATRIX_MAX_COLS];
        struct delayed_work work;
+       spinlock_t lock;
        bool scan_pending;
        bool stopped;
-       spinlock_t lock;
 };
 
 /*
@@ -222,9 +224,16 @@ static int matrix_keypad_suspend(struct device *dev)
 
        matrix_keypad_stop(keypad->input_dev);
 
-       if (device_may_wakeup(&pdev->dev))
-               for (i = 0; i < pdata->num_row_gpios; i++)
-                       enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+       if (device_may_wakeup(&pdev->dev)) {
+               for (i = 0; i < pdata->num_row_gpios; i++) {
+                       if (!test_bit(i, keypad->disabled_gpios)) {
+                               unsigned int gpio = pdata->row_gpios[i];
+
+                               if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
+                                       __set_bit(i, keypad->disabled_gpios);
+                       }
+               }
+       }
 
        return 0;
 }
@@ -236,9 +245,15 @@ static int matrix_keypad_resume(struct device *dev)
        const struct matrix_keypad_platform_data *pdata = keypad->pdata;
        int i;
 
-       if (device_may_wakeup(&pdev->dev))
-               for (i = 0; i < pdata->num_row_gpios; i++)
-                       disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+       if (device_may_wakeup(&pdev->dev)) {
+               for (i = 0; i < pdata->num_row_gpios; i++) {
+                       if (test_and_clear_bit(i, keypad->disabled_gpios)) {
+                               unsigned int gpio = pdata->row_gpios[i];
+
+                               disable_irq_wake(gpio_to_irq(gpio));
+                       }
+               }
+       }
 
        matrix_keypad_start(keypad->input_dev);