>From e3d36240832be914034bb3fb55dcf65c5a9f01df Mon Sep 17 00:00:00 2001 From: Yehuda Yitschak Date: Thu, 27 Dec 2012 13:03:36 +0200 Subject: [PATCH] arm: mvebu: Fix interrupt handling in SMP mode The Multi Processor interrupt Controller (MPIC), unlike the GIC, allows several CPUs to acknowledge the same global interrupt. This patch introduces changes to avoid this situation by forbidding multi-CPU interrupt affinity. This is done by setting the default interrupt affinity to the boot CPU and rejecting the affinity requests to more than one CPU. Signed-off-by: Yehuda Yitschak Acked-by: Gregory CLEMENT --- arch/arm/mach-mvebu/irq-armada-370-xp.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c index c041ee8..f99a4a2 100644 --- a/arch/arm/mach-mvebu/irq-armada-370-xp.c +++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c @@ -98,15 +98,26 @@ static int armada_xp_set_affinity(struct irq_data *d, unsigned long reg; unsigned long new_mask = 0; unsigned long online_mask = 0; + unsigned long count = 0; irq_hw_number_t hwirq = irqd_to_hwirq(d); int cpu; + for_each_cpu(cpu, mask_val) { + new_mask |= 1 << cpu_logical_map(cpu); + count++; + } + + /* + * Forbid mutlicore interrupt affinity + * This is required since the MPIC HW doesn't limit + * several CPUs from acknowledging the same interrupt. + */ + if (count > 1) + return -EINVAL; + for_each_cpu(cpu, cpu_online_mask) online_mask |= 1 << cpu_logical_map(cpu); - for_each_cpu(cpu, mask_val) - new_mask |= 1 << cpu_logical_map(cpu); - raw_spin_lock(&irq_controller_lock); reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); @@ -207,6 +218,15 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, #ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init(); + + /* + * Set the default affinity from all CPUs to the boot cpu. + * This is required since the MPIC doesn't limit several CPUs + * from acknowledging the same interrupt. + */ + cpumask_clear(irq_default_affinity); + cpumask_set_cpu(smp_processor_id(), irq_default_affinity); + #endif return 0; -- 1.7.9.5