Commit b1f416aa authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Avi Kivity
Browse files

virtio: move common ioeventfd handling out of virtio-pci



All transports can use the same event handler for the ioeventfd, though
the exact setup (address/memory region) will be specific.

This lets virtio use event_notifier_set_handler.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 6bf819f0
Loading
Loading
Loading
Loading
+2 −34
Original line number Diff line number Diff line
@@ -173,46 +173,18 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
                         __func__, r);
            return r;
        }
        virtio_queue_set_host_notifier_fd_handler(vq, true);
        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
                                  true, n, notifier);
    } else {
        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
                                  true, n, notifier);
        /* Handle the race condition where the guest kicked and we deassigned
         * before we got around to handling the kick.
         */
        if (event_notifier_test_and_clear(notifier)) {
            virtio_queue_notify_vq(vq);
        }

        virtio_queue_set_host_notifier_fd_handler(vq, false);
        event_notifier_cleanup(notifier);
    }
    return r;
}

static void virtio_pci_host_notifier_read(void *opaque)
{
    VirtQueue *vq = opaque;
    EventNotifier *n = virtio_queue_get_host_notifier(vq);
    if (event_notifier_test_and_clear(n)) {
        virtio_queue_notify_vq(vq);
    }
}

static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
                                                    int n, bool assign)
{
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
    if (assign) {
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
                            virtio_pci_host_notifier_read, NULL, vq);
    } else {
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
                            NULL, NULL, NULL);
    }
}

static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
    int n, r;
@@ -232,8 +204,6 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
        if (r < 0) {
            goto assign_error;
        }

        virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
    }
    proxy->ioeventfd_started = true;
    return;
@@ -244,7 +214,6 @@ assign_error:
            continue;
        }

        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
        assert(r >= 0);
    }
@@ -266,7 +235,6 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
            continue;
        }

        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
        assert(r >= 0);
    }
+22 −0
Original line number Diff line number Diff line
@@ -988,6 +988,28 @@ EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
{
    return &vq->guest_notifier;
}

static void virtio_queue_host_notifier_read(EventNotifier *n)
{
    VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
    if (event_notifier_test_and_clear(n)) {
        virtio_queue_notify_vq(vq);
    }
}

void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign)
{
    if (assign) {
        event_notifier_set_handler(&vq->host_notifier,
                                   virtio_queue_host_notifier_read);
    } else {
        event_notifier_set_handler(&vq->host_notifier, NULL);
        /* Test and clear notifier before after disabling event,
         * in case poll callback didn't have time to run. */
        virtio_queue_host_notifier_read(&vq->host_notifier);
    }
}

EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
{
    return &vq->host_notifier;
+1 −0
Original line number Diff line number Diff line
@@ -232,6 +232,7 @@ VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
int virtio_queue_get_id(VirtQueue *vq);
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign);
void virtio_queue_notify_vq(VirtQueue *vq);
void virtio_irq(VirtQueue *vq);
#endif