Skip to contentSkip to conversation

drm/tegra: dc: Free syncpoint on errors

PATCH In review Thierry Reding 2 participants 14 messages May 4, 2018 – May 10, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/4 drm/tegra: dc: Free syncpoint on errors

From: Thierry Reding <[email protected]>

If an error happens during display controller initialization, the host1x syncpoint previously requested would be leaked. Properly clean up the syncpoint along with the other resources.

---
 drivers/gpu/drm/tegra/dc.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/tegra/dc.c +2 -0
index f20648f58e49..c843f11043db 100644
@@ -1925,6 +1925,8 @@ static int tegra_dc_init(struct host1x_client *client)
 		iommu_group_put(dc->group);
 	}
 
+	host1x_syncpt_free(dc->syncpt);
+
 	return err;
 }
 
Signature · 6 lines
2.17.0

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#1 lore raw

PATCH 2/4 drm/tegra: gr2d: Properly clean up resources

From: Thierry Reding <[email protected]>

Failure to register the Tegra DRM client would leak the resources. Move cleanup code to error unwinding gotos to fix that and share the cleanup code with the other error paths.

---
 drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
drivers/gpu/drm/tegra/gr2d.c +22 -6
index 8eb530a85dd0..0b42e99da8ad 100644
@@ -42,8 +42,9 @@ static int gr2d_init(struct host1x_client *client)
 
 	client->syncpts[0] = host1x_syncpt_request(client, flags);
 	if (!client->syncpts[0]) {
-		host1x_channel_put(gr2d->channel);
-		return -ENOMEM;
+		err = -ENOMEM;
+		dev_err(client->dev, "failed to request syncpoint: %d\n", err);
+		goto put;
 	}
 
 	if (tegra->domain) {
@@ -55,15 +56,30 @@ static int gr2d_init(struct host1x_client *client)
 				dev_err(client->dev,
 					"failed to attach to domain: %d\n",
 					err);
-				host1x_syncpt_free(client->syncpts[0]);
-				host1x_channel_put(gr2d->channel);
 				iommu_group_put(gr2d->group);
-				return err;
+				goto free;
 			}
 		}
 	}
 
-	return tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(tegra, drm);
+	if (err < 0) {
+		dev_err(client->dev, "failed to register client: %d\n", err);
+		goto detach;
+	}
+
+	return 0;
+
+detach:
+	if (gr2d->group) {
+		iommu_detach_group(tegra->domain, gr2d->group);
+		iommu_group_put(gr2d->group);
+	}
+free:
+	host1x_syncpt_free(client->syncpts[0]);
+put:
+	host1x_channel_put(gr2d->channel);
+	return err;
 }
 
 static int gr2d_exit(struct host1x_client *client)
Signature · 6 lines
2.17.0

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v1 2/4
#2 lore raw

Re: [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources

Quoted 53 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Failure to register the Tegra DRM client would leak the resources. Move cleanup code to error unwinding gotos to fix that and share the cleanup code with the other error paths.

---
 drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
drivers/gpu/drm/tegra/gr2d.c +15 -6
index 8eb530a85dd0..0b42e99da8ad 100644
@@ -42,8 +42,9 @@ static int gr2d_init(struct host1x_client *client)
 
 	client->syncpts[0] = host1x_syncpt_request(client, flags);
 	if (!client->syncpts[0]) {
-		host1x_channel_put(gr2d->channel);
-		return -ENOMEM;
+		err = -ENOMEM;
+		dev_err(client->dev, "failed to request syncpoint: %d\n", err);
+		goto put;
 	}
 
 	if (tegra->domain) {
@@ -55,15 +56,30 @@ static int gr2d_init(struct host1x_client *client)
 				dev_err(client->dev,
 					"failed to attach to domain: %d\n",
 					err);
-				host1x_syncpt_free(client->syncpts[0]);
-				host1x_channel_put(gr2d->channel);
 				iommu_group_put(gr2d->group);
-				return err;
+				goto free;
 			}
 		}
 	}
 
