Commit 011c2282 authored by Imre Deak's avatar Imre Deak Committed by Dave Airlie

drm: prime: fix refcounting on the dmabuf import error path

In commit be8a42ae 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: default avatarImre Deak <imre.deak@intel.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 219b4733
...@@ -271,7 +271,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, ...@@ -271,7 +271,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
* refcount on gem itself instead of f_count of dmabuf. * refcount on gem itself instead of f_count of dmabuf.
*/ */
drm_gem_object_reference(obj); drm_gem_object_reference(obj);
dma_buf_put(dma_buf);
return obj; return obj;
} }
} }
...@@ -280,6 +279,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, ...@@ -280,6 +279,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
if (IS_ERR(attach)) if (IS_ERR(attach))
return ERR_PTR(PTR_ERR(attach)); return ERR_PTR(PTR_ERR(attach));
get_dma_buf(dma_buf);
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR_OR_NULL(sgt)) { if (IS_ERR_OR_NULL(sgt)) {
ret = PTR_ERR(sgt); ret = PTR_ERR(sgt);
...@@ -300,6 +301,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, ...@@ -300,6 +301,8 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach: fail_detach:
dma_buf_detach(dma_buf, attach); dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
EXPORT_SYMBOL(drm_gem_prime_import); EXPORT_SYMBOL(drm_gem_prime_import);
...@@ -342,6 +345,9 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev, ...@@ -342,6 +345,9 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
goto fail; goto fail;
mutex_unlock(&file_priv->prime.lock); mutex_unlock(&file_priv->prime.lock);
dma_buf_put(dma_buf);
return 0; return 0;
fail: fail:
......
...@@ -235,7 +235,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, ...@@ -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. * refcount on gem itself instead of f_count of dmabuf.
*/ */
drm_gem_object_reference(obj); drm_gem_object_reference(obj);
dma_buf_put(dma_buf);
return obj; return obj;
} }
} }
...@@ -244,6 +243,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, ...@@ -244,6 +243,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
if (IS_ERR(attach)) if (IS_ERR(attach))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
get_dma_buf(dma_buf);
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR_OR_NULL(sgt)) { if (IS_ERR_OR_NULL(sgt)) {
...@@ -298,6 +298,8 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, ...@@ -298,6 +298,8 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
err_buf_detach: err_buf_detach:
dma_buf_detach(dma_buf, attach); dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
......
...@@ -272,7 +272,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -272,7 +272,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
* refcount on gem itself instead of f_count of dmabuf. * refcount on gem itself instead of f_count of dmabuf.
*/ */
drm_gem_object_reference(&obj->base); drm_gem_object_reference(&obj->base);
dma_buf_put(dma_buf);
return &obj->base; return &obj->base;
} }
} }
...@@ -282,6 +281,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -282,6 +281,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
if (IS_ERR(attach)) if (IS_ERR(attach))
return ERR_CAST(attach); return ERR_CAST(attach);
get_dma_buf(dma_buf);
obj = i915_gem_object_alloc(dev); obj = i915_gem_object_alloc(dev);
if (obj == NULL) { if (obj == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -301,5 +302,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -301,5 +302,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
fail_detach: fail_detach:
dma_buf_detach(dma_buf, attach); dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -212,7 +212,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, ...@@ -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. * refcount on gem itself instead of f_count of dmabuf.
*/ */
drm_gem_object_reference(obj); drm_gem_object_reference(obj);
dma_buf_put(buffer);
return obj; return obj;
} }
} }
......
...@@ -303,6 +303,8 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, ...@@ -303,6 +303,8 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
if (IS_ERR(attach)) if (IS_ERR(attach))
return ERR_CAST(attach); return ERR_CAST(attach);
get_dma_buf(dma_buf);
sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sg)) { if (IS_ERR(sg)) {
ret = PTR_ERR(sg); ret = PTR_ERR(sg);
...@@ -322,5 +324,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, ...@@ -322,5 +324,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
fail_detach: fail_detach:
dma_buf_detach(dma_buf, attach); dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment