Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (c) 2023 Arm Limited. 3 : : */ 4 : : 5 : : #include <stdint.h> 6 : : #include <ethdev_driver.h> 7 : : 8 : : #include "base/i40e_prototype.h" 9 : : #include "base/i40e_type.h" 10 : : #include "i40e_ethdev.h" 11 : : #include "i40e_rxtx.h" 12 : : 13 : : #pragma GCC diagnostic ignored "-Wcast-qual" 14 : : 15 : : void 16 : 0 : i40e_recycle_rx_descriptors_refill_vec(void *rx_queue, uint16_t nb_mbufs) 17 : : { 18 : : struct i40e_rx_queue *rxq = rx_queue; 19 : : struct i40e_rx_entry *rxep; 20 : : volatile union i40e_rx_desc *rxdp; 21 : : uint16_t rx_id; 22 : : uint64_t paddr; 23 : : uint64_t dma_addr; 24 : : uint16_t i; 25 : : 26 : 0 : rxdp = rxq->rx_ring + rxq->rxrearm_start; 27 : 0 : rxep = &rxq->sw_ring[rxq->rxrearm_start]; 28 : : 29 [ # # ]: 0 : for (i = 0; i < nb_mbufs; i++) { 30 : : /* Initialize rxdp descs. */ 31 : 0 : paddr = (rxep[i].mbuf)->buf_iova + RTE_PKTMBUF_HEADROOM; 32 : : dma_addr = rte_cpu_to_le_64(paddr); 33 : : /* flush desc with pa dma_addr */ 34 : 0 : rxdp[i].read.hdr_addr = 0; 35 : 0 : rxdp[i].read.pkt_addr = dma_addr; 36 : : } 37 : : 38 : : /* Update the descriptor initializer index */ 39 : 0 : rxq->rxrearm_start += nb_mbufs; 40 : 0 : rx_id = rxq->rxrearm_start - 1; 41 : : 42 [ # # ]: 0 : if (unlikely(rxq->rxrearm_start >= rxq->nb_rx_desc)) { 43 : 0 : rxq->rxrearm_start = 0; 44 : 0 : rx_id = rxq->nb_rx_desc - 1; 45 : : } 46 : : 47 : 0 : rxq->rxrearm_nb -= nb_mbufs; 48 : : 49 : 0 : rte_io_wmb(); 50 : : /* Update the tail pointer on the NIC */ 51 : 0 : I40E_PCI_REG_WRITE_RELAXED(rxq->qrx_tail, rx_id); 52 : 0 : } 53 : : 54 : : uint16_t 55 : 0 : i40e_recycle_tx_mbufs_reuse_vec(void *tx_queue, 56 : : struct rte_eth_recycle_rxq_info *recycle_rxq_info) 57 : : { 58 : : struct i40e_tx_queue *txq = tx_queue; 59 : : struct i40e_tx_entry *txep; 60 : : struct rte_mbuf **rxep; 61 : : int i, n; 62 : : uint16_t nb_recycle_mbufs; 63 : : uint16_t avail = 0; 64 : 0 : uint16_t mbuf_ring_size = recycle_rxq_info->mbuf_ring_size; 65 : 0 : uint16_t mask = recycle_rxq_info->mbuf_ring_size - 1; 66 : 0 : uint16_t refill_requirement = recycle_rxq_info->refill_requirement; 67 : 0 : uint16_t refill_head = *recycle_rxq_info->refill_head; 68 : 0 : uint16_t receive_tail = *recycle_rxq_info->receive_tail; 69 : : 70 : : /* Get available recycling Rx buffers. */ 71 : 0 : avail = (mbuf_ring_size - (refill_head - receive_tail)) & mask; 72 : : 73 : : /* Check Tx free thresh and Rx available space. */ 74 [ # # # # ]: 0 : if (txq->nb_tx_free > txq->tx_free_thresh || avail <= txq->tx_rs_thresh) 75 : : return 0; 76 : : 77 : : /* check DD bits on threshold descriptor */ 78 [ # # ]: 0 : if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz & 79 : : rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) != 80 : : rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) 81 : : return 0; 82 : : 83 : 0 : n = txq->tx_rs_thresh; 84 : : nb_recycle_mbufs = n; 85 : : 86 : : /* Mbufs recycle mode can only support no ring buffer wrapping around. 87 : : * Two case for this: 88 : : * 89 : : * case 1: The refill head of Rx buffer ring needs to be aligned with 90 : : * mbuf ring size. In this case, the number of Tx freeing buffers 91 : : * should be equal to refill_requirement. 92 : : * 93 : : * case 2: The refill head of Rx ring buffer does not need to be aligned 94 : : * with mbuf ring size. In this case, the update of refill head can not 95 : : * exceed the Rx mbuf ring size. 96 : : */ 97 [ # # # # : 0 : if ((refill_requirement && refill_requirement != n) || # # ] 98 [ # # ]: 0 : (!refill_requirement && (refill_head + n > mbuf_ring_size))) 99 : : return 0; 100 : : 101 : : /* First buffer to free from S/W ring is at index 102 : : * tx_next_dd - (tx_rs_thresh-1). 103 : : */ 104 : 0 : txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)]; 105 : 0 : rxep = recycle_rxq_info->mbuf_ring; 106 : 0 : rxep += refill_head; 107 : : 108 [ # # ]: 0 : if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) { 109 : : /* Avoid txq contains buffers from unexpected mempool. */ 110 [ # # ]: 0 : if (unlikely(recycle_rxq_info->mp 111 : : != txep[0].mbuf->pool)) 112 : : return 0; 113 : : 114 : : /* Directly put mbufs from Tx to Rx. */ 115 [ # # ]: 0 : for (i = 0; i < n; i++) 116 : 0 : rxep[i] = txep[i].mbuf; 117 : : } else { 118 [ # # ]: 0 : for (i = 0; i < n; i++) { 119 [ # # ]: 0 : rxep[i] = rte_pktmbuf_prefree_seg(txep[i].mbuf); 120 : : 121 : : /* If Tx buffers are not the last reference or from 122 : : * unexpected mempool, previous copied buffers are 123 : : * considered as invalid. 124 : : */ 125 [ # # # # ]: 0 : if (unlikely(rxep[i] == NULL || 126 : : recycle_rxq_info->mp != txep[i].mbuf->pool)) 127 : : nb_recycle_mbufs = 0; 128 : : } 129 : : /* If Tx buffers are not the last reference or 130 : : * from unexpected mempool, all recycled buffers 131 : : * are put into mempool. 132 : : */ 133 [ # # ]: 0 : if (nb_recycle_mbufs == 0) 134 [ # # ]: 0 : for (i = 0; i < n; i++) { 135 [ # # ]: 0 : if (rxep[i] != NULL) 136 [ # # ]: 0 : rte_mempool_put(rxep[i]->pool, rxep[i]); 137 : : } 138 : : } 139 : : 140 : : /* Update counters for Tx. */ 141 : 0 : txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); 142 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); 143 [ # # ]: 0 : if (txq->tx_next_dd >= txq->nb_tx_desc) 144 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); 145 : : 146 : : return nb_recycle_mbufs; 147 : : }