Instead of strictly measuring vblanks, we try to see if a page flip is queued on the next vblank if we run legacy cursor updates to the pipe and another pipe in the background. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101634 --- tests/kms_cursor_legacy.c | 90 ++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/tests/kms_cursor_legacy.c b/tests/kms_cursor_legacy.c index 5720dbef90d3..b8b15b609d7f 100644 --- a/tests/kms_cursor_legacy.c +++ b/tests/kms_cursor_legacy.c @@ -884,14 +884,23 @@ cleanup: static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset, bool atomic) { - struct drm_mode_cursor arg[2], arg2[2]; - struct drm_event_vblank vbl; + struct drm_mode_cursor arg1[2], arg2[2]; struct igt_fb fb_info, fb2_info, cursor_fb; - unsigned vblank_start; enum pipe pipe = find_connected_pipe(display, false); enum pipe pipe2 = find_connected_pipe(display, true); igt_output_t *output, *output2; bool skip_test = false; + volatile unsigned long *shared; + + if (modeset) { + uint64_t val; + + igt_fail_on(!atomic); + igt_assert(drmGetCap(display->drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &val) == 0); + } + + shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + igt_assert(shared != MAP_FAILED); igt_fail_on(modeset && !atomic); @@ -903,9 +912,9 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb); set_cursor_on_pipe(display, pipe, &cursor_fb); - populate_cursor_args(display, pipe, arg, &cursor_fb); + populate_cursor_args(display, pipe, arg1, &cursor_fb); - arg[1].x = arg[1].y = 192; + arg1[1].x = arg1[1].y = 192; set_cursor_on_pipe(display, pipe2, &cursor_fb); populate_cursor_args(display, pipe2, arg2, &cursor_fb); @@ -917,29 +926,29 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); - vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS); - igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start); - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]); - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]); - igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start); + igt_fork(child, 2) { + struct drm_mode_cursor *arg = child ? arg2 : arg1; + + while (!shared[0]) + do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, + &arg[!shared[1]]); + } while (nloops--) { - /* Start with a synchronous query to align with the vblank */ - vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS); - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]); + unsigned vblank_start = + get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS); + + shared[1] = nloops & 1; + + if (!modeset) { + flip_nonblocking(display, pipe, atomic, &fb_info); + } else { + unsigned flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + flags |= DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT; - if (!modeset) - flip_nonblocking(display, pipe, false, &fb_info); - else { /* - * There are 2 design issues that prevent us from doing - * the test we would like here: - * - * - drm_event_vblank doesn't set crtc_id, so if we - * use events we don't know which pipe fired the event, - * no way to distinguish. - * - Doing a modeset may add unrelated pipes, and fail with - * -EBUSY if a page flip is queued on one of those. + * Doing a modeset may add unrelated pipes, and fail with + * -EBUSY if a page flip is queued on one of those. * * Work around it by not setting an event, but doing a synchronous * commit to wait for completion, and queue the page flip and modeset @@ -948,26 +957,32 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool igt_plane_set_fb(igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY), &fb_info); igt_output_set_pipe(output2, (nloops & 1) ? PIPE_NONE : pipe2); - igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL); + igt_display_commit_atomic(display, flags, NULL); } - igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start); - - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]); if (!modeset) { - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]); - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]); - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]); - - igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start); + struct drm_event_vblank vbl; igt_set_timeout(1, "Stuck page flip"); + igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl))); - igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1); - igt_reset_timeout(); + igt_assert(vbl.crtc_id == display->pipes[pipe].crtc_id); + igt_assert(vbl.sequence == vblank_start + 1); } else { - do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]); + struct drm_event_vblank vbl, vbl2; + + igt_set_timeout(35, "Stuck nonblocking modeset"); + + igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl))); + igt_ignore_warn(read(display->drm_fd, &vbl2, sizeof(vbl2))); + + igt_assert(vbl.crtc_id != vbl2.crtc_id); + igt_assert(vbl.crtc_id == display->pipes[pipe].crtc_id || + vbl.crtc_id == display->pipes[pipe2].crtc_id); + igt_assert(vbl2.crtc_id == display->pipes[pipe].crtc_id || + vbl2.crtc_id == display->pipes[pipe2].crtc_id); } + igt_reset_timeout(); if (modeset) { /* wait for pending modeset and page flip to complete, to prevent -EBUSY */ @@ -977,6 +992,9 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool } } + shared[0] = 1; + igt_waitchildren(); + cleanup: do_cleanup_display(display); igt_remove_fb(display->drm_fd, &fb_info); -- 2.15.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx