From 160c88535f07084051ebba97689fc4a7b2e9037c Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Thu, 19 Mar 2020 11:23:41 +0530 Subject: [PATCH] lib: utils: Improve fdt_cpu_fixup() implementation Currently, the fdt_cpu_fixup() implementation assumes: 1. We have one CPU DT for each HART under /cpus DT node 2. The CPU DT nodes are named sequentially (i.e cpu@0, cpu@1, ...) which is not true for discontinuous and sparse HART ids (i.e. cpu@0, cpu@4, cpu@5). Generally, CPU DT node are named based on HART id and not HART index If any of the above assumptions are violated then the fdt_cpu_fixup() will not work. This improves fdt_cpu_fixup() implementation and makes it independent of above assumptions. Signed-off-by: Anup Patel Reviewed-by: Bin Meng Reviewed-by: Atish Patra --- lib/utils/fdt/fdt_fixup.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c index b91e95f..d6e4cc1 100644 --- a/lib/utils/fdt/fdt_fixup.c +++ b/lib/utils/fdt/fdt_fixup.c @@ -12,30 +12,43 @@ #include #include #include +#include void fdt_cpu_fixup(void *fdt) { struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); const struct sbi_platform *plat = sbi_platform_ptr(scratch); - char cpu_node[32] = ""; - int cpu_offset; - int err; - u32 i; + int err, len, cpu_offset, cpus_offset; + const fdt32_t *val; + const void *prop; + u32 hartid; err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32); if (err < 0) return; - /* assume hart ids are continuous */ - for (i = 0; i < sbi_platform_hart_count(plat); i++) { - sbi_sprintf(cpu_node, "/cpus/cpu@%d", i); - cpu_offset = fdt_path_offset(fdt, cpu_node); + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + return; - if (sbi_platform_hart_invalid(plat, i)) + fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) { + prop = fdt_getprop(fdt, cpu_offset, "device_type", &len); + if (!prop || !len) + continue; + if (sbi_strcmp(prop, "cpu")) + continue; + + val = fdt_getprop(fdt, cpu_offset, "reg", &len); + if (!val || len < sizeof(fdt32_t)) + continue; + + if (len > sizeof(fdt32_t)) + val++; + hartid = fdt32_to_cpu(*val); + + if (sbi_platform_hart_invalid(plat, hartid)) fdt_setprop_string(fdt, cpu_offset, "status", "disabled"); - - memset(cpu_node, 0, sizeof(cpu_node)); } }