diff mbox series

[3/5] drm/i915/dp: Fix link training interrupted by a short HPD pulse

Message ID 20250224193115.2058512-4-imre.deak@intel.com (mailing list archive)
State New
Headers show
Series drm/dp: Fix link training interrupted by HPD pulse | expand

Commit Message

Imre Deak Feb. 24, 2025, 7:31 p.m. UTC
During Display Port link training the handling of HPD pulses should be
prevented, as that handling can interfere with the link training:

- Accessing DPCD registers outside the range of link training registers
  are not allowed by the Standard (see DP Standard v2.1, 3.5.2.16.1,
  3.6.6.1). The pulse handler reads the DPRX capability registers, which
  are outside of the allowed range.
- Switching of the LTTPR transparent/non-transparent mode may reset the
  LTTPRs on the link, thus aborting any ongoing link training. The pulse
  handler does set the LTTPR mode, thus it could unexpectedly abort the
  ongoing link training.

Suspend/resume the HPD pulse handling for the duration of the link
training to prevent the above DPCD register accesses / LTTPR mode
change.

Apart from the above scenarios, there are other ways a non-link training
DPCD register could be accessed during link training: via the DRM AUX
device node, or via DPCD register probing (as performed by
drm_dp_dpcd_probe()). These will be addressed by a follow-up change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_link_training.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 11953b03bb6aa..1519c202bf8c1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -1123,6 +1123,8 @@  intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp,
 void intel_dp_stop_link_train(struct intel_dp *intel_dp,
 			      const struct intel_crtc_state *crtc_state)
 {
+	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+
 	intel_dp->link_trained = true;
 
 	intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX);
@@ -1133,6 +1135,8 @@  void intel_dp_stop_link_train(struct intel_dp *intel_dp,
 	    wait_for(intel_dp_128b132b_intra_hop(intel_dp, crtc_state) == 0, 500)) {
 		lt_dbg(intel_dp, DP_PHY_DPRX, "128b/132b intra-hop not clearing\n");
 	}
+
+	intel_hpd_resume(encoder);
 }
 
 static bool
@@ -1615,7 +1619,11 @@  void intel_dp_start_link_train(struct intel_atomic_state *state,
 	 * non-transparent mode. During an earlier LTTPR detection this
 	 * could've been prevented by an active link.
 	 */
-	int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp);
+	int lttpr_count;
+
+	intel_hpd_suspend(encoder);
+
+	lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp);
 
 	if (lttpr_count < 0)
 		/* Still continue with enabling the port and link training. */