diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index b2d8496ce289..42a5cd23084c 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -118,10 +118,12 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); const unsigned pipe = drm_crtc_index(crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_pending_vblank_event *e = xchg(&vgdev->cache_event[pipe], NULL); /* Send cached event even it's still premature. */ if (e) { + wait_for_completion_interruptible_timeout(&vgdev->notify[pipe], nsecs_to_jiffies(vblank->framedur_ns)); spin_lock_irq(&dev->event_lock); drm_crtc_send_vblank_event(crtc, e); spin_unlock_irq(&dev->event_lock); @@ -172,6 +174,7 @@ static void virtio_gpu_crtc_atomic_begin(struct drm_crtc *crtc, spin_unlock_irq(&drm->event_lock); drm_crtc_vblank_put(crtc); } + init_completion(&vgdev->notify[pipe]); } crtc->state->event = NULL; } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 82bdee186574..700819f30021 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -253,6 +253,7 @@ struct virtio_gpu_device { struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS]; struct drm_pending_vblank_event *cache_event[VIRTIO_GPU_MAX_SCANOUTS]; + struct completion notify[VIRTIO_GPU_MAX_SCANOUTS]; atomic64_t flip_sequence[VIRTIO_GPU_MAX_SCANOUTS]; uint32_t num_scanouts; uint32_t num_vblankq; diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index e595bb5c4842..48217597b307 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -128,6 +128,7 @@ void virtio_gpu_vblank_ack(struct virtqueue *vq) if (drm_vblank_passed(atomic64_read(&vgdev->flip_sequence[target]), e->sequence)) { + complete(&vgdev->notify[target]); spin_lock_irqsave(&dev->event_lock, irqflags); drm_crtc_send_vblank_event(&vgdev->outputs[target].crtc, e); spin_unlock_irqrestore(&dev->event_lock, irqflags); @@ -135,6 +136,7 @@ void virtio_gpu_vblank_ack(struct virtqueue *vq) } else { WARN_ON((e = xchg(&vgdev->cache_event[target], e)) != NULL); if (e) { + complete(&vgdev->notify[target]); /* Should not come here ever, just in case... */ spin_lock_irqsave(&dev->event_lock, irqflags); drm_crtc_send_vblank_event(&vgdev->outputs[target].crtc, e);