* [PATCH v2 0/2] of: reserved_mem: use dynamically allocated reserved_mem array [not found] <CGME20261008152449eucas1p29758be26c325084093c14cfa9b8b2d04@eucas1p2.samsung.com> @ 2026-10-08 15:23 ` Marek Szyprowski 2026-10-08 15:24 ` [PATCH v2 1/2] of: reserved_mem: group allocation helpers together Marek Szyprowski 2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski 0 siblings, 2 replies; 7+ messages in thread From: Marek Szyprowski @ 2026-10-08 15:23 UTC (permalink / raw) To: linux-mm, devicetree, linux-kernel Cc: Marek Szyprowski, Mike Rapoport, Rob Herring, Saravana Kannan, Oreoluwa Babatunde, Wandun, Andrew Morton Mike Rapoport suggested [1] how to properly use dynamically allocated arrays during early boot. Use this approach for reserved_mem array during early scan of the reserved regions. Having all the reserved regions in a single array removes the need of the two pass initialization introduced by commit 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed"), so implement it to make the code simpler, easier to understand and ready for adding proper error checking. Tested on ARM32, ARM64 and RiscV64 based boards. [1] https://lore.kernel.org/all/asc6brs_g0ky0wOM@kernel.org/ Best regards Marek Szyprowski, PhD Samsung R&D Institute Poland Changelog: v2: - removed superfluous ifdefs v1: https://lore.kernel.org/all/20261008094125.3197971-1-m.szyprowski@samsung.com/ - initial version Patch summary: Marek Szyprowski (2): of: reserved_mem: group allocation helpers together of: reserved_mem: allocate and map the reserved_mem array early drivers/of/fdt.c | 3 - drivers/of/of_private.h | 2 - drivers/of/of_reserved_mem.c | 455 +++++++++++++++-------------------- 3 files changed, 195 insertions(+), 265 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] of: reserved_mem: group allocation helpers together 2026-10-08 15:23 ` [PATCH v2 0/2] of: reserved_mem: use dynamically allocated reserved_mem array Marek Szyprowski @ 2026-10-08 15:24 ` Marek Szyprowski 2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski 1 sibling, 0 replies; 7+ messages in thread From: Marek Szyprowski @ 2026-10-08 15:24 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] 7+ messages in thread
* [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early 2026-10-08 15:23 ` [PATCH v2 0/2] of: reserved_mem: use dynamically allocated reserved_mem array Marek Szyprowski 2026-10-08 15:24 ` [PATCH v2 1/2] of: reserved_mem: group allocation helpers together Marek Szyprowski @ 2026-10-08 15:24 ` Marek Szyprowski 2026-10-08 15:35 ` sashiko-bot ` (2 more replies) 1 sibling, 3 replies; 7+ messages in thread From: Marek Szyprowski @ 2026-10-08 15:24 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 through a temporary early_memremap() mapping. Such mapping is needed for some architectures (like ARM64), where linear map is not yet available during early boot scan. 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 directly during the early scan again. Suggested-by: Mike Rapoport <rppt@kernel.org> Link: https://lore.kernel.org/all/asc6brs_g0ky0wOM@kernel.org/ Assisted-By: LLM 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 | 247 +++++++++++++---------------------- 3 files changed, 92 insertions(+), 160 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..8d8fa7242d4a 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -24,12 +24,12 @@ #include <linux/slab.h> #include <linux/memblock.h> #include <linux/kmemleak.h> +#include <asm/early_ioremap.h> #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 int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, @@ -59,56 +59,46 @@ 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 + * reserved_mem_array_map() - make the freshly allocated reserved_mem array + * accessible during early boot * - * 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 (i.e. ARM64) the linear mapping is not yet usable when + * the reserved memory regions are scanned, so the array has to be accessed + * through a temporary early mapping. */ -static int __init alloc_reserved_mem_array(void) +static struct reserved_mem * __init reserved_mem_array_map(struct reserved_mem *array, + size_t size) { - struct reserved_mem *new_array; - size_t alloc_size, copy_size, memset_size; - int ret; + if (IS_ENABLED(CONFIG_GENERIC_EARLY_IOREMAP)) + return early_memremap(__pa(array), size); + else + return array; +} - if (!total_reserved_mem_cnt) - return 0; +static void __init reserved_mem_array_unmap(struct reserved_mem *map, size_t size) +{ + if (IS_ENABLED(CONFIG_GENERIC_EARLY_IOREMAP)) + early_memunmap(map, size); +} - alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array)); - if (alloc_size == SIZE_MAX) { - ret = -EOVERFLOW; - goto fail; - } +/* + * count_reserved_mem_nodes() - count the nodes that might need an entry in the + * reserved_mem array + */ +static int __init count_reserved_mem_nodes(const void *fdt, int node) +{ + int child, len, count = 0; - new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES); - if (!new_array) { - ret = -ENOMEM; - goto fail; - } + fdt_for_each_subnode(child, fdt, node) { + if (!of_fdt_device_is_available(fdt, child)) + continue; - 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; + /* 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)) + count++; } - - 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 count; } static void fdt_init_reserved_mem_node(unsigned long node, const char *uname, @@ -169,6 +159,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { fdt_fixup_reserved_mem_node(node, base, size); + fdt_init_reserved_mem_node(node, uname, base, size); pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", uname, &base, (unsigned long)(size / SZ_1M)); } else { @@ -381,143 +372,89 @@ static void __init __rmem_check_for_overlap(void) } } -/** - * fdt_scan_reserved_mem_late() - Scan FDT and initialize remaining 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. - */ -void __init fdt_scan_reserved_mem_late(void) -{ - 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 (__reserved_mem_check_root(node)) { - pr_err("Reserved memory: unsupported node format, ignoring\n"); - return; - } - - 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; - - if (size) { - uname = fdt_get_name(fdt, child, NULL); - fdt_init_reserved_mem_node(child, uname, base, size); - } - } - - /* check for overlapping reserved regions */ - __rmem_check_for_overlap(); -} /* * 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. + * This function is used to scan through the FDT and count the number of + * reserved memory regions, so the reserved_mem array can be allocated with + * the exact size. Then all static (defined by the "reg" property) reserved + * memory regions are marked as reserved, 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]; + struct reserved_mem *array, *map; + size_t array_bytes; + int node, child, cnt; const void *fdt = initial_boot_params; node = fdt_path_offset(fdt, "/reserved-memory"); - if (node < 0) { - total_reserved_mem_cnt = 0; + if (node < 0) return -ENODEV; - } if (__reserved_mem_check_root(node) != 0) { pr_err("Reserved memory: unsupported node format, ignoring\n"); - total_reserved_mem_cnt = 0; return -EINVAL; } - fdt_for_each_subnode(child, fdt, node) { - const char *uname; - int err; + /* First pass: count the entries needed for the reserved_mem array */ + cnt = count_reserved_mem_nodes(fdt, node); + if (!cnt) + return 0; - if (!of_fdt_device_is_available(fdt, child)) - continue; + array_bytes = array_size(cnt, sizeof(*array)); + array = memblock_alloc_raw(array_bytes, SMP_CACHE_BYTES); + if (!array) { + pr_err("Failed to allocate memory for reserved_mem array\n"); + return -ENOMEM; + } - uname = fdt_get_name(fdt, child, NULL); + map = reserved_mem_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); - err = __reserved_mem_reserve_reg(child, uname); - if (!err) - count++; + reserved_mem = map; + total_reserved_mem_cnt = cnt; - /* - * 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)) + /* Second pass: reserve and initialize the static regions */ + fdt_for_each_subnode(child, fdt, node) { + if (!of_fdt_device_is_available(fdt, child)) continue; - if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) { - pr_err("too many defined dynamic regions, skip '%s'\n", - uname); + __reserved_mem_reserve_reg(child, + fdt_get_name(fdt, child, NULL)); + } + + /* + * Allocate the dynamically-placed regions only 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. + */ + fdt_for_each_subnode(child, fdt, node) { + int len; + + 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 */ + reserved_mem_array_unmap(map, array_bytes); + reserved_mem = array; return 0; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early 2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski @ 2026-10-08 15:35 ` sashiko-bot 2026-10-09 2:16 ` Wandun 2026-10-09 5:20 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-10-08 15:35 UTC (permalink / raw) To: Marek Szyprowski; +Cc: conor+dt, devicetree, robh Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] of: reserved_mem: dynamic array allocation overlaps with static regions -- commit 363ba30305c792dd8e994b354929ef72e89a362e Author: Marek Szyprowski <m.szyprowski@samsung.com> of: reserved_mem: allocate and map the reserved_mem array early This commit replaces the statically sized reserved_mem array with a dynamically allocated array using memblock_alloc_raw(). It maps the new array early to handle architectures where the linear map is not yet available during the early boot scan. The commit aims to eliminate the two-step initialization, processing all regions during the early scan. Link: https://lore.kernel.org/all/asc6brs_g0ky0wOM@kernel.org/ > diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c > index 300fb236ab59f..51eea497a3192 100644 > --- a/drivers/of/of_reserved_mem.c > +++ b/drivers/of/of_reserved_mem.c [ ... ] > @@ -381,143 +372,89 @@ static void __init __rmem_check_for_overlap(void) > } > } > [ ... ] > /* > * 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. > + * This function is used to scan through the FDT and count the number of > + * reserved memory regions, so the reserved_mem array can be allocated with > + * the exact size. Then all static (defined by the "reg" property) reserved > + * memory regions are marked as reserved, 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]; > + struct reserved_mem *array, *map; > + size_t array_bytes; > + int node, child, cnt; > const void *fdt = initial_boot_params; > > node = fdt_path_offset(fdt, "/reserved-memory"); > - if (node < 0) { > - total_reserved_mem_cnt = 0; > + if (node < 0) > return -ENODEV; > - } > > if (__reserved_mem_check_root(node) != 0) { > pr_err("Reserved memory: unsupported node format, ignoring\n"); > - total_reserved_mem_cnt = 0; > return -EINVAL; > } > > - fdt_for_each_subnode(child, fdt, node) { > - const char *uname; > - int err; > + /* First pass: count the entries needed for the reserved_mem array */ > + cnt = count_reserved_mem_nodes(fdt, node); > + if (!cnt) > + return 0; > > - if (!of_fdt_device_is_available(fdt, child)) > - continue; > + array_bytes = array_size(cnt, sizeof(*array)); > + array = memblock_alloc_raw(array_bytes, SMP_CACHE_BYTES); [Severity: High] Does allocating the array here introduce a regression by creating a race with static reserved memory regions? Because the static regions have not yet been marked as reserved in memblock, memblock_alloc_raw() considers their physical addresses available and might allocate the array overlapping a device's static reserved region. > + if (!array) { > + pr_err("Failed to allocate memory for reserved_mem array\n"); > + return -ENOMEM; > + } > > - uname = fdt_get_name(fdt, child, NULL); > + map = reserved_mem_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); > > - err = __reserved_mem_reserve_reg(child, uname); > - if (!err) > - count++; > + reserved_mem = map; > + total_reserved_mem_cnt = cnt; > > - /* > - * 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)) > + /* Second pass: reserve and initialize the static regions */ > + fdt_for_each_subnode(child, fdt, node) { > + if (!of_fdt_device_is_available(fdt, child)) > continue; > > - if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) { > - pr_err("too many defined dynamic regions, skip '%s'\n", > - uname); > + __reserved_mem_reserve_reg(child, > + fdt_get_name(fdt, child, NULL)); > + } If the memblock array allocation overlaps a no-map static region, early_init_dt_reserve_memory() inside __reserved_mem_reserve_reg() will detect the overlap, return -EBUSY, and fail the device's reservation. If the region lacks no-map, memblock_reserve() will silently merge the reservations. The kernel's reserved_mem array will then reside inside the device's reserved memory, which could lead to memory corruption when the device driver later uses this memory. Can the memblock allocation be delayed until after the static regions are reserved? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261008152403.766439-1-m.szyprowski@samsung.com?part=2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early 2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski 2026-10-08 15:35 ` sashiko-bot @ 2026-10-09 2:16 ` Wandun 2026-10-09 11:27 ` Marek Szyprowski 2026-10-09 5:20 ` kernel test robot 2 siblings, 1 reply; 7+ messages in thread From: Wandun @ 2026-10-09 2:16 UTC (permalink / raw) To: Marek Szyprowski, linux-mm, devicetree, linux-kernel Cc: Mike Rapoport, Rob Herring, Saravana Kannan, Oreoluwa Babatunde, Andrew Morton On 10/8/26 23:24, Marek Szyprowski wrote: > Get rid of the static, limited-size reserved_mem array and replace it > with array allocated by memblock_alloc_raw() and accessed through a > temporary early_memremap() mapping. Such mapping is needed for some > architectures (like ARM64), where linear map is not yet available during > early boot scan. 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 > directly during the early scan again. One concern about the ordering here: the new memblock_alloc_raw() for the reserved_mem array runs *before* the static ("reg") regions are reserved, so the array can be allocated from inside one of them which makes the subsequent static region reservation fail. Best regards, Wandun > > Suggested-by: Mike Rapoport <rppt@kernel.org> > Link: https://lore.kernel.org/all/asc6brs_g0ky0wOM@kernel.org/ > Assisted-By: LLM > 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 | 247 +++++++++++++---------------------- > 3 files changed, 92 insertions(+), 160 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..8d8fa7242d4a 100644 > --- a/drivers/of/of_reserved_mem.c > +++ b/drivers/of/of_reserved_mem.c > @@ -24,12 +24,12 @@ > #include <linux/slab.h> > #include <linux/memblock.h> > #include <linux/kmemleak.h> > +#include <asm/early_ioremap.h> > > #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 int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, > @@ -59,56 +59,46 @@ 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 > + * reserved_mem_array_map() - make the freshly allocated reserved_mem array > + * accessible during early boot > * > - * 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 (i.e. ARM64) the linear mapping is not yet usable when > + * the reserved memory regions are scanned, so the array has to be accessed > + * through a temporary early mapping. > */ > -static int __init alloc_reserved_mem_array(void) > +static struct reserved_mem * __init reserved_mem_array_map(struct reserved_mem *array, > + size_t size) > { > - struct reserved_mem *new_array; > - size_t alloc_size, copy_size, memset_size; > - int ret; > + if (IS_ENABLED(CONFIG_GENERIC_EARLY_IOREMAP)) > + return early_memremap(__pa(array), size); > + else > + return array; > +} > > - if (!total_reserved_mem_cnt) > - return 0; > +static void __init reserved_mem_array_unmap(struct reserved_mem *map, size_t size) > +{ > + if (IS_ENABLED(CONFIG_GENERIC_EARLY_IOREMAP)) > + early_memunmap(map, size); > +} > > - alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array)); > - if (alloc_size == SIZE_MAX) { > - ret = -EOVERFLOW; > - goto fail; > - } > +/* > + * count_reserved_mem_nodes() - count the nodes that might need an entry in the > + * reserved_mem array > + */ > +static int __init count_reserved_mem_nodes(const void *fdt, int node) > +{ > + int child, len, count = 0; > > - new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES); > - if (!new_array) { > - ret = -ENOMEM; > - goto fail; > - } > + fdt_for_each_subnode(child, fdt, node) { > + if (!of_fdt_device_is_available(fdt, child)) > + continue; > > - 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; > + /* 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)) > + count++; > } > - > - 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 count; > } > > static void fdt_init_reserved_mem_node(unsigned long node, const char *uname, > @@ -169,6 +159,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, > > if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { > fdt_fixup_reserved_mem_node(node, base, size); > + fdt_init_reserved_mem_node(node, uname, base, size); > pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", > uname, &base, (unsigned long)(size / SZ_1M)); > } else { > @@ -381,143 +372,89 @@ static void __init __rmem_check_for_overlap(void) > } > } > > -/** > - * fdt_scan_reserved_mem_late() - Scan FDT and initialize remaining 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. > - */ > -void __init fdt_scan_reserved_mem_late(void) > -{ > - 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 (__reserved_mem_check_root(node)) { > - pr_err("Reserved memory: unsupported node format, ignoring\n"); > - return; > - } > - > - 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; > - > - if (size) { > - uname = fdt_get_name(fdt, child, NULL); > - fdt_init_reserved_mem_node(child, uname, base, size); > - } > - } > - > - /* check for overlapping reserved regions */ > - __rmem_check_for_overlap(); > -} > > /* > * 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. > + * This function is used to scan through the FDT and count the number of > + * reserved memory regions, so the reserved_mem array can be allocated with > + * the exact size. Then all static (defined by the "reg" property) reserved > + * memory regions are marked as reserved, 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]; > + struct reserved_mem *array, *map; > + size_t array_bytes; > + int node, child, cnt; > const void *fdt = initial_boot_params; > > node = fdt_path_offset(fdt, "/reserved-memory"); > - if (node < 0) { > - total_reserved_mem_cnt = 0; > + if (node < 0) > return -ENODEV; > - } > > if (__reserved_mem_check_root(node) != 0) { > pr_err("Reserved memory: unsupported node format, ignoring\n"); > - total_reserved_mem_cnt = 0; > return -EINVAL; > } > > - fdt_for_each_subnode(child, fdt, node) { > - const char *uname; > - int err; > + /* First pass: count the entries needed for the reserved_mem array */ > + cnt = count_reserved_mem_nodes(fdt, node); > + if (!cnt) > + return 0; > > - if (!of_fdt_device_is_available(fdt, child)) > - continue; > + array_bytes = array_size(cnt, sizeof(*array)); > + array = memblock_alloc_raw(array_bytes, SMP_CACHE_BYTES); > + if (!array) { > + pr_err("Failed to allocate memory for reserved_mem array\n"); > + return -ENOMEM; > + } > > - uname = fdt_get_name(fdt, child, NULL); > + map = reserved_mem_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); > > - err = __reserved_mem_reserve_reg(child, uname); > - if (!err) > - count++; > + reserved_mem = map; > + total_reserved_mem_cnt = cnt; > > - /* > - * 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)) > + /* Second pass: reserve and initialize the static regions */ > + fdt_for_each_subnode(child, fdt, node) { > + if (!of_fdt_device_is_available(fdt, child)) > continue; > > - if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) { > - pr_err("too many defined dynamic regions, skip '%s'\n", > - uname); > + __reserved_mem_reserve_reg(child, > + fdt_get_name(fdt, child, NULL)); > + } > + > + /* > + * Allocate the dynamically-placed regions only 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. > + */ > + fdt_for_each_subnode(child, fdt, node) { > + int len; > + > + 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 */ > + reserved_mem_array_unmap(map, array_bytes); > + reserved_mem = array; > return 0; > } > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early 2026-10-09 2:16 ` Wandun @ 2026-10-09 11:27 ` Marek Szyprowski 0 siblings, 0 replies; 7+ messages in thread From: Marek Szyprowski @ 2026-10-09 11:27 UTC (permalink / raw) To: Wandun, linux-mm, devicetree, linux-kernel Cc: Mike Rapoport, Rob Herring, Saravana Kannan, Oreoluwa Babatunde, Andrew Morton On 09.10.2026 04:16, Wandun wrote: > On 10/8/26 23:24, Marek Szyprowski wrote: >> Get rid of the static, limited-size reserved_mem array and replace it >> with array allocated by memblock_alloc_raw() and accessed through a >> temporary early_memremap() mapping. Such mapping is needed for some >> architectures (like ARM64), where linear map is not yet available during >> early boot scan. 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 >> directly during the early scan again. > One concern about the ordering here: the new memblock_alloc_raw() for the > reserved_mem array runs *before* the static ("reg") regions are reserved, > so the array can be allocated from inside one of them which makes the > subsequent static region reservation fail. Well, that's what Sashiko already reported. It will be trivial to process 'static' regions before doing the reserved_mem allocation, but this in turn returns us to the point of not being able to handle their reservation failures. I wonder what's worse... Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early 2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski 2026-10-08 15:35 ` sashiko-bot 2026-10-09 2:16 ` Wandun @ 2026-10-09 5:20 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2026-10-09 5:20 UTC (permalink / raw) To: Marek Szyprowski, linux-mm, devicetree, linux-kernel Cc: oe-kbuild-all, Marek Szyprowski, Mike Rapoport, Rob Herring, Saravana Kannan, Oreoluwa Babatunde, Wandun, Andrew Morton, Linux Memory Management List Hi Marek, kernel test robot noticed the following build errors: [auto build test ERROR on robh/for-next] [also build test ERROR on linus/master v7.3-rc6 next-20261008] [cannot apply to linux-review/Marek-Szyprowski/of-reserved_mem-group-allocation-helpers-together/20261008-114122] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Marek-Szyprowski/of-reserved_mem-group-allocation-helpers-together/20261008-172400 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20261008152403.766439-3-m.szyprowski%40samsung.com patch subject: [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early config: csky-allnoconfig (https://download.01.org/0day-ci/archive/20261009/202610091317.jGUqplBp-lkp@intel.com/config) compiler: csky-linux-gcc (GCC) 16.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261009/202610091317.jGUqplBp-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202610091317.jGUqplBp-lkp@intel.com/ All errors (new ones prefixed by >>): >> drivers/of/of_reserved_mem.c:27:10: fatal error: asm/early_ioremap.h: No such file or directory 27 | #include <asm/early_ioremap.h> | ^~~~~~~~~~~~~~~~~~~~~ compilation terminated. vim +27 drivers/of/of_reserved_mem.c 13 14 #include <linux/err.h> 15 #include <linux/ioport.h> 16 #include <linux/libfdt.h> 17 #include <linux/of.h> 18 #include <linux/of_fdt.h> 19 #include <linux/of_platform.h> 20 #include <linux/mm.h> 21 #include <linux/sizes.h> 22 #include <linux/of_reserved_mem.h> 23 #include <linux/sort.h> 24 #include <linux/slab.h> 25 #include <linux/memblock.h> 26 #include <linux/kmemleak.h> > 27 #include <asm/early_ioremap.h> 28 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-09 11:27 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20261008152449eucas1p29758be26c325084093c14cfa9b8b2d04@eucas1p2.samsung.com>
2026-10-08 15:23 ` [PATCH v2 0/2] of: reserved_mem: use dynamically allocated reserved_mem array Marek Szyprowski
2026-10-08 15:24 ` [PATCH v2 1/2] of: reserved_mem: group allocation helpers together Marek Szyprowski
2026-10-08 15:24 ` [PATCH v2 2/2] of: reserved_mem: allocate and map the reserved_mem array early Marek Szyprowski
2026-10-08 15:35 ` sashiko-bot
2026-10-09 2:16 ` Wandun
2026-10-09 11:27 ` Marek Szyprowski
2026-10-09 5:20 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox