[igt-dev] [PATCH i-g-t 3/3] tests/kms_chamelium: add a link-status test
Manasi Navare
manasi.d.navare at intel.com
Tue Aug 13 18:44:19 UTC 2019
This is a really good link training algorithm test using Chamellium so that now
it will get tested without DPR 120 and for every CI run.
Thanks Simon for writing this one. Great work!
Reviewed-by: Manasi Navare <manasi.d.navare at intel.com>
Regards
Manasi
On Tue, Aug 13, 2019 at 05:17:48PM +0300, Simon Ser wrote:
> This test first checks that on normal hotplug, the link-status property is set
> to GOOD. It then triggers a link failure, checks that the property is updated
> to BAD. Checks are performed to make sure the new mode list is a subset of the
> previous one. After that, a new modeset is performed if necessary and the
> link-status property is set back to GOOD.
>
> This whole dance is repeated until we reach fallback modes.
>
> Signed-off-by: Simon Ser <simon.ser at intel.com>
> ---
> tests/kms_chamelium.c | 142 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 142 insertions(+)
>
> diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
> index b7d30a2d0f55..bef4d6d3bbd8 100644
> --- a/tests/kms_chamelium.c
> +++ b/tests/kms_chamelium.c
> @@ -539,6 +539,145 @@ enable_output(data_t *data,
> drmModeFreeConnector(connector);
> }
>
> +static bool find_mode(const drmModeModeInfo *list, size_t list_len,
> + const drmModeModeInfo *mode)
> +{
> + size_t i;
> +
> + for (i = 0; i < list_len; i++) {
> + if (memcmp(&list[i], mode, sizeof(*mode)) == 0) {
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> +static void check_modes_subset(const drmModeModeInfo *prev, size_t prev_len,
> + const drmModeModeInfo *cur, size_t cur_len)
> +{
> + size_t i;
> +
> + for (i = 0; i < cur_len; i++) {
> + igt_assert_f(find_mode(prev, prev_len, &cur[i]),
> + "Got new mode %s after link status failure\n",
> + cur[i].name);
> + }
> +
> + igt_assert(cur_len <= prev_len); /* safety net */
> + igt_debug("New mode list contains %zu less modes\n",
> + prev_len - cur_len);
> +}
> +
> +static bool are_fallback_modes(const drmModeModeInfo *modes, size_t modes_len)
> +{
> + igt_assert(modes_len > 0);
> +
> + return modes[0].hdisplay <= 1024 && modes[0].vdisplay <= 768;
> +}
> +
> +static void
> +test_link_status(data_t *data, struct chamelium_port *port)
> +{
> + drmModeConnector *connector;
> + igt_output_t *output;
> + igt_plane_t *primary;
> + drmModeModeInfo *prev_modes;
> + size_t prev_modes_len;
> + drmModeModeInfo mode = {0};
> + uint32_t link_status_id;
> + uint64_t link_status;
> + bool has_prop;
> + unsigned int fb_id = 0;
> + struct igt_fb fb;
> + struct udev_monitor *mon;
> +
> + igt_require(chamelium_supports_trigger_link_failure(data->chamelium));
> +
> + reset_state(data, port);
> +
> + output = prepare_output(data, port, TEST_EDID_BASE);
> + connector = chamelium_port_get_connector(data->chamelium, port, false);
> + primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
> + igt_assert(primary);
> +
> + has_prop = kmstest_get_property(data->drm_fd, connector->connector_id,
> + DRM_MODE_OBJECT_CONNECTOR,
> + "link-status", &link_status_id,
> + &link_status, NULL);
> + igt_require(has_prop);
> + igt_assert_f(link_status == DRM_MODE_LINK_STATUS_GOOD,
> + "Expected link status to be %d initially, got %"PRIu64"\n",
> + DRM_MODE_LINK_STATUS_GOOD, link_status);
> +
> + igt_debug("Connector has %d modes\n", connector->count_modes);
> + prev_modes_len = connector->count_modes;
> + prev_modes = malloc(prev_modes_len * sizeof(drmModeModeInfo));
> + memcpy(prev_modes, connector->modes,
> + prev_modes_len * sizeof(drmModeModeInfo));
> +
> + mon = igt_watch_hotplug();
> +
> + while (1) {
> + if (link_status == DRM_MODE_LINK_STATUS_BAD) {
> + igt_output_set_prop_value(output,
> + IGT_CONNECTOR_LINK_STATUS,
> + DRM_MODE_LINK_STATUS_GOOD);
> + }
> +
> + if (memcmp(&connector->modes[0], &mode, sizeof(mode)) != 0) {
> + igt_assert(connector->count_modes > 0);
> + mode = connector->modes[0];
> + igt_debug("Modesetting with %s\n", mode.name);
> + if (fb_id > 0)
> + igt_remove_fb(data->drm_fd, &fb);
> + fb_id = igt_create_color_pattern_fb(data->drm_fd,
> + mode.hdisplay,
> + mode.vdisplay,
> + DRM_FORMAT_XRGB8888,
> + LOCAL_DRM_FORMAT_MOD_NONE,
> + 0, 0, 0, &fb);
> + igt_assert(fb_id > 0);
> + enable_output(data, port, output, &mode, &fb);
> + } else {
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> + }
> +
> + igt_debug("Triggering link failure\n");
> + chamelium_trigger_link_failure(data->chamelium, port);
> +
> + igt_assert(igt_hotplug_detected(mon, HOTPLUG_TIMEOUT));
> + igt_assert_eq(reprobe_connector(data, port),
> + DRM_MODE_CONNECTED);
> +
> + igt_flush_hotplugs(mon);
> +
> + drmModeFreeConnector(connector);
> + connector = chamelium_port_get_connector(data->chamelium, port,
> + false);
> + link_status = igt_output_get_prop(output, IGT_CONNECTOR_LINK_STATUS);
> + igt_assert_f(link_status == DRM_MODE_LINK_STATUS_BAD,
> + "Expected link status to be %d after link failure, "
> + "got %"PRIu64"\n",
> + DRM_MODE_LINK_STATUS_BAD, link_status);
> + check_modes_subset(prev_modes, prev_modes_len,
> + connector->modes, connector->count_modes);
> + prev_modes_len = connector->count_modes;
> + memcpy(prev_modes, connector->modes,
> + connector->count_modes * sizeof(drmModeModeInfo));
> +
> + if (are_fallback_modes(connector->modes, connector->count_modes)) {
> + igt_debug("Reached fallback modes\n");
> + break;
> + }
> + }
> +
> + igt_cleanup_hotplug(mon);
> + igt_remove_fb(data->drm_fd, &fb);
> + free(prev_modes);
> + drmModeFreeConnector(connector);
> +}
> +
> static void chamelium_paint_xr24_pattern(uint32_t *data,
> size_t width, size_t height,
> size_t stride, size_t block_size)
> @@ -2234,6 +2373,9 @@ igt_main
> test_hpd_storm_disable(&data, port,
> HPD_STORM_PULSE_INTERVAL_DP);
>
> + connector_subtest("dp-link-status", DisplayPort)
> + test_link_status(&data, port);
> +
> connector_subtest("dp-edid-change-during-suspend", DisplayPort)
> test_suspend_resume_edid_change(&data, port,
> SUSPEND_STATE_MEM,
> --
> 2.22.0
>
More information about the igt-dev
mailing list