All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors
@ 2018-05-04 13:37 Thierry Reding
  2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 13:37 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, Dmitry Osipenko, dri-devel

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/tegra/dc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index f20648f58e49..c843f11043db 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -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;
 }
 
-- 
2.17.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources
  2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
@ 2018-05-04 13:37 ` Thierry Reding
  2018-05-04 14:16   ` Dmitry Osipenko
  2018-05-07 20:57   ` Dmitry Osipenko
  2018-05-04 13:37 ` [PATCH 3/4] drm/tegra: gr3d: " Thierry Reding
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 13:37 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, Dmitry Osipenko, dri-devel

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 8eb530a85dd0..0b42e99da8ad 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -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)
-- 
2.17.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/4] drm/tegra: gr3d: Properly clean up resources
  2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
  2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
@ 2018-05-04 13:37 ` Thierry Reding
  2018-05-04 14:16   ` Dmitry Osipenko
  2018-05-04 13:37 ` [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach Thierry Reding
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 13:37 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, Dmitry Osipenko, dri-devel

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index ce5120683091..e129f1afff33 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -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)
-- 
2.17.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
  2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
  2018-05-04 13:37 ` [PATCH 3/4] drm/tegra: gr3d: " Thierry Reding
@ 2018-05-04 13:37 ` Thierry Reding
  2018-05-04 14:23   ` Dmitry Osipenko
  2018-05-10 23:42   ` Dmitry Osipenko
  2018-05-04 14:14 ` [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Dmitry Osipenko
  2018-05-04 15:16 ` Thierry Reding
  4 siblings, 2 replies; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 13:37 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, Dmitry Osipenko, dri-devel

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index c843f11043db..3e7ec3937346 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -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;
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 7afe2f635f74..bc1008305e1e 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -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;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 4f41aaec8530..fe263cf58f34 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -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);
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 0b42e99da8ad..2cd0f66c8aa9 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -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;
 }
 
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index e129f1afff33..98e3c67d0fb5 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -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;
 }
 
-- 
2.17.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors
  2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
                   ` (2 preceding siblings ...)
  2018-05-04 13:37 ` [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach Thierry Reding
@ 2018-05-04 14:14 ` Dmitry Osipenko
  2018-05-04 15:16 ` Thierry Reding
  4 siblings, 0 replies; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-04 14:14 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/tegra/dc.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index f20648f58e49..c843f11043db 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -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;
>  }

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources
  2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
@ 2018-05-04 14:16   ` Dmitry Osipenko
  2018-05-07 20:57   ` Dmitry Osipenko
  1 sibling, 0 replies; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-04 14:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
>  1 file changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> index 8eb530a85dd0..0b42e99da8ad 100644
> --- a/drivers/gpu/drm/tegra/gr2d.c
> +++ b/drivers/gpu/drm/tegra/gr2d.c
> @@ -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)
> 

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/4] drm/tegra: gr3d: Properly clean up resources
  2018-05-04 13:37 ` [PATCH 3/4] drm/tegra: gr3d: " Thierry Reding
@ 2018-05-04 14:16   ` Dmitry Osipenko
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-04 14:16 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++------
>  1 file changed, 21 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
> index ce5120683091..e129f1afff33 100644
> --- a/drivers/gpu/drm/tegra/gr3d.c
> +++ b/drivers/gpu/drm/tegra/gr3d.c
> @@ -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)
> 

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 13:37 ` [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach Thierry Reding
@ 2018-05-04 14:23   ` Dmitry Osipenko
  2018-05-04 15:10     ` Thierry Reding
  2018-05-10 23:42   ` Dmitry Osipenko
  1 sibling, 1 reply; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-04 14:23 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Attaching to and detaching from an IOMMU uses the same code sequence in
> every driver, so factor it out into separate helpers.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  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(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index c843f11043db..3e7ec3937346 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -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;
> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index 7afe2f635f74..bc1008305e1e 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -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;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 4f41aaec8530..fe263cf58f34 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -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);
> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> index 0b42e99da8ad..2cd0f66c8aa9 100644
> --- a/drivers/gpu/drm/tegra/gr2d.c
> +++ b/drivers/gpu/drm/tegra/gr2d.c
> @@ -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;
>  }
>  
> diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
> index e129f1afff33..98e3c67d0fb5 100644
> --- a/drivers/gpu/drm/tegra/gr3d.c
> +++ b/drivers/gpu/drm/tegra/gr3d.c
> @@ -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;
>  }
>  
> 

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 14:23   ` Dmitry Osipenko
@ 2018-05-04 15:10     ` Thierry Reding
  2018-05-04 15:17       ` Dmitry Osipenko
  0 siblings, 1 reply; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 15:10 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: linux-tegra, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 11021 bytes --]

On Fri, May 04, 2018 at 05:23:42PM +0300, Dmitry Osipenko wrote:
> On 04.05.2018 16:37, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > Attaching to and detaching from an IOMMU uses the same code sequence in
> > every driver, so factor it out into separate helpers.
> > 
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  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(-)
> > 
> > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> > index c843f11043db..3e7ec3937346 100644
> > --- a/drivers/gpu/drm/tegra/dc.c
> > +++ b/drivers/gpu/drm/tegra/dc.c
> > @@ -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;
> > diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> > index 7afe2f635f74..bc1008305e1e 100644
> > --- a/drivers/gpu/drm/tegra/drm.c
> > +++ b/drivers/gpu/drm/tegra/drm.c
> > @@ -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;
> > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > index 4f41aaec8530..fe263cf58f34 100644
> > --- a/drivers/gpu/drm/tegra/drm.h
> > +++ b/drivers/gpu/drm/tegra/drm.h
> > @@ -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);
> > diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> > index 0b42e99da8ad..2cd0f66c8aa9 100644
> > --- a/drivers/gpu/drm/tegra/gr2d.c
> > +++ b/drivers/gpu/drm/tegra/gr2d.c
> > @@ -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;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
> > index e129f1afff33..98e3c67d0fb5 100644
> > --- a/drivers/gpu/drm/tegra/gr3d.c
> > +++ b/drivers/gpu/drm/tegra/gr3d.c
> > @@ -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;
> >  }
> >  
> > 
> 
> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> 
> 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

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors
  2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
                   ` (3 preceding siblings ...)
  2018-05-04 14:14 ` [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Dmitry Osipenko
@ 2018-05-04 15:16 ` Thierry Reding
  4 siblings, 0 replies; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 15:16 UTC (permalink / raw)
  To: Dmitry Osipenko, linux-tegra, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 482 bytes --]

On Fri, May 04, 2018 at 03:37:04PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/tegra/dc.c | 2 ++
>  1 file changed, 2 insertions(+)

Patches 1-4 applied.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 15:10     ` Thierry Reding
@ 2018-05-04 15:17       ` Dmitry Osipenko
  2018-05-04 15:25         ` Thierry Reding
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-04 15:17 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 18:10, Thierry Reding wrote:
> On Fri, May 04, 2018 at 05:23:42PM +0300, Dmitry Osipenko wrote:
>> On 04.05.2018 16:37, Thierry Reding wrote:
>>> From: Thierry Reding <treding@nvidia.com>
>>>
>>> Attaching to and detaching from an IOMMU uses the same code sequence in
>>> every driver, so factor it out into separate helpers.
>>>
>>> Signed-off-by: Thierry Reding <treding@nvidia.com>
>>> ---
>>>  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(-)
>>>
>>> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
>>> index c843f11043db..3e7ec3937346 100644
>>> --- a/drivers/gpu/drm/tegra/dc.c
>>> +++ b/drivers/gpu/drm/tegra/dc.c
>>> @@ -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;
>>> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
>>> index 7afe2f635f74..bc1008305e1e 100644
>>> --- a/drivers/gpu/drm/tegra/drm.c
>>> +++ b/drivers/gpu/drm/tegra/drm.c
>>> @@ -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;
>>> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
>>> index 4f41aaec8530..fe263cf58f34 100644
>>> --- a/drivers/gpu/drm/tegra/drm.h
>>> +++ b/drivers/gpu/drm/tegra/drm.h
>>> @@ -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);
>>> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
>>> index 0b42e99da8ad..2cd0f66c8aa9 100644
>>> --- a/drivers/gpu/drm/tegra/gr2d.c
>>> +++ b/drivers/gpu/drm/tegra/gr2d.c
>>> @@ -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;
>>>  }
>>>  
>>> diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
>>> index e129f1afff33..98e3c67d0fb5 100644
>>> --- a/drivers/gpu/drm/tegra/gr3d.c
>>> +++ b/drivers/gpu/drm/tegra/gr3d.c
>>> @@ -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;
>>>  }
>>>  
>>>
>>
>> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
>>
>> 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!

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
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 15:17       ` Dmitry Osipenko
@ 2018-05-04 15:25         ` Thierry Reding
  0 siblings, 0 replies; 14+ messages in thread
