aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-10-17 02:26:29 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:49 -0400
commit1d99493b3a68e40e56459ea3565d4402fb6e5f3a (patch)
tree362ebcf8871e0fad07aa754bb5194de3a2cd64d3
parentf13ef7754f724842dbf5ae6d85d0604fff0d1a84 (diff)
Fix CONFIG_DEBUG_SHIRQ trigger on free_irq()
Andy Gospodarek pointed out that because we return in the middle of the free_irq() function, we never actually do call the IRQ handler that just got deregistered. This should fix it, although I expect Andrew will want to convert those 'return's to 'break'. That's a separate change though. Signed-off-by: David Woodhouse <dwmw2@infradead.org> Cc: Andy Gospodarek <andy@greyhouse.net> Cc: Fernando Luis Vzquez Cao <fernando@oss.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/irq/manage.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7230d914eaa2..80eab7a04205 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -405,7 +405,6 @@ void free_irq(unsigned int irq, void *dev_id)
405 struct irq_desc *desc; 405 struct irq_desc *desc;
406 struct irqaction **p; 406 struct irqaction **p;
407 unsigned long flags; 407 unsigned long flags;
408 irqreturn_t (*handler)(int, void *) = NULL;
409 408
410 WARN_ON(in_interrupt()); 409 WARN_ON(in_interrupt());
411 if (irq >= NR_IRQS) 410 if (irq >= NR_IRQS)
@@ -445,8 +444,21 @@ void free_irq(unsigned int irq, void *dev_id)
445 444
446 /* Make sure it's not being used on another CPU */ 445 /* Make sure it's not being used on another CPU */
447 synchronize_irq(irq); 446 synchronize_irq(irq);
448 if (action->flags & IRQF_SHARED) 447#ifdef CONFIG_DEBUG_SHIRQ
449 handler = action->handler; 448 /*
449 * It's a shared IRQ -- the driver ought to be
450 * prepared for it to happen even now it's
451 * being freed, so let's make sure.... We do
452 * this after actually deregistering it, to
453 * make sure that a 'real' IRQ doesn't run in
454 * parallel with our fake
455 */
456 if (action->flags & IRQF_SHARED) {
457 local_irq_save(flags);
458 action->handler(irq, dev_id);
459 local_irq_restore(flags);
460 }
461#endif
450 kfree(action); 462 kfree(action);
451 return; 463 return;
452 } 464 }
@@ -454,19 +466,6 @@ void free_irq(unsigned int irq, void *dev_id)
454 spin_unlock_irqrestore(&desc->lock, flags); 466 spin_unlock_irqrestore(&desc->lock, flags);
455 return; 467 return;
456 } 468 }
457#ifdef CONFIG_DEBUG_SHIRQ
458 if (handler) {
459 /*
460 * It's a shared IRQ -- the driver ought to be prepared for it
461 * to happen even now it's being freed, so let's make sure....
462 * We do this after actually deregistering it, to make sure that
463 * a 'real' IRQ doesn't run in parallel with our fake
464 */
465 local_irq_save(flags);
466 handler(irq, dev_id);
467 local_irq_restore(flags);
468 }
469#endif
470} 469}
471EXPORT_SYMBOL(free_irq); 470EXPORT_SYMBOL(free_irq);
472 471