Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Imre Deak <imre.deak@intel.com>
To: "Michał Grzelak" <michal.grzelak@intel.com>
Cc: <intel-gfx@lists.freedesktop.org>, <intel-xe@lists.freedesktop.org>
Subject: Re: [PATCH v2 33/34] drm/i915/kunit: DP link: add update config tests
Date: Mon, 6 Jul 2026 10:46:00 +0300	[thread overview]
Message-ID: <aktdOMmoEAL2UGFI@ideak-desk.lan> (raw)
In-Reply-To: <54004525-f3cc-614c-5edf-db3259137594@intel.com>

On Sat, Jul 04, 2026 at 12:51:20PM +0200, Michał Grzelak wrote:
> On Wed, 1 Jul 2026, Imre Deak wrote:
> > Add KUnit tests for link_caps updates shrinking or expanding the
> > supported rates and lane counts.
> > 
> > The tests also cover updates with disabled configurations, including
> > random shrink and expand sequences, to verify that disabled state,
> > allowed configurations, ordering, and max limits stay consistent across
> > updates.
> > 
> > v2: Remove test cases for the now unused merge update mode.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> > .../i915/display/tests/intel_dp_link_test.c   | 780 ++++++++++++++++++
> > 1 file changed, 780 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c b/drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c
> > index 1dc5bf6888990..43283245ad037 100644
> > --- a/drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c
> > +++ b/drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c
> > @@ -61,12 +61,29 @@ struct link_config_set {
> > 	int size;
> > };
> > 
> > +struct test_config_table {
> > +	struct kunit *test;
> > +
> > +	struct link_rate_set rates;
> > +	int max_lane_count;
> > +	struct link_config_set disabled_configs;
> > +};
> > +
> > static const int standard_dp_link_rates[] = {
> > 	162000, 270000, 540000, 810000, 1000000, 1350000, 2000000
> > };
> > 
> > #define LINK_TEST_NUM_STANDARD_RATES (ARRAY_SIZE(standard_dp_link_rates))
> > 
> > +#define INIT_STANDARD_TABLE(__test, __num_rates, __max_lane_count) { \
> > +	.test = (__test), \
> > +	.rates = { \
> > +		.entries = standard_dp_link_rates, \
> > +		.size = (__num_rates), \
> > +	}, \
> > +	.max_lane_count = (__max_lane_count), \
> > +}
> > +
> > static const struct link_config_set standard_dp_link_configs[] = {
> > 	[INTEL_DP_LINK_CAPS_ORDER_KEY_BW] = {                        /* MBps    PBN    */
> > 		.entries = {
> > @@ -159,12 +176,56 @@ static const struct link_config_set standard_dp_link_configs[] = {
> > 	},
> > };
> > 
> > +static int lookup_rate(const struct link_rate_set *rate_set, int rate)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < rate_set->size; i++)
> > +		if (rate_set->entries[i] == rate)
> > +			return i;
> > +
> > +	return -1;
> > +}
> > +
> > +static bool has_rate(const struct link_rate_set *rate_set, int rate)
> > +{
> > +	return lookup_rate(rate_set, rate) >= 0;
> > +}
> > +
> > static bool link_configs_match(const struct intel_dp_link_config *a,
> > 			       const struct intel_dp_link_config *b)
> > {
> > 	return a->rate == b->rate && a->lane_count == b->lane_count;
> > }
> > 
> > +static int lookup_config(const struct link_config_set *config_set,
> > +			 const struct intel_dp_link_config *config)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < config_set->size; i++)
> > +		if (link_configs_match(&config_set->entries[i], config))
> > +			return i;
> > +
> > +	return -1;
> > +}
> > +
> > +static bool has_config(const struct link_config_set *config_set,
> > +		       const struct intel_dp_link_config *config)
> > +{
> > +	return lookup_config(config_set, config) >= 0;
> > +}
> > +
> > +static void add_config(struct kunit *test,
> > +		       struct link_config_set *config_set,
> > +		       const struct intel_dp_link_config *config)
> > +{
> > +	KUNIT_ASSERT_LT(test, config_set->size, ARRAY_SIZE(config_set->entries));
> > +
> > +	config_set->entries[config_set->size] = *config;
> > +	config_set->size++;
> > +}
> > +
> > static const struct intel_dp_link_caps_order config_orders[] = {
> > 	{
> > 		.key = INTEL_DP_LINK_CAPS_ORDER_KEY_BW,
> > @@ -236,9 +297,728 @@ static void intel_dp_link_caps_test_baseline(struct kunit *test)
> > 		baseline_test_for_order(test, link_caps, config_orders[i]);
> > }
> > 
> > +static int get_num_configs(int num_rates, int max_lane_count)
> > +{
> > +	return num_rates * LINK_TEST_NUM_LANE_CONFIGS(max_lane_count);
> > +}
> > +
> > +static int rand_in_range(struct test_ctx *ctx, int min, int max)
> > +{
> > +	return min + (prandom_u32_state(&ctx->rnd) % (max - min + 1));
> > +}
> > +
> > +/*
> > + * TEST: Update reset
> > + * ------------------
> 
> Same comment as in PATCH 32/34.

To me the text below describes this test group sufficiently, similarly
to the other test group below.

> > + * Verify that resetting link_caps with the DP standard rates/lane
> > + * counts updates the configuration table accordingly for all
> > + * combinations.
> > + */
> > +static void verify_bw_asc_config_order(struct kunit *test,
> > +				       const struct intel_dp_link_config *last_config,
> > +				       const struct intel_dp_link_config *config)
> > +{
> > +	int config_bw = drm_dp_max_dprx_data_rate(config->rate,
> > +						  config->lane_count);
> > +	int last_config_bw = drm_dp_max_dprx_data_rate(last_config->rate,
> > +							  last_config->lane_count);
> > +
> > +	KUNIT_EXPECT_GE(test, config_bw, last_config_bw);
> > +	if (config_bw == last_config_bw)
> > +		KUNIT_EXPECT_GT(test, config->rate, last_config->rate);
> > +}
> > +
> > +static void verify_bw_desc_config_order(struct kunit *test,
> > +					const struct intel_dp_link_config *last_config,
> > +					const struct intel_dp_link_config *config)
> > +{
> > +	int config_bw = drm_dp_max_dprx_data_rate(config->rate,
> > +						  config->lane_count);
> > +	int last_config_bw = drm_dp_max_dprx_data_rate(last_config->rate,
> > +							  last_config->lane_count);
> > +
> > +	KUNIT_EXPECT_LE(test, config_bw, last_config_bw);
> > +	if (config_bw == last_config_bw)
> > +		KUNIT_EXPECT_LT(test, config->rate, last_config->rate);
> > +}
> > +
> > +static void verify_rate_lane_asc_config_order(struct kunit *test,
> > +					      const struct intel_dp_link_config *last_config,
> > +					      const struct intel_dp_link_config *config)
> > +{
> > +	KUNIT_EXPECT_GE(test, config->rate, last_config->rate);
> > +	if (config->rate == last_config->rate)
> > +		KUNIT_EXPECT_GT(test, config->lane_count, last_config->lane_count);
> > +}
> > +
> > +static void verify_rate_lane_desc_config_order(struct kunit *test,
> > +					       const struct intel_dp_link_config *last_config,
> > +					       const struct intel_dp_link_config *config)
> > +{
> > +	KUNIT_EXPECT_LE(test, config->rate, last_config->rate);
> > +	if (config->rate == last_config->rate)
> > +		KUNIT_EXPECT_LT(test, config->lane_count, last_config->lane_count);
> > +}
> > +
> > +static void verify_config_order(struct kunit *test,
> > +				struct intel_dp_link_caps_order config_order,
> > +				const struct intel_dp_link_config *last_config,
> > +				const struct intel_dp_link_config *config)
> > +{
> > +	switch (config_order.key) {
> > +	case INTEL_DP_LINK_CAPS_ORDER_KEY_BW:
> > +		if (config_order.dir == INTEL_DP_LINK_CAPS_ORDER_DIR_ASC)
> > +			verify_bw_asc_config_order(test, last_config, config);
> > +		else
> > +			verify_bw_desc_config_order(test, last_config, config);
> > +		break;
> > +	case INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE:
> > +		if (config_order.dir == INTEL_DP_LINK_CAPS_ORDER_DIR_ASC)
> > +			verify_rate_lane_asc_config_order(test, last_config, config);
> > +		else
> > +			verify_rate_lane_desc_config_order(test, last_config, config);
> > +		break;
> > +	default:
> > +		KUNIT_FAIL_AND_ABORT(test, "Missing order key: %d", config_order.key);
> > +	}
> > +}
> > +
> > +static int expected_num_configs(const struct test_config_table *expected_table,
> > +				const struct intel_dp_link_config *max_limits)
> > +{
> > +	int num_configs = 0;
> > +	int lane_count;
> > +	int rate_idx;
> > +
> > +	for (rate_idx = 0; rate_idx < expected_table->rates.size; rate_idx++) {
> > +		for (lane_count = 1; lane_count <= expected_table->max_lane_count; lane_count <<= 1) {
> > +			struct intel_dp_link_config config = {
> > +				.rate = expected_table->rates.entries[rate_idx],
> > +				.lane_count = lane_count,
> > +			};
> > +
> > +			if (config.rate > max_limits->rate ||
> > +			    config.lane_count > max_limits->lane_count)
> > +				continue;
> > +
> > +			if (has_config(&expected_table->disabled_configs, &config))
> > +				continue;
> > +
> > +			num_configs++;
> > +		}
> > +	}
> > +
> > +	return num_configs;
> > +}
> > +
> > +static void
> > +verify_link_caps_for_order(const struct test_config_table *expected_table,
> > +			   struct intel_dp_link_caps *link_caps,
> > +			   struct intel_dp_link_caps_order config_order,
> > +			   const struct intel_dp_link_config *max_limits)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct test_ctx *ctx = test->priv;
> > +	const struct intel_dp_link_caps_test_ops *ops =
> > +		ctx->link_caps_ops;
> > +	struct intel_dp_link_config expected_max_bw_config = {};
> > +	struct intel_dp_link_config actual_max_bw_config;
> > +	struct intel_dp_link_config last_config = {};
> > +	struct intel_dp_link_config old_max_limits;
> > +	struct intel_dp_link_config iter_config;
> > +	struct intel_dp_link_caps_iter iter;
> > +	int num_actual_configs = 0;
> > +	int max_bw = 0;
> > +
> > +	ops->get_max_limits(link_caps, &old_max_limits);
> > +	ops->set_max_limits(link_caps, max_limits);
> > +
> > +	ops->iter_start(&iter, link_caps, config_order, INTEL_DP_LINK_CAPS_FILTER_ALL);
> > +	for_each_dp_link_config(&iter, &iter_config) {
> > +		int bw;
> > +
> > +		KUNIT_EXPECT_LE(test, iter_config.rate, max_limits->rate);
> > +		KUNIT_EXPECT_LE(test, iter_config.lane_count, max_limits->lane_count);
> > +
> > +		num_actual_configs++;
> > +
> > +		/*
> > +		 * Verify the config's rate/lane-count values and its ordering relative
> > +		 * to the previous config.
> > +		 */
> > +		if (last_config.rate)
> > +			verify_config_order(test, config_order, &last_config, &iter_config);
> > +		last_config = iter_config;
> > +
> > +		KUNIT_EXPECT_TRUE(test, has_rate(&expected_table->rates,
> > +						 iter_config.rate));
> > +		KUNIT_EXPECT_LE(test, iter_config.lane_count,
> > +				      expected_table->max_lane_count);
> > +		KUNIT_EXPECT_TRUE(test, is_power_of_2(iter_config.lane_count));
> > +
> > +		/* Verify the config's disabled state */
> > +		KUNIT_EXPECT_FALSE(test, has_config(&expected_table->disabled_configs,
> > +						    &iter_config));
> > +
> > +		/*
> > +		 * Update the max limits for allowed configs, verified at the
> > +		 * end for the whole config table.
> > +		 */
> > +
> > +		bw = drm_dp_max_dprx_data_rate(iter_config.rate, iter_config.lane_count);
> > +		if (bw > max_bw ||
> > +		    (bw == max_bw && iter_config.rate > expected_max_bw_config.rate)) {
> > +			max_bw = bw;
> > +			expected_max_bw_config = iter_config;
> > +		}
> > +	}
> > +	ops->iter_end(&iter);
> > +
> > +	KUNIT_EXPECT_EQ(test, num_actual_configs, expected_num_configs(expected_table, max_limits));
> > +
> > +	ops->get_max_bw_config(link_caps, &actual_max_bw_config);
> > +	KUNIT_EXPECT_TRUE(test, link_configs_match(&expected_max_bw_config,
> > +						   &actual_max_bw_config));
> > +
> > +	KUNIT_ASSERT_TRUE(test, ops->set_max_limits(link_caps, &old_max_limits));
> > +}
> > +
> > +static bool max_limits_valid(const struct test_config_table *expected_table,
> > +			     const struct intel_dp_link_config *max_limits)
> > +{
> > +	int lane_count;
> > +	int rate_idx;
> > +
> > +	for (rate_idx = 0; rate_idx < expected_table->rates.size; rate_idx++) {
> > +		for (lane_count = 1; lane_count <= expected_table->max_lane_count; lane_count <<= 1) {
> > +			struct intel_dp_link_config config = {
> > +				.rate = expected_table->rates.entries[rate_idx],
> > +				.lane_count = lane_count,
> > +			};
> > +
> > +			if (has_config(&expected_table->disabled_configs, &config))
> > +				continue;
> > +
> > +			if (config.rate <= max_limits->rate &&
> > +			    config.lane_count <= max_limits->lane_count)
> > +				return true;
> > +		}
> > +	}
> > +
> > +	return false;
> > +}
> > +
> > +static void get_max_limits(const struct test_config_table *expected_table,
> > +			   struct intel_dp_link_config *max_limits)
> > +{
> > +	int lane_count;
> > +	int rate_idx;
> > +
> > +	max_limits->rate = 0;
> > +	max_limits->lane_count = 0;
> > +
> > +	for (rate_idx = 0; rate_idx < expected_table->rates.size; rate_idx++) {
> > +		for (lane_count = 1; lane_count <= expected_table->max_lane_count; lane_count <<= 1) {
> > +			struct intel_dp_link_config config = {
> > +				.rate = expected_table->rates.entries[rate_idx],
> > +				.lane_count = lane_count,
> > +			};
> > +
> > +			if (has_config(&expected_table->disabled_configs, &config))
> > +				continue;
> > +
> > +			max_limits->rate = max(max_limits->rate, config.rate);
> > +			max_limits->lane_count = max(max_limits->lane_count, config.lane_count);
> > +		}
> > +	}
> > +}
> > +
> > +static void verify_link_caps(const struct test_config_table *expected_table,
> > +			     struct intel_dp_link_caps *link_caps)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct test_ctx *ctx = test->priv;
> > +	const struct intel_dp_link_caps_test_ops *ops = ctx->link_caps_ops;
> > +	struct intel_dp_link_config max_limits;
> > +	int i;
> > +
> > +	get_max_limits(expected_table, &max_limits);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(config_orders); i++) {
> > +		int lane_count;
> > +		int rate_idx;
> > +
> > +		verify_link_caps_for_order(expected_table, link_caps, config_orders[i], &max_limits);
> > +		/*
> > +		 * Verify iteration after setting the max limits to each
> > +		 * configurations.
> > +		 */
> > +		for (rate_idx = 0; rate_idx < expected_table->rates.size; rate_idx++) {
> > +			for (lane_count = 1; lane_count <= expected_table->max_lane_count; lane_count <<= 1) {
> > +				struct intel_dp_link_config config = {
> > +					.rate = expected_table->rates.entries[rate_idx],
> > +					.lane_count = lane_count,
> > +				};
> > +
> > +				if (!max_limits_valid(expected_table, &config)) {
> > +					/* Verify that invalid max limits are rejected. */
> > +					KUNIT_EXPECT_FALSE(test, ops->set_max_limits(link_caps, &config));
> > +
> > +					continue;
> > +				}
> > +
> > +				verify_link_caps_for_order(expected_table, link_caps, config_orders[i],
> > +							   &config);
> > +			}
> > +		}
> > +	}
> > +}
> > +
> > +static void update_link_caps_and_verify(struct test_config_table *expected_table,
> > +					struct intel_dp_link_caps *link_caps,
> > +					bool reset)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct test_ctx *ctx = test->priv;
> > +	const struct intel_dp_link_caps_test_ops *ops =
> > +		ctx->link_caps_ops;
> > +	bool link_params_changed;
> > +
> > +	link_params_changed = ops->update(link_caps,
> > +					  expected_table->rates.entries,
> > +					  expected_table->rates.size,
> > +					  expected_table->max_lane_count,
> > +					  reset);
> > +	KUNIT_EXPECT_TRUE(test, !reset || link_params_changed);
> > +
> > +	/*
> > +	 * ops->update() re-enables all configurations when called with
> > +	 * reset=true, or changed link parameters.
> > +	 */
> > +	if (link_params_changed)
> > +		expected_table->disabled_configs.size = 0;
> > +
> > +	verify_link_caps(expected_table, link_caps);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_reset(struct kunit *test)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	int max_lane_count;
> > +	int num_rates;
> > +
> > +	for (max_lane_count = 1;
> > +	     max_lane_count <= LINK_TEST_MAX_LANE_COUNT;
> > +	     max_lane_count <<= 1) {
> > +		for (num_rates = 1;
> > +		     num_rates <= LINK_TEST_NUM_STANDARD_RATES;
> > +		     num_rates++) {
> 
> Here we break line after each statement, while in eg. verify_link_caps()
> we kept all of them in one line. Is it possible to unify the style, or
> here we are hitting hard limit on line's length?

It's usual to wrap the for(;;) lines if joining them would make the line
less readable.

> > +			struct test_config_table expected_table =
> > +				INIT_STANDARD_TABLE(test, num_rates,
> > +							     max_lane_count);
> > +
> > +			update_link_caps_and_verify(&expected_table, link_caps, true);
> > +		}
> > +	}
> > +}
> > +
> > +/*
> > + * TEST: Update shrink and expand
> > + * ------------------------------
> 
> Same comment as in PATCH 32/34.
> > + * Verify that removing or adding supported rates/lane counts updates
> > + * the configuration table accordingly.
> > + */
> > +static void disable_configs_and_verify(struct kunit *test,
> > +				       struct intel_dp_link_caps *link_caps,
> > +				       struct test_config_table *expected_table,
> > +				       const struct link_config_set *config_set)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	const struct intel_dp_link_caps_test_ops *ops =
> > +		ctx->link_caps_ops;
> > +	int i;
> > +
> > +	for (i = 0; i < config_set->size; i++) {
> > +		KUNIT_ASSERT_FALSE(test, has_config(&expected_table->disabled_configs,
> > +						    &config_set->entries[i]));
> > +		add_config(test, &expected_table->disabled_configs, &config_set->entries[i]);
> > +
> > +		KUNIT_ASSERT_TRUE(test, ops->disable_config(link_caps, &config_set->entries[i]));
> > +
> > +		verify_link_caps(expected_table, link_caps);
> > +	}
> > +}
> > +
> > +static void disable_configs_for_shrink_and_verify(struct test_config_table *expected_table,
> > +						  struct intel_dp_link_caps *link_caps)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct link_config_set config_set = {};
> > +	struct intel_dp_link_config max_config;
> > +
> > +	/*
> > +	 * When configs shrink disable the config with the
> > +	 * second-highest rate,lane params, so the disabled config
> 
> nit: s/rate,/rate, /
> > +	 * stays around after the configs got shrunk.
> > +	 */
> > +	KUNIT_ASSERT_GE(test, expected_table->rates.size, 2);
> > +	KUNIT_ASSERT_GE(test, expected_table->max_lane_count, 2);
> > +
> > +	max_config.rate = expected_table->rates.entries[expected_table->rates.size - 2];
> > +	max_config.lane_count = expected_table->max_lane_count >> 1;
> > +
> > +	add_config(test, &config_set, &max_config);
> > +	disable_configs_and_verify(test, link_caps, expected_table,
> > +			&config_set);
> > +}
> > +
> > +static void disable_configs_for_expand_and_verify(struct test_config_table *expected_table,
> > +						  struct intel_dp_link_caps *link_caps)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct link_config_set config_set = {};
> > +	struct intel_dp_link_config max_config;
> > +
> > +	KUNIT_ASSERT_GE(test, expected_table->rates.size, 1);
> > +
> > +	max_config.rate = expected_table->rates.entries[expected_table->rates.size - 1];
> > +	max_config.lane_count = expected_table->max_lane_count;
> > +
> > +	add_config(test, &config_set, &max_config);
> > +	disable_configs_and_verify(test, link_caps, expected_table,
> > +				   &config_set);
> > +}
> > +
> > +static void get_nth_rate_lane_config(const struct test_config_table *expected_table, int n,
> > +				     struct intel_dp_link_config *config)
> > +{
> > +	int num_lane_configs = LINK_TEST_NUM_LANE_CONFIGS(expected_table->max_lane_count);
> > +	int rate_idx = n / num_lane_configs;
> > +	int lane_count_exp = n % num_lane_configs;
> > +
> > +	config->rate = expected_table->rates.entries[rate_idx];
> > +	config->lane_count = 1 << lane_count_exp;
> > +}
> > +
> > +static void test_update_rates_shrink(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, LINK_TEST_NUM_STANDARD_RATES,
> > +					  LINK_TEST_MAX_LANE_COUNT);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.rates.size > 1) {
> > +		if (disable_configs)
> > +			disable_configs_for_shrink_and_verify(&expected_table, link_caps);
> > +
> > +		expected_table.rates.size--;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_rates_shrink(struct kunit *test)
> > +{
> > +	test_update_rates_shrink(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_rates_shrink_disable(struct kunit *test)
> > +{
> > +	test_update_rates_shrink(test, true);
> > +}
> > +
> > +static void test_update_rates_expand(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, 1, LINK_TEST_MAX_LANE_COUNT);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.rates.size < LINK_TEST_NUM_STANDARD_RATES) {
> > +		if (disable_configs)
> > +			disable_configs_for_expand_and_verify(&expected_table, link_caps);
> > +
> > +		expected_table.rates.size++;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_rates_expand(struct kunit *test)
> > +{
> > +	test_update_rates_expand(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_rates_expand_disable(struct kunit *test)
> > +{
> > +	test_update_rates_expand(test, true);
> > +}
> > +
> > +static void test_update_lanes_shrink(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, LINK_TEST_NUM_STANDARD_RATES,
> > +					  LINK_TEST_MAX_LANE_COUNT);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.max_lane_count > 1) {
> > +		if (disable_configs)
> > +			disable_configs_for_shrink_and_verify(&expected_table, link_caps);
> > +
> > +		expected_table.max_lane_count >>= 1;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_lanes_shrink(struct kunit *test)
> > +{
> > +	test_update_lanes_shrink(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_lanes_shrink_disable(struct kunit *test)
> > +{
> > +	test_update_lanes_shrink(test, true);
> > +}
> > +
> > +static void test_update_lanes_expand(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, LINK_TEST_NUM_STANDARD_RATES, 1);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.max_lane_count < LINK_TEST_MAX_LANE_COUNT) {
> > +		if (disable_configs)
> > +			disable_configs_for_expand_and_verify(&expected_table, link_caps);
> > +
> > +		expected_table.max_lane_count <<= 1;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_lanes_expand(struct kunit *test)
> > +{
> > +	test_update_lanes_expand(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_lanes_expand_disable(struct kunit *test)
> > +{
> > +	test_update_lanes_expand(test, true);
> > +}
> > +
> > +static void disable_random_configs_and_verify(struct test_config_table *expected_table,
> > +					      struct intel_dp_link_caps *link_caps)
> > +{
> > +	struct kunit *test = expected_table->test;
> > +	struct test_ctx *ctx = test->priv;
> > +	struct link_config_set config_set = {};
> > +	u32 disabled_config_mask;
> > +	int num_configs;
> > +	int i;
> > +
> > +	num_configs = get_num_configs(expected_table->rates.size,
> > +				      expected_table->max_lane_count);
> > +	disabled_config_mask = prandom_u32_state(&ctx->rnd) &
> > +			       GENMASK_U32(num_configs - 1, 0);
> > +
> > +	for (i = 0; i < num_configs; i++) {
> > +		struct intel_dp_link_config config;
> > +
> > +		/* At least one config must remain enabled. */
> > +		if (expected_table->disabled_configs.size +
> > +		    config_set.size + 1 >= num_configs)
> > +			break;
> > +
> > +		if (!(BIT(i) & disabled_config_mask))
> 
> Does it make any sense to do:
> 
> if (!REG_FIELD_GET(disabled_config_mask, BIT(i)))

Not really, the mask above is not a register value. Similarly to all the
masks below.

> > +			continue;
> > +
> > +		get_nth_rate_lane_config(expected_table, i, &config);
> > +		/* Don't disable a config twice. */
> > +		if (has_config(&expected_table->disabled_configs, &config))
> > +			continue;
> > +
> > +		add_config(test, &config_set, &config);
> > +	}
> > +
> > +	disable_configs_and_verify(test, link_caps, expected_table,
> > +				   &config_set);
> > +}
> > +
> > +static void get_params_shrink_step(struct test_ctx *ctx,
> > +				   int num_rates, int max_lane_count,
> > +				   int *rates_step, int *lanes_step)
> > +{
> > +	int shrink_mask;
> > +
> > +	*rates_step = 0;
> > +	*lanes_step = 0;
> > +
> > +	if (num_rates == 1)
> > +		shrink_mask = BIT(0);				/* shrink only lanes */
> > +	else if (max_lane_count == 1)
> > +		shrink_mask = BIT(1);				/* shrink only rates */
> > +	else
> > +		shrink_mask = rand_in_range(ctx,
> > +					    BIT(0),
> > +					    BIT(0) | BIT(1));	/* shrink one or both params */
> > +
> > +	if (shrink_mask & BIT(1))
> 
> here same for REG_FIELD_GET().
> 
> > +		*rates_step = rand_in_range(ctx, 1, num_rates - 1);
> > +
> > +	if (shrink_mask & BIT(0))
> 
> ditto.
> 
> > +		*lanes_step = rand_in_range(ctx, 1, ilog2(max_lane_count));
> > +}
> > +
> > +static void get_params_expand_step(struct test_ctx *ctx,
> > +				   int max_num_rates, int num_rates,
> > +				   int max_supported_lane_count, int max_lane_count,
> > +				   int *rates_step, int *lanes_step)
> > +{
> > +	int expand_mask;
> > +
> > +	*rates_step = 0;
> > +	*lanes_step = 0;
> > +
> > +	if (num_rates == max_num_rates)
> > +		expand_mask = BIT(0);				/* expand only lanes */
> > +	else if (max_lane_count == max_supported_lane_count)
> > +		expand_mask = BIT(1);				/* expand only rates */
> > +	else
> > +		expand_mask = rand_in_range(ctx,
> > +					    BIT(0),
> > +					    BIT(0) | BIT(1));	/* expand one or both params */
> > +
> > +	if (expand_mask & BIT(1))
> 
> ditto.
> 
> > +		*rates_step = rand_in_range(ctx, 1, max_num_rates - num_rates);
> > +
> > +	if (expand_mask & BIT(0))
> 
> ditto.
> 
> > +		*lanes_step = rand_in_range(ctx, 1, ilog2(max_supported_lane_count /
> > +							  max_lane_count));
> > +}
> > +
> > +static void test_update_params_shrink_random(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, LINK_TEST_NUM_STANDARD_RATES,
> > +						   LINK_TEST_MAX_LANE_COUNT);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.rates.size > 1 || expected_table.max_lane_count > 1) {
> > +		int rates_step;
> > +		int lanes_step;
> > +
> > +		if (disable_configs)
> > +			disable_random_configs_and_verify(&expected_table, link_caps);
> > +
> > +		get_params_shrink_step(ctx,
> > +				       expected_table.rates.size,
> > +				       expected_table.max_lane_count,
> > +				       &rates_step, &lanes_step);
> > +
> > +		expected_table.rates.size -= rates_step;
> > +		expected_table.max_lane_count >>= lanes_step;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_params_shrink_random(struct kunit *test)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < LINK_TEST_NUM_RANDOM_ITERATIONS; i++)
> > +		test_update_params_shrink_random(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_params_shrink_disable_random(struct kunit *test)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < LINK_TEST_NUM_RANDOM_ITERATIONS; i++)
> > +		test_update_params_shrink_random(test, true);
> > +}
> > +
> > +static void test_update_params_expand_random(struct kunit *test, bool disable_configs)
> > +{
> > +	struct test_ctx *ctx = test->priv;
> > +	struct intel_dp_link_caps *link_caps = ctx->dev.dig_port.dp.link.caps;
> > +	struct test_config_table expected_table =
> > +		INIT_STANDARD_TABLE(test, 1, 1);
> > +
> > +	update_link_caps_and_verify(&expected_table, link_caps, true);
> > +
> > +	while (expected_table.rates.size < LINK_TEST_NUM_STANDARD_RATES ||
> > +	       expected_table.max_lane_count < LINK_TEST_MAX_LANE_COUNT) {
> > +		int rates_step;
> > +		int lanes_step;
> > +
> > +		if (disable_configs)
> > +			disable_random_configs_and_verify(&expected_table, link_caps);
> > +
> > +		get_params_expand_step(ctx,
> > +				       LINK_TEST_NUM_STANDARD_RATES,
> > +				       expected_table.rates.size,
> > +				       LINK_TEST_MAX_LANE_COUNT,
> > +				       expected_table.max_lane_count,
> > +				       &rates_step, &lanes_step);
> > +
> > +		expected_table.rates.size += rates_step;
> > +		expected_table.max_lane_count <<= lanes_step;
> > +
> > +		update_link_caps_and_verify(&expected_table, link_caps, false);
> > +	}
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_params_expand_random(struct kunit *test)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < LINK_TEST_NUM_RANDOM_ITERATIONS; i++)
> > +		test_update_params_expand_random(test, false);
> > +}
> > +
> > +static void intel_dp_link_caps_test_update_params_expand_disable_random(struct kunit *test)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < LINK_TEST_NUM_RANDOM_ITERATIONS; i++)
> > +		test_update_params_expand_random(test, true);
> > +}
> > +
> > static struct kunit_case intel_dp_link_test_cases[] = {
> > 	KUNIT_CASE(intel_dp_link_caps_test_baseline),
> > 
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_reset),
> > +
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_rates_shrink),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_rates_shrink_disable),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_rates_expand),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_rates_expand_disable),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_lanes_shrink),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_lanes_shrink_disable),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_lanes_expand),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_lanes_expand_disable),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_params_shrink_random),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_params_shrink_disable_random),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_params_expand_random),
> > +	KUNIT_CASE(intel_dp_link_caps_test_update_params_expand_disable_random),
> > +
> 
> not sure if this newline is superfluous.
> 
> With all that addressed:
> 
> Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
> 
> BR,
> Michał
> 
> > 	{}
> > };
> > 
> > -- 
> > 2.49.1

  reply	other threads:[~2026-07-06  7:53 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01 15:31 [PATCH v2 00/34] drm/i915/dp_link: Unify modeset/fallback config selection Imre Deak
2026-07-01 15:31 ` [PATCH v2 01/34] drm/i915/doc: Document DP link capabilities Imre Deak
2026-07-02  5:17   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 02/34] drm/i915/dp_link_caps: Factor out helper to get link config by index Imre Deak
2026-07-03  2:55   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 03/34] drm/i915/dp_link_caps: Add support for link rate, lane count iteration orders Imre Deak
2026-07-01 15:31 ` [PATCH v2 04/34] drm/i915/dp_link_caps: Add link configuration iterator Imre Deak
2026-07-01 15:31 ` [PATCH v2 05/34] drm/i915/dp_link_caps: Add helper to get iteration order for a connector Imre Deak
2026-07-01 15:31 ` [PATCH v2 06/34] drm/i915/dp_link_caps: Validate max link limits Imre Deak
2026-07-06  8:17   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 07/34] drm/i915/dp_link_caps: Add filter for enabled link configurations Imre Deak
2026-07-06  8:08   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 08/34] drm/i915/dp_link_caps: Re-enable link configurations after a link reset Imre Deak
2026-07-06  8:09   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 09/34] drm/i915/dp_link_caps: Re-enable link configurations after sink caps change Imre Deak
2026-07-06  8:14   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 10/34] drm/i915/dp_link_caps: Drop noupdate postfix from max link limit set helpers Imre Deak
2026-07-06  8:16   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 11/34] drm/i915/dp_link_caps: Add debugfs entry showing allowed configurations Imre Deak
2026-07-02 10:35   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 12/34] drm/i915/dp: Add link configuration filter for modeset computation Imre Deak
2026-07-02 11:03   ` Luca Coelho
2026-07-06  7:52     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 13/34] drm/i915/dp_link_caps: Add helper to query max BW link configuration Imre Deak
2026-07-02 11:06   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 14/34] drm/i915/dp: Query max BW config via link_caps during mode validation Imre Deak
2026-07-02 11:22   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 15/34] drm/i915/dp_tunnel: Query max BW config via link_caps for BW computation Imre Deak
2026-07-02 11:23   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 16/34] drm/i915/dp_test: Use link caps for compliance link configs Imre Deak
2026-07-02 16:19   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 17/34] drm/i915/dp: Iterate configurations via link_caps for SST non-DSC Imre Deak
2026-07-06 10:42   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 18/34] drm/i915/dp: Iterate configurations via link_caps for SST DSC Imre Deak
2026-07-06 10:48   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 19/34] drm/i915/dp: Use link caps for eDP DSC config selection Imre Deak
2026-07-06 10:49   ` Luca Coelho
2026-07-06 15:03     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 20/34] drm/i915/dp_mst: Use link caps for non-DSC " Imre Deak
2026-07-06 16:45   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 21/34] drm/i915/dp_mst: Use link caps for MST DSC " Imre Deak
2026-07-01 15:31 ` [PATCH v2 22/34] drm/i915/dp: Remove min/max link config limits Imre Deak
2026-07-01 15:31 ` [PATCH v2 23/34] drm/i915/dp_link_training: Reset the max link limits in the fallback code Imre Deak
2026-07-01 15:31 ` [PATCH v2 24/34] drm/i915/dp_link_training: Use config iterator for fallback Imre Deak
2026-07-01 15:31 ` [PATCH v2 25/34] drm/i915/dp_link_training: Disable failed config during fallback Imre Deak
2026-07-01 15:31 ` [PATCH v2 26/34] drm/i915/kunit: Enable KUnit tests Imre Deak
2026-07-04 10:48   ` Michał Grzelak
2026-07-06  7:07     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 27/34] drm/i915/kunit: Add DP link test stub Imre Deak
2026-07-04 10:48   ` Michał Grzelak
2026-07-01 15:31 ` [PATCH v2 28/34] drm/xe/kunit: Add display test config Imre Deak
2026-07-04 10:49   ` Michał Grzelak
2026-07-01 15:31 ` [PATCH v2 29/34] drm/xe/kunit: Build DP link display tests Imre Deak
2026-07-04 10:49   ` Michał Grzelak
2026-07-06  7:14     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 30/34] drm/i915/kunit: Setup DP link test context Imre Deak
2026-07-04 10:50   ` Michał Grzelak
2026-07-06  7:18     ` Imre Deak
2026-07-01 15:32 ` [PATCH v2 31/34] drm/i915/kunit: Export link training and caps funcs for testing Imre Deak
2026-07-04 10:52   ` Michał Grzelak
2026-07-01 15:32 ` [PATCH v2 32/34] drm/i915/kunit: DP link: add baseline fixed table reference test Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:31     ` Imre Deak
2026-07-01 15:32 ` [PATCH v2 33/34] drm/i915/kunit: DP link: add update config tests Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:46     ` Imre Deak [this message]
2026-07-01 15:32 ` [PATCH v2 34/34] drm/i915/kunit: DP link: add fallback tests Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:51     ` Imre Deak
2026-07-01 16:39 ` ✗ CI.checkpatch: warning for drm/i915/dp_link: Unify modeset/fallback config selection Patchwork
2026-07-01 16:40 ` ✓ CI.KUnit: success " Patchwork
2026-07-01 16:59 ` ✗ CI.checksparse: warning " Patchwork
2026-07-01 17:43 ` ✓ Xe.CI.BAT: success " Patchwork
2026-07-02 12:25 ` ✓ Xe.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=aktdOMmoEAL2UGFI@ideak-desk.lan \
    --to=imre.deak@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=michal.grzelak@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