[PATCH 1/2] drm/i915/flipq: Drain the flip queue before disabling pipe planes

Mika Kahola <[email protected]> Tue, 4 Aug 2026 06:30:56 +0000
Newsgroups org.freedesktop.lists.intel-xe,org.freedesktop.lists.intel-gfx
Message-ID <[email protected]>
A plane update queued into a pipe's flip queue is executed by the pipe
DMC asynchronously, potentially several vblanks later. If a later,
unrelated commit disables the pipe before that queued update has run,
intel_crtc_disable_planes() can end up racing a write that is still
only queued, not yet applied to hardware:

  cursor D assertion failure (expected off, current on)
  WARNING: .../intel_display.c:406 at assert_plane+0x11e/0x140 [xe]

Add intel_flipq_drain() and call it before intel_crtc_disable_planes()
for pipes being disabled, so any queued-but-not-yet-executed entry is
neutralized before we synchronously write the real plane-disabled state
and before assert_planes_disabled() checks it.

Assisted-by: Copilot:claude-sonnet-5
Signed-off-by: Mika Kahola <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_display.c |  2 ++
 drivers/gpu/drm/i915/display/intel_flipq.c   | 13 +++++++++++++
 drivers/gpu/drm/i915/display/intel_flipq.h   |  1 +
 3 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 9dfd095f325f..3656b9be5b5c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7003,6 +7003,8 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
 		if ((disable_pipes & BIT(crtc->pipe)) == 0)
 			continue;
 
+		intel_flipq_drain(crtc);
+
 		intel_crtc_disable_planes(state, crtc);
 
 		drm_vblank_work_flush_all(&crtc->base);
diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c b/drivers/gpu/drm/i915/display/intel_flipq.c
index bf278f60bba7..cd2cd8eda447 100644
--- a/drivers/gpu/drm/i915/display/intel_flipq.c
+++ b/drivers/gpu/drm/i915/display/intel_flipq.c
@@ -326,6 +326,19 @@ void intel_flipq_disable(const struct intel_crtc_state *crtc_state)
 	intel_de_write(display, PIPEDMC_SCANLINECMPUPPER(crtc->pipe), 0);
 }
 
+/* Empty a pipe's flip queue, discarding any entries still queued. */
+void intel_flipq_drain(struct intel_crtc *crtc)
+{
+	struct intel_display *display = to_intel_display(crtc);
+
+	if (!intel_flipq_supported(display))
+		return;
+
+	intel_flipq_preempt(crtc, true);
+
+	intel_flipq_reset(display, crtc->pipe);
+}
+
 static bool assert_flipq_has_room(struct intel_crtc *crtc,
 				  enum intel_flipq_id flipq_id)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_flipq.h b/drivers/gpu/drm/i915/display/intel_flipq.h
index 012e3e9a6bcb..c39ee0aa2ce7 100644
--- a/drivers/gpu/drm/i915/display/intel_flipq.h
+++ b/drivers/gpu/drm/i915/display/intel_flipq.h
@@ -22,6 +22,7 @@ void intel_flipq_reset(struct intel_display *display, enum pipe pipe);
 
 void intel_flipq_enable(const struct intel_crtc_state *crtc_state);
 void intel_flipq_disable(const struct intel_crtc_state *old_crtc_state);
+void intel_flipq_drain(struct intel_crtc *crtc);
 
 void intel_flipq_add(struct intel_crtc *crtc,
 		     enum intel_flipq_id flip_queue_id,
-- 
2.43.0