|
@@ -167,6 +167,13 @@ out:
|
|
|
jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
|
|
|
}
|
|
|
|
|
|
+static inline int bad_action_ret(irqreturn_t action_ret)
|
|
|
+{
|
|
|
+ if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
|
|
|
+ return 0;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* If 99,900 of the previous 100,000 interrupts have not been handled
|
|
|
* then assume that the IRQ is stuck in some manner. Drop a diagnostic
|
|
@@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
|
|
|
struct irqaction *action;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
|
|
|
+ if (bad_action_ret(action_ret)) {
|
|
|
printk(KERN_ERR "irq event %d: bogus return value %x\n",
|
|
|
irq, action_ret);
|
|
|
} else {
|
|
@@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
|
|
|
raw_spin_lock_irqsave(&desc->lock, flags);
|
|
|
action = desc->action;
|
|
|
while (action) {
|
|
|
- printk(KERN_ERR "[<%p>]", action->handler);
|
|
|
- print_symbol(" (%s)",
|
|
|
- (unsigned long)action->handler);
|
|
|
- printk("\n");
|
|
|
+ printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
|
|
|
+ if (action->thread_fn)
|
|
|
+ printk(KERN_CONT " threaded [<%p>] %pf",
|
|
|
+ action->thread_fn, action->thread_fn);
|
|
|
+ printk(KERN_CONT "\n");
|
|
|
action = action->next;
|
|
|
}
|
|
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
|
@@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
|
|
if (desc->istate & IRQS_POLL_INPROGRESS)
|
|
|
return;
|
|
|
|
|
|
- if (unlikely(action_ret != IRQ_HANDLED)) {
|
|
|
+ /* we get here again via the threaded handler */
|
|
|
+ if (action_ret == IRQ_WAKE_THREAD)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (bad_action_ret(action_ret)) {
|
|
|
+ report_bad_irq(irq, desc, action_ret);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (unlikely(action_ret == IRQ_NONE)) {
|
|
|
/*
|
|
|
* If we are seeing only the odd spurious IRQ caused by
|
|
|
* bus asynchronicity then don't eventually trigger an error,
|
|
@@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
|
|
else
|
|
|
desc->irqs_unhandled++;
|
|
|
desc->last_unhandled = jiffies;
|
|
|
- if (unlikely(action_ret != IRQ_NONE))
|
|
|
- report_bad_irq(irq, desc, action_ret);
|
|
|
}
|
|
|
|
|
|
if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
|