handle.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. static irqreturn_t __handle_irq_event(unsigned int irq, struct irqaction *action)
  47. {
  48. irqreturn_t ret, retval = IRQ_NONE;
  49. unsigned int status = 0;
  50. do {
  51. trace_irq_handler_entry(irq, action);
  52. ret = action->handler(irq, action->dev_id);
  53. trace_irq_handler_exit(irq, action, ret);
  54. if (WARN_ON_ONCE(!irqs_disabled()))
  55. local_irq_disable();
  56. switch (ret) {
  57. case IRQ_WAKE_THREAD:
  58. /*
  59. * Set result to handled so the spurious check
  60. * does not trigger.
  61. */
  62. ret = IRQ_HANDLED;
  63. /*
  64. * Catch drivers which return WAKE_THREAD but
  65. * did not set up a thread function
  66. */
  67. if (unlikely(!action->thread_fn)) {
  68. warn_no_thread(irq, action);
  69. break;
  70. }
  71. /*
  72. * Wake up the handler thread for this
  73. * action. In case the thread crashed and was
  74. * killed we just pretend that we handled the
  75. * interrupt. The hardirq handler above has
  76. * disabled the device interrupt, so no irq
  77. * storm is lurking.
  78. */
  79. if (likely(!test_bit(IRQTF_DIED,
  80. &action->thread_flags))) {
  81. set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
  82. wake_up_process(action->thread);
  83. }
  84. /* Fall through to add to randomness */
  85. case IRQ_HANDLED:
  86. status |= action->flags;
  87. break;
  88. default:
  89. break;
  90. }
  91. retval |= ret;
  92. action = action->next;
  93. } while (action);
  94. if (status & IRQF_SAMPLE_RANDOM)
  95. add_interrupt_randomness(irq);
  96. return retval;
  97. }
  98. irqreturn_t
  99. handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
  100. {
  101. irqreturn_t ret = __handle_irq_event(desc->irq_data.irq, action);
  102. if (!noirqdebug)
  103. note_interrupt(desc->irq_data.irq, desc, ret);
  104. return ret;
  105. }
  106. irqreturn_t handle_irq_event(struct irq_desc *desc)
  107. {
  108. struct irqaction *action = desc->action;
  109. irqreturn_t ret;
  110. desc->status &= ~IRQ_PENDING;
  111. desc->status |= IRQ_INPROGRESS;
  112. raw_spin_unlock(&desc->lock);
  113. ret = handle_irq_event_percpu(desc, action);
  114. raw_spin_lock(&desc->lock);
  115. desc->status &= ~IRQ_INPROGRESS;
  116. return ret;
  117. }
  118. /**
  119. * handle_IRQ_event - irq action chain handler
  120. * @irq: the interrupt number
  121. * @action: the interrupt action chain for this irq
  122. *
  123. * Handles the action chain of an irq event
  124. */
  125. irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
  126. {
  127. return __handle_irq_event(irq, action);
  128. }