[linux-yocto] [PATCH 32/87] LSI axm55xx: Fix boot issues with PREMPT_RT kernel

Paul Butler butler.paul at gmail.com
Mon May 27 09:56:03 PDT 2013


From: David Mercado <david.mercado at windriver.com>

Modified arch/arm/mach-axxia/axxia-gic.c to to handle the slightly different
way in which a preempt_rt kernel manipulates the Axxia GIC API during boot.
Also updated arch/arm/configs/lsisim_defconfig to set the base level of
prempt_rt to CONFIG_PREEMPT_RTB.  The preempt_rt kernel must be set with
a minimal preempt model, to enable CONFIG_GENERIC_LOCKBREAK, which in turn
allows spinlocks to work correctly across multiple clusters.

Signed-off-by: David Mercado <david.mercado at windriver.com>
Signed-off-by: Paul Butler <paul.butler at windriver.com>
---
 arch/arm/mach-axxia/axxia-gic.c | 54 +++++++++++++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-axxia/axxia-gic.c b/arch/arm/mach-axxia/axxia-gic.c
index 058b837..20d04ea 100644
--- a/arch/arm/mach-axxia/axxia-gic.c
+++ b/arch/arm/mach-axxia/axxia-gic.c
@@ -155,9 +155,11 @@ static void gic_mask_irq(struct irq_data *d)
 	if (irqid >= 1020)
 		return;
 
-	/* We should never be disabling the AXM IPI interrupts. */
-	if ((irqid >= IPI0_CPU0) && (irqid < MAX_AXM_IPI_NUM))
+	/* Deal with PPI interrupts directly. */
+	if (irqid > 16 && irqid < 32) {
+		_gic_mask_irq(d);
 		return;
+	}
 
 	/*
 	 * If the cpu that this interrupt is assigned to falls within
@@ -182,22 +184,54 @@ static void gic_mask_irq(struct irq_data *d)
 	}
 }
 
-static void gic_unmask_irq(struct irq_data *d)
+static void _gic_unmask_irq(void *arg)
 {
+	struct irq_data *d = (struct irq_data *)arg;
 	u32 mask = 1 << (gic_irq(d) % 32);
 
-	/*
-	 * No need to run this at all clusters, since the kernel
-	 * also calls gic_set_affinity when unmasking interrupts.
-	 * In that routine we also unmask the interrupt, so doing
-	 * it here would be redundant.
-	 */
 	raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET
-			+ (gic_irq(d) / 32) * 4);
+				+ (gic_irq(d) / 32) * 4);
 	raw_spin_unlock(&irq_controller_lock);
 }
 
+static void gic_unmask_irq(struct irq_data *d)
+{
+	u32 pcpu = cpu_logical_map(smp_processor_id());
+	u32 irqid = gic_irq(d);
+
+	if (irqid >= 1020)
+		return;
+
+	/* Deal with PPI interrupts directly. */
+	if (irqid > 15 && irqid < 32) {
+		_gic_unmask_irq(d);
+		return;
+	}
+
+	/*
+	 * If the cpu that this interrupt is assigned to falls within
+	 * the same cluster as the cpu we're currently running on, do
+	 * the IRQ masking directly. Otherwise, use the IPI mechanism
+	 * to remotely do the masking.
+	 */
+	if ((cpu_logical_map(irq_cpuid[irqid]) / 4) == (pcpu / 4)) {
+		_gic_unmask_irq(d);
+	} else {
+		/*
+		 * We are running here with local interrupts
+		 * disabled. Temporarily re-enable them to
+		 * avoid possible deadlock when calling
+		 * smp_call_function_single().
+		 */
+		local_irq_enable();
+		smp_call_function_single(irq_cpuid[irqid],
+					 _gic_unmask_irq,
+					 d, 1);
+		local_irq_disable();
+	}
+}
+
 static void gic_eoi_irq(struct irq_data *d)
 {
 	/*
-- 
1.8.3




More information about the linux-yocto mailing list