[PATCH 02/20] iommu/terga-gart: Replace set_platform_dma_ops() with IOMMU_DOMAIN_PLATFORM
Jason Gunthorpe
jgg at nvidia.com
Mon May 1 11:02:46 PDT 2023
tegra-gart seems to be kind of wonky since from the start its 'detach_dev'
op doesn't actually touch hardware. It is supposed to empty the GART of
all translations loaded into it.
Call this weirdness PLATFORM which keeps the basic original
ops->detach_dev() semantic alive without needing much special core code
support. I'm guessing it really ends up in a BLOCKING configuration, but
without any forced cleanup it is unsafe.
Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
---
drivers/iommu/tegra-gart.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index a482ff838b5331..09865889ff2480 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -124,11 +124,27 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain,
return ret;
}
-static void gart_iommu_set_platform_dma(struct device *dev)
+/*
+ * FIXME: This weird function that doesn't touch the HW, but it is supposed to
+ * zap any current translation from the HW.
+ *
+ * Preserve whatever this was doing in 2011 as basically the same in the
+ * new API. The IOMMU_DOMAIN_PLATFORM's attach_dev function is called at almost
+ * the same times as the old detach_dev.
+ *
+ * I suspect the reality is that the UNMANAGED domain is never actually detached
+ * in real systems, or it is only detached once eveything is already unmapped,
+ * so this could get by this way.
+ */
+static int gart_iommu_platform_attach(struct iommu_domain *identity_domain,
+ struct device *dev)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
struct gart_device *gart = gart_handle;
+ if (domain == identity_domain || !domain)
+ return 0;
+
spin_lock(&gart->dom_lock);
if (dev_iommu_priv_get(dev) == domain) {
@@ -139,8 +155,18 @@ static void gart_iommu_set_platform_dma(struct device *dev)
}
spin_unlock(&gart->dom_lock);
+ return 0;
}
+static struct iommu_domain_ops gart_iommu_platform_ops = {
+ .attach_dev = gart_iommu_platform_attach,
+};
+
+static struct iommu_domain gart_iommu_platform_domain = {
+ .type = IOMMU_DOMAIN_PLATFORM,
+ .ops = &gart_iommu_platform_ops,
+};
+
static struct iommu_domain *gart_iommu_domain_alloc(unsigned type)
{
struct iommu_domain *domain;
@@ -267,10 +293,10 @@ static void gart_iommu_sync(struct iommu_domain *domain,
}
static const struct iommu_ops gart_iommu_ops = {
+ .default_domain = &gart_iommu_platform_domain,
.domain_alloc = gart_iommu_domain_alloc,
.probe_device = gart_iommu_probe_device,
.device_group = generic_device_group,
- .set_platform_dma_ops = gart_iommu_set_platform_dma,
.pgsize_bitmap = GART_IOMMU_PGSIZES,
.of_xlate = gart_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
--
2.40.0
More information about the linux-arm-kernel
mailing list