handle.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * linux/kernel/irq/handle.c
  3. *
  4. * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
  5. * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
  6. *
  7. * This file contains the core interrupt handling code.
  8. *
  9. * Detailed information is available in Documentation/DocBook/genericirq
  10. *
  11. */
  12. #include <linux/irq.h>
  13. #include <linux/random.h>
  14. #include <linux/sched.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/kernel_stat.h>
  17. #include <trace/events/irq.h>
  18. #include "internals.h"
  19. /**
  20. * handle_bad_irq - handle spurious and unhandled irqs
  21. * @irq: the interrupt number
  22. * @desc: description of the interrupt
  23. *
  24. * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
  25. */
  26. void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
  27. {
  28. print_irq_desc(irq, desc);
  29. kstat_incr_irqs_this_cpu(irq, desc);
  30. ack_bad_irq(irq);
  31. }
  32. /*
  33. * Special, empty irq handler:
  34. */
  35. irqreturn_t no_action(int cpl, void *dev_id)
  36. {
  37. return IRQ_NONE;
  38. }
  39. static void warn_no_thread(unsigned int irq, struct irqaction *action)
  40. {
  41. if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags))
  42. return;
  43. printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD "
  44. "but no thread function available.", irq, action->name);
  45. }
  46. /**
  47. * handle_IRQ_event - irq action chain handler
  48. * @irq: the interrupt number
  49. * @action: the interrupt action chain for this irq
  50. *
  51. * Handles the action chain of an irq event
  52. */
  53. irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
  54. {
  55. irqreturn_t ret, retval = IRQ_NONE;
  56. unsigned int status = 0;
  57. do {
  58. trace_irq_handler_entry(irq, action);
  59. ret = action->handler(irq, action->dev_id);
  60. trace_irq_handler_exit(irq, action, ret);
  61. switch (ret) {
  62. case IRQ_WAKE_THREAD:
  63. /*
  64. * Set result to handled so the spurious check
  65. * does not trigger.
  66. */
  67. ret = IRQ_HANDLED;
  68. /*
  69. * Catch drivers which return WAKE_THREAD but
  70. * did not set up a thread function
  71. */
  72. if (unlikely(!action->thread_fn)) {
  73. warn_no_thread(irq, action);
  74. break;
  75. }
  76. /*
  77. * Wake up the handler thread for this
  78. * action. In case the thread crashed and was
  79. * killed we just pretend that we handled the
  80. * interrupt. The hardirq handler above has
  81. * disabled the device interrupt, so no irq
  82. * storm is lurking.
  83. */
  84. if (likely(!test_bit(IRQTF_DIED,
  85. &action->thread_flags))) {
  86. set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
  87. wake_up_process(action->thread);
  88. }
  89. /* Fall through to add to randomness */
  90. case IRQ_HANDLED:
  91. status |= action->flags;
  92. break;
  93. default:
  94. break;
  95. }
  96. retval |= ret;
  97. action = action->next;
  98. } while (action);
  99. if (status & IRQF_SAMPLE_RANDOM)
  100. add_interrupt_randomness(irq);
  101. local_irq_disable();
  102. return retval;
  103. }