Commit 1d99493b authored by David Woodhouse's avatar David Woodhouse Committed by Linus Torvalds

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: default avatarDavid Woodhouse <dwmw2@infradead.org>
Cc: Andy Gospodarek <andy@greyhouse.net>
Cc: Fernando Luis Vzquez Cao <fernando@oss.ntt.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f13ef775
...@@ -405,7 +405,6 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -405,7 +405,6 @@ void free_irq(unsigned int irq, void *dev_id)
struct irq_desc *desc; struct irq_desc *desc;
struct irqaction **p; struct irqaction **p;
unsigned long flags; unsigned long flags;
irqreturn_t (*handler)(int, void *) = NULL;
WARN_ON(in_interrupt()); WARN_ON(in_interrupt());
if (irq >= NR_IRQS) if (irq >= NR_IRQS)
...@@ -445,8 +444,21 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -445,8 +444,21 @@ void free_irq(unsigned int irq, void *dev_id)
/* Make sure it's not being used on another CPU */ /* Make sure it's not being used on another CPU */
synchronize_irq(irq); synchronize_irq(irq);
if (action->flags & IRQF_SHARED) #ifdef CONFIG_DEBUG_SHIRQ
handler = action->handler; /*
* It's a shared IRQ -- the driver ought to be
* prepared for it to happen even now it's
* being freed, so let's make sure.... We do
* this after actually deregistering it, to
* make sure that a 'real' IRQ doesn't run in
* parallel with our fake
*/
if (action->flags & IRQF_SHARED) {
local_irq_save(flags);
action->handler(irq, dev_id);
local_irq_restore(flags);
}
#endif
kfree(action); kfree(action);
return; return;
} }
...@@ -454,19 +466,6 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -454,19 +466,6 @@ void free_irq(unsigned int irq, void *dev_id)
spin_unlock_irqrestore(&desc->lock, flags); spin_unlock_irqrestore(&desc->lock, flags);
return; return;
} }
#ifdef CONFIG_DEBUG_SHIRQ
if (handler) {
/*
* It's a shared IRQ -- the driver ought to be prepared for it
* to happen even now it's being freed, so let's make sure....
* We do this after actually deregistering it, to make sure that
* a 'real' IRQ doesn't run in parallel with our fake
*/
local_irq_save(flags);
handler(irq, dev_id);
local_irq_restore(flags);
}
#endif
} }
EXPORT_SYMBOL(free_irq); EXPORT_SYMBOL(free_irq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment