[PATCH 1/2] WIP: drm/i915/psr: Sync frontbuffer modifications with vblank

José Roberto de Souza jose.souza at intel.com
Wed Jul 22 20:01:19 UTC 2020


<Not final code, just did enough to prove that it works>

This fix the underruns, DMA errors and visual glitches when doing
frontbuffer modifications with high CPU usage with PSR enabled.

My teory is that HW is not able to delivery the required bandwidth
requested by PSR HW tracking(when i915 forces the PSR exit) + scanout
the same display at the same time during high CPU usage, that is why
syncing it with vblank fixes the issue.

Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
---
 drivers/gpu/drm/i915/display/intel_psr.c | 41 ++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_drv.h          |  2 ++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index bf9e320c547d..111d6f222963 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -916,6 +916,8 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
 	dev_priv->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
 	dev_priv->psr.dc3co_enabled = !!crtc_state->dc3co_exitline;
 	dev_priv->psr.transcoder = crtc_state->cpu_transcoder;
+	dev_priv->psr.adjusted = crtc_state->hw.adjusted_mode;
+	dev_priv->psr.crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	/* DC5/DC6 requires at least 6 idle frames */
 	val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6);
 	dev_priv->psr.dc3co_exit_delay = val;
@@ -1096,7 +1098,39 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 
 static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
 {
-	if (INTEL_GEN(dev_priv) >= 9)
+	if (INTEL_GEN(dev_priv) >= 9) {
+		wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&dev_priv->psr.crtc->base);
+		long timeout = msecs_to_jiffies_timeout(1);
+		DEFINE_WAIT(wait);
+		int min, max;
+
+		min = dev_priv->psr.adjusted.crtc_vblank_start -
+				intel_usecs_to_scanlines(&dev_priv->psr.adjusted, 250);
+		max = dev_priv->psr.adjusted.crtc_vblank_start - 1;
+		drm_WARN_ON(&dev_priv->drm, min <= 0 || max <= 0);
+
+		drm_crtc_vblank_get(&dev_priv->psr.crtc->base);
+		local_irq_disable();
+
+		while (true) {
+			int scanline;
+
+			prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
+
+			scanline = intel_get_crtc_scanline(dev_priv->psr.crtc);
+			if (scanline < min || scanline > max)
+				break;
+
+			drm_WARN_ON(&dev_priv->drm, !timeout);
+
+			local_irq_enable();
+			timeout = schedule_timeout(timeout);
+			local_irq_disable();
+		}
+
+		finish_wait(wq, &wait);
+		drm_crtc_vblank_put(&dev_priv->psr.crtc->base);
+
 		/*
 		 * Display WA #0884: skl+
 		 * This documented WA for bxt can be safely applied
@@ -1107,12 +1141,15 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
 		 * pipe.
 		 */
 		intel_de_write(dev_priv, CURSURFLIVE(dev_priv->psr.pipe), 0);
-	else
+
+		local_irq_enable();
+	} else {
 		/*
 		 * A write to CURSURFLIVE do not cause HW tracking to exit PSR
 		 * on older gens so doing the manual exit instead.
 		 */
 		intel_psr_exit(dev_priv);
+	}
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 56dfc6d98caa..2f2ffaa1af8b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -517,6 +517,8 @@ struct i915_psr {
 	struct delayed_work dc3co_work;
 	bool force_mode_changed;
 	struct drm_dp_vsc_sdp vsc;
+	struct drm_display_mode adjusted;
+	struct intel_crtc *crtc;
 };
 
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
-- 
2.27.0



More information about the Intel-gfx-trybot mailing list