Preserve a ref to surface during dumb buffer creation. This keeps the dumb
buffer valid for framebuffer usage and fixes all igt tests that use dumb
buffers.
Also fix ttm_prime_fd_to_handle(), which in the error case was leaking a
dma_buf reference. During vmw_prime_fd_to_handle() this function
is expected to fail for dumb buffers since the fd is for a gem object,
the dma_buf would in turn hold a reference to the dumb buffer gem object
and cause a memory leak.

Fixes: f42c09e614f1 ("drm/vmwgfx: Fix dumb buffer leak")
Cc: Ian Forbes <[email protected]>
Cc: Zack Rusin <[email protected]>
Cc: Broadcom internal kernel review list <[email protected]>
Cc: [email protected]
Signed-off-by: Maaz Mombasawala <[email protected]>
---
 drivers/gpu/drm/vmwgfx/ttm_object.c     |  7 +++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c      |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h     |  1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 14 +++++++++++++-
 4 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c 
b/drivers/gpu/drm/vmwgfx/ttm_object.c
index 2421b0dd057c..f9042bafdc93 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -547,14 +547,17 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
        if (IS_ERR(dma_buf))
                return PTR_ERR(dma_buf);
 
-       if (dma_buf->ops != &tdev->ops)
-               return -ENOSYS;
+       if (dma_buf->ops != &tdev->ops) {
+               ret = -ENOSYS;
+               goto out;
+       }
 
        prime = (struct ttm_prime_object *) dma_buf->priv;
        base = &prime->base;
        *handle = base->handle;
        ret = ttm_ref_object_add(tfile, base, NULL, false);
 
+out:
        dma_buf_put(dma_buf);
 
        return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index a69a6764ead2..3de255a619a8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -72,7 +72,7 @@ static void vmw_bo_free(struct ttm_buffer_object *bo)
                                               0);
                        mutex_unlock(&res->dev_priv->cmdbuf_mutex);
                }
-               vmw_surface_unreference(&vbo->dumb_surface);
+               vmw_dumb_surface_unref(&vbo->dumb_surface);
        }
        WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree));
        drm_gem_object_release(&vbo->tbo.base);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 812f1224f83e..cd46d3995ade 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1185,6 +1185,7 @@ u32 vmw_lookup_surface_handle_for_buffer(struct 
vmw_private *vmw,
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args);
+void vmw_dumb_surface_unref(struct vmw_surface **dumb_surface);
 
 /*
  * Shader management - vmwgfx_shader.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index ab611943d774..5a9c953eb73c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -2328,11 +2328,23 @@ int vmw_dumb_create(struct drm_file *file_priv,
        struct vmw_user_surface *usurf = container_of(vbo->dumb_surface,
                                                struct vmw_user_surface, srf);
        usurf->prime.base.refcount_release = NULL;
+
+       ttm_base_object_lookup_for_ref(dev_priv->tdev, arg.rep.handle);
+
 err:
        if (res)
                vmw_resource_unreference(&res);
-
        ttm_ref_object_base_unref(tfile, arg.rep.handle);
 
        return ret;
 }
+
+void vmw_dumb_surface_unref(struct vmw_surface **dumb_surface)
+{
+       struct vmw_user_surface *usurf = container_of(*dumb_surface,
+                                               struct vmw_user_surface, srf);
+       struct ttm_base_object *base = &usurf->prime.base;
+
+       ttm_base_object_unref(&base);
+       vmw_surface_unreference(dumb_surface);
+}
-- 
2.54.0

Reply via email to