-	return tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(tegra, drm);
+	if (err < 0) {
+		dev_err(client->dev, "failed to register client: %d\n", err);
+		goto detach;
+	}
+
+	return 0;
+
+detach:
+	if (gr2d->group) {
+		iommu_detach_group(tegra->domain, gr2d->group);

drivers/gpu/drm/tegra/gr2d.c static int gr2d_init(struct host1x_client *client) · line 85

Quoted 10 lines
drivers/gpu/drm/tegra/gr2d.c +7 -0
+		iommu_group_put(gr2d->group);
+	}
+free:
+	host1x_syncpt_free(client->syncpts[0]);
+put:
+	host1x_channel_put(gr2d->channel);
+	return err;
 }
 
 static int gr2d_exit(struct host1x_client *client)

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#3 lore raw

Re: [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources

In reply to Thierry Reding
Quoted 16 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Failure to register the Tegra DRM client would leak the resources. Move cleanup code to error unwinding gotos to fix that and share the cleanup code with the other error paths.

---
 drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
drivers/gpu/drm/tegra/gr2d.c +0 -0
index 8eb530a85dd0..0b42e99da8ad 100644

drivers/gpu/drm/tegra/gr2d.c static int gr2d_init(struct host1x_client *client) · line 46

Quoted 7 lines
drivers/gpu/drm/tegra/gr2d.c +2 -2
@@ -42,8 +42,9 @@ static int gr2d_init(struct host1x_client *client)
 
 	client->syncpts[0] = host1x_syncpt_request(client, flags);
 	if (!client->syncpts[0]) {
-		host1x_channel_put(gr2d->channel);
-		return -ENOMEM;
+		err = -ENOMEM;
+		dev_err(client->dev, "failed to request syncpoint: %d\n", err);

Nit: You could add the same error message to the gr3d patch for consistency.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#4 lore raw

PATCH 3/4 drm/tegra: gr3d: Properly clean up resources

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Failure to register the Tegra DRM client would leak the resources. Move cleanup code to error unwinding gotos to fix that and share the cleanup code with the other error paths.

---
 drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)
drivers/gpu/drm/tegra/gr3d.c +21 -6
index ce5120683091..e129f1afff33 100644
@@ -52,8 +52,8 @@ static int gr3d_init(struct host1x_client *client)
 
 	client->syncpts[0] = host1x_syncpt_request(client, flags);
 	if (!client->syncpts[0]) {
-		host1x_channel_put(gr3d->channel);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto put;
 	}
 
 	if (tegra->domain) {
@@ -65,15 +65,30 @@ static int gr3d_init(struct host1x_client *client)
 				dev_err(client->dev,
 					"failed to attach to domain: %d\n",
 					err);
-				host1x_syncpt_free(client->syncpts[0]);
-				host1x_channel_put(gr3d->channel);
 				iommu_group_put(gr3d->group);
-				return err;
+				goto free;
 			}
 		}
 	}
 
-	return tegra_drm_register_client(dev->dev_private, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
+	if (err < 0) {
+		dev_err(client->dev, "failed to register client: %d\n", err);
+		goto detach;
+	}
+
+	return 0;
+
+detach:
+	if (gr3d->group) {
+		iommu_detach_group(tegra->domain, gr3d->group);
+		iommu_group_put(gr3d->group);
+	}
+free:
+	host1x_syncpt_free(client->syncpts[0]);
+put:
+	host1x_channel_put(gr3d->channel);
+	return err;
 }
 
 static int gr3d_exit(struct host1x_client *client)
Signature · 6 lines
2.17.0

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v1 3/4
#5 lore raw

Re: [PATCH 3/4] drm/tegra: gr3d: Properly clean up resources

Quoted 52 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Failure to register the Tegra DRM client would leak the resources. Move cleanup code to error unwinding gotos to fix that and share the cleanup code with the other error paths.

---
 drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)
drivers/gpu/drm/tegra/gr3d.c +14 -6
index ce5120683091..e129f1afff33 100644
@@ -52,8 +52,8 @@ static int gr3d_init(struct host1x_client *client)
 
 	client->syncpts[0] = host1x_syncpt_request(client, flags);
 	if (!client->syncpts[0]) {
-		host1x_channel_put(gr3d->channel);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto put;
 	}
 
 	if (tegra->domain) {
@@ -65,15 +65,30 @@ static int gr3d_init(struct host1x_client *client)
 				dev_err(client->dev,
 					"failed to attach to domain: %d\n",
 					err);
-				host1x_syncpt_free(client->syncpts[0]);
-				host1x_channel_put(gr3d->channel);
 				iommu_group_put(gr3d->group);
-				return err;
+				goto free;
 			}
 		}
 	}
 
