From bcf55c93026ff1db8ff2838766bbaaa38741579e Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Mon, 11 Dec 2017 13:13:29 +0800 Subject: [PATCH] net/virtio: fix vector Rx flushing The vector Rx will be broken if backend has consumed all the descs in the avail ring before the device is started. Because in current implementation, vector Rx will return immediately without refilling the avail ring if the used ring is empty. So we have to refill the avail ring after flushing the elements in the used ring for vector Rx. Besides, vector Rx has a different ring layout assumption and mbuf management. So we need to handle it differently. Fixes: d8227497ec5c ("net/virtio: flush Rx queues on start") Cc: stable@dpdk.org Reported-by: Antonio Fischetti Signed-off-by: Tiwei Bie Reviewed-by: Maxime Coquelin Tested-by: Antonio Fischetti Acked-by: Yuanhan Liu --- drivers/net/virtio/virtio_ethdev.c | 2 +- drivers/net/virtio/virtqueue.c | 31 +++++++++++++++++++++++------- drivers/net/virtio/virtqueue.h | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 91321f9581..4b0fd854f1 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1831,7 +1831,7 @@ virtio_dev_start(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_rx_queues; i++) { rxvq = dev->data->rx_queues[i]; /* Flush the old packets */ - virtqueue_flush(rxvq->vq); + virtqueue_rxvq_flush(rxvq->vq); virtqueue_notify(rxvq->vq); } diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c index e6f60e6f61..1ada4fe08a 100644 --- a/drivers/net/virtio/virtqueue.c +++ b/drivers/net/virtio/virtqueue.c @@ -8,6 +8,7 @@ #include "virtqueue.h" #include "virtio_logs.h" #include "virtio_pci.h" +#include "virtio_rxtx_simple.h" /* * Two types of mbuf to be cleaned: @@ -33,8 +34,10 @@ virtqueue_detatch_unused(struct virtqueue *vq) /* Flush the elements in the used ring. */ void -virtqueue_flush(struct virtqueue *vq) +virtqueue_rxvq_flush(struct virtqueue *vq) { + struct virtnet_rx *rxq = &vq->rxq; + struct virtio_hw *hw = vq->hw; struct vring_used_elem *uep; struct vq_desc_extra *dxp; uint16_t used_idx, desc_idx; @@ -45,13 +48,27 @@ virtqueue_flush(struct virtqueue *vq) for (i = 0; i < nb_used; i++) { used_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1); uep = &vq->vq_ring.used->ring[used_idx]; - desc_idx = (uint16_t)uep->id; - dxp = &vq->vq_descx[desc_idx]; - if (dxp->cookie != NULL) { - rte_pktmbuf_free(dxp->cookie); - dxp->cookie = NULL; + if (hw->use_simple_rx) { + desc_idx = used_idx; + rte_pktmbuf_free(vq->sw_ring[desc_idx]); + vq->vq_free_cnt++; + } else { + desc_idx = (uint16_t)uep->id; + dxp = &vq->vq_descx[desc_idx]; + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + vq_ring_free_chain(vq, desc_idx); } vq->vq_used_cons_idx++; - vq_ring_free_chain(vq, desc_idx); + } + + if (hw->use_simple_rx) { + while (vq->vq_free_cnt >= RTE_VIRTIO_VPMD_RX_REARM_THRESH) { + virtio_rxq_rearm_vec(rxq); + if (virtqueue_kick_prepare(vq)) + virtqueue_notify(vq); + } } } diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 1482a951dd..33a0e18963 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -275,7 +275,7 @@ void virtqueue_dump(struct virtqueue *vq); struct rte_mbuf *virtqueue_detatch_unused(struct virtqueue *vq); /* Flush the elements in the used ring. */ -void virtqueue_flush(struct virtqueue *vq); +void virtqueue_rxvq_flush(struct virtqueue *vq); static inline int virtqueue_full(const struct virtqueue *vq) -- 2.20.1