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