diff mbox

[2/2] drm: prime: fix refcounting on the dmabuf import error path

Message ID 1366333916-31695-2-git-send-email-airlied@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dave Airlie April 19, 2013, 1:11 a.m. UTC
From: Imre Deak <imre.deak@intel.com>

In commit be8a42ae60 we inroduced a refcount problem, where on the
drm_gem_prime_fd_to_handle() error path we'll call dma_buf_put() for
self imported dma buffers.

Fix this by taking a reference on the dma buffer in the .gem_import
hook instead of assuming the caller had taken one. Besides fixing the
bug this is also more logical.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Dave Airlie <airlied@gmail.com>
---
 drivers/gpu/drm/drm_prime.c                | 8 +++++++-
 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 4 +++-
 drivers/gpu/drm/i915/i915_gem_dmabuf.c     | 5 ++++-
 drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c  | 1 -
 drivers/gpu/drm/udl/udl_gem.c              | 4 ++++
 5 files changed, 18 insertions(+), 4 deletions(-)

Comments

Daniel Vetter April 24, 2013, 3:21 p.m. UTC | #1
On Fri, Apr 19, 2013 at 11:11:56AM +1000, Dave Airlie wrote:
> From: Imre Deak <imre.deak@intel.com>
> 
> In commit be8a42ae60 we inroduced a refcount problem, where on the
> drm_gem_prime_fd_to_handle() error path we'll call dma_buf_put() for
> self imported dma buffers.
> 
> Fix this by taking a reference on the dma buffer in the .gem_import
> hook instead of assuming the caller had taken one. Besides fixing the
> bug this is also more logical.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Dave Airlie <airlied@gmail.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/drm_prime.c                | 8 +++++++-
>  drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 4 +++-
>  drivers/gpu/drm/i915/i915_gem_dmabuf.c     | 5 ++++-
>  drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c  | 1 -
>  drivers/gpu/drm/udl/udl_gem.c              | 4 ++++
>  5 files changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index eb7c38d..71f02ff 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -276,7 +276,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
>  			 * refcount on gem itself instead of f_count of dmabuf.
>  			 */
>  			drm_gem_object_reference(obj);
> -			dma_buf_put(dma_buf);
>  			return obj;
>  		}
>  	}
> @@ -285,6 +284,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
>  	if (IS_ERR(attach))
>  		return ERR_PTR(PTR_ERR(attach));
>  
> +	get_dma_buf(dma_buf);
> +
>  	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
>  	if (IS_ERR_OR_NULL(sgt)) {
>  		ret = PTR_ERR(sgt);
> @@ -305,6 +306,8 @@ fail_unmap:
>  	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
>  fail_detach:
>  	dma_buf_detach(dma_buf, attach);
> +	dma_buf_put(dma_buf);
> +
>  	return ERR_PTR(ret);
>  }
>  EXPORT_SYMBOL(drm_gem_prime_import);
> @@ -347,6 +350,9 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
>  		goto fail;
>  
>  	mutex_unlock(&file_priv->prime.lock);
> +
> +	dma_buf_put(dma_buf);
> +
>  	return 0;
>  
>  fail:
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> index ba0a3aa..ff7f2a8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
> @@ -235,7 +235,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>  			 * refcount on gem itself instead of f_count of dmabuf.
>  			 */
>  			drm_gem_object_reference(obj);
> -			dma_buf_put(dma_buf);
>  			return obj;
>  		}
>  	}
> @@ -244,6 +243,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
>  	if (IS_ERR(attach))
>  		return ERR_PTR(-EINVAL);
>  
> +	get_dma_buf(dma_buf);
>  
>  	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
>  	if (IS_ERR_OR_NULL(sgt)) {
> @@ -298,6 +298,8 @@ err_unmap_attach:
>  	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
>  err_buf_detach:
>  	dma_buf_detach(dma_buf, attach);
> +	dma_buf_put(dma_buf);
> +
>  	return ERR_PTR(ret);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> index 6a5af68..c303de1 100644
> --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> @@ -271,7 +271,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
>  			 * refcount on gem itself instead of f_count of dmabuf.
>  			 */
>  			drm_gem_object_reference(&obj->base);
> -			dma_buf_put(dma_buf);
>  			return &obj->base;
>  		}
>  	}
> @@ -281,6 +280,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
>  	if (IS_ERR(attach))
>  		return ERR_CAST(attach);
>  
> +	get_dma_buf(dma_buf);
> +
>  	obj = i915_gem_object_alloc(dev);
>  	if (obj == NULL) {
>  		ret = -ENOMEM;
> @@ -300,5 +301,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
>  
>  fail_detach:
>  	dma_buf_detach(dma_buf, attach);
> +	dma_buf_put(dma_buf);
> +
>  	return ERR_PTR(ret);
>  }
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> index ac74d1b..1bdf7e1 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> @@ -212,7 +212,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
>  			 * refcount on gem itself instead of f_count of dmabuf.
>  			 */
>  			drm_gem_object_reference(obj);
> -			dma_buf_put(buffer);
>  			return obj;
>  		}
>  	}
> diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
> index 3816270..ef034fa 100644
> --- a/drivers/gpu/drm/udl/udl_gem.c
> +++ b/drivers/gpu/drm/udl/udl_gem.c
> @@ -303,6 +303,8 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
>  	if (IS_ERR(attach))
>  		return ERR_CAST(attach);
>  
> +	get_dma_buf(dma_buf);
> +
>  	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
>  	if (IS_ERR(sg)) {
>  		ret = PTR_ERR(sg);
> @@ -322,5 +324,7 @@ fail_unmap:
>  	dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
>  fail_detach:
>  	dma_buf_detach(dma_buf, attach);
> +	dma_buf_put(dma_buf);
> +
>  	return ERR_PTR(ret);
>  }
> -- 
> 1.8.2
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index eb7c38d..71f02ff 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -276,7 +276,6 @@  struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
 			 * refcount on gem itself instead of f_count of dmabuf.
 			 */
 			drm_gem_object_reference(obj);
