of_dma_get_max_cpu_address() returns the highest CPU address that
devices can use for DMA. The implicit assumption is that all CPU
addresses below that limit are suitable for DMA. However the
'dma-ranges' property this code uses also encodes a lower limit for DMA
that is potentially non zero.

Rename to of_dma_get_cpu_limits(), and extend to retrieve also the lower
limit for the same 'dma-ranges' property describing the high limit.

Update callers of of_dma_get_max_cpu_address(). No functional change
intended.

Signed-off-by: Baruch Siach <bar...@tkos.co.il>
---
 arch/arm64/mm/init.c  |  2 +-
 drivers/of/address.c  | 38 +++++++++++++++++++++++++++-----------
 drivers/of/unittest.c |  8 ++++----
 include/linux/of.h    | 11 ++++++++---
 4 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 00508c69ca9e..77e942ca578b 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -128,7 +128,7 @@ static void __init zone_sizes_init(void)
 
 #ifdef CONFIG_ZONE_DMA
        acpi_zone_dma_limit = acpi_iort_dma_get_max_cpu_address();
-       dt_zone_dma_limit = of_dma_get_max_cpu_address(NULL);
+       of_dma_get_cpu_limits(NULL, &dt_zone_dma_limit, NULL);
        zone_dma_limit = min(dt_zone_dma_limit, acpi_zone_dma_limit);
        arm64_dma_phys_limit = max_zone_phys(zone_dma_limit);
        max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index ae46a3605904..ac009b3bb63b 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -964,21 +964,25 @@ int of_dma_get_range(struct device_node *np, const struct 
bus_dma_region **map)
 #endif /* CONFIG_HAS_DMA */
 
 /**
- * of_dma_get_max_cpu_address - Gets highest CPU address suitable for DMA
+ * of_dma_get_cpu_limits - Gets highest CPU address suitable for DMA
  * @np: The node to start searching from or NULL to start from the root
+ * @max: Pointer to high address limit or NULL if not needed
+ * @min: Pointer to low address limit or NULL if not needed
  *
  * Gets the highest CPU physical address that is addressable by all DMA masters
- * in the sub-tree pointed by np, or the whole tree if NULL is passed. If no
- * DMA constrained device is found, it returns PHYS_ADDR_MAX.
+ * in the sub-tree pointed by np, or the whole tree if @np in NULL. If no
+ * DMA constrained device is found, @*max is PHYS_ADDR_MAX, and @*low is 0.
  */
-phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
+void __init of_dma_get_cpu_limits(struct device_node *np,
+               phys_addr_t *max, phys_addr_t *min)
 {
        phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
        struct of_range_parser parser;
-       phys_addr_t subtree_max_addr;
+       phys_addr_t min_cpu_addr = 0;
        struct device_node *child;
        struct of_range range;
        const __be32 *ranges;
+       u64 cpu_start = 0;
        u64 cpu_end = 0;
        int len;
 
@@ -988,21 +992,33 @@ phys_addr_t __init of_dma_get_max_cpu_address(struct 
device_node *np)
        ranges = of_get_property(np, "dma-ranges", &len);
        if (ranges && len) {
                of_dma_range_parser_init(&parser, np);
-               for_each_of_range(&parser, &range)
-                       if (range.cpu_addr + range.size > cpu_end)
+               for_each_of_range(&parser, &range) {
+                       if (range.cpu_addr + range.size > cpu_end) {
                                cpu_end = range.cpu_addr + range.size - 1;
+                               cpu_start = range.cpu_addr;
+                       }
+               }
 
-               if (max_cpu_addr > cpu_end)
+               if (max_cpu_addr > cpu_end) {
                        max_cpu_addr = cpu_end;
+                       min_cpu_addr = cpu_start;
+               }
        }
 
        for_each_available_child_of_node(np, child) {
-               subtree_max_addr = of_dma_get_max_cpu_address(child);
-               if (max_cpu_addr > subtree_max_addr)
+               phys_addr_t subtree_max_addr, subtree_min_addr;
+
+               of_dma_get_cpu_limits(child, &subtree_max_addr, 
&subtree_min_addr);
+               if (max_cpu_addr > subtree_max_addr) {
                        max_cpu_addr = subtree_max_addr;
+                       min_cpu_addr = subtree_min_addr;
+               }
        }
 
-       return max_cpu_addr;
+       if (max)
+               *max = max_cpu_addr;
+       if (min)
+               *min = min_cpu_addr;
 }
 
 /**
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 6b5c36b6a758..2d632d4ec5b1 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -921,7 +921,7 @@ static void __init of_unittest_changeset(void)
 #endif
 }
 
-static void __init of_unittest_dma_get_max_cpu_address(void)
+static void __init of_unittest_dma_get_cpu_limits(void)
 {
        struct device_node *np;
        phys_addr_t cpu_addr;
@@ -935,9 +935,9 @@ static void __init of_unittest_dma_get_max_cpu_address(void)
                return;
        }
 
-       cpu_addr = of_dma_get_max_cpu_address(np);
+       of_dma_get_cpu_limits(np, &cpu_addr, NULL);
        unittest(cpu_addr == 0x4fffffff,
-                "of_dma_get_max_cpu_address: wrong CPU addr %pad (expecting 
%x)\n",
+                "of_dma_get_cpu_limits: wrong CPU addr %pad (expecting %x)\n",
                 &cpu_addr, 0x4fffffff);
 }
 
@@ -4109,7 +4109,7 @@ static int __init of_unittest(void)
        of_unittest_changeset();
        of_unittest_parse_interrupts();
        of_unittest_parse_interrupts_extended();
-       of_unittest_dma_get_max_cpu_address();
+       of_unittest_dma_get_cpu_limits();
        of_unittest_parse_dma_ranges();
        of_unittest_pci_dma_ranges();
        of_unittest_bus_ranges();
diff --git a/include/linux/of.h b/include/linux/of.h
index a0bedd038a05..7756441d3ce0 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -454,7 +454,8 @@ int of_map_id(struct device_node *np, u32 id,
               const char *map_name, const char *map_mask_name,
               struct device_node **target, u32 *id_out);
 
-phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
+void of_dma_get_cpu_limits(struct device_node *np, phys_addr_t *max,
+               phys_addr_t *min);
 
 struct kimage;
 void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
@@ -880,9 +881,13 @@ static inline int of_map_id(struct device_node *np, u32 id,
        return -EINVAL;
 }
 
-static inline phys_addr_t of_dma_get_max_cpu_address(struct device_node *np)
+static inline void of_dma_get_cpu_limits(struct device_node *np,
+               phys_addr_t *max, phys_addr_t *min)
 {
-       return PHYS_ADDR_MAX;
+       if (max)
+               *max = PHYS_ADDR_MAX;
+       if (min)
+               *min = 0;
 }
 
 static inline const void *of_device_get_match_data(const struct device *dev)
-- 
2.43.0

Reply via email to