of: Move all FDT reserved-memory handling into of_reserved_mem.c
authorRob Herring <robh@kernel.org>
Mon, 11 Mar 2024 18:13:03 +0000 (12:13 -0600)
committerRob Herring <robh@kernel.org>
Tue, 12 Mar 2024 15:23:26 +0000 (09:23 -0600)
The split of /reserved-memory handling between fdt.c and
of_reserved_mem.c makes for reading and restructuring the code
difficult. As of_reserved_mem.c is only built for
CONFIG_OF_EARLY_FLATTREE already, move all the code to one spot.

Acked-by: Saravana Kannan <saravanak@google.com>
Reviewed-by: Oreoluwa Babatunde <quic_obabatun@quicinc.com>
Link: https://lore.kernel.org/r/20240311181303.1516514-2-robh@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
drivers/of/fdt.c
drivers/of/of_private.h
drivers/of/of_reserved_mem.c

index e5a385285149ee1a3f0550e053b9743d5813848d..a8a04f27915b93f1d04e45aa882c48a041192c09 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/sizes.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -88,7 +87,7 @@ void __init of_fdt_limit_memory(int limit)
        }
 }
 
-static bool of_fdt_device_is_available(const void *blob, unsigned long node)
+bool of_fdt_device_is_available(const void *blob, unsigned long node)
 {
        const char *status = fdt_getprop(blob, node, "status", NULL);
 
@@ -484,126 +483,6 @@ void *initial_boot_params __ro_after_init;
 
 static u32 of_fdt_crc32;
 
-static int __init early_init_dt_reserve_memory(phys_addr_t base,
-                                              phys_addr_t size, bool nomap)
-{
-       if (nomap) {
-               /*
-                * If the memory is already reserved (by another region), we
-                * should not allow it to be marked nomap, but don't worry
-                * if the region isn't memory as it won't be mapped.
-                */
-               if (memblock_overlaps_region(&memblock.memory, base, size) &&
-                   memblock_is_region_reserved(base, size))
-                       return -EBUSY;
-
-               return memblock_mark_nomap(base, size);
-       }
-       return memblock_reserve(base, size);
-}
-
-/*
- * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property
- */
-static int __init __reserved_mem_reserve_reg(unsigned long node,
-                                            const char *uname)
-{
-       int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
-       phys_addr_t base, size;
-       int len;
-       const __be32 *prop;
-       int first = 1;
-       bool nomap;
-
-       prop = of_get_flat_dt_prop(node, "reg", &len);
-       if (!prop)
-               return -ENOENT;
-
-       if (len && len % t_len != 0) {
-               pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
-                      uname);
-               return -EINVAL;
-       }
-
-       nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
-
-       while (len >= t_len) {
-               base = dt_mem_next_cell(dt_root_addr_cells, &prop);
-               size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
-               if (size &&
-                   early_init_dt_reserve_memory(base, size, nomap) == 0)
-                       pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
-                               uname, &base, (unsigned long)(size / SZ_1M));
-               else
-                       pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
-                              uname, &base, (unsigned long)(size / SZ_1M));
-
-               len -= t_len;
-               if (first) {
-                       fdt_reserved_mem_save_node(node, uname, base, size);
-                       first = 0;
-               }
-       }
-       return 0;
-}
-
-/*
- * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
- * in /reserved-memory matches the values supported by the current implementation,
- * also check if ranges property has been provided
- */
-static int __init __reserved_mem_check_root(unsigned long node)
-{
-       const __be32 *prop;
-
-       prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
-       if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
-               return -EINVAL;
-
-       prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
-       if (!prop || be32_to_cpup(prop) != dt_root_addr_cells)
-               return -EINVAL;
-
-       prop = of_get_flat_dt_prop(node, "ranges", NULL);
-       if (!prop)
-               return -EINVAL;
-       return 0;
-}
-
-/*
- * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
- */
-static int __init fdt_scan_reserved_mem(void)
-{
-       int node, child;
-       const void *fdt = initial_boot_params;
-
-       node = fdt_path_offset(fdt, "/reserved-memory");
-       if (node < 0)
-               return -ENODEV;
-
-       if (__reserved_mem_check_root(node) != 0) {
-               pr_err("Reserved memory: unsupported node format, ignoring\n");
-               return -EINVAL;
-       }
-
-       fdt_for_each_subnode(child, fdt, node) {
-               const char *uname;
-               int err;
-
-               if (!of_fdt_device_is_available(fdt, child))
-                       continue;
-
-               uname = fdt_get_name(fdt, child, NULL);
-
-               err = __reserved_mem_reserve_reg(child, uname);
-               if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL))
-                       fdt_reserved_mem_save_node(child, uname, 0, 0);
-       }
-       return 0;
-}
-
 /*
  * fdt_reserve_elfcorehdr() - reserves memory for elf core header
  *
index f38397c7b58241799bfd8e8d4395180bf88b118e..485483524b7f1cf1e2c0833c063cd24637de7751 100644 (file)
@@ -175,8 +175,9 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
 }
 #endif
 
+int fdt_scan_reserved_mem(void);
 void fdt_init_reserved_mem(void);
-void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
-                              phys_addr_t base, phys_addr_t size);
+
+bool of_fdt_device_is_available(const void *blob, unsigned long node);
 
 #endif /* _LINUX_OF_PRIVATE_H */