-			dma_buf_put(dma_buf);
 			return obj;
 		}
 	}
@@ -285,6 +284,8 @@  struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
 	if (IS_ERR(attach))
 		return ERR_PTR(PTR_ERR(attach));
 
+	get_dma_buf(dma_buf);
+
 	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
 	if (IS_ERR_OR_NULL(sgt)) {
 		ret = PTR_ERR(sgt);
@@ -305,6 +306,8 @@  fail_unmap:
 	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
 fail_detach:
 	dma_buf_detach(dma_buf, attach);
+	dma_buf_put(dma_buf);
+
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(drm_gem_prime_import);
@@ -347,6 +350,9 @@  int drm_gem_prime_fd_to_handle(struct drm_device *dev,
 		goto fail;
 
 	mutex_unlock(&file_priv->prime.lock);
+
+	dma_buf_put(dma_buf);
+
 	return 0;
 
 fail:
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index ba0a3aa..ff7f2a8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -235,7 +235,6 @@  struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 			 * refcount on gem itself instead of f_count of dmabuf.
 			 */
 			drm_gem_object_reference(obj);
-			dma_buf_put(dma_buf);
 			return obj;
 		}
 	}
@@ -244,6 +243,7 @@  struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 	if (IS_ERR(attach))
 		return ERR_PTR(-EINVAL);
 
+	get_dma_buf(dma_buf);
 
 	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
 	if (IS_ERR_OR_NULL(sgt)) {
@@ -298,6 +298,8 @@  err_unmap_attach:
 	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
 err_buf_detach:
 	dma_buf_detach(dma_buf, attach);
+	dma_buf_put(dma_buf);
+
 	return ERR_PTR(ret);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 6a5af68..c303de1 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -271,7 +271,6 @@  struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 			 * refcount on gem itself instead of f_count of dmabuf.
 			 */
 			drm_gem_object_reference(&obj->base);
-			dma_buf_put(dma_buf);
 			return &obj->base;
 		}
 	}
@@ -281,6 +280,8 @@  struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 	if (IS_ERR(attach))
 		return ERR_CAST(attach);
 
+	get_dma_buf(dma_buf);
+
 	obj = i915_gem_object_alloc(dev);
 	if (obj == NULL) {
 		ret = -ENOMEM;
@@ -300,5 +301,7 @@  struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 
 fail_detach:
 	dma_buf_detach(dma_buf, attach);
+	dma_buf_put(dma_buf);
+
 	return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index ac74d1b..1bdf7e1 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -212,7 +212,6 @@  struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 			 * refcount on gem itself instead of f_count of dmabuf.
 			 */
 			drm_gem_object_reference(obj);
-			dma_buf_put(buffer);
 			return obj;
 		}
 	}
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index 3816270..ef034fa 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -303,6 +303,8 @@  struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
 	if (IS_ERR(attach))
 		return ERR_CAST(attach);
 
+	get_dma_buf(dma_buf);
+
 	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
 	if (IS_ERR(sg)) {
 		ret = PTR_ERR(sg);
@@ -322,5 +324,7 @@  fail_unmap:
 	dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
 fail_detach:
 	dma_buf_detach(dma_buf, attach);
+	dma_buf_put(dma_buf);
+
 	return ERR_PTR(ret);
 }