[PATCH 2/5] drm/amdgpu: cancel hang_detect_work before taking userq_mutex

<[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Vitaly Prosyak <[email protected]>

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 <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Sunil Khatri <[email protected]>
Signed-off-by: Vitaly Prosyak <[email protected]>
---
 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 0a816b3c5ff9..52cd7d1c9f2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -543,12 +543,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);
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.