spurious.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * linux/kernel/irq/spurious.c
  3. *
  4. * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
  5. *
  6. * This file contains spurious interrupt handling.
  7. */
  8. #include <linux/irq.h>
  9. #include <linux/module.h>
  10. #include <linux/kallsyms.h>
  11. #include <linux/interrupt.h>
  12. /*
  13. * If 99,900 of the previous 100,000 interrupts have not been handled
  14. * then assume that the IRQ is stuck in some manner. Drop a diagnostic
  15. * and try to turn the IRQ off.
  16. *
  17. * (The other 100-of-100,000 interrupts may have been a correctly
  18. * functioning device sharing an IRQ with the failing one)
  19. *
  20. * Called under desc->lock
  21. */
  22. static void
  23. __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
  24. {
  25. struct irqaction *action;
  26. if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
  27. printk(KERN_ERR "irq event %d: bogus return value %x\n",
  28. irq, action_ret);
  29. } else {
  30. printk(KERN_ERR "irq %d: nobody cared!\n", irq);
  31. }
  32. dump_stack();
  33. printk(KERN_ERR "handlers:\n");
  34. action = desc->action;
  35. while (action) {
  36. printk(KERN_ERR "[<%p>]", action->handler);
  37. print_symbol(" (%s)",
  38. (unsigned long)action->handler);
  39. printk("\n");
  40. action = action->next;
  41. }
  42. }
  43. void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
  44. {
  45. static int count = 100;
  46. if (count > 0) {
  47. count--;
  48. __report_bad_irq(irq, desc, action_ret);
  49. }
  50. }
  51. void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
  52. {
  53. if (action_ret != IRQ_HANDLED) {
  54. desc->irqs_unhandled++;
  55. if (action_ret != IRQ_NONE)
  56. report_bad_irq(irq, desc, action_ret);
  57. }
  58. desc->irq_count++;
  59. if (desc->irq_count < 100000)
  60. return;
  61. desc->irq_count = 0;
  62. if (desc->irqs_unhandled > 99900) {
  63. /*
  64. * The interrupt is stuck
  65. */
  66. __report_bad_irq(irq, desc, action_ret);
  67. /*
  68. * Now kill the IRQ
  69. */
  70. printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
  71. desc->status |= IRQ_DISABLED;
  72. desc->handler->disable(irq);
  73. }
  74. desc->irqs_unhandled = 0;
  75. }
  76. int noirqdebug;
  77. int __init noirqdebug_setup(char *str)
  78. {
  79. noirqdebug = 1;
  80. printk(KERN_INFO "IRQ lockup detection disabled\n");
  81. return 1;
  82. }
  83. __setup("noirqdebug", noirqdebug_setup);