[PATCH 6/7] iommu: Compute dev_iommu->require_direct sooner

Jason Gunthorpe jgg at nvidia.com
Thu Oct 5 11:28:17 PDT 2023


The next patch will need it. To reduce the cost cache if there are
any direct mappings at all and exit iommu_create_device_direct_mappings()
early.

Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
---
 drivers/iommu/iommu.c | 26 +++++++++++++++++++-------
 include/linux/iommu.h |  1 +
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 89db35e2c21771..efa65b3d1bd405 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -392,7 +392,9 @@ static u32 dev_iommu_get_max_pasids(struct device *dev)
  */
 static int iommu_init_device(struct device *dev, const struct iommu_ops *ops)
 {
+	struct iommu_resv_region *entry;
 	struct iommu_device *iommu_dev;
+	LIST_HEAD(mappings);
 	struct iommu_group *group;
 	int ret;
 
@@ -427,6 +429,17 @@ static int iommu_init_device(struct device *dev, const struct iommu_ops *ops)
 	dev->iommu->max_pasids = dev_iommu_get_max_pasids(dev);
 	if (ops->is_attach_deferred)
 		dev->iommu->attach_deferred = ops->is_attach_deferred(dev);
+
+	iommu_get_resv_regions(dev, &mappings);
+	list_for_each_entry(entry, &mappings, list) {
+		if (entry->type == IOMMU_RESV_DIRECT)
+			dev->iommu->require_direct = 1;
+		if (entry->type != IOMMU_RESV_DIRECT &&
+		    entry->type != IOMMU_RESV_DIRECT_RELAXABLE)
+			dev->iommu->has_direct = 1;
+	}
+	iommu_put_resv_regions(dev, &mappings);
+
 	return 0;
 
 err_unlink:
@@ -1068,7 +1081,10 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
 	pg_size = domain->pgsize_bitmap ? 1UL << __ffs(domain->pgsize_bitmap) : 0;
 	INIT_LIST_HEAD(&mappings);
 
-	if (WARN_ON_ONCE(iommu_is_dma_domain(domain) && !pg_size))
+	if (!iommu_is_dma_domain(domain) || !dev->iommu->has_direct)
+		return 0;
+
+	if (WARN_ON_ONCE(!pg_size))
 		return -EINVAL;
 
 	iommu_get_resv_regions(dev, &mappings);
@@ -1078,12 +1094,8 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
 		dma_addr_t start, end, addr;
 		size_t map_size = 0;
 
-		if (entry->type == IOMMU_RESV_DIRECT)
-			dev->iommu->require_direct = 1;
-
-		if ((entry->type != IOMMU_RESV_DIRECT &&
-		     entry->type != IOMMU_RESV_DIRECT_RELAXABLE) ||
-		    !iommu_is_dma_domain(domain))
+		if (entry->type != IOMMU_RESV_DIRECT &&
+		    entry->type != IOMMU_RESV_DIRECT_RELAXABLE)
 			continue;
 
 		start = ALIGN(entry->start, pg_size);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index e1a4c2c2c34d42..e27d2e67e48ef7 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -442,6 +442,7 @@ struct dev_iommu {
 	u32				attach_deferred:1;
 	u32				pci_32bit_workaround:1;
 	u32				require_direct:1;
+	u32				has_direct:1;
 };
 
 int iommu_device_register(struct iommu_device *iommu,
-- 
2.42.0




More information about the linux-arm-kernel mailing list