From 38f4fe785b5d58cde2ae9b9d26720755673e13c4 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Mon, 24 Aug 2026 17:44:24 -0400 Subject: [PATCH] drm/amdgpu: cancel hang_detect_work before taking userq_mutex cancel_delayed_work_sync() waits for any running work instance to finish. hang_detect_work takes userq_mutex during its run, so calling cancel_delayed_work_sync() inside userq_mutex in amdgpu_userq_destroy() risks deadlock: amdgpu_userq_destroy holds userq_mutex -> cancel_delayed_work_sync -> __flush_work (waits for work) -> hang_detect_work (running) tries to acquire userq_mutex -> DEADLOCK WARNING: possible circular locking dependency detected amd_basic/3761 is trying to acquire lock: (work_completion)(&(&queue->hang_detect_work)->work), at: __flush_work but task is already holding lock: (&userq_mgr->userq_mutex), at: amdgpu_userq_destroy+0x76/0x3e0 [amdgpu] Move the cancel before mutex_lock() to eliminate this dependency. Cc: Christian Koenig Cc: Alex Deucher Cc: Sunil Khatri Cc: Prike Liang Signed-off-by: Vitaly Prosyak Reviewed-by: Christian Koenig Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 62bf6b78a534..4c6e080671a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -540,12 +540,15 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que trace_amdgpu_userq_destroy_start(queue); cancel_delayed_work_sync(&uq_mgr->resume_work); + /* Cancel before taking userq_mutex: cancel_delayed_work_sync() waits + * for any running instance, which itself takes userq_mutex. + */ + cancel_delayed_work_sync(&queue->hang_detect_work); mutex_lock(&uq_mgr->userq_mutex); amdgpu_userq_wait_for_last_fence(queue); amdgpu_userq_detach_doorbell(queue); - cancel_delayed_work_sync(&queue->hang_detect_work); #if defined(CONFIG_DEBUG_FS) debugfs_remove_recursive(queue->debugfs_queue);