diff mbox

[v2,9/9] drm/i915/dp: Avoid concurrent access when HW is using aux ch

Message ID 20180418224311.16577-9-jose.souza@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Souza, Jose April 18, 2018, 10:43 p.m. UTC
This will avoid some cases of concurrent access to aux ch registers when
hardware is using it(HW uses it when PSR, GTC and aux frame is enabled).

It is just first step to see if this scenario happens, if so it will be
properly handled as described in bspec.

Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
---

New patch in this series, this is replacing to the patches in this series that
was exiting PSR before a aux transaction.
As discussed with Dhinakaran, let's check first if this scenary happens if
so I will bring those patches back.

 drivers/gpu/drm/i915/intel_dp.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 258e23961456..74abd4cd93dd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1062,7 +1062,7 @@  static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp,
 	       DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
 }
 
-static bool intel_dp_aux_is_busy(struct intel_dp *intel_dp)
+static bool intel_dp_aux_is_busy(struct intel_dp *intel_dp, unsigned int tries)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv =
@@ -1073,7 +1073,7 @@  static bool intel_dp_aux_is_busy(struct intel_dp *intel_dp)
 
 	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
 
-	for (try = 3; try; try--) {
+	for (try = tries; try; try--) {
 		status = I915_READ_NOTRACE(ch_ctl);
 		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
 			return false;
@@ -1127,7 +1127,7 @@  intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	intel_dp_check_edp(intel_dp);
 
 	/* Try to wait for any previous AUX channel activity */
-	if (intel_dp_aux_is_busy(intel_dp)) {
+	if (intel_dp_aux_is_busy(intel_dp, 3)) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -1148,6 +1148,18 @@  intel_dp_aux_xfer(struct intel_dp *intel_dp,
 
 		/* Must try at least 3 times according to DP spec */
 		for (try = 0; try < 5; try++) {
+			/* WA: try to avoid concurrent access to aux ch
+			 * registers while hardware is using it, the other
+			 * way is not handled at all.
+			 */
+			if (intel_dp_aux_is_busy(intel_dp, 1)) {
+				DRM_ERROR("Aux ch %c is busy, hw is using it",
+					  aux_ch_name(intel_dp->aux_ch));
+				/* sleep for a transaction time */
+				usleep_range(400, 500);
+				continue;
+			}
+
 			/* Load the send data into the aux channel data registers */
 			for (i = 0; i < send_bytes; i += 4)
 				I915_WRITE(ch_data[i >> 2],