Atomic DPMS can leave a connector assigned to an enabled but inactive CRTC after the driver has removed its DC stream. A later atomic commit can then change HDR_OUTPUT_METADATA or Broadcast RGB while leaving the CRTC mode, routing and active state unchanged.
That property-only commit does not require a modeset, so it reaches the connector stream-update path with a NULL stream. An HDR metadata change passes the update bailout and reaches dc_stream_get_status(NULL), while a Broadcast RGB change dereferences the stream earlier when comparing its output color space. Skip stream updates until a stream exists. The connector state remains stored, and an enabling modeset applies it to the newly created stream. The crash was reproduced on a Phoenix1 system with DCN 3.1.4 and Linux 7.2-rc5 using a one-shot AI-generated DRM atomic reproducer: https://pastebin.com/KxT1BcSs The reproducer first sets HDR_OUTPUT_METADATA on an active CRTC, then sets CRTC ACTIVE=0 to remove the DC stream while keeping the connector routed to the CRTC, and finally changes HDR_OUTPUT_METADATA from one non-NULL blob to another. The last commit does not require a modeset and reached dc_stream_get_status(NULL) from amdgpu_dm_atomic_commit_tail(). The same sequence completed without crashing with this fix applied. Fixes: b232d4ed92ea ("drm/amd/display: Only force modesets when toggling HDR") Cc: [email protected] Assisted-by: Codex:gpt-5.6-sol Signed-off-by: David Weber <[email protected]> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 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 1820547b1dde..13101a6be437 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -11519,6 +11519,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state) dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + /* DPMS-off leaves the connector routed to a streamless CRTC. */ + if (!dm_new_crtc_state->stream) + continue; scaling_changed = is_scaling_state_different(dm_new_con_state, dm_old_con_state); -- 2.54.0
