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@xxxxxxxxxx> --- 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