2021-12-15 15:01:09

by Rob Herring (Arm)

[permalink] [raw]
Subject: [PATCH v4] of/fdt: Rework early_init_dt_scan_memory() to call directly

Use of the of_scan_flat_dt() function predates libfdt and is discouraged
as libfdt provides a nicer set of APIs. Rework
early_init_dt_scan_memory() to be called directly and use libfdt.

Cc: John Crispin <[email protected]>
Cc: Thomas Bogendoerfer <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frank Rowand <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Rob Herring <[email protected]>
Reviewed-by: Frank Rowand <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Rob Herring <[email protected]>
---
v4:
- Revert the changes to search for memory nodes at any level which were
accidentally committed.
v3:
- Fix powerpc when /ibm,dynamic-reconfiguration-memory is present
v2:
- ralink: Use 'if' instead of 'else if'
- early_init_dt_scan_memory: continue instead of return on no reg
- Fix indentation
---
arch/mips/ralink/of.c | 19 +++--------
arch/powerpc/kernel/prom.c | 21 ++++++------
drivers/of/fdt.c | 68 ++++++++++++++++++++------------------
include/linux/of_fdt.h | 3 +-
4 files changed, 51 insertions(+), 60 deletions(-)

diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index 0135376c5de5..35a87a2da10b 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -53,17 +53,6 @@ void __init device_tree_init(void)
unflatten_and_copy_device_tree();
}

-static int memory_dtb;
-
-static int __init early_init_dt_find_memory(unsigned long node,
- const char *uname, int depth, void *data)
-{
- if (depth == 1 && !strcmp(uname, "memory@0"))
- memory_dtb = 1;
-
- return 0;
-}
-
void __init plat_mem_setup(void)
{
void *dtb;
@@ -77,10 +66,10 @@ void __init plat_mem_setup(void)
dtb = get_fdt();
__dt_setup_arch(dtb);

- of_scan_flat_dt(early_init_dt_find_memory, NULL);
- if (memory_dtb)
- of_scan_flat_dt(early_init_dt_scan_memory, NULL);
- else if (soc_info.mem_detect)
+ if (!early_init_dt_scan_memory())
+ return;
+
+ if (soc_info.mem_detect)
soc_info.mem_detect();
else if (soc_info.mem_size)
memblock_add(soc_info.mem_base, soc_info.mem_size * SZ_1M);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6e1a106f02eb..ad1230c4f3fe 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -532,19 +532,18 @@ static int __init early_init_drmem_lmb(struct drmem_lmb *lmb,
}
#endif /* CONFIG_PPC_PSERIES */

-static int __init early_init_dt_scan_memory_ppc(unsigned long node,
- const char *uname,
- int depth, void *data)
+static int __init early_init_dt_scan_memory_ppc(void)
{
#ifdef CONFIG_PPC_PSERIES
- if (depth == 1 &&
- strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) {
+ const void *fdt = initial_boot_params;
+ int node = fdt_path_offset(fdt, "/ibm,dynamic-reconfiguration-memory");
+
+ if (node > 0)
walk_drmem_lmbs_early(node, NULL, early_init_drmem_lmb);
- return 0;
- }
+
#endif
-
- return early_init_dt_scan_memory(node, uname, depth, data);
+
+ return early_init_dt_scan_memory();
}

/*
@@ -749,7 +748,7 @@ void __init early_init_devtree(void *params)

/* Scan memory nodes and rebuild MEMBLOCKs */
early_init_dt_scan_root();
- of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
+ early_init_dt_scan_memory_ppc();

parse_early_param();

@@ -858,7 +857,7 @@ void __init early_get_first_memblock_info(void *params, phys_addr_t *size)
*/
add_mem_to_memblock = 0;
early_init_dt_scan_root();
- of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
+ early_init_dt_scan_memory_ppc();
add_mem_to_memblock = 1;

if (size)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 5e216555fe4f..a835c458f50a 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1078,49 +1078,53 @@ u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
/*
* early_init_dt_scan_memory - Look for and parse memory nodes
*/
-int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
- int depth, void *data)
+int __init early_init_dt_scan_memory(void)
{
- const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
- const __be32 *reg, *endp;
- int l;
- bool hotpluggable;
+ int node;
+ const void *fdt = initial_boot_params;

- /* We are scanning "memory" nodes only */
- if (type == NULL || strcmp(type, "memory") != 0)
- return 0;
+ fdt_for_each_subnode(node, fdt, 0) {
+ const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ const __be32 *reg, *endp;
+ int l;
+ bool hotpluggable;

- reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
- if (reg == NULL)
- reg = of_get_flat_dt_prop(node, "reg", &l);
- if (reg == NULL)
- return 0;
+ /* We are scanning "memory" nodes only */
+ if (type == NULL || strcmp(type, "memory") != 0)
+ continue;

- endp = reg + (l / sizeof(__be32));
- hotpluggable = of_get_flat_dt_prop(node, "hotpluggable", NULL);
+ reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ if (reg == NULL)
+ reg = of_get_flat_dt_prop(node, "reg", &l);
+ if (reg == NULL)
+ continue;

- pr_debug("memory scan node %s, reg size %d,\n", uname, l);
+ endp = reg + (l / sizeof(__be32));
+ hotpluggable = of_get_flat_dt_prop(node, "hotpluggable", NULL);

- while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
- u64 base, size;
+ pr_debug("memory scan node %s, reg size %d,\n",
+ fdt_get_name(fdt, node, NULL), l);

- base = dt_mem_next_cell(dt_root_addr_cells, &reg);
- size = dt_mem_next_cell(dt_root_size_cells, &reg);
+ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+ u64 base, size;

- if (size == 0)
- continue;
- pr_debug(" - %llx, %llx\n", base, size);
+ base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+ size = dt_mem_next_cell(dt_root_size_cells, &reg);

- early_init_dt_add_memory_arch(base, size);
+ if (size == 0)
+ continue;
+ pr_debug(" - %llx, %llx\n", base, size);

- if (!hotpluggable)
- continue;
+ early_init_dt_add_memory_arch(base, size);

- if (memblock_mark_hotplug(base, size))
- pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
- base, base + size);
- }
+ if (!hotpluggable)
+ continue;

