to_cmtg_transcoder() returns INVALID_TRANSCODER (-1) for any
cpu_transcoder other than TRANSCODER_A/B. intel_cmtg_disable() then uses
the resulting cmtg_transcoder to index the per-transcoder register array
via TRANS_VRR_CTL(), but unlike the other CMTG helpers it does not check
for INVALID_TRANSCODER first. The only guard is crtc->cmtg.enabled, which
is a sticky flag on struct intel_crtc and can be set while the crtc_state
being disabled has a cpu_transcoder that does not map to a CMTG
transcoder (e.g. during a big-joiner reconfiguration that moves the eDP
across pipes).

This results in a negative array index (trans_offsets[-1]) and a UBSAN
splat:

  UBSAN: array-index-out-of-bounds in .../display/intel_cmtg.c:187:24
  intel_cmtg_disable+0x395/0x3d0 [xe]
  intel_old_crtc_state_disables+0xfb/0x1f0 [xe]
  intel_atomic_commit_tail+0xca6/0x2040 [xe]

Bail out early when cmtg_transcoder is INVALID_TRANSCODER, matching the
guard already used by the other CMTG helpers.

Fixes: 3bb44e8d421a ("drm/i915/cmtg: Modify existing hook to disable CMTG")
Signed-off-by: Animesh Manna <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_cmtg.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c 
b/drivers/gpu/drm/i915/display/intel_cmtg.c
index 6da28c185080..dcd29ebdb432 100644
--- a/drivers/gpu/drm/i915/display/intel_cmtg.c
+++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
@@ -183,6 +183,9 @@ void intel_cmtg_disable(const struct intel_crtc_state 
*crtc_state)
        if (!crtc->cmtg.enabled)
                return;
 
+       if (cmtg_transcoder == INVALID_TRANSCODER)
+               return;
+
        crtc->cmtg.enabled = false;
        intel_de_rmw(display, TRANS_VRR_CTL(display, cmtg_transcoder),
                     VRR_CTL_VRR_ENABLE | VRR_CTL_FLIP_LINE_EN, 0);
-- 
2.29.0

Reply via email to