[PATCH i-g-t 8/9] tests/intel/kms_dp_fallback: add test for validating fallback

Kunal Joshi kunal1.joshi at intel.com
Sun Jun 9 21:25:34 UTC 2024


add fallback test which tries to validate fallback by
reducing link rate / lane count, until retrain is disabled
or the lowest mode bw requirements are met.

Signed-off-by: Kunal Joshi <kunal1.joshi at intel.com>
---
 tests/intel/kms_dp_fallback.c | 207 ++++++++++++++++++++++++++++++++++
 tests/meson.build             |   1 +
 2 files changed, 208 insertions(+)
 create mode 100644 tests/intel/kms_dp_fallback.c

diff --git a/tests/intel/kms_dp_fallback.c b/tests/intel/kms_dp_fallback.c
new file mode 100644
index 000000000..935a77cc6
--- /dev/null
+++ b/tests/intel/kms_dp_fallback.c
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 20234 Intel Corporation
+ */
+
+/**
+ * TEST: kms dp fallback
+ * Category: Display
+ * Description: Test link training fallback for DP connectors
+ * Driver requirement: i915, xe
+ * Functionality: link training
+ * Mega feature: General Display Features
+ * Test category: functionality test
+ */
+
+#include <sys/types.h>
+
+#include "igt.h"
+#include "igt_psr.h"
+
+/**
+ * SUBTEST: fallback
+ * Description: Test fallback
+ */
+
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	drmModeModeInfo *mode;
+	igt_output_t *output;
+	enum pipe pipe;
+	struct igt_fb fb;
+	struct igt_plane *primary;
+} data_t;
+
+IGT_TEST_DESCRIPTION("Test link training fallback for DP connectors");
+
+#define BITS_PER_PIXEL 24
+#define ENCODING_OVERHEAD_8b_10b 0.8
+#define ENCODING_OVERHEAD_128b_132b 0.9723
+
+static const char *str_link_rate(enum dp_link_rate link_rate)
+{
+	switch (link_rate) {
+	case DP_LINK_RATE_162000:
+		return "1.62 Gbps";
+	case DP_LINK_RATE_216000:
+		return "2.16 Gbps";
+	case DP_LINK_RATE_243000:
+		return "2.43 Gbps";
+	case DP_LINK_RATE_270000:
+		return "2.70 Gbps";
+	case DP_LINK_RATE_324000:
+		return "3.24 Gbps";
+	case DP_LINK_RATE_432000:
+		return "4.32 Gbps";
+	case DP_LINK_RATE_540000:
+		return "5.40 Gbps";
+	case DP_LINK_RATE_675000:
+		return "6.75 Gbps";
+	case DP_LINK_RATE_810000:
+		return "8.10 Gbps";
+	case DP_LINK_RATE_1000000:
+		return "10.00 Gbps";
+	case DP_LINK_RATE_1350000:
+		return "13.50 Gbps";
+	case DP_LINK_RATE_2000000:
+		return "20.00 Gbps";
+	default:
+		igt_assert_f(0, "Invalid link rate %d\n", link_rate);
+	}
+}
+
+static void find_min_dp_config(int drm_fd, drmModeModeInfo mode, igt_output_t *output, uint64_t *min_link_rate, int *min_lane_count)
+{
+	int i, lanes;
+	int num_rates = 0;
+	float overhead;
+	uint64_t link_rates[DP_MAX_LINK_RATE_COUNT];
+	uint64_t required_bandwidth, available_bandwidth;
+
+	igt_require_f(mode.vdisplay > 0, "No modes found\n");
+	igt_require_f(output, "Output cannot be null\n");
+
+	required_bandwidth = (uint64_t)(mode.clock * BITS_PER_PIXEL);
+	read_link_rates(drm_fd, link_rates, &num_rates, output);
+
+	for (lanes = 4; lanes > 0 ; lanes = lanes/2) {
+		for (i = num_rates-1; i > 0; i--) {
+			overhead = link_rates[i] >= DP_LINK_RATE_1000000 ?
+						    ENCODING_OVERHEAD_128b_132b :
+						    ENCODING_OVERHEAD_8b_10b;
+			available_bandwidth = link_rates[i] * lanes * overhead * 10;
+			if (available_bandwidth < required_bandwidth) {
+				igt_info("Lowest link configuration for %s: Link Rate = %"PRIu64" Kbps, Lanes = %d\n", output->name, link_rates[i], lanes);
+				*min_link_rate = link_rates[i];
+				*min_lane_count = lanes;
+				return;
+			}
+		}
+	}
+}
+
+static const char *str_lane_count(enum dp_lane_count lane_count)
+{
+	switch (lane_count) {
+	case DP_LANE_COUNT_1:
+		return "1";
+	case DP_LANE_COUNT_2:
+		return "2";
+	case DP_LANE_COUNT_4:
+		return "4";
+	default:
+		igt_assert_f(0, "Invalid lane count %d\n", lane_count);
+	}
+}
+
+static bool is_retrain_disabled(data_t *data)
+{
+	struct dp_link_training_info info;
+
+	igt_read_link_training_info(data->drm_fd, data->output, &info);
+	return info.retrain_disabled;
+}
+
+static void test_fallback(data_t *data)
+{
+	bool first = true;
+	uint64_t min_link_rate;
+	int min_lane_count;
+
+	igt_sort_connector_modes(data->output->config.connector, sort_drm_modes_by_res_asc);
+	find_min_dp_config(data->drm_fd, data->output->config.connector->modes[0], data->output,
+			   &min_link_rate, &min_lane_count);
+
+	while (!is_retrain_disabled(data)) {
+		data->mode = &data->output->config.connector->modes[0];
+		igt_info("mode: %dx%d@%d\n", data->mode->hdisplay, data->mode->vdisplay, data->mode->vrefresh);
+		igt_create_pattern_fb(data->drm_fd, data->mode->hdisplay, data->mode->vdisplay, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR, &data->fb);
+		igt_output_set_pipe(data->output, data->pipe);
+		data->primary = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY);
+		igt_plane_set_fb(data->primary, &data->fb);
+		igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+		igt_info("Current link rate : %s, lane count : %s\n",
+		       str_link_rate(igt_get_dp_link_rate_set_for_output(data->drm_fd, data->output)),
+		       str_lane_count(igt_get_dp_lane_count_set_for_output(data->drm_fd, data->output)));
+		if ((igt_get_dp_link_rate_set_for_output(data->drm_fd, data->output) == min_link_rate) &&
+		   (igt_get_dp_lane_count_set_for_output(data->drm_fd, data->output) == min_lane_count))
+			break;
+		kmstest_force_connector_link_training_failure(data->drm_fd, data->output->config.connector, 2);
+		kmstest_force_connector_retrain(data->drm_fd, data->output->config.connector, 1);
+
+		if (!first) {
+			igt_display_reset(&data->display);
+			igt_display_commit2(&data->display, COMMIT_ATOMIC);
+		}
+		first = false;
+	}
+}
+
+igt_main
+{
+	data_t data = {};
+	igt_output_t *output;
+	enum pipe pipe;
+	enum dp_link_rate link_rate;
+	enum dp_lane_count lane_count;
+
+	igt_fixture {
+		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+		igt_display_require(&data.display, data.drm_fd);
+	}
+
+	igt_describe_f("Test fallback");
+	igt_subtest_with_dynamic_f("fallback")
+	{
+		for_each_connected_output(&data.display, output) {
+			if (!igt_has_force_link_training_failure_debugfs(data.drm_fd, output)) {
+				igt_info("Skipping output %s as doesn't support fallback\n",
+					 output->name);
+				continue;
+			}
+
+			data.output = output;
+			link_rate = igt_get_dp_max_link_rate(data.drm_fd, data.output);
+			lane_count = igt_get_dp_max_lane_count(data.drm_fd, data.output);
+
+			for_each_pipe(&data.display, pipe) {
+				igt_display_reset(&data.display);
+				data.pipe = pipe;
+				igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
+					test_fallback(&data);
+				kmstest_force_connector_link_rate(data.drm_fd, data.output->config.connector, link_rate);
+				kmstest_force_connector_lane_count(data.drm_fd, data.output->config.connector, lane_count);
+				igt_reset_connectors();
+			}
+		}
+	}
+
+	igt_fixture {
+		igt_reset_connectors();
+		igt_display_fini(&data.display);
+		drm_close_driver(data.drm_fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 758ae090c..1a4e6c18b 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -251,6 +251,7 @@ intel_kms_progs = [
 	'kms_ccs',
 	'kms_cdclk',
 	'kms_dirtyfb',
+	'kms_dp_fallback',
 	'kms_draw_crc',
 	'kms_dsc',
 	'kms_fb_coherency',
-- 
2.43.0



More information about the igt-dev mailing list