autoprobe.c 4.3 KB

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