From: Thierry Reding @ 2018-05-04 15:25 UTC (permalink / raw)
  To: Dmitry Osipenko; +Cc: linux-tegra, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 12166 bytes --]

On Fri, May 04, 2018 at 06:17:45PM +0300, Dmitry Osipenko wrote:
> On 04.05.2018 18:10, Thierry Reding wrote:
> > On Fri, May 04, 2018 at 05:23:42PM +0300, Dmitry Osipenko wrote:
> >> On 04.05.2018 16:37, Thierry Reding wrote:
> >>> From: Thierry Reding <treding@nvidia.com>
> >>>
> >>> Attaching to and detaching from an IOMMU uses the same code sequence in
> >>> every driver, so factor it out into separate helpers.
> >>>
> >>> Signed-off-by: Thierry Reding <treding@nvidia.com>
> >>> ---
> >>>  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(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> >>> index c843f11043db..3e7ec3937346 100644
> >>> --- a/drivers/gpu/drm/tegra/dc.c
> >>> +++ b/drivers/gpu/drm/tegra/dc.c
> >>> @@ -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;
> >>> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> >>> index 7afe2f635f74..bc1008305e1e 100644
> >>> --- a/drivers/gpu/drm/tegra/drm.c
> >>> +++ b/drivers/gpu/drm/tegra/drm.c
> >>> @@ -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;
> >>> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> >>> index 4f41aaec8530..fe263cf58f34 100644
> >>> --- a/drivers/gpu/drm/tegra/drm.h
> >>> +++ b/drivers/gpu/drm/tegra/drm.h
> >>> @@ -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);
> >>> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> >>> index 0b42e99da8ad..2cd0f66c8aa9 100644
> >>> --- a/drivers/gpu/drm/tegra/gr2d.c
> >>> +++ b/drivers/gpu/drm/tegra/gr2d.c
> >>> @@ -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;
> >>>  }
> >>>  
> >>> diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
> >>> index e129f1afff33..98e3c67d0fb5 100644
> >>> --- a/drivers/gpu/drm/tegra/gr3d.c
> >>> +++ b/drivers/gpu/drm/tegra/gr3d.c
> >>> @@ -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;
> >>>  }
> >>>  
> >>>
> >>
> >> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> >>
> >> 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!
> 
> 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

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources
  2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
  2018-05-04 14:16   ` Dmitry Osipenko
@ 2018-05-07 20:57   ` Dmitry Osipenko
  1 sibling, 0 replies; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-07 20:57 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/tegra/gr2d.c | 28 ++++++++++++++++++++++------
