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 <[email protected]>
---
 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


Reply via email to