[RFC PATCH v2 4/6] of: reserved_mem: Add code to use unflattened DT for reserved_mem nodes

From: Oreoluwa Babatunde
Date: Sun Dec 03 2023 - 23:14:39 EST


The unflattened devicetree APIs are available to be used right after
paging_init() runs. Therefore, use the unflattened devicetree APIs to
process the reserved memory regions from this point.

Using the unflattened devicetree APIs is more efficient than using the
flattened devicetree APIs.

Signed-off-by: Oreoluwa Babatunde <quic_obabatun@xxxxxxxxxxx>
---
drivers/of/fdt.c | 51 +--------------------
drivers/of/of_private.h | 4 +-
drivers/of/of_reserved_mem.c | 79 +++++++++++++++++++++++++--------
include/linux/of_fdt.h | 1 -
include/linux/of_reserved_mem.h | 2 +-
kernel/dma/coherent.c | 4 +-
kernel/dma/contiguous.c | 8 ++--
kernel/dma/swiotlb.c | 10 ++---
8 files changed, 76 insertions(+), 83 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 46adce306bbd..12769dd53c34 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -558,55 +558,6 @@ static int __init __reserved_mem_check_root(unsigned long node)
return 0;
}

-/*
- * Save the reserved_mem reg nodes in the reserved_mem array
- */
-void __init fdt_scan_reserved_mem_reg_nodes(void)
-
-{
- int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
- const void *fdt = initial_boot_params;
- phys_addr_t base, size;
- const __be32 *prop;
- int node, child;
- int len;
-
- node = fdt_path_offset(fdt, "/reserved-memory");
- if (node < 0) {
- pr_err("Reserved memory: Did not find reserved-memory node\n");
- return;
- }
-
- if (__reserved_mem_check_root(node) != 0) {
- pr_err("Reserved memory: unsupported node format, ignoring\n");
- return;
- }
-
- fdt_for_each_subnode(child, fdt, node) {
- const char *uname;
-
- prop = of_get_flat_dt_prop(child, "reg", &len);
- if (!prop)
- continue;
-
- if (!of_fdt_device_is_available(fdt, child))
- continue;
-
- uname = fdt_get_name(fdt, child, NULL);
- if (len && len % t_len != 0) {
- pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
- uname);
- continue;
- }
-
- base = dt_mem_next_cell(dt_root_addr_cells, &prop);
- size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
- if (size)
- fdt_reserved_mem_save_node(child, uname, base, size);
- }
-}
-
/*
* fdt_scan_reserved_mem() - scan a single FDT node for reserved memory.
*/
@@ -1393,7 +1344,7 @@ void __init unflatten_device_tree(void)
unittest_unflatten_overlay_base();

/*Initialize the reserved_mem regions*/
- fdt_init_reserved_mem();
+ init_reserved_mem();
}

/**
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 57694a704b00..575e2b4119e0 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -176,8 +176,8 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
}
#endif

-void fdt_init_reserved_mem(void);
-void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
+void init_reserved_mem(void);
+void dt_reserved_mem_save_node(struct device_node *node, const char *uname,
phys_addr_t base, phys_addr_t size);

#endif /* _LINUX_OF_PRIVATE_H */
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index d62f1956024c..2ef9edcb8c93 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -55,9 +55,9 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
}

/*
- * fdt_reserved_mem_save_node() - save fdt node for second pass initialization
+ * dt_reserved_mem_save_node() - save dt node for second pass initialization
*/
-void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
+void __init dt_reserved_mem_save_node(struct device_node *node, const char *uname,
phys_addr_t base, phys_addr_t size)
{
struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
@@ -67,7 +67,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
return;
}

- rmem->fdt_node = node;
+ rmem->dev_node = node;
rmem->name = uname;
rmem->base = base;
rmem->size = size;
@@ -76,6 +76,54 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
return;
}

