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