Messages in this thread Patch in this message | | | From | Jiaxun Yang <> | Subject | [PATCH v2 02/11] MIPS: prom: Add helper to parse CPU node in dt | Date | Sun, 12 Apr 2020 11:20:32 +0800 |
| |
Mostly identical with arm one. The only difference is that we allow to mark a CPU Node as status = "disabled" in dt, which means the core is physicaly present, but not possible for the kernel. It will occupy a bit in cpumask as well.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
-- v2: Exclude non-SMP config. --- arch/mips/include/asm/prom.h | 6 +++ arch/mips/kernel/prom.c | 97 ++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+)
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index c42e07671934..84802c70e426 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h @@ -24,6 +24,12 @@ extern int __dt_register_buses(const char *bus0, const char *bus1); static inline void device_tree_init(void) { } #endif /* CONFIG_OF */ +#if defined(CONFIG_OF) && defined(CONFIG_SMP) +extern void mips_dt_init_cpu_maps(void); +#else +static inline void mips_dt_init_cpu_maps(void) { } +#endif + extern char *mips_get_machine_name(void); extern void mips_set_machine_name(const char *name); diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 9e50dc8df2f6..deb5cc0a0eb5 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -89,4 +89,101 @@ int __init __dt_register_buses(const char *bus0, const char *bus1) return 0; } +#ifdef CONFIG_SMP +void __init mips_dt_init_cpu_maps(void) +{ + struct device_node *cpu, *cpus; + u32 i, j, cpuidx = 1; + u32 cpunum; + u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = U32_MAX }; + bool cpu_possible[NR_CPUS] = { [0 ... NR_CPUS-1] = false }; + bool bootcpu_valid = false; + + cpus = of_find_node_by_path("/cpus"); + if (!cpus) + return; + + if (cpu_has_mips_r2_r6) + cpunum = get_ebase_cpunum(); + else + cpunum = 0; /* For legacy system we assume boot from CPU 0 */ + + for_each_of_cpu_node(cpu) { + u32 hwid; + + pr_debug(" * %pOF...\n", cpu); + /* + * A device tree containing CPU nodes with missing "reg" + * properties is considered invalid to build the + * cpu_logical_map. + */ + + if (of_property_read_u32(cpu, "reg", &hwid)) { + pr_debug(" * %pOF missing reg property\n", cpu); + of_node_put(cpu); + return; + } + + /* + * Duplicate hwid are a recipe for disaster. + * Scan all initialized entries and check for + * duplicates. If any is found just bail out. + */ + for (j = 0; j < cpuidx; j++) + if (WARN(tmp_map[j] == hwid, + "Duplicate /cpu reg properties in the DT\n")) { + of_node_put(cpu); + return; + } + + /* + * Build a stashed array of hwid values. Numbering scheme + * requires that if detected the boot CPU must be assigned + * logical id 0. Other CPUs get sequential indexes starting + * from 1. If a CPU node with a reg property matching the + * boot CPU hwid is detected, this is recorded so that the + * logical map built from DT is validated. + */ + if (hwid == cpunum) { + i = 0; + if (of_device_is_available(cpu)) + bootcpu_valid = true; + } else { + i = cpuidx++; + } + + if (WARN(cpuidx > nr_cpu_ids, "DT /cpu %u nodes greater than " + "max cores %u, capping them\n", + cpuidx, nr_cpu_ids)) { + cpuidx = nr_cpu_ids; + of_node_put(cpu); + break; + } + + tmp_map[i] = hwid; + + if (of_device_is_available(cpu)) + cpu_possible[i] = true; + } + + if (!bootcpu_valid) { + pr_warn("DT missing boot CPU, fall back to default cpu_logical_map\n"); + return; + } + + init_cpu_possible(cpu_none_mask); + init_cpu_present(cpu_none_mask); + + for (i = 0; i < cpuidx; i++) { + set_cpu_possible(i, cpu_possible[i]); + cpu_logical_map(i) = tmp_map[i]; + pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i)); + } +} + +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ + return phys_id == cpu_logical_map(cpu); +} +#endif /* CONFIG_SMP */ #endif -- 2.26.0.rc2
| |