diff options
author | Jason Wang <jasowang@redhat.com> | 2015-04-23 14:21:46 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2015-04-27 21:02:41 +0200 |
commit | e0d686bf4b9d018ba5449f057b486bb5e1fa1a0d (patch) | |
tree | 6875ad1bdef6e72f830758929c66d2a1dc811254 /hw/virtio/virtio.c | |
parent | 955cc8c9541779e09895a9c5ccbf8ace15d884f5 (diff) | |
download | qemu-e0d686bf4b9d018ba5449f057b486bb5e1fa1a0d.zip qemu-e0d686bf4b9d018ba5449f057b486bb5e1fa1a0d.tar.gz qemu-e0d686bf4b9d018ba5449f057b486bb5e1fa1a0d.tar.bz2 |
virtio: introduce vector to virtqueues mapping
Currently we will try to traverse all virtqueues to find a subset that
using a specific vector. This is sub optimal when we will support
hundreds or even thousands of virtqueues. So this patch introduces a
method which could be used by transport to get all virtqueues that
using a same vector. This is done through QLISTs and the number of
QLISTs was queried through a transport specific method. When guest
setting vectors, the virtqueue will be linked and helpers for traverse
the list was also introduced.
The first user will be virtio pci which will use this to speed up
MSI-X masking and unmasking handling.
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio/virtio.c')
-rw-r--r-- | hw/virtio/virtio.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 17c1260..6985e76 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -89,6 +89,7 @@ struct VirtQueue VirtIODevice *vdev; EventNotifier guest_notifier; EventNotifier host_notifier; + QLIST_ENTRY(VirtQueue) node; }; /* virt queue functions */ @@ -605,7 +606,7 @@ void virtio_reset(void *opaque) vdev->vq[i].vring.used = 0; vdev->vq[i].last_avail_idx = 0; vdev->vq[i].pa = 0; - vdev->vq[i].vector = VIRTIO_NO_VECTOR; + virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR); vdev->vq[i].signalled_used = 0; vdev->vq[i].signalled_used_valid = false; vdev->vq[i].notification = true; @@ -730,6 +731,16 @@ void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) virtqueue_init(&vdev->vq[n]); } +VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector) +{ + return QLIST_FIRST(&vdev->vector_queues[vector]); +} + +VirtQueue *virtio_vector_next_queue(VirtQueue *vq) +{ + return QLIST_NEXT(vq, node); +} + int virtio_queue_get_num(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.num; @@ -780,8 +791,19 @@ uint16_t virtio_queue_vector(VirtIODevice *vdev, int n) void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector) { - if (n < VIRTIO_PCI_QUEUE_MAX) + VirtQueue *vq = &vdev->vq[n]; + + if (n < VIRTIO_PCI_QUEUE_MAX) { + if (vdev->vector_queues && + vdev->vq[n].vector != VIRTIO_NO_VECTOR) { + QLIST_REMOVE(vq, node); + } vdev->vq[n].vector = vector; + if (vdev->vector_queues && + vector != VIRTIO_NO_VECTOR) { + QLIST_INSERT_HEAD(&vdev->vector_queues[vector], vq, node); + } + } } VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, @@ -1088,6 +1110,7 @@ void virtio_cleanup(VirtIODevice *vdev) qemu_del_vm_change_state_handler(vdev->vmstate); g_free(vdev->config); g_free(vdev->vq); + g_free(vdev->vector_queues); } static void virtio_vmstate_change(void *opaque, int running, RunState state) @@ -1125,7 +1148,16 @@ void virtio_instance_init_common(Object *proxy_obj, void *data, void virtio_init(VirtIODevice *vdev, const char *name, uint16_t device_id, size_t config_size) { + BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int i; + int nvectors = k->query_nvectors ? k->query_nvectors(qbus->parent) : 0; + + if (nvectors) { + vdev->vector_queues = + g_malloc0(sizeof(*vdev->vector_queues) * nvectors); + } + vdev->device_id = device_id; vdev->status = 0; vdev->isr = 0; |