diff options
Diffstat (limited to 'kernel/irq/manage.c')
| -rw-r--r-- | kernel/irq/manage.c | 102 |
1 files changed, 52 insertions, 50 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a2aa73e536c..12a80fdae11c 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_data *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 | ||
| @@ -175,8 +166,28 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
| 175 | kref_get(&desc->affinity_notify->kref); | 166 | kref_get(&desc->affinity_notify->kref); |
| 176 | schedule_work(&desc->affinity_notify->work); | 167 | schedule_work(&desc->affinity_notify->work); |
| 177 | } | 168 | } |
| 178 | irq_compat_set_affinity(desc); | 169 | irqd_set(data, IRQD_AFFINITY_SET); |
| 179 | irqd_set(&desc->irq_data, IRQD_AFFINITY_SET); | 170 | |
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | /** | ||
| 175 | * irq_set_affinity - Set the irq affinity of a given irq | ||
| 176 | * @irq: Interrupt to set affinity | ||
| 177 | * @mask: cpumask | ||
| 178 | * | ||
| 179 | */ | ||
| 180 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
| 181 | { | ||
| 182 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 183 | unsigned long flags; | ||
| 184 | int ret; | ||
| 185 | |||
| 186 | if (!desc) | ||
| 187 | return -EINVAL; | ||
| 188 | |||
| 189 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 190 | ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); | ||
| 180 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 191 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 181 | return ret; | 192 | return ret; |
| 182 | } | 193 | } |
| @@ -206,7 +217,7 @@ static void irq_affinity_notify(struct work_struct *work) | |||
| 206 | goto out; | 217 | goto out; |
| 207 | 218 | ||
| 208 | raw_spin_lock_irqsave(&desc->lock, flags); | 219 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 209 | if (irq_move_pending(desc)) | 220 | if (irq_move_pending(&desc->irq_data)) |
| 210 | irq_get_pending(cpumask, desc); | 221 | irq_get_pending(cpumask, desc); |
| 211 | else | 222 | else |
| 212 | cpumask_copy(cpumask, desc->irq_data.affinity); | 223 | cpumask_copy(cpumask, desc->irq_data.affinity); |
| @@ -285,10 +296,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask) | |||
| 285 | if (cpumask_intersects(desc->irq_data.affinity, | 296 | if (cpumask_intersects(desc->irq_data.affinity, |
| 286 | cpu_online_mask)) | 297 | cpu_online_mask)) |
| 287 | set = desc->irq_data.affinity; | 298 | set = desc->irq_data.affinity; |
| 288 | else { | 299 | else |
| 289 | irq_compat_clr_affinity(desc); | ||
| 290 | irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET); | 300 | irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET); |
| 291 | } | ||
| 292 | } | 301 | } |
| 293 | 302 | ||
| 294 | cpumask_and(mask, cpu_online_mask, set); | 303 | cpumask_and(mask, cpu_online_mask, set); |
| @@ -551,9 +560,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 551 | flags &= IRQ_TYPE_SENSE_MASK; | 560 | flags &= IRQ_TYPE_SENSE_MASK; |
| 552 | 561 | ||
| 553 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { | 562 | if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { |
| 554 | if (!(desc->istate & IRQS_MASKED)) | 563 | if (!irqd_irq_masked(&desc->irq_data)) |
| 555 | mask_irq(desc); | 564 | mask_irq(desc); |
| 556 | if (!(desc->istate & IRQS_DISABLED)) | 565 | if (!irqd_irq_disabled(&desc->irq_data)) |
| 557 | unmask = 1; | 566 | unmask = 1; |
| 558 | } | 567 | } |
| 559 | 568 | ||
| @@ -575,8 +584,6 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 575 | irqd_set(&desc->irq_data, IRQD_LEVEL); | 584 | irqd_set(&desc->irq_data, IRQD_LEVEL); |
| 576 | } | 585 | } |
| 577 | 586 | ||
| 578 | if (chip != desc->irq_data.chip) | ||
| 579 | irq_chip_set_defaults(desc->irq_data.chip); | ||
| 580 | ret = 0; | 587 | ret = 0; |
| 581 | break; | 588 | break; |
| 582 | default: | 589 | default: |
| @@ -651,7 +658,7 @@ again: | |||
| 651 | * irq_wake_thread(). See the comment there which explains the | 658 | * irq_wake_thread(). See the comment there which explains the |
| 652 | * serialization. | 659 | * serialization. |
| 653 | */ | 660 | */ |
| 654 | if (unlikely(desc->istate & IRQS_INPROGRESS)) { | 661 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) { |
| 655 | raw_spin_unlock_irq(&desc->lock); | 662 | raw_spin_unlock_irq(&desc->lock); |
| 656 | chip_bus_sync_unlock(desc); | 663 | chip_bus_sync_unlock(desc); |
| 657 | cpu_relax(); | 664 | cpu_relax(); |
| @@ -668,12 +675,10 @@ again: | |||
| 668 | 675 | ||
| 669 | desc->threads_oneshot &= ~action->thread_mask; | 676 | desc->threads_oneshot &= ~action->thread_mask; |
| 670 | 677 | ||
| 671 | if (!desc->threads_oneshot && !(desc->istate & IRQS_DISABLED) && | 678 | if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && |
| 672 | (desc->istate & IRQS_MASKED)) { | 679 | irqd_irq_masked(&desc->irq_data)) |
| 673 | irq_compat_clr_masked(desc); | 680 | unmask_irq(desc); |
| 674 | desc->istate &= ~IRQS_MASKED; | 681 | |
| 675 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | ||
| 676 | } | ||
| 677 | out_unlock: | 682 | out_unlock: |
| 678 | raw_spin_unlock_irq(&desc->lock); | 683 | raw_spin_unlock_irq(&desc->lock); |
| 679 | chip_bus_sync_unlock(desc); | 684 | chip_bus_sync_unlock(desc); |
| @@ -767,7 +772,7 @@ static int irq_thread(void *data) | |||
| 767 | atomic_inc(&desc->threads_active); | 772 | atomic_inc(&desc->threads_active); |
| 768 | 773 | ||
| 769 | raw_spin_lock_irq(&desc->lock); | 774 | raw_spin_lock_irq(&desc->lock); |
| 770 | if (unlikely(desc->istate & IRQS_DISABLED)) { | 775 | if (unlikely(irqd_irq_disabled(&desc->irq_data))) { |
| 771 | /* | 776 | /* |
| 772 | * CHECKME: We might need a dedicated | 777 | * CHECKME: We might need a dedicated |
| 773 | * IRQ_THREAD_PENDING flag here, which | 778 | * IRQ_THREAD_PENDING flag here, which |
| @@ -775,7 +780,6 @@ static int irq_thread(void *data) | |||
| 775 | * but AFAICT IRQS_PENDING should be fine as it | 780 | * but AFAICT IRQS_PENDING should be fine as it |
| 776 | * retriggers the interrupt itself --- tglx | 781 | * retriggers the interrupt itself --- tglx |
| 777 | */ | 782 | */ |
| 778 | irq_compat_set_pending(desc); | ||
| 779 | desc->istate |= IRQS_PENDING; | 783 | desc->istate |= IRQS_PENDING; |
| 780 | raw_spin_unlock_irq(&desc->lock); | 784 | raw_spin_unlock_irq(&desc->lock); |
| 781 | } else { | 785 | } else { |
| @@ -971,8 +975,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 971 | new->thread_mask = 1 << ffz(thread_mask); | 975 | new->thread_mask = 1 << ffz(thread_mask); |
| 972 | 976 | ||
| 973 | if (!shared) { | 977 | if (!shared) { |
| 974 | irq_chip_set_defaults(desc->irq_data.chip); | ||
| 975 | |||
| 976 | init_waitqueue_head(&desc->wait_for_threads); | 978 | init_waitqueue_head(&desc->wait_for_threads); |
| 977 | 979 | ||
| 978 | /* Setup the type (level, edge polarity) if configured: */ | 980 | /* Setup the type (level, edge polarity) if configured: */ |
| @@ -985,8 +987,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 985 | } | 987 | } |
| 986 | 988 | ||
| 987 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ | 989 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ |
| 988 | IRQS_INPROGRESS | IRQS_ONESHOT | \ | 990 | IRQS_ONESHOT | IRQS_WAITING); |
| 989 | IRQS_WAITING); | 991 | irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); |
| 990 | 992 | ||
| 991 | if (new->flags & IRQF_PERCPU) { | 993 | if (new->flags & IRQF_PERCPU) { |
| 992 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | 994 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
