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>
This commit is contained in:
committed by
Linus Torvalds
parent
f13ef7754f
commit
1d99493b3a
@@ -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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user