dpu_encoder_virt_atomic_mode_set() only writes the first num_cwb entries
of dpu_enc->hw_cwb[], and not at all when the encoder is not the
writeback of a clone, so a modeset which drops the clone, or reserves
fewer CWB blocks, keeps the pointers from the previous reservation.
dpu_encoder_helper_phys_setup_cwb() then walks every non-NULL entry: it
programs a CWB mux the crtc no longer owns, and looks its pingpong up past
the pingpongs actually assigned, in the uninitialised part of rt_pp_list[].
Store NULL for the entries which have no CWB block, as is done for the
pingpongs.
Fixes: 5008375443ed ("drm/msm/dpu: Reserve resources for CWB")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1f20695f81e3..f06b52579740 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1205,9 +1205,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct
drm_encoder *drm_enc,
ARRAY_SIZE(hw_pp));
}
- for (i = 0; i < num_cwb; i++) {
- dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
- cwb_mask |= BIT(dpu_enc->hw_cwb[i]->idx - CWB_0);
+ for (i = 0; i < MAX_CWB_PER_ENC; i++) {
+ dpu_enc->hw_cwb[i] = i < num_cwb ? to_dpu_hw_cwb(hw_cwb[i]) :
NULL;
+ if (dpu_enc->hw_cwb[i])
+ cwb_mask |= BIT(dpu_enc->hw_cwb[i]->idx - CWB_0);
}
dpu_enc->cwb_mask = cwb_mask;
--
2.47.3