1
2
3
4
5
6
7
8
9#include <linux/irq.h>
10#include <linux/module.h>
11#include <linux/interrupt.h>
12#include <linux/delay.h>
13
14#include "internals.h"
15
16
17
18
19
20
21static DEFINE_MUTEX(probing_active);
22
23
24
25
26
27
28
29
30unsigned long probe_irq_on(void)
31{
32 struct irq_desc *desc;
33 unsigned long mask = 0;
34 unsigned int status;
35 int i;
36
37 mutex_lock(&probing_active);
38
39
40
41
42 for_each_irq_desc_reverse(i, desc) {
43 spin_lock_irq(&desc->lock);
44 if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
45
46
47
48
49 compat_irq_chip_set_default_handler(desc);
50
51
52
53
54
55 if (desc->chip->set_type)
56 desc->chip->set_type(i, IRQ_TYPE_PROBE);
57 desc->chip->startup(i);
58 }
59 spin_unlock_irq(&desc->lock);
60 }
61
62
63 msleep(20);
64
65
66
67
68
69
70 for_each_irq_desc_reverse(i, desc) {
71 spin_lock_irq(&desc->lock);
72 if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
73 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
74 if (desc->chip->startup(i))
75 desc->status |= IRQ_PENDING;
76 }
77 spin_unlock_irq(&desc->lock);
78 }
79
80
81
82
83 msleep(100);
84
85
86
87
88 for_each_irq_desc(i, desc) {
89 spin_lock_irq(&desc->lock);
90 status = desc->status;
91
92 if (status & IRQ_AUTODETECT) {
93
94 if (!(status & IRQ_WAITING)) {
95 desc->status = status & ~IRQ_AUTODETECT;
96 desc->chip->shutdown(i);
97 } else
98 if (i < 32)
99 mask |= 1 << i;
100 }
101 spin_unlock_irq(&desc->lock);
102 }
103
104 return mask;
105}
106EXPORT_SYMBOL(probe_irq_on);
107
108
109
110
111
112
113
114
115
116
117
118
119
120unsigned int probe_irq_mask(unsigned long val)
121{
122 unsigned int status, mask = 0;
123 struct irq_desc *desc;
124 int i;
125
126 for_each_irq_desc(i, desc) {
127 spin_lock_irq(&desc->lock);
128 status = desc->status;
129
130 if (status & IRQ_AUTODETECT) {
131 if (i < 16 && !(status & IRQ_WAITING))
132 mask |= 1 << i;
133
134 desc->status = status & ~IRQ_AUTODETECT;
135 desc->chip->shutdown(i);
136 }
137 spin_unlock_irq(&desc->lock);
138 }
139 mutex_unlock(&probing_active);
140
141 return mask & val;
142}
143EXPORT_SYMBOL(probe_irq_mask);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162int probe_irq_off(unsigned long val)
163{
164 int i, irq_found = 0, nr_of_irqs = 0;
165 struct irq_desc *desc;
166 unsigned int status;
167
168 for_each_irq_desc(i, desc) {
169 spin_lock_irq(&desc->lock);
170 status = desc->status;
171
172 if (status & IRQ_AUTODETECT) {
173 if (!(status & IRQ_WAITING)) {
174 if (!nr_of_irqs)
175 irq_found = i;
176 nr_of_irqs++;
177 }
178 desc->status = status & ~IRQ_AUTODETECT;
179 desc->chip->shutdown(i);
180 }
181 spin_unlock_irq(&desc->lock);
182 }
183 mutex_unlock(&probing_active);
184
185 if (nr_of_irqs > 1)
186 irq_found = -irq_found;
187
188 return irq_found;
189}
190EXPORT_SYMBOL(probe_irq_off);
191