xref: /dpdk/drivers/net/octeon_ep/otx_ep_rxtx.c (revision 2b843cac232eb3f2fa79e4254e21766817e2019f)
1423c8a29SSathesh Edara /* SPDX-License-Identifier: BSD-3-Clause
2423c8a29SSathesh Edara  * Copyright(C) 2021 Marvell.
3423c8a29SSathesh Edara  */
4423c8a29SSathesh Edara 
5423c8a29SSathesh Edara #include <unistd.h>
6dfa2f825SSathesh Edara #include <assert.h>
7423c8a29SSathesh Edara #include <rte_eal.h>
8423c8a29SSathesh Edara #include <rte_mempool.h>
9423c8a29SSathesh Edara #include <rte_mbuf.h>
10423c8a29SSathesh Edara #include <rte_io.h>
11423c8a29SSathesh Edara #include <rte_net.h>
12423c8a29SSathesh Edara #include <ethdev_pci.h>
13423c8a29SSathesh Edara 
14831cf744SVamsi Attunuru #include "cnxk_ep_rx.h"
15423c8a29SSathesh Edara #include "otx_ep_common.h"
16423c8a29SSathesh Edara #include "otx_ep_vf.h"
17423c8a29SSathesh Edara #include "otx_ep_rxtx.h"
18423c8a29SSathesh Edara 
19423c8a29SSathesh Edara static void
20423c8a29SSathesh Edara otx_ep_dmazone_free(const struct rte_memzone *mz)
21423c8a29SSathesh Edara {
22423c8a29SSathesh Edara 	const struct rte_memzone *mz_tmp;
23423c8a29SSathesh Edara 	int ret = 0;
24423c8a29SSathesh Edara 
25423c8a29SSathesh Edara 	if (mz == NULL) {
26f665790aSDavid Marchand 		otx_ep_err("Memzone: NULL");
27423c8a29SSathesh Edara 		return;
28423c8a29SSathesh Edara 	}
29423c8a29SSathesh Edara 
30423c8a29SSathesh Edara 	mz_tmp = rte_memzone_lookup(mz->name);
31423c8a29SSathesh Edara 	if (mz_tmp == NULL) {
32f665790aSDavid Marchand 		otx_ep_err("Memzone %s Not Found", mz->name);
33423c8a29SSathesh Edara 		return;
34423c8a29SSathesh Edara 	}
35423c8a29SSathesh Edara 
36423c8a29SSathesh Edara 	ret = rte_memzone_free(mz);
37423c8a29SSathesh Edara 	if (ret)
38f665790aSDavid Marchand 		otx_ep_err("Memzone free failed : ret = %d", ret);
39423c8a29SSathesh Edara }
40423c8a29SSathesh Edara 
41423c8a29SSathesh Edara /* Free IQ resources */
42423c8a29SSathesh Edara int
43423c8a29SSathesh Edara otx_ep_delete_iqs(struct otx_ep_device *otx_ep, uint32_t iq_no)
44423c8a29SSathesh Edara {
45423c8a29SSathesh Edara 	struct otx_ep_instr_queue *iq;
463db81df3SVamsi Attunuru 	uint32_t i;
47423c8a29SSathesh Edara 
48423c8a29SSathesh Edara 	iq = otx_ep->instr_queue[iq_no];
49423c8a29SSathesh Edara 	if (iq == NULL) {
50f665790aSDavid Marchand 		otx_ep_err("Invalid IQ[%d]", iq_no);
51423c8a29SSathesh Edara 		return -EINVAL;
52423c8a29SSathesh Edara 	}
53423c8a29SSathesh Edara 
543db81df3SVamsi Attunuru 	if (iq->req_list) {
553db81df3SVamsi Attunuru 		for (i = 0; i < iq->nb_desc; i++)
563db81df3SVamsi Attunuru 			rte_free(iq->req_list[i].finfo.g.sg);
57423c8a29SSathesh Edara 		rte_free(iq->req_list);
583db81df3SVamsi Attunuru 	}
593db81df3SVamsi Attunuru 
60423c8a29SSathesh Edara 	iq->req_list = NULL;
61423c8a29SSathesh Edara 
62423c8a29SSathesh Edara 	if (iq->iq_mz) {
63423c8a29SSathesh Edara 		otx_ep_dmazone_free(iq->iq_mz);
64423c8a29SSathesh Edara 		iq->iq_mz = NULL;
65423c8a29SSathesh Edara 	}
66423c8a29SSathesh Edara 
67423c8a29SSathesh Edara 	rte_free(otx_ep->instr_queue[iq_no]);
68423c8a29SSathesh Edara 	otx_ep->instr_queue[iq_no] = NULL;
69423c8a29SSathesh Edara 
70423c8a29SSathesh Edara 	otx_ep->nb_tx_queues--;
71423c8a29SSathesh Edara 
72f665790aSDavid Marchand 	otx_ep_info("IQ[%d] is deleted", iq_no);
73423c8a29SSathesh Edara 
74423c8a29SSathesh Edara 	return 0;
75423c8a29SSathesh Edara }
76423c8a29SSathesh Edara 
77423c8a29SSathesh Edara /* IQ initialization */
78423c8a29SSathesh Edara static int
79423c8a29SSathesh Edara otx_ep_init_instr_queue(struct otx_ep_device *otx_ep, int iq_no, int num_descs,
80423c8a29SSathesh Edara 		     unsigned int socket_id)
81423c8a29SSathesh Edara {
82423c8a29SSathesh Edara 	const struct otx_ep_config *conf;
83423c8a29SSathesh Edara 	struct otx_ep_instr_queue *iq;
843db81df3SVamsi Attunuru 	struct otx_ep_sg_entry *sg;
853db81df3SVamsi Attunuru 	uint32_t i, q_size;
86dfa2f825SSathesh Edara 	int ret;
87423c8a29SSathesh Edara 
88423c8a29SSathesh Edara 	conf = otx_ep->conf;
89423c8a29SSathesh Edara 	iq = otx_ep->instr_queue[iq_no];
90423c8a29SSathesh Edara 	q_size = conf->iq.instr_type * num_descs;
91423c8a29SSathesh Edara 
92423c8a29SSathesh Edara 	/* IQ memory creation for Instruction submission to OCTEON 9 */
93423c8a29SSathesh Edara 	iq->iq_mz = rte_eth_dma_zone_reserve(otx_ep->eth_dev,
94423c8a29SSathesh Edara 					     "instr_queue", iq_no, q_size,
95423c8a29SSathesh Edara 					     OTX_EP_PCI_RING_ALIGN,
96423c8a29SSathesh Edara 					     socket_id);
97423c8a29SSathesh Edara 	if (iq->iq_mz == NULL) {
98f665790aSDavid Marchand 		otx_ep_err("IQ[%d] memzone alloc failed", iq_no);
99423c8a29SSathesh Edara 		goto iq_init_fail;
100423c8a29SSathesh Edara 	}
101423c8a29SSathesh Edara 
102423c8a29SSathesh Edara 	iq->base_addr_dma = iq->iq_mz->iova;
103423c8a29SSathesh Edara 	iq->base_addr = (uint8_t *)iq->iq_mz->addr;
104423c8a29SSathesh Edara 
105423c8a29SSathesh Edara 	if (num_descs & (num_descs - 1)) {
106f665790aSDavid Marchand 		otx_ep_err("IQ[%d] descs not in power of 2", iq_no);
107423c8a29SSathesh Edara 		goto iq_init_fail;
108423c8a29SSathesh Edara 	}
109423c8a29SSathesh Edara 
110423c8a29SSathesh Edara 	iq->nb_desc = num_descs;
111423c8a29SSathesh Edara 
112423c8a29SSathesh Edara 	/* Create a IQ request list to hold requests that have been
113423c8a29SSathesh Edara 	 * posted to OCTEON 9. This list will be used for freeing the IQ
114423c8a29SSathesh Edara 	 * data buffer(s) later once the OCTEON 9 fetched the requests.
115423c8a29SSathesh Edara 	 */
116423c8a29SSathesh Edara 	iq->req_list = rte_zmalloc_socket("request_list",
117423c8a29SSathesh Edara 			(iq->nb_desc * OTX_EP_IQREQ_LIST_SIZE),
118423c8a29SSathesh Edara 			RTE_CACHE_LINE_SIZE,
119423c8a29SSathesh Edara 			rte_socket_id());
120423c8a29SSathesh Edara 	if (iq->req_list == NULL) {
121f665790aSDavid Marchand 		otx_ep_err("IQ[%d] req_list alloc failed", iq_no);
122423c8a29SSathesh Edara 		goto iq_init_fail;
123423c8a29SSathesh Edara 	}
124423c8a29SSathesh Edara 
1253db81df3SVamsi Attunuru 	for (i = 0; i < iq->nb_desc; i++) {
1263db81df3SVamsi Attunuru 		sg = rte_zmalloc_socket("sg_entry", (OTX_EP_MAX_SG_LISTS * OTX_EP_SG_ENTRY_SIZE),
1273db81df3SVamsi Attunuru 			OTX_EP_SG_ALIGN, rte_socket_id());
1283db81df3SVamsi Attunuru 		if (sg == NULL) {
129f665790aSDavid Marchand 			otx_ep_err("IQ[%d] sg_entries alloc failed", iq_no);
1303db81df3SVamsi Attunuru 			goto iq_init_fail;
1313db81df3SVamsi Attunuru 		}
1323db81df3SVamsi Attunuru 
1333db81df3SVamsi Attunuru 		iq->req_list[i].finfo.g.num_sg = OTX_EP_MAX_SG_LISTS;
1343db81df3SVamsi Attunuru 		iq->req_list[i].finfo.g.sg = sg;
1353db81df3SVamsi Attunuru 	}
1363db81df3SVamsi Attunuru 
137f665790aSDavid Marchand 	otx_ep_info("IQ[%d]: base: %p basedma: %lx count: %d",
138423c8a29SSathesh Edara 		     iq_no, iq->base_addr, (unsigned long)iq->base_addr_dma,
139423c8a29SSathesh Edara 		     iq->nb_desc);
140423c8a29SSathesh Edara 
14135dee56cSVamsi Attunuru 	iq->mbuf_list = rte_zmalloc_socket("mbuf_list",	(iq->nb_desc * sizeof(struct rte_mbuf *)),
14235dee56cSVamsi Attunuru 					   RTE_CACHE_LINE_SIZE, rte_socket_id());
14335dee56cSVamsi Attunuru 	if (!iq->mbuf_list) {
144f665790aSDavid Marchand 		otx_ep_err("IQ[%d] mbuf_list alloc failed", iq_no);
14535dee56cSVamsi Attunuru 		goto iq_init_fail;
14635dee56cSVamsi Attunuru 	}
14735dee56cSVamsi Attunuru 
148423c8a29SSathesh Edara 	iq->otx_ep_dev = otx_ep;
149423c8a29SSathesh Edara 	iq->q_no = iq_no;
150423c8a29SSathesh Edara 	iq->fill_cnt = 0;
151423c8a29SSathesh Edara 	iq->host_write_index = 0;
152423c8a29SSathesh Edara 	iq->otx_read_index = 0;
153423c8a29SSathesh Edara 	iq->flush_index = 0;
154423c8a29SSathesh Edara 	iq->instr_pending = 0;
155423c8a29SSathesh Edara 
156423c8a29SSathesh Edara 	otx_ep->io_qmask.iq |= (1ull << iq_no);
157423c8a29SSathesh Edara 
158423c8a29SSathesh Edara 	/* Set 32B/64B mode for each input queue */
159423c8a29SSathesh Edara 	if (conf->iq.instr_type == 64)
160423c8a29SSathesh Edara 		otx_ep->io_qmask.iq64B |= (1ull << iq_no);
161423c8a29SSathesh Edara 
162423c8a29SSathesh Edara 	iq->iqcmd_64B = (conf->iq.instr_type == 64);
163831cf744SVamsi Attunuru 	iq->ism_ena = otx_ep->ism_ena;
164423c8a29SSathesh Edara 
165423c8a29SSathesh Edara 	/* Set up IQ registers */
166dfa2f825SSathesh Edara 	ret = otx_ep->fn_list.setup_iq_regs(otx_ep, iq_no);
167dfa2f825SSathesh Edara 	if (ret)
168dfa2f825SSathesh Edara 		return ret;
169423c8a29SSathesh Edara 
170423c8a29SSathesh Edara 	return 0;
171423c8a29SSathesh Edara 
172423c8a29SSathesh Edara iq_init_fail:
173423c8a29SSathesh Edara 	return -ENOMEM;
174423c8a29SSathesh Edara }
175423c8a29SSathesh Edara 
176423c8a29SSathesh Edara int
177423c8a29SSathesh Edara otx_ep_setup_iqs(struct otx_ep_device *otx_ep, uint32_t iq_no, int num_descs,
178423c8a29SSathesh Edara 		 unsigned int socket_id)
179423c8a29SSathesh Edara {
180423c8a29SSathesh Edara 	struct otx_ep_instr_queue *iq;
181423c8a29SSathesh Edara 
182423c8a29SSathesh Edara 	iq = (struct otx_ep_instr_queue *)rte_zmalloc("otx_ep_IQ", sizeof(*iq),
183423c8a29SSathesh Edara 						RTE_CACHE_LINE_SIZE);
184423c8a29SSathesh Edara 	if (iq == NULL)
185423c8a29SSathesh Edara 		return -ENOMEM;
186423c8a29SSathesh Edara 
187423c8a29SSathesh Edara 	otx_ep->instr_queue[iq_no] = iq;
188423c8a29SSathesh Edara 
189423c8a29SSathesh Edara 	if (otx_ep_init_instr_queue(otx_ep, iq_no, num_descs, socket_id)) {
190f665790aSDavid Marchand 		otx_ep_err("IQ init is failed");
191423c8a29SSathesh Edara 		goto delete_IQ;
192423c8a29SSathesh Edara 	}
193423c8a29SSathesh Edara 	otx_ep->nb_tx_queues++;
194423c8a29SSathesh Edara 
195f665790aSDavid Marchand 	otx_ep_info("IQ[%d] is created.", iq_no);
196423c8a29SSathesh Edara 
197423c8a29SSathesh Edara 	return 0;
198423c8a29SSathesh Edara 
199423c8a29SSathesh Edara delete_IQ:
200423c8a29SSathesh Edara 	otx_ep_delete_iqs(otx_ep, iq_no);
201423c8a29SSathesh Edara 	return -ENOMEM;
202423c8a29SSathesh Edara }
203423c8a29SSathesh Edara 
204423c8a29SSathesh Edara static void
205423c8a29SSathesh Edara otx_ep_droq_reset_indices(struct otx_ep_droq *droq)
206423c8a29SSathesh Edara {
207423c8a29SSathesh Edara 	droq->read_idx  = 0;
208423c8a29SSathesh Edara 	droq->write_idx = 0;
209423c8a29SSathesh Edara 	droq->refill_idx = 0;
210423c8a29SSathesh Edara 	droq->refill_count = 0;
211423c8a29SSathesh Edara 	droq->last_pkt_count = 0;
212423c8a29SSathesh Edara 	droq->pkts_pending = 0;
213423c8a29SSathesh Edara }
214423c8a29SSathesh Edara 
215423c8a29SSathesh Edara static void
216423c8a29SSathesh Edara otx_ep_droq_destroy_ring_buffers(struct otx_ep_droq *droq)
217423c8a29SSathesh Edara {
218423c8a29SSathesh Edara 	uint32_t idx;
219423c8a29SSathesh Edara 
220423c8a29SSathesh Edara 	for (idx = 0; idx < droq->nb_desc; idx++) {
221423c8a29SSathesh Edara 		if (droq->recv_buf_list[idx]) {
222423c8a29SSathesh Edara 			rte_pktmbuf_free(droq->recv_buf_list[idx]);
223423c8a29SSathesh Edara 			droq->recv_buf_list[idx] = NULL;
224423c8a29SSathesh Edara 		}
225423c8a29SSathesh Edara 	}
226423c8a29SSathesh Edara 
227423c8a29SSathesh Edara 	otx_ep_droq_reset_indices(droq);
228423c8a29SSathesh Edara }
229423c8a29SSathesh Edara 
230423c8a29SSathesh Edara /* Free OQs resources */
231423c8a29SSathesh Edara int
232423c8a29SSathesh Edara otx_ep_delete_oqs(struct otx_ep_device *otx_ep, uint32_t oq_no)
233423c8a29SSathesh Edara {
234423c8a29SSathesh Edara 	struct otx_ep_droq *droq;
235423c8a29SSathesh Edara 
236423c8a29SSathesh Edara 	droq = otx_ep->droq[oq_no];
237423c8a29SSathesh Edara 	if (droq == NULL) {
238f665790aSDavid Marchand 		otx_ep_err("Invalid droq[%d]", oq_no);
239423c8a29SSathesh Edara 		return -EINVAL;
240423c8a29SSathesh Edara 	}
241423c8a29SSathesh Edara 
242423c8a29SSathesh Edara 	otx_ep_droq_destroy_ring_buffers(droq);
243423c8a29SSathesh Edara 	rte_free(droq->recv_buf_list);
244423c8a29SSathesh Edara 	droq->recv_buf_list = NULL;
245423c8a29SSathesh Edara 
246423c8a29SSathesh Edara 	if (droq->desc_ring_mz) {
247423c8a29SSathesh Edara 		otx_ep_dmazone_free(droq->desc_ring_mz);
248423c8a29SSathesh Edara 		droq->desc_ring_mz = NULL;
249423c8a29SSathesh Edara 	}
250423c8a29SSathesh Edara 
251423c8a29SSathesh Edara 	memset(droq, 0, OTX_EP_DROQ_SIZE);
252423c8a29SSathesh Edara 
253423c8a29SSathesh Edara 	rte_free(otx_ep->droq[oq_no]);
254423c8a29SSathesh Edara 	otx_ep->droq[oq_no] = NULL;
255423c8a29SSathesh Edara 
256423c8a29SSathesh Edara 	otx_ep->nb_rx_queues--;
257423c8a29SSathesh Edara 
258f665790aSDavid Marchand 	otx_ep_info("OQ[%d] is deleted", oq_no);
259423c8a29SSathesh Edara 	return 0;
260423c8a29SSathesh Edara }
261423c8a29SSathesh Edara 
262423c8a29SSathesh Edara static int
263423c8a29SSathesh Edara otx_ep_droq_setup_ring_buffers(struct otx_ep_droq *droq)
264423c8a29SSathesh Edara {
265423c8a29SSathesh Edara 	struct otx_ep_droq_desc *desc_ring = droq->desc_ring;
266423c8a29SSathesh Edara 	struct otx_ep_droq_info *info;
267423c8a29SSathesh Edara 	struct rte_mbuf *buf;
268423c8a29SSathesh Edara 	uint32_t idx;
269423c8a29SSathesh Edara 
270423c8a29SSathesh Edara 	for (idx = 0; idx < droq->nb_desc; idx++) {
271423c8a29SSathesh Edara 		buf = rte_pktmbuf_alloc(droq->mpool);
272423c8a29SSathesh Edara 		if (buf == NULL) {
273f665790aSDavid Marchand 			otx_ep_err("OQ buffer alloc failed");
274423c8a29SSathesh Edara 			droq->stats.rx_alloc_failure++;
275423c8a29SSathesh Edara 			return -ENOMEM;
276423c8a29SSathesh Edara 		}
277423c8a29SSathesh Edara 
278423c8a29SSathesh Edara 		droq->recv_buf_list[idx] = buf;
279423c8a29SSathesh Edara 		info = rte_pktmbuf_mtod(buf, struct otx_ep_droq_info *);
280423c8a29SSathesh Edara 		memset(info, 0, sizeof(*info));
281423c8a29SSathesh Edara 		desc_ring[idx].buffer_ptr = rte_mbuf_data_iova_default(buf);
282423c8a29SSathesh Edara 	}
283423c8a29SSathesh Edara 
284423c8a29SSathesh Edara 	otx_ep_droq_reset_indices(droq);
285423c8a29SSathesh Edara 
286423c8a29SSathesh Edara 	return 0;
287423c8a29SSathesh Edara }
288423c8a29SSathesh Edara 
289c30d99d2SPavan Nikhilesh static inline uint64_t
290c30d99d2SPavan Nikhilesh otx_ep_set_rearm_data(struct otx_ep_device *otx_ep)
291c30d99d2SPavan Nikhilesh {
292c30d99d2SPavan Nikhilesh 	uint16_t port_id = otx_ep->port_id;
293c30d99d2SPavan Nikhilesh 	struct rte_mbuf mb_def;
294c30d99d2SPavan Nikhilesh 	uint64_t *tmp;
295c30d99d2SPavan Nikhilesh 
296c30d99d2SPavan Nikhilesh 	RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_off) % 8 != 0);
297c30d99d2SPavan Nikhilesh 	RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, refcnt) - offsetof(struct rte_mbuf, data_off) !=
298c30d99d2SPavan Nikhilesh 			 2);
299c30d99d2SPavan Nikhilesh 	RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, nb_segs) - offsetof(struct rte_mbuf, data_off) !=
300c30d99d2SPavan Nikhilesh 			 4);
301c30d99d2SPavan Nikhilesh 	RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, port) - offsetof(struct rte_mbuf, data_off) !=
302c30d99d2SPavan Nikhilesh 			 6);
303c30d99d2SPavan Nikhilesh 	mb_def.nb_segs = 1;
304c30d99d2SPavan Nikhilesh 	mb_def.data_off = RTE_PKTMBUF_HEADROOM + OTX_EP_INFO_SIZE;
305c30d99d2SPavan Nikhilesh 	mb_def.port = port_id;
306c30d99d2SPavan Nikhilesh 	rte_mbuf_refcnt_set(&mb_def, 1);
307c30d99d2SPavan Nikhilesh 
308c30d99d2SPavan Nikhilesh 	/* Prevent compiler reordering: rearm_data covers previous fields */
309c30d99d2SPavan Nikhilesh 	rte_compiler_barrier();
310c30d99d2SPavan Nikhilesh 	tmp = (uint64_t *)&mb_def.rearm_data;
311c30d99d2SPavan Nikhilesh 
312c30d99d2SPavan Nikhilesh 	return *tmp;
313c30d99d2SPavan Nikhilesh }
314c30d99d2SPavan Nikhilesh 
315423c8a29SSathesh Edara /* OQ initialization */
316423c8a29SSathesh Edara static int
317423c8a29SSathesh Edara otx_ep_init_droq(struct otx_ep_device *otx_ep, uint32_t q_no,
318423c8a29SSathesh Edara 	      uint32_t num_descs, uint32_t desc_size,
319423c8a29SSathesh Edara 	      struct rte_mempool *mpool, unsigned int socket_id)
320423c8a29SSathesh Edara {
321423c8a29SSathesh Edara 	const struct otx_ep_config *conf = otx_ep->conf;
322423c8a29SSathesh Edara 	uint32_t c_refill_threshold;
323423c8a29SSathesh Edara 	struct otx_ep_droq *droq;
324423c8a29SSathesh Edara 	uint32_t desc_ring_size;
325dfa2f825SSathesh Edara 	int ret;
326423c8a29SSathesh Edara 
327f665790aSDavid Marchand 	otx_ep_info("OQ[%d] Init start", q_no);
328423c8a29SSathesh Edara 
329423c8a29SSathesh Edara 	droq = otx_ep->droq[q_no];
330423c8a29SSathesh Edara 	droq->otx_ep_dev = otx_ep;
331423c8a29SSathesh Edara 	droq->q_no = q_no;
332423c8a29SSathesh Edara 	droq->mpool = mpool;
333423c8a29SSathesh Edara 
334423c8a29SSathesh Edara 	droq->nb_desc      = num_descs;
335423c8a29SSathesh Edara 	droq->buffer_size  = desc_size;
336423c8a29SSathesh Edara 	c_refill_threshold = RTE_MAX(conf->oq.refill_threshold,
337423c8a29SSathesh Edara 				     droq->nb_desc / 2);
338423c8a29SSathesh Edara 
339423c8a29SSathesh Edara 	/* OQ desc_ring set up */
340423c8a29SSathesh Edara 	desc_ring_size = droq->nb_desc * OTX_EP_DROQ_DESC_SIZE;
341423c8a29SSathesh Edara 	droq->desc_ring_mz = rte_eth_dma_zone_reserve(otx_ep->eth_dev, "droq",
342423c8a29SSathesh Edara 						      q_no, desc_ring_size,
343423c8a29SSathesh Edara 						      OTX_EP_PCI_RING_ALIGN,
344423c8a29SSathesh Edara 						      socket_id);
345423c8a29SSathesh Edara 
346423c8a29SSathesh Edara 	if (droq->desc_ring_mz == NULL) {
347f665790aSDavid Marchand 		otx_ep_err("OQ:%d desc_ring allocation failed", q_no);
348423c8a29SSathesh Edara 		goto init_droq_fail;
349423c8a29SSathesh Edara 	}
350423c8a29SSathesh Edara 
351423c8a29SSathesh Edara 	droq->desc_ring_dma = droq->desc_ring_mz->iova;
352423c8a29SSathesh Edara 	droq->desc_ring = (struct otx_ep_droq_desc *)droq->desc_ring_mz->addr;
353423c8a29SSathesh Edara 
354f665790aSDavid Marchand 	otx_ep_dbg("OQ[%d]: desc_ring: virt: 0x%p, dma: %lx",
355423c8a29SSathesh Edara 		    q_no, droq->desc_ring, (unsigned long)droq->desc_ring_dma);
356f665790aSDavid Marchand 	otx_ep_dbg("OQ[%d]: num_desc: %d", q_no, droq->nb_desc);
357423c8a29SSathesh Edara 
358423c8a29SSathesh Edara 	/* OQ buf_list set up */
359423c8a29SSathesh Edara 	droq->recv_buf_list = rte_zmalloc_socket("recv_buf_list",
360423c8a29SSathesh Edara 				(droq->nb_desc * sizeof(struct rte_mbuf *)),
361423c8a29SSathesh Edara 				 RTE_CACHE_LINE_SIZE, socket_id);
362423c8a29SSathesh Edara 	if (droq->recv_buf_list == NULL) {
363f665790aSDavid Marchand 		otx_ep_err("OQ recv_buf_list alloc failed");
364423c8a29SSathesh Edara 		goto init_droq_fail;
365423c8a29SSathesh Edara 	}
366423c8a29SSathesh Edara 
367423c8a29SSathesh Edara 	if (otx_ep_droq_setup_ring_buffers(droq))
368423c8a29SSathesh Edara 		goto init_droq_fail;
369423c8a29SSathesh Edara 
370423c8a29SSathesh Edara 	droq->refill_threshold = c_refill_threshold;
371c30d99d2SPavan Nikhilesh 	droq->rearm_data = otx_ep_set_rearm_data(otx_ep);
372831cf744SVamsi Attunuru 	droq->ism_ena = otx_ep->ism_ena;
373423c8a29SSathesh Edara 
374423c8a29SSathesh Edara 	/* Set up OQ registers */
375dfa2f825SSathesh Edara 	ret = otx_ep->fn_list.setup_oq_regs(otx_ep, q_no);
376dfa2f825SSathesh Edara 	if (ret)
377dfa2f825SSathesh Edara 		return ret;
378423c8a29SSathesh Edara 
379423c8a29SSathesh Edara 	otx_ep->io_qmask.oq |= (1ull << q_no);
380423c8a29SSathesh Edara 
381423c8a29SSathesh Edara 	return 0;
382423c8a29SSathesh Edara 
383423c8a29SSathesh Edara init_droq_fail:
384423c8a29SSathesh Edara 	return -ENOMEM;
385423c8a29SSathesh Edara }
386423c8a29SSathesh Edara 
387423c8a29SSathesh Edara /* OQ configuration and setup */
388423c8a29SSathesh Edara int
389423c8a29SSathesh Edara otx_ep_setup_oqs(struct otx_ep_device *otx_ep, int oq_no, int num_descs,
390423c8a29SSathesh Edara 		 int desc_size, struct rte_mempool *mpool,
391423c8a29SSathesh Edara 		 unsigned int socket_id)
392423c8a29SSathesh Edara {
393423c8a29SSathesh Edara 	struct otx_ep_droq *droq;
394423c8a29SSathesh Edara 
395423c8a29SSathesh Edara 	/* Allocate new droq. */
396423c8a29SSathesh Edara 	droq = (struct otx_ep_droq *)rte_zmalloc("otx_ep_OQ",
397423c8a29SSathesh Edara 				sizeof(*droq), RTE_CACHE_LINE_SIZE);
398423c8a29SSathesh Edara 	if (droq == NULL) {
399f665790aSDavid Marchand 		otx_ep_err("Droq[%d] Creation Failed", oq_no);
400423c8a29SSathesh Edara 		return -ENOMEM;
401423c8a29SSathesh Edara 	}
402423c8a29SSathesh Edara 	otx_ep->droq[oq_no] = droq;
403423c8a29SSathesh Edara 
404423c8a29SSathesh Edara 	if (otx_ep_init_droq(otx_ep, oq_no, num_descs, desc_size, mpool,
405423c8a29SSathesh Edara 			     socket_id)) {
406f665790aSDavid Marchand 		otx_ep_err("Droq[%d] Initialization failed", oq_no);
407423c8a29SSathesh Edara 		goto delete_OQ;
408423c8a29SSathesh Edara 	}
409f665790aSDavid Marchand 	otx_ep_info("OQ[%d] is created.", oq_no);
410423c8a29SSathesh Edara 
411423c8a29SSathesh Edara 	otx_ep->nb_rx_queues++;
412423c8a29SSathesh Edara 
413423c8a29SSathesh Edara 	return 0;
414423c8a29SSathesh Edara 
415423c8a29SSathesh Edara delete_OQ:
416423c8a29SSathesh Edara 	otx_ep_delete_oqs(otx_ep, oq_no);
417423c8a29SSathesh Edara 	return -ENOMEM;
418423c8a29SSathesh Edara }
419423c8a29SSathesh Edara 
420423c8a29SSathesh Edara static inline void
421423c8a29SSathesh Edara otx_ep_iqreq_delete(struct otx_ep_instr_queue *iq, uint32_t idx)
422423c8a29SSathesh Edara {
4233db81df3SVamsi Attunuru 	struct rte_mbuf *mbuf;
424423c8a29SSathesh Edara 	uint32_t reqtype;
425423c8a29SSathesh Edara 
4263db81df3SVamsi Attunuru 	mbuf    = iq->req_list[idx].finfo.mbuf;
427423c8a29SSathesh Edara 	reqtype = iq->req_list[idx].reqtype;
428423c8a29SSathesh Edara 
429423c8a29SSathesh Edara 	switch (reqtype) {
430423c8a29SSathesh Edara 	case OTX_EP_REQTYPE_NORESP_NET:
431423c8a29SSathesh Edara 	case OTX_EP_REQTYPE_NORESP_GATHER:
432423c8a29SSathesh Edara 		/* This will take care of multiple segments also */
4333db81df3SVamsi Attunuru 		rte_pktmbuf_free(mbuf);
434f665790aSDavid Marchand 		otx_ep_dbg("IQ buffer freed at idx[%d]", idx);
435423c8a29SSathesh Edara 		break;
436423c8a29SSathesh Edara 
437423c8a29SSathesh Edara 	case OTX_EP_REQTYPE_NONE:
438423c8a29SSathesh Edara 	default:
439f665790aSDavid Marchand 		otx_ep_info("This iqreq mode is not supported:%d", reqtype);
440423c8a29SSathesh Edara 	}
441423c8a29SSathesh Edara 
442423c8a29SSathesh Edara 	/* Reset the request list at this index */
4433db81df3SVamsi Attunuru 	iq->req_list[idx].finfo.mbuf = NULL;
444423c8a29SSathesh Edara 	iq->req_list[idx].reqtype = 0;
445423c8a29SSathesh Edara }
446423c8a29SSathesh Edara 
447423c8a29SSathesh Edara static inline void
4483db81df3SVamsi Attunuru otx_ep_iqreq_add(struct otx_ep_instr_queue *iq, struct rte_mbuf *mbuf,
449423c8a29SSathesh Edara 		uint32_t reqtype, int index)
450423c8a29SSathesh Edara {
4513db81df3SVamsi Attunuru 	iq->req_list[index].finfo.mbuf = mbuf;
452423c8a29SSathesh Edara 	iq->req_list[index].reqtype = reqtype;
453423c8a29SSathesh Edara }
454423c8a29SSathesh Edara 
455423c8a29SSathesh Edara static uint32_t
456423c8a29SSathesh Edara otx_vf_update_read_index(struct otx_ep_instr_queue *iq)
457423c8a29SSathesh Edara {
458d360d7bfSSathesh Edara 	uint32_t val;
459d360d7bfSSathesh Edara 
460d360d7bfSSathesh Edara 	/*
461d360d7bfSSathesh Edara 	 * Batch subtractions from the HW counter to reduce PCIe traffic
462d360d7bfSSathesh Edara 	 * This adds an extra local variable, but almost halves the
463d360d7bfSSathesh Edara 	 * number of PCIe writes.
464d360d7bfSSathesh Edara 	 */
465d360d7bfSSathesh Edara 	val = *iq->inst_cnt_ism;
466831cf744SVamsi Attunuru 	iq->inst_cnt += val - iq->inst_cnt_prev;
467831cf744SVamsi Attunuru 	iq->inst_cnt_prev = val;
468d360d7bfSSathesh Edara 
469d360d7bfSSathesh Edara 	if (val > (uint32_t)(1 << 31)) {
470d360d7bfSSathesh Edara 		/*
471d360d7bfSSathesh Edara 		 * Only subtract the packet count in the HW counter
472d360d7bfSSathesh Edara 		 * when count above halfway to saturation.
473d360d7bfSSathesh Edara 		 */
474d360d7bfSSathesh Edara 		rte_write32(val, iq->inst_cnt_reg);
475859ba654SVamsi Attunuru 		rte_mb();
476859ba654SVamsi Attunuru 
477859ba654SVamsi Attunuru 		rte_write64(OTX2_SDP_REQUEST_ISM, iq->inst_cnt_reg);
478e12a0166STyler Retzlaff 		while (rte_atomic_load_explicit(iq->inst_cnt_ism,
479e12a0166STyler Retzlaff 				rte_memory_order_relaxed) >= val) {
480859ba654SVamsi Attunuru 			rte_write64(OTX2_SDP_REQUEST_ISM, iq->inst_cnt_reg);
481859ba654SVamsi Attunuru 			rte_mb();
482859ba654SVamsi Attunuru 		}
483859ba654SVamsi Attunuru 
484831cf744SVamsi Attunuru 		iq->inst_cnt_prev = 0;
485d360d7bfSSathesh Edara 	}
486d360d7bfSSathesh Edara 	rte_write64(OTX2_SDP_REQUEST_ISM, iq->inst_cnt_reg);
487d360d7bfSSathesh Edara 
488423c8a29SSathesh Edara 	/* Modulo of the new index with the IQ size will give us
489423c8a29SSathesh Edara 	 * the new index.
490423c8a29SSathesh Edara 	 */
491d360d7bfSSathesh Edara 	return iq->inst_cnt & (iq->nb_desc - 1);
492423c8a29SSathesh Edara }
493423c8a29SSathesh Edara 
494423c8a29SSathesh Edara static void
495423c8a29SSathesh Edara otx_ep_flush_iq(struct otx_ep_instr_queue *iq)
496423c8a29SSathesh Edara {
497423c8a29SSathesh Edara 	uint32_t instr_processed = 0;
498423c8a29SSathesh Edara 
499423c8a29SSathesh Edara 	iq->otx_read_index = otx_vf_update_read_index(iq);
500423c8a29SSathesh Edara 	while (iq->flush_index != iq->otx_read_index) {
501423c8a29SSathesh Edara 		/* Free the IQ data buffer to the pool */
502423c8a29SSathesh Edara 		otx_ep_iqreq_delete(iq, iq->flush_index);
503423c8a29SSathesh Edara 		iq->flush_index =
504423c8a29SSathesh Edara 			otx_ep_incr_index(iq->flush_index, 1, iq->nb_desc);
505423c8a29SSathesh Edara 
506423c8a29SSathesh Edara 		instr_processed++;
507423c8a29SSathesh Edara 	}
508423c8a29SSathesh Edara 
509423c8a29SSathesh Edara 	iq->stats.instr_processed = instr_processed;
510423c8a29SSathesh Edara 	iq->instr_pending -= instr_processed;
511423c8a29SSathesh Edara }
512423c8a29SSathesh Edara 
513423c8a29SSathesh Edara static inline void
514423c8a29SSathesh Edara otx_ep_ring_doorbell(struct otx_ep_device *otx_ep __rte_unused,
515423c8a29SSathesh Edara 		struct otx_ep_instr_queue *iq)
516423c8a29SSathesh Edara {
517423c8a29SSathesh Edara 	rte_wmb();
518423c8a29SSathesh Edara 	rte_write64(iq->fill_cnt, iq->doorbell_reg);
519423c8a29SSathesh Edara 	iq->fill_cnt = 0;
520423c8a29SSathesh Edara }
521423c8a29SSathesh Edara 
522423c8a29SSathesh Edara static inline int
523423c8a29SSathesh Edara post_iqcmd(struct otx_ep_instr_queue *iq, uint8_t *iqcmd)
524423c8a29SSathesh Edara {
525423c8a29SSathesh Edara 	uint8_t *iqptr, cmdsize;
526423c8a29SSathesh Edara 
527423c8a29SSathesh Edara 	/* This ensures that the read index does not wrap around to
528423c8a29SSathesh Edara 	 * the same position if queue gets full before OCTEON 9 could
529423c8a29SSathesh Edara 	 * fetch any instr.
530423c8a29SSathesh Edara 	 */
531423c8a29SSathesh Edara 	if (iq->instr_pending > (iq->nb_desc - 1))
532423c8a29SSathesh Edara 		return OTX_EP_IQ_SEND_FAILED;
533423c8a29SSathesh Edara 
534423c8a29SSathesh Edara 	/* Copy cmd into iq */
535423c8a29SSathesh Edara 	cmdsize = 64;
536423c8a29SSathesh Edara 	iqptr   = iq->base_addr + (iq->host_write_index << 6);
537423c8a29SSathesh Edara 
538423c8a29SSathesh Edara 	rte_memcpy(iqptr, iqcmd, cmdsize);
539423c8a29SSathesh Edara 
540423c8a29SSathesh Edara 	/* Increment the host write index */
541423c8a29SSathesh Edara 	iq->host_write_index =
542423c8a29SSathesh Edara 		otx_ep_incr_index(iq->host_write_index, 1, iq->nb_desc);
543423c8a29SSathesh Edara 
544423c8a29SSathesh Edara 	iq->fill_cnt++;
545423c8a29SSathesh Edara 
546423c8a29SSathesh Edara 	/* Flush the command into memory. We need to be sure the data
547423c8a29SSathesh Edara 	 * is in memory before indicating that the instruction is
548423c8a29SSathesh Edara 	 * pending.
549423c8a29SSathesh Edara 	 */
550423c8a29SSathesh Edara 	iq->instr_pending++;
551423c8a29SSathesh Edara 	/* OTX_EP_IQ_SEND_SUCCESS */
552423c8a29SSathesh Edara 	return 0;
553423c8a29SSathesh Edara }
554423c8a29SSathesh Edara 
555423c8a29SSathesh Edara 
556423c8a29SSathesh Edara static int
557423c8a29SSathesh Edara otx_ep_send_data(struct otx_ep_device *otx_ep, struct otx_ep_instr_queue *iq,
558423c8a29SSathesh Edara 		 void *cmd, int dbell)
559423c8a29SSathesh Edara {
560423c8a29SSathesh Edara 	uint32_t ret;
561423c8a29SSathesh Edara 
562423c8a29SSathesh Edara 	/* Submit IQ command */
563423c8a29SSathesh Edara 	ret = post_iqcmd(iq, cmd);
564423c8a29SSathesh Edara 
565423c8a29SSathesh Edara 	if (ret == OTX_EP_IQ_SEND_SUCCESS) {
566423c8a29SSathesh Edara 		if (dbell)
567423c8a29SSathesh Edara 			otx_ep_ring_doorbell(otx_ep, iq);
568423c8a29SSathesh Edara 		iq->stats.instr_posted++;
569423c8a29SSathesh Edara 
570423c8a29SSathesh Edara 	} else {
571423c8a29SSathesh Edara 		iq->stats.instr_dropped++;
572423c8a29SSathesh Edara 		if (iq->fill_cnt)
573423c8a29SSathesh Edara 			otx_ep_ring_doorbell(otx_ep, iq);
574423c8a29SSathesh Edara 	}
575423c8a29SSathesh Edara 	return ret;
576423c8a29SSathesh Edara }
577423c8a29SSathesh Edara 
578423c8a29SSathesh Edara static inline void
579423c8a29SSathesh Edara set_sg_size(struct otx_ep_sg_entry *sg_entry, uint16_t size, uint32_t pos)
580423c8a29SSathesh Edara {
581423c8a29SSathesh Edara #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
582423c8a29SSathesh Edara 	sg_entry->u.size[pos] = size;
583423c8a29SSathesh Edara #elif RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5843db81df3SVamsi Attunuru 	sg_entry->u.size[(OTX_EP_NUM_SG_PTRS - 1) - pos] = size;
585423c8a29SSathesh Edara #endif
586423c8a29SSathesh Edara }
587423c8a29SSathesh Edara 
5883db81df3SVamsi Attunuru static inline int
5893db81df3SVamsi Attunuru prepare_xmit_gather_list(struct otx_ep_instr_queue *iq, struct rte_mbuf *m, uint64_t *dptr,
5903db81df3SVamsi Attunuru 			 union otx_ep_instr_ih *ih)
5913db81df3SVamsi Attunuru {
5923db81df3SVamsi Attunuru 	uint16_t j = 0, frags, num_sg, mask = OTX_EP_NUM_SG_PTRS - 1;
5933db81df3SVamsi Attunuru 	struct otx_ep_buf_free_info *finfo;
5943db81df3SVamsi Attunuru 	uint32_t pkt_len;
5953db81df3SVamsi Attunuru 	int rc = -1;
5963db81df3SVamsi Attunuru 
5973db81df3SVamsi Attunuru 	pkt_len = rte_pktmbuf_pkt_len(m);
5983db81df3SVamsi Attunuru 	frags = m->nb_segs;
5993db81df3SVamsi Attunuru 	num_sg = (frags + mask) / OTX_EP_NUM_SG_PTRS;
6003db81df3SVamsi Attunuru 
6013db81df3SVamsi Attunuru 	if (unlikely(pkt_len > OTX_EP_MAX_PKT_SZ && num_sg > OTX_EP_MAX_SG_LISTS)) {
602f665790aSDavid Marchand 		otx_ep_err("Failed to xmit the pkt, pkt_len is higher or pkt has more segments");
6033db81df3SVamsi Attunuru 		goto exit;
6043db81df3SVamsi Attunuru 	}
6053db81df3SVamsi Attunuru 
6063db81df3SVamsi Attunuru 	finfo = &iq->req_list[iq->host_write_index].finfo;
6073db81df3SVamsi Attunuru 	*dptr = rte_mem_virt2iova(finfo->g.sg);
608859ba654SVamsi Attunuru 	ih->u64 |= ((1ULL << 62) | ((uint64_t)frags << 48) | (pkt_len + ih->s.fsz));
6093db81df3SVamsi Attunuru 
6103db81df3SVamsi Attunuru 	while (frags--) {
6113db81df3SVamsi Attunuru 		finfo->g.sg[(j >> 2)].ptr[(j & mask)] = rte_mbuf_data_iova(m);
6123db81df3SVamsi Attunuru 		set_sg_size(&finfo->g.sg[(j >> 2)], m->data_len, (j & mask));
6133db81df3SVamsi Attunuru 		j++;
6143db81df3SVamsi Attunuru 		m = m->next;
6153db81df3SVamsi Attunuru 	}
6163db81df3SVamsi Attunuru 
6173db81df3SVamsi Attunuru 	return 0;
6183db81df3SVamsi Attunuru 
6193db81df3SVamsi Attunuru exit:
6203db81df3SVamsi Attunuru 	return rc;
6213db81df3SVamsi Attunuru }
6223db81df3SVamsi Attunuru 
623423c8a29SSathesh Edara /* Enqueue requests/packets to OTX_EP IQ queue.
624423c8a29SSathesh Edara  * returns number of requests enqueued successfully
625423c8a29SSathesh Edara  */
626423c8a29SSathesh Edara uint16_t
627423c8a29SSathesh Edara otx_ep_xmit_pkts(void *tx_queue, struct rte_mbuf **pkts, uint16_t nb_pkts)
628423c8a29SSathesh Edara {
6293db81df3SVamsi Attunuru 	struct otx_ep_instr_queue *iq = (struct otx_ep_instr_queue *)tx_queue;
6303db81df3SVamsi Attunuru 	struct otx_ep_device *otx_ep = iq->otx_ep_dev;
631423c8a29SSathesh Edara 	struct otx_ep_instr_64B iqcmd;
632423c8a29SSathesh Edara 	int dbell, index, count = 0;
6333db81df3SVamsi Attunuru 	uint32_t iqreq_type;
6343db81df3SVamsi Attunuru 	uint32_t pkt_len, i;
6353db81df3SVamsi Attunuru 	struct rte_mbuf *m;
636423c8a29SSathesh Edara 
637423c8a29SSathesh Edara 	iqcmd.ih.u64 = 0;
638423c8a29SSathesh Edara 	iqcmd.pki_ih3.u64 = 0;
639423c8a29SSathesh Edara 	iqcmd.irh.u64 = 0;
640423c8a29SSathesh Edara 
641423c8a29SSathesh Edara 	/* ih invars */
642423c8a29SSathesh Edara 	iqcmd.ih.s.fsz = OTX_EP_FSZ;
643423c8a29SSathesh Edara 	iqcmd.ih.s.pkind = otx_ep->pkind; /* The SDK decided PKIND value */
644423c8a29SSathesh Edara 
645423c8a29SSathesh Edara 	/* pki ih3 invars */
646423c8a29SSathesh Edara 	iqcmd.pki_ih3.s.w = 1;
647423c8a29SSathesh Edara 	iqcmd.pki_ih3.s.utt = 1;
648423c8a29SSathesh Edara 	iqcmd.pki_ih3.s.tagtype = ORDERED_TAG;
649423c8a29SSathesh Edara 	/* sl will be sizeof(pki_ih3) */
650423c8a29SSathesh Edara 	iqcmd.pki_ih3.s.sl = OTX_EP_FSZ + OTX_CUST_DATA_LEN;
651423c8a29SSathesh Edara 
652423c8a29SSathesh Edara 	/* irh invars */
653423c8a29SSathesh Edara 	iqcmd.irh.s.opcode = OTX_EP_NW_PKT_OP;
654423c8a29SSathesh Edara 
655423c8a29SSathesh Edara 	for (i = 0; i < nb_pkts; i++) {
656423c8a29SSathesh Edara 		m = pkts[i];
657423c8a29SSathesh Edara 		if (m->nb_segs == 1) {
658423c8a29SSathesh Edara 			pkt_len = rte_pktmbuf_data_len(m);
6593db81df3SVamsi Attunuru 			iqcmd.ih.s.tlen = pkt_len + iqcmd.ih.s.fsz;
6603db81df3SVamsi Attunuru 			iqcmd.dptr = rte_mbuf_data_iova(m); /*dptr*/
6613db81df3SVamsi Attunuru 			iqcmd.ih.s.gather = 0;
6623db81df3SVamsi Attunuru 			iqcmd.ih.s.gsz = 0;
663423c8a29SSathesh Edara 			iqreq_type = OTX_EP_REQTYPE_NORESP_NET;
664423c8a29SSathesh Edara 		} else {
665423c8a29SSathesh Edara 			if (!(otx_ep->tx_offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS))
666423c8a29SSathesh Edara 				goto xmit_fail;
667423c8a29SSathesh Edara 
6683db81df3SVamsi Attunuru 			if (unlikely(prepare_xmit_gather_list(iq, m, &iqcmd.dptr, &iqcmd.ih) < 0))
669423c8a29SSathesh Edara 				goto xmit_fail;
670423c8a29SSathesh Edara 
6713db81df3SVamsi Attunuru 			pkt_len = rte_pktmbuf_pkt_len(m);
672423c8a29SSathesh Edara 			iqreq_type = OTX_EP_REQTYPE_NORESP_GATHER;
673423c8a29SSathesh Edara 		}
674423c8a29SSathesh Edara 
6753db81df3SVamsi Attunuru 		iqcmd.irh.u64 = rte_bswap64(iqcmd.irh.u64);
676423c8a29SSathesh Edara 
677423c8a29SSathesh Edara #ifdef OTX_EP_IO_DEBUG
678f665790aSDavid Marchand 		otx_ep_dbg("After swapping");
679f665790aSDavid Marchand 		otx_ep_dbg("Word0 [dptr]: 0x%016lx",
680423c8a29SSathesh Edara 			   (unsigned long)iqcmd.dptr);
681f665790aSDavid Marchand 		otx_ep_dbg("Word1 [ihtx]: 0x%016lx", (unsigned long)iqcmd.ih);
682f665790aSDavid Marchand 		otx_ep_dbg("Word2 [pki_ih3]: 0x%016lx",
683423c8a29SSathesh Edara 			   (unsigned long)iqcmd.pki_ih3);
684f665790aSDavid Marchand 		otx_ep_dbg("Word3 [rptr]: 0x%016lx",
685423c8a29SSathesh Edara 			   (unsigned long)iqcmd.rptr);
686f665790aSDavid Marchand 		otx_ep_dbg("Word4 [irh]: 0x%016lx", (unsigned long)iqcmd.irh);
687f665790aSDavid Marchand 		otx_ep_dbg("Word5 [exhdr[0]]: 0x%016lx",
688423c8a29SSathesh Edara 				(unsigned long)iqcmd.exhdr[0]);
689423c8a29SSathesh Edara 		rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
690423c8a29SSathesh Edara #endif
691423c8a29SSathesh Edara 		dbell = (i == (unsigned int)(nb_pkts - 1)) ? 1 : 0;
692423c8a29SSathesh Edara 		index = iq->host_write_index;
693423c8a29SSathesh Edara 		if (otx_ep_send_data(otx_ep, iq, &iqcmd, dbell))
694423c8a29SSathesh Edara 			goto xmit_fail;
6953db81df3SVamsi Attunuru 		otx_ep_iqreq_add(iq, m, iqreq_type, index);
696423c8a29SSathesh Edara 		iq->stats.tx_pkts++;
697423c8a29SSathesh Edara 		iq->stats.tx_bytes += pkt_len;
698423c8a29SSathesh Edara 		count++;
699423c8a29SSathesh Edara 	}
700423c8a29SSathesh Edara 
701423c8a29SSathesh Edara xmit_fail:
702423c8a29SSathesh Edara 	if (iq->instr_pending >= OTX_EP_MAX_INSTR)
703423c8a29SSathesh Edara 		otx_ep_flush_iq(iq);
704423c8a29SSathesh Edara 
705423c8a29SSathesh Edara 	/* Return no# of instructions posted successfully. */
706423c8a29SSathesh Edara 	return count;
707423c8a29SSathesh Edara }
708423c8a29SSathesh Edara 
709423c8a29SSathesh Edara static uint32_t
710423c8a29SSathesh Edara otx_ep_droq_refill(struct otx_ep_droq *droq)
711423c8a29SSathesh Edara {
712859ba654SVamsi Attunuru 	struct otx_ep_droq_desc *desc_ring = droq->desc_ring;
713423c8a29SSathesh Edara 	struct otx_ep_droq_info *info;
714423c8a29SSathesh Edara 	struct rte_mbuf *buf = NULL;
715423c8a29SSathesh Edara 	uint32_t desc_refilled = 0;
716423c8a29SSathesh Edara 
717423c8a29SSathesh Edara 	while (droq->refill_count && (desc_refilled < droq->nb_desc)) {
718423c8a29SSathesh Edara 		buf = rte_pktmbuf_alloc(droq->mpool);
719423c8a29SSathesh Edara 		/* If a buffer could not be allocated, no point in
720423c8a29SSathesh Edara 		 * continuing
721423c8a29SSathesh Edara 		 */
722859ba654SVamsi Attunuru 		if (unlikely(!buf)) {
723423c8a29SSathesh Edara 			droq->stats.rx_alloc_failure++;
724423c8a29SSathesh Edara 			break;
725423c8a29SSathesh Edara 		}
726423c8a29SSathesh Edara 		info = rte_pktmbuf_mtod(buf, struct otx_ep_droq_info *);
727859ba654SVamsi Attunuru 		info->length = 0;
728423c8a29SSathesh Edara 
729423c8a29SSathesh Edara 		droq->recv_buf_list[droq->refill_idx] = buf;
730423c8a29SSathesh Edara 		desc_ring[droq->refill_idx].buffer_ptr =
731423c8a29SSathesh Edara 					rte_mbuf_data_iova_default(buf);
732423c8a29SSathesh Edara 		droq->refill_idx = otx_ep_incr_index(droq->refill_idx, 1,
733423c8a29SSathesh Edara 				droq->nb_desc);
734423c8a29SSathesh Edara 
735423c8a29SSathesh Edara 		desc_refilled++;
736423c8a29SSathesh Edara 		droq->refill_count--;
737423c8a29SSathesh Edara 	}
738423c8a29SSathesh Edara 
739423c8a29SSathesh Edara 	return desc_refilled;
740423c8a29SSathesh Edara }
741423c8a29SSathesh Edara 
742423c8a29SSathesh Edara static struct rte_mbuf *
743859ba654SVamsi Attunuru otx_ep_droq_read_packet(struct otx_ep_device *otx_ep, struct otx_ep_droq *droq, int next_fetch)
744423c8a29SSathesh Edara {
745423c8a29SSathesh Edara 	volatile struct otx_ep_droq_info *info;
746859ba654SVamsi Attunuru 	struct rte_mbuf *mbuf_next = NULL;
747859ba654SVamsi Attunuru 	struct rte_mbuf *mbuf = NULL;
748423c8a29SSathesh Edara 	uint64_t total_pkt_len;
749423c8a29SSathesh Edara 	uint32_t pkt_len = 0;
750423c8a29SSathesh Edara 	int next_idx;
751423c8a29SSathesh Edara 
752859ba654SVamsi Attunuru 	mbuf = droq->recv_buf_list[droq->read_idx];
753859ba654SVamsi Attunuru 	info = rte_pktmbuf_mtod(mbuf, struct otx_ep_droq_info *);
754859ba654SVamsi Attunuru 
755423c8a29SSathesh Edara 	/* make sure info is available */
756423c8a29SSathesh Edara 	rte_rmb();
757423c8a29SSathesh Edara 	if (unlikely(!info->length)) {
758423c8a29SSathesh Edara 		int retry = OTX_EP_MAX_DELAYED_PKT_RETRIES;
759423c8a29SSathesh Edara 		/* otx_ep_dbg("OCTEON DROQ[%d]: read_idx: %d; Data not ready "
760f665790aSDavid Marchand 		 * "yet, Retry; pending=%lu", droq->q_no, droq->read_idx,
761423c8a29SSathesh Edara 		 * droq->pkts_pending);
762423c8a29SSathesh Edara 		 */
763423c8a29SSathesh Edara 		droq->stats.pkts_delayed_data++;
764dfa2f825SSathesh Edara 		while (retry && !info->length) {
765423c8a29SSathesh Edara 			retry--;
766dfa2f825SSathesh Edara 			rte_delay_us_block(50);
767dfa2f825SSathesh Edara 		}
768423c8a29SSathesh Edara 		if (!retry && !info->length) {
769f665790aSDavid Marchand 			otx_ep_err("OCTEON DROQ[%d]: read_idx: %d; Retry failed !!",
770423c8a29SSathesh Edara 				   droq->q_no, droq->read_idx);
771423c8a29SSathesh Edara 			/* May be zero length packet; drop it */
772dfa2f825SSathesh Edara 			assert(0);
773423c8a29SSathesh Edara 		}
774423c8a29SSathesh Edara 	}
775859ba654SVamsi Attunuru 
776423c8a29SSathesh Edara 	if (next_fetch) {
777423c8a29SSathesh Edara 		next_idx = otx_ep_incr_index(droq->read_idx, 1, droq->nb_desc);
778859ba654SVamsi Attunuru 		mbuf_next = droq->recv_buf_list[next_idx];
779859ba654SVamsi Attunuru 		rte_prefetch0(rte_pktmbuf_mtod(mbuf_next, void *));
780423c8a29SSathesh Edara 	}
781423c8a29SSathesh Edara 
782859ba654SVamsi Attunuru 	info->length = rte_bswap16(info->length >> 48);
783423c8a29SSathesh Edara 	/* Deduce the actual data size */
7844e356755SSathesh Edara 	total_pkt_len = info->length + OTX_EP_INFO_SIZE;
785423c8a29SSathesh Edara 	if (total_pkt_len <= droq->buffer_size) {
786859ba654SVamsi Attunuru 		mbuf->data_off += OTX_EP_INFO_SIZE;
787423c8a29SSathesh Edara 		pkt_len = (uint32_t)info->length;
788859ba654SVamsi Attunuru 		mbuf->pkt_len  = pkt_len;
789859ba654SVamsi Attunuru 		mbuf->data_len  = pkt_len;
790859ba654SVamsi Attunuru 		mbuf->port = otx_ep->port_id;
791423c8a29SSathesh Edara 		droq->recv_buf_list[droq->read_idx] = NULL;
792859ba654SVamsi Attunuru 		droq->read_idx = otx_ep_incr_index(droq->read_idx, 1, droq->nb_desc);
793423c8a29SSathesh Edara 		droq->refill_count++;
794423c8a29SSathesh Edara 	} else {
795423c8a29SSathesh Edara 		struct rte_mbuf *first_buf = NULL;
796423c8a29SSathesh Edara 		struct rte_mbuf *last_buf = NULL;
797423c8a29SSathesh Edara 
798742a8c3cSSathesh Edara 		/* csr read helps to flush pending dma */
799742a8c3cSSathesh Edara 		droq->sent_reg_val = rte_read32(droq->pkts_sent_reg);
800742a8c3cSSathesh Edara 		rte_rmb();
801742a8c3cSSathesh Edara 
802423c8a29SSathesh Edara 		while (pkt_len < total_pkt_len) {
803423c8a29SSathesh Edara 			int cpy_len = 0;
804423c8a29SSathesh Edara 
805859ba654SVamsi Attunuru 			cpy_len = ((pkt_len + droq->buffer_size) > total_pkt_len)
806859ba654SVamsi Attunuru 					? ((uint32_t)total_pkt_len - pkt_len)
807423c8a29SSathesh Edara 					: droq->buffer_size;
808423c8a29SSathesh Edara 
809859ba654SVamsi Attunuru 			mbuf = droq->recv_buf_list[droq->read_idx];
810423c8a29SSathesh Edara 			droq->recv_buf_list[droq->read_idx] = NULL;
811423c8a29SSathesh Edara 
812859ba654SVamsi Attunuru 			if (likely(mbuf)) {
813423c8a29SSathesh Edara 				/* Note the first seg */
814423c8a29SSathesh Edara 				if (!pkt_len)
815859ba654SVamsi Attunuru 					first_buf = mbuf;
816423c8a29SSathesh Edara 
817859ba654SVamsi Attunuru 				mbuf->port = otx_ep->port_id;
818423c8a29SSathesh Edara 				if (!pkt_len) {
819859ba654SVamsi Attunuru 					mbuf->data_off += OTX_EP_INFO_SIZE;
820859ba654SVamsi Attunuru 					mbuf->pkt_len = cpy_len - OTX_EP_INFO_SIZE;
821859ba654SVamsi Attunuru 					mbuf->data_len = cpy_len - OTX_EP_INFO_SIZE;
822423c8a29SSathesh Edara 				} else {
823859ba654SVamsi Attunuru 					mbuf->pkt_len = cpy_len;
824859ba654SVamsi Attunuru 					mbuf->data_len = cpy_len;
825423c8a29SSathesh Edara 				}
826423c8a29SSathesh Edara 
827423c8a29SSathesh Edara 				if (pkt_len) {
828423c8a29SSathesh Edara 					first_buf->nb_segs++;
829859ba654SVamsi Attunuru 					first_buf->pkt_len += mbuf->pkt_len;
830423c8a29SSathesh Edara 				}
831423c8a29SSathesh Edara 
832423c8a29SSathesh Edara 				if (last_buf)
833859ba654SVamsi Attunuru 					last_buf->next = mbuf;
834423c8a29SSathesh Edara 
835859ba654SVamsi Attunuru 				last_buf = mbuf;
836423c8a29SSathesh Edara 			} else {
837f665790aSDavid Marchand 				otx_ep_err("no buf");
838dfa2f825SSathesh Edara 				assert(0);
839423c8a29SSathesh Edara 			}
840423c8a29SSathesh Edara 
841423c8a29SSathesh Edara 			pkt_len += cpy_len;
842859ba654SVamsi Attunuru 			droq->read_idx = otx_ep_incr_index(droq->read_idx, 1, droq->nb_desc);
843423c8a29SSathesh Edara 			droq->refill_count++;
844423c8a29SSathesh Edara 		}
845859ba654SVamsi Attunuru 		mbuf = first_buf;
846423c8a29SSathesh Edara 	}
847423c8a29SSathesh Edara 
848859ba654SVamsi Attunuru 	return mbuf;
849423c8a29SSathesh Edara }
850423c8a29SSathesh Edara 
851423c8a29SSathesh Edara static inline uint32_t
852423c8a29SSathesh Edara otx_ep_check_droq_pkts(struct otx_ep_droq *droq)
853423c8a29SSathesh Edara {
854423c8a29SSathesh Edara 	uint32_t new_pkts;
855d360d7bfSSathesh Edara 	uint32_t val;
856423c8a29SSathesh Edara 
857d360d7bfSSathesh Edara 	/*
858d360d7bfSSathesh Edara 	 * Batch subtractions from the HW counter to reduce PCIe traffic
859d360d7bfSSathesh Edara 	 * This adds an extra local variable, but almost halves the
860d360d7bfSSathesh Edara 	 * number of PCIe writes.
861d360d7bfSSathesh Edara 	 */
862d360d7bfSSathesh Edara 	val = *droq->pkts_sent_ism;
863831cf744SVamsi Attunuru 	new_pkts = val - droq->pkts_sent_prev;
864831cf744SVamsi Attunuru 	droq->pkts_sent_prev = val;
865d360d7bfSSathesh Edara 
866d360d7bfSSathesh Edara 	if (val > (uint32_t)(1 << 31)) {
867d360d7bfSSathesh Edara 		/*
868d360d7bfSSathesh Edara 		 * Only subtract the packet count in the HW counter
869d360d7bfSSathesh Edara 		 * when count above halfway to saturation.
870d360d7bfSSathesh Edara 		 */
871d360d7bfSSathesh Edara 		rte_write32(val, droq->pkts_sent_reg);
872859ba654SVamsi Attunuru 		rte_mb();
873859ba654SVamsi Attunuru 
874859ba654SVamsi Attunuru 		rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
875e12a0166STyler Retzlaff 		while (rte_atomic_load_explicit(droq->pkts_sent_ism,
876e12a0166STyler Retzlaff 				rte_memory_order_relaxed) >= val) {
877859ba654SVamsi Attunuru 			rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
878859ba654SVamsi Attunuru 			rte_mb();
879859ba654SVamsi Attunuru 		}
880859ba654SVamsi Attunuru 
881831cf744SVamsi Attunuru 		droq->pkts_sent_prev = 0;
882d360d7bfSSathesh Edara 	}
883d360d7bfSSathesh Edara 	rte_write64(OTX2_SDP_REQUEST_ISM, droq->pkts_sent_reg);
884423c8a29SSathesh Edara 	droq->pkts_pending += new_pkts;
885d360d7bfSSathesh Edara 
886423c8a29SSathesh Edara 	return new_pkts;
887423c8a29SSathesh Edara }
888423c8a29SSathesh Edara 
889859ba654SVamsi Attunuru static inline int32_t __rte_hot
890859ba654SVamsi Attunuru otx_ep_rx_pkts_to_process(struct otx_ep_droq *droq, uint16_t nb_pkts)
891859ba654SVamsi Attunuru {
892859ba654SVamsi Attunuru 	if (unlikely(droq->pkts_pending < nb_pkts))
893859ba654SVamsi Attunuru 		otx_ep_check_droq_pkts(droq);
894859ba654SVamsi Attunuru 
895859ba654SVamsi Attunuru 	return RTE_MIN(nb_pkts, droq->pkts_pending);
896859ba654SVamsi Attunuru }
897859ba654SVamsi Attunuru 
898423c8a29SSathesh Edara /* Check for response arrival from OCTEON 9
899423c8a29SSathesh Edara  * returns number of requests completed
900423c8a29SSathesh Edara  */
901423c8a29SSathesh Edara uint16_t
902859ba654SVamsi Attunuru otx_ep_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
903423c8a29SSathesh Edara {
904423c8a29SSathesh Edara 	struct otx_ep_droq *droq = rx_queue;
905423c8a29SSathesh Edara 	struct otx_ep_device *otx_ep;
906423c8a29SSathesh Edara 	struct rte_mbuf *oq_pkt;
907859ba654SVamsi Attunuru 	uint16_t pkts, new_pkts;
908dfa2f825SSathesh Edara 	uint32_t valid_pkts = 0;
909423c8a29SSathesh Edara 	int next_fetch;
910423c8a29SSathesh Edara 
911423c8a29SSathesh Edara 	otx_ep = droq->otx_ep_dev;
912859ba654SVamsi Attunuru 	new_pkts = otx_ep_rx_pkts_to_process(droq, nb_pkts);
913423c8a29SSathesh Edara 
914423c8a29SSathesh Edara 	for (pkts = 0; pkts < new_pkts; pkts++) {
915423c8a29SSathesh Edara 		/* Push the received pkt to application */
916423c8a29SSathesh Edara 		next_fetch = (pkts == new_pkts - 1) ? 0 : 1;
917423c8a29SSathesh Edara 		oq_pkt = otx_ep_droq_read_packet(otx_ep, droq, next_fetch);
918423c8a29SSathesh Edara 		if (!oq_pkt) {
919*2b843cacSDavid Marchand 			RTE_LOG_DP_LINE(ERR, OTX_NET_EP,
920423c8a29SSathesh Edara 				   "DROQ read pkt failed pending %" PRIu64
921*2b843cacSDavid Marchand 				    "last_pkt_count %" PRIu64 "new_pkts %d.",
922423c8a29SSathesh Edara 				   droq->pkts_pending, droq->last_pkt_count,
923423c8a29SSathesh Edara 				   new_pkts);
924423c8a29SSathesh Edara 			droq->stats.rx_err++;
925dfa2f825SSathesh Edara 			continue;
926dfa2f825SSathesh Edara 		} else {
927dfa2f825SSathesh Edara 			rx_pkts[valid_pkts] = oq_pkt;
928dfa2f825SSathesh Edara 			valid_pkts++;
929423c8a29SSathesh Edara 			/* Stats */
930423c8a29SSathesh Edara 			droq->stats.pkts_received++;
931423c8a29SSathesh Edara 			droq->stats.bytes_received += oq_pkt->pkt_len;
932423c8a29SSathesh Edara 		}
933dfa2f825SSathesh Edara 	}
934423c8a29SSathesh Edara 	droq->pkts_pending -= pkts;
935423c8a29SSathesh Edara 
936423c8a29SSathesh Edara 	/* Refill DROQ buffers */
937423c8a29SSathesh Edara 	if (droq->refill_count >= DROQ_REFILL_THRESHOLD) {
938423c8a29SSathesh Edara 		int desc_refilled = otx_ep_droq_refill(droq);
939423c8a29SSathesh Edara 
940423c8a29SSathesh Edara 		/* Flush the droq descriptor data to memory to be sure
941423c8a29SSathesh Edara 		 * that when we update the credits the data in memory is
942423c8a29SSathesh Edara 		 * accurate.
943423c8a29SSathesh Edara 		 */
944859ba654SVamsi Attunuru 		rte_io_wmb();
945423c8a29SSathesh Edara 		rte_write32(desc_refilled, droq->pkts_credit_reg);
946423c8a29SSathesh Edara 	} else {
947423c8a29SSathesh Edara 		/*
948423c8a29SSathesh Edara 		 * SDP output goes into DROP state when output doorbell count
949423c8a29SSathesh Edara 		 * goes below drop count. When door bell count is written with
950423c8a29SSathesh Edara 		 * a value greater than drop count SDP output should come out
951423c8a29SSathesh Edara 		 * of DROP state. Due to a race condition this is not happening.
952423c8a29SSathesh Edara 		 * Writing doorbell register with 0 again may make SDP output
953423c8a29SSathesh Edara 		 * come out of this state.
954423c8a29SSathesh Edara 		 */
955423c8a29SSathesh Edara 
956423c8a29SSathesh Edara 		rte_write32(0, droq->pkts_credit_reg);
957423c8a29SSathesh Edara 	}
958dfa2f825SSathesh Edara 	return valid_pkts;
959423c8a29SSathesh Edara }
960