autoprobe.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * linux/kernel/irq/autoprobe.c
  3. *
  4. * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
  5. *
  6. * This file contains the interrupt probing code and driver APIs.
  7. */
  8. #include <linux/irq.h>
  9. #include <linux/module.h>
  10. #include <linux/interrupt.h>
  11. /*
  12. * Autodetection depends on the fact that any interrupt that
  13. * comes in on to an unassigned handler will get stuck with
  14. * "IRQ_WAITING" cleared and the interrupt disabled.
  15. */
  16. static DECLARE_MUTEX(probe_sem);
  17. /**
  18. * probe_irq_on - begin an interrupt autodetect
  19. *
  20. * Commence probing for an interrupt. The interrupts are scanned
  21. * and a mask of potential interrupt lines is returned.
  22. *
  23. */
  24. unsigned long probe_irq_on(void)
  25. {
  26. unsigned long val, delay;
  27. irq_desc_t *desc;
  28. unsigned int i;
  29. down(&probe_sem);
  30. /*
  31. * something may have generated an irq long ago and we want to
  32. * flush such a longstanding irq before considering it as spurious.
  33. */
  34. for (i = NR_IRQS-1; i > 0; i--) {
  35. desc = irq_desc + i;
  36. spin_lock_irq(&desc->lock);
  37. if (!irq_desc[i].action)
  38. irq_desc[i].handler->startup(i);
  39. spin_unlock_irq(&desc->lock);
  40. }
  41. /* Wait for longstanding interrupts to trigger. */
  42. for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
  43. /* about 20ms delay */ barrier();
  44. /*
  45. * enable any unassigned irqs
  46. * (we must startup again here because if a longstanding irq
  47. * happened in the previous stage, it may have masked itself)
  48. */
  49. for (i = NR_IRQS-1; i > 0; i--) {
  50. desc = irq_desc + i;
  51. spin_lock_irq(&desc->lock);
  52. if (!desc->action) {
  53. desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
  54. if (desc->handler->startup(i))
  55. desc->status |= IRQ_PENDING;
  56. }
  57. spin_unlock_irq(&desc->lock);
  58. }
  59. /*
  60. * Wait for spurious interrupts to trigger
  61. */
  62. for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
  63. /* about 100ms delay */ barrier();
  64. /*
  65. * Now filter out any obviously spurious interrupts
  66. */
  67. val = 0;
  68. for (i = 0; i < NR_IRQS; i++) {
  69. irq_desc_t *desc = irq_desc + i;
  70. unsigned int status;
  71. spin_lock_irq(&desc->lock);
  72. status = desc->status;
  73. if (status & IRQ_AUTODETECT) {
  74. /* It triggered already - consider it spurious. */
  75. if (!(status & IRQ_WAITING)) {
  76. desc->status = status & ~IRQ_AUTODETECT;
  77. desc->handler->shutdown(i);
  78. } else
  79. if (i < 32)
  80. val |= 1 << i;
  81. }
  82. spin_unlock_irq(&desc->lock);
  83. }
  84. return val;
  85. }
  86. EXPORT_SYMBOL(probe_irq_on);
  87. /**
  88. * probe_irq_mask - scan a bitmap of interrupt lines
  89. * @val: mask of interrupts to consider
  90. *
  91. * Scan the interrupt lines and return a bitmap of active
  92. * autodetect interrupts. The interrupt probe logic state
  93. * is then returned to its previous value.
  94. *
  95. * Note: we need to scan all the irq's even though we will
  96. * only return autodetect irq numbers - just so that we reset
  97. * them all to a known state.
  98. */
  99. unsigned int probe_irq_mask(unsigned long val)
  100. {
  101. unsigned int mask;
  102. int i;
  103. mask = 0;
  104. for (i = 0; i < NR_IRQS; i++) {
  105. irq_desc_t *desc = irq_desc + i;
  106. unsigned int status;
  107. spin_lock_irq(&desc->lock);
  108. status = desc->status;
  109. if (status & IRQ_AUTODETECT) {
  110. if (i < 16 && !(status & IRQ_WAITING))
  111. mask |= 1 << i;
  112. desc->status = status & ~IRQ_AUTODETECT;
  113. desc->handler->shutdown(i);
  114. }
  115. spin_unlock_irq(&desc->lock);
  116. }
  117. up(&probe_sem);
  118. return mask & val;
  119. }
  120. EXPORT_SYMBOL(probe_irq_mask);
  121. /**
  122. * probe_irq_off - end an interrupt autodetect
  123. * @val: mask of potential interrupts (unused)
  124. *
  125. * Scans the unused interrupt lines and returns the line which
  126. * appears to have triggered the interrupt. If no interrupt was
  127. * found then zero is returned. If more than one interrupt is
  128. * found then minus the first candidate is returned to indicate
  129. * their is doubt.
  130. *
  131. * The interrupt probe logic state is returned to its previous
  132. * value.
  133. *
  134. * BUGS: When used in a module (which arguably shouldn't happen)
  135. * nothing prevents two IRQ probe callers from overlapping. The
  136. * results of this are non-optimal.
  137. */
  138. int probe_irq_off(unsigned long val)
  139. {
  140. int i, irq_found = 0, nr_irqs = 0;
  141. for (i = 0; i < NR_IRQS; i++) {
  142. irq_desc_t *desc = irq_desc + i;
  143. unsigned int status;
  144. spin_lock_irq(&desc->lock);
  145. status = desc->status;
  146. if (status & IRQ_AUTODETECT) {
  147. if (!(status & IRQ_WAITING)) {
  148. if (!nr_irqs)
  149. irq_found = i;
  150. nr_irqs++;
  151. }
  152. desc->status = status & ~IRQ_AUTODETECT;
  153. desc->handler->shutdown(i);
  154. }
  155. spin_unlock_irq(&desc->lock);
  156. }
  157. up(&probe_sem);
  158. if (nr_irqs > 1)
  159. irq_found = -irq_found;
  160. return irq_found;
  161. }
  162. EXPORT_SYMBOL(probe_irq_off);