drm/vmwgfx: Add error path for xa_store in vmw_bo_add_detached_resource
authorKeisuke Nishimura <keisuke.nishimura@inria.fr>
Tue, 25 Feb 2025 14:52:23 +0000 (15:52 +0100)
committerZack Rusin <zack.rusin@broadcom.com>
Mon, 10 Mar 2025 18:31:43 +0000 (14:31 -0400)
The xa_store() may fail due to memory allocation failure because there
is no guarantee that the index is already used. This fix introduces new
paths to handle the error.

This patch also aligns the order of function calls by calling
vmw_bo_add_detached_resource() before ttm_prime_object_init() in order
to allow consistent error handling.

Fixes: d6667f0ddf46 ("drm/vmwgfx: Fix handling of dumb buffers")
Signed-off-by: Keisuke Nishimura <keisuke.nishimura@inria.fr>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250225145223.34773-1-keisuke.nishimura@inria.fr
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c

index b7766421d2f5ab5e53d756f7c11e4420371ae70f..8832e4de86f1c12573f613e141f3e10fb199a2a2 100644 (file)
@@ -848,9 +848,9 @@ void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo)
        vmw_bo_placement_set(bo, domain, domain);
 }
 
-void vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res)
+int vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res)
 {
-       xa_store(&vbo->detached_resources, (unsigned long)res, res, GFP_KERNEL);
+       return xa_err(xa_store(&vbo->detached_resources, (unsigned long)res, res, GFP_KERNEL));
 }
 
 void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res)
index e97cae2365c8274b66dcab2ccdc7e7fe05f771ca..8c81ae3f54618cb5df06f47d36238d09c0157418 100644 (file)
@@ -141,7 +141,7 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo,
                        struct ttm_resource *mem);
 void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
 
-void vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res);
+int vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res);
 void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res);
 struct vmw_surface *vmw_bo_surface(struct vmw_bo *vbo);
 
index 1a0a544b1ad07f0675b04845b469700d8f92cf6f..02ab65cc63ecadb6ee95c976af59e2631d89345f 100644 (file)
@@ -838,7 +838,12 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
                        vmw_resource_unreference(&res);
                        goto out_unlock;
                }
-               vmw_bo_add_detached_resource(res->guest_memory_bo, res);
+
+               ret = vmw_bo_add_detached_resource(res->guest_memory_bo, res);
+               if (unlikely(ret != 0)) {
+                       vmw_resource_unreference(&res);
+                       goto out_unlock;
+               }
        }
 
        tmp = vmw_resource_reference(&srf->res);
@@ -1637,6 +1642,14 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
 
        }
 
+       if (res->guest_memory_bo) {
+               ret = vmw_bo_add_detached_resource(res->guest_memory_bo, res);
+               if (unlikely(ret != 0)) {
+                       vmw_resource_unreference(&res);
+                       goto out_unlock;
+               }
+       }
+
        tmp = vmw_resource_reference(res);
        ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime,
                                    VMW_RES_SURFACE,
@@ -1651,7 +1664,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
        rep->handle      = user_srf->prime.base.handle;
        rep->backup_size = res->guest_memory_size;
        if (res->guest_memory_bo) {
-               vmw_bo_add_detached_resource(res->guest_memory_bo, res);
                rep->buffer_map_handle =
                        drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node);
                rep->buffer_size = res->guest_memory_bo->tbo.base.size;