summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinkai Gong <gonglinkai@kylinos.cn>2026-08-19 13:47:42 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-08-25 18:24:30 -0400
commit92a9eebd2a1f892fe482154d83f9f1626bc73d3b (patch)
tree29d34692e69827d330534406f62a5c77a5da1f1e /drivers
parent84298acf1c8be2b1b03c0339bf1eb63102c51728 (diff)
drm/amd/display: fix dc_lock leak on GPU reset error paths
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: stable@vger.kernel.org Signed-off-by: Linkai Gong <gonglinkai@kylinos.cn> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c6
1 files changed, 6 insertions, 0 deletions
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 284aac4d96bc..ec483276d753 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1589,6 +1589,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;
}
@@ -1884,6 +1887,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;
}