Browse Source

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>
Ben Nizette 16 năm trước cách đây
mục cha
commit
0f751719e4
1 tập tin đã thay đổi với 14 bổ sung2 xóa
  1. 14 2
      drivers/input/keyboard/omap-keypad.c

+ 14 - 2
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 */
 	/* disable keyboard interrupt and schedule for handling */
 	if (cpu_is_omap24xx()) {
 	if (cpu_is_omap24xx()) {
 		int i;
 		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
 	} else
 		/* disable keyboard interrupt and schedule for handling */
 		/* disable keyboard interrupt and schedule for handling */
 		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
 		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);