When prime_handle_to_fd is called on a gem buffer handle, we return an
fd for the surface handle if the gem buffer backs a surface.
Return the gem buffer's handle instead for cases when the surface is a
scanout buffer.
Also bump the minor version since this is a slight change in behaviour.

This fixes gem_close() errors in kwin where the compositor expects a gem
handle but gets a vmw surface handle instead.

Signed-off-by: Maaz Mombasawala <[email protected]>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h     | 10 ++++---
 drivers/gpu/drm/vmwgfx/vmwgfx_prime.c   | 14 +++++----
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 38 ++++++++++++-------------
 3 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 38bea8abab84..ff33ba1075a4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -39,7 +39,7 @@
 
 #define VMWGFX_DRIVER_NAME "vmwgfx"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 21
+#define VMWGFX_DRIVER_MINOR 22
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_NUM_DISPLAY_UNITS 8
@@ -1180,9 +1180,11 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv,
 struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw,
                                                  struct vmw_bo *bo,
                                                  u32 handle);
-u32 vmw_lookup_surface_handle_for_buffer(struct vmw_private *vmw,
-                                        struct vmw_bo *bo,
-                                        u32 handle);
+void vmw_lookup_surface_and_handle_for_buffer(struct vmw_private *vmw,
+                                             struct vmw_bo *bo,
+                                             u32 handle,
+                                             u32 *srf_handle,
+                                             struct vmw_surface **p_srf);
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
index 598b90ac7590..7e6581ee09cc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
@@ -93,8 +93,9 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
        struct vmw_private *vmw = vmw_priv(dev);
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
        struct vmw_bo *vbo;
+       struct vmw_surface *surface = NULL;
+       int surf_handle = 0;
        int ret;
-       int surf_handle;
 
        if (handle > VMWGFX_NUM_MOB) {
                ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
@@ -106,16 +107,19 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
                        ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle,
                                                         flags, prime_fd);
                } else {
-                       surf_handle = vmw_lookup_surface_handle_for_buffer(vmw,
-                                                                          vbo,
-                                                                          
handle);
-                       if (surf_handle > 0)
+                       vmw_lookup_surface_and_handle_for_buffer(vmw, vbo,
+                                                                handle,
+                                                                &surf_handle,
+                                                                &surface);
+                       if (surface && !surface->metadata.scanout)
                                ret = ttm_prime_handle_to_fd(tfile, surf_handle,
                                                             flags, prime_fd);
                        else
                                ret = drm_gem_prime_handle_to_fd(dev, file_priv,
                                                                 handle, flags,
                                                                 prime_fd);
+                       if (surface)
+                               vmw_surface_unreference(&surface);
                }
                vmw_user_bo_unref(&vbo);
        }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index bd0563741e89..15455bdba402 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -895,38 +895,38 @@ vmw_lookup_user_surface_for_buffer(struct vmw_private 
*vmw, struct vmw_bo *bo,
        return user_srf;
 }
 
-struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw,
-                                                 struct vmw_bo *bo,
-                                                 u32 handle)
+void vmw_lookup_surface_and_handle_for_buffer(struct vmw_private *vmw,
+                                             struct vmw_bo *bo,
+                                             u32 handle,
+                                             u32 *srf_handle,
+                                             struct vmw_surface **p_srf)
 {
        struct vmw_user_surface *user_srf =
                vmw_lookup_user_surface_for_buffer(vmw, bo, handle);
-       struct vmw_surface *surf = NULL;
        struct ttm_base_object *base;
 
+       if (p_srf)
+               *p_srf = NULL;
+       if (srf_handle)
+               *srf_handle = 0;
        if (user_srf) {
-               surf = vmw_surface_reference(&user_srf->srf);
+               if (p_srf)
+                       *p_srf = vmw_surface_reference(&user_srf->srf);
                base = &user_srf->prime.base;
+               if (srf_handle)
+                       *srf_handle = (u32)base->handle;
                ttm_base_object_unref(&base);
        }
-       return surf;
 }
 
-u32 vmw_lookup_surface_handle_for_buffer(struct vmw_private *vmw,
-                                        struct vmw_bo *bo,
-                                        u32 handle)
+struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw,
+                                                 struct vmw_bo *bo,
+                                                 u32 handle)
 {
-       struct vmw_user_surface *user_srf =
-               vmw_lookup_user_surface_for_buffer(vmw, bo, handle);
-       int surf_handle = 0;
-       struct ttm_base_object *base;
+       struct vmw_surface *surface = NULL;
 
-       if (user_srf) {
-               base = &user_srf->prime.base;
-               surf_handle = (u32)base->handle;
-               ttm_base_object_unref(&base);
-       }
-       return surf_handle;
+       vmw_lookup_surface_and_handle_for_buffer(vmw, bo, handle, NULL, 
&surface);
+       return surface;
 }
 
 static int vmw_buffer_prime_to_surface_base(struct vmw_private *dev_priv,
-- 
2.55.0

Reply via email to