+/*
+ * Save the reserved_mem reg nodes in the reserved_mem array
+ */
+static void __init scan_reserved_mem_reg_nodes(void)
+
+{
+ int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
+ struct device_node *node, *child;
+ phys_addr_t base, size;
+ const __be32 *prop;
+ int len;
+
+ node = of_find_node_by_path("/reserved-memory");
+ if (node < 0) {
+ pr_err("Reserved memory: Did not find reserved-memory node\n");
+ return;
+ }
+
+ for_each_child_of_node(node, child) {
+ const char *uname;
+ struct reserved_mem *rmem;
+
+ if (!of_device_is_available(child))
+ continue;
+
+ prop = of_get_property(child, "reg", &len);
+ if (!prop) {
+ rmem = of_reserved_mem_lookup(child);
+ if (rmem)
+ rmem->dev_node = child;
+ continue;
+ }
+
+ uname = of_node_full_name(child);
+ if (len && len % t_len != 0) {
+ pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
+ uname);
+ continue;
+ }
+
+ base = dt_mem_next_cell(dt_root_addr_cells, &prop);
+ size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+ if (size)
+ dt_reserved_mem_save_node(child, uname, base, size);
+ }
+}
+
/*
* __reserved_mem_alloc_in_range() - allocate reserved memory described with
* 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
@@ -210,7 +258,7 @@ int __init __reserved_mem_alloc_size(unsigned long node, const char *uname)
uname, (unsigned long)(size / SZ_1M));
return -ENOMEM;
}
- fdt_reserved_mem_save_node(node, uname, base, size);
+ dt_reserved_mem_save_node(NULL, uname, base, size);
return 0;
}

@@ -230,7 +278,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
reservedmem_of_init_fn initfn = i->data;
const char *compat = i->compatible;

- if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
+ if (!of_device_is_compatible(rmem->dev_node, compat))
continue;

ret = initfn(rmem);
@@ -263,11 +311,6 @@ static int __init __rmem_cmp(const void *a, const void *b)
if (ra->size > rb->size)
return 1;

- if (ra->fdt_node < rb->fdt_node)
- return -1;
- if (ra->fdt_node > rb->fdt_node)
- return 1;
-
return 0;
}

@@ -299,29 +342,29 @@ static void __init __rmem_check_for_overlap(void)
}

/**
- * fdt_init_reserved_mem() - allocate and init all saved reserved memory regions
+ * init_reserved_mem() - allocate and init all saved reserved memory regions
*/
-void __init fdt_init_reserved_mem(void)
+void __init init_reserved_mem(void)
{
int i;

- fdt_scan_reserved_mem_reg_nodes();
+ scan_reserved_mem_reg_nodes();

/* check for overlapping reserved regions */
__rmem_check_for_overlap();

for (i = 0; i < reserved_mem_count; i++) {
struct reserved_mem *rmem = &reserved_mem[i];
- unsigned long node = rmem->fdt_node;
+ struct device_node *node = rmem->dev_node;
int len;
const __be32 *prop;
int err = 0;
bool nomap;

- nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
- prop = of_get_flat_dt_prop(node, "phandle", &len);
+ nomap = of_get_property(node, "no-map", NULL) != NULL;
+ prop = of_get_property(node, "phandle", &len);
if (!prop)
- prop = of_get_flat_dt_prop(node, "linux,phandle", &len);
+ prop = of_get_property(node, "linux,phandle", &len);
if (prop)
rmem->phandle = of_read_number(prop, len/4);

@@ -337,7 +380,7 @@ void __init fdt_init_reserved_mem(void)
} else {
phys_addr_t end = rmem->base + rmem->size - 1;
bool reusable =
- (of_get_flat_dt_prop(node, "reusable", NULL)) != NULL;
+ (of_get_property(node, "reusable", NULL)) != NULL;

pr_info("%pa..%pa (%lu KiB) %s %s %s\n",
&rmem->base, &end, (unsigned long)(rmem->size / SZ_1K),
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 7b2a5d93d719..d69ad5bb1eb1 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -73,7 +73,6 @@ extern int early_init_dt_scan_root(void);
extern bool early_init_dt_scan(void *params);
extern bool early_init_dt_verify(void *params);
extern void early_init_dt_scan_nodes(void);
-extern void fdt_scan_reserved_mem_reg_nodes(void);

extern const char *of_flat_dt_get_machine_name(void);
extern const void *of_flat_dt_match_machine(const void *default_match,
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index dc13bcd04b12..2b205ce6beb9 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -10,7 +10,7 @@ struct reserved_mem_ops;

struct reserved_mem {
const char *name;
- unsigned long fdt_node;
+ struct device_node *dev_node;
unsigned long phandle;
const struct reserved_mem_ops *ops;
phys_addr_t base;
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index c21abc77c53e..3eba9678dc33 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -360,9 +360,9 @@ static const struct reserved_mem_ops rmem_dma_ops = {

static int __init rmem_dma_setup(struct reserved_mem *rmem)
{
- unsigned long node = rmem->fdt_node;
+ struct device_node *node = rmem->dev_node;

- if (of_get_flat_dt_prop(node, "reusable", NULL))
+ if (of_get_property(node, "reusable", NULL))
return -EINVAL;

#ifdef CONFIG_ARM
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index f005c66f378c..b54cf128a9d9 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -462,8 +462,8 @@ static const struct reserved_mem_ops rmem_cma_ops = {

static int __init rmem_cma_setup(struct reserved_mem *rmem)
{
- unsigned long node = rmem->fdt_node;
- bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
+ struct device_node *node = rmem->dev_node;
+ bool default_cma = of_get_property(node, "linux,cma-default", NULL);
struct cma *cma;
int err;

@@ -473,8 +473,8 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
return -EBUSY;
}

- if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
- of_get_flat_dt_prop(node, "no-map", NULL))
+ if (!of_get_property(node, "reusable", NULL) ||
+ of_get_property(node, "no-map", NULL))
return -EINVAL;

if (!IS_ALIGNED(rmem->base | rmem->size, CMA_MIN_ALIGNMENT_BYTES)) {
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 33d942615be5..14840a58a6e6 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -1709,12 +1709,12 @@ static const struct reserved_mem_ops rmem_swiotlb_ops = {

static int __init rmem_swiotlb_setup(struct reserved_mem *rmem)
{
- unsigned long node = rmem->fdt_node;
+ struct device_node *node = rmem->dev_node;

- if (of_get_flat_dt_prop(node, "reusable", NULL) ||
- of_get_flat_dt_prop(node, "linux,cma-default", NULL) ||
- of_get_flat_dt_prop(node, "linux,dma-default", NULL) ||
- of_get_flat_dt_prop(node, "no-map", NULL))
+ if (of_get_property(node, "reusable", NULL) ||
+ of_get_property(node, "linux,cma-default", NULL) ||
+ of_get_property(node, "linux,dma-default", NULL) ||
+ of_get_property(node, "no-map", NULL))
return -EINVAL;

rmem->ops = &rmem_swiotlb_ops;
--
2.17.1