Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/vmwgfx: Add seqno waiter for sync_files

Because sync_files are passive waiters they do not participate in
the processing of fences like the traditional vmw_fence_wait IOCTL.
If userspace exclusively uses sync_files for synchronization then
nothing in the kernel actually processes fence updates as interrupts
for fences are masked and ignored if the kernel does not indicate to the
SVGA device that there are active waiters.

This oversight results in a bug where the entire GUI can freeze waiting
on a sync_file that will never be signalled as we've masked the interrupts
to signal its completion. This bug is incredibly racy as any process which
interacts with the fencing code via the 3D stack can process the stuck
fences on behalf of the stuck process causing it to run again. Even a
simple app like eglinfo is enough to resume the stuck process. Usually
this bug is seen at a login screen like GDM because there are no other
3D apps running.

By adding a seqno waiter we re-enable interrupt based processing of the
dma_fences associated with the sync_file which is signalled as part of a
dma_fence_callback.

This has likely been broken since it was initially added to the kernel in
2017 but has gone unnoticed until mutter recently started using sync_files
heavily over the course of 2024 as part of their explicit sync support.

Fixes: c906965dee22 ("drm/vmwgfx: Add export fence to file descriptor support")
Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250228200633.642417-1-ian.forbes@broadcom.com

authored by

Ian Forbes and committed by
Zack Rusin
0039a3b3 171e3a45

+26
+26
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
··· 4068 4068 return 0; 4069 4069 } 4070 4070 4071 + /* 4072 + * DMA fence callback to remove a seqno_waiter 4073 + */ 4074 + struct seqno_waiter_rm_context { 4075 + struct dma_fence_cb base; 4076 + struct vmw_private *dev_priv; 4077 + }; 4078 + 4079 + static void seqno_waiter_rm_cb(struct dma_fence *f, struct dma_fence_cb *cb) 4080 + { 4081 + struct seqno_waiter_rm_context *ctx = 4082 + container_of(cb, struct seqno_waiter_rm_context, base); 4083 + 4084 + vmw_seqno_waiter_remove(ctx->dev_priv); 4085 + kfree(ctx); 4086 + } 4087 + 4071 4088 int vmw_execbuf_process(struct drm_file *file_priv, 4072 4089 struct vmw_private *dev_priv, 4073 4090 void __user *user_commands, void *kernel_commands, ··· 4265 4248 } else { 4266 4249 /* Link the fence with the FD created earlier */ 4267 4250 fd_install(out_fence_fd, sync_file->file); 4251 + struct seqno_waiter_rm_context *ctx = 4252 + kmalloc(sizeof(*ctx), GFP_KERNEL); 4253 + ctx->dev_priv = dev_priv; 4254 + vmw_seqno_waiter_add(dev_priv); 4255 + if (dma_fence_add_callback(&fence->base, &ctx->base, 4256 + seqno_waiter_rm_cb) < 0) { 4257 + vmw_seqno_waiter_remove(dev_priv); 4258 + kfree(ctx); 4259 + } 4268 4260 } 4269 4261 } 4270 4262