1a9643ea8Slogwang /*- 2a9643ea8Slogwang * BSD LICENSE 3a9643ea8Slogwang * 4a9643ea8Slogwang * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. 5a9643ea8Slogwang * All rights reserved. 6a9643ea8Slogwang * 7a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 8a9643ea8Slogwang * modification, are permitted provided that the following conditions 9a9643ea8Slogwang * are met: 10a9643ea8Slogwang * 11a9643ea8Slogwang * * Redistributions of source code must retain the above copyright 12a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 13a9643ea8Slogwang * * Redistributions in binary form must reproduce the above copyright 14a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in 15a9643ea8Slogwang * the documentation and/or other materials provided with the 16a9643ea8Slogwang * distribution. 17a9643ea8Slogwang * * Neither the name of Intel Corporation nor the names of its 18a9643ea8Slogwang * contributors may be used to endorse or promote products derived 19a9643ea8Slogwang * from this software without specific prior written permission. 20a9643ea8Slogwang * 21a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22a9643ea8Slogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23a9643ea8Slogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24a9643ea8Slogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25a9643ea8Slogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26a9643ea8Slogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27a9643ea8Slogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28a9643ea8Slogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29a9643ea8Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31a9643ea8Slogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32a9643ea8Slogwang */ 33a9643ea8Slogwang #include <stdint.h> 34a9643ea8Slogwang 35a9643ea8Slogwang #include <rte_mbuf.h> 36a9643ea8Slogwang 37a9643ea8Slogwang #include "virtqueue.h" 38a9643ea8Slogwang #include "virtio_logs.h" 39a9643ea8Slogwang #include "virtio_pci.h" 40*2bfe3f2eSlogwang #include "virtio_rxtx_simple.h" 41a9643ea8Slogwang 42a9643ea8Slogwang /* 43a9643ea8Slogwang * Two types of mbuf to be cleaned: 44a9643ea8Slogwang * 1) mbuf that has been consumed by backend but not used by virtio. 45a9643ea8Slogwang * 2) mbuf that hasn't been consued by backend. 46a9643ea8Slogwang */ 47a9643ea8Slogwang struct rte_mbuf * 48a9643ea8Slogwang virtqueue_detatch_unused(struct virtqueue *vq) 49a9643ea8Slogwang { 50a9643ea8Slogwang struct rte_mbuf *cookie; 51*2bfe3f2eSlogwang struct virtio_hw *hw; 52*2bfe3f2eSlogwang uint16_t start, end; 53*2bfe3f2eSlogwang int type, idx; 54a9643ea8Slogwang 55*2bfe3f2eSlogwang if (vq == NULL) 56*2bfe3f2eSlogwang return NULL; 57*2bfe3f2eSlogwang 58*2bfe3f2eSlogwang hw = vq->hw; 59*2bfe3f2eSlogwang type = virtio_get_queue_type(hw, vq->vq_queue_index); 60*2bfe3f2eSlogwang start = vq->vq_avail_idx & (vq->vq_nentries - 1); 61*2bfe3f2eSlogwang end = (vq->vq_avail_idx + vq->vq_free_cnt) & (vq->vq_nentries - 1); 62*2bfe3f2eSlogwang 63a9643ea8Slogwang for (idx = 0; idx < vq->vq_nentries; idx++) { 64*2bfe3f2eSlogwang if (hw->use_simple_rx && type == VTNET_RQ) { 65*2bfe3f2eSlogwang if (start <= end && idx >= start && idx < end) 66*2bfe3f2eSlogwang continue; 67*2bfe3f2eSlogwang if (start > end && (idx >= start || idx < end)) 68*2bfe3f2eSlogwang continue; 69*2bfe3f2eSlogwang cookie = vq->sw_ring[idx]; 70*2bfe3f2eSlogwang if (cookie != NULL) { 71*2bfe3f2eSlogwang vq->sw_ring[idx] = NULL; 72*2bfe3f2eSlogwang return cookie; 73*2bfe3f2eSlogwang } 74*2bfe3f2eSlogwang } else { 75a9643ea8Slogwang cookie = vq->vq_descx[idx].cookie; 76a9643ea8Slogwang if (cookie != NULL) { 77a9643ea8Slogwang vq->vq_descx[idx].cookie = NULL; 78a9643ea8Slogwang return cookie; 79a9643ea8Slogwang } 80a9643ea8Slogwang } 81*2bfe3f2eSlogwang } 82*2bfe3f2eSlogwang 83a9643ea8Slogwang return NULL; 84a9643ea8Slogwang } 85*2bfe3f2eSlogwang 86*2bfe3f2eSlogwang /* Flush the elements in the used ring. */ 87*2bfe3f2eSlogwang void 88*2bfe3f2eSlogwang virtqueue_rxvq_flush(struct virtqueue *vq) 89*2bfe3f2eSlogwang { 90*2bfe3f2eSlogwang struct virtnet_rx *rxq = &vq->rxq; 91*2bfe3f2eSlogwang struct virtio_hw *hw = vq->hw; 92*2bfe3f2eSlogwang struct vring_used_elem *uep; 93*2bfe3f2eSlogwang struct vq_desc_extra *dxp; 94*2bfe3f2eSlogwang uint16_t used_idx, desc_idx; 95*2bfe3f2eSlogwang uint16_t nb_used, i; 96*2bfe3f2eSlogwang 97*2bfe3f2eSlogwang nb_used = VIRTQUEUE_NUSED(vq); 98*2bfe3f2eSlogwang 99*2bfe3f2eSlogwang for (i = 0; i < nb_used; i++) { 100*2bfe3f2eSlogwang used_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1); 101*2bfe3f2eSlogwang uep = &vq->vq_ring.used->ring[used_idx]; 102*2bfe3f2eSlogwang if (hw->use_simple_rx) { 103*2bfe3f2eSlogwang desc_idx = used_idx; 104*2bfe3f2eSlogwang rte_pktmbuf_free(vq->sw_ring[desc_idx]); 105*2bfe3f2eSlogwang vq->vq_free_cnt++; 106*2bfe3f2eSlogwang } else { 107*2bfe3f2eSlogwang desc_idx = (uint16_t)uep->id; 108*2bfe3f2eSlogwang dxp = &vq->vq_descx[desc_idx]; 109*2bfe3f2eSlogwang if (dxp->cookie != NULL) { 110*2bfe3f2eSlogwang rte_pktmbuf_free(dxp->cookie); 111*2bfe3f2eSlogwang dxp->cookie = NULL; 112*2bfe3f2eSlogwang } 113*2bfe3f2eSlogwang vq_ring_free_chain(vq, desc_idx); 114*2bfe3f2eSlogwang } 115*2bfe3f2eSlogwang vq->vq_used_cons_idx++; 116*2bfe3f2eSlogwang } 117*2bfe3f2eSlogwang 118*2bfe3f2eSlogwang if (hw->use_simple_rx) { 119*2bfe3f2eSlogwang while (vq->vq_free_cnt >= RTE_VIRTIO_VPMD_RX_REARM_THRESH) { 120*2bfe3f2eSlogwang virtio_rxq_rearm_vec(rxq); 121*2bfe3f2eSlogwang if (virtqueue_kick_prepare(vq)) 122*2bfe3f2eSlogwang virtqueue_notify(vq); 123*2bfe3f2eSlogwang } 124*2bfe3f2eSlogwang } 125*2bfe3f2eSlogwang } 126