drm/tegra: Simplify IOMMU group selection

All the devices that make up the DRM device are now part of the same
IOMMU group. This simplifies the handling of the IOMMU attachment and
also avoids exhausting the number of IOMMUs available on early Tegra
SoC generations.

Signed-off-by: Thierry Reding <treding@nvidia.com>
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 54966f5..36c36b2 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -2014,7 +2014,7 @@
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	err = host1x_client_iommu_attach(client, true);
+	err = host1x_client_iommu_attach(client);
 	if (err < 0) {
 		dev_err(client->dev, "failed to attach to domain: %d\n", err);
 		return err;
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 7480f57..9a1c169 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -904,7 +904,7 @@
 	return 0;
 }
 
-int host1x_client_iommu_attach(struct host1x_client *client, bool shared)
+int host1x_client_iommu_attach(struct host1x_client *client)
 {
 	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_drm *tegra = drm->dev_private;
@@ -912,29 +912,30 @@
 	int err;
 
 	if (tegra->domain) {
+		struct iommu_domain *domain;
+
 		group = iommu_group_get(client->dev);
 		if (!group) {
 			dev_err(client->dev, "failed to get IOMMU group\n");
 			return -ENODEV;
 		}
 
-		if (!shared || (shared && (group != tegra->group))) {
 #if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
-			if (client->dev->archdata.mapping) {
-				struct dma_iommu_mapping *mapping =
-					to_dma_iommu_mapping(client->dev);
-				arm_iommu_detach_device(client->dev);
-				arm_iommu_release_mapping(mapping);
-			}
+		if (client->dev->archdata.mapping) {
+			struct dma_iommu_mapping *mapping =
+				to_dma_iommu_mapping(client->dev);
+			arm_iommu_detach_device(client->dev);
+			arm_iommu_release_mapping(mapping);
+		}
 #endif
+
+		domain = iommu_get_domain_for_dev(client->dev);
+		if (domain != tegra->domain) {
 			err = iommu_attach_group(tegra->domain, group);
 			if (err < 0) {
 				iommu_group_put(group);
 				return err;
 			}
-
-			if (shared && !tegra->group)
-				tegra->group = group;
 		}
 	}
 
@@ -947,12 +948,17 @@
 {
 	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_domain *domain;
 
 	if (client->group) {
-		if (client->group == tegra->group) {
+		/*
+		 * Devices that are part of the same group may no longer be
+		 * attached to a domain at this point because their group may
+		 * have been detached by an earlier client.
+		 */
+		domain = iommu_get_domain_for_dev(client->dev);
+		if (domain)
 			iommu_detach_group(tegra->domain, client->group);
-			tegra->group = NULL;
-		}
 
 		iommu_group_put(client->group);
 	}
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 8b812bb..28f2820 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -36,7 +36,6 @@
 	struct drm_device *drm;
 
 	struct iommu_domain *domain;
-	struct iommu_group *group;
 	struct mutex mm_lock;
 	struct drm_mm mm;
 
@@ -100,7 +99,7 @@
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
-int host1x_client_iommu_attach(struct host1x_client *client, bool shared);
+int host1x_client_iommu_attach(struct host1x_client *client);
 void host1x_client_iommu_detach(struct host1x_client *client);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 5d5af9a..1fc4e56 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -50,7 +50,7 @@
 		goto put;
 	}
 
-	err = host1x_client_iommu_attach(client, false);
+	err = host1x_client_iommu_attach(client);
 	if (err < 0) {
 		dev_err(client->dev, "failed to attach to domain: %d\n", err);
 		goto free;
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index c249a6b..24fae0f6 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -59,7 +59,7 @@
 		goto put;
 	}
 
-	err = host1x_client_iommu_attach(client, false);
+	err = host1x_client_iommu_attach(client);
 	if (err < 0) {
 		dev_err(client->dev, "failed to attach to domain: %d\n", err);
 		goto free;
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index d34b1ad..603f41e 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -187,7 +187,7 @@
 	struct vic *vic = to_vic(drm);
 	int err;
 
-	err = host1x_client_iommu_attach(client, false);
+	err = host1x_client_iommu_attach(client);
 	if (err < 0) {
 		dev_err(vic->dev, "failed to attach to domain: %d\n", err);
 		return err;