mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
drm/vmwgfx: take fman->lock around fence list mutation in fifo_down
vmw_fence_fifo_down() drops fman->lock to wait on a fence and, on
timeout, mutates fman->fence_list via list_del_init() and signals
the fence without re-acquiring the lock. __vmw_fences_update() walks
and removes entries from the same list under fman->lock from any
other waiter, the fence-IRQ thread, or vmw_fences_update(), so the
unlocked list_del_init() can corrupt the list head.
Re-take fman->lock before manipulating fence->head and use
dma_fence_signal_locked(). Wrap the locked signalling in
dma_fence_begin_signalling() / dma_fence_end_signalling() so the
lockdep annotation that dma_fence_signal() previously provided is
preserved (the same pattern as __vmw_fences_update()).
dma_fence_put() is moved outside the lock to avoid a recursive
acquire from vmw_fence_obj_destroy(), which also takes fman->lock.
Fixes: ae2a104058 ("vmwgfx: Implement fence objects")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
Link: https://patch.msgid.link/20260505222728.519626-5-zack.rusin@broadcom.com
This commit is contained in:
parent
f47d542d59
commit
250af2e8c3
|
|
@ -367,13 +367,24 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
|
|||
ret = vmw_fence_obj_wait(fence, false, false,
|
||||
VMW_FENCE_WAIT_TIMEOUT);
|
||||
|
||||
spin_lock(&fman->lock);
|
||||
if (unlikely(ret != 0)) {
|
||||
bool cookie = dma_fence_begin_signalling();
|
||||
|
||||
list_del_init(&fence->head);
|
||||
dma_fence_signal(&fence->base);
|
||||
if (fence->waiter_added) {
|
||||
vmw_seqno_waiter_remove(fman->dev_priv);
|
||||
fence->waiter_added = false;
|
||||
}
|
||||
dma_fence_signal_locked(&fence->base);
|
||||
dma_fence_end_signalling(cookie);
|
||||
}
|
||||
|
||||
BUG_ON(!list_empty(&fence->head));
|
||||
spin_unlock(&fman->lock);
|
||||
|
||||
dma_fence_put(&fence->base);
|
||||
|
||||
spin_lock(&fman->lock);
|
||||
}
|
||||
spin_unlock(&fman->lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user