[PATCH 03/15] resource: implement gap-aware lookup_region
Ahmad Fatoum
a.fatoum at pengutronix.de
Tue Jan 27 00:39:13 PST 2026
The incoming bootm rework hinges on being able to determine how much
total space there is for boot artifacts. For that purpose, add
memory_bank_lookup_region(), which will return the gap or the resource a
specified address resides in.
While at it, give the local variable two leading __, so it's less likely
to mask local variables.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
common/memory.c | 25 +++++++++++++++++++++++++
common/resource.c | 33 +++++++++++++++++++++++++++++++++
include/linux/ioport.h | 11 +++++++----
include/memory.h | 2 ++
4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/common/memory.c b/common/memory.c
index 1c18c5b38710..b61df68e02dc 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -410,6 +410,31 @@ int memory_bank_first_find_space(resource_size_t *retstart,
return -ENOENT;
}
+/**
+ * memory_bank_lookup_region - find the memory region containing a given address
+ * @addr: physical address to look up
+ * @gap: if non-NULL and addr is in a gap, the gap info is copied here
+ *
+ * Searches all memory banks for the region containing @addr. If @addr falls
+ * within a gap between allocated regions and @gap is provided, the gap
+ * boundaries are returned via @gap.
+ *
+ * Return: pointer to the resource containing @addr, @gap if in a gap,
+ * or NULL if not found in any memory bank
+ */
+struct resource *memory_bank_lookup_region(resource_size_t addr, struct resource *gap)
+{
+ struct memory_bank *bank;
+
+ for_each_memory_bank(bank) {
+ if (addr < bank->res->start || bank->res->end < addr)
+ continue;
+ return lookup_region(bank->res, addr, gap);
+ }
+
+ return NULL;
+}
+
#ifdef CONFIG_OFTREE
static int of_memory_fixup(struct device_node *root, void *unused)
diff --git a/common/resource.c b/common/resource.c
index 33eb122f4668..e391d268e0bb 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -417,6 +417,39 @@ resource_iter_prev(struct resource *current,
return resource_iter_gap(parent, prev, gap, current);
}
+/**
+ * lookup_region - find the region containing a given address
+ * @parent: parent resource to search within
+ * @addr: address to look up
+ * @gap: if non-NULL and addr is in a gap, the gap info is copied here
+ *
+ * Searches the children of @parent (and gaps between them) for the region
+ * containing @addr.
+ *
+ * Return: pointer to the resource containing @addr, or @gap if @addr is in
+ * a gap and @gap is non-NULL, or NULL if @addr is not found or is
+ * in a gap and @gap is NULL
+ */
+struct resource *lookup_region(struct resource *parent,
+ resource_size_t addr, struct resource *gap)
+{
+ for_each_resource_region(parent, region) {
+ if (addr < region->start || region->end < addr)
+ continue;
+
+ if (!region_is_gap(region))
+ return region;
+ if (!gap)
+ return NULL;
+
+ *gap = *region;
+ INIT_LIST_HEAD(&gap->sibling);
+ return gap;
+ }
+
+ return NULL;
+}
+
struct resource_entry *resource_list_create_entry(struct resource *res,
size_t extra_size)
{
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 20c72e1b6cbb..5baae0dae10a 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -279,14 +279,17 @@ struct resource *resource_iter_last(struct resource *current, struct resource *g
struct resource *resource_iter_prev(struct resource *current, struct resource *gap);
struct resource *resource_iter_next(struct resource *current, struct resource *gap);
+struct resource *lookup_region(struct resource *parent,
+ resource_size_t addr, struct resource *gap);
+
/**
* for_each_resource_region - Iterate over child resources and gaps between them
* @parent: parent resource
* @region: pointer to child resource or gap
*/
#define for_each_resource_region(parent, region) \
- for (struct resource gap, *region = resource_iter_first((parent), &gap); \
- region; region = resource_iter_next(region, &gap))
+ for (struct resource __gap, *region = resource_iter_first((parent), &__gap); \
+ region; region = resource_iter_next(region, &__gap))
/**
* for_each_resource_region_reverse - Reverse iterate over child resources and gaps between them
@@ -294,8 +297,8 @@ struct resource *resource_iter_next(struct resource *current, struct resource *g
* @region: pointer to child resource or gap
*/
#define for_each_resource_region_reverse(parent, region) \
- for (struct resource gap, *region = resource_iter_last((parent), &gap); \
- region; region = resource_iter_prev(region, &gap))
+ for (struct resource __gap, *region = resource_iter_last((parent), &__gap); \
+ region; region = resource_iter_prev(region, &__gap))
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */
diff --git a/include/memory.h b/include/memory.h
index 6b7ada641c9d..92483c39b0f4 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -97,6 +97,8 @@ void memory_bank_find_space(struct memory_bank *bank, resource_size_t *retstart,
int memory_bank_first_find_space(resource_size_t *retstart,
resource_size_t *retend);
+struct resource *memory_bank_lookup_region(resource_size_t addr, struct resource *gap);
+
static inline u64 memory_sdram_size(unsigned int cols,
unsigned int rows,
unsigned int banks,
--
2.47.3
More information about the barebox
mailing list