From: Huawei Xie Date: Sun, 19 Jun 2016 17:48:52 +0000 (+0800) Subject: net/virtio: fix used index retrieved only once X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=b81026f1e71887999ee60eb1f2fc94988f869f21;p=dpdk.git net/virtio: fix used index retrieved only once In the following loop: while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { ... } There is no external function call or any explict memory barrier in the loop, the re-read of used->idx might be optimized and only be retrieved once. Use of voaltile normally should be prohibited, and access_once is Linux kernel's style to handle this issue; Once we have that macro in DPDK, we could change to that style. virtio_recv_mergable_pkts might also have the same issue, so fix it as well. Fixes: 823ad647950a ("virtio: support multiple queues") Fixes: 13ce5e7eb94f ("virtio: mergeable buffers") Signed-off-by: Huawei Xie Acked-by: Yuanhan Liu --- diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 12fa6403ae..c89fa9f6b8 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -222,12 +222,12 @@ virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, virtqueue_notify(vq); rte_rmb(); - while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { + while (VIRTQUEUE_NUSED(vq) == 0) { rte_rmb(); usleep(100); } - while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { + while (VIRTQUEUE_NUSED(vq)) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; diff --git a/drivers/net/virtio/virtio_ring.h b/drivers/net/virtio/virtio_ring.h index 447760a8e5..fcecc1614c 100644 --- a/drivers/net/virtio/virtio_ring.h +++ b/drivers/net/virtio/virtio_ring.h @@ -79,7 +79,7 @@ struct vring_used_elem { struct vring_used { uint16_t flags; - uint16_t idx; + volatile uint16_t idx; struct vring_used_elem ring[0]; }; diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index 7b50119f46..242ad90d06 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -184,8 +184,7 @@ virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, if (unlikely(nb_pkts < RTE_VIRTIO_DESC_PER_LOOP)) return 0; - nb_used = *(volatile uint16_t *)&vq->vq_ring.used->idx - - vq->vq_used_cons_idx; + nb_used = VIRTQUEUE_NUSED(vq); rte_compiler_barrier();