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 <anup.patel@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
Anup Patel
2020-03-19 11:23:41 +05:30
committed by Anup Patel
parent 550ba88db1
commit 160c88535f

View File

@@ -12,30 +12,43 @@
#include <sbi/sbi_console.h> #include <sbi/sbi_console.h>
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h> #include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
void fdt_cpu_fixup(void *fdt) void fdt_cpu_fixup(void *fdt)
{ {
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
const struct sbi_platform *plat = sbi_platform_ptr(scratch); const struct sbi_platform *plat = sbi_platform_ptr(scratch);
char cpu_node[32] = ""; int err, len, cpu_offset, cpus_offset;
int cpu_offset; const fdt32_t *val;
int err; const void *prop;
u32 i; u32 hartid;
err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32); err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
if (err < 0) if (err < 0)
return; return;
/* assume hart ids are continuous */ cpus_offset = fdt_path_offset(fdt, "/cpus");
for (i = 0; i < sbi_platform_hart_count(plat); i++) { if (cpus_offset < 0)
sbi_sprintf(cpu_node, "/cpus/cpu@%d", i); return;
cpu_offset = fdt_path_offset(fdt, cpu_node);
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", fdt_setprop_string(fdt, cpu_offset, "status",
"disabled"); "disabled");
memset(cpu_node, 0, sizeof(cpu_node));
} }
} }