dc_state_create_copy() can return NULL on allocation failure.
dm_suspend() only conditionally skips dm_gpureset_toggle_interrupts()
and continues execution, returning success.  dm_resume() then
dereferences the NULL cached_dc_state in link_enc_cfg_copy() and the
following dc_state->stream_count loop, crashing during GPU reset
recovery.

Return -ENOMEM immediately if the copy fails, so the caller aborts
suspend instead of leaving a NULL cached state for resume.

Fixes: 8092aa3ab8f7 ("drm/amd/display: Add null checker before passing 
variables")
Cc: [email protected]
Signed-off-by: Jiangshan Yi <[email protected]>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 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 ec483276d753..88505efb42a3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1582,9 +1582,14 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
                dc_allow_idle_optimizations(adev->dm.dc, false);

                dm->cached_dc_state = 
dc_state_create_copy(dm->dc->current_state);
+               if (!dm->cached_dc_state) {
+                       drm_err(adev_to_drm(adev),
+                               "Failed to allocate cached DC state during 
suspend\n");
+                       mutex_unlock(&dm->dc_lock);
+                       return -ENOMEM;
+               }

-               if (dm->cached_dc_state)
-                       dm_gpureset_toggle_interrupts(adev, 
dm->cached_dc_state, false);
+               dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);

                res = amdgpu_dm_commit_zero_streams(dm->dc);
                if (res != DC_OK) {
--
2.25.1

Reply via email to