xref: /openbmc/linux/kernel/irq/autoprobe.c (revision 1da177e4)
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