Blob Blame History Raw
From f40e1590c5270e5559fb95a5a0a7c1f5266a522d Mon Sep 17 00:00:00 2001
From: Thierry Reding <treding@nvidia.com>
Date: Mon, 14 May 2018 11:14:00 +0200
Subject: gpu: host1x: Acquire a reference to the IOVA cache
References: bsc#1090888
Patch-mainline: v4.18-rc1
Git-commit: f40e1590c5270e5559fb95a5a0a7c1f5266a522d

The IOVA API uses a memory cache to allocate IOVA nodes from. To make
sure that this cache is available, obtain a reference to it and release
the reference when the cache is no longer needed.

On 64-bit ARM this is hidden by the fact that the DMA mapping API gets
that reference and never releases it. On 32-bit ARM, this is papered
over by the Tegra DRM driver (the sole user of the host1x API requiring
the cache) acquiring a reference to the IOVA cache for its own purposes.
However, there may be additional users of this API in the future, so fix
this upfront to avoid surprises.

Changes during backport:

 * struct iommu_group is not used by the host1x driver. This required
   changes to the patch to apply without the related code artifacts
   being present.

Fixes: 404bfb78daf3 ("gpu: host1x: Add IOMMU support")
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/host1x/dev.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -181,14 +181,21 @@ static int host1x_probe(struct platform_
 		struct iommu_domain_geometry *geometry;
 		unsigned long order;

+		err = iova_cache_get();
+		if (err < 0)
+			return err;
+
 		host->domain = iommu_domain_alloc(&platform_bus_type);
-		if (!host->domain)
-			return -ENOMEM;
+		if (!host->domain) {
+			err = -ENOMEM;
+			goto put_cache;
+		}

 		err = iommu_attach_device(host->domain, &pdev->dev);
 		if (err == -ENODEV) {
 			iommu_domain_free(host->domain);
 			host->domain = NULL;
+			iova_cache_put();
 			goto skip_iommu;
 		} else if (err) {
 			goto fail_free_domain;
@@ -258,6 +265,9 @@ fail_detach_device:
 fail_free_domain:
 	if (host->domain)
 		iommu_domain_free(host->domain);
+put_cache:
+	if (iommu_present(&platform_bus_type))
+		iova_cache_put();

 	return err;
 }
@@ -276,6 +286,7 @@ static int host1x_remove(struct platform
 		put_iova_domain(&host->iova);
 		iommu_detach_device(host->domain, &pdev->dev);
 		iommu_domain_free(host->domain);
+		iova_cache_put();
 	}

 	return 0;