summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-11-14 05:03:55 +0000
committerDave Airlie <airlied@redhat.com>2013-11-14 05:03:55 +0000
commitcc599515182dc345771775b908fe66f4a1f5ffcb (patch)
tree9d3866caad6b58f35f1b6f8c8ffafe7696aa692e
parentfd9710f734bd57fbdb44f8eb16c483da41379ce1 (diff)
add event q suppotr and polled connector
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c9
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c64
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;
+
+}