Commit a304e1b82808904c561b7b149b467e338c53fcce
Committed by
Linus Torvalds
1 parent
f9e4acf3be
Exists in
master
and in
4 other branches
[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>
Showing 2 changed files with 42 additions and 0 deletions Side-by-side Diff
kernel/irq/manage.c
... | ... | @@ -357,6 +357,7 @@ |
357 | 357 | struct irq_desc *desc; |
358 | 358 | struct irqaction **p; |
359 | 359 | unsigned long flags; |
360 | + irqreturn_t (*handler)(int, void *) = NULL; | |
360 | 361 | |
361 | 362 | WARN_ON(in_interrupt()); |
362 | 363 | if (irq >= NR_IRQS) |
... | ... | @@ -396,6 +397,8 @@ |
396 | 397 | |
397 | 398 | /* Make sure it's not being used on another CPU */ |
398 | 399 | synchronize_irq(irq); |
400 | + if (action->flags & IRQF_SHARED) | |
401 | + handler = action->handler; | |
399 | 402 | kfree(action); |
400 | 403 | return; |
401 | 404 | } |
... | ... | @@ -403,6 +406,17 @@ |
403 | 406 | spin_unlock_irqrestore(&desc->lock, flags); |
404 | 407 | return; |
405 | 408 | } |
409 | +#ifdef CONFIG_DEBUG_SHIRQ | |
410 | + if (handler) { | |
411 | + /* | |
412 | + * It's a shared IRQ -- the driver ought to be prepared for it | |
413 | + * to happen even now it's being freed, so let's make sure.... | |
414 | + * We do this after actually deregistering it, to make sure that | |
415 | + * a 'real' IRQ doesn't run in parallel with our fake | |
416 | + */ | |
417 | + handler(irq, dev_id); | |
418 | + } | |
419 | +#endif | |
406 | 420 | } |
407 | 421 | EXPORT_SYMBOL(free_irq); |
408 | 422 | |
... | ... | @@ -474,6 +488,25 @@ |
474 | 488 | action->dev_id = dev_id; |
475 | 489 | |
476 | 490 | select_smp_affinity(irq); |
491 | + | |
492 | +#ifdef CONFIG_DEBUG_SHIRQ | |
493 | + if (irqflags & IRQF_SHARED) { | |
494 | + /* | |
495 | + * It's a shared IRQ -- the driver ought to be prepared for it | |
496 | + * to happen immediately, so let's make sure.... | |
497 | + * We do this before actually registering it, to make sure that | |
498 | + * a 'real' IRQ doesn't run in parallel with our fake | |
499 | + */ | |
500 | + if (irqflags & IRQF_DISABLED) { | |
501 | + unsigned long flags; | |
502 | + | |
503 | + local_irq_save(flags); | |
504 | + handler(irq, dev_id); | |
505 | + local_irq_restore(flags); | |
506 | + } else | |
507 | + handler(irq, dev_id); | |
508 | + } | |
509 | +#endif | |
477 | 510 | |
478 | 511 | retval = setup_irq(irq, action); |
479 | 512 | if (retval) |
lib/Kconfig.debug
... | ... | @@ -77,6 +77,15 @@ |
77 | 77 | Say Y here if you are developing drivers or trying to debug and |
78 | 78 | identify kernel problems. |
79 | 79 | |
80 | +config DEBUG_SHIRQ | |
81 | + bool "Debug shared IRQ handlers" | |
82 | + depends on DEBUG_KERNEL && GENERIC_HARDIRQS | |
83 | + help | |
84 | + Enable this to generate a spurious interrupt as soon as a shared | |
85 | + interrupt handler is registered, and just before one is deregistered. | |
86 | + Drivers ought to be able to handle interrupts coming in at those | |
87 | + points; some don't and need to be caught. | |
88 | + | |
80 | 89 | config LOG_BUF_SHIFT |
81 | 90 | int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL |
82 | 91 | range 12 21 |