15566a3e3SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 25566a3e3SBruce Richardson * Copyright(c) 2010-2015 Intel Corporation 36c3169a3SBruce Richardson */ 46c3169a3SBruce Richardson #include <stdint.h> 56c3169a3SBruce Richardson 66c3169a3SBruce Richardson #include <rte_mbuf.h> 76c3169a3SBruce Richardson 86c3169a3SBruce Richardson #include "virtqueue.h" 96c3169a3SBruce Richardson #include "virtio_logs.h" 106c3169a3SBruce Richardson #include "virtio_pci.h" 11bcf55c93STiwei Bie #include "virtio_rxtx_simple.h" 126c3169a3SBruce Richardson 136c3169a3SBruce Richardson /* 146c3169a3SBruce Richardson * Two types of mbuf to be cleaned: 156c3169a3SBruce Richardson * 1) mbuf that has been consumed by backend but not used by virtio. 166c3169a3SBruce Richardson * 2) mbuf that hasn't been consued by backend. 176c3169a3SBruce Richardson */ 186c3169a3SBruce Richardson struct rte_mbuf * 19727411f5SOlivier Matz virtqueue_detach_unused(struct virtqueue *vq) 206c3169a3SBruce Richardson { 216c3169a3SBruce Richardson struct rte_mbuf *cookie; 22e67ae1e2SOlivier Matz struct virtio_hw *hw; 23e67ae1e2SOlivier Matz uint16_t start, end; 24e67ae1e2SOlivier Matz int type, idx; 256c3169a3SBruce Richardson 26e67ae1e2SOlivier Matz if (vq == NULL) 27e67ae1e2SOlivier Matz return NULL; 28e67ae1e2SOlivier Matz 29e67ae1e2SOlivier Matz hw = vq->hw; 30e67ae1e2SOlivier Matz type = virtio_get_queue_type(hw, vq->vq_queue_index); 31e67ae1e2SOlivier Matz start = vq->vq_avail_idx & (vq->vq_nentries - 1); 32e67ae1e2SOlivier Matz end = (vq->vq_avail_idx + vq->vq_free_cnt) & (vq->vq_nentries - 1); 33e67ae1e2SOlivier Matz 346c3169a3SBruce Richardson for (idx = 0; idx < vq->vq_nentries; idx++) { 35e67ae1e2SOlivier Matz if (hw->use_simple_rx && type == VTNET_RQ) { 36e67ae1e2SOlivier Matz if (start <= end && idx >= start && idx < end) 37e67ae1e2SOlivier Matz continue; 38e67ae1e2SOlivier Matz if (start > end && (idx >= start || idx < end)) 39e67ae1e2SOlivier Matz continue; 40e67ae1e2SOlivier Matz cookie = vq->sw_ring[idx]; 41e67ae1e2SOlivier Matz if (cookie != NULL) { 42e67ae1e2SOlivier Matz vq->sw_ring[idx] = NULL; 43e67ae1e2SOlivier Matz return cookie; 44e67ae1e2SOlivier Matz } 45e67ae1e2SOlivier Matz } else { 462f7fdb9dSBernard Iremonger cookie = vq->vq_descx[idx].cookie; 472f7fdb9dSBernard Iremonger if (cookie != NULL) { 486c3169a3SBruce Richardson vq->vq_descx[idx].cookie = NULL; 496c3169a3SBruce Richardson return cookie; 506c3169a3SBruce Richardson } 516c3169a3SBruce Richardson } 52e67ae1e2SOlivier Matz } 53e67ae1e2SOlivier Matz 546c3169a3SBruce Richardson return NULL; 556c3169a3SBruce Richardson } 56d8227497STiwei Bie 57a76290c8SJens Freimann /* Flush used descs */ 58a76290c8SJens Freimann static void 59a76290c8SJens Freimann virtqueue_rxvq_flush_packed(struct virtqueue *vq) 60a76290c8SJens Freimann { 61a76290c8SJens Freimann struct vq_desc_extra *dxp; 62a76290c8SJens Freimann uint16_t i; 63a76290c8SJens Freimann 64*4cdc4d98STiwei Bie struct vring_packed_desc *descs = vq->vq_packed.ring.desc; 65a76290c8SJens Freimann int cnt = 0; 66a76290c8SJens Freimann 67a76290c8SJens Freimann i = vq->vq_used_cons_idx; 68a76290c8SJens Freimann while (desc_is_used(&descs[i], vq) && cnt++ < vq->vq_nentries) { 69a76290c8SJens Freimann dxp = &vq->vq_descx[descs[i].id]; 70a76290c8SJens Freimann if (dxp->cookie != NULL) { 71a76290c8SJens Freimann rte_pktmbuf_free(dxp->cookie); 72a76290c8SJens Freimann dxp->cookie = NULL; 73a76290c8SJens Freimann } 74a76290c8SJens Freimann vq->vq_free_cnt++; 75a76290c8SJens Freimann vq->vq_used_cons_idx++; 76a76290c8SJens Freimann if (vq->vq_used_cons_idx >= vq->vq_nentries) { 77a76290c8SJens Freimann vq->vq_used_cons_idx -= vq->vq_nentries; 78dfd33aa4STiwei Bie vq->vq_packed.used_wrap_counter ^= 1; 79a76290c8SJens Freimann } 80a76290c8SJens Freimann i = vq->vq_used_cons_idx; 81a76290c8SJens Freimann } 82a76290c8SJens Freimann } 83a76290c8SJens Freimann 84d8227497STiwei Bie /* Flush the elements in the used ring. */ 85a76290c8SJens Freimann static void 86a76290c8SJens Freimann virtqueue_rxvq_flush_split(struct virtqueue *vq) 87d8227497STiwei Bie { 88bcf55c93STiwei Bie struct virtnet_rx *rxq = &vq->rxq; 89bcf55c93STiwei Bie struct virtio_hw *hw = vq->hw; 90d8227497STiwei Bie struct vring_used_elem *uep; 91d8227497STiwei Bie struct vq_desc_extra *dxp; 92d8227497STiwei Bie uint16_t used_idx, desc_idx; 93d8227497STiwei Bie uint16_t nb_used, i; 94d8227497STiwei Bie 95d8227497STiwei Bie nb_used = VIRTQUEUE_NUSED(vq); 96d8227497STiwei Bie 97d8227497STiwei Bie for (i = 0; i < nb_used; i++) { 98d8227497STiwei Bie used_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1); 99dfd33aa4STiwei Bie uep = &vq->vq_split.ring.used->ring[used_idx]; 100bcf55c93STiwei Bie if (hw->use_simple_rx) { 101bcf55c93STiwei Bie desc_idx = used_idx; 102bcf55c93STiwei Bie rte_pktmbuf_free(vq->sw_ring[desc_idx]); 103bcf55c93STiwei Bie vq->vq_free_cnt++; 1047097ca1bSMarvin Liu } else if (hw->use_inorder_rx) { 1057097ca1bSMarvin Liu desc_idx = (uint16_t)uep->id; 1067097ca1bSMarvin Liu dxp = &vq->vq_descx[desc_idx]; 1077097ca1bSMarvin Liu if (dxp->cookie != NULL) { 1087097ca1bSMarvin Liu rte_pktmbuf_free(dxp->cookie); 1097097ca1bSMarvin Liu dxp->cookie = NULL; 1107097ca1bSMarvin Liu } 1117097ca1bSMarvin Liu vq_ring_free_inorder(vq, desc_idx, 1); 112bcf55c93STiwei Bie } else { 113d8227497STiwei Bie desc_idx = (uint16_t)uep->id; 114d8227497STiwei Bie dxp = &vq->vq_descx[desc_idx]; 115d8227497STiwei Bie if (dxp->cookie != NULL) { 116d8227497STiwei Bie rte_pktmbuf_free(dxp->cookie); 117d8227497STiwei Bie dxp->cookie = NULL; 118d8227497STiwei Bie } 119d8227497STiwei Bie vq_ring_free_chain(vq, desc_idx); 120d8227497STiwei Bie } 121bcf55c93STiwei Bie vq->vq_used_cons_idx++; 122bcf55c93STiwei Bie } 123bcf55c93STiwei Bie 124bcf55c93STiwei Bie if (hw->use_simple_rx) { 125bcf55c93STiwei Bie while (vq->vq_free_cnt >= RTE_VIRTIO_VPMD_RX_REARM_THRESH) { 126bcf55c93STiwei Bie virtio_rxq_rearm_vec(rxq); 127bcf55c93STiwei Bie if (virtqueue_kick_prepare(vq)) 128bcf55c93STiwei Bie virtqueue_notify(vq); 129bcf55c93STiwei Bie } 130bcf55c93STiwei Bie } 131d8227497STiwei Bie } 132a76290c8SJens Freimann 133a76290c8SJens Freimann /* Flush the elements in the used ring. */ 134a76290c8SJens Freimann void 135a76290c8SJens Freimann virtqueue_rxvq_flush(struct virtqueue *vq) 136a76290c8SJens Freimann { 137a76290c8SJens Freimann struct virtio_hw *hw = vq->hw; 138a76290c8SJens Freimann 139a76290c8SJens Freimann if (vtpci_packed_queue(hw)) 140a76290c8SJens Freimann virtqueue_rxvq_flush_packed(vq); 141a76290c8SJens Freimann else 142a76290c8SJens Freimann virtqueue_rxvq_flush_split(vq); 143a76290c8SJens Freimann } 144