[PATCH 30/46] of: reserved_mem: Add code to use unflattened DT for reserved_mem nodes

From: Oreoluwa Babatunde
Date: Fri Jan 26 2024 - 19:07:14 EST


The unflattened devicetree APIs are available to be used not long after
the processing is done for the reserved memory regions on some
architectures, and is available even before that on other architectures.
Therefore, use the unflattened devicetree APIs to process and store
information for the reserved memory regions.

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 | 49 ----------------------
drivers/of/of_private.h | 4 +-
drivers/of/of_reserved_mem.c | 74 ++++++++++++++++++++++++++-------
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, 72 insertions(+), 80 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ebd2fa9e0114..2bc01ffdabfe 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.
*/
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index c338e1c019c7..f7da22108e7a 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -177,7 +177,7 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
#endif

void update_reserved_mem_max_cnt(int max_count);
-void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
- phys_addr_t base, phys_addr_t size);
+void fdt_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 419b062cb41f..645b02e27492 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -96,11 +96,58 @@ static int alloc_reserved_mem_array(void)
return -1;
}

+/*
+ * Save the reserved_mem reg nodes in the reserved_mem array
+ */
+static void __init dt_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)
+ fdt_reserved_mem_save_node(child, uname, base, size);
+ }
+}
+
/*
* fdt_reserved_mem_save_node() - save fdt node for second pass initialization
*/
-void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
- phys_addr_t base, phys_addr_t size)
+void __init fdt_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];

@@ -109,7 +156,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;
@@ -252,7 +299,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);
+ fdt_reserved_mem_save_node(NULL, uname, base, size);
return 0;
}

@@ -272,7 +319,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);
@@ -305,11 +352,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;
}

@@ -351,23 +393,23 @@ void __init fdt_init_reserved_mem(void)
if (ret)
pr_err("Failed to allocate memory for reserved_mem array with err: %d", ret);

- fdt_scan_reserved_mem_reg_nodes();
+ dt_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);

@@ -383,7 +425,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 9b85bbc5d9f5..fb7b437141bd 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 2a3178920bae..e92babd669c2 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 ff5683a57f77..5ab26fe11c29 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -362,9 +362,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 b079a9a8e087..ea1f734c8c35 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -1732,12 +1732,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