Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ben Nizette and committed by
Dmitry Torokhov
0f751719 0c387ec8

+14 -2
+14 -2
drivers/input/keyboard/omap-keypad.c
··· 100 100 /* disable keyboard interrupt and schedule for handling */ 101 101 if (cpu_is_omap24xx()) { 102 102 int i; 103 - for (i = 0; i < omap_kp->rows; i++) 104 - disable_irq(gpio_to_irq(row_gpios[i])); 103 + 104 + for (i = 0; i < omap_kp->rows; i++) { 105 + int gpio_irq = gpio_to_irq(row_gpios[i]); 106 + /* 107 + * The interrupt which we're currently handling should 108 + * be disabled _nosync() to avoid deadlocks waiting 109 + * for this handler to complete. All others should 110 + * be disabled the regular way for SMP safety. 111 + */ 112 + if (gpio_irq == irq) 113 + disable_irq_nosync(gpio_irq); 114 + else 115 + disable_irq(gpio_irq); 116 + } 105 117 } else 106 118 /* disable keyboard interrupt and schedule for handling */ 107 119 omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);