Commit 384a290283fde63ba8dc671fca5420111cdac19a seems to break 11MPCore boot

Russell King - ARM Linux linux at arm.linux.org.uk
Wed Jan 30 12:19:18 EST 2013


On Wed, Jan 30, 2013 at 04:45:35PM +0000, Russell King - ARM Linux wrote:
> What we could do is scan interrupts 0-31 for a non-zero value.  If they're
> all zero, we should complain.  Otherwise, we use the first non-zero value
> we find and validate it for a single bit set.

And here's a patch to do this - I've not run this but it's just built
successfully here.  Anyone want to give it a go?

I've decided that if we do hit the mask==0 case, we should just wail
loudly - panic'ing will bring the kernel to a halt right there and then,
which may be before any console drivers have been initialized (and the
kernel message buffer is no longer easy to read).  Moreover, panic()ing,
along with the possibility of rebooting won't really fix this kind of
error - it's rather fatal as far as that goes.  So, I think just wailing
at CRIT level is fine for this condition that should not occur.

 arch/arm/common/gic.c |   23 +++++++++++++++++++++--
 1 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 36ae03a..3bcef49 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -351,6 +351,23 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static u8 gic_get_cpumask(struct gic_chip_data *gic)
+{
+	void __iomem *base = gic_data_dist_base(gic);
+	u8 mask, i;
+
+	for (i = mask = 0; i < 32; i++) {
+		mask = readl_relaxed(base + GIC_DIST_TARGET + i);
+		if (mask)
+			break;
+	}
+
+	if (!mask)
+		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
+
+	return mask;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic)
 {
 	unsigned int i;
@@ -369,7 +386,9 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
 	/*
 	 * Set all global interrupts to this CPU only.
 	 */
-	cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0);
+	cpumask = gic_get_cpumask(gic);
+	cpumask |= cpumask << 8;
+	cpumask |= cpumask << 16;
 	for (i = 32; i < gic_irqs; i += 4)
 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
@@ -400,7 +419,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 	 * Get what the GIC says our CPU mask is.
 	 */
 	BUG_ON(cpu >= NR_GIC_CPU_IF);
-	cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0);
+	cpu_mask = gic_get_cpumask(gic);
 	gic_cpu_map[cpu] = cpu_mask;
 
 	/*




More information about the linux-arm-kernel mailing list