| From ea4f7bd2aca9f68470e9aac0fc9432fd180b1fe7 Mon Sep 17 00:00:00 2001 |
| From: Zhang Bo <zbsdta@126.com> |
| Date: Mon, 5 Feb 2018 14:56:21 -0800 |
| Subject: Input: matrix_keypad - fix race when disabling interrupts |
| |
| From: Zhang Bo <zbsdta@126.com> |
| |
| commit ea4f7bd2aca9f68470e9aac0fc9432fd180b1fe7 upstream. |
| |
| If matrix_keypad_stop() is executing and the keypad interrupt is triggered, |
| disable_row_irqs() may be called by both matrix_keypad_interrupt() and |
| matrix_keypad_stop() at the same time, causing interrupts to be disabled |
| twice and the keypad being "stuck" after resuming. |
| |
| Take lock when setting keypad->stopped to ensure that ISR will not race |
| with matrix_keypad_stop() disabling interrupts. |
| |
| Signed-off-by: Zhang Bo <zbsdta@126.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/input/keyboard/matrix_keypad.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/input/keyboard/matrix_keypad.c |
| +++ b/drivers/input/keyboard/matrix_keypad.c |
| @@ -218,8 +218,10 @@ static void matrix_keypad_stop(struct in |
| { |
| struct matrix_keypad *keypad = input_get_drvdata(dev); |
| |
| + spin_lock_irq(&keypad->lock); |
| keypad->stopped = true; |
| - mb(); |
| + spin_unlock_irq(&keypad->lock); |
| + |
| flush_work(&keypad->work.work); |
| /* |
| * matrix_keypad_scan() will leave IRQs enabled; |