aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-10-21 22:48:07 +0200
committerMichael S. Tsirkin <mst@redhat.com>2016-10-30 19:51:32 +0200
commitff4c07df67f098234d9e49850435ccb49b8cbbdc (patch)
tree52c0cf25041eec19e18dd2d2ef87784bb21e9f11 /hw/virtio
parentb13d39622703ae7449f769c14da7a90f20f2c25c (diff)
downloadqemu-ff4c07df67f098234d9e49850435ccb49b8cbbdc.zip
qemu-ff4c07df67f098234d9e49850435ccb49b8cbbdc.tar.gz
qemu-ff4c07df67f098234d9e49850435ccb49b8cbbdc.tar.bz2
virtio: add start_ioeventfd and stop_ioeventfd to VirtioDeviceClass
Allow customization of the start and stop of ioeventfd. This will allow direct start of dataplane without passing through the default ioeventfd handlers, which in turn allows using the dataplane logic instead of virtio_add_queue_aio. It will also enable some code simplification, because the sole entry point to ioeventfd setup will be virtio_bus_set_host_notifier. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/virtio-bus.c54
-rw-r--r--hw/virtio/virtio.c64
2 files changed, 81 insertions, 37 deletions
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 97cdb11..a8d2bd8 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -153,8 +153,8 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
* assign: register/deregister ioeventfd with the kernel
* set_handler: use the generic ioeventfd handler
*/
-static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
- int n, bool assign, bool set_handler)
+int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
+ int n, bool assign, bool set_handler)
{
VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
@@ -185,61 +185,41 @@ static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
return r;
}
-void virtio_bus_start_ioeventfd(VirtioBusState *bus)
+int virtio_bus_start_ioeventfd(VirtioBusState *bus)
{
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
DeviceState *proxy = DEVICE(BUS(bus)->parent);
- VirtIODevice *vdev;
- int n, r;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ int r;
if (!k->ioeventfd_assign || k->ioeventfd_disabled(proxy)) {
- return;
+ return -ENOSYS;
}
if (bus->ioeventfd_started || bus->ioeventfd_disabled) {
- return;
+ return 0;
}
- vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
+ r = vdc->start_ioeventfd(vdev);
+ if (r < 0) {
+ error_report("%s: failed. Fallback to userspace (slower).", __func__);
+ return r;
}
bus->ioeventfd_started = true;
- return;
-
-assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
- error_report("%s: failed. Fallback to userspace (slower).", __func__);
+ return 0;
}
void virtio_bus_stop_ioeventfd(VirtioBusState *bus)
{
- DeviceState *proxy = DEVICE(BUS(bus)->parent);
VirtIODevice *vdev;
- int n, r;
+ VirtioDeviceClass *vdc;
if (!bus->ioeventfd_started) {
return;
}
+
vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
+ vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ vdc->stop_ioeventfd(vdev);
bus->ioeventfd_started = false;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 3e318e4..e228518 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2172,15 +2172,79 @@ static Property virtio_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
+{
+ VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ DeviceState *proxy = DEVICE(BUS(qbus)->parent);
+ int n, r, err;
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, qbus, n, true, true);
+ if (r < 0) {
+ err = r;
+ goto assign_error;
+ }
+ }
+ return 0;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = set_host_notifier_internal(proxy, qbus, n, false, false);
+ assert(r >= 0);
+ }
+ return err;
+}
+
+int virtio_device_start_ioeventfd(VirtIODevice *vdev)
+{
+ BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+ VirtioBusState *vbus = VIRTIO_BUS(qbus);
+
+ return virtio_bus_start_ioeventfd(vbus);
+}
+
+static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
+{
+ VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ DeviceState *proxy = DEVICE(BUS(qbus)->parent);
+ int n, r;
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, qbus, n, false, false);
+ assert(r >= 0);
+ }
+}
+
+void virtio_device_stop_ioeventfd(VirtIODevice *vdev)
+{
+ BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+ VirtioBusState *vbus = VIRTIO_BUS(qbus);
+
+ virtio_bus_stop_ioeventfd(vbus);
+}
+
static void virtio_device_class_init(ObjectClass *klass, void *data)
{
/* Set the default value here. */
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = virtio_device_realize;
dc->unrealize = virtio_device_unrealize;
dc->bus_type = TYPE_VIRTIO_BUS;
dc->props = virtio_properties;
+ vdc->start_ioeventfd = virtio_device_start_ioeventfd_impl;
+ vdc->stop_ioeventfd = virtio_device_stop_ioeventfd_impl;
}
static const TypeInfo virtio_device_info = {