Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion drivers/gpu/drm/virtio/virtgpu_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static int virtio_irq_enable_vblank(struct drm_crtc *crtc)
do {
virtio_gpu_vblank_poll_arm(vgdev->vblank[output->index].vblank.vq);
} while (!virtqueue_enable_cb(vgdev->vblank[output->index].vblank.vq));
vgdev->vblank[output->index].enabled = true;
return 0;
}

Expand All @@ -71,7 +72,11 @@ static void virtio_irq_disable_vblank(struct drm_crtc *crtc)
vgdev = dev->dev_private;
struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc);

virtqueue_disable_cb(vgdev->vblank[output->index].vblank.vq);
if (vgdev->cache_event[output->index]) {
printk("bosheng pending event in disable vblank\n");
virtqueue_disable_cb(vgdev->vblank[output->index].vblank.vq);
vgdev->vblank[output->index].enabled = false;
}
}

static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/virtio/virtgpu_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ struct virtio_gpu_drv_cap_cache {
struct virtio_gpu_vblank {
struct virtio_gpu_queue vblank;
uint32_t buf[4];
uint32_t idle_vblank_count;
bool enabled;
};

static inline bool drm_vblank_passed(u64 seq, u64 ref)
Expand Down
24 changes: 20 additions & 4 deletions drivers/gpu/drm/virtio/virtgpu_vq.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void virtio_gpu_vblank_poll_arm(struct virtqueue *vq)
spin_unlock_irqrestore(&vgdev->vblank[target].vblank.qlock, irqflags);
}

#define PAGEFLIP_RESET 10
void virtio_gpu_vblank_ack(struct virtqueue *vq)
{
struct drm_device *dev = vq->vdev->priv;
Expand All @@ -101,6 +102,7 @@ void virtio_gpu_vblank_ack(struct virtqueue *vq)
unsigned int len;
unsigned int *ret_value;
unsigned target = 0;
bool timeout = false;

while((target < vgdev->num_vblankq) && (vgdev->vblank[target].vblank.vq != vq)) {
target++;
Expand All @@ -114,6 +116,10 @@ void virtio_gpu_vblank_ack(struct virtqueue *vq)
drm_handle_vblank(dev, target);

if (*ret_value != 0) {
if (atomic64_read(&vgdev->flip_sequence[target]) == *ret_value)
vgdev->vblank[target].idle_vblank_count++;
else
vgdev->vblank[target].idle_vblank_count = 0;
atomic64_set(&vgdev->flip_sequence[target], *ret_value);
}

Expand All @@ -123,10 +129,20 @@ void virtio_gpu_vblank_ack(struct virtqueue *vq)
return;

struct drm_pending_vblank_event *e = xchg(&vgdev->cache_event[target], NULL);
if (!e)
if (!e) {
spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
if (!dev->vblank[target].enabled && vgdev->vblank[target].enabled) {
virtqueue_disable_cb(vgdev->vblank[target].vblank.vq);
vgdev->vblank[target].enabled = false;
}
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
return;

if (drm_vblank_passed(atomic64_read(&vgdev->flip_sequence[target]),
}
if (vgdev->vblank[target].idle_vblank_count >= PAGEFLIP_RESET) {
vgdev->vblank[target].idle_vblank_count = 0;
timeout = true;
}
if (timeout || drm_vblank_passed(atomic64_read(&vgdev->flip_sequence[target]),
e->sequence)) {
spin_lock_irqsave(&dev->event_lock, irqflags);
drm_crtc_send_vblank_event(&vgdev->outputs[target].crtc, e);
Expand Down Expand Up @@ -559,7 +575,7 @@ void virtio_gpu_vblankq_notify(struct virtio_gpu_device *vgdev)

for(i=0; i < vgdev->num_vblankq; i++) {
spin_lock_irqsave(&vgdev->vblank[i].vblank.qlock, irqflags);

vgdev->vblank[i].idle_vblank_count = 0;
size = virtqueue_get_vring_size(vgdev->vblank[i].vblank.vq);
if (size > ARRAY_SIZE(vgdev->vblank[i].buf))
size = ARRAY_SIZE(vgdev->vblank[i].buf);
Expand Down