]> git.hungrycats.org Git - linux/commitdiff
drm: prime: fix refcounting on the dmabuf import error path
authorImre Deak <imre.deak@intel.com>
Fri, 19 Apr 2013 01:11:56 +0000 (11:11 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 May 2013 14:18:26 +0000 (07:18 -0700)
commit 011c2282c74db120f01a8414edc66c3f217f5511 upstream.

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>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/udl/udl_gem.c

index 366910ddcfcb3cd96b33c2dcd9c1d122b01990b5..4064522959ff102562aedb65c77bee5182a329ae 100644 (file)
@@ -268,7 +268,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;
                }
        }
@@ -277,6 +276,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);
@@ -297,6 +298,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);
@@ -339,6 +342,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:
index ba0a3aa785474f27ca0ba23b181e71d7d5bf82a9..ff7f2a886a346aaf5c0d03cd565e69f4967fb306 100644 (file)
@@ -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);
 }
 
index 6a5af6828624e257d4b2516ade02ce79eaf4d839..c303de1034c7a9d3ec875571e697f2d8db9d4b9d 100644 (file)
@@ -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);
 }
index ac74d1bc67bfc885e740e6adc809a0bd5c8d2b1d..1bdf7e1c37963cdb68def59fd662bef569f505d0 100644 (file)
@@ -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;
                }
        }
index 3816270ba49b31f20064e98b1fa7449792baf8ac..ef034fa3e6f5982a88fe2341a1fa03d38138d8fb 100644 (file)
@@ -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);
 }