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

Reddy Guddati, Santhosh santhosh.reddy.guddati at intel.com
Tue Aug 20 03:23:42 UTC 2024


Hi Kunal,

Can we use macros something like below to make code readable ?

#define STR_LINK_RATE(link_rate) \
	(link_rate == DP_LINK_RATE_162000 ? "1.62 Gbps" : \
	link_rate == DP_LINK_RATE_216000 ? "2.16 Gbps" : \
	link_rate == DP_LINK_RATE_243000 ? "2.43 Gbps" : \
	link_rate == DP_LINK_RATE_270000 ? "2.70 Gbps" : \
	link_rate == DP_LINK_RATE_324000 ? "3.24 Gbps" : \
	link_rate == DP_LINK_RATE_432000 ? "4.32 Gbps" : \
	link_rate == DP_LINK_RATE_540000 ? "5.40 Gbps" : \
	link_rate == DP_LINK_RATE_675000 ? "6.75 Gbps" : \
	link_rate == DP_LINK_RATE_810000 ? "8.10 Gbps" : \
	link_rate == DP_LINK_RATE_1000000 ? "10.00 Gbps" : \
	link_rate == DP_LINK_RATE_1350000 ? "13.50 Gbps" : \
	link_rate == DP_LINK_RATE_2000000 ? "20.00 Gbps" : \
	(igt_assert_f(0, "Invalid link rate %d\n", link_rate), NULL))

#define STR_LINK_TO_WRITE(link_rate) \
	(link_rate == DP_LINK_RATE_162000 ? "162000" : \
	link_rate == DP_LINK_RATE_216000 ? "216000" : \
	link_rate == DP_LINK_RATE_243000 ? "243000" : \
	link_rate == DP_LINK_RATE_270000 ? "270000" : \
	link_rate == DP_LINK_RATE_324000 ? "324000" : \
	link_rate == DP_LINK_RATE_432000 ? "432000" : \
	link_rate == DP_LINK_RATE_540000 ? "540000" : \
	link_rate == DP_LINK_RATE_675000 ? "675000" : \
	link_rate == DP_LINK_RATE_810000 ? "810000" : \
	link_rate == DP_LINK_RATE_1000000 ? "1000000" : \
	link_rate == DP_LINK_RATE_1350000 ? "1350000" : \
	link_rate == DP_LINK_RATE_2000000 ? "2000000" : \
	(igt_assert_f(0, "Invalid link rate %d\n", link_rate), NULL))
#define STR_LANE_COUNT(lane_count) \
	(lane_count == DP_LANE_COUNT_1 ? "1" : \
	lane_count == DP_LANE_COUNT_2 ? "2" : \
	lane_count == DP_LANE_COUNT_4 ? "4" : \
	(igt_assert_f(0, "Invalid lane count %d\n", lane_count), NULL))

DP_LINK_RATE link_rate = DP_LINK_RATE_540000;
const char* link_rate_str = STR_LINK_RATE(link_rate);
printf("Link rate: %s\n", link_rate_str);

Thanks,
santhosh

On 10-06-2024 02:55, Kunal Joshi wrote:
> 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',


More information about the igt-dev mailing list