123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- /*
- * linux/kernel/irq/spurious.c
- *
- * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
- *
- * This file contains spurious interrupt handling.
- */
- #include <linux/irq.h>
- #include <linux/module.h>
- #include <linux/kallsyms.h>
- #include <linux/interrupt.h>
- /*
- * 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
- * and try to turn the IRQ off.
- *
- * (The other 100-of-100,000 interrupts may have been a correctly
- * functioning device sharing an IRQ with the failing one)
- *
- * Called under desc->lock
- */
- static void
- __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
- {
- struct irqaction *action;
- if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
- printk(KERN_ERR "irq event %d: bogus return value %x\n",
- irq, action_ret);
- } else {
- printk(KERN_ERR "irq %d: nobody cared!\n", irq);
- }
- dump_stack();
- printk(KERN_ERR "handlers:\n");
- action = desc->action;
- while (action) {
- printk(KERN_ERR "[<%p>]", action->handler);
- print_symbol(" (%s)",
- (unsigned long)action->handler);
- printk("\n");
- action = action->next;
- }
- }
- void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
- {
- static int count = 100;
- if (count > 0) {
- count--;
- __report_bad_irq(irq, desc, action_ret);
- }
- }
- void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
- {
- if (action_ret != IRQ_HANDLED) {
- desc->irqs_unhandled++;
- if (action_ret != IRQ_NONE)
- report_bad_irq(irq, desc, action_ret);
- }
- desc->irq_count++;
- if (desc->irq_count < 100000)
- return;
- desc->irq_count = 0;
- if (desc->irqs_unhandled > 99900) {
- /*
- * The interrupt is stuck
- */
- __report_bad_irq(irq, desc, action_ret);
- /*
- * Now kill the IRQ
- */
- printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
- desc->status |= IRQ_DISABLED;
- desc->handler->disable(irq);
- }
- desc->irqs_unhandled = 0;
- }
- int noirqdebug;
- int __init noirqdebug_setup(char *str)
- {
- noirqdebug = 1;
- printk(KERN_INFO "IRQ lockup detection disabled\n");
- return 1;
- }
- __setup("noirqdebug", noirqdebug_setup);
|