vhost: fix interrupt suppression for the split ring
authorJiayu Hu <jiayu.hu@intel.com>
Sun, 17 Mar 2019 06:38:32 +0000 (14:38 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 20 Mar 2019 17:15:42 +0000 (18:15 +0100)
The VIRTIO_RING_F_EVENT_IDX feature of split ring might
be broken, as the value of signalled_used is invalid
after live migration, start up and virtio driver reload.
This patch fixes it by using signalled_used_valid.

In addition, this patch makes the VIRTIO_RING_F_EVENT_IDX
implementation of split ring match kernel backend to suppress
more interrupts.

Fixes: e37ff954405a ("vhost: support virtqueue interrupt/notification suppression")
Cc: stable@dpdk.org
Signed-off-by: Jiayu Hu <jiayu.hu@intel.com>
Tested-by: Yinan Wang <yinan.wang@intel.com>
Reviewed-by: Tiwei Bie <tiwei.bie@intel.com>
lib/librte_vhost/vhost.h
lib/librte_vhost/vhost_user.c

index f008ec4..e9138df 100644 (file)
@@ -633,16 +633,20 @@ vhost_vring_call_split(struct virtio_net *dev, struct vhost_virtqueue *vq)
        if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX)) {
                uint16_t old = vq->signalled_used;
                uint16_t new = vq->last_used_idx;
+               bool signalled_used_valid = vq->signalled_used_valid;
+
+               vq->signalled_used = new;
+               vq->signalled_used_valid = true;
 
                VHOST_LOG_DEBUG(VHOST_DATA, "%s: used_event_idx=%d, old=%d, new=%d\n",
                        __func__,
                        vhost_used_event(vq),
                        old, new);
-               if (vhost_need_event(vhost_used_event(vq), new, old)
-                       && (vq->callfd >= 0)) {
-                       vq->signalled_used = vq->last_used_idx;
+
+               if ((vhost_need_event(vhost_used_event(vq), new, old) &&
+                                       (vq->callfd >= 0)) ||
+                               unlikely(!signalled_used_valid))
                        eventfd_write(vq->callfd, (eventfd_t) 1);
-               }
        } else {
                /* Kick the guest if necessary. */
                if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
index 555d09a..4f21576 100644 (file)
@@ -1298,6 +1298,8 @@ vhost_user_get_vring_base(struct virtio_net **pdev,
 
        vq->callfd = VIRTIO_UNINITIALIZED_EVENTFD;
 
+       vq->signalled_used_valid = false;
+
        if (dev->dequeue_zero_copy)
                free_zmbufs(vq);
        if (vq_is_packed(dev)) {