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
next prev parent reply other threads:[~2026-07-06 7:53 UTC|newest]
Thread overview: 79+ 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-07 4:06 ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 04/34] drm/i915/dp_link_caps: Add link configuration iterator Imre Deak
2026-07-07 4:17 ` Kandpal, Suraj
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-07 5:13 ` Kandpal, Suraj
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-07 6:49 ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 22/34] drm/i915/dp: Remove min/max link config limits Imre Deak
2026-07-07 9:32 ` Luca Coelho
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-07 9:55 ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 24/34] drm/i915/dp_link_training: Use config iterator for fallback Imre Deak
2026-07-07 9:58 ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 25/34] drm/i915/dp_link_training: Disable failed config during fallback Imre Deak
2026-07-07 10:01 ` Luca Coelho
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-02 1:54 ` ✓ i915.CI.BAT: success for drm/i915/dp_link: Unify modeset/fallback config selection Patchwork
2026-07-02 19:43 ` ✓ i915.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