xref: /dpdk/drivers/net/octeon_ep/cnxk_ep_rx.h (revision e12a0166c80f65e35408f4715b2f3a60763c3741)
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