diff options
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r-- | kernel/irq/chip.c | 699 |
1 files changed, 300 insertions, 399 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index baa5c4acad83..d5a3009da71a 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -19,140 +19,115 @@ | |||
19 | #include "internals.h" | 19 | #include "internals.h" |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * set_irq_chip - set the irq chip for an irq | 22 | * irq_set_chip - set the irq chip for an irq |
23 | * @irq: irq number | 23 | * @irq: irq number |
24 | * @chip: pointer to irq chip description structure | 24 | * @chip: pointer to irq chip description structure |
25 | */ | 25 | */ |
26 | int set_irq_chip(unsigned int irq, struct irq_chip *chip) | 26 | int irq_set_chip(unsigned int irq, struct irq_chip *chip) |
27 | { | 27 | { |
28 | struct irq_desc *desc = irq_to_desc(irq); | ||
29 | unsigned long flags; | 28 | unsigned long flags; |
29 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
30 | 30 | ||
31 | if (!desc) { | 31 | if (!desc) |
32 | WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq); | ||
33 | return -EINVAL; | 32 | return -EINVAL; |
34 | } | ||
35 | 33 | ||
36 | if (!chip) | 34 | if (!chip) |
37 | chip = &no_irq_chip; | 35 | chip = &no_irq_chip; |
38 | 36 | ||
39 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
40 | irq_chip_set_defaults(chip); | ||
41 | desc->irq_data.chip = chip; | 37 | desc->irq_data.chip = chip; |
42 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 38 | irq_put_desc_unlock(desc, flags); |
43 | 39 | /* | |
40 | * For !CONFIG_SPARSE_IRQ make the irq show up in | ||
41 | * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is | ||
42 | * already marked, and this call is harmless. | ||
43 | */ | ||
44 | irq_reserve_irq(irq); | ||
44 | return 0; | 45 | return 0; |
45 | } | 46 | } |
46 | EXPORT_SYMBOL(set_irq_chip); | 47 | EXPORT_SYMBOL(irq_set_chip); |
47 | 48 | ||
48 | /** | 49 | /** |
49 | * set_irq_type - set the irq trigger type for an irq | 50 | * irq_set_type - set the irq trigger type for an irq |
50 | * @irq: irq number | 51 | * @irq: irq number |
51 | * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h | 52 | * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h |
52 | */ | 53 | */ |
53 | int set_irq_type(unsigned int irq, unsigned int type) | 54 | int irq_set_irq_type(unsigned int irq, unsigned int type) |
54 | { | 55 | { |
55 | struct irq_desc *desc = irq_to_desc(irq); | ||
56 | unsigned long flags; | 56 | unsigned long flags; |
57 | int ret = -ENXIO; | 57 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); |
58 | int ret = 0; | ||
58 | 59 | ||
59 | if (!desc) { | 60 | if (!desc) |
60 | printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); | 61 | return -EINVAL; |
61 | return -ENODEV; | ||
62 | } | ||
63 | 62 | ||
64 | type &= IRQ_TYPE_SENSE_MASK; | 63 | type &= IRQ_TYPE_SENSE_MASK; |
65 | if (type == IRQ_TYPE_NONE) | 64 | if (type != IRQ_TYPE_NONE) |
66 | return 0; | 65 | ret = __irq_set_trigger(desc, irq, type); |
67 | 66 | irq_put_desc_busunlock(desc, flags); | |
68 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
69 | ret = __irq_set_trigger(desc, irq, type); | ||
70 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
71 | return ret; | 67 | return ret; |
72 | } | 68 | } |
73 | EXPORT_SYMBOL(set_irq_type); | 69 | EXPORT_SYMBOL(irq_set_irq_type); |
74 | 70 | ||
75 | /** | 71 | /** |
76 | * set_irq_data - set irq type data for an irq | 72 | * irq_set_handler_data - set irq handler data for an irq |
77 | * @irq: Interrupt number | 73 | * @irq: Interrupt number |
78 | * @data: Pointer to interrupt specific data | 74 | * @data: Pointer to interrupt specific data |
79 | * | 75 | * |
80 | * Set the hardware irq controller data for an irq | 76 | * Set the hardware irq controller data for an irq |
81 | */ | 77 | */ |
82 | int set_irq_data(unsigned int irq, void *data) | 78 | int irq_set_handler_data(unsigned int irq, void *data) |
83 | { | 79 | { |
84 | struct irq_desc *desc = irq_to_desc(irq); | ||
85 | unsigned long flags; | 80 | unsigned long flags; |
81 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
86 | 82 | ||
87 | if (!desc) { | 83 | if (!desc) |
88 | printk(KERN_ERR | ||
89 | "Trying to install controller data for IRQ%d\n", irq); | ||
90 | return -EINVAL; | 84 | return -EINVAL; |
91 | } | ||
92 | |||
93 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
94 | desc->irq_data.handler_data = data; | 85 | desc->irq_data.handler_data = data; |
95 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 86 | irq_put_desc_unlock(desc, flags); |
96 | return 0; | 87 | return 0; |
97 | } | 88 | } |
98 | EXPORT_SYMBOL(set_irq_data); | 89 | EXPORT_SYMBOL(irq_set_handler_data); |
99 | 90 | ||
100 | /** | 91 | /** |
101 | * set_irq_msi - set MSI descriptor data for an irq | 92 | * irq_set_msi_desc - set MSI descriptor data for an irq |
102 | * @irq: Interrupt number | 93 | * @irq: Interrupt number |
103 | * @entry: Pointer to MSI descriptor data | 94 | * @entry: Pointer to MSI descriptor data |
104 | * | 95 | * |
105 | * Set the MSI descriptor entry for an irq | 96 | * Set the MSI descriptor entry for an irq |
106 | */ | 97 | */ |
107 | int set_irq_msi(unsigned int irq, struct msi_desc *entry) | 98 | int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) |
108 | { | 99 | { |
109 | struct irq_desc *desc = irq_to_desc(irq); | ||
110 | unsigned long flags; | 100 | unsigned long flags; |
101 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
111 | 102 | ||
112 | if (!desc) { | 103 | if (!desc) |
113 | printk(KERN_ERR | ||
114 | "Trying to install msi data for IRQ%d\n", irq); | ||
115 | return -EINVAL; | 104 | return -EINVAL; |
116 | } | ||
117 | |||
118 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
119 | desc->irq_data.msi_desc = entry; | 105 | desc->irq_data.msi_desc = entry; |
120 | if (entry) | 106 | if (entry) |
121 | entry->irq = irq; | 107 | entry->irq = irq; |
122 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 108 | irq_put_desc_unlock(desc, flags); |
123 | return 0; | 109 | return 0; |
124 | } | 110 | } |
125 | 111 | ||
126 | /** | 112 | /** |
127 | * set_irq_chip_data - set irq chip data for an irq | 113 | * irq_set_chip_data - set irq chip data for an irq |
128 | * @irq: Interrupt number | 114 | * @irq: Interrupt number |
129 | * @data: Pointer to chip specific data | 115 | * @data: Pointer to chip specific data |
130 | * | 116 | * |
131 | * Set the hardware irq chip data for an irq | 117 | * Set the hardware irq chip data for an irq |
132 | */ | 118 | */ |
133 | int set_irq_chip_data(unsigned int irq, void *data) | 119 | int irq_set_chip_data(unsigned int irq, void *data) |
134 | { | 120 | { |
135 | struct irq_desc *desc = irq_to_desc(irq); | ||
136 | unsigned long flags; | 121 | unsigned long flags; |
122 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
137 | 123 | ||
138 | if (!desc) { | 124 | if (!desc) |
139 | printk(KERN_ERR | ||
140 | "Trying to install chip data for IRQ%d\n", irq); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | if (!desc->irq_data.chip) { | ||
145 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); | ||
146 | return -EINVAL; | 125 | return -EINVAL; |
147 | } | ||
148 | |||
149 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
150 | desc->irq_data.chip_data = data; | 126 | desc->irq_data.chip_data = data; |
151 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 127 | irq_put_desc_unlock(desc, flags); |
152 | |||
153 | return 0; | 128 | return 0; |
154 | } | 129 | } |
155 | EXPORT_SYMBOL(set_irq_chip_data); | 130 | EXPORT_SYMBOL(irq_set_chip_data); |
156 | 131 | ||
157 | struct irq_data *irq_get_irq_data(unsigned int irq) | 132 | struct irq_data *irq_get_irq_data(unsigned int irq) |
158 | { | 133 | { |
@@ -162,221 +137,71 @@ struct irq_data *irq_get_irq_data(unsigned int irq) | |||
162 | } | 137 | } |
163 | EXPORT_SYMBOL_GPL(irq_get_irq_data); | 138 | EXPORT_SYMBOL_GPL(irq_get_irq_data); |
164 | 139 | ||
165 | /** | 140 | static void irq_state_clr_disabled(struct irq_desc *desc) |
166 | * set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq | ||
167 | * | ||
168 | * @irq: Interrupt number | ||
169 | * @nest: 0 to clear / 1 to set the IRQ_NESTED_THREAD flag | ||
170 | * | ||
171 | * The IRQ_NESTED_THREAD flag indicates that on | ||
172 | * request_threaded_irq() no separate interrupt thread should be | ||
173 | * created for the irq as the handler are called nested in the | ||
174 | * context of a demultiplexing interrupt handler thread. | ||
175 | */ | ||
176 | void set_irq_nested_thread(unsigned int irq, int nest) | ||
177 | { | ||
178 | struct irq_desc *desc = irq_to_desc(irq); | ||
179 | unsigned long flags; | ||
180 | |||
181 | if (!desc) | ||
182 | return; | ||
183 | |||
184 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
185 | if (nest) | ||
186 | desc->status |= IRQ_NESTED_THREAD; | ||
187 | else | ||
188 | desc->status &= ~IRQ_NESTED_THREAD; | ||
189 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(set_irq_nested_thread); | ||
192 | |||
193 | /* | ||
194 | * default enable function | ||
195 | */ | ||
196 | static void default_enable(struct irq_data *data) | ||
197 | { | 141 | { |
198 | struct irq_desc *desc = irq_data_to_desc(data); | 142 | irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED); |
199 | |||
200 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
201 | desc->status &= ~IRQ_MASKED; | ||
202 | } | 143 | } |
203 | 144 | ||
204 | /* | 145 | static void irq_state_set_disabled(struct irq_desc *desc) |
205 | * default disable function | ||
206 | */ | ||
207 | static void default_disable(struct irq_data *data) | ||
208 | { | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * default startup function | ||
213 | */ | ||
214 | static unsigned int default_startup(struct irq_data *data) | ||
215 | { | 146 | { |
216 | struct irq_desc *desc = irq_data_to_desc(data); | 147 | irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); |
217 | |||
218 | desc->irq_data.chip->irq_enable(data); | ||
219 | return 0; | ||
220 | } | 148 | } |
221 | 149 | ||
222 | /* | 150 | static void irq_state_clr_masked(struct irq_desc *desc) |
223 | * default shutdown function | ||
224 | */ | ||
225 | static void default_shutdown(struct irq_data *data) | ||
226 | { | 151 | { |
227 | struct irq_desc *desc = irq_data_to_desc(data); | 152 | irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED); |
228 | |||
229 | desc->irq_data.chip->irq_mask(&desc->irq_data); | ||
230 | desc->status |= IRQ_MASKED; | ||
231 | } | 153 | } |
232 | 154 | ||
233 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | 155 | static void irq_state_set_masked(struct irq_desc *desc) |
234 | /* Temporary migration helpers */ | ||
235 | static void compat_irq_mask(struct irq_data *data) | ||
236 | { | 156 | { |
237 | data->chip->mask(data->irq); | 157 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); |
238 | } | 158 | } |
239 | 159 | ||
240 | static void compat_irq_unmask(struct irq_data *data) | 160 | int irq_startup(struct irq_desc *desc) |
241 | { | 161 | { |
242 | data->chip->unmask(data->irq); | 162 | irq_state_clr_disabled(desc); |
243 | } | 163 | desc->depth = 0; |
244 | 164 | ||
245 | static void compat_irq_ack(struct irq_data *data) | 165 | if (desc->irq_data.chip->irq_startup) { |
246 | { | 166 | int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); |
247 | data->chip->ack(data->irq); | 167 | irq_state_clr_masked(desc); |
248 | } | 168 | return ret; |
249 | 169 | } | |
250 | static void compat_irq_mask_ack(struct irq_data *data) | ||
251 | { | ||
252 | data->chip->mask_ack(data->irq); | ||
253 | } | ||
254 | |||
255 | static void compat_irq_eoi(struct irq_data *data) | ||
256 | { | ||
257 | data->chip->eoi(data->irq); | ||
258 | } | ||
259 | |||
260 | static void compat_irq_enable(struct irq_data *data) | ||
261 | { | ||
262 | data->chip->enable(data->irq); | ||
263 | } | ||
264 | |||
265 | static void compat_irq_disable(struct irq_data *data) | ||
266 | { | ||
267 | data->chip->disable(data->irq); | ||
268 | } | ||
269 | |||
270 | static void compat_irq_shutdown(struct irq_data *data) | ||
271 | { | ||
272 | data->chip->shutdown(data->irq); | ||
273 | } | ||
274 | |||
275 | static unsigned int compat_irq_startup(struct irq_data *data) | ||
276 | { | ||
277 | return data->chip->startup(data->irq); | ||
278 | } | ||
279 | |||
280 | static int compat_irq_set_affinity(struct irq_data *data, | ||
281 | const struct cpumask *dest, bool force) | ||
282 | { | ||
283 | return data->chip->set_affinity(data->irq, dest); | ||
284 | } | ||
285 | |||
286 | static int compat_irq_set_type(struct irq_data *data, unsigned int type) | ||
287 | { | ||
288 | return data->chip->set_type(data->irq, type); | ||
289 | } | ||
290 | |||
291 | static int compat_irq_set_wake(struct irq_data *data, unsigned int on) | ||
292 | { | ||
293 | return data->chip->set_wake(data->irq, on); | ||
294 | } | ||
295 | 170 | ||
296 | static int compat_irq_retrigger(struct irq_data *data) | 171 | irq_enable(desc); |
297 | { | 172 | return 0; |
298 | return data->chip->retrigger(data->irq); | ||
299 | } | 173 | } |
300 | 174 | ||
301 | static void compat_bus_lock(struct irq_data *data) | 175 | void irq_shutdown(struct irq_desc *desc) |
302 | { | 176 | { |
303 | data->chip->bus_lock(data->irq); | 177 | irq_state_set_disabled(desc); |
178 | desc->depth = 1; | ||
179 | if (desc->irq_data.chip->irq_shutdown) | ||
180 | desc->irq_data.chip->irq_shutdown(&desc->irq_data); | ||
181 | if (desc->irq_data.chip->irq_disable) | ||
182 | desc->irq_data.chip->irq_disable(&desc->irq_data); | ||
183 | else | ||
184 | desc->irq_data.chip->irq_mask(&desc->irq_data); | ||
185 | irq_state_set_masked(desc); | ||
304 | } | 186 | } |
305 | 187 | ||
306 | static void compat_bus_sync_unlock(struct irq_data *data) | 188 | void irq_enable(struct irq_desc *desc) |
307 | { | 189 | { |
308 | data->chip->bus_sync_unlock(data->irq); | 190 | irq_state_clr_disabled(desc); |
191 | if (desc->irq_data.chip->irq_enable) | ||
192 | desc->irq_data.chip->irq_enable(&desc->irq_data); | ||
193 | else | ||
194 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
195 | irq_state_clr_masked(desc); | ||
309 | } | 196 | } |
310 | #endif | ||
311 | 197 | ||
312 | /* | 198 | void irq_disable(struct irq_desc *desc) |
313 | * Fixup enable/disable function pointers | ||
314 | */ | ||
315 | void irq_chip_set_defaults(struct irq_chip *chip) | ||
316 | { | 199 | { |
317 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | 200 | irq_state_set_disabled(desc); |
318 | /* | 201 | if (desc->irq_data.chip->irq_disable) { |
319 | * Compat fixup functions need to be before we set the | 202 | desc->irq_data.chip->irq_disable(&desc->irq_data); |
320 | * defaults for enable/disable/startup/shutdown | 203 | irq_state_set_masked(desc); |
321 | */ | 204 | } |
322 | if (chip->enable) | ||
323 | chip->irq_enable = compat_irq_enable; | ||
324 | if (chip->disable) | ||
325 | chip->irq_disable = compat_irq_disable; | ||
326 | if (chip->shutdown) | ||
327 | chip->irq_shutdown = compat_irq_shutdown; | ||
328 | if (chip->startup) | ||
329 | chip->irq_startup = compat_irq_startup; | ||
330 | #endif | ||
331 | /* | ||
332 | * The real defaults | ||
333 | */ | ||
334 | if (!chip->irq_enable) | ||
335 | chip->irq_enable = default_enable; | ||
336 | if (!chip->irq_disable) | ||
337 | chip->irq_disable = default_disable; | ||
338 | if (!chip->irq_startup) | ||
339 | chip->irq_startup = default_startup; | ||
340 | /* | ||
341 | * We use chip->irq_disable, when the user provided its own. When | ||
342 | * we have default_disable set for chip->irq_disable, then we need | ||
343 | * to use default_shutdown, otherwise the irq line is not | ||
344 | * disabled on free_irq(): | ||
345 | */ | ||
346 | if (!chip->irq_shutdown) | ||
347 | chip->irq_shutdown = chip->irq_disable != default_disable ? | ||
348 | chip->irq_disable : default_shutdown; | ||
349 | |||
350 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | ||
351 | if (!chip->end) | ||
352 | chip->end = dummy_irq_chip.end; | ||
353 | |||
354 | /* | ||
355 | * Now fix up the remaining compat handlers | ||
356 | */ | ||
357 | if (chip->bus_lock) | ||
358 | chip->irq_bus_lock = compat_bus_lock; | ||
359 | if (chip->bus_sync_unlock) | ||
360 | chip->irq_bus_sync_unlock = compat_bus_sync_unlock; | ||
361 | if (chip->mask) | ||
362 | chip->irq_mask = compat_irq_mask; | ||
363 | if (chip->unmask) | ||
364 | chip->irq_unmask = compat_irq_unmask; | ||
365 | if (chip->ack) | ||
366 | chip->irq_ack = compat_irq_ack; | ||
367 | if (chip->mask_ack) | ||
368 | chip->irq_mask_ack = compat_irq_mask_ack; | ||
369 | if (chip->eoi) | ||
370 | chip->irq_eoi = compat_irq_eoi; | ||
371 | if (chip->set_affinity) | ||
372 | chip->irq_set_affinity = compat_irq_set_affinity; | ||
373 | if (chip->set_type) | ||
374 | chip->irq_set_type = compat_irq_set_type; | ||
375 | if (chip->set_wake) | ||
376 | chip->irq_set_wake = compat_irq_set_wake; | ||
377 | if (chip->retrigger) | ||
378 | chip->irq_retrigger = compat_irq_retrigger; | ||
379 | #endif | ||
380 | } | 205 | } |
381 | 206 | ||
382 | static inline void mask_ack_irq(struct irq_desc *desc) | 207 | static inline void mask_ack_irq(struct irq_desc *desc) |
@@ -388,22 +213,22 @@ static inline void mask_ack_irq(struct irq_desc *desc) | |||
388 | if (desc->irq_data.chip->irq_ack) | 213 | if (desc->irq_data.chip->irq_ack) |
389 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 214 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
390 | } | 215 | } |
391 | desc->status |= IRQ_MASKED; | 216 | irq_state_set_masked(desc); |
392 | } | 217 | } |
393 | 218 | ||
394 | static inline void mask_irq(struct irq_desc *desc) | 219 | void mask_irq(struct irq_desc *desc) |
395 | { | 220 | { |
396 | if (desc->irq_data.chip->irq_mask) { | 221 | if (desc->irq_data.chip->irq_mask) { |
397 | desc->irq_data.chip->irq_mask(&desc->irq_data); | 222 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
398 | desc->status |= IRQ_MASKED; | 223 | irq_state_set_masked(desc); |
399 | } | 224 | } |
400 | } | 225 | } |
401 | 226 | ||
402 | static inline void unmask_irq(struct irq_desc *desc) | 227 | void unmask_irq(struct irq_desc *desc) |
403 | { | 228 | { |
404 | if (desc->irq_data.chip->irq_unmask) { | 229 | if (desc->irq_data.chip->irq_unmask) { |
405 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 230 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
406 | desc->status &= ~IRQ_MASKED; | 231 | irq_state_clr_masked(desc); |
407 | } | 232 | } |
408 | } | 233 | } |
409 | 234 | ||
@@ -428,10 +253,10 @@ void handle_nested_irq(unsigned int irq) | |||
428 | kstat_incr_irqs_this_cpu(irq, desc); | 253 | kstat_incr_irqs_this_cpu(irq, desc); |
429 | 254 | ||
430 | action = desc->action; | 255 | action = desc->action; |
431 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 256 | if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) |
432 | goto out_unlock; | 257 | goto out_unlock; |
433 | 258 | ||
434 | desc->status |= IRQ_INPROGRESS; | 259 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
435 | raw_spin_unlock_irq(&desc->lock); | 260 | raw_spin_unlock_irq(&desc->lock); |
436 | 261 | ||
437 | action_ret = action->thread_fn(action->irq, action->dev_id); | 262 | action_ret = action->thread_fn(action->irq, action->dev_id); |
@@ -439,13 +264,20 @@ void handle_nested_irq(unsigned int irq) | |||
439 | note_interrupt(irq, desc, action_ret); | 264 | note_interrupt(irq, desc, action_ret); |
440 | 265 | ||
441 | raw_spin_lock_irq(&desc->lock); | 266 | raw_spin_lock_irq(&desc->lock); |
442 | desc->status &= ~IRQ_INPROGRESS; | 267 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
443 | 268 | ||
444 | out_unlock: | 269 | out_unlock: |
445 | raw_spin_unlock_irq(&desc->lock); | 270 | raw_spin_unlock_irq(&desc->lock); |
446 | } | 271 | } |
447 | EXPORT_SYMBOL_GPL(handle_nested_irq); | 272 | EXPORT_SYMBOL_GPL(handle_nested_irq); |
448 | 273 | ||
274 | static bool irq_check_poll(struct irq_desc *desc) | ||
275 | { | ||
276 | if (!(desc->istate & IRQS_POLL_INPROGRESS)) | ||
277 | return false; | ||
278 | return irq_wait_for_poll(desc); | ||
279 | } | ||
280 | |||
449 | /** | 281 | /** |
450 | * handle_simple_irq - Simple and software-decoded IRQs. | 282 | * handle_simple_irq - Simple and software-decoded IRQs. |
451 | * @irq: the interrupt number | 283 | * @irq: the interrupt number |
@@ -461,32 +293,24 @@ EXPORT_SYMBOL_GPL(handle_nested_irq); | |||
461 | void | 293 | void |
462 | handle_simple_irq(unsigned int irq, struct irq_desc *desc) | 294 | handle_simple_irq(unsigned int irq, struct irq_desc *desc) |
463 | { | 295 | { |
464 | struct irqaction *action; | ||
465 | irqreturn_t action_ret; | ||
466 | |||
467 | raw_spin_lock(&desc->lock); | 296 | raw_spin_lock(&desc->lock); |
468 | 297 | ||
469 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 298 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
470 | goto out_unlock; | 299 | if (!irq_check_poll(desc)) |
471 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 300 | goto out_unlock; |
301 | |||
302 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
472 | kstat_incr_irqs_this_cpu(irq, desc); | 303 | kstat_incr_irqs_this_cpu(irq, desc); |
473 | 304 | ||
474 | action = desc->action; | 305 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
475 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
476 | goto out_unlock; | 306 | goto out_unlock; |
477 | 307 | ||
478 | desc->status |= IRQ_INPROGRESS; | 308 | handle_irq_event(desc); |
479 | raw_spin_unlock(&desc->lock); | ||
480 | 309 | ||
481 | action_ret = handle_IRQ_event(irq, action); | ||
482 | if (!noirqdebug) | ||
483 | note_interrupt(irq, desc, action_ret); | ||
484 | |||
485 | raw_spin_lock(&desc->lock); | ||
486 | desc->status &= ~IRQ_INPROGRESS; | ||
487 | out_unlock: | 310 | out_unlock: |
488 | raw_spin_unlock(&desc->lock); | 311 | raw_spin_unlock(&desc->lock); |
489 | } | 312 | } |
313 | EXPORT_SYMBOL_GPL(handle_simple_irq); | ||
490 | 314 | ||
491 | /** | 315 | /** |
492 | * handle_level_irq - Level type irq handler | 316 | * handle_level_irq - Level type irq handler |
@@ -501,42 +325,42 @@ out_unlock: | |||
501 | void | 325 | void |
502 | handle_level_irq(unsigned int irq, struct irq_desc *desc) | 326 | handle_level_irq(unsigned int irq, struct irq_desc *desc) |
503 | { | 327 | { |
504 | struct irqaction *action; | ||
505 | irqreturn_t action_ret; | ||
506 | |||
507 | raw_spin_lock(&desc->lock); | 328 | raw_spin_lock(&desc->lock); |
508 | mask_ack_irq(desc); | 329 | mask_ack_irq(desc); |
509 | 330 | ||
510 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 331 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
511 | goto out_unlock; | 332 | if (!irq_check_poll(desc)) |
512 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 333 | goto out_unlock; |
334 | |||
335 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
513 | kstat_incr_irqs_this_cpu(irq, desc); | 336 | kstat_incr_irqs_this_cpu(irq, desc); |
514 | 337 | ||
515 | /* | 338 | /* |
516 | * If its disabled or no action available | 339 | * If its disabled or no action available |
517 | * keep it masked and get out of here | 340 | * keep it masked and get out of here |
518 | */ | 341 | */ |
519 | action = desc->action; | 342 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
520 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
521 | goto out_unlock; | 343 | goto out_unlock; |
522 | 344 | ||
523 | desc->status |= IRQ_INPROGRESS; | 345 | handle_irq_event(desc); |
524 | raw_spin_unlock(&desc->lock); | ||
525 | |||
526 | action_ret = handle_IRQ_event(irq, action); | ||
527 | if (!noirqdebug) | ||
528 | note_interrupt(irq, desc, action_ret); | ||
529 | |||
530 | raw_spin_lock(&desc->lock); | ||
531 | desc->status &= ~IRQ_INPROGRESS; | ||
532 | 346 | ||
533 | if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT))) | 347 | if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) |
534 | unmask_irq(desc); | 348 | unmask_irq(desc); |
535 | out_unlock: | 349 | out_unlock: |
536 | raw_spin_unlock(&desc->lock); | 350 | raw_spin_unlock(&desc->lock); |
537 | } | 351 | } |
538 | EXPORT_SYMBOL_GPL(handle_level_irq); | 352 | EXPORT_SYMBOL_GPL(handle_level_irq); |
539 | 353 | ||
354 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
355 | static inline void preflow_handler(struct irq_desc *desc) | ||
356 | { | ||
357 | if (desc->preflow_handler) | ||
358 | desc->preflow_handler(&desc->irq_data); | ||
359 | } | ||
360 | #else | ||
361 | static inline void preflow_handler(struct irq_desc *desc) { } | ||
362 | #endif | ||
363 | |||
540 | /** | 364 | /** |
541 | * handle_fasteoi_irq - irq handler for transparent controllers | 365 | * handle_fasteoi_irq - irq handler for transparent controllers |
542 | * @irq: the interrupt number | 366 | * @irq: the interrupt number |
@@ -550,42 +374,40 @@ EXPORT_SYMBOL_GPL(handle_level_irq); | |||
550 | void | 374 | void |
551 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | 375 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) |
552 | { | 376 | { |
553 | struct irqaction *action; | ||
554 | irqreturn_t action_ret; | ||
555 | |||
556 | raw_spin_lock(&desc->lock); | 377 | raw_spin_lock(&desc->lock); |
557 | 378 | ||
558 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 379 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
559 | goto out; | 380 | if (!irq_check_poll(desc)) |
381 | goto out; | ||
560 | 382 | ||
561 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 383 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
562 | kstat_incr_irqs_this_cpu(irq, desc); | 384 | kstat_incr_irqs_this_cpu(irq, desc); |
563 | 385 | ||
564 | /* | 386 | /* |
565 | * If its disabled or no action available | 387 | * If its disabled or no action available |
566 | * then mask it and get out of here: | 388 | * then mask it and get out of here: |
567 | */ | 389 | */ |
568 | action = desc->action; | 390 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { |
569 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { | 391 | desc->istate |= IRQS_PENDING; |
570 | desc->status |= IRQ_PENDING; | ||
571 | mask_irq(desc); | 392 | mask_irq(desc); |
572 | goto out; | 393 | goto out; |
573 | } | 394 | } |
574 | 395 | ||
575 | desc->status |= IRQ_INPROGRESS; | 396 | if (desc->istate & IRQS_ONESHOT) |
576 | desc->status &= ~IRQ_PENDING; | 397 | mask_irq(desc); |
577 | raw_spin_unlock(&desc->lock); | ||
578 | 398 | ||
579 | action_ret = handle_IRQ_event(irq, action); | 399 | preflow_handler(desc); |
580 | if (!noirqdebug) | 400 | handle_irq_event(desc); |
581 | note_interrupt(irq, desc, action_ret); | ||
582 | 401 | ||
583 | raw_spin_lock(&desc->lock); | 402 | out_eoi: |
584 | desc->status &= ~IRQ_INPROGRESS; | ||
585 | out: | ||
586 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 403 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
587 | 404 | out_unlock: | |
588 | raw_spin_unlock(&desc->lock); | 405 | raw_spin_unlock(&desc->lock); |
406 | return; | ||
407 | out: | ||
408 | if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED)) | ||
409 | goto out_eoi; | ||
410 | goto out_unlock; | ||
589 | } | 411 | } |
590 | 412 | ||
591 | /** | 413 | /** |
@@ -594,7 +416,7 @@ out: | |||
594 | * @desc: the interrupt description structure for this irq | 416 | * @desc: the interrupt description structure for this irq |
595 | * | 417 | * |
596 | * Interrupt occures on the falling and/or rising edge of a hardware | 418 | * Interrupt occures on the falling and/or rising edge of a hardware |
597 | * signal. The occurence is latched into the irq controller hardware | 419 | * signal. The occurrence is latched into the irq controller hardware |
598 | * and must be acked in order to be reenabled. After the ack another | 420 | * and must be acked in order to be reenabled. After the ack another |
599 | * interrupt can happen on the same source even before the first one | 421 | * interrupt can happen on the same source even before the first one |
600 | * is handled by the associated event handler. If this happens it | 422 | * is handled by the associated event handler. If this happens it |
@@ -609,32 +431,27 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
609 | { | 431 | { |
610 | raw_spin_lock(&desc->lock); | 432 | raw_spin_lock(&desc->lock); |
611 | 433 | ||
612 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 434 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
613 | |||
614 | /* | 435 | /* |
615 | * If we're currently running this IRQ, or its disabled, | 436 | * If we're currently running this IRQ, or its disabled, |
616 | * we shouldn't process the IRQ. Mark it pending, handle | 437 | * we shouldn't process the IRQ. Mark it pending, handle |
617 | * the necessary masking and go out | 438 | * the necessary masking and go out |
618 | */ | 439 | */ |
619 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | 440 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || |
620 | !desc->action)) { | 441 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { |
621 | desc->status |= (IRQ_PENDING | IRQ_MASKED); | 442 | if (!irq_check_poll(desc)) { |
622 | mask_ack_irq(desc); | 443 | desc->istate |= IRQS_PENDING; |
623 | goto out_unlock; | 444 | mask_ack_irq(desc); |
445 | goto out_unlock; | ||
446 | } | ||
624 | } | 447 | } |
625 | kstat_incr_irqs_this_cpu(irq, desc); | 448 | kstat_incr_irqs_this_cpu(irq, desc); |
626 | 449 | ||
627 | /* Start handling the irq */ | 450 | /* Start handling the irq */ |
628 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 451 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
629 | 452 | ||
630 | /* Mark the IRQ currently in progress.*/ | ||
631 | desc->status |= IRQ_INPROGRESS; | ||
632 | |||
633 | do { | 453 | do { |
634 | struct irqaction *action = desc->action; | 454 | if (unlikely(!desc->action)) { |
635 | irqreturn_t action_ret; | ||
636 | |||
637 | if (unlikely(!action)) { | ||
638 | mask_irq(desc); | 455 | mask_irq(desc); |
639 | goto out_unlock; | 456 | goto out_unlock; |
640 | } | 457 | } |
@@ -644,26 +461,66 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
644 | * one, we could have masked the irq. | 461 | * one, we could have masked the irq. |
645 | * Renable it, if it was not disabled in meantime. | 462 | * Renable it, if it was not disabled in meantime. |
646 | */ | 463 | */ |
647 | if (unlikely((desc->status & | 464 | if (unlikely(desc->istate & IRQS_PENDING)) { |
648 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == | 465 | if (!irqd_irq_disabled(&desc->irq_data) && |
649 | (IRQ_PENDING | IRQ_MASKED))) { | 466 | irqd_irq_masked(&desc->irq_data)) |
650 | unmask_irq(desc); | 467 | unmask_irq(desc); |
651 | } | 468 | } |
652 | 469 | ||
653 | desc->status &= ~IRQ_PENDING; | 470 | handle_irq_event(desc); |
654 | raw_spin_unlock(&desc->lock); | ||
655 | action_ret = handle_IRQ_event(irq, action); | ||
656 | if (!noirqdebug) | ||
657 | note_interrupt(irq, desc, action_ret); | ||
658 | raw_spin_lock(&desc->lock); | ||
659 | 471 | ||
660 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | 472 | } while ((desc->istate & IRQS_PENDING) && |
473 | !irqd_irq_disabled(&desc->irq_data)); | ||
661 | 474 | ||
662 | desc->status &= ~IRQ_INPROGRESS; | ||
663 | out_unlock: | 475 | out_unlock: |
664 | raw_spin_unlock(&desc->lock); | 476 | raw_spin_unlock(&desc->lock); |
665 | } | 477 | } |
666 | 478 | ||
479 | #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER | ||
480 | /** | ||
481 | * handle_edge_eoi_irq - edge eoi type IRQ handler | ||
482 | * @irq: the interrupt number | ||
483 | * @desc: the interrupt description structure for this irq | ||
484 | * | ||
485 | * Similar as the above handle_edge_irq, but using eoi and w/o the | ||
486 | * mask/unmask logic. | ||
487 | */ | ||
488 | void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc) | ||
489 | { | ||
490 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
491 | |||
492 | raw_spin_lock(&desc->lock); | ||
493 | |||
494 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
495 | /* | ||
496 | * If we're currently running this IRQ, or its disabled, | ||
497 | * we shouldn't process the IRQ. Mark it pending, handle | ||
498 | * the necessary masking and go out | ||
499 | */ | ||
500 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || | ||
501 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { | ||
502 | if (!irq_check_poll(desc)) { | ||
503 | desc->istate |= IRQS_PENDING; | ||
504 | goto out_eoi; | ||
505 | } | ||
506 | } | ||
507 | kstat_incr_irqs_this_cpu(irq, desc); | ||
508 | |||
509 | do { | ||
510 | if (unlikely(!desc->action)) | ||
511 | goto out_eoi; | ||
512 | |||
513 | handle_irq_event(desc); | ||
514 | |||
515 | } while ((desc->istate & IRQS_PENDING) && | ||
516 | !irqd_irq_disabled(&desc->irq_data)); | ||
517 | |||
518 | out_eoi: | ||
519 | chip->irq_eoi(&desc->irq_data); | ||
520 | raw_spin_unlock(&desc->lock); | ||
521 | } | ||
522 | #endif | ||
523 | |||
667 | /** | 524 | /** |
668 | * handle_percpu_irq - Per CPU local irq handler | 525 | * handle_percpu_irq - Per CPU local irq handler |
669 | * @irq: the interrupt number | 526 | * @irq: the interrupt number |
@@ -674,103 +531,147 @@ out_unlock: | |||
674 | void | 531 | void |
675 | handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | 532 | handle_percpu_irq(unsigned int irq, struct irq_desc *desc) |
676 | { | 533 | { |
677 | irqreturn_t action_ret; | 534 | struct irq_chip *chip = irq_desc_get_chip(desc); |
678 | 535 | ||
679 | kstat_incr_irqs_this_cpu(irq, desc); | 536 | kstat_incr_irqs_this_cpu(irq, desc); |
680 | 537 | ||
681 | if (desc->irq_data.chip->irq_ack) | 538 | if (chip->irq_ack) |
682 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 539 | chip->irq_ack(&desc->irq_data); |
683 | 540 | ||
684 | action_ret = handle_IRQ_event(irq, desc->action); | 541 | handle_irq_event_percpu(desc, desc->action); |
685 | if (!noirqdebug) | ||
686 | note_interrupt(irq, desc, action_ret); | ||
687 | 542 | ||
688 | if (desc->irq_data.chip->irq_eoi) | 543 | if (chip->irq_eoi) |
689 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 544 | chip->irq_eoi(&desc->irq_data); |
690 | } | 545 | } |
691 | 546 | ||
692 | void | 547 | void |
693 | __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | 548 | __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, |
694 | const char *name) | 549 | const char *name) |
695 | { | 550 | { |
696 | struct irq_desc *desc = irq_to_desc(irq); | ||
697 | unsigned long flags; | 551 | unsigned long flags; |
552 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); | ||
698 | 553 | ||
699 | if (!desc) { | 554 | if (!desc) |
700 | printk(KERN_ERR | ||
701 | "Trying to install type control for IRQ%d\n", irq); | ||
702 | return; | 555 | return; |
703 | } | ||
704 | 556 | ||
705 | if (!handle) | 557 | if (!handle) { |
706 | handle = handle_bad_irq; | 558 | handle = handle_bad_irq; |
707 | else if (desc->irq_data.chip == &no_irq_chip) { | 559 | } else { |
708 | printk(KERN_WARNING "Trying to install %sinterrupt handler " | 560 | if (WARN_ON(desc->irq_data.chip == &no_irq_chip)) |
709 | "for IRQ%d\n", is_chained ? "chained " : "", irq); | 561 | goto out; |
710 | /* | ||
711 | * Some ARM implementations install a handler for really dumb | ||
712 | * interrupt hardware without setting an irq_chip. This worked | ||
713 | * with the ARM no_irq_chip but the check in setup_irq would | ||
714 | * prevent us to setup the interrupt at all. Switch it to | ||
715 | * dummy_irq_chip for easy transition. | ||
716 | */ | ||
717 | desc->irq_data.chip = &dummy_irq_chip; | ||
718 | } | 562 | } |
719 | 563 | ||
720 | chip_bus_lock(desc); | ||
721 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
722 | |||
723 | /* Uninstall? */ | 564 | /* Uninstall? */ |
724 | if (handle == handle_bad_irq) { | 565 | if (handle == handle_bad_irq) { |
725 | if (desc->irq_data.chip != &no_irq_chip) | 566 | if (desc->irq_data.chip != &no_irq_chip) |
726 | mask_ack_irq(desc); | 567 | mask_ack_irq(desc); |
727 | desc->status |= IRQ_DISABLED; | 568 | irq_state_set_disabled(desc); |
728 | desc->depth = 1; | 569 | desc->depth = 1; |
729 | } | 570 | } |
730 | desc->handle_irq = handle; | 571 | desc->handle_irq = handle; |
731 | desc->name = name; | 572 | desc->name = name; |
732 | 573 | ||
733 | if (handle != handle_bad_irq && is_chained) { | 574 | if (handle != handle_bad_irq && is_chained) { |
734 | desc->status &= ~IRQ_DISABLED; | 575 | irq_settings_set_noprobe(desc); |
735 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; | 576 | irq_settings_set_norequest(desc); |
736 | desc->depth = 0; | 577 | irq_settings_set_nothread(desc); |
737 | desc->irq_data.chip->irq_startup(&desc->irq_data); | 578 | irq_startup(desc); |
738 | } | 579 | } |
739 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 580 | out: |
740 | chip_bus_sync_unlock(desc); | 581 | irq_put_desc_busunlock(desc, flags); |
741 | } | ||
742 | EXPORT_SYMBOL_GPL(__set_irq_handler); | ||
743 | |||
744 | void | ||
745 | set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, | ||
746 | irq_flow_handler_t handle) | ||
747 | { | ||
748 | set_irq_chip(irq, chip); | ||
749 | __set_irq_handler(irq, handle, 0, NULL); | ||
750 | } | 582 | } |
583 | EXPORT_SYMBOL_GPL(__irq_set_handler); | ||
751 | 584 | ||
752 | void | 585 | void |
753 | set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | 586 | irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, |
754 | irq_flow_handler_t handle, const char *name) | 587 | irq_flow_handler_t handle, const char *name) |
755 | { | 588 | { |
756 | set_irq_chip(irq, chip); | 589 | irq_set_chip(irq, chip); |
757 | __set_irq_handler(irq, handle, 0, name); | 590 | __irq_set_handler(irq, handle, 0, name); |
758 | } | 591 | } |
759 | 592 | ||
760 | void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | 593 | void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) |
761 | { | 594 | { |
762 | struct irq_desc *desc = irq_to_desc(irq); | ||
763 | unsigned long flags; | 595 | unsigned long flags; |
596 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
764 | 597 | ||
765 | if (!desc) | 598 | if (!desc) |
766 | return; | 599 | return; |
600 | irq_settings_clr_and_set(desc, clr, set); | ||
601 | |||
602 | irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU | | ||
603 | IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT); | ||
604 | if (irq_settings_has_no_balance_set(desc)) | ||
605 | irqd_set(&desc->irq_data, IRQD_NO_BALANCING); | ||
606 | if (irq_settings_is_per_cpu(desc)) | ||
607 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | ||
608 | if (irq_settings_can_move_pcntxt(desc)) | ||
609 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); | ||
610 | if (irq_settings_is_level(desc)) | ||
611 | irqd_set(&desc->irq_data, IRQD_LEVEL); | ||
612 | |||
613 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); | ||
614 | |||
615 | irq_put_desc_unlock(desc, flags); | ||
616 | } | ||
617 | EXPORT_SYMBOL_GPL(irq_modify_status); | ||
618 | |||
619 | /** | ||
620 | * irq_cpu_online - Invoke all irq_cpu_online functions. | ||
621 | * | ||
622 | * Iterate through all irqs and invoke the chip.irq_cpu_online() | ||
623 | * for each. | ||
624 | */ | ||
625 | void irq_cpu_online(void) | ||
626 | { | ||
627 | struct irq_desc *desc; | ||
628 | struct irq_chip *chip; | ||
629 | unsigned long flags; | ||
630 | unsigned int irq; | ||
631 | |||
632 | for_each_active_irq(irq) { | ||
633 | desc = irq_to_desc(irq); | ||
634 | if (!desc) | ||
635 | continue; | ||
767 | 636 | ||
768 | /* Sanitize flags */ | 637 | raw_spin_lock_irqsave(&desc->lock, flags); |
769 | set &= IRQF_MODIFY_MASK; | ||
770 | clr &= IRQF_MODIFY_MASK; | ||
771 | 638 | ||
772 | raw_spin_lock_irqsave(&desc->lock, flags); | 639 | chip = irq_data_get_irq_chip(&desc->irq_data); |
773 | desc->status &= ~clr; | 640 | if (chip && chip->irq_cpu_online && |
774 | desc->status |= set; | 641 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || |
775 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 642 | !irqd_irq_disabled(&desc->irq_data))) |
643 | chip->irq_cpu_online(&desc->irq_data); | ||
644 | |||
645 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /** | ||
650 | * irq_cpu_offline - Invoke all irq_cpu_offline functions. | ||
651 | * | ||
652 | * Iterate through all irqs and invoke the chip.irq_cpu_offline() | ||
653 | * for each. | ||
654 | */ | ||
655 | void irq_cpu_offline(void) | ||
656 | { | ||
657 | struct irq_desc *desc; | ||
658 | struct irq_chip *chip; | ||
659 | unsigned long flags; | ||
660 | unsigned int irq; | ||
661 | |||
662 | for_each_active_irq(irq) { | ||
663 | desc = irq_to_desc(irq); | ||
664 | if (!desc) | ||
665 | continue; | ||
666 | |||
667 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
668 | |||
669 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
670 | if (chip && chip->irq_cpu_offline && | ||
671 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || | ||
672 | !irqd_irq_disabled(&desc->irq_data))) | ||
673 | chip->irq_cpu_offline(&desc->irq_data); | ||
674 | |||
675 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
676 | } | ||
776 | } | 677 | } |