Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(C) 2023 Marvell. 3 : : */ 4 : : 5 : : #include <rte_vect.h> 6 : : 7 : : #include "otx_ep_common.h" 8 : : #include "otx2_ep_vf.h" 9 : : #include "otx_ep_rxtx.h" 10 : : 11 : : #define CNXK_EP_OQ_DESC_PER_LOOP_SSE 4 12 : : #define CNXK_EP_OQ_DESC_PER_LOOP_AVX 8 13 : : 14 : : static inline int 15 : 0 : cnxk_ep_rx_refill_mbuf(struct otx_ep_droq *droq, uint32_t count) 16 : : { 17 : 0 : struct otx_ep_droq_desc *desc_ring = droq->desc_ring; 18 : 0 : struct rte_mbuf **recv_buf_list = droq->recv_buf_list; 19 : 0 : uint32_t refill_idx = droq->refill_idx; 20 : : struct rte_mbuf *buf; 21 : : uint32_t i; 22 : : int rc; 23 : : 24 [ # # ]: 0 : rc = rte_mempool_get_bulk(droq->mpool, (void **)&recv_buf_list[refill_idx], count); 25 [ # # ]: 0 : if (unlikely(rc)) { 26 : 0 : droq->stats.rx_alloc_failure++; 27 : 0 : return rc; 28 : : } 29 : : 30 [ # # ]: 0 : for (i = 0; i < count; i++) { 31 : 0 : rte_prefetch_non_temporal(&desc_ring[(refill_idx + 1) & 3]); 32 [ # # ]: 0 : if (i < count - 1) 33 : 0 : rte_prefetch_non_temporal(recv_buf_list[refill_idx + 1]); 34 : 0 : buf = recv_buf_list[refill_idx]; 35 : 0 : desc_ring[refill_idx].buffer_ptr = rte_mbuf_data_iova_default(buf); 36 : : refill_idx++; 37 : : } 38 : : 39 : 0 : droq->refill_idx = otx_ep_incr_index(droq->refill_idx, count, droq->nb_desc); 40 : 0 : droq->refill_count -= count; 41 : : 42 : 0 : return 0; 43 : : } 44 : : 45 : : static inline void 46 : 0 : cnxk_ep_rx_refill(struct otx_ep_droq *droq) 47 : : { 48 : 0 : const uint32_t nb_desc = droq->nb_desc; 49 : 0 : uint32_t refill_idx = droq->refill_idx; 50 : : uint32_t desc_refilled = 0, count; 51 : : int rc; 52 : : 53 [ # # ]: 0 : if (unlikely(droq->read_idx == refill_idx)) 54 : : return; 55 : : 56 [ # # ]: 0 : if (refill_idx < droq->read_idx) { 57 : 0 : count = droq->read_idx - refill_idx; 58 : 0 : rc = cnxk_ep_rx_refill_mbuf(droq, count); 59 [ # # ]: 0 : if (unlikely(rc)) { 60 : 0 : droq->stats.rx_alloc_failure++; 61 : 0 : return; 62 : : } 63 : : desc_refilled = count; 64 : : } else { 65 : 0 : count = nb_desc - refill_idx; 66 : 0 : rc = cnxk_ep_rx_refill_mbuf(droq, count); 67 [ # # ]: 0 : if (unlikely(rc)) { 68 : 0 : droq->stats.rx_alloc_failure++; 69 : 0 : return; 70 : : } 71 : : 72 : : desc_refilled = count; 73 : 0 : count = droq->read_idx; 74 : 0 : rc = cnxk_ep_rx_refill_mbuf(droq, count); 75 [ # # ]: 0 : if (unlikely(rc)) { 76 : 0 : droq->stats.rx_alloc_failure++; 77 : 0 : return; 78 : : } 79 : 0 : desc_refilled += count; 80 : : } 81 : : 82 : : /* Flush the droq descriptor data to memory to be sure 83 : : * that when we update the credits the data in memory is 84 : : * accurate. 85 : : */ 86 : 0 : rte_io_wmb(); 87 : 0 : rte_write32(desc_refilled, droq->pkts_credit_reg); 88 : : } 89 : : 90 : : static inline uint32_t 91 : 0 : cnxk_ep_check_rx_ism_mem(void *rx_queue) 92 : : { 93 : : struct otx_ep_droq *droq = (struct otx_ep_droq *)rx_queue; 94 : : uint32_t new_pkts; 95 : : uint32_t val; 96 : : 97 : : /* Batch subtractions from the HW counter to reduce PCIe traffic 98 : : * This adds an extra local variable, but almost halves the 99 : : * number of PCIe writes. 100 : : */ 101 : 0 : val = __atomic_load_n(droq->pkts_sent_ism, __ATOMIC_RELAXED); 102 : : 103 : 0 : new_pkts = val - droq->pkts_sent_prev; 104 : 0 : droq->pkts_sent_prev = val; 105 : : 106 [ # # ]: 0 : if (val > RTE_BIT32(31)) { 107 : : /* Only subtract the packet count in the HW counter 108 : : * when count above halfway to saturation. 109 : : */ 110 : 0 : rte_write64((uint64_t)val, droq->pkts_sent_reg); 111 : : rte_mb(); 112 : : 113 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 114 [ # # ]: 0 : while (__atomic_load_n(droq->pkts_sent_ism, __ATOMIC_RELAXED) >= val) { 115 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 116 : : rte_mb(); 117 : : } 118 : 0 : droq->pkts_sent_prev = 0; 119 : : } 120 : : 121 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 122 : : 123 : 0 : return new_pkts; 124 : : } 125 : : 126 : : static inline uint32_t 127 : 0 : cnxk_ep_check_rx_pkt_reg(void *rx_queue) 128 : : { 129 : : struct otx_ep_droq *droq = (struct otx_ep_droq *)rx_queue; 130 : : uint32_t new_pkts; 131 : : uint32_t val; 132 : : 133 : 0 : val = rte_read32(droq->pkts_sent_reg); 134 : : 135 : 0 : new_pkts = val - droq->pkts_sent_prev; 136 : 0 : droq->pkts_sent_prev = val; 137 : : 138 [ # # ]: 0 : if (val > RTE_BIT32(31)) { 139 : : /* Only subtract the packet count in the HW counter 140 : : * when count above halfway to saturation. 141 : : */ 142 : 0 : rte_write64((uint64_t)val, droq->pkts_sent_reg); 143 : : rte_mb(); 144 : 0 : droq->pkts_sent_prev = 0; 145 : : } 146 : : 147 : 0 : return new_pkts; 148 : : } 149 : : 150 : : static inline int16_t __rte_hot 151 : : cnxk_ep_rx_pkts_to_process(struct otx_ep_droq *droq, uint16_t nb_pkts) 152 : : { 153 : 0 : const otx_ep_check_pkt_count_t cnxk_rx_pkt_count[2] = { cnxk_ep_check_rx_pkt_reg, 154 : : cnxk_ep_check_rx_ism_mem}; 155 : : 156 [ # # # # : 0 : if (droq->pkts_pending < nb_pkts) # # # # ] 157 : 0 : droq->pkts_pending += cnxk_rx_pkt_count[droq->ism_ena](droq); 158 : : 159 [ # # ]: 0 : return RTE_MIN(nb_pkts, droq->pkts_pending); 160 : : } 161 : : 162 : : #define cnxk_pktmbuf_mtod(m, t) ((t)(void *)((char *)(m)->buf_addr + RTE_PKTMBUF_HEADROOM)) 163 : : 164 : : static __rte_always_inline void 165 : : cnxk_ep_process_pkts_scalar(struct rte_mbuf **rx_pkts, struct otx_ep_droq *droq, uint16_t new_pkts) 166 : : { 167 : 0 : struct rte_mbuf **recv_buf_list = droq->recv_buf_list; 168 : 0 : uint32_t bytes_rsvd = 0, read_idx = droq->read_idx; 169 : 0 : uint16_t nb_desc = droq->nb_desc; 170 : : uint16_t pkts; 171 : : 172 [ # # # # ]: 0 : for (pkts = 0; pkts < new_pkts; pkts++) { 173 : : struct otx_ep_droq_info *info; 174 : : struct rte_mbuf *mbuf; 175 : : uint16_t pkt_len; 176 : : 177 : 0 : rte_prefetch0(recv_buf_list[otx_ep_incr_index(read_idx, 2, nb_desc)]); 178 : 0 : rte_prefetch0(rte_pktmbuf_mtod(recv_buf_list[otx_ep_incr_index(read_idx, 179 : : 2, nb_desc)], 180 : : void *)); 181 : : 182 : 0 : mbuf = recv_buf_list[read_idx]; 183 [ # # # # ]: 0 : info = cnxk_pktmbuf_mtod(mbuf, struct otx_ep_droq_info *); 184 : : read_idx = otx_ep_incr_index(read_idx, 1, nb_desc); 185 [ # # # # ]: 0 : pkt_len = rte_bswap16(info->length >> 48); 186 : 0 : mbuf->pkt_len = pkt_len; 187 : 0 : mbuf->data_len = pkt_len; 188 : : 189 : 0 : *(uint64_t *)&mbuf->rearm_data = droq->rearm_data; 190 : 0 : rx_pkts[pkts] = mbuf; 191 : 0 : bytes_rsvd += pkt_len; 192 : : } 193 : 0 : droq->read_idx = read_idx; 194 : : 195 : 0 : droq->refill_count += new_pkts; 196 : 0 : droq->pkts_pending -= new_pkts; 197 : : /* Stats */ 198 : 0 : droq->stats.pkts_received += new_pkts; 199 [ # # ]: 0 : droq->stats.bytes_received += bytes_rsvd; 200 : : }