diff options
author | Stefan Hajnoczi | 2016-11-21 12:09:58 +0100 |
---|---|---|
committer | Stefan Hajnoczi | 2016-11-21 12:09:58 +0100 |
commit | c36ed06e9159fa484b711dfdd27ec64d7ac3d17a (patch) | |
tree | e87010bcb634dd0ed1f2abb8123e044d308e4a71 /hw/virtio/virtio-bus.c | |
parent | Merge remote-tracking branch 'public/tags/tracing-pull-request' into staging (diff) | |
parent | acpi: Use apic_id_limit when calculating legacy ACPI table size (diff) | |
download | qemu-c36ed06e9159fa484b711dfdd27ec64d7ac3d17a.tar.gz qemu-c36ed06e9159fa484b711dfdd27ec64d7ac3d17a.tar.xz qemu-c36ed06e9159fa484b711dfdd27ec64d7ac3d17a.zip |
Merge remote-tracking branch 'mst/tags/for_upstream' into staging
virtio, vhost, pc: fixes
Most notably this fixes a regression with vhost introduced by the pull before
last.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Fri 18 Nov 2016 03:51:55 PM GMT
# gpg: using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* mst/tags/for_upstream:
acpi: Use apic_id_limit when calculating legacy ACPI table size
ipmi: fix qemu crash while migrating with ipmi
ivshmem: Fix 64 bit memory bar configuration
virtio: set ISR on dataplane notifications
virtio: access ISR atomically
virtio: introduce grab/release_ioeventfd to fix vhost
virtio-crypto: fix virtio_queue_set_notification() race
Message-id: 1479484366-7977-1-git-send-email-mst@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/virtio/virtio-bus.c')
-rw-r--r-- | hw/virtio/virtio-bus.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index bf61f66a04..d6c0c72bd2 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -147,6 +147,39 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config) } } +/* On success, ioeventfd ownership belongs to the caller. */ +int virtio_bus_grab_ioeventfd(VirtioBusState *bus) +{ + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus); + + /* vhost can be used even if ioeventfd=off in the proxy device, + * so do not check k->ioeventfd_enabled. + */ + if (!k->ioeventfd_assign) { + return -ENOSYS; + } + + if (bus->ioeventfd_grabbed == 0 && bus->ioeventfd_started) { + virtio_bus_stop_ioeventfd(bus); + /* Remember that we need to restart ioeventfd + * when ioeventfd_grabbed becomes zero. + */ + bus->ioeventfd_started = true; + } + bus->ioeventfd_grabbed++; + return 0; +} + +void virtio_bus_release_ioeventfd(VirtioBusState *bus) +{ + assert(bus->ioeventfd_grabbed != 0); + if (--bus->ioeventfd_grabbed == 0 && bus->ioeventfd_started) { + /* Force virtio_bus_start_ioeventfd to act. */ + bus->ioeventfd_started = false; + virtio_bus_start_ioeventfd(bus); + } +} + int virtio_bus_start_ioeventfd(VirtioBusState *bus) { VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus); @@ -161,10 +194,14 @@ int virtio_bus_start_ioeventfd(VirtioBusState *bus) if (bus->ioeventfd_started) { return 0; } - r = vdc->start_ioeventfd(vdev); - if (r < 0) { - error_report("%s: failed. Fallback to userspace (slower).", __func__); - return r; + + /* Only set our notifier if we have ownership. */ + if (!bus->ioeventfd_grabbed) { + r = vdc->start_ioeventfd(vdev); + if (r < 0) { + error_report("%s: failed. Fallback to userspace (slower).", __func__); + return r; + } } bus->ioeventfd_started = true; return 0; @@ -179,9 +216,12 @@ void virtio_bus_stop_ioeventfd(VirtioBusState *bus) return; } - vdev = virtio_bus_get_device(bus); - vdc = VIRTIO_DEVICE_GET_CLASS(vdev); - vdc->stop_ioeventfd(vdev); + /* Only remove our notifier if we have ownership. */ + if (!bus->ioeventfd_grabbed) { + vdev = virtio_bus_get_device(bus); + vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + vdc->stop_ioeventfd(vdev); + } bus->ioeventfd_started = false; } @@ -211,7 +251,6 @@ int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign) } if (assign) { - assert(!bus->ioeventfd_started); r = event_notifier_init(notifier, 1); if (r < 0) { error_report("%s: unable to init event notifier: %s (%d)", @@ -225,9 +264,6 @@ int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign) } return 0; } else { - if (!bus->ioeventfd_started) { - return 0; - } k->ioeventfd_assign(proxy, notifier, n, false); } |