sched: fix arch_get_fast_and_slow_cpus to get logical cpumask correctly
authorSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Mon, 24 Sep 2012 13:07:20 +0000 (14:07 +0100)
committerJon Medhurst <tixy@linaro.org>
Wed, 17 Jul 2013 10:12:26 +0000 (11:12 +0100)
The patch "sched: Use device-tree to provide fast/slow CPU list for HMP"
depends on the ordering of CPU's in the device tree. It breaks to determine
the logical mask correctly if the logical mask of the CPUs differ from
physical ordering in the device tree.

This patch fix the logic by depending on the mpidr in the device tree
and mapping that mpidr to the logical cpu.

Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
arch/arm/kernel/topology.c

index 0d406ff2e5b66e056591c28c8a62b90e689d17a6..f2ca9e030808ed1ab2d09779bd9a2d6403b9caf2 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 
 #include <asm/cputype.h>
+#include <asm/smp_plat.h>
 #include <asm/topology.h>
 
 /*
@@ -310,7 +311,7 @@ void __init arch_get_fast_and_slow_cpus(struct cpumask *fast,
                                        struct cpumask *slow)
 {
        struct device_node *cn = NULL;
-       int cpu = 0;
+       int cpu;
 
        cpumask_clear(fast);
        cpumask_clear(slow);
@@ -332,15 +333,26 @@ void __init arch_get_fast_and_slow_cpus(struct cpumask *fast,
         */
        while ((cn = of_find_node_by_type(cn, "cpu"))) {
 
-               if (cpu >= num_possible_cpus())
+               const u32 *mpidr;
+               int len;
+
+               mpidr = of_get_property(cn, "reg", &len);
+               if (!mpidr || len != 4) {
+                       pr_err("* %s missing reg property\n", cn->full_name);
+                       continue;
+               }
+
+               cpu = get_logical_index(be32_to_cpup(mpidr));
+               if (cpu == -EINVAL) {
+                       pr_err("couldn't get logical index for mpidr %x\n",
+                                                       be32_to_cpup(mpidr));
                        break;
+               }
 
                if (is_little_cpu(cn))
                        cpumask_set_cpu(cpu, slow);
                else
                        cpumask_set_cpu(cpu, fast);
-
-               cpu++;
        }
 
        if (!cpumask_empty(fast) && !cpumask_empty(slow))