diff mbox series

[DO_NOT_REVIEW] drm/i915/display/dp: On AUX xfer timeout restart freshly

Message ID 20230622050830.1145626-1-arun.r.murthy@intel.com (mailing list archive)
State New, archived
Headers show
Series [DO_NOT_REVIEW] drm/i915/display/dp: On AUX xfer timeout restart freshly | expand

Commit Message

Murthy, Arun R June 22, 2023, 5:08 a.m. UTC
At the beginning of the aux transfer a check for aux control busy bit is
done. Then as per the spec on aux transfer timeout, need to retry
freshly for 3 times with a delay which is taken care by the control
register.
On each of these 3 trials a check for busy has to be done so as to start
freshly.

v2: updated the commit message
v4: check for SEND_BUSY after write (Imre)
v5: reverted the send_ctl to the while loop (Jani)
v6: Fixed the BAT failure

Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_aux.c | 36 ++++++++++++++-------
 1 file changed, 24 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 197c6e81db14..bebe9a337e37 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -37,7 +37,7 @@  static void intel_dp_aux_unpack(u32 src, u8 *dst, int dst_bytes)
 }
 
 static u32
-intel_dp_aux_wait_done(struct intel_dp *intel_dp)
+intel_dp_aux_wait_for(struct intel_dp *intel_dp, u32 mask, u32 val)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
@@ -45,8 +45,7 @@  intel_dp_aux_wait_done(struct intel_dp *intel_dp)
 	u32 status;
 	int ret;
 
-	ret = __intel_de_wait_for_register(i915, ch_ctl,
-					   DP_AUX_CH_CTL_SEND_BUSY, 0,
+	ret = __intel_de_wait_for_register(i915, ch_ctl, mask, val,
 					   2, timeout_ms, &status);
 
 	if (ret == -ETIMEDOUT)
@@ -321,13 +320,8 @@  intel_dp_aux_xfer(struct intel_dp *intel_dp,
 			/* Send the command and wait for it to complete */
 			intel_de_write(i915, ch_ctl, send_ctl);
 
-			status = intel_dp_aux_wait_done(intel_dp);
-
-			/* Clear done status and any errors */
-			intel_de_write(i915, ch_ctl,
-				       status | DP_AUX_CH_CTL_DONE |
-				       DP_AUX_CH_CTL_TIME_OUT_ERROR |
-				       DP_AUX_CH_CTL_RECEIVE_ERROR);
+			status = intel_dp_aux_wait_for(intel_dp,
+						       DP_AUX_CH_CTL_DONE, 1);
 
 			/*
 			 * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
@@ -335,15 +329,33 @@  intel_dp_aux_xfer(struct intel_dp *intel_dp,
 			 *   Timeout errors from the HW already meet this
 			 *   requirement so skip to next iteration
 			 */
-			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
+			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+				/* Clear the timeout error */
+				intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_TIME_OUT_ERROR, 0);
+
+				/* Clear all errors */
+				status = intel_de_read(i915, ch_ctl);
+				intel_de_write(i915, ch_ctl, status);
 				continue;
+			}
 
 			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+				/* Clear the reveive error */
+				intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_RECEIVE_ERROR, 0);
 				usleep_range(400, 500);
+				/* Clear all errors */
+				status = intel_de_read(i915, ch_ctl);
+				intel_de_write(i915, ch_ctl, status);
 				continue;
 			}
-			if (status & DP_AUX_CH_CTL_DONE)
+			if (status & DP_AUX_CH_CTL_DONE) {
+				/* Clear aux done */
+				intel_de_rmw(i915, ch_ctl, DP_AUX_CH_CTL_DONE, 0);
+				/* Clear all errors */
+				status = intel_de_read(i915, ch_ctl);
+				intel_de_write(i915, ch_ctl, status);
 				goto done;
+			}
 		}
 	}