+ if (memblock_mark_hotplug(base, size))
+ pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
+ base, base + size);
+ }
+ }
return 0;
}

@@ -1271,7 +1275,7 @@ void __init early_init_dt_scan_nodes(void)
pr_warn("No chosen node found, continuing without\n");

/* Setup memory, calling early_init_dt_add_memory_arch */
- of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+ early_init_dt_scan_memory();

/* Handle linux,usable-memory-range property */
memblock_cap_memory_range(cap_mem_addr, cap_mem_size);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index df3d31926c3c..914739f3c192 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -59,8 +59,7 @@ extern unsigned long of_get_flat_dt_root(void);
extern uint32_t of_get_flat_dt_phandle(unsigned long node);

extern int early_init_dt_scan_chosen(char *cmdline);
-extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
- int depth, void *data);
+extern int early_init_dt_scan_memory(void);
extern int early_init_dt_scan_chosen_stdout(void);
extern void early_init_fdt_scan_reserved_mem(void);
extern void early_init_fdt_reserve_self(void);
--
2.32.0



2021-12-16 05:20:01

by Michael Ellerman

[permalink] [raw]
Subject: Re: [PATCH v4] of/fdt: Rework early_init_dt_scan_memory() to call directly

Rob Herring <[email protected]> writes:
> Use of the of_scan_flat_dt() function predates libfdt and is discouraged
> as libfdt provides a nicer set of APIs. Rework
> early_init_dt_scan_memory() to be called directly and use libfdt.
>
> Cc: John Crispin <[email protected]>
> Cc: Thomas Bogendoerfer <[email protected]>
> Cc: Michael Ellerman <[email protected]>
> Cc: Benjamin Herrenschmidt <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Frank Rowand <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Signed-off-by: Rob Herring <[email protected]>
> Reviewed-by: Frank Rowand <[email protected]>
> Link: https://lore.kernel.org/r/[email protected]
> Signed-off-by: Rob Herring <[email protected]>
> ---
> v4:
> - Revert the changes to search for memory nodes at any level which were
> accidentally committed.

Sorry for the mix up, this version works for me.

Tested-by: Michael Ellerman <[email protected]>

cheers

2022-12-17 00:54:30

by Andreas Rammhold

[permalink] [raw]
Subject: Re: [PATCH v4] of/fdt: Rework early_init_dt_scan_memory() to call directly


Hi,

I've just debugged an issue that I traced down to this commit.

My mt7621 based board relies on the soc_info.mem_detect function for
memblock init which is never being called again with this patch being
applied.

The code in the original patch as well was on 6.0 doesn't allow any of
the other (fallback?) memory initialization code to run as
early_init_dt_scan_memory() always returns 0.

Was this an oversight in the implementation or are some follow-up
patches missing? Perhaps the code just has to return a different
value when it has found some blocks of memory that should be used?


Andi