Re: [PATCH v2 2/5] of/address: Introduce of_dma_lower_bus_limit()
From: Nicolas Saenz Julienne <hidden>
Date: 2020-10-14 11:52:54
Also in:
linux-devicetree, linux-iommu, lkml
Hi Rob, On Mon, 2020-10-12 at 10:25 -0500, Rob Herring wrote:
On Sat, Oct 10, 2020 at 10:12 AM Nicolas Saenz Julienne [off-list ref] wrote:quoted
The function provides the CPU physical address addressable by the most constrained bus in the system. It might be useful in order to dynamically set up memory zones during boot. Signed-off-by: Nicolas Saenz Julienne <redacted> --- drivers/of/address.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/of.h | 7 +++++++ 2 files changed, 41 insertions(+)diff --git a/drivers/of/address.c b/drivers/of/address.c index eb9ab4f1e80b..755e97b65096 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c@@ -1024,6 +1024,40 @@ int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) } #endif /* CONFIG_HAS_DMA */ +/** + * of_dma_safe_phys_limit - Get system wide DMA safe address space + * + * Gets the CPU physical address limit for safe DMA addressing system wide by + * searching for the most constraining dma-range. Otherwise it returns ~0ULL. + */ +u64 __init of_dma_safe_phys_limit(void) +{ + struct device_node *np = NULL; + struct of_range_parser parser; + const __be32 *ranges = NULL; + u64 phys_dma_limit = ~0ULL; + struct of_range range; + int len; + + for_each_of_allnodes(np) { + dma_addr_t cpu_end = 0; + + ranges = of_get_property(np, "dma-ranges", &len); + if (!ranges || !len) + continue; + + of_dma_range_parser_init(&parser, np); + for_each_of_range(&parser, &range) + if (range.cpu_addr + range.size > cpu_end) + cpu_end = range.cpu_addr + range.size;This doesn't work if you have more than one level of dma-ranges. The address has to be translated first. It should be okay to do that on the start or end address (if not, your DT is broken).
for_each_of_range() calls of_pci_range_parser_one() which utimately populates range.cpu_addr with of_translate_dma_address() results. Isn't that good enough?
Please add/extend a unittest for this.
Will do. Regards, Nicolas