Commit 5c79c34b authored by Imre Deak's avatar Imre Deak

tests/kms_flip: Check for link reset during TS calibration as well

The timestamp calibration can fail when using certain monitors with a
behavior described in

commit 60e8be7c
Author: Imre Deak <imre.deak@intel.com>
Date:   Mon May 11 22:08:53 2020 +0300

    tests/kms_flip: Retry test in case of a DP/HDMI link reset

As in the above commit, retry the calibration once if a hotplug was
detected during the calibration.

v2:
- Reinit the event->name fields too when retrying after a link reset.
Signed-off-by: Imre Deak's avatarImre Deak <imre.deak@intel.com>
Reviewed-by: Uma Shankar's avatarUma Shankar <uma.shankar@intel.com>
parent bfbf195b
...@@ -1115,7 +1115,7 @@ static void free_test_output(struct test_output *o) ...@@ -1115,7 +1115,7 @@ static void free_test_output(struct test_output *o)
} }
} }
static void calibrate_ts(struct test_output *o, int crtc_idx) static bool calibrate_ts(struct test_output *o, int crtc_idx)
{ {
#define CALIBRATE_TS_STEPS 16 #define CALIBRATE_TS_STEPS 16
drmVBlank wait; drmVBlank wait;
...@@ -1125,6 +1125,7 @@ static void calibrate_ts(struct test_output *o, int crtc_idx) ...@@ -1125,6 +1125,7 @@ static void calibrate_ts(struct test_output *o, int crtc_idx)
double expected; double expected;
double mean; double mean;
double stddev; double stddev;
bool failed = false;
int n; int n;
memset(&wait, 0, sizeof(wait)); memset(&wait, 0, sizeof(wait));
...@@ -1176,7 +1177,18 @@ static void calibrate_ts(struct test_output *o, int crtc_idx) ...@@ -1176,7 +1177,18 @@ static void calibrate_ts(struct test_output *o, int crtc_idx)
igt_assert_eq(errno, EINTR); igt_assert_eq(errno, EINTR);
} }
igt_assert(read(drm_fd, &ev, sizeof(ev)) == sizeof(ev)); igt_assert(read(drm_fd, &ev, sizeof(ev)) == sizeof(ev));
igt_assert_eq(ev.sequence, last_seq + 1);
if (failed)
continue;
if (ev.sequence != last_seq + 1) {
igt_debug("Unexpected frame sequence %d vs. expected %d\n",
ev.sequence, last_seq + 1);
failed = true;
/* Continue to flush all the events queued up */
continue;
}
now = ev.tv_sec; now = ev.tv_sec;
now *= 1000000; now *= 1000000;
...@@ -1188,6 +1200,9 @@ static void calibrate_ts(struct test_output *o, int crtc_idx) ...@@ -1188,6 +1200,9 @@ static void calibrate_ts(struct test_output *o, int crtc_idx)
last_seq = ev.sequence; last_seq = ev.sequence;
} }
if (failed)
return false;
expected = mode_frame_time(o); expected = mode_frame_time(o);
mean = igt_stats_get_mean(&stats); mean = igt_stats_get_mean(&stats);
...@@ -1207,6 +1222,30 @@ static void calibrate_ts(struct test_output *o, int crtc_idx) ...@@ -1207,6 +1222,30 @@ static void calibrate_ts(struct test_output *o, int crtc_idx)
} }
o->vblank_interval = mean; o->vblank_interval = mean;
return true;
}
/*
* Some monitors with odd behavior signal a bad link after waking from a power
* saving state and the subsequent (successful) modeset. This will result in a
* link-retraining (DP) or async modeset (HDMI), which in turn makes the test
* miss vblank/flip events and fail. Work around this by retrying the test
* once in case of such a link reset event, which the driver signals with a
* hotplug event.
*/
static bool needs_retry_after_link_reset(struct udev_monitor *mon)
{
bool hotplug_detected;
igt_suspend_signal_helper();
hotplug_detected = igt_hotplug_detected(mon, 3);
igt_resume_signal_helper();
if (hotplug_detected)
igt_debug("Retrying after a hotplug event\n");
return hotplug_detected;
} }
static void __run_test_on_crtc_set(struct test_output *o, int *crtc_idxs, static void __run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
...@@ -1259,6 +1298,11 @@ static void __run_test_on_crtc_set(struct test_output *o, int *crtc_idxs, ...@@ -1259,6 +1298,11 @@ static void __run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
kmstest_dump_mode(&o->kmode[i]); kmstest_dump_mode(&o->kmode[i]);
retry: retry:
memset(&o->vblank_state, 0, sizeof(o->vblank_state));
memset(&o->flip_state, 0, sizeof(o->flip_state));
o->flip_state.name = "flip";
o->vblank_state.name = "vblank";
kmstest_unset_all_crtcs(drm_fd, resources); kmstest_unset_all_crtcs(drm_fd, resources);
igt_flush_uevents(mon); igt_flush_uevents(mon);
...@@ -1282,8 +1326,13 @@ retry: ...@@ -1282,8 +1326,13 @@ retry:
} }
/* quiescent the hw a bit so ensure we don't miss a single frame */ /* quiescent the hw a bit so ensure we don't miss a single frame */
if (o->flags & TEST_CHECK_TS) if (o->flags & TEST_CHECK_TS && !calibrate_ts(o, crtc_idxs[0])) {
calibrate_ts(o, crtc_idxs[0]); igt_assert(!retried && needs_retry_after_link_reset(mon));
retried = true;
goto retry;
}
if (o->flags & TEST_BO_TOOBIG) { if (o->flags & TEST_BO_TOOBIG) {
int err = do_page_flip(o, o->fb_ids[1], true); int err = do_page_flip(o, o->fb_ids[1], true);
...@@ -1316,28 +1365,10 @@ retry: ...@@ -1316,28 +1365,10 @@ retry:
if (o->flags & TEST_VBLANK) if (o->flags & TEST_VBLANK)
state_ok &= check_final_state(o, &o->vblank_state, elapsed); state_ok &= check_final_state(o, &o->vblank_state, elapsed);
/*
* Some monitors with odd behavior signal a bad link after waking from
* a power saving state and the subsequent (successful) modeset. This
* will result in a link-retraining (DP) or async modeset (HDMI),
* which in turn makes the test miss vblank/flip events and fail.
* Work around this by retrying the test once in case of such a link
* reset event, which the driver signals with a hotplug event.
*/
if (!state_ok) { if (!state_ok) {
bool hotplug_detected; igt_assert(!retried && needs_retry_after_link_reset(mon));
igt_suspend_signal_helper();
if (!retried)
hotplug_detected = igt_hotplug_detected(mon, 3);
igt_resume_signal_helper();
igt_assert(!retried && hotplug_detected);
igt_debug("Retrying after a hotplug event\n");
retried = true; retried = true;
memset(&o->vblank_state, 0, sizeof(o->vblank_state));
memset(&o->flip_state, 0, sizeof(o->flip_state));
goto retry; goto retry;
} }
...@@ -1412,8 +1443,6 @@ static int run_test(int duration, int flags) ...@@ -1412,8 +1443,6 @@ static int run_test(int duration, int flags)
o.count = 1; o.count = 1;
o._connector[0] = resources->connectors[i]; o._connector[0] = resources->connectors[i];
o.flags = flags; o.flags = flags;
o.flip_state.name = "flip";
o.vblank_state.name = "vblank";
o.bpp = 32; o.bpp = 32;
o.depth = 24; o.depth = 24;
...@@ -1438,8 +1467,6 @@ static int run_test(int duration, int flags) ...@@ -1438,8 +1467,6 @@ static int run_test(int duration, int flags)
o.count = 1; o.count = 1;
o._connector[0] = resources->connectors[i]; o._connector[0] = resources->connectors[i];
o.flags = flags; o.flags = flags;
o.flip_state.name = "flip";
o.vblank_state.name = "vblank";
o.bpp = 32; o.bpp = 32;
o.depth = 24; o.depth = 24;
...@@ -1474,8 +1501,6 @@ static int run_pair(int duration, int flags) ...@@ -1474,8 +1501,6 @@ static int run_pair(int duration, int flags)
o._connector[0] = resources->connectors[i]; o._connector[0] = resources->connectors[i];
o._connector[1] = resources->connectors[j]; o._connector[1] = resources->connectors[j];
o.flags = flags; o.flags = flags;
o.flip_state.name = "flip";
o.vblank_state.name = "vblank";
o.bpp = 32; o.bpp = 32;
o.depth = 24; o.depth = 24;
...@@ -1507,8 +1532,6 @@ static int run_pair(int duration, int flags) ...@@ -1507,8 +1532,6 @@ static int run_pair(int duration, int flags)
o._connector[0] = resources->connectors[i]; o._connector[0] = resources->connectors[i];
o._connector[1] = resources->connectors[j]; o._connector[1] = resources->connectors[j];
o.flags = flags; o.flags = flags;
o.flip_state.name = "flip";
o.vblank_state.name = "vblank";
o.bpp = 32; o.bpp = 32;
o.depth = 24; o.depth = 24;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment