aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-03-04 15:43:41 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-04-28 15:27:15 -0400
commit8cc3cfc5ccf1680b7c88f874912b6bec2797b76b (patch)
tree33658295928340d76ca4ce6c30f488c49c7f8043
parent62a08ae2a5763aabeee98264605236b001503e0c (diff)
irqchip: armanda: Sanitize set_irq_affinity()
The set_irq_affinity() function has two issues: 1) It has no protection against selecting an offline cpu from the given mask. 2) It pointlessly restricts the affinity masks to have a single cpu set. This collides with the irq migration code of arm. irq affinity is set to core 3 core 3 goes offline migration code sets mask to cpu_online_mask and calls the irq_set_affinity() callback of the irq_chip which fails due to bit 0,1,2 set. So instead of doing silly for_each_cpu() loops just pick any bit of the mask which intersects with the online mask. Get rid of fiddling with the default_irq_affinity as well. [ Gregory: Fixed the access to the routing register ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@elte.hu> Link: http://lkml.kernel.org/r/20140304203101.088889302@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c37
1 files changed, 6 insertions, 31 deletions
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 41be897df8d5..304a20d0ad15 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -41,6 +41,7 @@
41#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) 41#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
42#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) 42#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
43#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) 43#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
44#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF
44 45
45#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) 46#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
46#define ARMADA_375_PPI_CAUSE (0x10) 47#define ARMADA_375_PPI_CAUSE (0x10)
@@ -244,35 +245,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
244static int armada_xp_set_affinity(struct irq_data *d, 245static int armada_xp_set_affinity(struct irq_data *d,
245 const struct cpumask *mask_val, bool force) 246 const struct cpumask *mask_val, bool force)
246{ 247{
247 unsigned long reg;
248 unsigned long new_mask = 0;
249 unsigned long online_mask = 0;
250 unsigned long count = 0;
251 irq_hw_number_t hwirq = irqd_to_hwirq(d); 248 irq_hw_number_t hwirq = irqd_to_hwirq(d);
249 unsigned long reg, mask;
252 int cpu; 250 int cpu;
253 251
254 for_each_cpu(cpu, mask_val) { 252 /* Select a single core from the affinity mask which is online */
255 new_mask |= 1 << cpu_logical_map(cpu); 253 cpu = cpumask_any_and(mask_val, cpu_online_mask);
256 count++; 254 mask = 1UL << cpu_logical_map(cpu);
257 }
258
259 /*
260 * Forbid mutlicore interrupt affinity
261 * This is required since the MPIC HW doesn't limit
262 * several CPUs from acknowledging the same interrupt.
263 */
264 if (count > 1)
265 return -EINVAL;
266
267 for_each_cpu(cpu, cpu_online_mask)
268 online_mask |= 1 << cpu_logical_map(cpu);
269 255
270 raw_spin_lock(&irq_controller_lock); 256 raw_spin_lock(&irq_controller_lock);
271
272 reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); 257 reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
273 reg = (reg & (~online_mask)) | new_mask; 258 reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;
274 writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); 259 writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
275
276 raw_spin_unlock(&irq_controller_lock); 260 raw_spin_unlock(&irq_controller_lock);
277 261
278 return 0; 262 return 0;
@@ -494,15 +478,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
494 478
495#ifdef CONFIG_SMP 479#ifdef CONFIG_SMP
496 armada_xp_mpic_smp_cpu_init(); 480 armada_xp_mpic_smp_cpu_init();
497
498 /*
499 * Set the default affinity from all CPUs to the boot cpu.
500 * This is required since the MPIC doesn't limit several CPUs
501 * from acknowledging the same interrupt.
502 */
503 cpumask_clear(irq_default_affinity);
504 cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
505
506#endif 481#endif
507 482
508 armada_370_xp_msi_init(node, main_int_res.start); 483 armada_370_xp_msi_init(node, main_int_res.start);