>From dff1f3ce5f313dc88503c1da01c959638b7d42e4 Mon Sep 17 00:00:00 2001
Message-ID: 
<dff1f3ce5f313dc88503c1da01c959638b7d42e4.1790083445.git.arthur_liber...@hotmail.com>
In-Reply-To: <[email protected]>
References: <[email protected]>
From: Arthur Liberman <[email protected]>
Date: Mon, 21 Sep 2026 01:41:20 +0300
Subject: [PATCH 1/3] drm/amd/display: fix NULL stream deref on MST DPMS-off

dc_stream_get_status() and dc_stream_get_status_const() load
stream->ctx with no NULL check. HPD detect of an MST daisy-chain
reaches them from link_set_all_streams_dpms_off_for_link() through
dc_commit_updates_for_stream(). On 6.13 that oopsed when the first
full update released current_state and the next loop iteration passed
the cleared pipe stream:

  BUG: unable to handle page fault for address: 0000000000006460
  RIP: dc_stream_get_status
  Call Trace:
    update_planes_and_stream_v1
    dc_commit_updates_for_stream
    link_set_all_streams_dpms_off_for_link
    link_detect
    handle_hpd_irq_helper

Commit 1561782686cc ("drm/amd/display: fix link_set_dpms_off
multi-display MST corner case") caches those pointers before the
loop, so the loop no longer re-reads the cleared pipe_ctx. The
helpers still oops if a caller passes NULL.

Return NULL when stream is NULL, and skip a NULL cached entry in
the DPMS-off loop.

Fixes: 09f609c34fc8 ("drm/amd/display: Fix driver load crash in amdgpu_dm")
Cc: [email protected]
Assisted-by: Cursor:xai-grok-4.6
Signed-off-by: Arthur Liberman <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++++++++++--
 drivers/gpu/drm/amd/display/dc/link/link_dpms.c |  7 +++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 8d3aacc7b96c..e5134c103bdb 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -267,14 +267,24 @@ struct dc_stream_state *dc_copy_stream(const struct 
dc_stream_state *stream)
 struct dc_stream_status *dc_stream_get_status(
        struct dc_stream_state *stream)
 {
-       struct dc *dc = stream->ctx->dc;
+       struct dc *dc;
+
+       if (!stream)
+               return NULL;
+
+       dc = stream->ctx->dc;
        return dc_state_get_stream_status(dc->current_state, stream);
 }
 
 const struct dc_stream_status *dc_stream_get_status_const(
        const struct dc_stream_state *stream)
 {
-       struct dc *dc = stream->ctx->dc;
+       struct dc *dc;
+
+       if (!stream)
+               return NULL;
+
+       dc = stream->ctx->dc;
        return dc_state_get_stream_status(dc->current_state, stream);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c 
b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 48b086d15ab0..17cb831ce8c4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -177,6 +177,13 @@ void link_set_all_streams_dpms_off_for_link(struct dc_link 
*link)
                streams[i] = pipes[i]->stream;
 
        for (i = 0; i < count; i++) {
+               /* A full update can release current_state and NULL remaining
+                * pipe streams. MST daisy-chains have multiple streams on one
+                * link, so skip any that disappeared mid-loop.
+                */
+               if (!streams[i])
+                       continue;
+
                stream_update.stream = streams[i];
                dc_commit_updates_for_stream(link->ctx->dc, NULL, 0,
                                streams[i], &stream_update,
-- 
2.55.0

Reply via email to