From: Stefan Hajnoczi <[email protected]> The difference between these two functions: - virtio_notify() uses the interrupt code path (MSI or classic IRQs) - virtio_notify_irqfd() uses guest notifiers (irqfds)
virtio_notify() can only be called with the BQL held because the interrupt code path requires the BQL. Device models use virtio_notify_irqfd() from IOThreads since the BQL is not held. The two functions can be unified by pushing down the if (qemu_in_iothread()) check from virtio-blk and virtio-scsi into core virtio code. This is in preparation for the next commit that will add irqfd support to virtio_notify_config() and where it's unattractive to introduce another irqfd-only API for device model callers. Signed-off-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Reviewed-by: Michael S. Tsirkin <[email protected]> Message-ID: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> --- include/hw/virtio/virtio.h | 1 - hw/block/virtio-blk.c | 6 +----- hw/scsi/virtio-scsi.c | 6 +----- hw/virtio/virtio.c | 28 +++++++++++++--------------- hw/virtio/trace-events | 1 - 5 files changed, 15 insertions(+), 27 deletions(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 2aeb021fb3..d97529c3f1 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -294,7 +294,6 @@ int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, unsigned int *out_bytes, unsigned max_in_bytes, unsigned max_out_bytes); -void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq); void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); int virtio_save(VirtIODevice *vdev, QEMUFile *f); diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 9bab2716c1..64efce4846 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -62,11 +62,7 @@ void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) iov_discard_undo(&req->inhdr_undo); iov_discard_undo(&req->outhdr_undo); virtqueue_push(req->vq, &req->elem, req->in_len); - if (qemu_in_iothread()) { - virtio_notify_irqfd(vdev, req->vq); - } else { - virtio_notify(vdev, req->vq); - } + virtio_notify(vdev, req->vq); } static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 34ae14f7bf..d817fc42b4 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -116,11 +116,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req, QemuMutex *vq_lock) } virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size); - if (s->dataplane_started && !s->dataplane_fenced) { - virtio_notify_irqfd(vdev, vq); - } else { - virtio_notify(vdev, vq); - } + virtio_notify(vdev, vq); if (vq_lock) { qemu_mutex_unlock(vq_lock); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 34f977a3c9..6ce5823898 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -31,6 +31,7 @@ #include "hw/qdev-properties.h" #include "hw/virtio/virtio-access.h" #include "system/dma.h" +#include "system/iothread.h" #include "system/runstate.h" #include "virtio-qmp.h" @@ -2654,16 +2655,8 @@ static void virtio_notify_irqfd_deferred_fn(void *opaque) event_notifier_set(notifier); } -void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq) +static void virtio_irq(VirtQueue *vq) { - WITH_RCU_READ_LOCK_GUARD() { - if (!virtio_should_notify(vdev, vq)) { - return; - } - } - - trace_virtio_notify_irqfd(vdev, vq); - /* * virtio spec 1.0 says ISR bit 0 should be ignored with MSI, but * windows drivers included in virtio-win 1.8.0 (circa 2015) are @@ -2680,13 +2673,18 @@ void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq) * to an atomic operation. */ virtio_set_isr(vq->vdev, 0x1); - defer_call(virtio_notify_irqfd_deferred_fn, &vq->guest_notifier); -} -static void virtio_irq(VirtQueue *vq) -{ - virtio_set_isr(vq->vdev, 0x1); - virtio_notify_vector(vq->vdev, vq->vector); + /* + * The interrupt code path requires the Big QEMU Lock (BQL), so use the + * notifier instead when in an IOThread. This assumes that device models + * have already called ->set_guest_notifiers() sometime before calling this + * function. + */ + if (qemu_in_iothread()) { + defer_call(virtio_notify_irqfd_deferred_fn, &vq->guest_notifier); + } else { + virtio_notify_vector(vq->vdev, vq->vector); + } } void virtio_notify(VirtIODevice *vdev, VirtQueue *vq) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 76f0d458b2..658cc365e7 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -75,7 +75,6 @@ virtqueue_flush(void *vq, unsigned int count) "vq %p count %u" virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u" virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p" virtio_notify_irqfd_deferred_fn(void *vdev, void *vq) "vdev %p vq %p" -virtio_notify_irqfd(void *vdev, void *vq) "vdev %p vq %p" virtio_notify(void *vdev, void *vq) "vdev %p vq %p" virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u" -- MST
