virtio: fix kick race issue
Change-Id: I25b2a28513821bc5eab9ac6890a3964d412b0399 Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
Damjan Marion
committed by
Damjan Marion
parent
294afe297c
commit
e40231b1ec
@ -169,7 +169,6 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_vring_t * vring, u32 bi,
|
||||
return n_added;
|
||||
}
|
||||
|
||||
|
||||
static_always_inline uword
|
||||
virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame, virtio_if_t * vif)
|
||||
@ -184,6 +183,10 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
|
||||
clib_spinlock_lock_if_init (&vif->lockp);
|
||||
|
||||
if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 &&
|
||||
vring->last_kick_avail_idx != vring->avail->idx)
|
||||
virtio_kick (vring);
|
||||
|
||||
/* free consumed buffers */
|
||||
virtio_free_used_desc (vm, vring);
|
||||
|
||||
@ -209,10 +212,7 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vring->desc_next = next;
|
||||
vring->desc_in_use = used;
|
||||
if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
|
||||
{
|
||||
u64 x = 1;
|
||||
CLIB_UNUSED (int r) = write (vring->kick_fd, &x, sizeof (x));
|
||||
}
|
||||
virtio_kick (vring);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -87,6 +87,7 @@ typedef struct
|
||||
u32 call_file_index;
|
||||
u32 *buffers;
|
||||
u16 last_used_idx;
|
||||
u16 last_kick_avail_idx;
|
||||
} virtio_vring_t;
|
||||
|
||||
typedef struct
|
||||
@ -137,6 +138,16 @@ extern void virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring);
|
||||
|
||||
format_function_t format_virtio_device_name;
|
||||
|
||||
static_always_inline void
|
||||
virtio_kick (virtio_vring_t * vring)
|
||||
{
|
||||
u64 x = 1;
|
||||
int __clib_unused r;
|
||||
|
||||
r = write (vring->kick_fd, &x, sizeof (x));
|
||||
vring->last_kick_avail_idx = vring->avail->idx;
|
||||
}
|
||||
|
||||
#endif /* _VNET_DEVICES_VIRTIO_VIRTIO_H_ */
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user