/* * This function handles both assigning the ioeventfd handler and * registering it with the kernel. * 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) { VirtIODevice *vdev = virtio_bus_get_device(bus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus); VirtQueue *vq = virtio_get_queue(vdev, n); EventNotifier *notifier = virtio_queue_get_host_notifier(vq); int r = 0; if (assign) { r = event_notifier_init(notifier, 1); if (r < 0) { error_report("%s: unable to init event notifier: %d", __func__, r); return r; } virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); r = k->ioeventfd_assign(proxy, notifier, n, assign); if (r < 0) { error_report("%s: unable to assign ioeventfd: %d", __func__, r); virtio_queue_set_host_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); return r; } } else { k->ioeventfd_assign(proxy, notifier, n, assign); virtio_queue_set_host_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); } return r; }
static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n, bool assign, bool set_handler) { VirtQueue *vq = virtio_get_queue(dev->vdev, n); EventNotifier *notifier = virtio_queue_get_host_notifier(vq); int r = 0; SubchDev *sch = dev->sch; uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid; if (assign) { r = event_notifier_init(notifier, 1); if (r < 0) { error_report("%s: unable to init event notifier: %d", __func__, r); return r; } virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); r = s390_assign_subch_ioeventfd(event_notifier_get_fd(notifier), sch_id, n, assign); if (r < 0) { error_report("%s: unable to assign ioeventfd: %d", __func__, r); virtio_queue_set_host_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); return r; } } else { virtio_queue_set_host_notifier_fd_handler(vq, false, false); s390_assign_subch_ioeventfd(event_notifier_get_fd(notifier), sch_id, n, assign); event_notifier_cleanup(notifier); } return r; }