2021-11-18 18:12:17

by Rob Herring (Arm)

[permalink] [raw]
Subject: [PATCH 0/3] of/fdt: Rework early FDT scanning functions

The early FDT scanning functions use of_scan_flat_dt() which implements
its own node walking method. This function predates libfdt and is an
unnecessary indirection. This series reworks
early_init_dt_scan_chosen(), early_init_dt_scan_root(), and
early_init_dt_scan_memory() to be called directly and use libfdt calls.

Ultimately, I want to remove of_scan_flat_dt(). Most of the remaining
of_scan_flat_dt() users are in powerpc.

Rob


Rob Herring (3):
of/fdt: Rework early_init_dt_scan_chosen() to call directly
of/fdt: Rework early_init_dt_scan_root() to call directly
of/fdt: Rework early_init_dt_scan_memory() to call directly

arch/mips/ralink/of.c | 16 +---
arch/powerpc/kernel/prom.c | 22 ++---
arch/powerpc/mm/nohash/kaslr_booke.c | 4 +-
drivers/of/fdt.c | 121 ++++++++++++++-------------
include/linux/of_fdt.h | 9 +-
5 files changed, 79 insertions(+), 93 deletions(-)

--
2.32.0



2021-11-18 18:12:22

by Rob Herring (Arm)

[permalink] [raw]
Subject: [PATCH 1/3] of/fdt: Rework early_init_dt_scan_chosen() 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_chosen() to be called directly and use libfdt.

Cc: Michael Ellerman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frank Rowand <[email protected]>
Cc: [email protected]
Signed-off-by: Rob Herring <[email protected]>
---
arch/powerpc/kernel/prom.c | 2 +-
arch/powerpc/mm/nohash/kaslr_booke.c | 4 +--
drivers/of/fdt.c | 39 ++++++++++++++--------------
include/linux/of_fdt.h | 3 +--
4 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 2e67588f6f6e..c6c398ccd98a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -402,7 +402,7 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
const unsigned long *lprop; /* All these set by kernel, so no need to convert endian */

/* Use common scan routine to determine if this is the chosen node */
- if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
+ if (early_init_dt_scan_chosen(data) < 0)
return 0;

#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c
index 8fc49b1b4a91..90debe19ab4c 100644
--- a/arch/powerpc/mm/nohash/kaslr_booke.c
+++ b/arch/powerpc/mm/nohash/kaslr_booke.c
@@ -44,9 +44,7 @@ struct regions __initdata regions;

static __init void kaslr_get_cmdline(void *fdt)
{
- int node = fdt_path_offset(fdt, "/chosen");
-
- early_init_dt_scan_chosen(node, "chosen", 1, boot_command_line);
+ early_init_dt_scan_chosen(boot_command_line);
}

static unsigned long __init rotate_xor(unsigned long hash, const void *area,
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index bdca35284ceb..1f1705f76263 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1124,18 +1124,18 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
return 0;
}

-int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
- int depth, void *data)
+int __init early_init_dt_scan_chosen(char *cmdline)
{
- int l;
+ int l, node;
const char *p;
const void *rng_seed;
+ const void *fdt = initial_boot_params;

- pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
- if (depth != 1 || !data ||
- (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
- return 0;
+ node = fdt_path_offset(fdt, "/chosen");
+ if (node < 0)
+ node = fdt_path_offset(fdt, "/chosen@0");
+ if (node < 0)
+ return -ENOENT;

early_init_dt_check_for_initrd(node);
early_init_dt_check_for_elfcorehdr(node);
@@ -1144,7 +1144,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
/* Retrieve command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
- strlcpy(data, p, min(l, COMMAND_LINE_SIZE));
+ strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE));

/*
* CONFIG_CMDLINE is meant to be a default in case nothing else
@@ -1153,18 +1153,18 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
*/
#ifdef CONFIG_CMDLINE
#if defined(CONFIG_CMDLINE_EXTEND)
- strlcat(data, " ", COMMAND_LINE_SIZE);
- strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+ strlcat(cmdline, " ", COMMAND_LINE_SIZE);
+ strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+ strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
/* No arguments from boot loader, use kernel's cmdl*/
- if (!((char *)data)[0])
- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+ if (!((char *)cmdline)[0])
+ strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */

- pr_debug("Command line is: %s\n", (char *)data);
+ pr_debug("Command line is: %s\n", (char *)cmdline);

rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l);
if (rng_seed && l > 0) {
@@ -1178,8 +1178,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
fdt_totalsize(initial_boot_params));
}

- /* break now */
- return 1;
+ return 0;
}