-	return tegra_drm_register_client(dev->dev_private, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
+	if (err < 0) {
+		dev_err(client->dev, "failed to register client: %d\n", err);
+		goto detach;
+	}
+
+	return 0;
+
+detach:
+	if (gr3d->group) {
+		iommu_detach_group(tegra->domain, gr3d->group);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_init(struct host1x_client *client) · line 94

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +7 -0
+		iommu_group_put(gr3d->group);
+	}
+free:
+	host1x_syncpt_free(client->syncpts[0]);
+put:
+	host1x_channel_put(gr3d->channel);
+	return err;
 }
 
 static int gr3d_exit(struct host1x_client *client)

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#6 lore raw

PATCH 4/4 drm/tegra: Refactor IOMMU attach/detach

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +42 -0

48 lines not on this page · raw message

drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -24
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 
Signature · 6 lines
2.17.0

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v1 4/4
#7 lore raw

Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach

Quoted 290 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +42 -0
index 7afe2f635f74..bc1008305e1e 100644
@@ -1114,6 +1114,48 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_group *group = NULL;
+	int err;
+
+	if (tegra->domain) {
+		group = iommu_group_get(client->dev);
+
+		if (group && (!shared || (shared && (group != tegra->group)))) {
+			err = iommu_attach_group(tegra->domain, group);
+			if (err < 0) {
+				iommu_group_put(group);
+				return ERR_PTR(err);
+			}
+
+			if (shared && !tegra->group)
+				tegra->group = group;
+		}
+	}
+
+	return group;
+}
+
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+
+	if (group) {
+		if (group == tegra->group) {
+			iommu_detach_group(tegra->domain, group);
+			tegra->group = NULL;
+		}
+
+		iommu_group_put(group);
+	}
+}
+
 void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
 {
 	struct iova *alloc;
drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -19
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_exit(struct host1x_client *client) · line 99

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +0 -5
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 

Though I'd prefer to have tegra->group renamed, maybe to 'shared_dc_group'.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#8 lore raw

Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach

Quoted 304 lines · Dmitry Osipenko
Quoted 290 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +42 -0
index 7afe2f635f74..bc1008305e1e 100644
@@ -1114,6 +1114,48 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_group *group = NULL;
+	int err;
+
+	if (tegra->domain) {
+		group = iommu_group_get(client->dev);
+
+		if (group && (!shared || (shared && (group != tegra->group)))) {
+			err = iommu_attach_group(tegra->domain, group);
+			if (err < 0) {
+				iommu_group_put(group);
+				return ERR_PTR(err);
+			}
+
+			if (shared && !tegra->group)
+				tegra->group = group;
+		}
+	}
+
+	return group;
+}
+
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+
+	if (group) {
+		if (group == tegra->group) {
+			iommu_detach_group(tegra->domain, group);
+			tegra->group = NULL;
+		}
+
+		iommu_group_put(group);
+	}
+}
+
 void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
 {
 	struct iova *alloc;
drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -19
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_exit(struct host1x_client *client) · line 99

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +0 -5
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 
Quoted 1 line

Though I'd prefer to have tegra->group renamed, maybe to 'shared_dc_group'.

tegra->group doesn't bother me at all. I think just the fact that it's in struct tegra_drm implies that it is shared. It's also declared closely to all the other "shared" variables, so I think that makes it pretty clear. If there were other IOMMU groups I'd agree that renaming it would be good to clarify the purpose. But as it is, I think there's no need for that.

Thanks for the review!

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#9 lore raw

Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach

Quoted 307 lines · Thierry Reding
Quoted 304 lines · Dmitry Osipenko
Quoted 290 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +42 -0
index 7afe2f635f74..bc1008305e1e 100644
@@ -1114,6 +1114,48 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_group *group = NULL;
+	int err;
+
+	if (tegra->domain) {
+		group = iommu_group_get(client->dev);
+
+		if (group && (!shared || (shared && (group != tegra->group)))) {
+			err = iommu_attach_group(tegra->domain, group);
+			if (err < 0) {
+				iommu_group_put(group);
+				return ERR_PTR(err);
+			}
+
+			if (shared && !tegra->group)
+				tegra->group = group;
+		}
+	}
+
+	return group;
+}
+
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+
+	if (group) {
+		if (group == tegra->group) {
+			iommu_detach_group(tegra->domain, group);
+			tegra->group = NULL;
+		}
+
+		iommu_group_put(group);
+	}
+}
+
 void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
 {
 	struct iova *alloc;
drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -19
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_exit(struct host1x_client *client) · line 99

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +0 -5
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 
Quoted 1 line

Though I'd prefer to have tegra->group renamed, maybe to 'shared_dc_group'.

Quoted 8 lines

tegra->group doesn't bother me at all. I think just the fact that it's in struct tegra_drm implies that it is shared. It's also declared closely to all the other "shared" variables, so I think that makes it pretty clear. If there were other IOMMU groups I'd agree that renaming it would be good to clarify the purpose. But as it is, I think there's no need for that.

Thanks for the review!

Well, okay. On the other hand IOMMU API should handle re-attaching from a different device and then that shared group isn't needed at all. Does that re-attaching cause any problems right now? If yes, maybe it's worth fixing the root of the problem rather than trying to workaround it.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#10 lore raw

Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach

Quoted 315 lines · Dmitry Osipenko
Quoted 314 lines · Thierry Reding
Quoted 304 lines · Dmitry Osipenko
Quoted 290 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +42 -0
index 7afe2f635f74..bc1008305e1e 100644
@@ -1114,6 +1114,48 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_group *group = NULL;
+	int err;
+
+	if (tegra->domain) {
+		group = iommu_group_get(client->dev);
+
+		if (group && (!shared || (shared && (group != tegra->group)))) {
+			err = iommu_attach_group(tegra->domain, group);
+			if (err < 0) {
+				iommu_group_put(group);
+				return ERR_PTR(err);
+			}
+
+			if (shared && !tegra->group)
+				tegra->group = group;
+		}
+	}
+
+	return group;
+}
+
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+
+	if (group) {
+		if (group == tegra->group) {
+			iommu_detach_group(tegra->domain, group);
+			tegra->group = NULL;
+		}
+
+		iommu_group_put(group);
+	}
+}
+
 void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
 {
 	struct iova *alloc;
drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -19
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_exit(struct host1x_client *client) · line 99

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +0 -5
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 
Quoted 1 line

Though I'd prefer to have tegra->group renamed, maybe to 'shared_dc_group'.

tegra->group doesn't bother me at all. I think just the fact that it's in struct tegra_drm implies that it is shared. It's also declared closely to all the other "shared" variables, so I think that makes it pretty clear. If there were other IOMMU groups I'd agree that renaming it would be good to clarify the purpose. But as it is, I think there's no need for that.

Quoted 6 lines
Quoted 1 line

Thanks for the review!

Well, okay. On the other hand IOMMU API should handle re-attaching from a different device and then that shared group isn't needed at all. Does that re-attaching cause any problems right now? If yes, maybe it's worth fixing the root of the problem rather than trying to workaround it.

Agreed. I've got that on my TODO list somewhere, let me bump that up a little.

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#11 lore raw

Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach

In reply to Thierry Reding
Quoted 107 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Attaching to and detaching from an IOMMU uses the same code sequence in every driver, so factor it out into separate helpers.

---
 drivers/gpu/drm/tegra/dc.c   | 42 ++++++------------------------------
 drivers/gpu/drm/tegra/drm.c  | 42 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tegra/drm.h  |  4 ++++
 drivers/gpu/drm/tegra/gr2d.c | 32 +++++++--------------------
 drivers/gpu/drm/tegra/gr3d.c | 31 ++++++--------------------
 5 files changed, 68 insertions(+), 83 deletions(-)
drivers/gpu/drm/tegra/dc.c +7 -35
index c843f11043db..3e7ec3937346 100644
@@ -1837,21 +1837,11 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!dc->syncpt)
 		dev_warn(dc->dev, "failed to allocate syncpoint\n");
 
