From: Vitaly Prosyak <[email protected]>

During GPU reset, reset_domain->sem is held exclusively (down_write)
for the entire reset sequence, which prevents any concurrent firmware
operations - they all require down_read of reset_sem before running.

However psp_resume() unconditionally takes firmware.mutex, which
inverts the lock ordering that lockdep has learned from the init path:

  firmware.mutex -> reservation_ww_class_mutex
                 -> userq_mutex -> reset_domain->sem

Lockdep reports a circular dependency when psp_resume() tries to
acquire firmware.mutex while reset_domain->sem is already held
(via amdgpu_device_lock_reset_domain).

Since down_write(reset_domain->sem) already provides the necessary
mutual exclusion against concurrent firmware operations during reset,
skip firmware.mutex when called from a GPU reset context.

Signed-off-by: Vitaly Prosyak <[email protected]>
Change-Id: Ie4c3093269d473b9859b36f67c832ad8143627cc
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index a0f6df5067e6..da344a21063c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -3954,7 +3954,12 @@ static int psp_resume(struct amdgpu_ip_block *ip_block)
                }
        }
 
-       mutex_lock(&adev->firmware.mutex);
+       /* reset_domain->sem is held exclusively during GPU reset, so no
+        * concurrent firmware operations can run; skip firmware.mutex to
+        * avoid inverting the firmware.mutex -> reset_domain->sem ordering.
+        */
+       if (!amdgpu_in_reset(adev))
+               mutex_lock(&adev->firmware.mutex);
 
        ret = amdgpu_ucode_init_bo(adev);
        if (ret)
@@ -4017,13 +4022,15 @@ static int psp_resume(struct amdgpu_ip_block *ip_block)
                                "SECUREDISPLAY: Failed to initialize 
SECUREDISPLAY\n");
        }
 
-       mutex_unlock(&adev->firmware.mutex);
+       if (!amdgpu_in_reset(adev))
+               mutex_unlock(&adev->firmware.mutex);
 
        return 0;
 
 failed:
        dev_err(adev->dev, "PSP resume failed\n");
-       mutex_unlock(&adev->firmware.mutex);
+       if (!amdgpu_in_reset(adev))
+               mutex_unlock(&adev->firmware.mutex);
        return ret;
 }
 
-- 
2.43.0

Reply via email to