瀏覽代碼

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 年之前
父節點
當前提交
0f751719e4
共有 1 個文件被更改,包括 14 次插入2 次删除
  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);