diff options
author | Ben Nizette <bn@niasdigital.com> | 2009-04-17 20:35:57 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-04-17 20:41:44 -0700 |
commit | 0f751719e4e689efbe537233552e5f0529ecb8ce (patch) | |
tree | e08255dc20010d49a2640e589c8ac042153795bc /drivers/input | |
parent | 0c387ec88abf4f1ddfe8c3be10ea981bc447b406 (diff) | |
download | kernel_samsung_tuna-0f751719e4e689efbe537233552e5f0529ecb8ce.zip kernel_samsung_tuna-0f751719e4e689efbe537233552e5f0529ecb8ce.tar.gz kernel_samsung_tuna-0f751719e4e689efbe537233552e5f0529ecb8ce.tar.bz2 |
Input: omap-keypad - use disable_irq_nosync() in irq handler
disable_irq() waits for all running handlers to complete before
returning. As such, if it's used to disable an interrupt from
that interrupt's handler it will deadlock. This replaces the
dangerous instances with the _nosync() variant which doesn't have
this problem.
Signed-off-by: Ben Nizette <bn@niasdigital.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/omap-keypad.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 058fa8b..87ec7b1 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -100,8 +100,20 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) /* disable keyboard interrupt and schedule for handling */ if (cpu_is_omap24xx()) { int i; - for (i = 0; i < omap_kp->rows; i++) - disable_irq(gpio_to_irq(row_gpios[i])); + + for (i = 0; i < omap_kp->rows; i++) { + int gpio_irq = gpio_to_irq(row_gpios[i]); + /* + * The interrupt which we're currently handling should + * be disabled _nosync() to avoid deadlocks waiting + * for this handler to complete. All others should + * be disabled the regular way for SMP safety. + */ + if (gpio_irq == irq) + disable_irq_nosync(gpio_irq); + else + disable_irq(gpio_irq); + } } else /* disable keyboard interrupt and schedule for handling */ omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |