소스 검색

Don't call "note_interrupt()" with irq descriptor lock held

This reverts commit f72fa707604c015a6625e80f269506032d5430dc, and solves
the problem that it tried to fix by simply making "__do_IRQ()" call the
note_interrupt() function without the lock held, the way everybody else
does.

It should be noted that all interrupt handling code must never allow the
descriptor actors to be entered "recursively" (that's why we do all the
magic IRQ_PENDING stuff in the first place), so there actually is
exclusion at that much higher level, even in the absense of locking.

Acked-by: Vivek Goyal <vgoyal@in.ibm.com>
Acked-by:Pavel Emelianov <xemul@openvz.org>
Cc: Andrew Morton <akpm@osdl.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Linus Torvalds 18 년 전
부모
커밋
b42172fc7b
2개의 변경된 파일3개의 추가작업 그리고 7개의 파일을 삭제
  1. 2 2
      kernel/irq/handle.c
  2. 1 5
      kernel/irq/spurious.c

+ 2 - 2
kernel/irq/handle.c

@@ -231,10 +231,10 @@ fastcall unsigned int __do_IRQ(unsigned int irq)
 		spin_unlock(&desc->lock);
 		spin_unlock(&desc->lock);
 
 
 		action_ret = handle_IRQ_event(irq, action);
 		action_ret = handle_IRQ_event(irq, action);
-
-		spin_lock(&desc->lock);
 		if (!noirqdebug)
 		if (!noirqdebug)
 			note_interrupt(irq, desc, action_ret);
 			note_interrupt(irq, desc, action_ret);
+
+		spin_lock(&desc->lock);
 		if (likely(!(desc->status & IRQ_PENDING)))
 		if (likely(!(desc->status & IRQ_PENDING)))
 			break;
 			break;
 		desc->status &= ~IRQ_PENDING;
 		desc->status &= ~IRQ_PENDING;

+ 1 - 5
kernel/irq/spurious.c

@@ -147,11 +147,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
 	if (unlikely(irqfixup)) {
 	if (unlikely(irqfixup)) {
 		/* Don't punish working computers */
 		/* Don't punish working computers */
 		if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
 		if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
-			int ok;
-
-			spin_unlock(&desc->lock);
-			ok = misrouted_irq(irq);
-			spin_lock(&desc->lock);
+			int ok = misrouted_irq(irq);
 			if (action_ret == IRQ_NONE)
 			if (action_ret == IRQ_NONE)
 				desc->irqs_unhandled -= ok;
 				desc->irqs_unhandled -= ok;
 		}
 		}