virtio: fix kick race issue
[vpp.git] / src / vnet / devices / virtio / node.c
index e019513..d7a0b39 100644 (file)
@@ -87,17 +87,23 @@ virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring)
   u16 sz = vring->size;
   u16 mask = sz - 1;
 
+more:
   used = vring->desc_in_use;
 
   if (sz - used < sz / 8)
     return;
 
-  n_slots = sz - used;
+  /* deliver free buffers in chunks of 64 */
+  n_slots = clib_min (sz - used, 64);
+
   next = vring->desc_next;
   avail = vring->avail->idx;
   n_slots = vlib_buffer_alloc_to_ring (vm, vring->buffers, next, vring->size,
                                       n_slots);
 
+  if (n_slots == 0)
+    return;
+
   while (n_slots)
     {
       struct vring_desc *d = &vring->desc[next];;
@@ -117,10 +123,8 @@ virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring)
   vring->desc_in_use = used;
 
   if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
-    {
-      u64 b = 1;
-      CLIB_UNUSED (int r) = write (vring->kick_fd, &b, sizeof (b));
-    }
+    virtio_kick (vring);
+  goto more;
 }
 
 static_always_inline uword
@@ -140,6 +144,10 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
   u16 last = vring->last_used_idx;
   u16 n_left = vring->used->idx - last;
 
+  if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 &&
+      vring->last_kick_avail_idx != vring->avail->idx)
+    virtio_kick (vring);
+
   if (n_left == 0)
     goto refill;