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

Reply via email to