diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/Kconfig | 4 | ||||
-rw-r--r-- | kernel/irq/chip.c | 154 | ||||
-rw-r--r-- | kernel/irq/debug.h | 10 | ||||
-rw-r--r-- | kernel/irq/handle.c | 16 | ||||
-rw-r--r-- | kernel/irq/internals.h | 6 | ||||
-rw-r--r-- | kernel/irq/irqdesc.c | 3 | ||||
-rw-r--r-- | kernel/irq/manage.c | 92 | ||||
-rw-r--r-- | kernel/irq/migration.c | 5 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 10 |
9 files changed, 205 insertions, 95 deletions
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 00f2c037267a..72606ba10b14 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -51,6 +51,10 @@ config HARDIRQS_SW_RESEND | |||
51 | config IRQ_PREFLOW_FASTEOI | 51 | config IRQ_PREFLOW_FASTEOI |
52 | bool | 52 | bool |
53 | 53 | ||
54 | # Edge style eoi based handler (cell) | ||
55 | config IRQ_EDGE_EOI_HANDLER | ||
56 | bool | ||
57 | |||
54 | # Support forced irq threading | 58 | # Support forced irq threading |
55 | config IRQ_FORCED_THREADING | 59 | config IRQ_FORCED_THREADING |
56 | bool | 60 | bool |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index c9c0601f0615..03099d521f5e 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -37,6 +37,12 @@ int irq_set_chip(unsigned int irq, struct irq_chip *chip) | |||
37 | irq_chip_set_defaults(chip); | 37 | irq_chip_set_defaults(chip); |
38 | desc->irq_data.chip = chip; | 38 | desc->irq_data.chip = chip; |
39 | irq_put_desc_unlock(desc, flags); | 39 | irq_put_desc_unlock(desc, flags); |
40 | /* | ||
41 | * For !CONFIG_SPARSE_IRQ make the irq show up in | ||
42 | * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is | ||
43 | * already marked, and this call is harmless. | ||
44 | */ | ||
45 | irq_reserve_irq(irq); | ||
40 | return 0; | 46 | return 0; |
41 | } | 47 | } |
42 | EXPORT_SYMBOL(irq_set_chip); | 48 | EXPORT_SYMBOL(irq_set_chip); |
@@ -134,25 +140,25 @@ EXPORT_SYMBOL_GPL(irq_get_irq_data); | |||
134 | 140 | ||
135 | static void irq_state_clr_disabled(struct irq_desc *desc) | 141 | static void irq_state_clr_disabled(struct irq_desc *desc) |
136 | { | 142 | { |
137 | desc->istate &= ~IRQS_DISABLED; | 143 | irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED); |
138 | irq_compat_clr_disabled(desc); | 144 | irq_compat_clr_disabled(desc); |
139 | } | 145 | } |
140 | 146 | ||
141 | static void irq_state_set_disabled(struct irq_desc *desc) | 147 | static void irq_state_set_disabled(struct irq_desc *desc) |
142 | { | 148 | { |
143 | desc->istate |= IRQS_DISABLED; | 149 | irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); |
144 | irq_compat_set_disabled(desc); | 150 | irq_compat_set_disabled(desc); |
145 | } | 151 | } |
146 | 152 | ||
147 | static void irq_state_clr_masked(struct irq_desc *desc) | 153 | static void irq_state_clr_masked(struct irq_desc *desc) |
148 | { | 154 | { |
149 | desc->istate &= ~IRQS_MASKED; | 155 | irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED); |
150 | irq_compat_clr_masked(desc); | 156 | irq_compat_clr_masked(desc); |
151 | } | 157 | } |
152 | 158 | ||
153 | static void irq_state_set_masked(struct irq_desc *desc) | 159 | static void irq_state_set_masked(struct irq_desc *desc) |
154 | { | 160 | { |
155 | desc->istate |= IRQS_MASKED; | 161 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); |
156 | irq_compat_set_masked(desc); | 162 | irq_compat_set_masked(desc); |
157 | } | 163 | } |
158 | 164 | ||
@@ -372,11 +378,11 @@ void handle_nested_irq(unsigned int irq) | |||
372 | kstat_incr_irqs_this_cpu(irq, desc); | 378 | kstat_incr_irqs_this_cpu(irq, desc); |
373 | 379 | ||
374 | action = desc->action; | 380 | action = desc->action; |
375 | if (unlikely(!action || (desc->istate & IRQS_DISABLED))) | 381 | if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) |
376 | goto out_unlock; | 382 | goto out_unlock; |
377 | 383 | ||
378 | irq_compat_set_progress(desc); | 384 | irq_compat_set_progress(desc); |
379 | desc->istate |= IRQS_INPROGRESS; | 385 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
380 | raw_spin_unlock_irq(&desc->lock); | 386 | raw_spin_unlock_irq(&desc->lock); |
381 | 387 | ||
382 | action_ret = action->thread_fn(action->irq, action->dev_id); | 388 | action_ret = action->thread_fn(action->irq, action->dev_id); |
@@ -384,7 +390,7 @@ void handle_nested_irq(unsigned int irq) | |||
384 | note_interrupt(irq, desc, action_ret); | 390 | note_interrupt(irq, desc, action_ret); |
385 | 391 | ||
386 | raw_spin_lock_irq(&desc->lock); | 392 | raw_spin_lock_irq(&desc->lock); |
387 | desc->istate &= ~IRQS_INPROGRESS; | 393 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
388 | irq_compat_clr_progress(desc); | 394 | irq_compat_clr_progress(desc); |
389 | 395 | ||
390 | out_unlock: | 396 | out_unlock: |
@@ -416,14 +422,14 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
416 | { | 422 | { |
417 | raw_spin_lock(&desc->lock); | 423 | raw_spin_lock(&desc->lock); |
418 | 424 | ||
419 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 425 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
420 | if (!irq_check_poll(desc)) | 426 | if (!irq_check_poll(desc)) |
421 | goto out_unlock; | 427 | goto out_unlock; |
422 | 428 | ||
423 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | 429 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); |
424 | kstat_incr_irqs_this_cpu(irq, desc); | 430 | kstat_incr_irqs_this_cpu(irq, desc); |
425 | 431 | ||
426 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) | 432 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
427 | goto out_unlock; | 433 | goto out_unlock; |
428 | 434 | ||
429 | handle_irq_event(desc); | 435 | handle_irq_event(desc); |
@@ -448,7 +454,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
448 | raw_spin_lock(&desc->lock); | 454 | raw_spin_lock(&desc->lock); |
449 | mask_ack_irq(desc); | 455 | mask_ack_irq(desc); |
450 | 456 | ||
451 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 457 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
452 | if (!irq_check_poll(desc)) | 458 | if (!irq_check_poll(desc)) |
453 | goto out_unlock; | 459 | goto out_unlock; |
454 | 460 | ||
@@ -459,12 +465,12 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
459 | * If its disabled or no action available | 465 | * If its disabled or no action available |
460 | * keep it masked and get out of here | 466 | * keep it masked and get out of here |
461 | */ | 467 | */ |
462 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) | 468 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) |
463 | goto out_unlock; | 469 | goto out_unlock; |
464 | 470 | ||
465 | handle_irq_event(desc); | 471 | handle_irq_event(desc); |
466 | 472 | ||
467 | if (!(desc->istate & (IRQS_DISABLED | IRQS_ONESHOT))) | 473 | if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) |
468 | unmask_irq(desc); | 474 | unmask_irq(desc); |
469 | out_unlock: | 475 | out_unlock: |
470 | raw_spin_unlock(&desc->lock); | 476 | raw_spin_unlock(&desc->lock); |
@@ -496,7 +502,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
496 | { | 502 | { |
497 | raw_spin_lock(&desc->lock); | 503 | raw_spin_lock(&desc->lock); |
498 | 504 | ||
499 | if (unlikely(desc->istate & IRQS_INPROGRESS)) | 505 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
500 | if (!irq_check_poll(desc)) | 506 | if (!irq_check_poll(desc)) |
501 | goto out; | 507 | goto out; |
502 | 508 | ||
@@ -507,7 +513,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
507 | * If its disabled or no action available | 513 | * If its disabled or no action available |
508 | * then mask it and get out of here: | 514 | * then mask it and get out of here: |
509 | */ | 515 | */ |
510 | if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) { | 516 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { |
511 | irq_compat_set_pending(desc); | 517 | irq_compat_set_pending(desc); |
512 | desc->istate |= IRQS_PENDING; | 518 | desc->istate |= IRQS_PENDING; |
513 | mask_irq(desc); | 519 | mask_irq(desc); |
@@ -558,8 +564,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
558 | * we shouldn't process the IRQ. Mark it pending, handle | 564 | * we shouldn't process the IRQ. Mark it pending, handle |
559 | * the necessary masking and go out | 565 | * the necessary masking and go out |
560 | */ | 566 | */ |
561 | if (unlikely((desc->istate & (IRQS_DISABLED | IRQS_INPROGRESS) || | 567 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || |
562 | !desc->action))) { | 568 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { |
563 | if (!irq_check_poll(desc)) { | 569 | if (!irq_check_poll(desc)) { |
564 | irq_compat_set_pending(desc); | 570 | irq_compat_set_pending(desc); |
565 | desc->istate |= IRQS_PENDING; | 571 | desc->istate |= IRQS_PENDING; |
@@ -584,20 +590,65 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
584 | * Renable it, if it was not disabled in meantime. | 590 | * Renable it, if it was not disabled in meantime. |
585 | */ | 591 | */ |
586 | if (unlikely(desc->istate & IRQS_PENDING)) { | 592 | if (unlikely(desc->istate & IRQS_PENDING)) { |
587 | if (!(desc->istate & IRQS_DISABLED) && | 593 | if (!irqd_irq_disabled(&desc->irq_data) && |
588 | (desc->istate & IRQS_MASKED)) | 594 | irqd_irq_masked(&desc->irq_data)) |
589 | unmask_irq(desc); | 595 | unmask_irq(desc); |
590 | } | 596 | } |
591 | 597 | ||
592 | handle_irq_event(desc); | 598 | handle_irq_event(desc); |
593 | 599 | ||
594 | } while ((desc->istate & IRQS_PENDING) && | 600 | } while ((desc->istate & IRQS_PENDING) && |
595 | !(desc->istate & IRQS_DISABLED)); | 601 | !irqd_irq_disabled(&desc->irq_data)); |
596 | 602 | ||
597 | out_unlock: | 603 | out_unlock: |
598 | raw_spin_unlock(&desc->lock); | 604 | raw_spin_unlock(&desc->lock); |
599 | } | 605 | } |
600 | 606 | ||
607 | #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER | ||
608 | /** | ||
609 | * handle_edge_eoi_irq - edge eoi type IRQ handler | ||
610 | * @irq: the interrupt number | ||
611 | * @desc: the interrupt description structure for this irq | ||
612 | * | ||
613 | * Similar as the above handle_edge_irq, but using eoi and w/o the | ||
614 | * mask/unmask logic. | ||
615 | */ | ||
616 | void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc) | ||
617 | { | ||
618 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
619 | |||
620 | raw_spin_lock(&desc->lock); | ||
621 | |||
622 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
623 | /* | ||
624 | * If we're currently running this IRQ, or its disabled, | ||
625 | * we shouldn't process the IRQ. Mark it pending, handle | ||
626 | * the necessary masking and go out | ||
627 | */ | ||
628 | if (unlikely(irqd_irq_disabled(&desc->irq_data) || | ||
629 | irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { | ||
630 | if (!irq_check_poll(desc)) { | ||
631 | desc->istate |= IRQS_PENDING; | ||
632 | goto out_eoi; | ||
633 | } | ||
634 | } | ||
635 | kstat_incr_irqs_this_cpu(irq, desc); | ||
636 | |||
637 | do { | ||
638 | if (unlikely(!desc->action)) | ||
639 | goto out_eoi; | ||
640 | |||
641 | handle_irq_event(desc); | ||
642 | |||
643 | } while ((desc->istate & IRQS_PENDING) && | ||
644 | !irqd_irq_disabled(&desc->irq_data)); | ||
645 | |||
646 | out_unlock: | ||
647 | chip->irq_eoi(&desc->irq_data); | ||
648 | raw_spin_unlock(&desc->lock); | ||
649 | } | ||
650 | #endif | ||
651 | |||
601 | /** | 652 | /** |
602 | * handle_percpu_irq - Per CPU local irq handler | 653 | * handle_percpu_irq - Per CPU local irq handler |
603 | * @irq: the interrupt number | 654 | * @irq: the interrupt number |
@@ -642,8 +693,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
642 | if (handle == handle_bad_irq) { | 693 | if (handle == handle_bad_irq) { |
643 | if (desc->irq_data.chip != &no_irq_chip) | 694 | if (desc->irq_data.chip != &no_irq_chip) |
644 | mask_ack_irq(desc); | 695 | mask_ack_irq(desc); |
645 | irq_compat_set_disabled(desc); | 696 | irq_state_set_disabled(desc); |
646 | desc->istate |= IRQS_DISABLED; | ||
647 | desc->depth = 1; | 697 | desc->depth = 1; |
648 | } | 698 | } |
649 | desc->handle_irq = handle; | 699 | desc->handle_irq = handle; |
@@ -684,8 +734,70 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | |||
684 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | 734 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
685 | if (irq_settings_can_move_pcntxt(desc)) | 735 | if (irq_settings_can_move_pcntxt(desc)) |
686 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); | 736 | irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); |
737 | if (irq_settings_is_level(desc)) | ||
738 | irqd_set(&desc->irq_data, IRQD_LEVEL); | ||
687 | 739 | ||
688 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); | 740 | irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); |
689 | 741 | ||
690 | irq_put_desc_unlock(desc, flags); | 742 | irq_put_desc_unlock(desc, flags); |
691 | } | 743 | } |
744 | |||
745 | /** | ||
746 | * irq_cpu_online - Invoke all irq_cpu_online functions. | ||
747 | * | ||
748 | * Iterate through all irqs and invoke the chip.irq_cpu_online() | ||
749 | * for each. | ||
750 | */ | ||
751 | void irq_cpu_online(void) | ||
752 | { | ||
753 | struct irq_desc *desc; | ||
754 | struct irq_chip *chip; | ||
755 | unsigned long flags; | ||
756 | unsigned int irq; | ||
757 | |||
758 | for_each_active_irq(irq) { | ||
759 | desc = irq_to_desc(irq); | ||
760 | if (!desc) | ||
761 | continue; | ||
762 | |||
763 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
764 | |||
765 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
766 | if (chip && chip->irq_cpu_online && | ||
767 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || | ||
768 | !irqd_irq_disabled(&desc->irq_data))) | ||
769 | chip->irq_cpu_online(&desc->irq_data); | ||
770 | |||
771 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | /** | ||
776 | * irq_cpu_offline - Invoke all irq_cpu_offline functions. | ||
777 | * | ||
778 | * Iterate through all irqs and invoke the chip.irq_cpu_offline() | ||
779 | * for each. | ||
780 | */ | ||
781 | void irq_cpu_offline(void) | ||
782 | { | ||
783 | struct irq_desc *desc; | ||
784 | struct irq_chip *chip; | ||
785 | unsigned long flags; | ||
786 | unsigned int irq; | ||
787 | |||
788 | for_each_active_irq(irq) { | ||
789 | desc = irq_to_desc(irq); | ||
790 | if (!desc) | ||
791 | continue; | ||
792 | |||
793 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
794 | |||
795 | chip = irq_data_get_irq_chip(&desc->irq_data); | ||
796 | if (chip && chip->irq_cpu_offline && | ||
797 | (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) || | ||
798 | !irqd_irq_disabled(&desc->irq_data))) | ||
799 | chip->irq_cpu_offline(&desc->irq_data); | ||
800 | |||
801 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
802 | } | ||
803 | } | ||
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h index d1a33b7fa61d..a0bd875ba3d5 100644 --- a/kernel/irq/debug.h +++ b/kernel/irq/debug.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | #define P(f) if (desc->status & f) printk("%14s set\n", #f) | 7 | #define P(f) if (desc->status & f) printk("%14s set\n", #f) |
8 | #define PS(f) if (desc->istate & f) printk("%14s set\n", #f) | 8 | #define PS(f) if (desc->istate & f) printk("%14s set\n", #f) |
9 | /* FIXME */ | ||
10 | #define PD(f) do { } while (0) | ||
9 | 11 | ||
10 | static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | 12 | static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) |
11 | { | 13 | { |
@@ -28,13 +30,15 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | |||
28 | P(IRQ_NOAUTOEN); | 30 | P(IRQ_NOAUTOEN); |
29 | 31 | ||
30 | PS(IRQS_AUTODETECT); | 32 | PS(IRQS_AUTODETECT); |
31 | PS(IRQS_INPROGRESS); | ||
32 | PS(IRQS_REPLAY); | 33 | PS(IRQS_REPLAY); |
33 | PS(IRQS_WAITING); | 34 | PS(IRQS_WAITING); |
34 | PS(IRQS_DISABLED); | ||
35 | PS(IRQS_PENDING); | 35 | PS(IRQS_PENDING); |
36 | PS(IRQS_MASKED); | 36 | |
37 | PD(IRQS_INPROGRESS); | ||
38 | PD(IRQS_DISABLED); | ||
39 | PD(IRQS_MASKED); | ||
37 | } | 40 | } |
38 | 41 | ||
39 | #undef P | 42 | #undef P |
40 | #undef PS | 43 | #undef PS |
44 | #undef PD | ||
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 517561fc7317..1a2fb77f2fd6 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -178,25 +178,13 @@ irqreturn_t handle_irq_event(struct irq_desc *desc) | |||
178 | irq_compat_clr_pending(desc); | 178 | irq_compat_clr_pending(desc); |
179 | desc->istate &= ~IRQS_PENDING; | 179 | desc->istate &= ~IRQS_PENDING; |
180 | irq_compat_set_progress(desc); | 180 | irq_compat_set_progress(desc); |
181 | desc->istate |= IRQS_INPROGRESS; | 181 | irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
182 | raw_spin_unlock(&desc->lock); | 182 | raw_spin_unlock(&desc->lock); |
183 | 183 | ||
184 | ret = handle_irq_event_percpu(desc, action); | 184 | ret = handle_irq_event_percpu(desc, action); |
185 | 185 | ||
186 | raw_spin_lock(&desc->lock); | 186 | raw_spin_lock(&desc->lock); |
187 | desc->istate &= ~IRQS_INPROGRESS; | 187 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
188 | irq_compat_clr_progress(desc); | 188 | irq_compat_clr_progress(desc); |
189 | return ret; | 189 | return ret; |
190 | } | 190 | } |
191 | |||
192 | /** | ||
193 | * handle_IRQ_event - irq action chain handler | ||
194 | * @irq: the interrupt number | ||
195 | * @action: the interrupt action chain for this irq | ||
196 | * | ||
197 | * Handles the action chain of an irq event | ||
198 | */ | ||
199 | irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | ||
200 | { | ||
201 | return handle_irq_event_percpu(irq_to_desc(irq), action); | ||
202 | } | ||
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 6c6ec9a49027..6b8b9713e28d 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -44,26 +44,20 @@ enum { | |||
44 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt | 44 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt |
45 | * detection | 45 | * detection |
46 | * IRQS_POLL_INPROGRESS - polling in progress | 46 | * IRQS_POLL_INPROGRESS - polling in progress |
47 | * IRQS_INPROGRESS - Interrupt in progress | ||
48 | * IRQS_ONESHOT - irq is not unmasked in primary handler | 47 | * IRQS_ONESHOT - irq is not unmasked in primary handler |
49 | * IRQS_REPLAY - irq is replayed | 48 | * IRQS_REPLAY - irq is replayed |
50 | * IRQS_WAITING - irq is waiting | 49 | * IRQS_WAITING - irq is waiting |
51 | * IRQS_DISABLED - irq is disabled | ||
52 | * IRQS_PENDING - irq is pending and replayed later | 50 | * IRQS_PENDING - irq is pending and replayed later |
53 | * IRQS_MASKED - irq is masked | ||
54 | * IRQS_SUSPENDED - irq is suspended | 51 | * IRQS_SUSPENDED - irq is suspended |
55 | */ | 52 | */ |
56 | enum { | 53 | enum { |
57 | IRQS_AUTODETECT = 0x00000001, | 54 | IRQS_AUTODETECT = 0x00000001, |
58 | IRQS_SPURIOUS_DISABLED = 0x00000002, | 55 | IRQS_SPURIOUS_DISABLED = 0x00000002, |
59 | IRQS_POLL_INPROGRESS = 0x00000008, | 56 | IRQS_POLL_INPROGRESS = 0x00000008, |
60 | IRQS_INPROGRESS = 0x00000010, | ||
61 | IRQS_ONESHOT = 0x00000020, | 57 | IRQS_ONESHOT = 0x00000020, |
62 | IRQS_REPLAY = 0x00000040, | 58 | IRQS_REPLAY = 0x00000040, |
63 | IRQS_WAITING = 0x00000080, | 59 | IRQS_WAITING = 0x00000080, |
64 | IRQS_DISABLED = 0x00000100, | ||
65 | IRQS_PENDING = 0x00000200, | 60 | IRQS_PENDING = 0x00000200, |
66 | IRQS_MASKED = 0x00000400, | ||
67 | IRQS_SUSPENDED = 0x00000800, | 61 | IRQS_SUSPENDED = 0x00000800, |
68 | }; | 62 | }; |
69 | 63 | ||
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 6fb014f172f7..2c039c9b9383 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -80,7 +80,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | |||
80 | desc->irq_data.handler_data = NULL; | 80 | desc->irq_data.handler_data = NULL; |
81 | desc->irq_data.msi_desc = NULL; | 81 | desc->irq_data.msi_desc = NULL; |
82 | irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); | 82 | irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); |
83 | desc->istate = IRQS_DISABLED; | 83 | irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); |
84 | desc->handle_irq = handle_bad_irq; | 84 | desc->handle_irq = handle_bad_irq; |
85 | desc->depth = 1; | 85 | desc->depth = 1; |
86 | desc->irq_count = 0; | 86 | desc->irq_count = 0; |
@@ -238,7 +238,6 @@ int __init early_irq_init(void) | |||
238 | 238 | ||
239 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 239 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
240 | [0 ... NR_IRQS-1] = { | 240 | [0 ... NR_IRQS-1] = { |
241 | .istate = IRQS_DISABLED, | ||
242 | .handle_irq = handle_bad_irq, | 241 | .handle_irq = handle_bad_irq, |
243 | .depth = 1, | 242 | .depth = 1, |
244 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), | 243 | .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a2aa73e536c..acf540768b8f 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -41,7 +41,7 @@ early_param("threadirqs", setup_forced_irqthreads); | |||
41 | void synchronize_irq(unsigned int irq) | 41 | void synchronize_irq(unsigned int irq) |
42 | { | 42 | { |
43 | struct irq_desc *desc = irq_to_desc(irq); | 43 | struct irq_desc *desc = irq_to_desc(irq); |
44 | unsigned int state; | 44 | bool inprogress; |
45 | 45 | ||
46 | if (!desc) | 46 | if (!desc) |
47 | return; | 47 | return; |
@@ -53,16 +53,16 @@ void synchronize_irq(unsigned int irq) | |||
53 | * Wait until we're out of the critical section. This might | 53 | * Wait until we're out of the critical section. This might |
54 | * give the wrong answer due to the lack of memory barriers. | 54 | * give the wrong answer due to the lack of memory barriers. |
55 | */ | 55 | */ |
56 | while (desc->istate & IRQS_INPROGRESS) | 56 | while (irqd_irq_inprogress(&desc->irq_data)) |
57 | cpu_relax(); | 57 | cpu_relax(); |
58 | 58 | ||
59 | /* Ok, that indicated we're done: double-check carefully. */ | 59 | /* Ok, that indicated we're done: double-check carefully. */ |
60 | raw_spin_lock_irqsave(&desc->lock, flags); | 60 | raw_spin_lock_irqsave(&desc->lock, flags); |
61 | state = desc->istate; | 61 | inprogress = irqd_irq_inprogress(&desc->irq_data); |
62 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 62 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
63 | 63 | ||
64 | /* Oops, that failed? */ | 64 | /* Oops, that failed? */ |
65 | } while (state & IRQS_INPROGRESS); | 65 | } while (inprogress); |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * We made sure that no hardirq handler is running. Now verify | 68 | * We made sure that no hardirq handler is running. Now verify |
@@ -112,13 +112,13 @@ void irq_set_thread_affinity(struct irq_desc *desc) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 114 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
115 | static inline bool irq_can_move_pcntxt(struct irq_desc *desc) | 115 | static inline bool irq_can_move_pcntxt(struct irq_data *data) |
116 | { | 116 | { |
117 | return irq_settings_can_move_pcntxt(desc); | 117 | return irqd_can_move_in_process_context(data); |
118 | } | 118 | } |
119 | static inline bool irq_move_pending(struct irq_desc *desc) | 119 | static inline bool irq_move_pending(struct irq_data *data) |
120 | { | 120 | { |
121 | return irqd_is_setaffinity_pending(&desc->irq_data); | 121 | return irqd_is_setaffinity_pending(data); |
122 | } | 122 | } |
123 | static inline void | 123 | static inline void |
124 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) | 124 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) |
@@ -131,43 +131,34 @@ irq_get_pending(struct cpumask *mask, struct irq_desc *desc) | |||
131 | cpumask_copy(mask, desc->pending_mask); | 131 | cpumask_copy(mask, desc->pending_mask); |
132 | } | 132 | } |
133 | #else | 133 | #else |
134 | static inline bool irq_can_move_pcntxt(struct irq_desc *desc) { return true; } | 134 | static inline bool irq_can_move_pcntxt(struct irq_data *data) { return true; } |
135 | static inline bool irq_move_pending(struct irq_desc *desc) { return false; } | 135 | static inline bool irq_move_pending(struct irq_desc *data) { return false; } |
136 | static inline void | 136 | static inline void |
137 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { } | 137 | irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { } |
138 | static inline void | 138 | static inline void |
139 | irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { } | 139 | irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { } |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | /** | 142 | int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) |
143 | * irq_set_affinity - Set the irq affinity of a given irq | ||
144 | * @irq: Interrupt to set affinity | ||
145 | * @cpumask: cpumask | ||
146 | * | ||
147 | */ | ||
148 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
149 | { | 143 | { |
150 | struct irq_desc *desc = irq_to_desc(irq); | 144 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
151 | struct irq_chip *chip = desc->irq_data.chip; | 145 | struct irq_desc *desc = irq_data_to_desc(data); |
152 | unsigned long flags; | ||
153 | int ret = 0; | 146 | int ret = 0; |
154 | 147 | ||
155 | if (!chip->irq_set_affinity) | 148 | if (!chip || !chip->irq_set_affinity) |
156 | return -EINVAL; | 149 | return -EINVAL; |
157 | 150 | ||
158 | raw_spin_lock_irqsave(&desc->lock, flags); | 151 | if (irq_can_move_pcntxt(data)) { |
159 | 152 | ret = chip->irq_set_affinity(data, mask, false); | |
160 | if (irq_can_move_pcntxt(desc)) { | ||
161 | ret = chip->irq_set_affinity(&desc->irq_data, mask, false); | ||
162 | switch (ret) { | 153 | switch (ret) { |
163 | case IRQ_SET_MASK_OK: | 154 | case IRQ_SET_MASK_OK: |
164 | cpumask_copy(desc->irq_data.affinity, mask); | 155 | cpumask_copy(data->affinity, mask); |
165 | case IRQ_SET_MASK_OK_NOCOPY: | 156 | case IRQ_SET_MASK_OK_NOCOPY: |
166 | irq_set_thread_affinity(desc); | 157 | irq_set_thread_affinity(desc); |
167 | ret = 0; | 158 | ret = 0; |
168 | } | 159 | } |
169 | } else { | 160 | } else { |
170 | irqd_set_move_pending(&desc->irq_data); | 161 | irqd_set_move_pending(data); |
171 | irq_copy_pending(desc, mask); | 162 | irq_copy_pending(desc, mask); |
172 | } | 163 | } |
173 | 164 | ||
@@ -176,7 +167,28 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
176 | schedule_work(&desc->affinity_notify->work); | 167 | schedule_work(&desc->affinity_notify->work); |
177 | } | 168 | } |
178 | irq_compat_set_affinity(desc); | 169 | irq_compat_set_affinity(desc); |
179 | irqd_set(&desc->irq_data, IRQD_AFFINITY_SET); | 170 | irqd_set(data, IRQD_AFFINITY_SET); |
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * irq_set_affinity - Set the irq affinity of a given irq | ||
177 | * @irq: Interrupt to set affinity | ||
178 | * @mask: cpumask | ||
179 | * | ||
180 | */ | ||
181 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
182 | { | ||
183 | struct irq_desc *desc = irq_to_desc(irq); | ||
184 | unsigned long flags; | ||
185 | int ret; | ||
186 | |||
187 | if (!desc) | ||
188 | return -EINVAL; | ||
189 | |||
190 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
191 | ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); | ||
180 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 192 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
181 | return ret; | 193 | return ret; |
182 | } | 194 | } |
@@ -206,7 +218,7 @@ static void irq_affinity_notify(struct work_struct *work) | |||
206 | goto out; | 218 | goto out; |
207 | 219 | ||
208 | raw_spin_lock_irqsave(&desc->lock, flags); | 220 | raw_spin_lock_irqsave(&desc->lock, flags); |
209 | if (irq_move_pending(desc)) | 221 | if (irq_move_pending(&desc->irq_data)) |
210 | irq_get_pending(cpumask, desc); | 222 | irq_get_pending(cpumask, desc); |
211 | else | 223 | else |
212 | cpumask_copy(cpumask, desc->irq_data.affinity); | 224 | cpumask_copy(cpumask, desc->irq_data.affinity); |
@@ -551,9 +563,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
551 | flags &= IRQ_TYPE_SENSE_MASK; | 563 | flags &= IRQ_TYPE_SENSE_MASK; |
552 | 564 | ||
553 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { | 565 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { |
554 | if (!(desc->istate & IRQS_MASKED)) | 566 | if (!irqd_irq_masked(&desc->irq_data)) |
555 | mask_irq(desc); | 567 | mask_irq(desc); |
556 | if (!(desc->istate & IRQS_DISABLED)) | 568 | if (!irqd_irq_disabled(&desc->irq_data)) |
557 | unmask = 1; | 569 | unmask = 1; |
558 | } | 570 | } |
559 | 571 | ||
@@ -651,7 +663,7 @@ again: | |||
651 | * irq_wake_thread(). See the comment there which explains the | 663 | * irq_wake_thread(). See the comment there which explains the |
652 | * serialization. | 664 | * serialization. |
653 | */ | 665 | */ |
654 | if (unlikely(desc->istate & IRQS_INPROGRESS)) { | 666 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) { |
655 | raw_spin_unlock_irq(&desc->lock); | 667 | raw_spin_unlock_irq(&desc->lock); |
656 | chip_bus_sync_unlock(desc); | 668 | chip_bus_sync_unlock(desc); |
657 | cpu_relax(); | 669 | cpu_relax(); |
@@ -668,12 +680,10 @@ again: | |||
668 | 680 | ||
669 | desc->threads_oneshot &= ~action->thread_mask; | 681 | desc->threads_oneshot &= ~action->thread_mask; |
670 | 682 | ||
671 | if (!desc->threads_oneshot && !(desc->istate & IRQS_DISABLED) && | 683 | if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && |
672 | (desc->istate & IRQS_MASKED)) { | 684 | irqd_irq_masked(&desc->irq_data)) |
673 | irq_compat_clr_masked(desc); | 685 | unmask_irq(desc); |
674 | desc->istate &= ~IRQS_MASKED; | 686 | |
675 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
676 | } | ||
677 | out_unlock: | 687 | out_unlock: |
678 | raw_spin_unlock_irq(&desc->lock); | 688 | raw_spin_unlock_irq(&desc->lock); |
679 | chip_bus_sync_unlock(desc); | 689 | chip_bus_sync_unlock(desc); |
@@ -767,7 +777,7 @@ static int irq_thread(void *data) | |||
767 | atomic_inc(&desc->threads_active); | 777 | atomic_inc(&desc->threads_active); |
768 | 778 | ||
769 | raw_spin_lock_irq(&desc->lock); | 779 | raw_spin_lock_irq(&desc->lock); |
770 | if (unlikely(desc->istate & IRQS_DISABLED)) { | 780 | if (unlikely(irqd_irq_disabled(&desc->irq_data))) { |
771 | /* | 781 | /* |
772 | * CHECKME: We might need a dedicated | 782 | * CHECKME: We might need a dedicated |
773 | * IRQ_THREAD_PENDING flag here, which | 783 | * IRQ_THREAD_PENDING flag here, which |
@@ -985,8 +995,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
985 | } | 995 | } |
986 | 996 | ||
987 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ | 997 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ |
988 | IRQS_INPROGRESS | IRQS_ONESHOT | \ | 998 | IRQS_ONESHOT | IRQS_WAITING); |
989 | IRQS_WAITING); | 999 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
990 | 1000 | ||
991 | if (new->flags & IRQF_PERCPU) { | 1001 | if (new->flags & IRQF_PERCPU) { |
992 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | 1002 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index ec4806d4778b..e33d9c8d5089 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -60,13 +60,12 @@ void move_masked_irq(int irq) | |||
60 | 60 | ||
61 | void irq_move_irq(struct irq_data *idata) | 61 | void irq_move_irq(struct irq_data *idata) |
62 | { | 62 | { |
63 | struct irq_desc *desc = irq_data_to_desc(idata); | ||
64 | bool masked; | 63 | bool masked; |
65 | 64 | ||
66 | if (likely(!irqd_is_setaffinity_pending(idata))) | 65 | if (likely(!irqd_is_setaffinity_pending(idata))) |
67 | return; | 66 | return; |
68 | 67 | ||
69 | if (unlikely(desc->istate & IRQS_DISABLED)) | 68 | if (unlikely(irqd_irq_disabled(idata))) |
70 | return; | 69 | return; |
71 | 70 | ||
72 | /* | 71 | /* |
@@ -74,7 +73,7 @@ void irq_move_irq(struct irq_data *idata) | |||
74 | * threaded interrupt with ONESHOT set, we can end up with an | 73 | * threaded interrupt with ONESHOT set, we can end up with an |
75 | * interrupt storm. | 74 | * interrupt storm. |
76 | */ | 75 | */ |
77 | masked = desc->istate & IRQS_MASKED; | 76 | masked = irqd_irq_masked(idata); |
78 | if (!masked) | 77 | if (!masked) |
79 | idata->chip->irq_mask(idata); | 78 | idata->chip->irq_mask(idata); |
80 | irq_move_masked_irq(idata); | 79 | irq_move_masked_irq(idata); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dd586ebf9c8c..83f4799f46be 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -45,12 +45,12 @@ bool irq_wait_for_poll(struct irq_desc *desc) | |||
45 | #ifdef CONFIG_SMP | 45 | #ifdef CONFIG_SMP |
46 | do { | 46 | do { |
47 | raw_spin_unlock(&desc->lock); | 47 | raw_spin_unlock(&desc->lock); |
48 | while (desc->istate & IRQS_INPROGRESS) | 48 | while (irqd_irq_inprogress(&desc->irq_data)) |
49 | cpu_relax(); | 49 | cpu_relax(); |
50 | raw_spin_lock(&desc->lock); | 50 | raw_spin_lock(&desc->lock); |
51 | } while (desc->istate & IRQS_INPROGRESS); | 51 | } while (irqd_irq_inprogress(&desc->irq_data)); |
52 | /* Might have been disabled in meantime */ | 52 | /* Might have been disabled in meantime */ |
53 | return !(desc->istate & IRQS_DISABLED) && desc->action; | 53 | return !irqd_irq_disabled(&desc->irq_data) && desc->action; |
54 | #else | 54 | #else |
55 | return false; | 55 | return false; |
56 | #endif | 56 | #endif |
@@ -75,7 +75,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
75 | * Do not poll disabled interrupts unless the spurious | 75 | * Do not poll disabled interrupts unless the spurious |
76 | * disabled poller asks explicitely. | 76 | * disabled poller asks explicitely. |
77 | */ | 77 | */ |
78 | if ((desc->istate & IRQS_DISABLED) && !force) | 78 | if (irqd_irq_disabled(&desc->irq_data) && !force) |
79 | goto out; | 79 | goto out; |
80 | 80 | ||
81 | /* | 81 | /* |
@@ -88,7 +88,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
88 | goto out; | 88 | goto out; |
89 | 89 | ||
90 | /* Already running on another processor */ | 90 | /* Already running on another processor */ |
91 | if (desc->istate & IRQS_INPROGRESS) { | 91 | if (irqd_irq_inprogress(&desc->irq_data)) { |
92 | /* | 92 | /* |
93 | * Already running: If it is shared get the other | 93 | * Already running: If it is shared get the other |
94 | * CPU to go looking for our mystery interrupt too | 94 | * CPU to go looking for our mystery interrupt too |