DF-4437 / fix.diff
--- a/sys/dev/drm/drm_plane.c +++ b/sys/dev/drm/drm_plane.c @@ -1018,6 +1018,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_pending_vblank_event *e = NULL; u32 target_vblank = page_flip->sequence; struct drm_modeset_acquire_ctx ctx; + bool vblank_ref_held = false; int ret = -EINVAL; if (!drm_core_check_feature(dev, DRIVER_MODESET)) @@ -1087,6 +1088,14 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); retry: + if (crtc->funcs->page_flip_target && !vblank_ref_held) { + ret = drm_crtc_vblank_get(crtc); + if (ret) + goto out; + vblank_ref_held = true; + } + ret = drm_modeset_lock(&crtc->mutex, &ctx); if (ret) goto out; @@ -1178,6 +1187,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (plane->old_fb) drm_framebuffer_put(plane->old_fb); plane->old_fb = NULL; + if (vblank_ref_held) { + drm_crtc_vblank_put(crtc); + vblank_ref_held = false; + } if (ret == -EDEADLK) { ret = drm_modeset_backoff(&ctx); @@ -1192,9 +1206,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - - if (ret && crtc->funcs->page_flip_target) - drm_crtc_vblank_put(crtc); return ret; } |