[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