From a4270ea4ff79b46280dd542f4ab3eb45f8c9685a Mon Sep 17 00:00:00 2001 From: Jens Freimann Date: Fri, 11 Jan 2019 10:39:28 +0100 Subject: [PATCH] net/virtio: check head desc with correct wrap counter In virtio_pq_send_command() we check for a used descriptor and wait in an idle loop until it becomes used. We can't use vq->used_wrap_counter here to check for the first descriptor we made available because the ring could have wrapped. Let's use the used_wrap_counter that matches the state of the head descriptor. Fixes: ec194c2f1895 ("net/virtio: support packed queue in send command") Signed-off-by: Jens Freimann Reviewed-by: Maxime Coquelin --- drivers/net/virtio/virtio_ethdev.c | 11 ++++++----- drivers/net/virtio/virtqueue.h | 10 ++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 6d461180ce..ee5a98b7c0 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -149,7 +149,7 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, int head; struct vring_packed_desc *desc = vq->ring_packed.desc_packed; struct virtio_pmd_ctrl *result; - int wrap_counter; + bool avail_wrap_counter, used_wrap_counter; uint16_t flags; int sum = 0; int k; @@ -161,7 +161,8 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, * One RX packet for ACK. */ head = vq->vq_avail_idx; - wrap_counter = vq->avail_wrap_counter; + avail_wrap_counter = vq->avail_wrap_counter; + used_wrap_counter = vq->used_wrap_counter; desc[head].flags = VRING_DESC_F_NEXT; desc[head].addr = cvq->virtio_net_hdr_mem; desc[head].len = sizeof(struct virtio_net_ctrl_hdr); @@ -199,8 +200,8 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, VRING_DESC_F_USED(!vq->avail_wrap_counter); desc[vq->vq_avail_idx].flags = flags; flags = VRING_DESC_F_NEXT; - flags |= VRING_DESC_F_AVAIL(wrap_counter) | - VRING_DESC_F_USED(!wrap_counter); + flags |= VRING_DESC_F_AVAIL(avail_wrap_counter) | + VRING_DESC_F_USED(!avail_wrap_counter); desc[head].flags = flags; rte_smp_wmb(); @@ -216,7 +217,7 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, do { rte_rmb(); usleep(100); - } while (!desc_is_used(&desc[head], vq)); + } while (!__desc_is_used(&desc[head], used_wrap_counter)); /* now get used descriptors */ while (desc_is_used(&desc[vq->vq_used_cons_idx], vq)) { diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 123bec34f2..7fcde5643c 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -281,7 +281,7 @@ struct virtio_tx_region { }; static inline int -desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq) +__desc_is_used(struct vring_packed_desc *desc, bool wrap_counter) { uint16_t used, avail, flags; @@ -289,7 +289,13 @@ desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq) used = !!(flags & VRING_DESC_F_USED(1)); avail = !!(flags & VRING_DESC_F_AVAIL(1)); - return avail == used && used == vq->used_wrap_counter; + return avail == used && used == wrap_counter; +} + +static inline int +desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq) +{ + return __desc_is_used(desc, vq->used_wrap_counter); }