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_pkts(struct otx_ep_droq *droq) 92 : : { 93 : : uint32_t new_pkts; 94 : : uint32_t val; 95 : : 96 : : /* Batch subtractions from the HW counter to reduce PCIe traffic 97 : : * This adds an extra local variable, but almost halves the 98 : : * number of PCIe writes. 99 : : */ 100 : 0 : val = __atomic_load_n(droq->pkts_sent_ism, __ATOMIC_RELAXED); 101 : 0 : new_pkts = val - droq->pkts_sent_ism_prev; 102 : 0 : droq->pkts_sent_ism_prev = val; 103 : : 104 [ # # ]: 0 : if (val > RTE_BIT32(31)) { 105 : : /* Only subtract the packet count in the HW counter 106 : : * when count above halfway to saturation. 107 : : */ 108 : 0 : rte_write64((uint64_t)val, droq->pkts_sent_reg); 109 : : rte_mb(); 110 : : 111 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 112 [ # # ]: 0 : while (__atomic_load_n(droq->pkts_sent_ism, __ATOMIC_RELAXED) >= val) { 113 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 114 : : rte_mb(); 115 : : } 116 : : 117 : 0 : droq->pkts_sent_ism_prev = 0; 118 : : } 119 : 0 : rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg); 120 : 0 : droq->pkts_pending += new_pkts; 121 : : 122 : 0 : return new_pkts; 123 : : } 124 : : 125 : : static inline int16_t __rte_hot 126 : : cnxk_ep_rx_pkts_to_process(struct otx_ep_droq *droq, uint16_t nb_pkts) 127 : : { 128 [ # # # # : 0 : if (droq->pkts_pending < nb_pkts) # # # # ] 129 : 0 : cnxk_ep_check_rx_pkts(droq); 130 : : 131 [ # # ]: 0 : return RTE_MIN(nb_pkts, droq->pkts_pending); 132 : : } 133 : : 134 : : #define cnxk_pktmbuf_mtod(m, t) ((t)(void *)((char *)(m)->buf_addr + RTE_PKTMBUF_HEADROOM)) 135 : : 136 : : static __rte_always_inline void 137 : : cnxk_ep_process_pkts_scalar(struct rte_mbuf **rx_pkts, struct otx_ep_droq *droq, uint16_t new_pkts) 138 : : { 139 : 0 : struct rte_mbuf **recv_buf_list = droq->recv_buf_list; 140 : 0 : uint32_t bytes_rsvd = 0, read_idx = droq->read_idx; 141 : 0 : uint16_t nb_desc = droq->nb_desc; 142 : : uint16_t pkts; 143 : : 144 [ # # # # ]: 0 : for (pkts = 0; pkts < new_pkts; pkts++) { 145 : : struct otx_ep_droq_info *info; 146 : : struct rte_mbuf *mbuf; 147 : : uint16_t pkt_len; 148 : : 149 : 0 : rte_prefetch0(recv_buf_list[otx_ep_incr_index(read_idx, 2, nb_desc)]); 150 : 0 : rte_prefetch0(rte_pktmbuf_mtod(recv_buf_list[otx_ep_incr_index(read_idx, 151 : : 2, nb_desc)], 152 : : void *)); 153 : : 154 : 0 : mbuf = recv_buf_list[read_idx]; 155 [ # # # # ]: 0 : info = cnxk_pktmbuf_mtod(mbuf, struct otx_ep_droq_info *); 156 : : read_idx = otx_ep_incr_index(read_idx, 1, nb_desc); 157 [ # # # # ]: 0 : pkt_len = rte_bswap16(info->length >> 48); 158 : 0 : mbuf->pkt_len = pkt_len; 159 : 0 : mbuf->data_len = pkt_len; 160 : : 161 : 0 : *(uint64_t *)&mbuf->rearm_data = droq->rearm_data; 162 : 0 : rx_pkts[pkts] = mbuf; 163 : 0 : bytes_rsvd += pkt_len; 164 : : } 165 : 0 : droq->read_idx = read_idx; 166 : : 167 : 0 : droq->refill_count += new_pkts; 168 : 0 : droq->pkts_pending -= new_pkts; 169 : : /* Stats */ 170 : 0 : droq->stats.pkts_received += new_pkts; 171 [ # # ]: 0 : droq->stats.bytes_received += bytes_rsvd; 172 : : }