diff options
author | Dave Airlie <airlied@redhat.com> | 2013-11-14 05:03:55 +0000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-11-14 05:03:55 +0000 |
commit | cc599515182dc345771775b908fe66f4a1f5ffcb (patch) | |
tree | 9d3866caad6b58f35f1b6f8c8ffafe7696aa692e | |
parent | fd9710f734bd57fbdb44f8eb16c483da41379ce1 (diff) |
add event q suppotr and polled connector
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_kms.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_vq.c | 64 |
4 files changed, 71 insertions, 5 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 366e53662ba9..b97b998ae7a5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -484,7 +484,7 @@ int vgdev_output_init(struct drm_device *dev, int num_output) encoder = &virtgpu_output->enc; drm_connector_init(dev, &virtgpu_output->base, &virtgpu_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); - + connector->polled = DRM_CONNECTOR_POLL_HPD; drm_encoder_init(dev, &virtgpu_output->enc, &virtgpu_enc_funcs, DRM_MODE_ENCODER_VIRTUAL); diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 1f6b8524aa06..6682c5f7fb38 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -185,6 +185,7 @@ int virtgpu_attach_status_page(struct virtgpu_device *vgdev); int virtgpu_detach_status_page(struct virtgpu_device *vgdev); void virtgpu_cursor_ping(struct virtgpu_device *vgdev); int virtgpu_cmd_get_display_info(struct virtgpu_device *vgdev); +int virtgpu_fill_event_vq(struct virtgpu_device *vgdev, int entries); /* virtgpu_display.c */ int virtgpu_framebuffer_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index b184adfed732..5937d7ae1a77 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -16,7 +16,7 @@ int virtgpu_driver_load(struct drm_device *dev, unsigned long flags) { struct virtgpu_device *vgdev; /* this will expand later */ - struct virtqueue *vqs[2]; + struct virtqueue *vqs[3]; vq_callback_t *callbacks[] = { virtgpu_ctrl_ack, virtgpu_cursor_ack, virtgpu_event_ack }; const char *names[] = { "control", "cursor", "event" }; int nvqs; @@ -35,14 +35,14 @@ int virtgpu_driver_load(struct drm_device *dev, unsigned long flags) virtgpu_init_vq(&vgdev->ctrlq, virtgpu_dequeue_ctrl_func); virtgpu_init_vq(&vgdev->cursorq, virtgpu_dequeue_cursor_func); virtgpu_init_vq(&vgdev->eventq, virtgpu_dequeue_event_func); - + vgdev->cursor_page = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!vgdev->cursor_page) { kfree(vgdev); return -ENOMEM; } - nvqs = 2; + nvqs = 3; ret = vgdev->vdev->config->find_vqs(vgdev->vdev, nvqs, vqs, callbacks, names); if (ret) { @@ -53,6 +53,9 @@ int virtgpu_driver_load(struct drm_device *dev, unsigned long flags) vgdev->ctrlq.vq = vqs[0]; vgdev->cursorq.vq = vqs[1]; + vgdev->eventq.vq = vqs[2]; + + virtgpu_fill_event_vq(vgdev, 64); /* get display info */ virtgpu_cmd_get_display_info(vgdev); diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 06286c8a760e..a232002ee5d3 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -108,6 +108,20 @@ struct virtgpu_command *virtgpu_alloc_cmd_resp(struct virtgpu_device *vgdev, return (struct virtgpu_command *)vbuf->buf; } +static int add_inbuf(struct virtqueue *vq, struct virtgpu_vbuffer *vbuf) +{ + struct scatterlist sg[1]; + int ret; + + sg_init_one(sg, vbuf->resp_buf, vbuf->resp_size); + + ret = virtqueue_add_inbuf(vq, sg, 1, vbuf, GFP_ATOMIC); + virtqueue_kick(vq); + if (!ret) + ret = vq->num_free; + return ret; +} + static void free_vbuf(struct virtgpu_device *vgdev, struct virtgpu_vbuffer *vbuf) { if (vbuf->vaddr) @@ -179,11 +193,19 @@ void virtgpu_dequeue_event_func(struct work_struct *work) struct virtgpu_device *vgdev = container_of(work, struct virtgpu_device, eventq.dequeue_work); struct virtqueue *vq = vgdev->eventq.vq; + struct virtgpu_vbuffer *vbuf; unsigned int len; spin_lock(&vgdev->eventq.qlock); do { virtqueue_disable_cb(vgdev->eventq.vq); - while (virtqueue_get_buf(vq, &len)) { + while ((vbuf = virtqueue_get_buf(vq, &len))) { + + if (vbuf->resp_cb) + vbuf->resp_cb(vgdev, vbuf); + if (add_inbuf(vgdev->eventq.vq, vbuf) < 0) { + DRM_ERROR("Error adding buffer to queue\n"); + free_vbuf(vgdev, vbuf); + } } } while (!virtqueue_enable_cb(vgdev->eventq.vq)); spin_unlock(&vgdev->eventq.qlock); @@ -475,3 +497,43 @@ void virtgpu_cursor_ping(struct virtgpu_device *vgdev) virtgpu_queue_cursor(vgdev); } +void virtgpu_event_cb(struct virtgpu_device *vgdev, + struct virtgpu_vbuffer *vbuf) +{ + struct virtgpu_event *event; + + event = (struct virtgpu_event *)vbuf->resp_buf; + + DRM_INFO("drm got event cb %d\n", event->type); + if (event->type == VIRTGPU_EVENT_DISPLAY_CHANGE) { + spin_lock(&vgdev->display_info_lock); + memcpy(&vgdev->display_info, &event->u.display_info, sizeof(struct virtgpu_display_info)); + + spin_unlock(&vgdev->display_info_lock); + drm_helper_hpd_irq_event(vgdev->ddev); + } +} + +int virtgpu_fill_event_vq(struct virtgpu_device *vgdev, int entries) +{ + struct virtgpu_vbuffer *vbuf; + int i; + int ret; + for (i = 0; i < entries; i++) { + vbuf = virtgpu_allocate_vbuf(vgdev, 0, sizeof(struct virtgpu_event), virtgpu_event_cb); + if (!vbuf) + break; + + spin_lock_irq(&vgdev->eventq.qlock); + + ret = add_inbuf(vgdev->eventq.vq, vbuf); + if (ret < 0) { + free_vbuf(vgdev, vbuf); + spin_unlock_irq(&vgdev->eventq.qlock); + break; + } + spin_unlock_irq(&vgdev->eventq.qlock); + } + return i; + +} |