ARM: bL_switcher: do not hardcode GIC IDs in the code
authorNicolas Pitre <nicolas.pitre@linaro.org>
Fri, 6 Jul 2012 01:33:26 +0000 (21:33 -0400)
committerNicolas Pitre <nicolas.pitre@linaro.org>
Wed, 19 Jun 2013 20:54:22 +0000 (16:54 -0400)
Currently, GIC IDs are hardcoded making the code dependent on the x4 b.L
configuration.  Let's allow for GIC IDs to be discovered upon switcher
initialization to support other b.L configurations such as the x1 one.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
arch/arm/common/bL_switcher.c
drivers/irqchip/irq-gic.c
include/linux/irqchip/arm-gic.h

index 4604834737910005b35c32bb5f000f29903fa3e2..0d9ece547a1268a152b7e272350404735ecb59f2 100644 (file)
@@ -111,6 +111,8 @@ static int bL_switchpoint(unsigned long _arg)
  * Generic switcher interface
  */
 
+static unsigned int bL_gic_id[MAX_CPUS_PER_CLUSTER][MAX_NR_CLUSTERS];
+
 /*
  * bL_switch_to - Switch to a specific cluster for the current CPU
  * @new_cluster_id: the ID of the cluster to switch to.
@@ -160,7 +162,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
        this_cpu = smp_processor_id();
 
        /* redirect GIC's SGIs to our counterpart */
-       gic_migrate_target(cpuid + ib_cluster*4);
+       gic_migrate_target(bL_gic_id[cpuid][ib_cluster]);
 
        /*
         * Raise a SGI on the inbound CPU to make sure it doesn't stall
@@ -340,6 +342,16 @@ static int __init bL_switcher_halve_cpus(void)
                cluster = (cpu_logical_map(i) >> 8) & 0xff;
 
                if (cpumask_test_cpu(cpu, &common_mask)) {
+                       /* Let's take note of the GIC ID for this CPU */
+                       int gic_id = gic_get_cpu_id(i);
+                       if (gic_id < 0) {
+                               pr_err("%s: bad GIC ID for CPU %d\n", __func__, i);
+                               return -EINVAL;
+                       }
+                       bL_gic_id[cpu][cluster] = gic_id;
+                       pr_info("GIC ID for CPU %u cluster %u is %u\n",
+                               cpu, cluster, gic_id);
+
                        /*
                         * We keep only those logical CPUs which number
                         * is equal to their physical CPU number. This is
index c212513bffdff028dd2b3ef455d3801ff62bc295..29b876b98d449fba459c8593120c661f0b61889e 100644 (file)
@@ -667,6 +667,27 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 #endif
 
 #ifdef CONFIG_BL_SWITCHER
+/*
+ * gic_get_cpu_id - get the CPU interface ID for the specified CPU
+ *
+ * @cpu: the logical CPU number to get the GIC ID for.
+ *
+ * Return the CPU interface ID for the given logical CPU number,
+ * or -1 if the CPU number is too large or the interface ID is
+ * unknown (more than one bit set).
+ */
+int gic_get_cpu_id(unsigned int cpu)
+{
+       unsigned int cpu_bit;
+
+       if (cpu >= NR_GIC_CPU_IF)
+               return -1;
+       cpu_bit = gic_cpu_map[cpu];
+       if (cpu_bit & (cpu_bit - 1))
+              return -1;
+       return __ffs(cpu_bit);
+}
+
 /*
  * gic_migrate_target - migrate IRQs to another PU interface
  *
index 40bfcac959404a5f8cdaae2e165e26ef7cfbc1fd..2d7d47e8dfaffc336976e52d4190731bbb2eb166 100644 (file)
@@ -75,6 +75,7 @@ static inline void gic_init(unsigned int nr, int start,
        gic_init_bases(nr, start, dist, cpu, 0, NULL);
 }
 
+int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
 
 #endif /* __ASSEMBLY */