sched: fix arch_get_fast_and_slow_cpus to get logical cpumask correctly
authorSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Thu, 29 Jan 2015 09:08:20 +0000 (18:08 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:41:31 +0000 (13:41 +0900)
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>
[k.kozlowski: rebased on 4.1, no signed-off-by of previous committer]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
arch/arm64/kernel/topology.c

index a75a8d0..56ff331 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 
 #include <asm/cputype.h>
+#include <asm/smp_plat.h>
 #include <asm/topology.h>
 
 static int __init get_cpu_for_node(struct device_node *node)
@@ -296,7 +297,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);
@@ -318,15 +319,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))