diff options
Diffstat (limited to 'drivers/net/virtio/virtqueue.c')
-rw-r--r-- | drivers/net/virtio/virtqueue.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c index 4f8707ae..0e9e03c7 100644 --- a/drivers/net/virtio/virtqueue.c +++ b/drivers/net/virtio/virtqueue.c @@ -37,6 +37,7 @@ #include "virtqueue.h" #include "virtio_logs.h" #include "virtio_pci.h" +#include "virtio_rxtx_simple.h" void virtqueue_disable_intr(struct virtqueue *vq) @@ -55,26 +56,50 @@ virtqueue_disable_intr(struct virtqueue *vq) * 2) mbuf that hasn't been consued by backend. */ struct rte_mbuf * -virtqueue_detatch_unused(struct virtqueue *vq) +virtqueue_detach_unused(struct virtqueue *vq) { struct rte_mbuf *cookie; - int idx; + struct virtio_hw *hw; + uint16_t start, end; + int type, idx; - if (vq != NULL) - for (idx = 0; idx < vq->vq_nentries; idx++) { + if (vq == NULL) + return NULL; + + hw = vq->hw; + type = virtio_get_queue_type(hw, vq->vq_queue_index); + start = vq->vq_avail_idx & (vq->vq_nentries - 1); + end = (vq->vq_avail_idx + vq->vq_free_cnt) & (vq->vq_nentries - 1); + + for (idx = 0; idx < vq->vq_nentries; idx++) { + if (hw->use_simple_rxtx && type == VTNET_RQ) { + if (start <= end && idx >= start && idx < end) + continue; + if (start > end && (idx >= start || idx < end)) + continue; + cookie = vq->sw_ring[idx]; + if (cookie != NULL) { + vq->sw_ring[idx] = NULL; + return cookie; + } + } else { cookie = vq->vq_descx[idx].cookie; if (cookie != NULL) { vq->vq_descx[idx].cookie = NULL; return cookie; } } + } + return NULL; } /* 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; @@ -85,13 +110,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_rxtx) { + 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_rxtx) { + while (vq->vq_free_cnt >= RTE_VIRTIO_VPMD_RX_REARM_THRESH) { + virtio_rxq_rearm_vec(rxq); + if (virtqueue_kick_prepare(vq)) + virtqueue_notify(vq); + } } } |