From c4347efb98b2506807259336ac1c4c0a9ded85e6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 24 May 2007 08:37:14 -0700 Subject: [PATCH] --- yaml --- r: 56927 b: refs/heads/master c: 92ea77275b5345c1300433f28689493dc4163f24 h: refs/heads/master i: 56925: 74ce242bd202f379a3abb221d1ea8926f173656d 56923: ed3cd0aa828f4d53f1e72c0400b988c021d06b1b 56919: 6243437f6cd07d72888665333df615387df6cb82 56911: f60716bfc2f99a79d43b5323ae503a8bc7be0955 56895: 2d6c5d62af1c1a57a737f433ce3afa4e676e2f67 v: v3 --- [refs] | 2 +- trunk/kernel/irq/spurious.c | 46 +++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index e5ea6e7d6597..567bccd56f22 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: db2668fdbeb2e3c95ebadf95856c9e31a8a8d569 +refs/heads/master: 92ea77275b5345c1300433f28689493dc4163f24 diff --git a/trunk/kernel/irq/spurious.c b/trunk/kernel/irq/spurious.c index b0d81aae472f..bd9e272d55e9 100644 --- a/trunk/kernel/irq/spurious.c +++ b/trunk/kernel/irq/spurious.c @@ -135,6 +135,39 @@ report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) } } +static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) +{ + struct irqaction *action; + + if (!irqfixup) + return 0; + + /* We didn't actually handle the IRQ - see if it was misrouted? */ + if (action_ret == IRQ_NONE) + return 1; + + /* + * But for 'irqfixup == 2' we also do it for handled interrupts if + * they are marked as IRQF_IRQPOLL (or for irq zero, which is the + * traditional PC timer interrupt.. Legacy) + */ + if (irqfixup < 2) + return 0; + + if (!irq) + return 1; + + /* + * Since we don't get the descriptor lock, "action" can + * change under us. We don't really care, but we don't + * want to follow a NULL pointer. So tell the compiler to + * just load it once by using a barrier. + */ + action = desc->action; + barrier(); + return action && (action->flags & IRQF_IRQPOLL); +} + void note_interrupt(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) { @@ -144,15 +177,10 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, report_bad_irq(irq, desc, action_ret); } - if (unlikely(irqfixup)) { - /* Don't punish working computers */ - if ((irqfixup == 2 && ((irq == 0) || - (desc->action->flags & IRQF_IRQPOLL))) || - action_ret == IRQ_NONE) { - int ok = misrouted_irq(irq); - if (action_ret == IRQ_NONE) - desc->irqs_unhandled -= ok; - } + if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { + int ok = misrouted_irq(irq); + if (action_ret == IRQ_NONE) + desc->irqs_unhandled -= ok; } desc->irq_count++;