#ifndef MIN_MEMBLOCK_ADDR
@@ -1261,14 +1260,14 @@ bool __init early_init_dt_verify(void *params)

void __init early_init_dt_scan_nodes(void)
{
- int rc = 0;
+ int rc;

/* Initialize {size,address}-cells info */
of_scan_flat_dt(early_init_dt_scan_root, NULL);

/* Retrieve various information from the /chosen node */
- rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
- if (!rc)
+ rc = early_init_dt_scan_chosen(boot_command_line);
+ if (rc)
pr_warn("No chosen node found, continuing without\n");

/* Setup memory, calling early_init_dt_add_memory_arch */
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index cf48983d3c86..654722235df6 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -58,8 +58,7 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
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(unsigned long node, const char *uname,
- int depth, void *data);
+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_chosen_stdout(void);
--
2.32.0


2021-11-18 18:12:24

by Rob Herring (Arm)

[permalink] [raw]
Subject: [PATCH 2/3] of/fdt: Rework early_init_dt_scan_root() 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_root()
to be called directly and use libfdt.

Cc: Michael Ellerman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frank Rowand <[email protected]>
Cc: [email protected]
Signed-off-by: Rob Herring <[email protected]>
---
arch/powerpc/kernel/prom.c | 4 ++--
drivers/of/fdt.c | 14 +++++++-------
include/linux/of_fdt.h | 3 +--
3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index c6c398ccd98a..6e1a106f02eb 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -748,7 +748,7 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_chosen_ppc, boot_command_line);

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

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

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 1f1705f76263..5e216555fe4f 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1042,13 +1042,14 @@ int __init early_init_dt_scan_chosen_stdout(void)
/*
* early_init_dt_scan_root - fetch the top level address and size cells
*/
-int __init early_init_dt_scan_root(unsigned long node, const char *uname,
- int depth, void *data)
+int __init early_init_dt_scan_root(void)
{
const __be32 *prop;
+ const void *fdt = initial_boot_params;
+ int node = fdt_path_offset(fdt, "/");

- if (depth != 0)
- return 0;
+ if (node < 0)
+ return -ENODEV;

dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
@@ -1063,8 +1064,7 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
dt_root_addr_cells = be32_to_cpup(prop);
pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);

- /* break now */
- return 1;
+ return 0;
}

u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
@@ -1263,7 +1263,7 @@ void __init early_init_dt_scan_nodes(void)
int rc;

/* Initialize {size,address}-cells info */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
+ early_init_dt_scan_root();

/* Retrieve various information from the /chosen node */
rc = early_init_dt_scan_chosen(boot_command_line);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 654722235df6..df3d31926c3c 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -68,8 +68,7 @@ extern void early_init_dt_add_memory_arch(u64 base, u64 size);
extern u64 dt_mem_next_cell(int s, const __be32 **cellp);

/* Early flat tree scan hooks */
-extern int early_init_dt_scan_root(unsigned long node, const char *uname,
- int depth, void *data);
+extern int early_init_dt_scan_root(void);

extern bool early_init_dt_scan(void *params);
extern bool early_init_dt_verify(void *params);
--
2.32.0


2021-11-18 18:12:29

by Rob Herring (Arm)

