public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: bitey <s.mavlenkov@mail.ru>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Cc: jani.nikula@linux.intel.com, rodrigo.vivi@intel.com
Subject: [PATCH] drm/i915/dp: Fix link retrain loop on pre-gen8 platforms with DP adapters
Date: Thu, 30 Apr 2026 06:08:46 +0300	[thread overview]
Message-ID: <20260430030846.29373-1-s.mavlenkov@mail.ru> (raw)

On Ivy Bridge (and other pre-gen8 platforms), active DP-to-HDMI protocol
converters such as the Chrontel CH73111 trigger an infinite link retrain
loop on kernels 6.x+. The monitor connected through the adapter goes
black and recovers approximately once per second, eventually causing
system instability.

Three changes introduced in the i915 DP stack combine to cause this:

1. intel_dp_stop_link_train() now automatically schedules a post-training
   link check via intel_encoder_link_check_queue_work(). The Chrontel
   adapter reports non-standard DPCD link status, which causes the check
   to fail and trigger a retrain, looping indefinitely.

2. intel_dp_needs_link_retrain() unconditionally returns true when
   seq_train_failures > 0, bypassing the actual DPCD link status read.
   A single marginal training attempt permanently marks the link as
   needing retrain.

3. intel_dp_short_pulse() forces LINK_STATUS_CHANGED on every short HPD
   for all platforms, causing unnecessary link checks that initiate the
   retrain cycle on adapters that generate frequent short HPDs.

Fix all three by gating the new behavior behind DISPLAY_VER(display) >= 8,
restoring the 5.15-era behavior for Ivy Bridge/Sandy Bridge and earlier.
These platforms use the older g4x DP path and do not benefit from the
aggressive post-training link monitoring.

Tested on Intel HD 2500 (Ivy Bridge, device ID 0152) with a Chrontel
CH73111 DP-to-HDMI adapter driving a 1920x1080 display over 2 lanes
at HBR (270 MHz).

Signed-off-by: bitey <s.mavlenkov@mail.ru>
---
 drivers/gpu/drm/i915/display/intel_dp.c              | 8 +++++++-
 drivers/gpu/drm/i915/display/intel_dp_link_training.c | 3 ++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ORIGINAL..FIXED 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5676,6 +5676,7 @@ static int
 intel_dp_read_link_status(struct intel_dp *intel_dp,
 			  u8 link_status[DP_LINK_STATUS_SIZE])
 {
+	struct intel_display *display = to_intel_display(intel_dp);
 	int err;
 
 	memset(link_status, 0, DP_LINK_STATUS_SIZE);
@@ -5712,7 +5713,8 @@ static bool intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
 	if (intel_dp->link.retrain_disabled)
 		return false;
 
-	if (intel_dp->link.seq_train_failures)
+	if (DISPLAY_VER(display) >= 8 &&
+	    intel_dp->link.seq_train_failures)
 		return true;
 
 	/* Retrain if link not ok */
@@ -5965,6 +5967,7 @@ static bool
 intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
+	struct intel_display *display = to_intel_display(intel_dp);
 	bool reprobe_needed = false;
 	u8 esi[4] = {};
 
@@ -5988,7 +5991,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 	 * TODO: let the link status check depend on LINK_STATUS_CHANGED
 	 * or intel_dp->link.force_retrain for DPCD_REV >= 1.2
 	 */
-	esi[3] |= LINK_STATUS_CHANGED;
+	if (DISPLAY_VER(display) >= 8)
+		esi[3] |= LINK_STATUS_CHANGED;
 	if (intel_dp_handle_link_service_irq(intel_dp, esi[3]))
 		reprobe_needed = true;
 
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 ORIGINAL..FIXED 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -1154,7 +1154,8 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp,
 
 	intel_hpd_unblock(encoder);
 
-	if (!display->hotplug.ignore_long_hpd &&
+	if (DISPLAY_VER(display) >= 8 &&
+	    !display->hotplug.ignore_long_hpd &&
 	    intel_dp->link.seq_train_failures < MAX_SEQ_TRAIN_FAILURES) {
 		int delay_ms = intel_dp->link.seq_train_failures ? 0 : 2000;
 
-- 
2.49.0

             reply	other threads:[~2026-04-30  7:38 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-30  3:08 bitey [this message]
2026-04-30  7:45 ` [PATCH] drm/i915/dp: Fix link retrain loop on pre-gen8 platforms with DP adapters Jani Nikula
2026-05-05  0:51 ` Claude review: " Claude Code Review Bot
2026-05-05  0:51 ` Claude Code Review Bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260430030846.29373-1-s.mavlenkov@mail.ru \
    --to=s.mavlenkov@mail.ru \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=rodrigo.vivi@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox