diff options
Diffstat (limited to 'kernel/irq/spurious.c')
| -rw-r--r-- | kernel/irq/spurious.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dfbd550401b2..aa57d5da18c1 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
| @@ -167,6 +167,13 @@ out: | |||
| 167 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); | 167 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static inline int bad_action_ret(irqreturn_t action_ret) | ||
| 171 | { | ||
| 172 | if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) | ||
| 173 | return 0; | ||
| 174 | return 1; | ||
| 175 | } | ||
| 176 | |||
| 170 | /* | 177 | /* |
| 171 | * If 99,900 of the previous 100,000 interrupts have not been handled | 178 | * If 99,900 of the previous 100,000 interrupts have not been handled |
| 172 | * then assume that the IRQ is stuck in some manner. Drop a diagnostic | 179 | * 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, | |||
| 182 | struct irqaction *action; | 189 | struct irqaction *action; |
| 183 | unsigned long flags; | 190 | unsigned long flags; |
| 184 | 191 | ||
| 185 | if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { | 192 | if (bad_action_ret(action_ret)) { |
| 186 | printk(KERN_ERR "irq event %d: bogus return value %x\n", | 193 | printk(KERN_ERR "irq event %d: bogus return value %x\n", |
| 187 | irq, action_ret); | 194 | irq, action_ret); |
| 188 | } else { | 195 | } else { |
| @@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, | |||
| 201 | raw_spin_lock_irqsave(&desc->lock, flags); | 208 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 202 | action = desc->action; | 209 | action = desc->action; |
| 203 | while (action) { | 210 | while (action) { |
| 204 | printk(KERN_ERR "[<%p>]", action->handler); | 211 | printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler); |
| 205 | print_symbol(" (%s)", | 212 | if (action->thread_fn) |
| 206 | (unsigned long)action->handler); | 213 | printk(KERN_CONT " threaded [<%p>] %pf", |
| 207 | printk("\n"); | 214 | action->thread_fn, action->thread_fn); |
| 215 | printk(KERN_CONT "\n"); | ||
| 208 | action = action->next; | 216 | action = action->next; |
| 209 | } | 217 | } |
| 210 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 218 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| @@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, | |||
| 262 | if (desc->istate & IRQS_POLL_INPROGRESS) | 270 | if (desc->istate & IRQS_POLL_INPROGRESS) |
| 263 | return; | 271 | return; |
| 264 | 272 | ||
| 265 | if (unlikely(action_ret != IRQ_HANDLED)) { | 273 | /* we get here again via the threaded handler */ |
| 274 | if (action_ret == IRQ_WAKE_THREAD) | ||
| 275 | return; | ||
| 276 | |||
| 277 | if (bad_action_ret(action_ret)) { | ||
| 278 | report_bad_irq(irq, desc, action_ret); | ||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (unlikely(action_ret == IRQ_NONE)) { | ||
| 266 | /* | 283 | /* |
| 267 | * If we are seeing only the odd spurious IRQ caused by | 284 | * If we are seeing only the odd spurious IRQ caused by |
| 268 | * bus asynchronicity then don't eventually trigger an error, | 285 | * bus asynchronicity then don't eventually trigger an error, |
| @@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, | |||
| 274 | else | 291 | else |
| 275 | desc->irqs_unhandled++; | 292 | desc->irqs_unhandled++; |
| 276 | desc->last_unhandled = jiffies; | 293 | desc->last_unhandled = jiffies; |
| 277 | if (unlikely(action_ret != IRQ_NONE)) | ||
| 278 | report_bad_irq(irq, desc, action_ret); | ||
| 279 | } | 294 | } |
| 280 | 295 | ||
| 281 | if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { | 296 | if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { |
