From: Kunal Joshi <kunal1.joshi@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Kunal Joshi <kunal1.joshi@intel.com>
Subject: [PATCH i-g-t 13/13] tests/intel/kms_dp_link_training: Verify the trained link from the sink side
Date: Wed, 16 Sep 2026 10:18:01 +0530 [thread overview]
Message-ID: <20260916044801.1279102-14-kunal1.joshi@intel.com> (raw)
In-Reply-To: <20260916044801.1279102-1-kunal1.joshi@intel.com>
The test reads everything back from the driver. A driver that believes
a link is up when the sink does not would pass, and the UHBR subtests
infer 128b/132b from the rate rather than checking it.
After training, ask the sink. MAIN_LINK_CHANNEL_CODING_SET must select
128b/132b for a UHBR configuration and 8b/10b otherwise, and the link
status must show every lane in use locked. That is the only direct
evidence that the coding the rate implies is the coding that reached
the wire.
Skip when the DPCD can be opened but not read, rather than reporting the
configuration as trained on evidence the test failed to collect. A
missing AUX character device is treated differently and only logged:
CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not enabled by default, so there is
often none at all, and that says nothing about the link, whereas AUX is
out of band and answers whether or not the link trained, so a read that
fails once the device is open is a result in itself.
An MST stream connector's AUX reaches the far sink over sideband rather
than the link partner, which is the end of the link being trained, so
use the topology's root connector for MST. The root reads disconnected
while MST is active, so find it by id instead of walking the connected
outputs.
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
tests/intel/kms_dp_link_training.c | 91 +++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
diff --git a/tests/intel/kms_dp_link_training.c b/tests/intel/kms_dp_link_training.c
index 229eb3d69..a228b5493 100644
--- a/tests/intel/kms_dp_link_training.c
+++ b/tests/intel/kms_dp_link_training.c
@@ -55,8 +55,11 @@
* link.
*/
+#include <string.h>
+
#include "i915/i915_dp.h"
#include "igt.h"
+#include "igt_dp.h"
#include "igt_kms.h"
#include "intel/kms_joiner_helper.h"
#include "intel/kms_mst_helper.h"
@@ -80,6 +83,7 @@ typedef struct {
uint32_t devid;
igt_display_t display;
igt_output_t *output;
+ int aux_fd;
} data_t;
/*
@@ -323,6 +327,79 @@ static void assert_link_recovery_idle(data_t *data,
} while (elapsed < LINK_RECOVERY_TIMEOUT);
}
+/*
+ * open_link_aux - Open the AUX device at the near end of the link.
+ *
+ * An MST stream connector's AUX reaches the far sink over sideband rather than
+ * the link partner, which is the end of the link being trained, so for MST it
+ * is the topology's root connector that has to be asked. The root reads
+ * disconnected while MST is active, so it is found by id rather than by
+ * walking the connected outputs.
+ */
+static int open_link_aux(data_t *data, bool mst)
+{
+ igt_output_t *output = data->output;
+
+ if (mst) {
+ int root_id = igt_get_dp_mst_connector_id(data->output);
+ int i;
+
+ output = NULL;
+
+ for (i = 0; i < data->display.n_outputs; i++) {
+ igt_output_t *root = &data->display.outputs[i];
+
+ if (root->config.connector &&
+ root->config.connector->connector_id == root_id) {
+ output = root;
+ break;
+ }
+ }
+
+ if (!output)
+ return -ENOENT;
+ }
+
+ return igt_dp_aux_open(data->drm_fd, output);
+}
+
+/*
+ * assert_sink_agrees - Ask the sink whether the link is really up.
+ *
+ * Everything else the test checks is read back from the driver. This is the
+ * only check that the sink agrees, and the only direct evidence of which
+ * channel coding reached the wire.
+ *
+ * A DPCD the test could open but cannot read leaves the case unverified, so
+ * skip rather than report it as trained. A missing AUX device does not: AUX is
+ * out of band and answers whether or not the link trained, so a read that
+ * fails once the device is open is a result in itself, while
+ * CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV not being enabled - it is not by default -
+ * says nothing about the link and would take every driver side check down with
+ * it.
+ */
+static void assert_sink_agrees(data_t *data,
+ const struct i915_dp_link_config *config)
+{
+ bool uhbr = i915_dp_is_uhbr_rate(config->link_rate);
+ int ret;
+
+ if (data->aux_fd < 0)
+ return;
+
+ ret = igt_dp_channel_coding_ok(data->aux_fd, uhbr);
+ igt_skip_on_f(ret < 0, "Unable to read the sink's channel coding: %s\n",
+ strerror(-ret));
+ igt_assert_f(ret, "Sink is not set to %s at rate %d\n",
+ uhbr ? "128b/132b" : "8b/10b", config->link_rate);
+
+ ret = igt_dp_link_status_ok(data->aux_fd, config->lane_count, uhbr);
+ igt_skip_on_f(ret < 0, "Unable to read the sink's link status: %s\n",
+ strerror(-ret));
+ igt_assert_f(ret, "Sink does not report %d lanes locked at rate %d\n",
+ config->lane_count, config->link_rate);
+}
+
/*
* train_link_config - Force one link configuration, re-establish the link and
* check that the configuration took effect and survived training.
@@ -366,6 +443,8 @@ static void train_link_config(data_t *data, bool mst,
* count resets the recovery state, which would mask the failure.
*/
assert_link_recovery_idle(data, config);
+
+ assert_sink_agrees(data, config);
}
/*
@@ -564,6 +643,11 @@ static bool run_link_rate_test(data_t *data, bool mst, bool uhbr)
data->output),
"Kernel has no intel_dp_allowed_link_configs debugfs\n");
+ data->aux_fd = open_link_aux(data, mst);
+ if (data->aux_fd < 0)
+ igt_info("%s: no AUX device (%s), sink side checks are skipped\n",
+ igt_output_name(data->output), strerror(-data->aux_fd));
+
/*
* Enumerate with the forced parameters reset, or the set being read is
* the forced one rather than the one the driver would pick from.
@@ -603,6 +687,11 @@ static bool run_link_rate_test(data_t *data, bool mst, bool uhbr)
igt_info("Output %s allows no %sUHBR link config\n",
igt_output_name(data->output), uhbr ? "" : "non-");
+ if (data->aux_fd >= 0) {
+ close(data->aux_fd);
+ data->aux_fd = -1;
+ }
+
igt_info("----------------------------------------------------\n");
return num_dynamics > 0;
}
@@ -718,7 +807,7 @@ IGT_TEST_DESCRIPTION("Test to validate link training on SST/MST with "
int igt_main()
{
- data_t data = {};
+ data_t data = { .aux_fd = -1 };
igt_fixture() {
data.drm_fd = drm_open_driver_master(DRIVER_INTEL | DRIVER_XE);
--
2.25.1
next prev parent reply other threads:[~2026-09-16 4:32 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-16 4:47 [PATCH i-g-t 00/13] Expand kms_dp_link_training coverage Kunal Joshi
2026-09-16 4:47 ` [PATCH i-g-t 01/13] lib/i915/i915_dp: Add helpers for the allowed link configs debugfs Kunal Joshi
2026-09-21 8:37 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 02/13] tests/intel/kms_dp_link_training: Use the UHBR helpers from lib Kunal Joshi
2026-09-21 8:38 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 03/13] tests/intel/kms_dp_link_training: Extract train_link_config() Kunal Joshi
2026-09-22 11:51 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 04/13] tests/intel/kms_dp_link_training: Check the config survived training Kunal Joshi
2026-09-22 5:25 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 05/13] tests/intel/kms_dp_link_training: Drive the smallest mode the sink offers Kunal Joshi
2026-09-22 11:59 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 06/13] tests/intel/kms_dp_link_training: Train every allowed link config Kunal Joshi
2026-09-22 13:51 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 07/13] lib/i915/i915_dp: Add a Type-C port mode query Kunal Joshi
2026-09-22 14:55 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 08/13] tests/intel/kms_dp_link_training: Log the DP link inventory in the fixture Kunal Joshi
2026-09-23 12:46 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 09/13] tests/intel/kms_dp_link_training: Group the outputs into links Kunal Joshi
2026-09-23 13:10 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 10/13] tests/intel/kms_dp_link_training: Add per connector mode subtests Kunal Joshi
2026-09-23 13:29 ` S, Sowmiya
2026-09-16 4:47 ` [PATCH i-g-t 11/13] lib/igt_dp: Add DPCD read helpers Kunal Joshi
2026-09-23 13:34 ` S, Sowmiya
2026-09-16 4:48 ` [PATCH i-g-t 12/13] lib/igt_dp: Add link status predicates for both channel codings Kunal Joshi
2026-09-23 13:55 ` S, Sowmiya
2026-09-16 4:48 ` Kunal Joshi [this message]
2026-09-23 14:00 ` [PATCH i-g-t 13/13] tests/intel/kms_dp_link_training: Verify the trained link from the sink side S, Sowmiya
2026-09-16 5:08 ` ✓ Xe.CI.BAT: success for Expand kms_dp_link_training coverage Patchwork
2026-09-16 5:25 ` ✓ i915.CI.BAT: " Patchwork
2026-09-16 6:15 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-09-16 11:59 ` ✗ i915.CI.Full: " Patchwork
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=20260916044801.1279102-14-kunal1.joshi@intel.com \
--to=kunal1.joshi@intel.com \
--cc=igt-dev@lists.freedesktop.org \
/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 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.