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 | |
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>
-rw-r--r-- | include/linux/irq.h | 1 | ||||
-rw-r--r-- | kernel/irq/manage.c | 48 |
2 files changed, 31 insertions, 18 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 76e948fa88f8..a10717e1c1f3 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -382,6 +382,7 @@ extern void remove_irq(unsigned int irq, struct irqaction *act); | |||
382 | 382 | ||
383 | extern void irq_cpu_online(void); | 383 | extern void irq_cpu_online(void); |
384 | extern void irq_cpu_offline(void); | 384 | extern void irq_cpu_offline(void); |
385 | extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask); | ||
385 | 386 | ||
386 | #ifdef CONFIG_GENERIC_HARDIRQS | 387 | #ifdef CONFIG_GENERIC_HARDIRQS |
387 | 388 | ||
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 | } |