1ab09499eSPavan Nikhilesh /* SPDX-License-Identifier: BSD-3-Clause
2ab09499eSPavan Nikhilesh * Copyright(C) 2023 Marvell.
3ab09499eSPavan Nikhilesh */
4ab09499eSPavan Nikhilesh
5ab09499eSPavan Nikhilesh #include <rte_vect.h>
6ab09499eSPavan Nikhilesh
7ab09499eSPavan Nikhilesh #include "otx_ep_common.h"
8ab09499eSPavan Nikhilesh #include "otx2_ep_vf.h"
9ab09499eSPavan Nikhilesh #include "otx_ep_rxtx.h"
10ab09499eSPavan Nikhilesh
11ab09499eSPavan Nikhilesh #define CNXK_EP_OQ_DESC_PER_LOOP_SSE 4
12ab09499eSPavan Nikhilesh #define CNXK_EP_OQ_DESC_PER_LOOP_AVX 8
13ab09499eSPavan Nikhilesh
14ab09499eSPavan Nikhilesh static inline int
cnxk_ep_rx_refill_mbuf(struct otx_ep_droq * droq,uint32_t count)15ab09499eSPavan Nikhilesh cnxk_ep_rx_refill_mbuf(struct otx_ep_droq *droq, uint32_t count)
16ab09499eSPavan Nikhilesh {
17ab09499eSPavan Nikhilesh struct otx_ep_droq_desc *desc_ring = droq->desc_ring;
18ab09499eSPavan Nikhilesh struct rte_mbuf **recv_buf_list = droq->recv_buf_list;
19ab09499eSPavan Nikhilesh uint32_t refill_idx = droq->refill_idx;
20ab09499eSPavan Nikhilesh struct rte_mbuf *buf;
21ab09499eSPavan Nikhilesh uint32_t i;
22ab09499eSPavan Nikhilesh int rc;
23ab09499eSPavan Nikhilesh
24bdfb48bfSPavan Nikhilesh rc = rte_mempool_get_bulk(droq->mpool, (void **)&recv_buf_list[refill_idx], count);
25ab09499eSPavan Nikhilesh if (unlikely(rc)) {
26ab09499eSPavan Nikhilesh droq->stats.rx_alloc_failure++;
27ab09499eSPavan Nikhilesh return rc;
28ab09499eSPavan Nikhilesh }
29ab09499eSPavan Nikhilesh
30ab09499eSPavan Nikhilesh for (i = 0; i < count; i++) {
31bdfb48bfSPavan Nikhilesh rte_prefetch_non_temporal(&desc_ring[(refill_idx + 1) & 3]);
32bdfb48bfSPavan Nikhilesh if (i < count - 1)
33bdfb48bfSPavan Nikhilesh rte_prefetch_non_temporal(recv_buf_list[refill_idx + 1]);
34ab09499eSPavan Nikhilesh buf = recv_buf_list[refill_idx];
35ab09499eSPavan Nikhilesh desc_ring[refill_idx].buffer_ptr = rte_mbuf_data_iova_default(buf);
36ab09499eSPavan Nikhilesh refill_idx++;
37ab09499eSPavan Nikhilesh }
38ab09499eSPavan Nikhilesh
39ab09499eSPavan Nikhilesh droq->refill_idx = otx_ep_incr_index(droq->refill_idx, count, droq->nb_desc);
40ab09499eSPavan Nikhilesh droq->refill_count -= count;
41ab09499eSPavan Nikhilesh
42ab09499eSPavan Nikhilesh return 0;
43ab09499eSPavan Nikhilesh }
44ab09499eSPavan Nikhilesh
45ab09499eSPavan Nikhilesh static inline void
cnxk_ep_rx_refill(struct otx_ep_droq * droq)46ab09499eSPavan Nikhilesh cnxk_ep_rx_refill(struct otx_ep_droq *droq)
47ab09499eSPavan Nikhilesh {
48bdfb48bfSPavan Nikhilesh const uint32_t nb_desc = droq->nb_desc;
49ab09499eSPavan Nikhilesh uint32_t refill_idx = droq->refill_idx;
50bdfb48bfSPavan Nikhilesh uint32_t desc_refilled = 0, count;
51ab09499eSPavan Nikhilesh int rc;
52ab09499eSPavan Nikhilesh
53ab09499eSPavan Nikhilesh if (unlikely(droq->read_idx == refill_idx))
54ab09499eSPavan Nikhilesh return;
55ab09499eSPavan Nikhilesh
56ab09499eSPavan Nikhilesh if (refill_idx < droq->read_idx) {
57ab09499eSPavan Nikhilesh count = droq->read_idx - refill_idx;
58ab09499eSPavan Nikhilesh rc = cnxk_ep_rx_refill_mbuf(droq, count);
59ab09499eSPavan Nikhilesh if (unlikely(rc)) {
60ab09499eSPavan Nikhilesh droq->stats.rx_alloc_failure++;
61ab09499eSPavan Nikhilesh return;
62ab09499eSPavan Nikhilesh }
63ab09499eSPavan Nikhilesh desc_refilled = count;
64ab09499eSPavan Nikhilesh } else {
65ab09499eSPavan Nikhilesh count = nb_desc - refill_idx;
66ab09499eSPavan Nikhilesh rc = cnxk_ep_rx_refill_mbuf(droq, count);
67ab09499eSPavan Nikhilesh if (unlikely(rc)) {
68ab09499eSPavan Nikhilesh droq->stats.rx_alloc_failure++;
69ab09499eSPavan Nikhilesh return;
70ab09499eSPavan Nikhilesh }
71ab09499eSPavan Nikhilesh
72ab09499eSPavan Nikhilesh desc_refilled = count;
73ab09499eSPavan Nikhilesh count = droq->read_idx;
74ab09499eSPavan Nikhilesh rc = cnxk_ep_rx_refill_mbuf(droq, count);
75ab09499eSPavan Nikhilesh if (unlikely(rc)) {
76ab09499eSPavan Nikhilesh droq->stats.rx_alloc_failure++;
77ab09499eSPavan Nikhilesh return;
78ab09499eSPavan Nikhilesh }
79ab09499eSPavan Nikhilesh desc_refilled += count;
80ab09499eSPavan Nikhilesh }
81ab09499eSPavan Nikhilesh
82ab09499eSPavan Nikhilesh /* Flush the droq descriptor data to memory to be sure
83ab09499eSPavan Nikhilesh * that when we update the credits the data in memory is
84ab09499eSPavan Nikhilesh * accurate.
85ab09499eSPavan Nikhilesh */
86ab09499eSPavan Nikhilesh rte_io_wmb();
87ab09499eSPavan Nikhilesh rte_write32(desc_refilled, droq->pkts_credit_reg);
88ab09499eSPavan Nikhilesh }
89ab09499eSPavan Nikhilesh
90ab09499eSPavan Nikhilesh static inline uint32_t
cnxk_ep_check_rx_ism_mem(void * rx_queue)91831cf744SVamsi Attunuru cnxk_ep_check_rx_ism_mem(void *rx_queue)
92ab09499eSPavan Nikhilesh {
93831cf744SVamsi Attunuru struct otx_ep_droq *droq = (struct otx_ep_droq *)rx_queue;
94ab09499eSPavan Nikhilesh uint32_t new_pkts;
95ab09499eSPavan Nikhilesh uint32_t val;
96ab09499eSPavan Nikhilesh
97ab09499eSPavan Nikhilesh /* Batch subtractions from the HW counter to reduce PCIe traffic
98ab09499eSPavan Nikhilesh * This adds an extra local variable, but almost halves the
99ab09499eSPavan Nikhilesh * number of PCIe writes.
100ab09499eSPavan Nikhilesh */
101*e12a0166STyler Retzlaff val = rte_atomic_load_explicit(droq->pkts_sent_ism, rte_memory_order_relaxed);
102831cf744SVamsi Attunuru
103831cf744SVamsi Attunuru new_pkts = val - droq->pkts_sent_prev;
104831cf744SVamsi Attunuru droq->pkts_sent_prev = val;
105ab09499eSPavan Nikhilesh
106ab09499eSPavan Nikhilesh if (val > RTE_BIT32(31)) {
107ab09499eSPavan Nikhilesh /* Only subtract the packet count in the HW counter
108ab09499eSPavan Nikhilesh * when count above halfway to saturation.
109ab09499eSPavan Nikhilesh */
110ab09499eSPavan Nikhilesh rte_write64((uint64_t)val, droq->pkts_sent_reg);
111ab09499eSPavan Nikhilesh rte_mb();
112ab09499eSPavan Nikhilesh
113ab09499eSPavan Nikhilesh rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
114*e12a0166STyler Retzlaff while (rte_atomic_load_explicit(droq->pkts_sent_ism,
115*e12a0166STyler Retzlaff rte_memory_order_relaxed) >= val) {
116ab09499eSPavan Nikhilesh rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
117ab09499eSPavan Nikhilesh rte_mb();
118ab09499eSPavan Nikhilesh }
119831cf744SVamsi Attunuru droq->pkts_sent_prev = 0;
120ab09499eSPavan Nikhilesh }
121831cf744SVamsi Attunuru
122ab09499eSPavan Nikhilesh rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
123831cf744SVamsi Attunuru
124831cf744SVamsi Attunuru return new_pkts;
125831cf744SVamsi Attunuru }
126831cf744SVamsi Attunuru
127831cf744SVamsi Attunuru static inline uint32_t
cnxk_ep_check_rx_pkt_reg(void * rx_queue)128831cf744SVamsi Attunuru cnxk_ep_check_rx_pkt_reg(void *rx_queue)
129831cf744SVamsi Attunuru {
130831cf744SVamsi Attunuru struct otx_ep_droq *droq = (struct otx_ep_droq *)rx_queue;
131831cf744SVamsi Attunuru uint32_t new_pkts;
132831cf744SVamsi Attunuru uint32_t val;
133831cf744SVamsi Attunuru
134831cf744SVamsi Attunuru val = rte_read32(droq->pkts_sent_reg);
135831cf744SVamsi Attunuru
136831cf744SVamsi Attunuru new_pkts = val - droq->pkts_sent_prev;
137831cf744SVamsi Attunuru droq->pkts_sent_prev = val;
138831cf744SVamsi Attunuru
139831cf744SVamsi Attunuru if (val > RTE_BIT32(31)) {
140831cf744SVamsi Attunuru /* Only subtract the packet count in the HW counter
141831cf744SVamsi Attunuru * when count above halfway to saturation.
142831cf744SVamsi Attunuru */
143831cf744SVamsi Attunuru rte_write64((uint64_t)val, droq->pkts_sent_reg);
144831cf744SVamsi Attunuru rte_mb();
145831cf744SVamsi Attunuru droq->pkts_sent_prev = 0;
146831cf744SVamsi Attunuru }
147ab09499eSPavan Nikhilesh
148ab09499eSPavan Nikhilesh return new_pkts;
149ab09499eSPavan Nikhilesh }
150ab09499eSPavan Nikhilesh
151ab09499eSPavan Nikhilesh static inline int16_t __rte_hot
cnxk_ep_rx_pkts_to_process(struct otx_ep_droq * droq,uint16_t nb_pkts)152ab09499eSPavan Nikhilesh cnxk_ep_rx_pkts_to_process(struct otx_ep_droq *droq, uint16_t nb_pkts)
153ab09499eSPavan Nikhilesh {
154831cf744SVamsi Attunuru const otx_ep_check_pkt_count_t cnxk_rx_pkt_count[2] = { cnxk_ep_check_rx_pkt_reg,
155831cf744SVamsi Attunuru cnxk_ep_check_rx_ism_mem};
156831cf744SVamsi Attunuru
157ab09499eSPavan Nikhilesh if (droq->pkts_pending < nb_pkts)
158831cf744SVamsi Attunuru droq->pkts_pending += cnxk_rx_pkt_count[droq->ism_ena](droq);
159ab09499eSPavan Nikhilesh
160ab09499eSPavan Nikhilesh return RTE_MIN(nb_pkts, droq->pkts_pending);
161ab09499eSPavan Nikhilesh }
162ab09499eSPavan Nikhilesh
163bdfb48bfSPavan Nikhilesh #define cnxk_pktmbuf_mtod(m, t) ((t)(void *)((char *)(m)->buf_addr + RTE_PKTMBUF_HEADROOM))
164bdfb48bfSPavan Nikhilesh
165ab09499eSPavan Nikhilesh static __rte_always_inline void
cnxk_ep_process_pkts_scalar(struct rte_mbuf ** rx_pkts,struct otx_ep_droq * droq,uint16_t new_pkts)166ab09499eSPavan Nikhilesh cnxk_ep_process_pkts_scalar(struct rte_mbuf **rx_pkts, struct otx_ep_droq *droq, uint16_t new_pkts)
167ab09499eSPavan Nikhilesh {
168ab09499eSPavan Nikhilesh struct rte_mbuf **recv_buf_list = droq->recv_buf_list;
169ab09499eSPavan Nikhilesh uint32_t bytes_rsvd = 0, read_idx = droq->read_idx;
170ab09499eSPavan Nikhilesh uint16_t nb_desc = droq->nb_desc;
171ab09499eSPavan Nikhilesh uint16_t pkts;
172ab09499eSPavan Nikhilesh
173ab09499eSPavan Nikhilesh for (pkts = 0; pkts < new_pkts; pkts++) {
174ab09499eSPavan Nikhilesh struct otx_ep_droq_info *info;
175ab09499eSPavan Nikhilesh struct rte_mbuf *mbuf;
176ab09499eSPavan Nikhilesh uint16_t pkt_len;
177ab09499eSPavan Nikhilesh
178ab09499eSPavan Nikhilesh rte_prefetch0(recv_buf_list[otx_ep_incr_index(read_idx, 2, nb_desc)]);
179ab09499eSPavan Nikhilesh rte_prefetch0(rte_pktmbuf_mtod(recv_buf_list[otx_ep_incr_index(read_idx,
180ab09499eSPavan Nikhilesh 2, nb_desc)],
181ab09499eSPavan Nikhilesh void *));
182ab09499eSPavan Nikhilesh
183ab09499eSPavan Nikhilesh mbuf = recv_buf_list[read_idx];
184bdfb48bfSPavan Nikhilesh info = cnxk_pktmbuf_mtod(mbuf, struct otx_ep_droq_info *);
185ab09499eSPavan Nikhilesh read_idx = otx_ep_incr_index(read_idx, 1, nb_desc);
186ab09499eSPavan Nikhilesh pkt_len = rte_bswap16(info->length >> 48);
187ab09499eSPavan Nikhilesh mbuf->pkt_len = pkt_len;
188ab09499eSPavan Nikhilesh mbuf->data_len = pkt_len;
189ab09499eSPavan Nikhilesh
190ab09499eSPavan Nikhilesh *(uint64_t *)&mbuf->rearm_data = droq->rearm_data;
191ab09499eSPavan Nikhilesh rx_pkts[pkts] = mbuf;
192ab09499eSPavan Nikhilesh bytes_rsvd += pkt_len;
193ab09499eSPavan Nikhilesh }
194ab09499eSPavan Nikhilesh droq->read_idx = read_idx;
195ab09499eSPavan Nikhilesh
196ab09499eSPavan Nikhilesh droq->refill_count += new_pkts;
197ab09499eSPavan Nikhilesh droq->pkts_pending -= new_pkts;
198ab09499eSPavan Nikhilesh /* Stats */
199ab09499eSPavan Nikhilesh droq->stats.pkts_received += new_pkts;
200ab09499eSPavan Nikhilesh droq->stats.bytes_received += bytes_rsvd;
201ab09499eSPavan Nikhilesh }
202