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