diff options
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r-- | kernel/irq/chip.c | 126 |
1 files changed, 21 insertions, 105 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 3aca9f29d30..dc5114b4c16 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -16,8 +16,6 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel_stat.h> | 17 | #include <linux/kernel_stat.h> |
18 | 18 | ||
19 | #include <trace/events/irq.h> | ||
20 | |||
21 | #include "internals.h" | 19 | #include "internals.h" |
22 | 20 | ||
23 | /** | 21 | /** |
@@ -28,7 +26,7 @@ | |||
28 | int irq_set_chip(unsigned int irq, struct irq_chip *chip) | 26 | int irq_set_chip(unsigned int irq, struct irq_chip *chip) |
29 | { | 27 | { |
30 | unsigned long flags; | 28 | unsigned long flags; |
31 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); | 29 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); |
32 | 30 | ||
33 | if (!desc) | 31 | if (!desc) |
34 | return -EINVAL; | 32 | return -EINVAL; |
@@ -56,14 +54,15 @@ EXPORT_SYMBOL(irq_set_chip); | |||
56 | int irq_set_irq_type(unsigned int irq, unsigned int type) | 54 | int irq_set_irq_type(unsigned int irq, unsigned int type) |
57 | { | 55 | { |
58 | unsigned long flags; | 56 | unsigned long flags; |
59 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); | 57 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); |
60 | int ret = 0; | 58 | int ret = 0; |
61 | 59 | ||
62 | if (!desc) | 60 | if (!desc) |
63 | return -EINVAL; | 61 | return -EINVAL; |
64 | 62 | ||
65 | type &= IRQ_TYPE_SENSE_MASK; | 63 | type &= IRQ_TYPE_SENSE_MASK; |
66 | ret = __irq_set_trigger(desc, irq, type); | 64 | if (type != IRQ_TYPE_NONE) |
65 | ret = __irq_set_trigger(desc, irq, type); | ||
67 | irq_put_desc_busunlock(desc, flags); | 66 | irq_put_desc_busunlock(desc, flags); |
68 | return ret; | 67 | return ret; |
69 | } | 68 | } |
@@ -79,7 +78,7 @@ EXPORT_SYMBOL(irq_set_irq_type); | |||
79 | int irq_set_handler_data(unsigned int irq, void *data) | 78 | int irq_set_handler_data(unsigned int irq, void *data) |
80 | { | 79 | { |
81 | unsigned long flags; | 80 | unsigned long flags; |
82 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); | 81 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); |
83 | 82 | ||
84 | if (!desc) | 83 | if (!desc) |
85 | return -EINVAL; | 84 | return -EINVAL; |
@@ -99,7 +98,7 @@ EXPORT_SYMBOL(irq_set_handler_data); | |||
99 | int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) | 98 | int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) |
100 | { | 99 | { |
101 | unsigned long flags; | 100 | unsigned long flags; |
102 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); | 101 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); |
103 | 102 | ||
104 | if (!desc) | 103 | if (!desc) |
105 | return -EINVAL; | 104 | return -EINVAL; |
@@ -120,7 +119,7 @@ int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) | |||
120 | int irq_set_chip_data(unsigned int irq, void *data) | 119 | int irq_set_chip_data(unsigned int irq, void *data) |
121 | { | 120 | { |
122 | unsigned long flags; | 121 | unsigned long flags; |
123 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); | 122 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); |
124 | 123 | ||
125 | if (!desc) | 124 | if (!desc) |
126 | return -EINVAL; | 125 | return -EINVAL; |
@@ -158,22 +157,19 @@ static void irq_state_set_masked(struct irq_desc *desc) | |||
158 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); | 157 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); |
159 | } | 158 | } |
160 | 159 | ||
161 | int irq_startup(struct irq_desc *desc, bool resend) | 160 | int irq_startup(struct irq_desc *desc) |
162 | { | 161 | { |
163 | int ret = 0; | ||
164 | |||
165 | irq_state_clr_disabled(desc); | 162 | irq_state_clr_disabled(desc); |
166 | desc->depth = 0; | 163 | desc->depth = 0; |
167 | 164 | ||
168 | if (desc->irq_data.chip->irq_startup) { | 165 | if (desc->irq_data.chip->irq_startup) { |
169 | ret = desc->irq_data.chip->irq_startup(&desc->irq_data); | 166 | int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); |
170 | irq_state_clr_masked(desc); | 167 | irq_state_clr_masked(desc); |
171 | } else { | 168 | return ret; |
172 | irq_enable(desc); | ||
173 | } | 169 | } |
174 | if (resend) | 170 | |
175 | check_irq_resend(desc, desc->irq_data.irq); | 171 | irq_enable(desc); |
176 | return ret; | 172 | return 0; |
177 | } | 173 | } |
178 | 174 | ||
179 | void irq_shutdown(struct irq_desc *desc) | 175 | void irq_shutdown(struct irq_desc *desc) |
@@ -208,24 +204,6 @@ void irq_disable(struct irq_desc *desc) | |||
208 | } | 204 | } |
209 | } | 205 | } |
210 | 206 | ||
211 | void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu) | ||
212 | { | ||
213 | if (desc->irq_data.chip->irq_enable) | ||
214 | desc->irq_data.chip->irq_enable(&desc->irq_data); | ||
215 | else | ||
216 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
217 | cpumask_set_cpu(cpu, desc->percpu_enabled); | ||
218 | } | ||
219 | |||
220 | void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu) | ||
221 | { | ||
222 | if (desc->irq_data.chip->irq_disable) | ||
223 | desc->irq_data.chip->irq_disable(&desc->irq_data); | ||
224 | else | ||
225 | desc->irq_data.chip->irq_mask(&desc->irq_data); | ||
226 | cpumask_clear_cpu(cpu, desc->percpu_enabled); | ||
227 | } | ||
228 | |||
229 | static inline void mask_ack_irq(struct irq_desc *desc) | 207 | static inline void mask_ack_irq(struct irq_desc *desc) |
230 | { | 208 | { |
231 | if (desc->irq_data.chip->irq_mask_ack) | 209 | if (desc->irq_data.chip->irq_mask_ack) |
@@ -272,14 +250,11 @@ void handle_nested_irq(unsigned int irq) | |||
272 | 250 | ||
273 | raw_spin_lock_irq(&desc->lock); | 251 | raw_spin_lock_irq(&desc->lock); |
274 | 252 | ||
275 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
276 | kstat_incr_irqs_this_cpu(irq, desc); | 253 | kstat_incr_irqs_this_cpu(irq, desc); |
277 | 254 | ||
278 | action = desc->action; | 255 | action = desc->action; |
279 | if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) { | 256 | if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) |
280 | desc->istate |= IRQS_PENDING; | ||
281 | goto out_unlock; | 257 | goto out_unlock; |
282 | } | ||
283 | 258 | ||
284 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); | 259 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
285 | raw_spin_unlock_irq(&desc->lock); | 260 | raw_spin_unlock_irq(&desc->lock); |
@@ -327,10 +302,8 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
327 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | 302 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
328 | kstat_incr_irqs_this_cpu(irq, desc); | 303 | kstat_incr_irqs_this_cpu(irq, desc); |
329 | 304 | ||
330 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { | 305 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
331 | desc->istate |= IRQS_PENDING; | ||
332 | goto out_unlock; | 306 | goto out_unlock; |
333 | } | ||
334 | 307 | ||
335 | handle_irq_event(desc); | 308 | handle_irq_event(desc); |
336 | 309 | ||
@@ -339,24 +312,6 @@ out_unlock: | |||
339 | } | 312 | } |
340 | EXPORT_SYMBOL_GPL(handle_simple_irq); | 313 | EXPORT_SYMBOL_GPL(handle_simple_irq); |
341 | 314 | ||
342 | /* | ||
343 | * Called unconditionally from handle_level_irq() and only for oneshot | ||
344 | * interrupts from handle_fasteoi_irq() | ||
345 | */ | ||
346 | static void cond_unmask_irq(struct irq_desc *desc) | ||
347 | { | ||
348 | /* | ||
349 | * We need to unmask in the following cases: | ||
350 | * - Standard level irq (IRQF_ONESHOT is not set) | ||
351 | * - Oneshot irq which did not wake the thread (caused by a | ||
352 | * spurious interrupt or a primary handler handling it | ||
353 | * completely). | ||
354 | */ | ||
355 | if (!irqd_irq_disabled(&desc->irq_data) && | ||
356 | irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) | ||
357 | unmask_irq(desc); | ||
358 | } | ||
359 | |||
360 | /** | 315 | /** |
361 | * handle_level_irq - Level type irq handler | 316 | * handle_level_irq - Level type irq handler |
362 | * @irq: the interrupt number | 317 | * @irq: the interrupt number |
@@ -384,15 +339,13 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
384 | * If its disabled or no action available | 339 | * If its disabled or no action available |
385 | * keep it masked and get out of here | 340 | * keep it masked and get out of here |
386 | */ | 341 | */ |
387 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { | 342 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
388 | desc->istate |= IRQS_PENDING; | ||
389 | goto out_unlock; | 343 | goto out_unlock; |
390 | } | ||
391 | 344 | ||
392 | handle_irq_event(desc); | 345 | handle_irq_event(desc); |
393 | 346 | ||
394 | cond_unmask_irq(desc); | 347 | if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) |
395 | 348 | unmask_irq(desc); | |
396 | out_unlock: | 349 | out_unlock: |
397 | raw_spin_unlock(&desc->lock); | 350 | raw_spin_unlock(&desc->lock); |
398 | } | 351 | } |
@@ -446,9 +399,6 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
446 | preflow_handler(desc); | 399 | preflow_handler(desc); |
447 | handle_irq_event(desc); | 400 | handle_irq_event(desc); |
448 | 401 | ||
449 | if (desc->istate & IRQS_ONESHOT) | ||
450 | cond_unmask_irq(desc); | ||
451 | |||
452 | out_eoi: | 402 | out_eoi: |
453 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 403 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
454 | out_unlock: | 404 | out_unlock: |
@@ -525,7 +475,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
525 | out_unlock: | 475 | out_unlock: |
526 | raw_spin_unlock(&desc->lock); | 476 | raw_spin_unlock(&desc->lock); |
527 | } | 477 | } |
528 | EXPORT_SYMBOL(handle_edge_irq); | ||
529 | 478 | ||
530 | #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER | 479 | #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER |
531 | /** | 480 | /** |
@@ -595,44 +544,12 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | |||
595 | chip->irq_eoi(&desc->irq_data); | 544 | chip->irq_eoi(&desc->irq_data); |
596 | } | 545 | } |
597 | 546 | ||
598 | /** | ||
599 | * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids | ||
600 | * @irq: the interrupt number | ||
601 | * @desc: the interrupt description structure for this irq | ||
602 | * | ||
603 | * Per CPU interrupts on SMP machines without locking requirements. Same as | ||
604 | * handle_percpu_irq() above but with the following extras: | ||
605 | * | ||
606 | * action->percpu_dev_id is a pointer to percpu variables which | ||
607 | * contain the real device id for the cpu on which this handler is | ||
608 | * called | ||
609 | */ | ||
610 | void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc) | ||
611 | { | ||
612 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
613 | struct irqaction *action = desc->action; | ||
614 | void *dev_id = __this_cpu_ptr(action->percpu_dev_id); | ||
615 | irqreturn_t res; | ||
616 | |||
617 | kstat_incr_irqs_this_cpu(irq, desc); | ||
618 | |||
619 | if (chip->irq_ack) | ||
620 | chip->irq_ack(&desc->irq_data); | ||
621 | |||
622 | trace_irq_handler_entry(irq, action); | ||
623 | res = action->handler(irq, dev_id); | ||
624 | trace_irq_handler_exit(irq, action, res); | ||
625 | |||
626 | if (chip->irq_eoi) | ||
627 | chip->irq_eoi(&desc->irq_data); | ||
628 | } | ||
629 | |||
630 | void | 547 | void |
631 | __irq_set_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, |
632 | const char *name) | 549 | const char *name) |
633 | { | 550 | { |
634 | unsigned long flags; | 551 | unsigned long flags; |
635 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0); | 552 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); |
636 | 553 | ||
637 | if (!desc) | 554 | if (!desc) |
638 | return; | 555 | return; |
@@ -658,7 +575,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
658 | irq_settings_set_noprobe(desc); | 575 | irq_settings_set_noprobe(desc); |
659 | irq_settings_set_norequest(desc); | 576 | irq_settings_set_norequest(desc); |
660 | irq_settings_set_nothread(desc); | 577 | irq_settings_set_nothread(desc); |
661 | irq_startup(desc, true); | 578 | irq_startup(desc); |
662 | } | 579 | } |
663 | out: | 580 | out: |
664 | irq_put_desc_busunlock(desc, flags); | 581 | irq_put_desc_busunlock(desc, flags); |
@@ -672,12 +589,11 @@ irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | |||
672 | irq_set_chip(irq, chip); | 589 | irq_set_chip(irq, chip); |
673 | __irq_set_handler(irq, handle, 0, name); | 590 | __irq_set_handler(irq, handle, 0, name); |
674 | } | 591 | } |
675 | EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); | ||
676 | 592 | ||
677 | 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) |
678 | { | 594 | { |
679 | unsigned long flags; | 595 | unsigned long flags; |
680 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); | 596 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); |
681 | 597 | ||
682 | if (!desc) | 598 | if (!desc) |
683 | return; | 599 | return; |