diff options
| author | David Daney <ddaney@caviumnetworks.com> | 2011-03-25 15:38:50 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2011-03-27 11:45:59 -0400 |
| commit | c2d0c555c22242c3a76e366074c4d83ef9fa3b8c (patch) | |
| tree | 7426945b566129163639229fa0a5f420cdce13a8 /kernel/irq | |
| parent | b3d422329f2e061d66af4f933ef316e50e5edcac (diff) | |
genirq: Split irq_set_affinity() so it can be called with lock held.
The .irq_cpu_online() and .irq_cpu_offline() functions may need to
adjust affinity, but they are called with the descriptor lock held.
Create __irq_set_affinity_locked() which is called with the lock held.
Make irq_set_affinity() just a wrapper that acquires the lock.
[ tglx: Changed the argument to irq_data, added a !desc check and
moved the !irq_set_affinity check where it belongs ]
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Cc: ralf@linux-mips.org
LKML-Reference: <1301081931-11240-4-git-send-email-ddaney@caviumnetworks.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq')
| -rw-r--r-- | kernel/irq/manage.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a2aa73e536c..3d151fd762ad 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -139,35 +139,26 @@ 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 (irqd_can_move_in_process_context(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 | * @cpumask: 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 | } |
