Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Kunal Joshi <kunal1.joshi@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Kunal Joshi <kunal1.joshi@intel.com>, Sowmiya S <sowmiya.s@intel.com>
Subject: [PATCH i-g-t 13/13] tests/intel/kms_dp_link_training: check the link from the sink side
Date: Thu,  1 Oct 2026 13:07:03 +0530	[thread overview]
Message-ID: <20261001073703.5067-14-kunal1.joshi@intel.com> (raw)
In-Reply-To: <20261001073703.5067-1-kunal1.joshi@intel.com>

All the checks so far are based on what the driver reports. After
training, also check the sink's DPCD. The channel coding must be
128b/132b for UHBR and 8b/10b otherwise, and all the lanes in use must
be locked.

If the DPCD can't be read, skip rather than pass on the driver side
checks alone. If there's no AUX device at all, only log it, and carry
on without the sink side checks. CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV
isn't enabled by default, and its absence says nothing about the link.

For MST, use the AUX of the root connector. The stream connector's AUX
goes to the far end sink via sideband messages, not the link partner.

Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
Reviewed-by: Sowmiya S <sowmiya.s@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 8f99f43f0..c1f5d45df 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;
 
 /*
@@ -325,6 +329,79 @@ static void assert_link_retrain_not_disabled(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.
@@ -368,6 +445,8 @@ static void train_link_config(data_t *data, bool mst,
 	 * count resets the recovery state, which would mask the failure.
 	 */
 	assert_link_retrain_not_disabled(data, config);
+
+	assert_sink_agrees(data, config);
 }
 
 /*
@@ -569,6 +648,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.
@@ -606,6 +690,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;
 }
@@ -721,7 +810,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


  parent reply	other threads:[~2026-10-01  7:19 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01  7:36 [PATCH i-g-t 00/13] Expand kms_dp_link_training coverage Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 01/13] lib/i915/i915_dp: add helpers for the allowed link configs debugfs Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 02/13] tests/intel/kms_dp_link_training: use i915_dp_is_uhbr_rate() Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 03/13] tests/intel/kms_dp_link_training: extract train_link_config() Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 04/13] tests/intel/kms_dp_link_training: detect links that failed training Kunal Joshi
2026-10-01  9:05   ` S, Sowmiya
2026-10-01  7:36 ` [PATCH i-g-t 05/13] tests/intel/kms_dp_link_training: use the lowest pixel clock mode Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 06/13] tests/intel/kms_dp_link_training: train all allowed link configs Kunal Joshi
2026-10-01  9:05   ` S, Sowmiya
2026-10-01  7:36 ` [PATCH i-g-t 07/13] lib/i915/i915_dp: add i915_dp_get_tc_mode() Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 08/13] tests/intel/kms_dp_link_training: log the DP link inventory Kunal Joshi
2026-10-01  7:36 ` [PATCH i-g-t 09/13] tests/intel/kms_dp_link_training: train each MST topology only once Kunal Joshi
2026-10-01  7:37 ` [PATCH i-g-t 10/13] tests/intel/kms_dp_link_training: add tbt-alt and direct link subtests Kunal Joshi
2026-10-01  7:37 ` [PATCH i-g-t 11/13] lib/igt_dp: add DPCD read helpers Kunal Joshi
2026-10-01  7:37 ` [PATCH i-g-t 12/13] lib/igt_dp: add DPCD link status and channel coding checks Kunal Joshi
2026-10-01  7:37 ` Kunal Joshi [this message]
2026-10-01 13:13 ` ✓ i915.CI.BAT: success for Expand kms_dp_link_training coverage (rev2) Patchwork
2026-10-01 16:42 ` ✓ Xe.CI.BAT: " Patchwork
2026-10-01 21:02 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-10-05 16:06   ` Joshi, Kunal1
2026-10-02 17:18 ` ✗ i915.CI.Full: " Patchwork
2026-10-05 16:04   ` Joshi, Kunal1

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=20261001073703.5067-14-kunal1.joshi@intel.com \
    --to=kunal1.joshi@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=sowmiya.s@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