diff options
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r-- | kernel/irq/chip.c | 483 |
1 files changed, 199 insertions, 284 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index baa5c4acad83..c9c0601f0615 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -19,140 +19,110 @@ | |||
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); | 37 | irq_chip_set_defaults(chip); |
41 | desc->irq_data.chip = chip; | 38 | desc->irq_data.chip = chip; |
42 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 39 | irq_put_desc_unlock(desc, flags); |
43 | |||
44 | return 0; | 40 | return 0; |
45 | } | 41 | } |
46 | EXPORT_SYMBOL(set_irq_chip); | 42 | EXPORT_SYMBOL(irq_set_chip); |
47 | 43 | ||
48 | /** | 44 | /** |
49 | * set_irq_type - set the irq trigger type for an irq | 45 | * irq_set_type - set the irq trigger type for an irq |
50 | * @irq: irq number | 46 | * @irq: irq number |
51 | * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h | 47 | * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h |
52 | */ | 48 | */ |
53 | int set_irq_type(unsigned int irq, unsigned int type) | 49 | int irq_set_irq_type(unsigned int irq, unsigned int type) |
54 | { | 50 | { |
55 | struct irq_desc *desc = irq_to_desc(irq); | ||
56 | unsigned long flags; | 51 | unsigned long flags; |
57 | int ret = -ENXIO; | 52 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); |
53 | int ret = 0; | ||
58 | 54 | ||
59 | if (!desc) { | 55 | if (!desc) |
60 | printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); | 56 | return -EINVAL; |
61 | return -ENODEV; | ||
62 | } | ||
63 | 57 | ||
64 | type &= IRQ_TYPE_SENSE_MASK; | 58 | type &= IRQ_TYPE_SENSE_MASK; |
65 | if (type == IRQ_TYPE_NONE) | 59 | if (type != IRQ_TYPE_NONE) |
66 | return 0; | 60 | ret = __irq_set_trigger(desc, irq, type); |
67 | 61 | 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; | 62 | return ret; |
72 | } | 63 | } |
73 | EXPORT_SYMBOL(set_irq_type); | 64 | EXPORT_SYMBOL(irq_set_irq_type); |
74 | 65 | ||
75 | /** | 66 | /** |
76 | * set_irq_data - set irq type data for an irq | 67 | * irq_set_handler_data - set irq handler data for an irq |
77 | * @irq: Interrupt number | 68 | * @irq: Interrupt number |
78 | * @data: Pointer to interrupt specific data | 69 | * @data: Pointer to interrupt specific data |
79 | * | 70 | * |
80 | * Set the hardware irq controller data for an irq | 71 | * Set the hardware irq controller data for an irq |
81 | */ | 72 | */ |
82 | int set_irq_data(unsigned int irq, void *data) | 73 | int irq_set_handler_data(unsigned int irq, void *data) |
83 | { | 74 | { |
84 | struct irq_desc *desc = irq_to_desc(irq); | ||
85 | unsigned long flags; | 75 | unsigned long flags; |
76 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
86 | 77 | ||
87 | if (!desc) { | 78 | if (!desc) |
88 | printk(KERN_ERR | ||
89 | "Trying to install controller data for IRQ%d\n", irq); | ||
90 | return -EINVAL; | 79 | return -EINVAL; |
91 | } | ||
92 | |||
93 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
94 | desc->irq_data.handler_data = data; | 80 | desc->irq_data.handler_data = data; |
95 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 81 | irq_put_desc_unlock(desc, flags); |
96 | return 0; | 82 | return 0; |
97 | } | 83 | } |
98 | EXPORT_SYMBOL(set_irq_data); | 84 | EXPORT_SYMBOL(irq_set_handler_data); |
99 | 85 | ||
100 | /** | 86 | /** |
101 | * set_irq_msi - set MSI descriptor data for an irq | 87 | * irq_set_msi_desc - set MSI descriptor data for an irq |
102 | * @irq: Interrupt number | 88 | * @irq: Interrupt number |
103 | * @entry: Pointer to MSI descriptor data | 89 | * @entry: Pointer to MSI descriptor data |
104 | * | 90 | * |
105 | * Set the MSI descriptor entry for an irq | 91 | * Set the MSI descriptor entry for an irq |
106 | */ | 92 | */ |
107 | int set_irq_msi(unsigned int irq, struct msi_desc *entry) | 93 | int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) |
108 | { | 94 | { |
109 | struct irq_desc *desc = irq_to_desc(irq); | ||
110 | unsigned long flags; | 95 | unsigned long flags; |
96 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
111 | 97 | ||
112 | if (!desc) { | 98 | if (!desc) |
113 | printk(KERN_ERR | ||
114 | "Trying to install msi data for IRQ%d\n", irq); | ||
115 | return -EINVAL; | 99 | return -EINVAL; |
116 | } | ||
117 | |||
118 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
119 | desc->irq_data.msi_desc = entry; | 100 | desc->irq_data.msi_desc = entry; |
120 | if (entry) | 101 | if (entry) |
121 | entry->irq = irq; | 102 | entry->irq = irq; |
122 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 103 | irq_put_desc_unlock(desc, flags); |
123 | return 0; | 104 | return 0; |
124 | } | 105 | } |
125 | 106 | ||
126 | /** | 107 | /** |
127 | * set_irq_chip_data - set irq chip data for an irq | 108 | * irq_set_chip_data - set irq chip data for an irq |
128 | * @irq: Interrupt number | 109 | * @irq: Interrupt number |
129 | * @data: Pointer to chip specific data | 110 | * @data: Pointer to chip specific data |
130 | * | 111 | * |
131 | * Set the hardware irq chip data for an irq | 112 | * Set the hardware irq chip data for an irq |
132 | */ | 113 | */ |
133 | int set_irq_chip_data(unsigned int irq, void *data) | 114 | int irq_set_chip_data(unsigned int irq, void *data) |
134 | { | 115 | { |
135 | struct irq_desc *desc = irq_to_desc(irq); | ||
136 | unsigned long flags; | 116 | unsigned long flags; |
117 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
137 | 118 | ||
138 | if (!desc) { | 119 | 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; | 120 | return -EINVAL; |
147 | } | ||
148 | |||
149 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
150 | desc->irq_data.chip_data = data; | 121 | desc->irq_data.chip_data = data; |
151 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 122 | irq_put_desc_unlock(desc, flags); |
152 | |||
153 | return 0; | 123 | return 0; |
154 | } | 124 | } |
155 | EXPORT_SYMBOL(set_irq_chip_data); | 125 | EXPORT_SYMBOL(irq_set_chip_data); |
156 | 126 | ||
157 | struct irq_data *irq_get_irq_data(unsigned int irq) | 127 | struct irq_data *irq_get_irq_data(unsigned int irq) |
158 | { | 128 | { |
@@ -162,72 +132,75 @@ struct irq_data *irq_get_irq_data(unsigned int irq) | |||
162 | } | 132 | } |
163 | EXPORT_SYMBOL_GPL(irq_get_irq_data); | 133 | EXPORT_SYMBOL_GPL(irq_get_irq_data); |
164 | 134 | ||
165 | /** | 135 | 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 | { | 136 | { |
178 | struct irq_desc *desc = irq_to_desc(irq); | 137 | desc->istate &= ~IRQS_DISABLED; |
179 | unsigned long flags; | 138 | irq_compat_clr_disabled(desc); |
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 | } | 139 | } |
191 | EXPORT_SYMBOL_GPL(set_irq_nested_thread); | ||
192 | 140 | ||
193 | /* | 141 | static void irq_state_set_disabled(struct irq_desc *desc) |
194 | * default enable function | ||
195 | */ | ||
196 | static void default_enable(struct irq_data *data) | ||
197 | { | 142 | { |
198 | struct irq_desc *desc = irq_data_to_desc(data); | 143 | desc->istate |= IRQS_DISABLED; |
144 | irq_compat_set_disabled(desc); | ||
145 | } | ||
199 | 146 | ||
200 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 147 | static void irq_state_clr_masked(struct irq_desc *desc) |
201 | desc->status &= ~IRQ_MASKED; | 148 | { |
149 | desc->istate &= ~IRQS_MASKED; | ||
150 | irq_compat_clr_masked(desc); | ||
202 | } | 151 | } |
203 | 152 | ||
204 | /* | 153 | static void irq_state_set_masked(struct irq_desc *desc) |
205 | * default disable function | ||
206 | */ | ||
207 | static void default_disable(struct irq_data *data) | ||
208 | { | 154 | { |
155 | desc->istate |= IRQS_MASKED; | ||
156 | irq_compat_set_masked(desc); | ||
209 | } | 157 | } |
210 | 158 | ||
211 | /* | 159 | int irq_startup(struct irq_desc *desc) |
212 | * default startup function | ||
213 | */ | ||
214 | static unsigned int default_startup(struct irq_data *data) | ||
215 | { | 160 | { |
216 | struct irq_desc *desc = irq_data_to_desc(data); | 161 | irq_state_clr_disabled(desc); |
162 | desc->depth = 0; | ||
163 | |||
164 | if (desc->irq_data.chip->irq_startup) { | ||
165 | int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); | ||
166 | irq_state_clr_masked(desc); | ||
167 | return ret; | ||
168 | } | ||
217 | 169 | ||
218 | desc->irq_data.chip->irq_enable(data); | 170 | irq_enable(desc); |
219 | return 0; | 171 | return 0; |
220 | } | 172 | } |
221 | 173 | ||
222 | /* | 174 | void irq_shutdown(struct irq_desc *desc) |
223 | * default shutdown function | ||
224 | */ | ||
225 | static void default_shutdown(struct irq_data *data) | ||
226 | { | 175 | { |
227 | struct irq_desc *desc = irq_data_to_desc(data); | 176 | irq_state_set_disabled(desc); |
177 | desc->depth = 1; | ||
178 | if (desc->irq_data.chip->irq_shutdown) | ||
179 | desc->irq_data.chip->irq_shutdown(&desc->irq_data); | ||
180 | if (desc->irq_data.chip->irq_disable) | ||
181 | desc->irq_data.chip->irq_disable(&desc->irq_data); | ||
182 | else | ||
183 | desc->irq_data.chip->irq_mask(&desc->irq_data); | ||
184 | irq_state_set_masked(desc); | ||
185 | } | ||
228 | 186 | ||
229 | desc->irq_data.chip->irq_mask(&desc->irq_data); | 187 | void irq_enable(struct irq_desc *desc) |
230 | desc->status |= IRQ_MASKED; | 188 | { |
189 | irq_state_clr_disabled(desc); | ||
190 | if (desc->irq_data.chip->irq_enable) | ||
191 | desc->irq_data.chip->irq_enable(&desc->irq_data); | ||
192 | else | ||
193 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
194 | irq_state_clr_masked(desc); | ||
195 | } | ||
196 | |||
197 | void irq_disable(struct irq_desc *desc) | ||
198 | { | ||
199 | irq_state_set_disabled(desc); | ||
200 | if (desc->irq_data.chip->irq_disable) { | ||
201 | desc->irq_data.chip->irq_disable(&desc->irq_data); | ||
202 | irq_state_set_masked(desc); | ||
203 | } | ||
231 | } | 204 | } |
232 | 205 | ||
233 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | 206 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED |
@@ -315,10 +288,6 @@ static void compat_bus_sync_unlock(struct irq_data *data) | |||
315 | void irq_chip_set_defaults(struct irq_chip *chip) | 288 | void irq_chip_set_defaults(struct irq_chip *chip) |
316 | { | 289 | { |
317 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | 290 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED |
318 | /* | ||
319 | * Compat fixup functions need to be before we set the | ||
320 | * defaults for enable/disable/startup/shutdown | ||
321 | */ | ||
322 | if (chip->enable) | 291 | if (chip->enable) |
323 | chip->irq_enable = compat_irq_enable; | 292 | chip->irq_enable = compat_irq_enable; |
324 | if (chip->disable) | 293 | if (chip->disable) |
@@ -327,33 +296,8 @@ void irq_chip_set_defaults(struct irq_chip *chip) | |||
327 | chip->irq_shutdown = compat_irq_shutdown; | 296 | chip->irq_shutdown = compat_irq_shutdown; |
328 | if (chip->startup) | 297 | if (chip->startup) |
329 | chip->irq_startup = compat_irq_startup; | 298 | 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) | 299 | if (!chip->end) |
352 | chip->end = dummy_irq_chip.end; | 300 | chip->end = dummy_irq_chip.end; |
353 | |||
354 | /* | ||
355 | * Now fix up the remaining compat handlers | ||
356 | */ | ||
357 | if (chip->bus_lock) | 301 | if (chip->bus_lock) |
358 | chip->irq_bus_lock = compat_bus_lock; | 302 | chip->irq_bus_lock = compat_bus_lock; |
359 | if (chip->bus_sync_unlock) | 303 | if (chip->bus_sync_unlock) |
@@ -388,22 +332,22 @@ static inline void mask_ack_irq(struct irq_desc *desc) | |||
388 | if (desc->irq_data.chip->irq_ack) | 332 | if (desc->irq_data.chip->irq_ack) |
389 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 333 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
390 | } | 334 | } |
391 | desc->status |= IRQ_MASKED; | 335 | irq_state_set_masked(desc); |
392 | } | 336 | } |
393 | 337 | ||
394 | static inline void mask_irq(struct irq_desc *desc) | 338 | void mask_irq(struct irq_desc *desc) |
395 | { | 339 | { |
396 | if (desc->irq_data.chip->irq_mask) { | 340 | if (desc->irq_data.chip->irq_mask) { |
397 | desc->irq_data.chip->irq_mask(&desc->irq_data); | 341 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
398 | desc->status |= IRQ_MASKED; | 342 | irq_state_set_masked(desc); |
399 | } | 343 | } |
400 | } | 344 | } |
401 | 345 | ||
402 | static inline void unmask_irq(struct irq_desc *desc) | 346 | void unmask_irq(struct irq_desc *desc) |
403 | { | 347 | { |
404 | if (desc->irq_data.chip->irq_unmask) { | 348 | if (desc->irq_data.chip->irq_unmask) { |
405 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 349 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
406 | desc->status &= ~IRQ_MASKED; | 350 | irq_state_clr_masked(desc); |
407 | } | 351 | } |
408 | } | 352 | } |
409 | 353 | ||
@@ -428,10 +372,11 @@ void handle_nested_irq(unsigned int irq) | |||
428 | kstat_incr_irqs_this_cpu(irq, desc); | 372 | kstat_incr_irqs_this_cpu(irq, desc); |
429 | 373 | ||
430 | action = desc->action; | 374 | action = desc->action; |
431 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 375 | if (unlikely(!action || (desc->istate & IRQS_DISABLED))) |
432 | goto out_unlock; | 376 | goto out_unlock; |
433 | 377 | ||
434 | desc->status |= IRQ_INPROGRESS; | 378 | irq_compat_set_progress(desc); |
379 | desc->istate |= IRQS_INPROGRESS; | ||
435 | raw_spin_unlock_irq(&desc->lock); | 380 | raw_spin_unlock_irq(&desc->lock); |
436 | 381 | ||
437 | action_ret = action->thread_fn(action->irq, action->dev_id); | 382 | action_ret = action->thread_fn(action->irq, action->dev_id); |
@@ -439,13 +384,21 @@ void handle_nested_irq(unsigned int irq) | |||
439 | note_interrupt(irq, desc, action_ret); | 384 | note_interrupt(irq, desc, action_ret); |
440 | 385 | ||
441 | raw_spin_lock_irq(&desc->lock); | 386 | raw_spin_lock_irq(&desc->lock); |
442 | desc->status &= ~IRQ_INPROGRESS; | 387 | desc->istate &= ~IRQS_INPROGRESS; |
388 | irq_compat_clr_progress(desc); | ||
443 | 389 | ||
444 | out_unlock: | 390 | out_unlock: |
445 | raw_spin_unlock_irq(&desc->lock); | 391 | raw_spin_unlock_irq(&desc->lock); |
446 | } | 392 | } |
447 | EXPORT_SYMBOL_GPL(handle_nested_irq); | 393 | EXPORT_SYMBOL_GPL(handle_nested_irq); |
448 | 394 | ||
395 | static bool irq_check_poll(struct irq_desc *desc) | ||
396 | { | ||
397 | if (!(desc->istate & IRQS_POLL_INPROGRESS)) | ||
398 | return false; | ||
399 | return irq_wait_for_poll(desc); | ||
400 | } | ||
401 | |||
449 | /** | 402 | /** |
450 | * handle_simple_irq - Simple and software-decoded IRQs. | 403 | * handle_simple_irq - Simple and software-decoded IRQs. |
451 | * @irq: the interrupt number | 404 | * @irq: the interrupt number |
@@ -461,29 +414,20 @@ EXPORT_SYMBOL_GPL(handle_nested_irq); | |||
461 | void | 414 | void |
462 | handle_simple_irq(unsigned int irq, struct irq_desc *desc) | 415 | handle_simple_irq(unsigned int irq, struct irq_desc *desc) |
463 | { | 416 | { |
464 | struct irqaction *action; | ||
465 | irqreturn_t action_ret; | ||
466 | |||
467 | raw_spin_lock(&desc->lock); | 417 | raw_spin_lock(&desc->lock); |
468 | 418 | ||
469 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 419 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
470 | goto out_unlock; | 420 | if (!irq_check_poll(desc)) |
471 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 421 | goto out_unlock; |
422 | |||
423 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
472 | kstat_incr_irqs_this_cpu(irq, desc); | 424 | kstat_incr_irqs_this_cpu(irq, desc); |
473 | 425 | ||
474 | action = desc->action; | 426 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) |
475 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
476 | goto out_unlock; | 427 | goto out_unlock; |
477 | 428 | ||
478 | desc->status |= IRQ_INPROGRESS; | 429 | handle_irq_event(desc); |
479 | raw_spin_unlock(&desc->lock); | ||
480 | 430 | ||
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: | 431 | out_unlock: |
488 | raw_spin_unlock(&desc->lock); | 432 | raw_spin_unlock(&desc->lock); |
489 | } | 433 | } |
@@ -501,42 +445,42 @@ out_unlock: | |||
501 | void | 445 | void |
502 | handle_level_irq(unsigned int irq, struct irq_desc *desc) | 446 | handle_level_irq(unsigned int irq, struct irq_desc *desc) |
503 | { | 447 | { |
504 | struct irqaction *action; | ||
505 | irqreturn_t action_ret; | ||
506 | |||
507 | raw_spin_lock(&desc->lock); | 448 | raw_spin_lock(&desc->lock); |
508 | mask_ack_irq(desc); | 449 | mask_ack_irq(desc); |
509 | 450 | ||
510 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 451 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
511 | goto out_unlock; | 452 | if (!irq_check_poll(desc)) |
512 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 453 | goto out_unlock; |
454 | |||
455 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
513 | kstat_incr_irqs_this_cpu(irq, desc); | 456 | kstat_incr_irqs_this_cpu(irq, desc); |
514 | 457 | ||
515 | /* | 458 | /* |
516 | * If its disabled or no action available | 459 | * If its disabled or no action available |
517 | * keep it masked and get out of here | 460 | * keep it masked and get out of here |
518 | */ | 461 | */ |
519 | action = desc->action; | 462 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) |
520 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
521 | goto out_unlock; | 463 | goto out_unlock; |
522 | 464 | ||
523 | desc->status |= IRQ_INPROGRESS; | 465 | 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 | 466 | ||
530 | raw_spin_lock(&desc->lock); | 467 | if (!(desc->istate & (IRQS_DISABLED | IRQS_ONESHOT))) |
531 | desc->status &= ~IRQ_INPROGRESS; | ||
532 | |||
533 | if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT))) | ||
534 | unmask_irq(desc); | 468 | unmask_irq(desc); |
535 | out_unlock: | 469 | out_unlock: |
536 | raw_spin_unlock(&desc->lock); | 470 | raw_spin_unlock(&desc->lock); |
537 | } | 471 | } |
538 | EXPORT_SYMBOL_GPL(handle_level_irq); | 472 | EXPORT_SYMBOL_GPL(handle_level_irq); |
539 | 473 | ||
474 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
475 | static inline void preflow_handler(struct irq_desc *desc) | ||
476 | { | ||
477 | if (desc->preflow_handler) | ||
478 | desc->preflow_handler(&desc->irq_data); | ||
479 | } | ||
480 | #else | ||
481 | static inline void preflow_handler(struct irq_desc *desc) { } | ||
482 | #endif | ||
483 | |||
540 | /** | 484 | /** |
541 | * handle_fasteoi_irq - irq handler for transparent controllers | 485 | * handle_fasteoi_irq - irq handler for transparent controllers |
542 | * @irq: the interrupt number | 486 | * @irq: the interrupt number |
@@ -550,42 +494,41 @@ EXPORT_SYMBOL_GPL(handle_level_irq); | |||
550 | void | 494 | void |
551 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | 495 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) |
552 | { | 496 | { |
553 | struct irqaction *action; | ||
554 | irqreturn_t action_ret; | ||
555 | |||
556 | raw_spin_lock(&desc->lock); | 497 | raw_spin_lock(&desc->lock); |
557 | 498 | ||
558 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 499 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
559 | goto out; | 500 | if (!irq_check_poll(desc)) |
501 | goto out; | ||
560 | 502 | ||
561 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 503 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
562 | kstat_incr_irqs_this_cpu(irq, desc); | 504 | kstat_incr_irqs_this_cpu(irq, desc); |
563 | 505 | ||
564 | /* | 506 | /* |
565 | * If its disabled or no action available | 507 | * If its disabled or no action available |
566 | * then mask it and get out of here: | 508 | * then mask it and get out of here: |
567 | */ | 509 | */ |
568 | action = desc->action; | 510 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) { |
569 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { | 511 | irq_compat_set_pending(desc); |
570 | desc->status |= IRQ_PENDING; | 512 | desc->istate |= IRQS_PENDING; |
571 | mask_irq(desc); | 513 | mask_irq(desc); |
572 | goto out; | 514 | goto out; |
573 | } | 515 | } |
574 | 516 | ||
575 | desc->status |= IRQ_INPROGRESS; | 517 | if (desc->istate & IRQS_ONESHOT) |
576 | desc->status &= ~IRQ_PENDING; | 518 | mask_irq(desc); |
577 | raw_spin_unlock(&desc->lock); | ||
578 | 519 | ||
579 | action_ret = handle_IRQ_event(irq, action); | 520 | preflow_handler(desc); |
580 | if (!noirqdebug) | 521 | handle_irq_event(desc); |
581 | note_interrupt(irq, desc, action_ret); | ||
582 | 522 | ||
583 | raw_spin_lock(&desc->lock); | 523 | out_eoi: |
584 | desc->status &= ~IRQ_INPROGRESS; | ||
585 | out: | ||
586 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 524 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
587 | 525 | out_unlock: | |
588 | raw_spin_unlock(&desc->lock); | 526 | raw_spin_unlock(&desc->lock); |
527 | return; | ||
528 | out: | ||
529 | if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED)) | ||
530 | goto out_eoi; | ||
531 | goto out_unlock; | ||
589 | } | 532 | } |
590 | 533 | ||
591 | /** | 534 | /** |
@@ -609,32 +552,28 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
609 | { | 552 | { |
610 | raw_spin_lock(&desc->lock); | 553 | raw_spin_lock(&desc->lock); |
611 | 554 | ||
612 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 555 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
613 | |||
614 | /* | 556 | /* |
615 | * If we're currently running this IRQ, or its disabled, | 557 | * If we're currently running this IRQ, or its disabled, |
616 | * we shouldn't process the IRQ. Mark it pending, handle | 558 | * we shouldn't process the IRQ. Mark it pending, handle |
617 | * the necessary masking and go out | 559 | * the necessary masking and go out |
618 | */ | 560 | */ |
619 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | 561 | if (unlikely((desc->istate & (IRQS_DISABLED | IRQS_INPROGRESS) || |
620 | !desc->action)) { | 562 | !desc->action))) { |
621 | desc->status |= (IRQ_PENDING | IRQ_MASKED); | 563 | if (!irq_check_poll(desc)) { |
622 | mask_ack_irq(desc); | 564 | irq_compat_set_pending(desc); |
623 | goto out_unlock; | 565 | desc->istate |= IRQS_PENDING; |
566 | mask_ack_irq(desc); | ||
567 | goto out_unlock; | ||
568 | } | ||
624 | } | 569 | } |
625 | kstat_incr_irqs_this_cpu(irq, desc); | 570 | kstat_incr_irqs_this_cpu(irq, desc); |
626 | 571 | ||
627 | /* Start handling the irq */ | 572 | /* Start handling the irq */ |
628 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 573 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
629 | 574 | ||
630 | /* Mark the IRQ currently in progress.*/ | ||
631 | desc->status |= IRQ_INPROGRESS; | ||
632 | |||
633 | do { | 575 | do { |
634 | struct irqaction *action = desc->action; | 576 | if (unlikely(!desc->action)) { |
635 | irqreturn_t action_ret; | ||
636 | |||
637 | if (unlikely(!action)) { | ||
638 | mask_irq(desc); | 577 | mask_irq(desc); |
639 | goto out_unlock; | 578 | goto out_unlock; |
640 | } | 579 | } |
@@ -644,22 +583,17 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
644 | * one, we could have masked the irq. | 583 | * one, we could have masked the irq. |
645 | * Renable it, if it was not disabled in meantime. | 584 | * Renable it, if it was not disabled in meantime. |
646 | */ | 585 | */ |
647 | if (unlikely((desc->status & | 586 | if (unlikely(desc->istate & IRQS_PENDING)) { |
648 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == | 587 | if (!(desc->istate & IRQS_DISABLED) && |
649 | (IRQ_PENDING | IRQ_MASKED))) { | 588 | (desc->istate & IRQS_MASKED)) |
650 | unmask_irq(desc); | 589 | unmask_irq(desc); |
651 | } | 590 | } |
652 | 591 | ||
653 | desc->status &= ~IRQ_PENDING; | 592 | 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 | 593 | ||
660 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | 594 | } while ((desc->istate & IRQS_PENDING) && |
595 | !(desc->istate & IRQS_DISABLED)); | ||
661 | 596 | ||
662 | desc->status &= ~IRQ_INPROGRESS; | ||
663 | out_unlock: | 597 | out_unlock: |
664 | raw_spin_unlock(&desc->lock); | 598 | raw_spin_unlock(&desc->lock); |
665 | } | 599 | } |
@@ -674,103 +608,84 @@ out_unlock: | |||
674 | void | 608 | void |
675 | handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | 609 | handle_percpu_irq(unsigned int irq, struct irq_desc *desc) |
676 | { | 610 | { |
677 | irqreturn_t action_ret; | 611 | struct irq_chip *chip = irq_desc_get_chip(desc); |
678 | 612 | ||
679 | kstat_incr_irqs_this_cpu(irq, desc); | 613 | kstat_incr_irqs_this_cpu(irq, desc); |
680 | 614 | ||
681 | if (desc->irq_data.chip->irq_ack) | 615 | if (chip->irq_ack) |
682 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 616 | chip->irq_ack(&desc->irq_data); |
683 | 617 | ||
684 | action_ret = handle_IRQ_event(irq, desc->action); | 618 | handle_irq_event_percpu(desc, desc->action); |
685 | if (!noirqdebug) | ||
686 | note_interrupt(irq, desc, action_ret); | ||
687 | 619 | ||
688 | if (desc->irq_data.chip->irq_eoi) | 620 | if (chip->irq_eoi) |
689 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 621 | chip->irq_eoi(&desc->irq_data); |
690 | } | 622 | } |
691 | 623 | ||
692 | void | 624 | void |
693 | __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | 625 | __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, |
694 | const char *name) | 626 | const char *name) |
695 | { | 627 | { |
696 | struct irq_desc *desc = irq_to_desc(irq); | ||
697 | unsigned long flags; | 628 | unsigned long flags; |
629 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); | ||
698 | 630 | ||
699 | if (!desc) { | 631 | if (!desc) |
700 | printk(KERN_ERR | ||
701 | "Trying to install type control for IRQ%d\n", irq); | ||
702 | return; | 632 | return; |
703 | } | ||
704 | 633 | ||
705 | if (!handle) | 634 | if (!handle) { |
706 | handle = handle_bad_irq; | 635 | handle = handle_bad_irq; |
707 | else if (desc->irq_data.chip == &no_irq_chip) { | 636 | } else { |
708 | printk(KERN_WARNING "Trying to install %sinterrupt handler " | 637 | if (WARN_ON(desc->irq_data.chip == &no_irq_chip)) |
709 | "for IRQ%d\n", is_chained ? "chained " : "", irq); | 638 | 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 | } | 639 | } |
719 | 640 | ||
720 | chip_bus_lock(desc); | ||
721 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
722 | |||
723 | /* Uninstall? */ | 641 | /* Uninstall? */ |
724 | if (handle == handle_bad_irq) { | 642 | if (handle == handle_bad_irq) { |
725 | if (desc->irq_data.chip != &no_irq_chip) | 643 | if (desc->irq_data.chip != &no_irq_chip) |
726 | mask_ack_irq(desc); | 644 | mask_ack_irq(desc); |
727 | desc->status |= IRQ_DISABLED; | 645 | irq_compat_set_disabled(desc); |
646 | desc->istate |= IRQS_DISABLED; | ||
728 | desc->depth = 1; | 647 | desc->depth = 1; |
729 | } | 648 | } |
730 | desc->handle_irq = handle; | 649 | desc->handle_irq = handle; |
731 | desc->name = name; | 650 | desc->name = name; |
732 | 651 | ||
733 | if (handle != handle_bad_irq && is_chained) { | 652 | if (handle != handle_bad_irq && is_chained) { |
734 | desc->status &= ~IRQ_DISABLED; | 653 | irq_settings_set_noprobe(desc); |
735 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; | 654 | irq_settings_set_norequest(desc); |
736 | desc->depth = 0; | 655 | irq_startup(desc); |
737 | desc->irq_data.chip->irq_startup(&desc->irq_data); | ||
738 | } | 656 | } |
739 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 657 | out: |
740 | chip_bus_sync_unlock(desc); | 658 | 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 | } | 659 | } |
660 | EXPORT_SYMBOL_GPL(__irq_set_handler); | ||
751 | 661 | ||
752 | void | 662 | void |
753 | set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | 663 | irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, |
754 | irq_flow_handler_t handle, const char *name) | 664 | irq_flow_handler_t handle, const char *name) |
755 | { | 665 | { |
756 | set_irq_chip(irq, chip); | 666 | irq_set_chip(irq, chip); |
757 | __set_irq_handler(irq, handle, 0, name); | 667 | __irq_set_handler(irq, handle, 0, name); |
758 | } | 668 | } |
759 | 669 | ||
760 | void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | 670 | void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) |
761 | { | 671 | { |
762 | struct irq_desc *desc = irq_to_desc(irq); | ||
763 | unsigned long flags; | 672 | unsigned long flags; |
673 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | ||
764 | 674 | ||
765 | if (!desc) | 675 | if (!desc) |
766 | return; | 676 | return; |
677 | irq_settings_clr_and_set(desc, clr, set); | ||
678 | |||
679 | irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU | | ||
680 | IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT); | ||
681 | if (irq_settings_has_no_balance_set(desc)) | ||
682 | irqd_set(&desc->irq_data, IRQD_NO_BALANCING); | ||
683 | if (irq_settings_is_per_cpu(desc)) | ||
684 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | ||
685 | if (irq_settings_can_move_pcntxt(desc)) | ||
686 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); | ||
767 | 687 | ||
768 | /* Sanitize flags */ | 688 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); |
769 | set &= IRQF_MODIFY_MASK; | ||
770 | clr &= IRQF_MODIFY_MASK; | ||
771 | 689 | ||
772 | raw_spin_lock_irqsave(&desc->lock, flags); | 690 | irq_put_desc_unlock(desc, flags); |
773 | desc->status &= ~clr; | ||
774 | desc->status |= set; | ||
775 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
776 | } | 691 | } |