Blob Blame History Raw
From: Rob Clark <robdclark@gmail.com>
Date: Tue, 3 Jul 2018 08:14:32 -0400
Subject: drm/msm/mdp5: fix missing CTL flush
Git-commit: 6e8bed6a3e2fd6f1e82ea9b1f705bbc82060a2b7
Patch-mainline: v4.19-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

f9cb8d8d836e fixed various race conditions with CTL flush, in particular
flushing and sending the START signal before encoder state was updated.
But it did this a little too well in some cases that don't trigger
encoder->enable(), and CTL[n].FLUSH would never be set.  When page flips
happen it would paper over the bug, since the first plag flip would
flush out the state to the hardware.

The issue could be reproduced with, for example, modetest (without the
'-v' argument).

Fixes: f9cb8d8d836e drm/msm/mdp5: rework CTL START signal handling
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
@@ -319,7 +319,17 @@ static int mdp5_encoder_atomic_check(str
 
 	mdp5_cstate->ctl = ctl;
 	mdp5_cstate->pipeline.intf = intf;
-	mdp5_cstate->defer_start = true;
+
+	/*
+	 * This is a bit awkward, but we want to flush the CTL and hit the
+	 * START bit at most once for an atomic update.  In the non-full-
+	 * modeset case, this is done from crtc->atomic_flush(), but that
+	 * is too early in the case of full modeset, in which case we
+	 * defer to encoder->enable().  But we need to *know* whether
+	 * encoder->enable() will be called to do this:
+	 */
+	if (drm_atomic_crtc_needs_modeset(crtc_state))
+		mdp5_cstate->defer_start = true;
 
 	return 0;
 }