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/amdgpu: Fix user queue deadlock by reordering mutex locking

This resolves a deadlock between user queue management and GPU reset
paths by enforcing consistent lock ordering.

The deadlock occurred when:

1. Process exit path (amdgpu_userq_mgr_fini) would:
- Take uqm->userq_mutex
- Then try to take adev->userq_mutex for list operations

2. GPU reset path (amdgpu_userq_pre_reset) would:
- Take adev->userq_mutex first (for list traversal)
- Then take uqm->userq_mutex

The solution establishes a strict top-down locking order:
1. Always take adev->userq_mutex before any uqm->userq_mutex
2. Maintain this order consistently across all code paths

Changes made:
- Reordered locking in amdgpu_userq_mgr_fini() to take device lock first
- Kept existing proper order in amdgpu_userq_pre_reset()
- Simplified the fini flow by removing redundant operations

This prevents circular dependencies while maintaining thread safety
during both normal operation and GPU reset scenarios.

Fixes: 4ce60dbada96 ("drm/amdgpu: store userq_managers in a list in adev")
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Arvind Yadav <Arvind.Yadav@amd.com>
Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jesse.Zhang and committed by
Alex Deucher
648a0dc0 f71509fd

+3 -2
+3 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
··· 779 779 780 780 cancel_delayed_work_sync(&userq_mgr->resume_work); 781 781 782 + mutex_lock(&adev->userq_mutex); 782 783 mutex_lock(&userq_mgr->userq_mutex); 783 784 idr_for_each_entry(&userq_mgr->userq_idr, queue, queue_id) { 784 785 amdgpu_userq_wait_for_last_fence(userq_mgr, queue); 785 786 amdgpu_userq_unmap_helper(userq_mgr, queue); 786 787 amdgpu_userq_cleanup(userq_mgr, queue, queue_id); 787 788 } 788 - mutex_lock(&adev->userq_mutex); 789 + 789 790 list_for_each_entry_safe(uqm, tmp, &adev->userq_mgr_list, list) { 790 791 if (uqm == userq_mgr) { 791 792 list_del(&uqm->list); 792 793 break; 793 794 } 794 795 } 795 - mutex_unlock(&adev->userq_mutex); 796 796 idr_destroy(&userq_mgr->userq_idr); 797 797 mutex_unlock(&userq_mgr->userq_mutex); 798 + mutex_unlock(&adev->userq_mutex); 798 799 mutex_destroy(&userq_mgr->userq_mutex); 799 800 } 800 801