Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2025 Intel Corporation 3 : : */ 4 : : 5 : : #ifndef _COMMON_INTEL_RECYCLE_MBUFS_H_ 6 : : #define _COMMON_INTEL_RECYCLE_MBUFS_H_ 7 : : 8 : : #include <stdint.h> 9 : : #include <unistd.h> 10 : : 11 : : #include <rte_mbuf.h> 12 : : #include <rte_io.h> 13 : : #include <ethdev_driver.h> 14 : : 15 : : #include "rx.h" 16 : : #include "tx.h" 17 : : 18 : : /** 19 : : * Recycle mbufs for Rx queue. 20 : : * 21 : : * @param rxq Rx queue pointer 22 : : * @param nb_mbufs number of mbufs to recycle 23 : : * @param desc_len length of Rx descriptor 24 : : */ 25 : : static __rte_always_inline void 26 : : ci_rx_recycle_mbufs(struct ci_rx_queue *rxq, const uint16_t nb_mbufs) 27 : : { 28 : : struct ci_rx_entry *rxep; 29 : : volatile union ci_rx_desc *rxdp; 30 : : uint16_t rx_id; 31 : : uint16_t i; 32 : : 33 : 0 : rxdp = rxq->rx_ring + rxq->rxrearm_start; 34 : 0 : rxep = &rxq->sw_ring[rxq->rxrearm_start]; 35 : : 36 [ # # ]: 0 : for (i = 0; i < nb_mbufs; i++) { 37 : 0 : struct rte_mbuf *mb = rxep[i].mbuf; 38 : : 39 : : #if RTE_IOVA_IN_MBUF 40 : 0 : const uint64_t iova = mb->buf_iova + RTE_PKTMBUF_HEADROOM; 41 : : const uint64_t dma_addr = rte_cpu_to_le_64(iova); 42 : : #else 43 : : const uint64_t vaddr = (uintptr_t)mb->buf_addr + RTE_PKTMBUF_HEADROOM; 44 : : const uint64_t dma_addr = rte_cpu_to_le_64(vaddr); 45 : : #endif 46 : : 47 : 0 : rxdp[i].read.hdr_addr = 0; 48 : 0 : rxdp[i].read.pkt_addr = dma_addr; 49 : : } 50 : : 51 : : /* Update the descriptor initializer index */ 52 : 0 : rxq->rxrearm_start += nb_mbufs; 53 : 0 : rx_id = rxq->rxrearm_start - 1; 54 : : 55 [ # # ]: 0 : if (unlikely(rxq->rxrearm_start >= rxq->nb_rx_desc)) { 56 : 0 : rxq->rxrearm_start = 0; 57 : 0 : rx_id = rxq->nb_rx_desc - 1; 58 : : } 59 : : 60 : 0 : rxq->rxrearm_nb -= nb_mbufs; 61 : : 62 : 0 : rte_io_wmb(); 63 : : 64 : : /* Update the tail pointer on the NIC */ 65 [ # # ]: 0 : rte_write32_wc_relaxed(rte_cpu_to_le_32(rx_id), rxq->qrx_tail); 66 : : } 67 : : 68 : : /** 69 : : * Recycle buffers on Tx. 70 : : * 71 : : * @param txq Tx queue pointer 72 : : * @param desc_done function to check if the Tx descriptor is done 73 : : * @param recycle_rxq_info recycling mbuf information 74 : : * 75 : : * @return how many buffers were recycled 76 : : */ 77 : : static __rte_always_inline uint16_t 78 : : ci_tx_recycle_mbufs(struct ci_tx_queue *txq, ci_desc_done_fn desc_done, 79 : : struct rte_eth_recycle_rxq_info *recycle_rxq_info) 80 : : { 81 : : struct ci_tx_entry *txep; 82 : : struct rte_mbuf **rxep; 83 : : int i, n; 84 : : uint16_t nb_recycle_mbufs; 85 : : uint16_t avail = 0; 86 : 0 : uint16_t mbuf_ring_size = recycle_rxq_info->mbuf_ring_size; 87 : 0 : uint16_t mask = recycle_rxq_info->mbuf_ring_size - 1; 88 : 0 : uint16_t refill_requirement = recycle_rxq_info->refill_requirement; 89 : 0 : uint16_t refill_head = *recycle_rxq_info->refill_head; 90 : 0 : uint16_t receive_tail = *recycle_rxq_info->receive_tail; 91 : : 92 : : /* Get available recycling Rx buffers. */ 93 : 0 : avail = (mbuf_ring_size - (refill_head - receive_tail)) & mask; 94 : : 95 : : /* Check Tx free thresh and Rx available space. */ 96 [ # # # # ]: 0 : if (txq->nb_tx_free > txq->tx_free_thresh || avail <= txq->tx_rs_thresh) 97 : : return 0; 98 : : 99 [ # # ]: 0 : if (!desc_done(txq, txq->tx_next_dd)) { 100 : : /* If the Tx descriptor is not done, we can not recycle 101 : : * buffers. 102 : : */ 103 : : return 0; 104 : : } 105 : : 106 : 0 : n = txq->tx_rs_thresh; 107 : : nb_recycle_mbufs = n; 108 : : 109 : : /* Mbufs recycle mode can only support no ring buffer wrapping around. 110 : : * Two case for this: 111 : : * 112 : : * case 1: The refill head of Rx buffer ring needs to be aligned with 113 : : * mbuf ring size. In this case, the number of Tx freeing buffers 114 : : * should be equal to refill_requirement. 115 : : * 116 : : * case 2: The refill head of Rx ring buffer does not need to be aligned 117 : : * with mbuf ring size. In this case, the update of refill head can not 118 : : * exceed the Rx mbuf ring size. 119 : : */ 120 [ # # # # : 0 : if ((refill_requirement && refill_requirement != n) || # # ] 121 [ # # ]: 0 : (!refill_requirement && (refill_head + n > mbuf_ring_size))) 122 : : return 0; 123 : : 124 : : /* First buffer to free from S/W ring is at index 125 : : * tx_next_dd - (tx_rs_thresh-1). 126 : : */ 127 : 0 : txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)]; 128 : 0 : rxep = recycle_rxq_info->mbuf_ring; 129 : 0 : rxep += refill_head; 130 : : 131 : : /* is fast-free enabled in offloads? */ 132 : : struct rte_mempool *fast_free_mp = 133 : 0 : likely(txq->fast_free_mp != (void *)UINTPTR_MAX) ? 134 [ # # ]: 0 : txq->fast_free_mp : 135 : 0 : (txq->fast_free_mp = txep[0].mbuf->pool); 136 : : 137 [ # # ]: 0 : if (fast_free_mp != NULL) { 138 : : /* Avoid txq containing buffers from unexpected mempool. */ 139 [ # # ]: 0 : if (unlikely(recycle_rxq_info->mp != fast_free_mp)) 140 : : return 0; 141 : : 142 : : /* Directly put mbufs from Tx to Rx. */ 143 [ # # ]: 0 : for (i = 0; i < n; i++) 144 : 0 : rxep[i] = txep[i].mbuf; 145 : : } else { 146 [ # # ]: 0 : for (i = 0; i < n; i++) { 147 [ # # ]: 0 : rxep[i] = rte_pktmbuf_prefree_seg(txep[i].mbuf); 148 : : 149 : : /* If Tx buffers are not the last reference or from 150 : : * unexpected mempool, previous copied buffers are 151 : : * considered as invalid. 152 : : */ 153 [ # # # # ]: 0 : if (unlikely(rxep[i] == NULL || 154 : : recycle_rxq_info->mp != txep[i].mbuf->pool)) 155 : : nb_recycle_mbufs = 0; 156 : : } 157 : : /* If Tx buffers are not the last reference or 158 : : * from unexpected mempool, all recycled buffers 159 : : * are put into mempool. 160 : : */ 161 [ # # ]: 0 : if (nb_recycle_mbufs == 0) 162 [ # # ]: 0 : for (i = 0; i < n; i++) { 163 [ # # ]: 0 : if (rxep[i] != NULL) 164 [ # # ]: 0 : rte_mempool_put(rxep[i]->pool, rxep[i]); 165 : : } 166 : : } 167 : : 168 : : /* Update counters for Tx. */ 169 : 0 : txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); 170 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); 171 [ # # ]: 0 : if (txq->tx_next_dd >= txq->nb_tx_desc) 172 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); 173 : : 174 : : return nb_recycle_mbufs; 175 : : } 176 : : 177 : : #endif