-	if (tegra->domain) {
-		dc->group = iommu_group_get(client->dev);
-
-		if (dc->group && dc->group != tegra->group) {
-			err = iommu_attach_group(tegra->domain, dc->group);
-			if (err < 0) {
-				dev_err(dc->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(dc->group);
-				return err;
-			}
-
-			tegra->group = dc->group;
-		}
+	dc->group = host1x_client_iommu_attach(client, true);
+	if (IS_ERR(dc->group)) {
+		err = PTR_ERR(dc->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		return err;
 	}
 
 	if (dc->soc->wgrps)
@@ -1916,15 +1906,7 @@ static int tegra_dc_init(struct host1x_client *client)
 	if (!IS_ERR(primary))
 		drm_plane_cleanup(primary);
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return err;
@@ -1932,9 +1914,7 @@ static int tegra_dc_init(struct host1x_client *client)
 
 static int tegra_dc_exit(struct host1x_client *client)
 {
-	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
-	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	devm_free_irq(dc->dev, dc->irq, dc);
@@ -1945,15 +1925,7 @@ static int tegra_dc_exit(struct host1x_client *client)
 		return err;
 	}
 
-	if (dc->group) {
-		if (dc->group == tegra->group) {
-			iommu_detach_group(tegra->domain, dc->group);
-			tegra->group = NULL;
-		}
-
-		iommu_group_put(dc->group);
-	}
-
+	host1x_client_iommu_detach(client, dc->group);
 	host1x_syncpt_free(dc->syncpt);
 
 	return 0;
drivers/gpu/drm/tegra/drm.c +10 -0
index 7afe2f635f74..bc1008305e1e 100644
@@ -1114,6 +1114,48 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 	return 0;
 }
 
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+	struct iommu_group *group = NULL;
+	int err;
+
+	if (tegra->domain) {
+		group = iommu_group_get(client->dev);

drivers/gpu/drm/tegra/drm.c int tegra_drm_unregister_client(struct tegra_drm *tegra, · line 1136

Quoted 10 lines
drivers/gpu/drm/tegra/drm.c +10 -0
+
+		if (group && (!shared || (shared && (group != tegra->group)))) {
+			err = iommu_attach_group(tegra->domain, group);
+			if (err < 0) {
+				iommu_group_put(group);
+				return ERR_PTR(err);
+			}
+
+			if (shared && !tegra->group)
+				tegra->group = group;

Nit: Probably it doesn't make much sense to have devices unattached to BO's AS, what about to error out here or at least display a error/warning message?

@@ -1796,7 +1796,12 @@ struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,

        if (tegra->domain) {
                group = iommu_group_get(client->dev);

- if (group && (!shared || (shared && (group != tegra->group)))) {
+ if (!group) {
+ dev_err(client->dev, "Failed to get IOMMU group\n");
+ return ERR_PTR(-EINVAL);
+ }
+

+               if (!shared || group != tegra->group) {
                        err = iommu_attach_group(tegra->domain, group);
                        if (err < 0) {
                                iommu_group_put(group);
Quoted 173 lines
drivers/gpu/drm/tegra/drm.c +22 -0
+		}
+	}
+
+	return group;
+}
+
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group)
+{
+	struct drm_device *drm = dev_get_drvdata(client->parent);
+	struct tegra_drm *tegra = drm->dev_private;
+
+	if (group) {
+		if (group == tegra->group) {
+			iommu_detach_group(tegra->domain, group);
+			tegra->group = NULL;
+		}
+
+		iommu_group_put(group);
+	}
+}
+
 void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
 {
 	struct iova *alloc;
drivers/gpu/drm/tegra/drm.h +4 -0
index 4f41aaec8530..fe263cf58f34 100644
@@ -110,6 +110,10 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
 			      struct tegra_drm_client *client);
 int tegra_drm_unregister_client(struct tegra_drm *tegra,
 				struct tegra_drm_client *client);
+struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
+					       bool shared);
+void host1x_client_iommu_detach(struct host1x_client *client,
+				struct iommu_group *group);
 
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
drivers/gpu/drm/tegra/gr2d.c +8 -24
index 0b42e99da8ad..2cd0f66c8aa9 100644
@@ -32,7 +32,6 @@ static int gr2d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr2d *gr2d = to_gr2d(drm);
 	int err;
 
@@ -47,22 +46,14 @@ static int gr2d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr2d->group = iommu_group_get(client->dev);
-
-		if (gr2d->group) {
-			err = iommu_attach_group(tegra->domain, gr2d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr2d->group);
-				goto free;
-			}
-		}
+	gr2d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr2d->group)) {
+		err = PTR_ERR(gr2d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
-	err = tegra_drm_register_client(tegra, drm);
+	err = tegra_drm_register_client(dev->dev_private, drm);
 	if (err < 0) {
 		dev_err(client->dev, "failed to register client: %d\n", err);
 		goto detach;
@@ -71,10 +62,7 @@ static int gr2d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
+	host1x_client_iommu_detach(client, gr2d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -94,14 +82,10 @@ static int gr2d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr2d->group);
 	host1x_syncpt_free(client->syncpts[0]);
 	host1x_channel_put(gr2d->channel);
 
-	if (gr2d->group) {
-		iommu_detach_group(tegra->domain, gr2d->group);
-		iommu_group_put(gr2d->group);
-	}
-
 	return 0;
 }
 
drivers/gpu/drm/tegra/gr3d.c +7 -19
index e129f1afff33..98e3c67d0fb5 100644
@@ -42,7 +42,6 @@ static int gr3d_init(struct host1x_client *client)
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
 	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -56,19 +55,11 @@ static int gr3d_init(struct host1x_client *client)
 		goto put;
 	}
 
-	if (tegra->domain) {
-		gr3d->group = iommu_group_get(client->dev);
-
-		if (gr3d->group) {
-			err = iommu_attach_group(tegra->domain, gr3d->group);
-			if (err < 0) {
-				dev_err(client->dev,
-					"failed to attach to domain: %d\n",
-					err);
-				iommu_group_put(gr3d->group);
-				goto free;
-			}
-		}
+	gr3d->group = host1x_client_iommu_attach(client, false);
+	if (IS_ERR(gr3d->group)) {
+		err = PTR_ERR(gr3d->group);
+		dev_err(client->dev, "failed to attach to domain: %d\n", err);
+		goto free;
 	}
 
 	err = tegra_drm_register_client(dev->dev_private, drm);
@@ -80,10 +71,7 @@ static int gr3d_init(struct host1x_client *client)
 	return 0;
 
 detach:
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
+	host1x_client_iommu_detach(client, gr3d->group);
 free:
 	host1x_syncpt_free(client->syncpts[0]);
 put:
@@ -95,7 +83,6 @@ static int gr3d_exit(struct host1x_client *client)
 {
 	struct tegra_drm_client *drm = host1x_to_drm_client(client);
 	struct drm_device *dev = dev_get_drvdata(client->parent);
-	struct tegra_drm *tegra = dev->dev_private;
 	struct gr3d *gr3d = to_gr3d(drm);
 	int err;
 
@@ -103,14 +90,10 @@ static int gr3d_exit(struct host1x_client *client)
 	if (err < 0)
 		return err;
 
+	host1x_client_iommu_detach(client, gr3d->group);
 	host1x_syncpt_free(client->syncpts[0]);

drivers/gpu/drm/tegra/gr3d.c static int gr3d_exit(struct host1x_client *client) · line 99

Quoted 10 lines
drivers/gpu/drm/tegra/gr3d.c +0 -5
 	host1x_channel_put(gr3d->channel);
 
-	if (gr3d->group) {
-		iommu_detach_group(tegra->domain, gr3d->group);
-		iommu_group_put(gr3d->group);
-	}
-
 	return 0;
 }
 

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reviewed-by on v1 1/4
#12 lore raw
In reply to Thierry Reding
Quoted 16 lines · Thierry Reding

From: Thierry Reding <[email protected]>

If an error happens during display controller initialization, the host1x syncpoint previously requested would be leaked. Properly clean up the syncpoint along with the other resources.

---
 drivers/gpu/drm/tegra/dc.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/tegra/dc.c +0 -0
index f20648f58e49..c843f11043db 100644

drivers/gpu/drm/tegra/dc.c static int tegra_dc_init(struct host1x_client *client) · line 1931

Quoted 7 lines
drivers/gpu/drm/tegra/dc.c +2 -0
@@ -1925,6 +1925,8 @@ static int tegra_dc_init(struct host1x_client *client)
 		iommu_group_put(dc->group);
 	}
 
+	host1x_syncpt_free(dc->syncpt);
+
 	return err;
 }

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#13 lore raw
In reply to Thierry Reding
Quoted 10 lines · Thierry Reding

From: Thierry Reding <[email protected]>

If an error happens during display controller initialization, the host1x syncpoint previously requested would be leaked. Properly clean up the syncpoint along with the other resources.

---
 drivers/gpu/drm/tegra/dc.c | 2 ++
 1 file changed, 2 insertions(+)

Patches 1-4 applied.

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel