vmw_bo_free() detaches the surface associated with a dumb buffer and
clears its guest memory binding. It reserves the resource, but does not
hold the buffer reservation required by vmw_resource_mob_detach(). TTM
releases that reservation before invoking the buffer destructor.

KMS clients destroying dumb buffers can therefore trigger the reservation
assertion from vmw_resource_mob_detach(). GNOME reaches this path through
DRM_IOCTL_MODE_DESTROY_DUMB during cursor and display updates.

Reacquire the buffer reservation while detaching the surface and clearing
its dirty tracking and guest memory binding. Acquire it after
cmdbuf_mutex, following the command validation lock order, and release it
before releasing the resource and GEM object.

Fixes: d6667f0ddf46 ("drm/vmwgfx: Fix handling of dumb buffers")
Cc: [email protected]
Assisted-by: LLM
Signed-off-by: Zack Rusin <[email protected]>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 9c7a73c0b0dc..a6d7156e4281 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -55,6 +55,8 @@ static void vmw_bo_free(struct ttm_buffer_object *bo)
                        /* Reserve and switch the backing mob. */
                        mutex_lock(&res->dev_priv->cmdbuf_mutex);
                        (void)vmw_resource_reserve(res, false, true);
+                       /* TTM drops the reservation before calling the 
destructor. */
+                       dma_resv_lock(bo->base.resv, NULL);
                        vmw_resource_mob_detach(res);
                        if (res->dirty)
                                res->func->dirty_free(res);
@@ -62,6 +64,7 @@ static void vmw_bo_free(struct ttm_buffer_object *bo)
                                vmw_bo_dirty_release(res->guest_memory_bo);
                        res->guest_memory_bo = NULL;
                        res->guest_memory_offset = 0;
+                       dma_resv_unlock(bo->base.resv);
                        vmw_resource_unreserve(res, true, false, false, NULL,
                                               0);
                        mutex_unlock(&res->dev_priv->cmdbuf_mutex);
-- 
2.53.0

Reply via email to