[PATCH] Debug shared irqs
Drivers registering IRQ handlers with SA_SHIRQ really ought to be able to handle an interrupt happening before request_irq() returns. They also ought to be able to handle an interrupt happening during the start of their call to free_irq(). Let's test that hypothesis.... [bunk@stusta.de: Kconfig fixes] Signed-off-by: David Woodhouse <dwmw2@infradead.org> Cc: Arjan van de Ven <arjan@infradead.org> Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f9e4acf3be
commit
a304e1b828
@ -357,6 +357,7 @@ void free_irq(unsigned int irq, void *dev_id)
|
||||
struct irq_desc *desc;
|
||||
struct irqaction **p;
|
||||
unsigned long flags;
|
||||
irqreturn_t (*handler)(int, void *) = NULL;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
if (irq >= NR_IRQS)
|
||||
@ -396,6 +397,8 @@ void free_irq(unsigned int irq, void *dev_id)
|
||||
|
||||
/* Make sure it's not being used on another CPU */
|
||||
synchronize_irq(irq);
|
||||
if (action->flags & IRQF_SHARED)
|
||||
handler = action->handler;
|
||||
kfree(action);
|
||||
return;
|
||||
}
|
||||
@ -403,6 +406,17 @@ void free_irq(unsigned int irq, void *dev_id)
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
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
|
||||
*/
|
||||
handler(irq, dev_id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(free_irq);
|
||||
|
||||
@ -475,6 +489,25 @@ int request_irq(unsigned int irq, irq_handler_t handler,
|
||||
|
||||
select_smp_affinity(irq);
|
||||
|
||||
#ifdef CONFIG_DEBUG_SHIRQ
|
||||
if (irqflags & IRQF_SHARED) {
|
||||
/*
|
||||
* It's a shared IRQ -- the driver ought to be prepared for it
|
||||
* to happen immediately, so let's make sure....
|
||||
* We do this before actually registering it, to make sure that
|
||||
* a 'real' IRQ doesn't run in parallel with our fake
|
||||
*/
|
||||
if (irqflags & IRQF_DISABLED) {
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
handler(irq, dev_id);
|
||||
local_irq_restore(flags);
|
||||
} else
|
||||
handler(irq, dev_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
retval = setup_irq(irq, action);
|
||||
if (retval)
|
||||
kfree(action);
|
||||
|
@ -77,6 +77,15 @@ config DEBUG_KERNEL
|
||||
Say Y here if you are developing drivers or trying to debug and
|
||||
identify kernel problems.
|
||||
|
||||
config DEBUG_SHIRQ
|
||||
bool "Debug shared IRQ handlers"
|
||||
depends on DEBUG_KERNEL && GENERIC_HARDIRQS
|
||||
help
|
||||
Enable this to generate a spurious interrupt as soon as a shared
|
||||
interrupt handler is registered, and just before one is deregistered.
|
||||
Drivers ought to be able to handle interrupts coming in at those
|
||||
points; some don't and need to be caught.
|
||||
|
||||
config LOG_BUF_SHIFT
|
||||
int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
|
||||
range 12 21
|
||||
|
Loading…
Reference in New Issue
Block a user