The "iommu-addresses" property describes an identity 1:1 mapping between an IOVA range and the physical memory specified by "reg" in the same reserved-memory node. Without "reg", there is no physical memory to map.
The DT schema now requires "reg" whenever "iommu-addresses" is present. Align the kernel implementation with this requirement. https://github.com/devicetree-org/dt-schema/pull/207 An identity mapping requires matching IOVA and "reg" ranges. Reject mismatched ranges and report an error. Suggested-by: Rob Herring <[email protected]> Co-developed-by: Vishnu Reddy <[email protected]> Signed-off-by: Vishnu Reddy <[email protected]> Signed-off-by: Vikash Garodia <[email protected]> --- drivers/iommu/of_iommu.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 6675fc900e6c2d55b34c61dc9effaeb48e24f18f..00b02c19f27e195fc36c4bc1d91253255147c9ab 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -174,19 +174,12 @@ iommu_resv_region_get_type(struct device *dev, { phys_addr_t end = start + length - 1; - /* - * IOMMU regions without an associated physical region cannot be - * mapped and are simply reservations. - */ - if (phys->start >= phys->end) - return IOMMU_RESV_RESERVED; - /* may be IOMMU_RESV_DIRECT_RELAXABLE for certain cases */ if (start == phys->start && end == phys->end) return IOMMU_RESV_DIRECT; - dev_warn(dev, "treating non-direct mapping [%pr] -> [%pap-%pap] as reservation\n", phys, - &start, &end); + dev_err(dev, "non-direct mapping [%pr] -> [%pap-%pap] is not supported\n", phys, + &start, &end); return IOMMU_RESV_RESERVED; } @@ -211,12 +204,14 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) struct resource phys; int size; - memset(&phys, 0, sizeof(phys)); + maps = of_get_property(it.node, "iommu-addresses", &size); + if (!maps) + continue; /* - * The "reg" property is optional and can be omitted by reserved-memory regions - * that represent reservations in the IOVA space, which are regions that should - * not be mapped. + * "iommu-addresses" must be used in combination with a "reg" that provides + * the physical address and size of this memory region, for an identity 1:1 + * IOVA mapping to that physical memory. */ if (of_property_present(it.node, "reg")) { err = of_address_to_resource(it.node, 0, &phys); @@ -225,11 +220,11 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) it.node, err); continue; } - } - - maps = of_get_property(it.node, "iommu-addresses", &size); - if (!maps) + } else { + dev_err(dev, "%pOF: iommu-addresses requires a reg property\n", + it.node); continue; + } end = maps + size / sizeof(__be32); @@ -257,6 +252,9 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) } type = iommu_resv_region_get_type(dev, &phys, iova, length); + if (type != IOMMU_RESV_DIRECT) + continue; + region = iommu_alloc_resv_region(iova, length, prot, type, GFP_KERNEL); if (region) -- 2.34.1
