drm/prime: drop reference on imported dma-buf come from gem
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Thu, 27 Sep 2012 06:30:06 +0000 (15:30 +0900)
committerDave Airlie <airlied@redhat.com>
Tue, 8 Jan 2013 04:41:53 +0000 (14:41 +1000)
Increasing ref counts of both dma-buf and gem for imported dma-buf come from gem
makes memory leak. release function of dma-buf cannot be called because f_count
of dma-buf increased by importing gem and gem ref count cannot be decrease
because of exported dma-buf.

So I add dma_buf_put() for imported gem come from its own gem into each drivers
having prime_import and prime_export capabilities. With this, only gem ref
count is increased if importing gem exported from gem of same driver.

Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Kyungmin.park <kyungmin.park@samsung.com>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Rob Clark <rob.clark@linaro.org>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/nouveau/nouveau_prime.c
drivers/gpu/drm/radeon/radeon_prime.c
drivers/staging/omapdrm/omap_gem_dmabuf.c

index 315037a..9df9771 100644 (file)
@@ -232,7 +232,12 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 
                /* is it from our device? */
                if (obj->dev == drm_dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(obj);
+                       dma_buf_put(dma_buf);
                        return obj;
                }
        }
index 7be4241..abeaafe 100644 (file)
@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
                obj = dma_buf->priv;
                /* is it from our device? */
                if (obj->base.dev == dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(&obj->base);
+                       dma_buf_put(dma_buf);
                        return &obj->base;
                }
        }
index 3543fec..b8e05ae 100644 (file)
@@ -193,6 +193,7 @@ struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev,
                if (nvbo->gem) {
                        if (nvbo->gem->dev == dev) {
                                drm_gem_object_reference(nvbo->gem);
+                               dma_buf_put(dma_buf);
                                return nvbo->gem;
                        }
                }
index e095218..26c23bb 100644 (file)
@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_import(struct drm_device *dev,
                bo = dma_buf->priv;
                if (bo->gem_base.dev == dev) {
                        drm_gem_object_reference(&bo->gem_base);
+                       dma_buf_put(dma_buf);
                        return &bo->gem_base;
                }
        }
index 9a30206..ea38400 100644 (file)
@@ -207,7 +207,12 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
                obj = buffer->priv;
                /* is it from our device? */
                if (obj->dev == dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(obj);
+                       dma_buf_put(buffer);
                        return obj;
                }
        }