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 [ # # ]: 0 : if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) { 133 : : /* Avoid txq containing buffers from unexpected mempool. */ 134 [ # # ]: 0 : if (unlikely(recycle_rxq_info->mp 135 : : != txep[0].mbuf->pool)) 136 : : return 0; 137 : : 138 : : /* Directly put mbufs from Tx to Rx. */ 139 [ # # ]: 0 : for (i = 0; i < n; i++) 140 : 0 : rxep[i] = txep[i].mbuf; 141 : : } else { 142 [ # # ]: 0 : for (i = 0; i < n; i++) { 143 [ # # ]: 0 : rxep[i] = rte_pktmbuf_prefree_seg(txep[i].mbuf); 144 : : 145 : : /* If Tx buffers are not the last reference or from 146 : : * unexpected mempool, previous copied buffers are 147 : : * considered as invalid. 148 : : */ 149 [ # # # # ]: 0 : if (unlikely(rxep[i] == NULL || 150 : : recycle_rxq_info->mp != txep[i].mbuf->pool)) 151 : : nb_recycle_mbufs = 0; 152 : : } 153 : : /* If Tx buffers are not the last reference or 154 : : * from unexpected mempool, all recycled buffers 155 : : * are put into mempool. 156 : : */ 157 [ # # ]: 0 : if (nb_recycle_mbufs == 0) 158 [ # # ]: 0 : for (i = 0; i < n; i++) { 159 [ # # ]: 0 : if (rxep[i] != NULL) 160 [ # # ]: 0 : rte_mempool_put(rxep[i]->pool, rxep[i]); 161 : : } 162 : : } 163 : : 164 : : /* Update counters for Tx. */ 165 : 0 : txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); 166 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); 167 [ # # ]: 0 : if (txq->tx_next_dd >= txq->nb_tx_desc) 168 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); 169 : : 170 : : return nb_recycle_mbufs; 171 : : } 172 : : 173 : : #endif