Replace vmwgfx's vblank timer with DRM's common implementation. The timer handling is almost identical with a few additional bug fixes in the common code.
Replace most of vmwgfx's vmw_vkms_get_vblank_timestamp() with the shared helper drm_crtc_vblank_get_vblank_timeout(). The common helper also works in the presence of delayed vblank timeouts that modify the vblank counter concurrently. Set the timeout handler to vmw_vkms_handle_vblank_timeout(). In addition to handling vblank events, this function also controls CRC generation. Remove all the hrtimer-related code from vmwgfx. DRM vblank timers provides this. Signed-off-by: Thomas Zimmermann <[email protected]> --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 - drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c | 63 ++++------------------------ drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h | 1 - 6 files changed, 10 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 445471fe9be6..b5670ece90a9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -322,8 +322,6 @@ struct vmw_display_unit { struct { struct work_struct crc_generator_work; - struct hrtimer timer; - ktime_t period_ns; /* protects concurrent access to the vblank handler */ atomic_t atomic_lock; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index f07669b27fba..6f22d5f5c379 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -402,6 +402,7 @@ static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { .atomic_flush = vmw_vkms_crtc_atomic_flush, .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_vkms_crtc_atomic_disable, + .handle_vblank_timeout = vmw_vkms_handle_vblank_timeout, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 605d037d18c6..cfb8ad3ebe43 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -797,6 +797,7 @@ static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .atomic_flush = vmw_vkms_crtc_atomic_flush, .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_sou_crtc_atomic_disable, + .handle_vblank_timeout = vmw_vkms_handle_vblank_timeout, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index dcbacee97f61..1f5497e2638a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1515,6 +1515,7 @@ static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { .atomic_flush = vmw_stdu_crtc_atomic_flush, .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_stdu_crtc_atomic_disable, + .handle_vblank_timeout = vmw_vkms_handle_vblank_timeout, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c index 15439ddd4f22..20b6dfd3d3c2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c @@ -195,27 +195,6 @@ vmw_vkms_handle_vblank_timeout(struct drm_crtc *crtc) return true; } -static enum hrtimer_restart -vmw_vkms_vblank_simulate(struct hrtimer *timer) -{ - struct vmw_display_unit *du = container_of(timer, struct vmw_display_unit, vkms.timer); - struct drm_crtc *crtc = &du->crtc; - u64 ret_overrun; - bool success; - - ret_overrun = hrtimer_forward_now(&du->vkms.timer, - du->vkms.period_ns); - if (ret_overrun != 1) - drm_dbg_driver(crtc->dev, "vblank timer missed %lld frames.\n", - ret_overrun - 1); - - success = vmw_vkms_handle_vblank_timeout(crtc); - if (!success) - return HRTIMER_NORESTART; - - return HRTIMER_RESTART; -} - void vmw_vkms_init(struct vmw_private *vmw) { @@ -258,32 +237,12 @@ vmw_vkms_get_vblank_timestamp(struct drm_crtc *crtc, ktime_t *vblank_time, bool in_vblank_irq) { - struct drm_device *dev = crtc->dev; - struct vmw_private *vmw = vmw_priv(dev); - struct vmw_display_unit *du = vmw_crtc_to_du(crtc); - struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); + struct vmw_private *vmw = vmw_priv(crtc->dev); if (!vmw->vkms_enabled) return false; - if (!READ_ONCE(vblank->enabled)) { - *vblank_time = ktime_get(); - return true; - } - - *vblank_time = READ_ONCE(du->vkms.timer.node.expires); - - if (WARN_ON(*vblank_time == vblank->time)) - return true; - - /* - * To prevent races we roll the hrtimer forward before we do any - * interrupt processing - this is how real hw works (the interrupt is - * only generated after all the vblank registers are updated) and what - * the vblank core expects. Therefore we need to always correct the - * timestampe by one frame. - */ - *vblank_time -= du->vkms.period_ns; + drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time); return true; } @@ -293,20 +252,11 @@ vmw_vkms_enable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct vmw_private *vmw = vmw_priv(dev); - struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); - struct vmw_display_unit *du = vmw_crtc_to_du(crtc); if (!vmw->vkms_enabled) return -EINVAL; - drm_calc_timestamping_constants(crtc, &crtc->mode); - - hrtimer_setup(&du->vkms.timer, &vmw_vkms_vblank_simulate, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - du->vkms.period_ns = ktime_set(0, vblank->framedur_ns); - hrtimer_start(&du->vkms.timer, du->vkms.period_ns, HRTIMER_MODE_REL); - - return 0; + return drm_crtc_vblank_start_timer(crtc); } void @@ -318,9 +268,9 @@ vmw_vkms_disable_vblank(struct drm_crtc *crtc) if (!vmw->vkms_enabled) return; - hrtimer_cancel(&du->vkms.timer); + drm_crtc_vblank_cancel_timer(crtc); + du->vkms.surface = NULL; - du->vkms.period_ns = ktime_set(0, 0); } enum vmw_vkms_lock_state { @@ -346,10 +296,11 @@ vmw_vkms_crtc_cleanup(struct drm_crtc *crtc) { struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + drm_crtc_vblank_cancel_timer(crtc); + if (du->vkms.surface) vmw_surface_unreference(&du->vkms.surface); WARN_ON(work_pending(&du->vkms.crc_generator_work)); - hrtimer_cancel(&du->vkms.timer); } void diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h index 0b6bbf7c4487..40c679f59db2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h @@ -29,7 +29,6 @@ #ifndef VMWGFX_VKMS_H_ #define VMWGFX_VKMS_H_ -#include <linux/hrtimer_types.h> #include <linux/types.h> struct drm_atomic_state; -- 2.53.0
