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