>  1 file changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> index 8eb530a85dd0..0b42e99da8ad 100644
> --- a/drivers/gpu/drm/tegra/gr2d.c
> +++ b/drivers/gpu/drm/tegra/gr2d.c
> @@ -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
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach
  2018-05-04 13:37 ` [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach Thierry Reding
  2018-05-04 14:23   ` Dmitry Osipenko
@ 2018-05-10 23:42   ` Dmitry Osipenko
  1 sibling, 0 replies; 14+ messages in thread
From: Dmitry Osipenko @ 2018-05-10 23:42 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-tegra, dri-devel

On 04.05.2018 16:37, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Attaching to and detaching from an IOMMU uses the same code sequence in
> every driver, so factor it out into separate helpers.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  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(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index c843f11043db..3e7ec3937346 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -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;
> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index 7afe2f635f74..bc1008305e1e 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -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;

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);

> +		}
> +	}
> +
> +	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;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 4f41aaec8530..fe263cf58f34 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -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);
> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
> index 0b42e99da8ad..2cd0f66c8aa9 100644
> --- a/drivers/gpu/drm/tegra/gr2d.c
> +++ b/drivers/gpu/drm/tegra/gr2d.c
> @@ -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;
>  }
>  
> diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
> index e129f1afff33..98e3c67d0fb5 100644
> --- a/drivers/gpu/drm/tegra/gr3d.c
> +++ b/drivers/gpu/drm/tegra/gr3d.c
> @@ -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;
>  }
>  
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2018-05-10 23:42 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-04 13:37 [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Thierry Reding
2018-05-04 13:37 ` [PATCH 2/4] drm/tegra: gr2d: Properly clean up resources Thierry Reding
2018-05-04 14:16   ` Dmitry Osipenko
2018-05-07 20:57   ` Dmitry Osipenko
2018-05-04 13:37 ` [PATCH 3/4] drm/tegra: gr3d: " Thierry Reding
2018-05-04 14:16   ` Dmitry Osipenko
2018-05-04 13:37 ` [PATCH 4/4] drm/tegra: Refactor IOMMU attach/detach Thierry Reding
2018-05-04 14:23   ` Dmitry Osipenko
2018-05-04 15:10     ` Thierry Reding
2018-05-04 15:17       ` Dmitry Osipenko
2018-05-04 15:25         ` Thierry Reding
2018-05-10 23:42   ` Dmitry Osipenko
2018-05-04 14:14 ` [PATCH 1/4] drm/tegra: dc: Free syncpoint on errors Dmitry Osipenko
2018-05-04 15:16 ` Thierry Reding

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.