All of lore.kernel.org
 help / color / mirror / Atom feed
* [REGRESSION] i915: UHBR training fails with TB5 dock after 1fd440de4e02; source FFE update skipped?
@ 2026-11-13 22:08 Frederik Schwan
  0 siblings, 0 replies; only message in thread
From: Frederik Schwan @ 2026-11-13 22:08 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: regressions, Imre Deak, Jani Nikula, Rodrigo Vivi


[-- Attachment #1.1: Type: text/plain, Size: 2663 bytes --]

Hi everyone,
I just upgraded my system to 7.3.x and found a regression with my notebook/dock setup.
3x 4k displays are hooked to the dock, 2 by DP and one through USB-C (I guess that DP-alt mode then).

Until 7.2 all displays worked. With 7.3 all displays work until kernel switches from fbdev (?) after
which the 2 DP displays have no signal anymore but the USB-C one still works.

Bisect:

# bad: [c03c1a14507dfaf8b856c2608f9ac216021fc222] Linux 7.3
# good: [8d3ae59288f1e7d58d76558a6ee96d533bc5019f] Linux 7.2
git bisect start 'v7.3' 'v7.2' '--' 'drivers/gpu/drm/i915/display' 'drivers/gpu/drm/display'
# good: [bbf51a67d1fe895f3d27402d2560259a619b6dba] drm/i915/dp_link_caps: Use max common lane count from link_caps
git bisect good bbf51a67d1fe895f3d27402d2560259a619b6dba
# good: [d6a1bc7c9b4ce71674a633242251d8a804ced82d] drm/i915: Throw away the BIOS fb if has the wrong depth/bpp
git bisect good d6a1bc7c9b4ce71674a633242251d8a804ced82d
# bad: [f0cabcc880aba3f05ca59d735f6d166b7fceca80] drm/i915/fbc: No surface size restrictions from LNL onwards
git bisect bad f0cabcc880aba3f05ca59d735f6d166b7fceca80
# good: [b0b6d44646dc7750df4f052d17688fb7e7569a74] drm/dp_tunnel: Add UHBR tunneling support
git bisect good b0b6d44646dc7750df4f052d17688fb7e7569a74
# bad: [662560bad9be29c3e1a2668806392d2ed9a743d6] drm/i915/bw: Fix spelling mistake "threshod" -> "threshold"
git bisect bad 662560bad9be29c3e1a2668806392d2ed9a743d6
# good: [47fff2b1749e9ba5dfab7528960555cc865360b5] drm/i915/dp: Disable UHBR link configs with 1/2 lanes
git bisect good 47fff2b1749e9ba5dfab7528960555cc865360b5
# bad: [8b9bc7786adef4e2df3a23293c0682efac6dcc83] drm/i915/dram: Interpret 0xF populated-channel count as 16
git bisect bad 8b9bc7786adef4e2df3a23293c0682efac6dcc83
# bad: [1fd440de4e02efab97874bbda0a4daf59d228fa3] drm/i915/dp_tunnel: Add UHBR tunneling support
git bisect bad 1fd440de4e02efab97874bbda0a4daf59d228fa3
# first 'bad' commit: [1fd440de4e02efab97874bbda0a4daf59d228fa3] drm/i915/dp_tunnel: Add UHBR tunneling support

I collected logs as well with `drm.debug=0x10e log_buf_len=32M thunderbolt.dyndbg=+p`:

good: v7.2-rc1-263-gb0b6d44646dc.log
bad: v7.2-rc1-268-g1fd440de4e02.log
patched: patched.log

#regzbot introduced: 1fd440de4e02efab97874bbda0a4daf59d228fa3
#regzbot title: i915: UHBR training fails through TB5 dock when source FFE updates are skipped

I was desperate and thought I'd give it a quick try with help of Codex which ended in a rabbit whole of DP protocol investigation for me :).
We came up with a patch which I tested successfully.

I've attached the patch and the "report" codex created in case you're interested.

Best regards,
Frederik

[-- Attachment #1.2: i915-uhbr-source-ffe.patch --]
[-- Type: text/plain, Size: 2472 bytes --]

From: Frederik Schwan <frederik@tty42.de>
Date: Fri, 13 Nov 2026 22:57:12 +0100
Subject: [PATCH] drm/i915/dp: Update source FFE presets during UHBR training with LTTPRs

UHBR link training uses intra-hop AUX replies at the DPRX address even
when LTTPRs are present. However, intel_dp_set_signal_levels() only
programs the source transmitter when intel_dp_phy_is_downstream_of_source()
identifies the receiver being trained as directly downstream of it.
With LTTPRs present, this check rejects DP_PHY_DPRX.

As a result, UHBR training updates the requested FFE presets in the DPCD
training set but does not apply them to the source PHY. This causes
UHBR20 and UHBR10 training failures on a Meteor Lake system connected to
a ThinkPad Thunderbolt 5 Smart Dock 7500. Enabling UHBR tunneling exposed
the existing assumption in the source signal-level update path.

Always update the source signal levels during UHBR training. Preserve
the per-PHY check for 8b/10b training, which trains downstream receivers
individually.

With this change, the affected system completes four-lane UHBR20
training, including channel equalization, interlane alignment and CDS.

Fixes: 1fd440de4e02 ("drm/i915/dp_tunnel: Add UHBR tunneling support")
Signed-off-by: Frederik Schwan <freswa@archlinux.org>
Assisted-by: Codex:gpt-6
---
The analysis and patch preparation were assisted by OpenAI Codex. The
reporter performed the bisect and hardware tests.

 drivers/gpu/drm/i915/display/intel_dp_link_training.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

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 cb92cff90614..92b8a8a1af3d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -1019,7 +1019,13 @@ void intel_dp_set_signal_levels(struct intel_dp *intel_dp,
 		       TRAIN_SET_PREEMPH_ARGS(intel_dp->train_set));
 	}
 
-	if (intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
+	/*
+	 * UHBR training uses intra-hop AUX replies at the DPRX address, even
+	 * with LTTPRs present. The requested FFE presets apply to the source
+	 * transmitter, unlike 8b/10b training of individual downstream PHYs.
+	 */
+	if (intel_dp_is_uhbr(crtc_state) ||
+	    intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
 		encoder->set_signal_levels(encoder, crtc_state);
 }
 

[-- Attachment #1.3: report.log --]
[-- Type: text/plain, Size: 7537 bytes --]

i915 UHBR / Thunderbolt 5 regression investigation
================================================

Provenance
----------
Frederik Schwan performed the bisect, built and booted the test kernels,
and supplied the hardware logs. OpenAI Codex, an AI coding assistant,
analyzed those logs and the kernel source, identified the skipped source
PHY callback, prepared the candidate fix, and ran the source-level checks.
This report was prepared by Codex. Its interpretation is offered for
maintainer review; the hardware results below come from the supplied logs.

Setup and regression boundary
-----------------------------
Host: Lenovo 21Q8CTO1WW, BIOS N4EET24W (1.10), 2026-06-29.
GPU: Intel Meteor Lake, i915, PCI ID 8086:7d51.
Dock: ThinkPad Thunderbolt 5 Smart Dock 7500, connected over Thunderbolt 5.
Display topology: dock MST hub feeding two DisplayPort 1.x displays.
Affected upstream display link: DP-4 / DDI TC3, four lanes, one LTTPR.
The GPU-side state dump shows tbt_mode: no: the physical source PHY is
in use, rather than the integrated TBT alternate-mode PHY path.

The bisect began with v7.2 good and v7.3 bad, restricted to
  drivers/gpu/drm/i915/display
  drivers/gpu/drm/display

First bad:
  1fd440de4e02efab97874bbda0a4daf59d228fa3
  drm/i915/dp_tunnel: Add UHBR tunneling support

Immediate parent tested good:
  47fff2b1749e9ba5dfab7528960555cc865360b5
  drm/i915/dp: Disable UHBR link configs with 1/2 lanes

The final patched hardware capture identifies its kernel as
7.3.4-arch1-2, built 2026-11-13 20:51:44 UTC. NVIDIA modules are also
loaded; the affected link and training messages in this report are i915.

Failure and unsuccessful experiments
------------------------------------
Before the source-FFE fix, four-lane UHBR20 training fails, including a
retry, followed by UHBR10 failure. Representative six-byte link status:
  UHBR20: 33 33 00 08 ee ee
  UHBR10: 33 33 00 08 66 66

The adjustment bytes request FFE preset 14 or 6, respectively, on all
four lanes. Lane EQ bits are set but alignment is absent. The sink-status
bit 0x08 is DP_INTRA_HOP_AUX_REPLY_INDICATION; these are intra-hop replies,
not proof that the entire downstream path has finished training.

Experiment 1 (dmesg.log): remove the legacy alignment-bit requirement
from the UHBR lane-EQ helper, preserving it for active-link monitoring.
Result: training advances to "Lane channel eq done" but then fails with
"Interlane align timeout". This did not fix the problem.

Experiment 2 (dmesg.log.1): restore the original helper and repeat the
0x2215 capability read after LTTPR initialization, logging tunnel caps.
Result: coding=01 rates=03 before initialization, after initialization,
and after the extra read; 0x2215 returns 00. UHBR20 and UHBR10 still fail
with "Max loop count reached". This did not fix the problem either.

Failed runs fall back to HBR3. Although HBR3 training passes, FEC-enable
polling subsequently times out with status 0x04 or 0x00. The logs show
8b/10b coding selected and intra-hop mode clearing; there is no evidence
that the driver simply leaves UHBR coding or intra-hop mode enabled.
The cause of the fallback FEC failure has not been established.

Source-level finding
--------------------
File: drivers/gpu/drm/i915/display/intel_dp_link_training.c
Function: intel_dp_set_signal_levels()

The existing code calls encoder->set_signal_levels() only if
intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy) returns true.
That helper accepts a link without repeaters or the source-adjacent
LTTPR, DP_PHY_LTTPR(lttpr_count - 1).

UHBR lane EQ calls the signal-level update path with DP_PHY_DPRX, even
when repeaters are present, because it uses intra-hop AUX replies.
Consequently, with one or more LTTPRs, the existing guard skips the
source transmitter callback. The debug print precedes the guard, so
"TX FFE presets: 14/14/14/14" does not establish that those presets
were programmed into the GPU PHY. The AUX training-set writes still run.

For this platform, the callback leads to intel_cx0_phy_set_signal_levels().
The lane level is derived from train_set through intel_ddi_dp_level(),
and the corresponding transmitter settings are written to the PHY.
The integrated TBT alternate-mode path has its own early return there;
that is not the path shown by this system's PHY state.

Candidate fix
-------------
Allow the callback whenever intel_dp_is_uhbr(crtc_state) is true, retaining
the existing per-PHY guard for 8b/10b:

  if (intel_dp_is_uhbr(crtc_state) ||
      intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
          encoder->set_signal_levels(encoder, crtc_state);

Neither unsuccessful experimental change is included in this fix.
The bisected commit enabled a path that exposes an older assumption;
it did not introduce the original guard itself.

Hardware evidence with the fix (dmesg.log.2)
-------------------------------------------
First successful sequence on DP-4:
  20.224632  Lane channel eq done
  20.271570  Interlane align done
  20.297496  CDS interlane align done
  20.297680  128b/132b Link Training passed at link rate = 2000000,
             lane count = 4

Second successful sequence on DP-4:
  33.891635  Lane channel eq done
  33.934586  Interlane align done
  33.956537  CDS interlane align done
  33.956747  128b/132b Link Training passed at link rate = 2000000,
             lane count = 4

The first sequence reaches status 77 77 8d 00 11 11 at CDS completion.
There are no UHBR training failures, fallback attempts, or FEC-enable
timeouts in this capture. Earlier Thunderbolt DPRX-read timeouts and
unrelated NVIDIA messages do appear; this is not an error-free system log.

The result strongly supports the skipped source FFE update as the cause
of the reported UHBR training failure. It also demonstrates that the
DP1.x monitors do not inherently prevent this upstream link training at
UHBR20. It does not establish long-term display stability or validate
UHBR-to-HBR3 fallback recovery, which was not exercised in this run.

Validation performed by Codex
-----------------------------
- Built intel_dp_link_training.o using a configuration copied from the
  running kernel and processed by olddefconfig.
- git diff --check and scripts/checkpatch.pl passed for the code change.
- A standalone harness extracted the source functions and mocked the
  encoder callback. Before the change, all UHBR cases with 1-8 repeaters
  missed the callback. Afterward, those cases passed, and tested 8b/10b
  per-PHY callback behavior was unchanged. This is not a KUnit or hardware
  test and does not validate electrical signal quality.
- The code patch applies cleanly to the v7.3 version of the source file.

Supporting material
-------------------
Primary attachments:
  bisect.log
  i915-uhbr-source-ffe.patch
  v7.2-rc1-263-gb0b6d44646dc.log (known-good capture)
  v7.2-rc1-268-g1fd440de4e02.log (first-bad capture)
  patched.log (successful final candidate on 7.3.4)

Optional experimental captures:
  dmesg.log (lane-EQ helper experiment)
  dmesg.log.1 (0x2215 refresh experiment)

Logging parameters:
  drm.debug=0x10e log_buf_len=32M thunderbolt.dyndbg=+p

Retain full logs, preferably compressed, so reviewers can inspect the
capability reads, AUX transactions, topology and ordering. The source
filenames from the bisect should be interpreted together with the actual
kernel banners and bisect.log.

[-- Attachment #1.4: v7.2-rc1-263-gb0b6d44646dc.log.zst --]
[-- Type: application/zstd, Size: 110127 bytes --]

[-- Attachment #1.5: v7.2-rc1-268-g1fd440de4e02.log.zst --]
[-- Type: application/zstd, Size: 152013 bytes --]

[-- Attachment #1.6: patched.log.zst --]
[-- Type: application/zstd, Size: 120801 bytes --]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 358 bytes --]

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-13 22:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 22:08 [REGRESSION] i915: UHBR training fails with TB5 dock after 1fd440de4e02; source FFE update skipped? Frederik Schwan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.