[permalink] [raw]
Subject: [PATCH 3/3] 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]>
---
arch/mips/ralink/of.c | 16 ++-------
arch/powerpc/kernel/prom.c | 16 ++++-----
drivers/of/fdt.c | 68 ++++++++++++++++++++------------------
include/linux/of_fdt.h | 3 +-
4 files changed, 47 insertions(+), 56 deletions(-)

diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index 0135376c5de5..e1d79523343a 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,9 +66,8 @@ 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);
+ if (!early_init_dt_scan_memory())
+ return;
else if (soc_info.mem_detect)
soc_info.mem_detect();
else if (soc_info.mem_size)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6e1a106f02eb..63762a3b75e8 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -532,19 +532,19 @@ 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 +749,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 +858,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..a799117886f4 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)
+ return 0;

- 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-11-24 16:13:19

by Frank Rowand

[permalink] [raw]
Subject: Re: [PATCH 1/3] of/fdt: Rework early_init_dt_scan_chosen() to call directly

On 11/18/21 1:12 PM, Rob Herring wrote:
> 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_chosen() to be called directly and use libfdt.
>
> Cc: Michael Ellerman <[email protected]>
> Cc: Benjamin Herrenschmidt <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Frank Rowand <[email protected]>
> Cc: [email protected]
> Signed-off-by: Rob Herring <[email protected]>
> ---
> arch/powerpc/kernel/prom.c | 2 +-
> arch/powerpc/mm/nohash/kaslr_booke.c | 4 +--
> drivers/of/fdt.c | 39 ++++++++++++++--------------
> include/linux/of_fdt.h | 3 +--
> 4 files changed, 22 insertions(+), 26 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 2e67588f6f6e..c6c398ccd98a 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -402,7 +402,7 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
> const unsigned long *lprop; /* All these set by kernel, so no need to convert endian */
>
> /* Use common scan routine to determine if this is the chosen node */
> - if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
> + if (early_init_dt_scan_chosen(data) < 0)
> return 0;
>
> #ifdef CONFIG_PPC64
> diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c
> index 8fc49b1b4a91..90debe19ab4c 100644
> --- a/arch/powerpc/mm/nohash/kaslr_booke.c
> +++ b/arch/powerpc/mm/nohash/kaslr_booke.c
> @@ -44,9 +44,7 @@ struct regions __initdata regions;
>
> static __init void kaslr_get_cmdline(void *fdt)
> {
> - int node = fdt_path_offset(fdt, "/chosen");
> -
> - early_init_dt_scan_chosen(node, "chosen", 1, boot_command_line);
> + early_init_dt_scan_chosen(boot_command_line);
> }
>
> static unsigned long __init rotate_xor(unsigned long hash, const void *area,
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index bdca35284ceb..1f1705f76263 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -1124,18 +1124,18 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
> return 0;
> }
>
> -int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
> - int depth, void *data)
> +int __init early_init_dt_scan_chosen(char *cmdline)
> {
> - int l;
> + int l, node;
> const char *p;
> const void *rng_seed;
> + const void *fdt = initial_boot_params;
>
> - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
> -
> - if (depth != 1 || !data ||
> - (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
> - return 0;
> + node = fdt_path_offset(fdt, "/chosen");
> + if (node < 0)
> + node = fdt_path_offset(fdt, "/chosen@0");
> + if (node < 0)
> + return -ENOENT;
>
> early_init_dt_check_for_initrd(node);
> early_init_dt_check_for_elfcorehdr(node);
> @@ -1144,7 +1144,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
> /* Retrieve command line */
> p = of_get_flat_dt_prop(node, "bootargs", &l);
> if (p != NULL && l > 0)
> - strlcpy(data, p, min(l, COMMAND_LINE_SIZE));
> + strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
>
> /*
> * CONFIG_CMDLINE is meant to be a default in case nothing else
> @@ -1153,18 +1153,18 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
> */
> #ifdef CONFIG_CMDLINE
> #if defined(CONFIG_CMDLINE_EXTEND)
> - strlcat(data, " ", COMMAND_LINE_SIZE);
> - strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> + strlcat(cmdline, " ", COMMAND_LINE_SIZE);
> + strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> #elif defined(CONFIG_CMDLINE_FORCE)
> - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> + strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> #else
> /* No arguments from boot loader, use kernel's cmdl*/
> - if (!((char *)data)[0])
> - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> + if (!((char *)cmdline)[0])
> + strlcpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
> #endif
> #endif /* CONFIG_CMDLINE */
>
> - pr_debug("Command line is: %s\n", (char *)data);
> + pr_debug("Command line is: %s\n", (char *)cmdline);
>
> rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l);
> if (rng_seed && l > 0) {
> @@ -1178,8 +1178,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
> fdt_totalsize(initial_boot_params));
> }
>
> - /* break now */
> - return 1;
> + return 0;
> }
>
> #ifndef MIN_MEMBLOCK_ADDR
> @@ -1261,14 +1260,14 @@ bool __init early_init_dt_verify(void *params)
>
> void __init early_init_dt_scan_nodes(void)
> {
> - int rc = 0;
> + int rc;
>
> /* Initialize {size,address}-cells info */
> of_scan_flat_dt(early_init_dt_scan_root, NULL);
>
> /* Retrieve various information from the /chosen node */
> - rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
> - if (!rc)
> + rc = early_init_dt_scan_chosen(boot_command_line);
> + if (rc)
> pr_warn("No chosen node found, continuing without\n");
>
> /* Setup memory, calling early_init_dt_add_memory_arch */
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index cf48983d3c86..654722235df6 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -58,8 +58,7 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
> 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(unsigned long node, const char *uname,
> - int depth, void *data);
> +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_chosen_stdout(void);
>

patch 1/3

Reviewed-by: Frank Rowand <[email protected]>


2021-11-24 16:20:31

by Frank Rowand

[permalink] [raw]
Subject: Re: [PATCH 2/3] of/fdt: Rework early_init_dt_scan_root() to call directly

On 11/18/21 1:12 PM, Rob Herring wrote:
> 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_root()
> to be called directly and use libfdt.
>
> Cc: Michael Ellerman <[email protected]>
> Cc: Benjamin Herrenschmidt <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Frank Rowand <[email protected]>
> Cc: [email protected]
> Signed-off-by: Rob Herring <[email protected]>
> ---
> arch/powerpc/kernel/prom.c | 4 ++--
> drivers/of/fdt.c | 14 +++++++-------
> include/linux/of_fdt.h | 3 +--
> 3 files changed, 10 insertions(+), 11 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index c6c398ccd98a..6e1a106f02eb 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -748,7 +748,7 @@ void __init early_init_devtree(void *params)
> of_scan_flat_dt(early_init_dt_scan_chosen_ppc, boot_command_line);
>
> /* Scan memory nodes and rebuild MEMBLOCKs */
> - of_scan_flat_dt(early_init_dt_scan_root, NULL);
> + early_init_dt_scan_root();
> of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
>
> parse_early_param();
> @@ -857,7 +857,7 @@ void __init early_get_first_memblock_info(void *params, phys_addr_t *size)
> * mess the memblock.
> */
> add_mem_to_memblock = 0;
> - of_scan_flat_dt(early_init_dt_scan_root, NULL);
> + early_init_dt_scan_root();
> of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
> add_mem_to_memblock = 1;
>
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 1f1705f76263..5e216555fe4f 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -1042,13 +1042,14 @@ int __init early_init_dt_scan_chosen_stdout(void)
> /*
> * early_init_dt_scan_root - fetch the top level address and size cells
> */
> -int __init early_init_dt_scan_root(unsigned long node, const char *uname,
> - int depth, void *data)
> +int __init early_init_dt_scan_root(void)
> {
> const __be32 *prop;
> + const void *fdt = initial_boot_params;
> + int node = fdt_path_offset(fdt, "/");
>
> - if (depth != 0)
> - return 0;
> + if (node < 0)
> + return -ENODEV;
>
> dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
> dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
> @@ -1063,8 +1064,7 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
> dt_root_addr_cells = be32_to_cpup(prop);
> pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
>
> - /* break now */
> - return 1;
> + return 0;
> }
>
> u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
> @@ -1263,7 +1263,7 @@ void __init early_init_dt_scan_nodes(void)
> int rc;
>
> /* Initialize {size,address}-cells info */
> - of_scan_flat_dt(early_init_dt_scan_root, NULL);
> + early_init_dt_scan_root();
>
> /* Retrieve various information from the /chosen node */
> rc = early_init_dt_scan_chosen(boot_command_line);
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index 654722235df6..df3d31926c3c 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -68,8 +68,7 @@ extern void early_init_dt_add_memory_arch(u64 base, u64 size);
> extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
>
> /* Early flat tree scan hooks */
> -extern int early_init_dt_scan_root(unsigned long node, const char *uname,
> - int depth, void *data);
> +extern int early_init_dt_scan_root(void);
>
> extern bool early_init_dt_scan(void *params);
> extern bool early_init_dt_verify(void *params);
>

Reviewed-by: Frank Rowand <[email protected]>

2021-11-24 16:59:10

by Frank Rowand

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

On 11/18/21 1:12 PM, Rob Herring wrote:
> 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]>
> ---
> arch/mips/ralink/of.c | 16 ++-------
> arch/powerpc/kernel/prom.c | 16 ++++-----
> drivers/of/fdt.c | 68 ++++++++++++++++++++------------------
> include/linux/of_fdt.h | 3 +-
> 4 files changed, 47 insertions(+), 56 deletions(-)
>
> diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
> index 0135376c5de5..e1d79523343a 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,9 +66,8 @@ 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);
> + if (!early_init_dt_scan_memory())
> + return;
> else if (soc_info.mem_detect)

The previous chunk is now:

if (XXX)
return;

instead of:

if (XXX)
YYY();

so "else if (soc_info.mem_detect)" should be:

if (soc_info.mem_detect)

> soc_info.mem_detect();
> else if (soc_info.mem_size)
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 6e1a106f02eb..63762a3b75e8 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -532,19 +532,19 @@ 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 +749,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 +858,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..a799117886f4 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)
> + return 0;

Should be "continue" instead of "return 0"?

>
> - 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);

Second line of pr_debug() should be indented one more space.

>
> - 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);
>



2021-11-24 17:01:48

by Frank Rowand

[permalink] [raw]
Subject: Re: [PATCH 0/3] of/fdt: Rework early FDT scanning functions

On 11/18/21 1:12 PM, Rob Herring wrote:
> The early FDT scanning functions use of_scan_flat_dt() which implements
> its own node walking method. This function predates libfdt and is an
> unnecessary indirection. This series reworks
> early_init_dt_scan_chosen(), early_init_dt_scan_root(), and
> early_init_dt_scan_memory() to be called directly and use libfdt calls.
>
> Ultimately, I want to remove of_scan_flat_dt(). Most of the remaining
> of_scan_flat_dt() users are in powerpc.
>
> Rob
>
>
> Rob Herring (3):
> of/fdt: Rework early_init_dt_scan_chosen() to call directly
> of/fdt: Rework early_init_dt_scan_root() to call directly
> of/fdt: Rework early_init_dt_scan_memory() to call directly
>
> arch/mips/ralink/of.c | 16 +---
> arch/powerpc/kernel/prom.c | 22 ++---
> arch/powerpc/mm/nohash/kaslr_booke.c | 4 +-
> drivers/of/fdt.c | 121 ++++++++++++++-------------
> include/linux/of_fdt.h | 9 +-
> 5 files changed, 79 insertions(+), 93 deletions(-)
>


"checkpatch --strict" reports some "CHECK" issues, but review of the patches
for correctness becomes much more difficult if they are addressed, so they
should be ignored for this series.

-Frank