]> git.droids-corp.org - dpdk.git/commitdiff
net/virtio: fix vector Rx flushing
authorTiwei Bie <tiwei.bie@intel.com>
Mon, 11 Dec 2017 05:13:29 +0000 (13:13 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
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 <antonio.fischetti@intel.com>
Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Antonio Fischetti <antonio.fischetti@intel.com>
Acked-by: Yuanhan Liu <yliu@fridaylinux.org>
drivers/net/virtio/virtio_ethdev.c
drivers/net/virtio/virtqueue.c
drivers/net/virtio/virtqueue.h

index 91321f95813020e1ba905101cdc3bbd0a9560b3c..4b0fd854f17d2663f45ec27e907049510dd656f8 100644 (file)
@@ -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);
        }
 
index e6f60e6f61919e45b6bacb0b7184fe3107d4482b..1ada4fe08a5426218877e08bb62657037ef1e66b 100644 (file)
@@ -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);
+               }
        }
 }
index 1482a951dd65e47a5c83022bc1204a1d5465061c..33a0e1896391de0e9925fbb6b0c7640c6017e035 100644 (file)
@@ -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)