Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm/dpu: Reorder encoder kickoff for CWB

Add a helper that will handle the correct order of the encoder kickoffs
for concurrent writeback.

For concurrent writeback, the realtime encoder must always kickoff last
as it will call the trigger flush and start.

This avoids the following scenario where the writeback encoder
increments the pending kickoff count after the WB_DONE interrupt is
fired:

If the realtime encoder is kicked off first, the encoder kickoff will
flush/start the encoder and increment the pending kickoff count. The
WB_DONE interrupt then fires (before the writeback encoder is kicked
off). When the writeback encoder enters its kickoff, it will skip the
flush/start (due to CWB being enabled) and hit a frame done timeout
as the frame was kicked off (and the WB_DONE interrupt fired) without
the pending kickoff count being incremented.

In addition, the writeback timer should only start after the realtime
encoder is kicked off to ensure that we don't get timeouts when the
system has a heavy load (ex. when debug logs are enabled)

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/637491/
Link: https://lore.kernel.org/r/20250214-concurrent-wb-v6-13-a44c293cf422@quicinc.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

authored by

Jessica Zhang and committed by
Dmitry Baryshkov
ad06972d 8144d17a

+60 -14
+60 -14
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
··· 953 953 return rc; 954 954 } 955 955 956 + static int dpu_crtc_kickoff_clone_mode(struct drm_crtc *crtc) 957 + { 958 + struct drm_encoder *encoder; 959 + struct drm_encoder *rt_encoder = NULL, *wb_encoder; 960 + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); 961 + 962 + /* Find encoder for real time display */ 963 + drm_for_each_encoder_mask(encoder, crtc->dev, 964 + crtc->state->encoder_mask) { 965 + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) 966 + wb_encoder = encoder; 967 + else 968 + rt_encoder = encoder; 969 + } 970 + 971 + if (!rt_encoder || !wb_encoder) { 972 + DRM_DEBUG_ATOMIC("real time or wb encoder not found\n"); 973 + return -EINVAL; 974 + } 975 + 976 + dpu_encoder_prepare_for_kickoff(wb_encoder); 977 + dpu_encoder_prepare_for_kickoff(rt_encoder); 978 + 979 + dpu_vbif_clear_errors(dpu_kms); 980 + 981 + /* 982 + * Kickoff real time encoder last as it's the encoder that 983 + * will do the flush 984 + */ 985 + dpu_encoder_kickoff(wb_encoder); 986 + dpu_encoder_kickoff(rt_encoder); 987 + 988 + /* Don't start frame done timers until the kickoffs have finished */ 989 + dpu_encoder_start_frame_done_timer(wb_encoder); 990 + dpu_encoder_start_frame_done_timer(rt_encoder); 991 + 992 + return 0; 993 + } 994 + 956 995 /** 957 996 * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc 958 997 * @crtc: Pointer to drm crtc object ··· 1020 981 goto end; 1021 982 } 1022 983 } 1023 - /* 1024 - * Encoder will flush/start now, unless it has a tx pending. If so, it 1025 - * may delay and flush at an irq event (e.g. ppdone) 1026 - */ 1027 - drm_for_each_encoder_mask(encoder, crtc->dev, 1028 - crtc->state->encoder_mask) 1029 - dpu_encoder_prepare_for_kickoff(encoder); 984 + 985 + if (drm_crtc_in_clone_mode(crtc->state)) { 986 + if (dpu_crtc_kickoff_clone_mode(crtc)) 987 + goto end; 988 + } else { 989 + /* 990 + * Encoder will flush/start now, unless it has a tx pending. 991 + * If so, it may delay and flush at an irq event (e.g. ppdone) 992 + */ 993 + drm_for_each_encoder_mask(encoder, crtc->dev, 994 + crtc->state->encoder_mask) 995 + dpu_encoder_prepare_for_kickoff(encoder); 996 + 997 + dpu_vbif_clear_errors(dpu_kms); 998 + 999 + drm_for_each_encoder_mask(encoder, crtc->dev, 1000 + crtc->state->encoder_mask) { 1001 + dpu_encoder_kickoff(encoder); 1002 + dpu_encoder_start_frame_done_timer(encoder); 1003 + } 1004 + } 1030 1005 1031 1006 if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) { 1032 1007 /* acquire bandwidth and other resources */ ··· 1049 996 DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id); 1050 997 1051 998 dpu_crtc->play_count++; 1052 - 1053 - dpu_vbif_clear_errors(dpu_kms); 1054 - 1055 - drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { 1056 - dpu_encoder_kickoff(encoder); 1057 - dpu_encoder_start_frame_done_timer(encoder); 1058 - } 1059 999 1060 1000 reinit_completion(&dpu_crtc->frame_done_comp); 1061 1001