* [PATCH v3 1/2] of: reserved_mem: group allocation helpers together
2026-10-15 8:23 ` [PATCH v3 0/2] of: reserved_mem: use dynamically allocated reserved_mem array Marek Szyprowski
@ 2026-10-15 8:23 ` Marek Szyprowski
2026-10-15 8:23 ` [PATCH v3 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski
1 sibling, 0 replies; 4+ messages in thread
From: Marek Szyprowski @ 2026-10-15 8:23 UTC (permalink / raw)
To: linux-mm, devicetree, linux-kernel
Cc: Marek Szyprowski, Mike Rapoport, Rob Herring, Saravana Kannan,
Oreoluwa Babatunde, Wandun, Andrew Morton
Move __reserved_mem_alloc_in_range() and __reserved_mem_alloc_size() right
after __reserved_mem_reserve_reg(), so the functions that reserve reserved
regions are grouped together and defined before their use.
No functional change.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/of/of_reserved_mem.c | 262 +++++++++++++++++------------------
1 file changed, 130 insertions(+), 132 deletions(-)
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 8c9d6395d6a3..300fb236ab59 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -178,6 +178,136 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
return 0;
}
+/*
+ * __reserved_mem_alloc_in_range() - allocate reserved memory described with
+ * 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
+ * reserved regions to keep the reserved memory contiguous if possible.
+ */
+static int __init __reserved_mem_alloc_in_range(phys_addr_t size,
+ phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
+ phys_addr_t *res_base)
+{
+ bool prev_bottom_up = memblock_bottom_up();
+ bool bottom_up = false, top_down = false;
+ int ret, i;
+
+ for (i = 0; i < reserved_mem_count; i++) {
+ struct reserved_mem *rmem = &reserved_mem[i];
+
+ /* Skip regions that were not reserved yet */
+ if (rmem->size == 0)
+ continue;
+
+ /*
+ * If range starts next to an existing reservation, use bottom-up:
+ * |....RRRR................RRRRRRRR..............|
+ * --RRRR------
+ */
+ if (start >= rmem->base && start <= (rmem->base + rmem->size))
+ bottom_up = true;
+
+ /*
+ * If range ends next to an existing reservation, use top-down:
+ * |....RRRR................RRRRRRRR..............|
+ * -------RRRR-----
+ */
+ if (end >= rmem->base && end <= (rmem->base + rmem->size))
+ top_down = true;
+ }
+
+ /* Change setting only if either bottom-up or top-down was selected */
+ if (bottom_up != top_down)
+ memblock_set_bottom_up(bottom_up);
+
+ ret = early_init_dt_alloc_reserved_memory_arch(size, align,
+ start, end, nomap, res_base);
+
+ /* Restore old setting if needed */
+ if (bottom_up != top_down)
+ memblock_set_bottom_up(prev_bottom_up);
+
+ return ret;
+}
+
+/*
+ * __reserved_mem_alloc_size() - allocate reserved memory described by
+ * 'size', 'alignment' and 'alloc-ranges' properties.
+ */
+static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname)
+{
+ phys_addr_t start = 0, end = 0;
+ phys_addr_t base = 0, align = 0, size;
+ int i, len;
+ const __be32 *prop;
+ bool nomap;
+ int ret;
+
+ prop = of_get_flat_dt_prop(node, "size", &len);
+ if (!prop)
+ return -EINVAL;
+
+ if (len != dt_root_size_cells * sizeof(__be32)) {
+ pr_err("invalid size property in '%s' node.\n", uname);
+ return -EINVAL;
+ }
+ size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+ prop = of_get_flat_dt_prop(node, "alignment", &len);
+ if (prop) {
+ if (len != dt_root_addr_cells * sizeof(__be32)) {
+ pr_err("invalid alignment property in '%s' node.\n",
+ uname);
+ return -EINVAL;
+ }
+ align = dt_mem_next_cell(dt_root_addr_cells, &prop);
+ }
+
+ nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
+
+ ret = fdt_validate_reserved_mem_node(node, &align);
+ if (ret && ret != -ENODEV)
+ return ret;
+
+ prop = of_flat_dt_get_addr_size_prop(node, "alloc-ranges", &len);
+ if (prop) {
+ for (i = 0; i < len; i++) {
+ u64 b, s;
+
+ of_flat_dt_read_addr_size(prop, i, &b, &s);
+
+ start = b;
+ end = b + s;
+
+ base = 0;
+ ret = __reserved_mem_alloc_in_range(size, align,
+ start, end, nomap, &base);
+ if (ret == 0) {
+ pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
+ uname, &base,
+ (unsigned long)(size / SZ_1M));
+ break;
+ }
+ }
+ } else {
+ ret = early_init_dt_alloc_reserved_memory_arch(size, align,
+ 0, 0, nomap, &base);
+ if (ret == 0)
+ pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
+ uname, &base, (unsigned long)(size / SZ_1M));
+ }
+
+ if (base == 0) {
+ pr_err("failed to allocate memory for node '%s': size %lu MiB\n",
+ uname, (unsigned long)(size / SZ_1M));
+ return -ENOMEM;
+ }
+
+ fdt_fixup_reserved_mem_node(node, base, size);
+ fdt_init_reserved_mem_node(node, uname, base, size);
+
+ return 0;
+}
+
/*
* __reserved_mem_check_root() - check if #size-cells, #address-cells provided
* in /reserved-memory matches the values supported by the current implementation,
@@ -316,8 +446,6 @@ void __init fdt_scan_reserved_mem_late(void)
__rmem_check_for_overlap();
}
-static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname);
-
/*
* fdt_scan_reserved_mem() - reserve and allocate memory occupied by
* reserved memory regions.
@@ -393,136 +521,6 @@ int __init fdt_scan_reserved_mem(void)
return 0;
}
-/*
- * __reserved_mem_alloc_in_range() - allocate reserved memory described with
- * 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
- * reserved regions to keep the reserved memory contiguous if possible.
- */
-static int __init __reserved_mem_alloc_in_range(phys_addr_t size,
- phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
- phys_addr_t *res_base)
-{
- bool prev_bottom_up = memblock_bottom_up();
- bool bottom_up = false, top_down = false;
- int ret, i;
-
- for (i = 0; i < reserved_mem_count; i++) {
- struct reserved_mem *rmem = &reserved_mem[i];
-
- /* Skip regions that were not reserved yet */
- if (rmem->size == 0)
- continue;
-
- /*
- * If range starts next to an existing reservation, use bottom-up:
- * |....RRRR................RRRRRRRR..............|
- * --RRRR------
- */
- if (start >= rmem->base && start <= (rmem->base + rmem->size))
- bottom_up = true;
-
- /*
- * If range ends next to an existing reservation, use top-down:
- * |....RRRR................RRRRRRRR..............|
- * -------RRRR-----
- */
- if (end >= rmem->base && end <= (rmem->base + rmem->size))
- top_down = true;
- }
-
- /* Change setting only if either bottom-up or top-down was selected */
- if (bottom_up != top_down)
- memblock_set_bottom_up(bottom_up);
-
- ret = early_init_dt_alloc_reserved_memory_arch(size, align,
- start, end, nomap, res_base);
-
- /* Restore old setting if needed */
- if (bottom_up != top_down)
- memblock_set_bottom_up(prev_bottom_up);
-
- return ret;
-}
-
-/*
- * __reserved_mem_alloc_size() - allocate reserved memory described by
- * 'size', 'alignment' and 'alloc-ranges' properties.
- */
-static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname)
-{
- phys_addr_t start = 0, end = 0;
- phys_addr_t base = 0, align = 0, size;
- int i, len;
- const __be32 *prop;
- bool nomap;
- int ret;
-
- prop = of_get_flat_dt_prop(node, "size", &len);
- if (!prop)
- return -EINVAL;
-
- if (len != dt_root_size_cells * sizeof(__be32)) {
- pr_err("invalid size property in '%s' node.\n", uname);
- return -EINVAL;
- }
- size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
- prop = of_get_flat_dt_prop(node, "alignment", &len);
- if (prop) {
- if (len != dt_root_addr_cells * sizeof(__be32)) {
- pr_err("invalid alignment property in '%s' node.\n",
- uname);
- return -EINVAL;
- }
- align = dt_mem_next_cell(dt_root_addr_cells, &prop);
- }
-
- nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
-
- ret = fdt_validate_reserved_mem_node(node, &align);
- if (ret && ret != -ENODEV)
- return ret;
-
- prop = of_flat_dt_get_addr_size_prop(node, "alloc-ranges", &len);
- if (prop) {
- for (i = 0; i < len; i++) {
- u64 b, s;
-
- of_flat_dt_read_addr_size(prop, i, &b, &s);
-
- start = b;
- end = b + s;
-
- base = 0;
- ret = __reserved_mem_alloc_in_range(size, align,
- start, end, nomap, &base);
- if (ret == 0) {
- pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
- uname, &base,
- (unsigned long)(size / SZ_1M));
- break;
- }
- }
- } else {
- ret = early_init_dt_alloc_reserved_memory_arch(size, align,
- 0, 0, nomap, &base);
- if (ret == 0)
- pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
- uname, &base, (unsigned long)(size / SZ_1M));
- }
-
- if (base == 0) {
- pr_err("failed to allocate memory for node '%s': size %lu MiB\n",
- uname, (unsigned long)(size / SZ_1M));
- return -ENOMEM;
- }
-
- fdt_fixup_reserved_mem_node(node, base, size);
- fdt_init_reserved_mem_node(node, uname, base, size);
-
- return 0;
-}
-
extern const struct of_device_id __reservedmem_of_table[];
static const struct of_device_id __rmem_of_table_sentinel
__used __section("__reservedmem_of_table_end");
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v3 2/2] of: reserved_mem: allocate and map the reserved_mem array early
2026-10-15 8:23 ` [PATCH v3 0/2] of: reserved_mem: use dynamically allocated reserved_mem array Marek Szyprowski
2026-10-15 8:23 ` [PATCH v3 1/2] of: reserved_mem: group allocation helpers together Marek Szyprowski
@ 2026-10-15 8:23 ` Marek Szyprowski
2026-10-15 8:51 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Marek Szyprowski @ 2026-10-15 8:23 UTC (permalink / raw)
To: linux-mm, devicetree, linux-kernel
Cc: Marek Szyprowski, Mike Rapoport, Rob Herring, Saravana Kannan,
Oreoluwa Babatunde, Wandun, Andrew Morton
Get rid of the static, limited-size reserved_mem array and replace it
with array allocated by memblock_alloc_raw() and accessed directly or
through a temporary early_memremap() mapping (depending on the
architecture support). Such mapping is needed for some architectures
(like ARM64), where linear map is not yet available during early boot
scan. The array is allocated from the bottom of RAM to avoid placing it
in highmem area, because some architectures (e.g. Xtensa, C-SKY, MIPS32)
set the memblock limit to the end of lowmem only after the early scan.
The early mapping is not used on PPC64, where the scan is done before
early_ioremap_setup(), but the memory allocated by memblock is already
accessible at that point.
Having a single, writeable array with all reserved regions removes the
need to perform two step initialization introduced by commit
8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory
regions are processed"), so all regions can be processed during the
early scan again.
The reserved_mem array is allocated only after all static (defined by
the 'reg' property) regions are marked as reserved or no-map, so it
cannot be placed in any of them. Errors of the early reservations are
not recorded per region, only the fact that some of them failed is
stored and a message asking to fix the device-tree is printed. The
region specific init functions for the static regions are then called
in a separate pass, once the array is available. Then all dynamically
allocated reserved regions are processed.
Suggested-by: Mike Rapoport <rppt@kernel.org>
Link: https://lore.kernel.org/all/asc6brs_g0ky0wOM@kernel.org/
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/of/fdt.c | 3 -
drivers/of/of_private.h | 2 -
drivers/of/of_reserved_mem.c | 277 ++++++++++++++++-------------------
3 files changed, 123 insertions(+), 159 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ecc923102622..a58efdcbac7f 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1283,9 +1283,6 @@ void __init unflatten_device_tree(void)
{
void *fdt = initial_boot_params;
- /* Save the statically-placed regions in the reserved_mem array */
- fdt_scan_reserved_mem_late();
-
/* Populate an empty root node when bootloader doesn't provide one */
if (!fdt) {
fdt = (void *) __dtb_empty_root_begin;
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 0ae16da066e2..895f868b4cfa 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -9,7 +9,6 @@
*/
#define FDT_ALIGN_SIZE 8
-#define MAX_RESERVED_REGIONS 64
/**
* struct alias_prop - Alias property in 'aliases' node
@@ -186,7 +185,6 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
#endif
int fdt_scan_reserved_mem(void);
-void __init fdt_scan_reserved_mem_late(void);
bool of_fdt_device_is_available(const void *blob, unsigned long node);
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 300fb236ab59..0fd1683cba01 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -27,10 +27,10 @@
#include "of_private.h"
-static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS] __initdata;
-static struct reserved_mem *reserved_mem __refdata = reserved_mem_array;
-static int total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
+static struct reserved_mem *reserved_mem __refdata;
+static int total_reserved_mem_cnt;
static int reserved_mem_count;
+static bool reserved_mem_reserve_failed __initdata;
static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
@@ -59,57 +59,28 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
}
/*
- * alloc_reserved_mem_array() - allocate memory for the reserved_mem
- * array using memblock
- *
- * This function is used to allocate memory for the reserved_mem
- * array according to the total number of reserved memory regions
- * defined in the DT.
- * After the new array is allocated, the information stored in
- * the initial static array is copied over to this new array and
- * the new array is used from this point on.
+ * On some architectures (e.g. ARM64) the linear mapping is not yet usable
+ * during the early reserved memory scan, so the array has to be accessed
+ * through a temporary early mapping. PPC64 runs the scan before early_ioremap
+ * is initialized, but the memory returned by memblock is already accessible.
*/
-static int __init alloc_reserved_mem_array(void)
+#if defined(CONFIG_GENERIC_EARLY_IOREMAP) && !defined(CONFIG_PPC64)
+#include <asm/early_ioremap.h>
+static inline void *early_array_map(void *array, size_t size)
{
- struct reserved_mem *new_array;
- size_t alloc_size, copy_size, memset_size;
- int ret;
-
- if (!total_reserved_mem_cnt)
- return 0;
-
- alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array));
- if (alloc_size == SIZE_MAX) {
- ret = -EOVERFLOW;
- goto fail;
- }
-
- new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
- if (!new_array) {
- ret = -ENOMEM;
- goto fail;
- }
-
- copy_size = array_size(reserved_mem_count, sizeof(*new_array));
- if (copy_size == SIZE_MAX) {
- memblock_free(new_array, alloc_size);
- ret = -EOVERFLOW;
- goto fail;
- }
-
- memset_size = alloc_size - copy_size;
-
- memcpy(new_array, reserved_mem, copy_size);
- memset(new_array + reserved_mem_count, 0, memset_size);
-
- reserved_mem = new_array;
- return 0;
-
-fail:
- pr_err("Failed to allocate memory for reserved_mem array with err: %d", ret);
- reserved_mem_count = 0;
- return ret;
+ return early_memremap(__pa(array), size);
+}
+static inline void early_array_unmap(void *map, size_t size)
+{
+ early_memunmap(map, size);
+}
+#else
+static inline void *early_array_map(void *array, size_t size)
+{
+ return array;
}
+static inline void early_array_unmap(void *map, size_t size) {}
+#endif
static void fdt_init_reserved_mem_node(unsigned long node, const char *uname,
phys_addr_t base, phys_addr_t size);
@@ -174,10 +145,42 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
} 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));
+ reserved_mem_reserve_failed = true;
}
return 0;
}
+/*
+ * __reserved_mem_init_reg() - initialize a static reserved memory region
+ * described in the first entry in 'reg' property
+ */
+static int __init __reserved_mem_init_reg(unsigned long node,
+ const char *uname)
+{
+ phys_addr_t base, size;
+ const __be32 *prop;
+ int len, err;
+ u64 b, s;
+
+ prop = of_flat_dt_get_addr_size_prop(node, "reg", &len);
+ if (!prop || !len)
+ return -ENOENT;
+
+ err = fdt_validate_reserved_mem_node(node, NULL);
+ if (err && err != -ENODEV)
+ return err;
+
+ of_flat_dt_read_addr_size(prop, 0, &b, &s);
+ base = b;
+ size = s;
+
+ if (!size)
+ return -ENOENT;
+
+ fdt_init_reserved_mem_node(node, uname, base, size);
+ return 0;
+}
+
/*
* __reserved_mem_alloc_in_range() - allocate reserved memory described with
* 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
@@ -381,143 +384,109 @@ static void __init __rmem_check_for_overlap(void)
}
}
-/**
- * fdt_scan_reserved_mem_late() - Scan FDT and initialize remaining reserved
- * memory regions.
+/*
+ * fdt_scan_reserved_mem() - reserve and allocate memory occupied by
+ * reserved memory regions.
*
- * This function is used to scan again through the DT and initialize the
- * "static" reserved memory regions, that are defined using the "reg"
- * property. Each such region is then initialized with its specific init
- * function and stored in the global reserved_mem array.
+ * This function is used to scan through the FDT, mark all static (defined by
+ * the "reg" property) reserved memory regions as reserved or no-map. Then
+ * the reserved_mem array is allocated and a region specific init function
+ * is called for each static region. Finally, memory for all dynamic regions
+ * (defined by size & alignment) is allocated and their init functions are
+ * called. Region information is stored in the reserved_mem array.
*/
-void __init fdt_scan_reserved_mem_late(void)
+int __init fdt_scan_reserved_mem(void)
{
+ struct reserved_mem *array, *map;
+ bool bottom_up = memblock_bottom_up();
+ size_t array_bytes;
+ int node, child, cnt = 0;
const void *fdt = initial_boot_params;
- phys_addr_t base, size;
- int node, child;
-
- if (!fdt)
- return;
node = fdt_path_offset(fdt, "/reserved-memory");
- if (node < 0) {
- pr_info("Reserved memory: No reserved-memory node in the DT\n");
- return;
- }
-
- /* Attempt dynamic allocation of a new reserved_mem array */
- if (alloc_reserved_mem_array())
- return;
+ if (node < 0)
+ return -ENODEV;
- if (__reserved_mem_check_root(node)) {
+ if (__reserved_mem_check_root(node) != 0) {
pr_err("Reserved memory: unsupported node format, ignoring\n");
- return;
+ return -EINVAL;
}
+ /* First pass: reserve the statically-placed regions */
fdt_for_each_subnode(child, fdt, node) {
- const __be32 *prop;
- const char *uname;
- u64 b, s;
- int ret;
int len;
if (!of_fdt_device_is_available(fdt, child))
continue;
- prop = of_flat_dt_get_addr_size_prop(child, "reg", &len);
- if (!prop || !len)
- continue;
-
- ret = fdt_validate_reserved_mem_node(child, NULL);
- if (ret && ret != -ENODEV)
- continue;
-
- of_flat_dt_read_addr_size(prop, 0, &b, &s);
- base = b;
- size = s;
+ /* static regions use 'reg', dynamic ones use 'size' */
+ if ((of_flat_dt_get_addr_size_prop(child, "reg", &len) && len) ||
+ (of_get_flat_dt_prop(child, "size", &len) && len))
+ cnt++;
- if (size) {
- uname = fdt_get_name(fdt, child, NULL);
- fdt_init_reserved_mem_node(child, uname, base, size);
- }
+ __reserved_mem_reserve_reg(child,
+ fdt_get_name(fdt, child, NULL));
}
- /* check for overlapping reserved regions */
- __rmem_check_for_overlap();
-}
+ if (reserved_mem_reserve_failed)
+ pr_err("Some reserved memory regions could not be reserved, system might be unstable. Please fix the device-tree.\n");
-/*
- * fdt_scan_reserved_mem() - reserve and allocate memory occupied by
- * reserved memory regions.
- *
- * This function is used to scan through the FDT and mark memory occupied
- * by all static (defined by the "reg" property) reserved memory regions.
- * Then memory for all dynamic regions (defined by size & alignment) is
- * allocated, a region specific init function is called and region information
- * is stored in the reserved_mem array.
- */
-int __init fdt_scan_reserved_mem(void)
-{
- int node, child;
- int dynamic_nodes_cnt = 0, count = 0;
- int dynamic_nodes[MAX_RESERVED_REGIONS];
- const void *fdt = initial_boot_params;
+ if (!cnt)
+ return 0;
- node = fdt_path_offset(fdt, "/reserved-memory");
- if (node < 0) {
- total_reserved_mem_cnt = 0;
- return -ENODEV;
+ array_bytes = array_size(cnt, sizeof(*array));
+ /*
+ * Allocate bottom-up, as some architectures (e.g. Xtensa, C-SKY,
+ * MIPS32) don't limit memblock to lowmem yet at this point.
+ */
+ memblock_set_bottom_up(true);
+ array = memblock_alloc_raw(array_bytes, SMP_CACHE_BYTES);
+ memblock_set_bottom_up(bottom_up);
+ if (!array) {
+ pr_err("Failed to allocate memory for reserved_mem array\n");
+ return -ENOMEM;
}
- if (__reserved_mem_check_root(node) != 0) {
- pr_err("Reserved memory: unsupported node format, ignoring\n");
- total_reserved_mem_cnt = 0;
- return -EINVAL;
+ map = early_array_map(array, array_bytes);
+ if (!map) {
+ pr_err("Failed to map memory for reserved_mem array\n");
+ memblock_free(array, array_bytes);
+ return -ENOMEM;
}
+ memset(map, 0, array_bytes);
- fdt_for_each_subnode(child, fdt, node) {
- const char *uname;
- int err;
+ reserved_mem = map;
+ total_reserved_mem_cnt = cnt;
+ /* Second pass: initialize the static regions */
+ fdt_for_each_subnode(child, fdt, node) {
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)
- count++;
+ __reserved_mem_init_reg(child, fdt_get_name(fdt, child, NULL));
+ }
- /*
- * Save the nodes for the dynamically-placed regions
- * into an array which will be used for allocation right
- * after all the statically-placed regions are reserved
- * or marked as no-map. This is done to avoid dynamically
- * allocating from one of the statically-placed regions.
- */
- if (err != -ENOENT || !of_get_flat_dt_prop(child, "size", NULL))
- continue;
+ /*
+ * Allocate the dynamically-placed regions only after all the
+ * statically-placed ones are reserved, to avoid overlapping with them.
+ */
+ fdt_for_each_subnode(child, fdt, node) {
+ int len;
- if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) {
- pr_err("too many defined dynamic regions, skip '%s'\n",
- uname);
+ if (!of_fdt_device_is_available(fdt, child) ||
+ (of_flat_dt_get_addr_size_prop(child, "reg", &len) && len))
continue;
- }
- dynamic_nodes[dynamic_nodes_cnt] = child;
- dynamic_nodes_cnt++;
- }
- for (int i = 0; i < dynamic_nodes_cnt; i++) {
- const char *uname;
- int err;
-
- child = dynamic_nodes[i];
- uname = fdt_get_name(fdt, child, NULL);
- err = __reserved_mem_alloc_size(child, uname);
- if (!err)
- count++;
+ __reserved_mem_alloc_size(child,
+ fdt_get_name(fdt, child, NULL));
}
- total_reserved_mem_cnt = count;
+
+ /* Check for overlapping reserved regions */
+ __rmem_check_for_overlap();
+
+ /* Switch to the permanent address of the array */
+ early_array_unmap(map, array_bytes);
+ reserved_mem = array;
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread