On GPU reset, dm_suspend() takes dc_lock and leaves it for dm_resume()
to drop. If amdgpu_dm_commit_zero_streams() or dm_dmub_hw_init() fails,
the function returns with the lock still held. The matching resume path
is then skipped, so every later dc_lock take hangs.

Release the cached DC state and unlock before returning the error.

Fixes: 3cf7a0bc87f0 ("drm/amd/display: Catch failures for 
amdgpu_dm_commit_zero_streams()")
Fixes: 2b6943df5413 ("drm/amd/display: Pass up errors for reset GPU that fails 
to init HW")
Cc: [email protected]
Signed-off-by: Linkai Gong <[email protected]>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 941c1a312824..214aca906fe1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3511,6 +3511,9 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
                res = amdgpu_dm_commit_zero_streams(dm->dc);
                if (res != DC_OK) {
                        drm_err(adev_to_drm(adev), "Failed to commit zero 
streams: %d\n", res);
+                       dc_state_release(dm->cached_dc_state);
+                       dm->cached_dc_state = NULL;
+                       mutex_unlock(&dm->dc_lock);
                        return -EINVAL;
                }
 
@@ -3824,6 +3827,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
                r = dm_dmub_hw_init(adev);
                if (r) {
                        drm_err(adev_to_drm(adev), "DMUB interface failed to 
initialize: status=%d\n", r);
+                       dc_state_release(dm->cached_dc_state);
+                       dm->cached_dc_state = NULL;
+                       mutex_unlock(&dm->dc_lock);
                        return r;
                }
 
-- 
2.25.1

Reply via email to