[2/2] drm/nouveau: tegra: Use IOMMU groups

Submitted by Thierry Reding on Jan. 11, 2018, 9:42 p.m.

Details

Message ID 20180111214221.25919-2-thierry.reding@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Thierry Reding Jan. 11, 2018, 9:42 p.m.
From: Thierry Reding <treding@nvidia.com>

Use IOMMU groups to attach the GPU to its IOMMU domain. This is not
strictly necessary because the domain isn't shared with any other
device, but it makes the code consistent with how IOMMU is handled in
other drivers and provides an easy way to detect when no IOMMU has
been attached via device tree.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h  |  1 +
 drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 18 +++++++++++-------
 2 files changed, 12 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
index 5c102d0206a7..5a9a796380dc 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
@@ -25,6 +25,7 @@  struct nvkm_device_tegra {
 
 		struct nvkm_mm mm;
 		struct iommu_domain *domain;
+		struct iommu_group *group;
 		unsigned long pgshift;
 	} iommu;
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index 78597da6313a..1f07999aea1d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -110,7 +110,8 @@  nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
 
 	mutex_init(&tdev->iommu.mutex);
 
-	if (iommu_present(&platform_bus_type)) {
+	tdev->iommu.group = iommu_group_get(dev);
+	if (tdev->iommu.group) {
 		tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
 		if (!tdev->iommu.domain)
 			goto error;
@@ -132,7 +133,7 @@  nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
 			tdev->iommu.pgshift -= 1;
 		}
 
-		ret = iommu_attach_device(tdev->iommu.domain, dev);
+		ret = iommu_attach_group(tdev->iommu.domain, tdev->iommu.group);
 		if (ret)
 			goto free_domain;
 
@@ -140,19 +141,21 @@  nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
 				   (1ULL << tdev->func->iommu_bit) >>
 				   tdev->iommu.pgshift, 1);
 		if (ret)
-			goto detach_device;
+			goto detach_group;
 	}
 
 	return;
 
-detach_device:
-	iommu_detach_device(tdev->iommu.domain, dev);
+detach_group:
+	iommu_detach_group(tdev->iommu.domain, tdev->iommu.group);
 
 free_domain:
 	iommu_domain_free(tdev->iommu.domain);
 
 error:
+	iommu_group_put(tdev->iommu.group);
 	tdev->iommu.domain = NULL;
+	tdev->iommu.group = NULL;
 	tdev->iommu.pgshift = 0;
 	dev_err(dev, "cannot initialize IOMMU MM\n");
 #endif
@@ -162,10 +165,11 @@  static void
 nvkm_device_tegra_remove_iommu(struct nvkm_device_tegra *tdev)
 {
 #if IS_ENABLED(CONFIG_IOMMU_API)
-	if (tdev->iommu.domain) {
+	if (tdev->iommu.group && tdev->iommu.domain) {
 		nvkm_mm_fini(&tdev->iommu.mm);
-		iommu_detach_device(tdev->iommu.domain, tdev->device.dev);
+		iommu_detach_group(tdev->iommu.domain, tdev->iommu.group);
 		iommu_domain_free(tdev->iommu.domain);
+		iommu_group_put(tdev->iommu.group);
 	}
 #endif
 }