diff options
author | Simon Ser <simon.ser@intel.com> | 2019-08-13 16:29:14 +0300 |
---|---|---|
committer | Simon Ser <simon.ser@intel.com> | 2019-08-15 13:09:38 +0300 |
commit | fbe61f529737191d0920521946a575bd55f00fbe (patch) | |
tree | af641023b28f7cb7d06d3a4328b194fbe72aff0f /tests/kms_chamelium.c | |
parent | 6dc34cd29235068bf51398e375a9f75093f4c67b (diff) |
tests/kms_chamelium: add a link-status test
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@intel.com>
Reviewed-by: Manasi Navare <manasi.d.navare@intel.com>
Diffstat (limited to 'tests/kms_chamelium.c')
-rw-r--r-- | tests/kms_chamelium.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c index 913a4cd8..585478ee 100644 --- a/tests/kms_chamelium.c +++ b/tests/kms_chamelium.c @@ -540,6 +540,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) @@ -2290,6 +2429,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, |