]> git.hungrycats.org Git - linux/commitdiff
drm/amd/display: fix dc_lock leak on GPU reset error paths
authorLinkai Gong <gonglinkai@kylinos.cn>
Wed, 19 Aug 2026 05:47:42 +0000 (13:47 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 25 Aug 2026 22:24:30 +0000 (18:24 -0400)
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>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 284aac4d96bceb740c4f3a4125436bd159ccc957..ec483276d75381e2c12b455bfa9fbf12ec382cb7 100644 (file)
@@ -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;
                }