Commit 3297f15f authored by Russell King's avatar Russell King

[ARM] Improve bad IRQ reporting.

This gives greater information on the cause of the bad IRQ, allowing
the cause to be more effectively traced.
parent c56ac808
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/kallsyms.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -225,6 +226,34 @@ static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs) ...@@ -225,6 +226,34 @@ static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs)
} }
static void static void
report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int ret)
{
static int count = 100;
struct irqaction *action;
if (!count)
return;
count--;
if (ret != IRQ_HANDLED && ret != IRQ_NONE) {
printk("irq%u: bogus retval mask %x\n", irq, ret);
} else {
printk("irq%u: nobody cared\n", irq);
}
show_regs(regs);
dump_stack();
printk(KERN_ERR "handlers:");
action = desc->action;
do {
printk("\n" KERN_ERR "[<%p>]", action->handler);
print_symbol(" (%s)", (unsigned long)action->handler);
action = action->next;
} while (action);
printk("\n");
}
static int
__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
{ {
unsigned int status; unsigned int status;
...@@ -247,18 +276,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) ...@@ -247,18 +276,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
spin_lock_irq(&irq_controller_lock); spin_lock_irq(&irq_controller_lock);
if (retval != 1) { return retval;
static int count = 100;
if (count) {
count--;
if (retval) {
printk("irq event %d: bogus retval mask %x\n",
irq, retval);
} else {
printk("irq %d: nobody cared\n", irq);
}
}
}
} }
/* /*
...@@ -276,8 +294,11 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -276,8 +294,11 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
kstat_cpu(cpu).irqs[irq]++; kstat_cpu(cpu).irqs[irq]++;
action = desc->action; action = desc->action;
if (action) if (action) {
__do_irq(irq, desc->action, regs); int ret = __do_irq(irq, action, regs);
if (ret != IRQ_HANDLED)
report_bad_irq(irq, regs, desc, ret);
}
} }
/* /*
...@@ -313,6 +334,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -313,6 +334,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
do { do {
struct irqaction *action; struct irqaction *action;
int ret;
action = desc->action; action = desc->action;
if (!action) if (!action)
...@@ -323,7 +345,9 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -323,7 +345,9 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
desc->chip->unmask(irq); desc->chip->unmask(irq);
} }
__do_irq(irq, action, regs); ret = __do_irq(irq, action, regs);
if (ret != IRQ_HANDLED)
report_bad_irq(irq, regs, desc, ret);
} while (desc->pending && !desc->disable_depth); } while (desc->pending && !desc->disable_depth);
desc->running = 0; desc->running = 0;
...@@ -368,7 +392,10 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -368,7 +392,10 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
*/ */
action = desc->action; action = desc->action;
if (action) { if (action) {
__do_irq(irq, desc->action, regs); int ret = __do_irq(irq, desc->action, regs);
if (ret != IRQ_HANDLED)
report_bad_irq(irq, regs, desc, ret);
if (likely(!desc->disable_depth && if (likely(!desc->disable_depth &&
!check_irq_lock(desc, irq, regs))) !check_irq_lock(desc, irq, regs)))
......
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