* [PATCH] drm/msm/dpu: count the pending frame before kicking it off
@ 2026-10-13 14:50 Michael Burch
0 siblings, 0 replies; only message in thread
From: Michael Burch @ 2026-10-13 14:50 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov
Cc: Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, Jun Nie, linux-arm-msm, dri-devel,
freedreno, linux-kernel, stable
dpu_crtc_commit_kickoff() increments frame_pending only after
dpu_encoder_kickoff() has sent the frame to the hardware. If the frame
completes before the increment, dpu_crtc_frame_event_work() sees
frame_pending == 0 and ignores the frame-done event. The increment that
follows is never matched, so the count stays one too high until
dpu_crtc_disable() resets it.
With frame_pending stuck at 1 or more:
- dpu_encoder_resource_control(FRAME_DONE) sees a pending count above 1
on every frame and never queues delayed_off_work. A video-mode encoder
therefore never reaches ENTER_IDLE and keeps its vsync interrupt
registered for as long as the display is on.
- dpu_crtc_frame_event_work() never sees the count drop to zero, so
dpu_core_perf_crtc_release_bw() is never called.
On an X1E80100 laptop with a 120 Hz eDP panel this left the vsync
interrupt firing 120 times a second on an idle desktop: 14,407 vblank
callbacks against 21 commits in 120 s, with no vblank events requested
by userspace. Every frame-done took the frame_event_more_pending path
(591 of 591 in one trace) and the encoder never entered idle. After a
suspend cycle reset the count, the same desktop showed 3 commits, 3
frame_event_done, 3 encoder idle transitions and 25 MDSS interrupts in
60 s.
Until commit ad06972d5365 ("drm/msm/dpu: Reorder encoder kickoff for
CWB") the increment came before the kickoff. Move it back there, and
undo it if the clone-mode kickoff fails before touching the hardware.
Fixes: ad06972d5365 ("drm/msm/dpu: Reorder encoder kickoff for CWB")
Cc: stable@vger.kernel.org
Assisted-by: Copilot:claude-opus-5.5
Signed-off-by: Michael Burch <me@michaelburch.net>
---
Tested on a Dell XPS 13 9345 (X1E80100, 120 Hz eDP, video mode) with
v7.3-rc6 based kernels. With this patch the count no longer leaks in
normal use: a 120 s trace 50 minutes after boot showed 22 commits, 22
frame_event_done and 22 encoder idle transitions; about 2 hours after
boot there were 27,479 vblanks against 16,693 commits over 6,040 s,
where a leaked count gives about 725,000. Not tested: clone mode or
writeback, which this machine does not have.
Jun Nie's "drm/msm/dpu: delete timeout timer when encoder is not busy"
[1] hits the same window: the frame-done interrupt arriving before
dpu_crtc_commit_kickoff() gets past dpu_encoder_kickoff().
[1] https://lore.kernel.org/r/20260903143004.1026181-1-jun.nie@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 42d0a529b4d5..c8bd9c305a59 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1105,9 +1105,19 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
}
}
+ /* The frame-done event may be handled before the kickoff below returns. */
+ if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) {
+ /* acquire bandwidth and other resources */
+ DRM_DEBUG_ATOMIC("crtc%d first commit\n", crtc->base.id);
+ } else {
+ DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id);
+ }
+
if (drm_crtc_in_clone_mode(crtc->state)) {
- if (dpu_crtc_kickoff_clone_mode(crtc))
+ if (dpu_crtc_kickoff_clone_mode(crtc)) {
+ atomic_dec(&dpu_crtc->frame_pending);
goto end;
+ }
} else {
/*
* Encoder will flush/start now, unless it has a tx pending.
@@ -1126,12 +1136,6 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
}
}
- if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) {
- /* acquire bandwidth and other resources */
- DRM_DEBUG_ATOMIC("crtc%d first commit\n", crtc->base.id);
- } else
- DRM_DEBUG_ATOMIC("crtc%d commit\n", crtc->base.id);
-
dpu_crtc->play_count++;
reinit_completion(&dpu_crtc->frame_done_comp);
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
--
2.56.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-13 14:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 14:50 [PATCH] drm/msm/dpu: count the pending frame before kicking it off Michael Burch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®