diff options
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 12 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 8 | ||||
-rw-r--r-- | include/linux/interrupt.h | 35 | ||||
-rw-r--r-- | include/linux/irq.h | 3 | ||||
-rw-r--r-- | kernel/irq/manage.c | 17 |
6 files changed, 52 insertions, 25 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index c2bb4f896ce7..3aa5b46b2d40 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
@@ -635,7 +635,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data) | |||
635 | cpumask_clear(&new_affinity); | 635 | cpumask_clear(&new_affinity); |
636 | cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); | 636 | cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); |
637 | } | 637 | } |
638 | __irq_set_affinity_locked(data, &new_affinity); | 638 | irq_set_affinity_locked(data, &new_affinity, false); |
639 | } | 639 | } |
640 | 640 | ||
641 | static int octeon_irq_ciu_set_affinity(struct irq_data *data, | 641 | static int octeon_irq_ciu_set_affinity(struct irq_data *data, |
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index a6ee6d7cd63f..acf5a329d538 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
@@ -416,8 +416,6 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
416 | evt->set_mode = exynos4_tick_set_mode; | 416 | evt->set_mode = exynos4_tick_set_mode; |
417 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 417 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
418 | evt->rating = 450; | 418 | evt->rating = 450; |
419 | clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), | ||
420 | 0xf, 0x7fffffff); | ||
421 | 419 | ||
422 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); | 420 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); |
423 | 421 | ||
@@ -430,9 +428,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
430 | evt->irq); | 428 | evt->irq); |
431 | return -EIO; | 429 | return -EIO; |
432 | } | 430 | } |
431 | irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); | ||
433 | } else { | 432 | } else { |
434 | enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); | 433 | enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); |
435 | } | 434 | } |
435 | clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), | ||
436 | 0xf, 0x7fffffff); | ||
436 | 437 | ||
437 | return 0; | 438 | return 0; |
438 | } | 439 | } |
@@ -450,7 +451,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self, | |||
450 | unsigned long action, void *hcpu) | 451 | unsigned long action, void *hcpu) |
451 | { | 452 | { |
452 | struct mct_clock_event_device *mevt; | 453 | struct mct_clock_event_device *mevt; |
453 | unsigned int cpu; | ||
454 | 454 | ||
455 | /* | 455 | /* |
456 | * Grab cpu pointer in each case to avoid spurious | 456 | * Grab cpu pointer in each case to avoid spurious |
@@ -461,12 +461,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self, | |||
461 | mevt = this_cpu_ptr(&percpu_mct_tick); | 461 | mevt = this_cpu_ptr(&percpu_mct_tick); |
462 | exynos4_local_timer_setup(&mevt->evt); | 462 | exynos4_local_timer_setup(&mevt->evt); |
463 | break; | 463 | break; |
464 | case CPU_ONLINE: | ||
465 | cpu = (unsigned long)hcpu; | ||
466 | if (mct_int_type == MCT_INT_SPI) | ||
467 | irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu], | ||
468 | cpumask_of(cpu)); | ||
469 | break; | ||
470 | case CPU_DYING: | 464 | case CPU_DYING: |
471 | mevt = this_cpu_ptr(&percpu_mct_tick); | 465 | mevt = this_cpu_ptr(&percpu_mct_tick); |
472 | exynos4_local_timer_stop(&mevt->evt); | 466 | exynos4_local_timer_stop(&mevt->evt); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4300b6606f5e..57d165e026f4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -246,10 +246,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
246 | bool force) | 246 | bool force) |
247 | { | 247 | { |
248 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); | 248 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); |
249 | unsigned int shift = (gic_irq(d) % 4) * 8; | 249 | unsigned int cpu, shift = (gic_irq(d) % 4) * 8; |
250 | unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); | ||
251 | u32 val, mask, bit; | 250 | u32 val, mask, bit; |
252 | 251 | ||
252 | if (!force) | ||
253 | cpu = cpumask_any_and(mask_val, cpu_online_mask); | ||
254 | else | ||
255 | cpu = cpumask_first(mask_val); | ||
256 | |||
253 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) | 257 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) |
254 | return -EINVAL; | 258 | return -EINVAL; |
255 | 259 | ||
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c7bfac1c4a7b..8834a7e5b944 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -203,7 +203,40 @@ static inline int check_wakeup_irqs(void) { return 0; } | |||
203 | 203 | ||
204 | extern cpumask_var_t irq_default_affinity; | 204 | extern cpumask_var_t irq_default_affinity; |
205 | 205 | ||
206 | extern int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask); | 206 | /* Internal implementation. Use the helpers below */ |
207 | extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask, | ||
208 | bool force); | ||
209 | |||
210 | /** | ||
211 | * irq_set_affinity - Set the irq affinity of a given irq | ||
212 | * @irq: Interrupt to set affinity | ||
213 | * @mask: cpumask | ||
214 | * | ||
215 | * Fails if cpumask does not contain an online CPU | ||
216 | */ | ||
217 | static inline int | ||
218 | irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | ||
219 | { | ||
220 | return __irq_set_affinity(irq, cpumask, false); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * irq_force_affinity - Force the irq affinity of a given irq | ||
225 | * @irq: Interrupt to set affinity | ||
226 | * @mask: cpumask | ||
227 | * | ||
228 | * Same as irq_set_affinity, but without checking the mask against | ||
229 | * online cpus. | ||
230 | * | ||
231 | * Solely for low level cpu hotplug code, where we need to make per | ||
232 | * cpu interrupts affine before the cpu becomes online. | ||
233 | */ | ||
234 | static inline int | ||
235 | irq_force_affinity(unsigned int irq, const struct cpumask *cpumask) | ||
236 | { | ||
237 | return __irq_set_affinity(irq, cpumask, true); | ||
238 | } | ||
239 | |||
207 | extern int irq_can_set_affinity(unsigned int irq); | 240 | extern int irq_can_set_affinity(unsigned int irq); |
208 | extern int irq_select_affinity(unsigned int irq); | 241 | extern int irq_select_affinity(unsigned int irq); |
209 | 242 | ||
diff --git a/include/linux/irq.h b/include/linux/irq.h index d278838908cb..10a0b1ac4ea0 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -394,7 +394,8 @@ extern void remove_percpu_irq(unsigned int irq, struct irqaction *act); | |||
394 | 394 | ||
395 | extern void irq_cpu_online(void); | 395 | extern void irq_cpu_online(void); |
396 | extern void irq_cpu_offline(void); | 396 | extern void irq_cpu_offline(void); |
397 | extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask); | 397 | extern int irq_set_affinity_locked(struct irq_data *data, |
398 | const struct cpumask *cpumask, bool force); | ||
398 | 399 | ||
399 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) | 400 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) |
400 | void irq_move_irq(struct irq_data *data); | 401 | void irq_move_irq(struct irq_data *data); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 2486a4c1a710..d34131ca372b 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -180,7 +180,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
180 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 180 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
181 | int ret; | 181 | int ret; |
182 | 182 | ||
183 | ret = chip->irq_set_affinity(data, mask, false); | 183 | ret = chip->irq_set_affinity(data, mask, force); |
184 | switch (ret) { | 184 | switch (ret) { |
185 | case IRQ_SET_MASK_OK: | 185 | case IRQ_SET_MASK_OK: |
186 | cpumask_copy(data->affinity, mask); | 186 | cpumask_copy(data->affinity, mask); |
@@ -192,7 +192,8 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) | 195 | int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, |
196 | bool force) | ||
196 | { | 197 | { |
197 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 198 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
198 | struct irq_desc *desc = irq_data_to_desc(data); | 199 | struct irq_desc *desc = irq_data_to_desc(data); |
@@ -202,7 +203,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) | |||
202 | return -EINVAL; | 203 | return -EINVAL; |
203 | 204 | ||
204 | if (irq_can_move_pcntxt(data)) { | 205 | if (irq_can_move_pcntxt(data)) { |
205 | ret = irq_do_set_affinity(data, mask, false); | 206 | ret = irq_do_set_affinity(data, mask, force); |
206 | } else { | 207 | } else { |
207 | irqd_set_move_pending(data); | 208 | irqd_set_move_pending(data); |
208 | irq_copy_pending(desc, mask); | 209 | irq_copy_pending(desc, mask); |
@@ -217,13 +218,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) | |||
217 | return ret; | 218 | return ret; |
218 | } | 219 | } |
219 | 220 | ||
220 | /** | 221 | int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force) |
221 | * irq_set_affinity - Set the irq affinity of a given irq | ||
222 | * @irq: Interrupt to set affinity | ||
223 | * @mask: cpumask | ||
224 | * | ||
225 | */ | ||
226 | int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | ||
227 | { | 222 | { |
228 | struct irq_desc *desc = irq_to_desc(irq); | 223 | struct irq_desc *desc = irq_to_desc(irq); |
229 | unsigned long flags; | 224 | unsigned long flags; |
@@ -233,7 +228,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
233 | return -EINVAL; | 228 | return -EINVAL; |
234 | 229 | ||
235 | raw_spin_lock_irqsave(&desc->lock, flags); | 230 | raw_spin_lock_irqsave(&desc->lock, flags); |
236 | ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask); | 231 | ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force); |
237 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 232 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
238 | return ret; | 233 | return ret; |
239 | } | 234 | } |