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

Mika Kahola <[email protected]>
Newsgroups org.freedesktop.lists.intel-gfx,org.freedesktop.lists.intel-xe
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.