[PATCH i-g-t v2 1/3] tests/kms_joiner: Add tests for Ultrajoiner validation
Reddy Guddati, Santhosh
santhosh.reddy.guddati at intel.com
Tue Sep 17 05:06:06 UTC 2024
nit, IMO guard the array boundaries against overflow, otherwise overall
changes LGTM.
Reviewed-by: Santhosh Reddy Guddati <santhosh.reddy.guddati at intel.com>
On 11-09-2024 12:52, Karthik B S wrote:
> Add a subtest to validate basic ultrajoiner modeset and a negative test
> to validate invalid pipe configs during an ultrajoiner modeset.
>
> Signed-off-by: Karthik B S <karthik.b.s at intel.com>
> ---
> lib/igt_kms.c | 44 +++++
> lib/igt_kms.h | 3 +
> .../intel/{kms_big_joiner.c => kms_joiner.c} | 150 ++++++++++++++++--
> tests/meson.build | 2 +-
> 4 files changed, 183 insertions(+), 16 deletions(-)
> rename tests/intel/{kms_big_joiner.c => kms_joiner.c} (74%)
>
> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> index dd530dbab..cf453dcfc 100644
> --- a/lib/igt_kms.c
> +++ b/lib/igt_kms.c
> @@ -6347,6 +6347,50 @@ bool bigjoiner_mode_found(int drm_fd, drmModeConnector *connector,
> return found;
> }
>
> +/**
> + * igt_ultrajoiner_possible:
> + * @mode: libdrm mode
> + * @max_dotclock: Max pixel clock frequency
> + *
> + * Ultrajoiner will come into the picture, when the requested
> + * mode resolution > 10K or mode clock > 2 * max_dotclock.
> + *
> + * Returns: True if mode requires Ultrajoiner, else False.
> + */
> +bool igt_ultrajoiner_possible(drmModeModeInfo *mode, int max_dotclock)
> +{
> + return (mode->hdisplay > 2 * MAX_HDISPLAY_PER_PIPE ||
> + mode->clock > 2 * max_dotclock);
> +}
> +
> +/**
> + * Ultrajoiner_mode_found:
> + * @drm_fd: drm file descriptor
> + * @connector: libdrm connector
> + * @max_dot_clock: max dot clock frequency
> + * @mode: libdrm mode to be filled
> + *
> + * Ultrajoiner will come in to the picture when the
> + * resolution > 10K or clock > 2 * max-dot-clock.
> + *
> + * Returns: True if ultra joiner found in connector modes
> + */
> +bool ultrajoiner_mode_found(int drm_fd, drmModeConnector *connector,
> + int max_dotclock, drmModeModeInfo *mode)
> +{
> + bool found = false;
> +
> + igt_sort_connector_modes(connector, sort_drm_modes_by_res_dsc);
> + found = igt_ultrajoiner_possible(&connector->modes[0], max_dotclock);
> + if (!found) {
> + igt_sort_connector_modes(connector, sort_drm_modes_by_clk_dsc);
> + found = igt_ultrajoiner_possible(&connector->modes[0], max_dotclock);
> + }
> + if (found)
> + *mode = connector->modes[0];
> + return found;
> +}
> +
> /**
> * igt_has_force_joiner_debugfs
> * @drmfd: A drm file descriptor
> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> index 25ba50916..4455632f4 100644
> --- a/lib/igt_kms.h
> +++ b/lib/igt_kms.h
> @@ -1216,6 +1216,9 @@ int igt_get_max_dotclock(int fd);
> bool igt_bigjoiner_possible(drmModeModeInfo *mode, int max_dotclock);
> bool bigjoiner_mode_found(int drm_fd, drmModeConnector *connector,
> int max_dotclock, drmModeModeInfo *mode);
> +bool igt_ultrajoiner_possible(drmModeModeInfo *mode, int max_dotclock);
> +bool ultrajoiner_mode_found(int drm_fd, drmModeConnector *connector,
> + int max_dotclock, drmModeModeInfo *mode);
> bool igt_has_force_joiner_debugfs(int drmfd, char *conn_name);
> bool igt_check_force_joiner_status(int drmfd, char *connector_name);
> bool igt_check_bigjoiner_support(igt_display_t *display);
> diff --git a/tests/intel/kms_big_joiner.c b/tests/intel/kms_joiner.c
> similarity index 74%
> rename from tests/intel/kms_big_joiner.c
> rename to tests/intel/kms_joiner.c
> index 7c370bc60..633bf51c7 100644
> --- a/tests/intel/kms_big_joiner.c
> +++ b/tests/intel/kms_joiner.c
> @@ -37,13 +37,20 @@
> #include "igt.h"
>
> /**
> - * SUBTEST: invalid-modeset
> + * SUBTEST: invalid-modeset-big-joiner
> * Description: Verify if the modeset on the adjoining pipe is rejected when
> * the pipe is active with a big joiner modeset
> *
> - * SUBTEST: basic
> + * SUBTEST: invalid-modeset-ultra-joiner
> + * Description: Verify if the modeset on the other pipes are rejected when
> + * the pipe A is active with ultra joiner modeset
> + *
> + * SUBTEST: basic-big-joiner
> * Description: Verify the basic modeset on big joiner mode on all pipes
> *
> + * SUBTEST: basic-ultra-joiner
> + * Description: Verify the basic modeset on ultra joiner mode on all pipes
> + *
> * SUBTEST: invalid-modeset-force-joiner
> * Description: Verify if modeset on adjacent pipe is declined when force joiner modeset is active.
> * Force joiner applies bigjoiner functionality to non-bigjoiner outputs,
> @@ -54,20 +61,24 @@
> * Force joiner applies bigjoiner functionality to non-bigjoiner outputs thus,
> * the test exclusively targets non-bigjoiner outputs.
> */
> -IGT_TEST_DESCRIPTION("Test big joiner / force joiner");
> +IGT_TEST_DESCRIPTION("Test joiner / force joiner");
>
> #define INVALID_TEST_OUTPUT 2
>
> typedef struct {
> int drm_fd;
> int big_joiner_output_count;
> + int ultra_joiner_output_count;
> int non_big_joiner_output_count;
> + int non_ultra_joiner_output_count;
> int mixed_output_count;
> int output_count;
> int n_pipes;
> uint32_t master_pipes;
> igt_output_t *big_joiner_output[IGT_MAX_PIPES];
> + igt_output_t *ultra_joiner_output[IGT_MAX_PIPES];
> igt_output_t *non_big_joiner_output[IGT_MAX_PIPES];
> + igt_output_t *non_ultra_joiner_output[IGT_MAX_PIPES];
> igt_output_t *mixed_output[IGT_MAX_PIPES];
> enum pipe pipe_seq[IGT_MAX_PIPES];
> igt_display_t display;
> @@ -286,6 +297,81 @@ static void test_joiner_on_last_pipe(data_t *data, bool force_joiner)
> }
> }
>
> +static void test_ultra_joiner(data_t *data, bool invalid_pipe, bool two_display)
> +{
> + int i, j, k, ret;
> + igt_output_t *output, *non_ultra_joiner_output;
> + igt_plane_t *primary;
> + igt_output_t **outputs;
> + igt_fb_t fb;
> + drmModeModeInfo mode;
> +
> + outputs = data->ultra_joiner_output;
> + igt_display_reset(&data->display);
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> + for (i = 0; i < data->ultra_joiner_output_count; i++) {
> + output = outputs[i];
> + igt_require(ultrajoiner_mode_found(data->drm_fd, output->config.connector, max_dotclock, &mode));
> + igt_output_override_mode(output, &mode);
> + for (j = 0; j < data->n_pipes; j++) {
> + /* Ultra joiner is only valid on PIPE_A */
> + if (invalid_pipe && j == PIPE_A)
> + continue;
> + if (!invalid_pipe && j != PIPE_A)
> + continue;
> + if (two_display && j != PIPE_A)
> + continue;
> +
> + igt_output_set_pipe(output, data->pipe_seq[j]);
> +
> + primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
> + igt_create_pattern_fb(data->drm_fd, mode.hdisplay, mode.vdisplay, DRM_FORMAT_XRGB8888,
> + DRM_FORMAT_MOD_LINEAR, &fb);
> + igt_plane_set_fb(primary, &fb);
> +
> + if (invalid_pipe)
> + ret = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
> + else
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> + if (two_display) {
> + for_each_connected_output(&data->display, non_ultra_joiner_output) {
> + if (output->id != non_ultra_joiner_output->id) {
> + for (k = 1; k < data->n_pipes; k++) {
> + igt_plane_t *plane;
> + drmModeModeInfo *mode1;
> +
> + mode1 = igt_output_get_mode(non_ultra_joiner_output);
> +
> + igt_output_set_pipe(non_ultra_joiner_output, data->pipe_seq[k]);
> + plane = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
> +
> + igt_plane_set_fb(plane, &fb);
> + igt_fb_set_size(&fb, plane, mode1->hdisplay, mode1->vdisplay);
> + igt_plane_set_size(plane, mode1->hdisplay, mode1->vdisplay);
> +
> + ret = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
> +
> + igt_plane_set_fb(plane, NULL);
> + igt_assert_f(ret != 0, "Commit expected to fail on second display\n");
> + }
> + /* Validation with one output is sufficient */
> + break;
> + }
> + }
> + }
> +
> + igt_display_reset(&data->display);
> + igt_plane_set_fb(primary, NULL);
> + igt_remove_fb(data->drm_fd, &fb);
> +
> + if (invalid_pipe)
> + igt_assert_f(ret != 0, "Commit shouldn't have passed\n");
> + }
> + }
> +}
> +
> igt_main
> {
> bool force_joiner_supported;
> @@ -297,7 +383,9 @@ igt_main
> igt_fixture {
> force_joiner_supported = false;
> data.big_joiner_output_count = 0;
> + data.ultra_joiner_output_count = 0;
> data.non_big_joiner_output_count = 0;
> + data.non_ultra_joiner_output_count = 0;
> data.mixed_output_count = 0;
> data.output_count = 0;
> j = 0;
> @@ -310,24 +398,31 @@ igt_main
> max_dotclock = igt_get_max_dotclock(data.drm_fd);
>
> for_each_connected_output(&data.display, output) {
> - bool found = false;
> + bool ultrajoiner_found = false, bigjoiner_found = false;
> drmModeConnector *connector = output->config.connector;
>
> /*
> * Bigjoiner will come in to the picture when the
> * resolution > 5K or clock > max-dot-clock.
> + * Ultrajoiner will come in to the picture when the
> + * resolution > 10K or clock > 2 * max-dot-clock.
> */
> - found = bigjoiner_mode_found(data.drm_fd, connector, max_dotclock, &mode);
> + bigjoiner_found = bigjoiner_mode_found(data.drm_fd, connector, max_dotclock, &mode);
> + ultrajoiner_found = ultrajoiner_mode_found(data.drm_fd, connector, max_dotclock, &mode);
>
> - if (found) {
> + if (igt_has_force_joiner_debugfs(data.drm_fd, output->name))
> + force_joiner_supported = true;
> +
> + if (ultrajoiner_found)
> + data.ultra_joiner_output[data.ultra_joiner_output_count++] = output;
> + else if (force_joiner_supported)
> + data.non_ultra_joiner_output[data.non_ultra_joiner_output_count++] = output;
>> nit, IMO guard the array boundaries against overflow, otherwise
overall changes LGTM.
if (ultrajoiner_found && data.ultra_joiner_output_count < IGT_MAX_PIPES)
data.ultra_joiner_output[data.ultra_joiner_output_count++] = output;
else if (force_joiner_supported && data.non_ultra_joiner_output_count
< IGT_MAX_PIPES)
data.non_ultra_joiner_output[data.non_ultra_joiner_output_count++] =
output;
> +
> + if (bigjoiner_found)
> data.big_joiner_output[data.big_joiner_output_count++] = output;
> - igt_output_override_mode(output, &mode);
> - } else {
> - if (igt_has_force_joiner_debugfs(data.drm_fd, output->name)) {
> - force_joiner_supported = true;
> - data.non_big_joiner_output[data.non_big_joiner_output_count++] = output;
> - }
> - }
> + else if (force_joiner_supported)
> + data.non_big_joiner_output[data.non_big_joiner_output_count++] = output;
> +
> data.output_count++;
> }
> if (data.big_joiner_output_count == 1 && data.non_big_joiner_output_count >= 1) {
> @@ -337,6 +432,7 @@ igt_main
> data.mixed_output[data.mixed_output_count++] = data.big_joiner_output[0];
> data.mixed_output[data.mixed_output_count++] = data.non_big_joiner_output[0];
> }
> +
> data.n_pipes = 0;
> for_each_pipe(&data.display, i) {
> data.n_pipes++;
> @@ -346,7 +442,7 @@ igt_main
> }
>
> igt_describe("Verify the basic modeset on big joiner mode on all pipes");
> - igt_subtest_with_dynamic("basic") {
> + igt_subtest_with_dynamic("basic-big-joiner") {
> igt_require_f(data.big_joiner_output_count > 0,
> "No bigjoiner output found\n");
> igt_require_f(data.n_pipes > 1,
> @@ -358,9 +454,19 @@ igt_main
> test_multi_joiner(&data, data.big_joiner_output_count, false);
> }
>
> + igt_describe("Verify the basic modeset on ultra joiner mode on all pipes");
> + igt_subtest_with_dynamic("basic-ultra-joiner") {
> + igt_require_f(data.ultra_joiner_output_count > 0,
> + "No ultrajoiner output found\n");
> + igt_require_f(data.n_pipes > 3,
> + "Minimum 4 pipes required\n");
> + igt_dynamic_f("single-joiner")
> + test_ultra_joiner(&data, false, false);
> + }
> +
> igt_describe("Verify if the modeset on the adjoining pipe is rejected "
> "when the pipe is active with a big joiner modeset");
> - igt_subtest_with_dynamic("invalid-modeset") {
> + igt_subtest_with_dynamic("invalid-modeset-big-joiner") {
> igt_require_f(data.big_joiner_output_count > 0, "Non big joiner output not found\n");
> igt_require_f(data.n_pipes > 1, "Minimum of 2 pipes are required\n");
> if (data.big_joiner_output_count >= 1)
> @@ -374,6 +480,20 @@ igt_main
> test_invalid_modeset_two_joiner(&data, true, false);
> }
>
> + igt_describe("Verify if the modeset on the other pipes are rejected "
> + "when the pipe A is active with a ultra joiner modeset");
> + igt_subtest_with_dynamic("invalid-modeset-ultra-joiner") {
> + igt_require_f(data.ultra_joiner_output_count > 0, "Ultra joiner output not found\n");
> + igt_require_f(data.n_pipes > 3, "Minimum of 4 pipes are required\n");
> +
> + igt_dynamic_f("ultra_joiner_on_invalid_pipe")
> + test_ultra_joiner(&data, true, false);
> + if (data.non_ultra_joiner_output_count > 0) {
> + igt_dynamic_f("2x")
> + test_ultra_joiner(&data, false, true);
> + }
> + }
> +
> igt_describe("Verify the basic modeset on big joiner mode on all pipes");
> igt_subtest_with_dynamic("basic-force-joiner") {
> igt_require_f(force_joiner_supported,
> diff --git a/tests/meson.build b/tests/meson.build
> index 00556c9d6..c8cba1b9a 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -242,7 +242,6 @@ intel_i915_progs = [
>
> intel_kms_progs = [
> 'kms_big_fb',
> - 'kms_big_joiner' ,
> 'kms_busy',
> 'kms_ccs',
> 'kms_cdclk',
> @@ -255,6 +254,7 @@ intel_kms_progs = [
> 'kms_flip_scaled_crc',
> 'kms_flip_tiling',
> 'kms_frontbuffer_tracking',
> + 'kms_joiner',
> 'kms_legacy_colorkey',
> 'kms_mmap_write_crc',
> 'kms_pipe_b_c_ivb',
More information about the igt-dev
mailing list