index 7ec94cfcbddb18e3645212e57b6b96d4ee1645c7..8236ecae29533694ae4efbc4251a0182c4af99d6 100644 (file)
@@ -12,6 +12,7 @@
 #define pr_fmt(fmt)    "OF: reserved mem: " fmt
 
 #include <linux/err.h>
+#include <linux/libfdt.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -58,8 +59,8 @@ 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
  */
-void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
-                                     phys_addr_t base, phys_addr_t size)
+static void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
+                                             phys_addr_t base, phys_addr_t size)
 {
        struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
 
@@ -77,6 +78,126 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
        return;
 }
 
+static int __init early_init_dt_reserve_memory(phys_addr_t base,
+                                              phys_addr_t size, bool nomap)
+{
+       if (nomap) {
+               /*
+                * If the memory is already reserved (by another region), we
+                * should not allow it to be marked nomap, but don't worry
+                * if the region isn't memory as it won't be mapped.
+                */
+               if (memblock_overlaps_region(&memblock.memory, base, size) &&
+                   memblock_is_region_reserved(base, size))
+                       return -EBUSY;
+
+               return memblock_mark_nomap(base, size);
+       }
+       return memblock_reserve(base, size);
+}
+
+/*
+ * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property
+ */
+static int __init __reserved_mem_reserve_reg(unsigned long node,
+                                            const char *uname)
+{
+       int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
+       phys_addr_t base, size;
+       int len;
+       const __be32 *prop;
+       int first = 1;
+       bool nomap;
+
+       prop = of_get_flat_dt_prop(node, "reg", &len);
+       if (!prop)
+               return -ENOENT;
+
+       if (len && len % t_len != 0) {
+               pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
+                      uname);
+               return -EINVAL;
+       }
+
+       nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
+
+       while (len >= t_len) {
+               base = dt_mem_next_cell(dt_root_addr_cells, &prop);
+               size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+               if (size &&
+                   early_init_dt_reserve_memory(base, size, nomap) == 0)
+                       pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
+                               uname, &base, (unsigned long)(size / SZ_1M));
+               else
+                       pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
+                              uname, &base, (unsigned long)(size / SZ_1M));
+
+               len -= t_len;
+               if (first) {
+                       fdt_reserved_mem_save_node(node, uname, base, size);
+                       first = 0;
+               }
+       }
+       return 0;
+}
+
+/*
+ * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
+ * in /reserved-memory matches the values supported by the current implementation,
+ * also check if ranges property has been provided
+ */
+static int __init __reserved_mem_check_root(unsigned long node)
+{
+       const __be32 *prop;
+
+       prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
+       if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
+               return -EINVAL;
+
+       prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
+       if (!prop || be32_to_cpup(prop) != dt_root_addr_cells)
+               return -EINVAL;
+
+       prop = of_get_flat_dt_prop(node, "ranges", NULL);
+       if (!prop)
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
+ */
+int __init fdt_scan_reserved_mem(void)
+{
+       int node, child;
+       const void *fdt = initial_boot_params;
+
+       node = fdt_path_offset(fdt, "/reserved-memory");
+       if (node < 0)
+               return -ENODEV;
+
+       if (__reserved_mem_check_root(node) != 0) {
+               pr_err("Reserved memory: unsupported node format, ignoring\n");
+               return -EINVAL;
+       }
+
+       fdt_for_each_subnode(child, fdt, node) {
+               const char *uname;
+               int err;
+
+               if (!of_fdt_device_is_available(fdt, child))
+                       continue;
+
+               uname = fdt_get_name(fdt, child, NULL);
+
+               err = __reserved_mem_reserve_reg(child, uname);
+               if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL))
+                       fdt_reserved_mem_save_node(child, uname, 0, 0);
+       }
+       return 0;
+}
+
 /*
  * __reserved_mem_alloc_in_range() - allocate reserved memory described with
  *     'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing