[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