X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fvirtio%2Fvirtqueue.c;h=5ff1e3587ebc1f8617e0a2a604737d5a971a599d;hb=e876497c4f6baef09fbee14b702025b67f4fed1c;hp=1ada4fe08a5426218877e08bb62657037ef1e66b;hpb=bcf55c93026ff1db8ff2838766bbaaa38741579e;p=dpdk.git diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c index 1ada4fe08a..5ff1e3587e 100644 --- a/drivers/net/virtio/virtqueue.c +++ b/drivers/net/virtio/virtqueue.c @@ -16,25 +16,74 @@ * 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_rx && 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 used descs */ +static void +virtqueue_rxvq_flush_packed(struct virtqueue *vq) +{ + struct vq_desc_extra *dxp; + uint16_t i; + + struct vring_packed_desc *descs = vq->vq_packed.ring.desc; + int cnt = 0; + + i = vq->vq_used_cons_idx; + while (desc_is_used(&descs[i], vq) && cnt++ < vq->vq_nentries) { + dxp = &vq->vq_descx[descs[i].id]; + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + vq->vq_free_cnt++; + vq->vq_used_cons_idx++; + if (vq->vq_used_cons_idx >= vq->vq_nentries) { + vq->vq_used_cons_idx -= vq->vq_nentries; + vq->vq_packed.used_wrap_counter ^= 1; + } + i = vq->vq_used_cons_idx; + } +} + /* Flush the elements in the used ring. */ -void -virtqueue_rxvq_flush(struct virtqueue *vq) +static void +virtqueue_rxvq_flush_split(struct virtqueue *vq) { struct virtnet_rx *rxq = &vq->rxq; struct virtio_hw *hw = vq->hw; @@ -47,11 +96,19 @@ virtqueue_rxvq_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]; + uep = &vq->vq_split.ring.used->ring[used_idx]; if (hw->use_simple_rx) { desc_idx = used_idx; rte_pktmbuf_free(vq->sw_ring[desc_idx]); vq->vq_free_cnt++; + } else if (hw->use_inorder_rx) { + 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_inorder(vq, desc_idx, 1); } else { desc_idx = (uint16_t)uep->id; dxp = &vq->vq_descx[desc_idx]; @@ -72,3 +129,15 @@ virtqueue_rxvq_flush(struct virtqueue *vq) } } } + +/* Flush the elements in the used ring. */ +void +virtqueue_rxvq_flush(struct virtqueue *vq) +{ + struct virtio_hw *hw = vq->hw; + + if (vtpci_packed_queue(hw)) + virtqueue_rxvq_flush_packed(vq); + else + virtqueue_rxvq_flush_split(vq); +}