xref: /dpdk/drivers/net/ngbe/ngbe_rxtx.c (revision 711a06e896ba6307089bb6aa707c16ab3a110d20)
143b7e5eaSJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
243b7e5eaSJiawen Wu  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
343b7e5eaSJiawen Wu  * Copyright(c) 2010-2017 Intel Corporation
443b7e5eaSJiawen Wu  */
543b7e5eaSJiawen Wu 
643b7e5eaSJiawen Wu #include <sys/queue.h>
743b7e5eaSJiawen Wu 
843b7e5eaSJiawen Wu #include <stdint.h>
943b7e5eaSJiawen Wu #include <rte_ethdev.h>
1043b7e5eaSJiawen Wu #include <ethdev_driver.h>
1143b7e5eaSJiawen Wu #include <rte_malloc.h>
129f320614SJiawen Wu #include <rte_net.h>
13e94c20c3SJiawen Wu #include <rte_vect.h>
1443b7e5eaSJiawen Wu 
1543b7e5eaSJiawen Wu #include "ngbe_logs.h"
1643b7e5eaSJiawen Wu #include "base/ngbe.h"
1743b7e5eaSJiawen Wu #include "ngbe_ethdev.h"
1843b7e5eaSJiawen Wu #include "ngbe_rxtx.h"
1943b7e5eaSJiawen Wu 
2024cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588
2160ad04e2SGagandeep Singh #define NGBE_TX_IEEE1588_TMST RTE_MBUF_F_TX_IEEE1588_TMST
2224cd85f7SJiawen Wu #else
2324cd85f7SJiawen Wu #define NGBE_TX_IEEE1588_TMST 0
2424cd85f7SJiawen Wu #endif
2524cd85f7SJiawen Wu 
269f320614SJiawen Wu /* Bit Mask to indicate what bits required for building Tx context */
279f320614SJiawen Wu static const u64 NGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM |
289f320614SJiawen Wu 		RTE_MBUF_F_TX_IPV6 |
299f320614SJiawen Wu 		RTE_MBUF_F_TX_IPV4 |
3059b46438SJiawen Wu 		RTE_MBUF_F_TX_VLAN |
319f320614SJiawen Wu 		RTE_MBUF_F_TX_L4_MASK |
329f320614SJiawen Wu 		RTE_MBUF_F_TX_TCP_SEG |
3324cd85f7SJiawen Wu 		NGBE_TX_IEEE1588_TMST);
3424cd85f7SJiawen Wu 
359f320614SJiawen Wu #define NGBE_TX_OFFLOAD_NOTSUP_MASK \
369f320614SJiawen Wu 		(RTE_MBUF_F_TX_OFFLOAD_MASK ^ NGBE_TX_OFFLOAD_MASK)
379f320614SJiawen Wu 
3893dfebd2SJiawen Wu /*
3993dfebd2SJiawen Wu  * Prefetch a cache line into all cache levels.
4093dfebd2SJiawen Wu  */
4193dfebd2SJiawen Wu #define rte_ngbe_prefetch(p)   rte_prefetch0(p)
4293dfebd2SJiawen Wu 
4393dfebd2SJiawen Wu /*********************************************************************
4493dfebd2SJiawen Wu  *
45aad91eddSJiawen Wu  *  Tx functions
46aad91eddSJiawen Wu  *
47aad91eddSJiawen Wu  **********************************************************************/
48aad91eddSJiawen Wu 
49aad91eddSJiawen Wu /*
50aad91eddSJiawen Wu  * Check for descriptors with their DD bit set and free mbufs.
51aad91eddSJiawen Wu  * Return the total number of buffers freed.
52aad91eddSJiawen Wu  */
53aad91eddSJiawen Wu static __rte_always_inline int
54aad91eddSJiawen Wu ngbe_tx_free_bufs(struct ngbe_tx_queue *txq)
55aad91eddSJiawen Wu {
56aad91eddSJiawen Wu 	struct ngbe_tx_entry *txep;
57aad91eddSJiawen Wu 	uint32_t status;
58aad91eddSJiawen Wu 	int i, nb_free = 0;
59aad91eddSJiawen Wu 	struct rte_mbuf *m, *free[RTE_NGBE_TX_MAX_FREE_BUF_SZ];
60aad91eddSJiawen Wu 
61aad91eddSJiawen Wu 	/* check DD bit on threshold descriptor */
62aad91eddSJiawen Wu 	status = txq->tx_ring[txq->tx_next_dd].dw3;
63aad91eddSJiawen Wu 	if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) {
64aad91eddSJiawen Wu 		if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
65aad91eddSJiawen Wu 			ngbe_set32_masked(txq->tdc_reg_addr,
66aad91eddSJiawen Wu 				NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH);
67aad91eddSJiawen Wu 		return 0;
68aad91eddSJiawen Wu 	}
69aad91eddSJiawen Wu 
70aad91eddSJiawen Wu 	/*
71aad91eddSJiawen Wu 	 * first buffer to free from S/W ring is at index
72aad91eddSJiawen Wu 	 * tx_next_dd - (tx_free_thresh-1)
73aad91eddSJiawen Wu 	 */
74aad91eddSJiawen Wu 	txep = &txq->sw_ring[txq->tx_next_dd - (txq->tx_free_thresh - 1)];
75aad91eddSJiawen Wu 	for (i = 0; i < txq->tx_free_thresh; ++i, ++txep) {
76aad91eddSJiawen Wu 		/* free buffers one at a time */
77aad91eddSJiawen Wu 		m = rte_pktmbuf_prefree_seg(txep->mbuf);
78aad91eddSJiawen Wu 		txep->mbuf = NULL;
79aad91eddSJiawen Wu 
80aad91eddSJiawen Wu 		if (unlikely(m == NULL))
81aad91eddSJiawen Wu 			continue;
82aad91eddSJiawen Wu 
83aad91eddSJiawen Wu 		if (nb_free >= RTE_NGBE_TX_MAX_FREE_BUF_SZ ||
84aad91eddSJiawen Wu 		    (nb_free > 0 && m->pool != free[0]->pool)) {
85aad91eddSJiawen Wu 			rte_mempool_put_bulk(free[0]->pool,
86aad91eddSJiawen Wu 					     (void **)free, nb_free);
87aad91eddSJiawen Wu 			nb_free = 0;
88aad91eddSJiawen Wu 		}
89aad91eddSJiawen Wu 
90aad91eddSJiawen Wu 		free[nb_free++] = m;
91aad91eddSJiawen Wu 	}
92aad91eddSJiawen Wu 
93aad91eddSJiawen Wu 	if (nb_free > 0)
94aad91eddSJiawen Wu 		rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free);
95aad91eddSJiawen Wu 
96aad91eddSJiawen Wu 	/* buffers were freed, update counters */
97aad91eddSJiawen Wu 	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_free_thresh);
98aad91eddSJiawen Wu 	txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_free_thresh);
99aad91eddSJiawen Wu 	if (txq->tx_next_dd >= txq->nb_tx_desc)
100aad91eddSJiawen Wu 		txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1);
101aad91eddSJiawen Wu 
102aad91eddSJiawen Wu 	return txq->tx_free_thresh;
103aad91eddSJiawen Wu }
104aad91eddSJiawen Wu 
105aad91eddSJiawen Wu /* Populate 4 descriptors with data from 4 mbufs */
106aad91eddSJiawen Wu static inline void
107aad91eddSJiawen Wu tx4(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts)
108aad91eddSJiawen Wu {
109aad91eddSJiawen Wu 	uint64_t buf_dma_addr;
110aad91eddSJiawen Wu 	uint32_t pkt_len;
111aad91eddSJiawen Wu 	int i;
112aad91eddSJiawen Wu 
113aad91eddSJiawen Wu 	for (i = 0; i < 4; ++i, ++txdp, ++pkts) {
114aad91eddSJiawen Wu 		buf_dma_addr = rte_mbuf_data_iova(*pkts);
115aad91eddSJiawen Wu 		pkt_len = (*pkts)->data_len;
1168d75bf03SJiawen Wu 		if (pkt_len < RTE_ETHER_HDR_LEN)
1178d75bf03SJiawen Wu 			pkt_len = NGBE_FRAME_SIZE_DFT;
118aad91eddSJiawen Wu 
119aad91eddSJiawen Wu 		/* write data to descriptor */
120aad91eddSJiawen Wu 		txdp->qw0 = rte_cpu_to_le_64(buf_dma_addr);
121aad91eddSJiawen Wu 		txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS |
122aad91eddSJiawen Wu 					NGBE_TXD_DATLEN(pkt_len));
123aad91eddSJiawen Wu 		txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len));
124aad91eddSJiawen Wu 
125aad91eddSJiawen Wu 		rte_prefetch0(&(*pkts)->pool);
126aad91eddSJiawen Wu 	}
127aad91eddSJiawen Wu }
128aad91eddSJiawen Wu 
129aad91eddSJiawen Wu /* Populate 1 descriptor with data from 1 mbuf */
130aad91eddSJiawen Wu static inline void
131aad91eddSJiawen Wu tx1(volatile struct ngbe_tx_desc *txdp, struct rte_mbuf **pkts)
132aad91eddSJiawen Wu {
133aad91eddSJiawen Wu 	uint64_t buf_dma_addr;
134aad91eddSJiawen Wu 	uint32_t pkt_len;
135aad91eddSJiawen Wu 
136aad91eddSJiawen Wu 	buf_dma_addr = rte_mbuf_data_iova(*pkts);
137aad91eddSJiawen Wu 	pkt_len = (*pkts)->data_len;
1388d75bf03SJiawen Wu 	if (pkt_len < RTE_ETHER_HDR_LEN)
1398d75bf03SJiawen Wu 		pkt_len = NGBE_FRAME_SIZE_DFT;
140aad91eddSJiawen Wu 
141aad91eddSJiawen Wu 	/* write data to descriptor */
142aad91eddSJiawen Wu 	txdp->qw0 = cpu_to_le64(buf_dma_addr);
143aad91eddSJiawen Wu 	txdp->dw2 = cpu_to_le32(NGBE_TXD_FLAGS |
144aad91eddSJiawen Wu 				NGBE_TXD_DATLEN(pkt_len));
145aad91eddSJiawen Wu 	txdp->dw3 = cpu_to_le32(NGBE_TXD_PAYLEN(pkt_len));
146aad91eddSJiawen Wu 
147aad91eddSJiawen Wu 	rte_prefetch0(&(*pkts)->pool);
148aad91eddSJiawen Wu }
149aad91eddSJiawen Wu 
150aad91eddSJiawen Wu /*
151aad91eddSJiawen Wu  * Fill H/W descriptor ring with mbuf data.
152aad91eddSJiawen Wu  * Copy mbuf pointers to the S/W ring.
153aad91eddSJiawen Wu  */
154aad91eddSJiawen Wu static inline void
155aad91eddSJiawen Wu ngbe_tx_fill_hw_ring(struct ngbe_tx_queue *txq, struct rte_mbuf **pkts,
156aad91eddSJiawen Wu 		      uint16_t nb_pkts)
157aad91eddSJiawen Wu {
158aad91eddSJiawen Wu 	volatile struct ngbe_tx_desc *txdp = &txq->tx_ring[txq->tx_tail];
159aad91eddSJiawen Wu 	struct ngbe_tx_entry *txep = &txq->sw_ring[txq->tx_tail];
160aad91eddSJiawen Wu 	const int N_PER_LOOP = 4;
161aad91eddSJiawen Wu 	const int N_PER_LOOP_MASK = N_PER_LOOP - 1;
162aad91eddSJiawen Wu 	int mainpart, leftover;
163aad91eddSJiawen Wu 	int i, j;
164aad91eddSJiawen Wu 
165aad91eddSJiawen Wu 	/*
166aad91eddSJiawen Wu 	 * Process most of the packets in chunks of N pkts.  Any
167aad91eddSJiawen Wu 	 * leftover packets will get processed one at a time.
168aad91eddSJiawen Wu 	 */
169aad91eddSJiawen Wu 	mainpart = (nb_pkts & ((uint32_t)~N_PER_LOOP_MASK));
170aad91eddSJiawen Wu 	leftover = (nb_pkts & ((uint32_t)N_PER_LOOP_MASK));
171aad91eddSJiawen Wu 	for (i = 0; i < mainpart; i += N_PER_LOOP) {
172aad91eddSJiawen Wu 		/* Copy N mbuf pointers to the S/W ring */
173aad91eddSJiawen Wu 		for (j = 0; j < N_PER_LOOP; ++j)
174aad91eddSJiawen Wu 			(txep + i + j)->mbuf = *(pkts + i + j);
175aad91eddSJiawen Wu 		tx4(txdp + i, pkts + i);
176aad91eddSJiawen Wu 	}
177aad91eddSJiawen Wu 
178aad91eddSJiawen Wu 	if (unlikely(leftover > 0)) {
179aad91eddSJiawen Wu 		for (i = 0; i < leftover; ++i) {
180aad91eddSJiawen Wu 			(txep + mainpart + i)->mbuf = *(pkts + mainpart + i);
181aad91eddSJiawen Wu 			tx1(txdp + mainpart + i, pkts + mainpart + i);
182aad91eddSJiawen Wu 		}
183aad91eddSJiawen Wu 	}
184aad91eddSJiawen Wu }
185aad91eddSJiawen Wu 
186aad91eddSJiawen Wu static inline uint16_t
187aad91eddSJiawen Wu tx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
188aad91eddSJiawen Wu 	     uint16_t nb_pkts)
189aad91eddSJiawen Wu {
190aad91eddSJiawen Wu 	struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue;
191aad91eddSJiawen Wu 	uint16_t n = 0;
192aad91eddSJiawen Wu 
193aad91eddSJiawen Wu 	/*
194aad91eddSJiawen Wu 	 * Begin scanning the H/W ring for done descriptors when the
195aad91eddSJiawen Wu 	 * number of available descriptors drops below tx_free_thresh.
196aad91eddSJiawen Wu 	 * For each done descriptor, free the associated buffer.
197aad91eddSJiawen Wu 	 */
198aad91eddSJiawen Wu 	if (txq->nb_tx_free < txq->tx_free_thresh)
199aad91eddSJiawen Wu 		ngbe_tx_free_bufs(txq);
200aad91eddSJiawen Wu 
201aad91eddSJiawen Wu 	/* Only use descriptors that are available */
202aad91eddSJiawen Wu 	nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts);
203aad91eddSJiawen Wu 	if (unlikely(nb_pkts == 0))
204aad91eddSJiawen Wu 		return 0;
205aad91eddSJiawen Wu 
206aad91eddSJiawen Wu 	/* Use exactly nb_pkts descriptors */
207aad91eddSJiawen Wu 	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts);
208aad91eddSJiawen Wu 
209aad91eddSJiawen Wu 	/*
210aad91eddSJiawen Wu 	 * At this point, we know there are enough descriptors in the
211aad91eddSJiawen Wu 	 * ring to transmit all the packets.  This assumes that each
212aad91eddSJiawen Wu 	 * mbuf contains a single segment, and that no new offloads
213aad91eddSJiawen Wu 	 * are expected, which would require a new context descriptor.
214aad91eddSJiawen Wu 	 */
215aad91eddSJiawen Wu 
216aad91eddSJiawen Wu 	/*
217aad91eddSJiawen Wu 	 * See if we're going to wrap-around. If so, handle the top
218aad91eddSJiawen Wu 	 * of the descriptor ring first, then do the bottom.  If not,
219aad91eddSJiawen Wu 	 * the processing looks just like the "bottom" part anyway...
220aad91eddSJiawen Wu 	 */
221aad91eddSJiawen Wu 	if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) {
222aad91eddSJiawen Wu 		n = (uint16_t)(txq->nb_tx_desc - txq->tx_tail);
223aad91eddSJiawen Wu 		ngbe_tx_fill_hw_ring(txq, tx_pkts, n);
224aad91eddSJiawen Wu 		txq->tx_tail = 0;
225aad91eddSJiawen Wu 	}
226aad91eddSJiawen Wu 
227aad91eddSJiawen Wu 	/* Fill H/W descriptor ring with mbuf data */
228aad91eddSJiawen Wu 	ngbe_tx_fill_hw_ring(txq, tx_pkts + n, (uint16_t)(nb_pkts - n));
229aad91eddSJiawen Wu 	txq->tx_tail = (uint16_t)(txq->tx_tail + (nb_pkts - n));
230aad91eddSJiawen Wu 
231aad91eddSJiawen Wu 	/*
232aad91eddSJiawen Wu 	 * Check for wrap-around. This would only happen if we used
233aad91eddSJiawen Wu 	 * up to the last descriptor in the ring, no more, no less.
234aad91eddSJiawen Wu 	 */
235aad91eddSJiawen Wu 	if (txq->tx_tail >= txq->nb_tx_desc)
236aad91eddSJiawen Wu 		txq->tx_tail = 0;
237aad91eddSJiawen Wu 
238aad91eddSJiawen Wu 	PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u",
239aad91eddSJiawen Wu 		   (uint16_t)txq->port_id, (uint16_t)txq->queue_id,
240aad91eddSJiawen Wu 		   (uint16_t)txq->tx_tail, (uint16_t)nb_pkts);
241aad91eddSJiawen Wu 
242aad91eddSJiawen Wu 	/* update tail pointer */
243aad91eddSJiawen Wu 	rte_wmb();
244aad91eddSJiawen Wu 	ngbe_set32_relaxed(txq->tdt_reg_addr, txq->tx_tail);
245aad91eddSJiawen Wu 
246aad91eddSJiawen Wu 	return nb_pkts;
247aad91eddSJiawen Wu }
248aad91eddSJiawen Wu 
249aad91eddSJiawen Wu uint16_t
250aad91eddSJiawen Wu ngbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
251aad91eddSJiawen Wu 		       uint16_t nb_pkts)
252aad91eddSJiawen Wu {
253aad91eddSJiawen Wu 	uint16_t nb_tx;
254aad91eddSJiawen Wu 
255aad91eddSJiawen Wu 	/* Try to transmit at least chunks of TX_MAX_BURST pkts */
256aad91eddSJiawen Wu 	if (likely(nb_pkts <= RTE_PMD_NGBE_TX_MAX_BURST))
257aad91eddSJiawen Wu 		return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts);
258aad91eddSJiawen Wu 
259aad91eddSJiawen Wu 	/* transmit more than the max burst, in chunks of TX_MAX_BURST */
260aad91eddSJiawen Wu 	nb_tx = 0;
261aad91eddSJiawen Wu 	while (nb_pkts != 0) {
262aad91eddSJiawen Wu 		uint16_t ret, n;
263aad91eddSJiawen Wu 
264aad91eddSJiawen Wu 		n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_TX_MAX_BURST);
265aad91eddSJiawen Wu 		ret = tx_xmit_pkts(tx_queue, &tx_pkts[nb_tx], n);
266aad91eddSJiawen Wu 		nb_tx = (uint16_t)(nb_tx + ret);
267aad91eddSJiawen Wu 		nb_pkts = (uint16_t)(nb_pkts - ret);
268aad91eddSJiawen Wu 		if (ret < n)
269aad91eddSJiawen Wu 			break;
270aad91eddSJiawen Wu 	}
271aad91eddSJiawen Wu 
272aad91eddSJiawen Wu 	return nb_tx;
273aad91eddSJiawen Wu }
274aad91eddSJiawen Wu 
275e94c20c3SJiawen Wu static uint16_t
276e94c20c3SJiawen Wu ngbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
277e94c20c3SJiawen Wu 		   uint16_t nb_pkts)
278e94c20c3SJiawen Wu {
279e94c20c3SJiawen Wu 	struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue;
280e94c20c3SJiawen Wu 	uint16_t nb_tx = 0;
281e94c20c3SJiawen Wu 
282e94c20c3SJiawen Wu 	while (nb_pkts) {
283e94c20c3SJiawen Wu 		uint16_t ret, num;
284e94c20c3SJiawen Wu 
285e94c20c3SJiawen Wu 		num = (uint16_t)RTE_MIN(nb_pkts, txq->tx_free_thresh);
286e94c20c3SJiawen Wu 		ret = ngbe_xmit_fixed_burst_vec(tx_queue, &tx_pkts[nb_tx], num);
287e94c20c3SJiawen Wu 		nb_tx += ret;
288e94c20c3SJiawen Wu 		nb_pkts -= ret;
289e94c20c3SJiawen Wu 		if (ret < num)
290e94c20c3SJiawen Wu 			break;
291e94c20c3SJiawen Wu 	}
292e94c20c3SJiawen Wu 
293e94c20c3SJiawen Wu 	return nb_tx;
294e94c20c3SJiawen Wu }
295e94c20c3SJiawen Wu 
2969f320614SJiawen Wu static inline void
2979f320614SJiawen Wu ngbe_set_xmit_ctx(struct ngbe_tx_queue *txq,
2989f320614SJiawen Wu 		volatile struct ngbe_tx_ctx_desc *ctx_txd,
2999f320614SJiawen Wu 		uint64_t ol_flags, union ngbe_tx_offload tx_offload)
3009f320614SJiawen Wu {
3019f320614SJiawen Wu 	union ngbe_tx_offload tx_offload_mask;
3029f320614SJiawen Wu 	uint32_t type_tucmd_mlhl;
3039f320614SJiawen Wu 	uint32_t mss_l4len_idx;
3049f320614SJiawen Wu 	uint32_t ctx_idx;
3059f320614SJiawen Wu 	uint32_t vlan_macip_lens;
3069f320614SJiawen Wu 	uint32_t tunnel_seed;
3079f320614SJiawen Wu 
3089f320614SJiawen Wu 	ctx_idx = txq->ctx_curr;
3099f320614SJiawen Wu 	tx_offload_mask.data[0] = 0;
3109f320614SJiawen Wu 	tx_offload_mask.data[1] = 0;
3119f320614SJiawen Wu 
3129f320614SJiawen Wu 	/* Specify which HW CTX to upload. */
3139f320614SJiawen Wu 	mss_l4len_idx = NGBE_TXD_IDX(ctx_idx);
3149f320614SJiawen Wu 	type_tucmd_mlhl = NGBE_TXD_CTXT;
3159f320614SJiawen Wu 
3169f320614SJiawen Wu 	tx_offload_mask.ptid |= ~0;
3179f320614SJiawen Wu 	type_tucmd_mlhl |= NGBE_TXD_PTID(tx_offload.ptid);
3189f320614SJiawen Wu 
3199f320614SJiawen Wu 	/* check if TCP segmentation required for this packet */
3209f320614SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
3219f320614SJiawen Wu 		tx_offload_mask.l2_len |= ~0;
3229f320614SJiawen Wu 		tx_offload_mask.l3_len |= ~0;
3239f320614SJiawen Wu 		tx_offload_mask.l4_len |= ~0;
3249f320614SJiawen Wu 		tx_offload_mask.tso_segsz |= ~0;
3259f320614SJiawen Wu 		mss_l4len_idx |= NGBE_TXD_MSS(tx_offload.tso_segsz);
3269f320614SJiawen Wu 		mss_l4len_idx |= NGBE_TXD_L4LEN(tx_offload.l4_len);
3279f320614SJiawen Wu 	} else { /* no TSO, check if hardware checksum is needed */
3289f320614SJiawen Wu 		if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
3299f320614SJiawen Wu 			tx_offload_mask.l2_len |= ~0;
3309f320614SJiawen Wu 			tx_offload_mask.l3_len |= ~0;
3319f320614SJiawen Wu 		}
3329f320614SJiawen Wu 
3339f320614SJiawen Wu 		switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
3349f320614SJiawen Wu 		case RTE_MBUF_F_TX_UDP_CKSUM:
3359f320614SJiawen Wu 			mss_l4len_idx |=
3369f320614SJiawen Wu 				NGBE_TXD_L4LEN(sizeof(struct rte_udp_hdr));
3379f320614SJiawen Wu 			tx_offload_mask.l2_len |= ~0;
3389f320614SJiawen Wu 			tx_offload_mask.l3_len |= ~0;
3399f320614SJiawen Wu 			break;
3409f320614SJiawen Wu 		case RTE_MBUF_F_TX_TCP_CKSUM:
3419f320614SJiawen Wu 			mss_l4len_idx |=
3429f320614SJiawen Wu 				NGBE_TXD_L4LEN(sizeof(struct rte_tcp_hdr));
3439f320614SJiawen Wu 			tx_offload_mask.l2_len |= ~0;
3449f320614SJiawen Wu 			tx_offload_mask.l3_len |= ~0;
3459f320614SJiawen Wu 			break;
3469f320614SJiawen Wu 		case RTE_MBUF_F_TX_SCTP_CKSUM:
3479f320614SJiawen Wu 			mss_l4len_idx |=
3489f320614SJiawen Wu 				NGBE_TXD_L4LEN(sizeof(struct rte_sctp_hdr));
3499f320614SJiawen Wu 			tx_offload_mask.l2_len |= ~0;
3509f320614SJiawen Wu 			tx_offload_mask.l3_len |= ~0;
3519f320614SJiawen Wu 			break;
3529f320614SJiawen Wu 		default:
3539f320614SJiawen Wu 			break;
3549f320614SJiawen Wu 		}
3559f320614SJiawen Wu 	}
3569f320614SJiawen Wu 
3579f320614SJiawen Wu 	vlan_macip_lens = NGBE_TXD_IPLEN(tx_offload.l3_len >> 1);
3589f320614SJiawen Wu 	vlan_macip_lens |= NGBE_TXD_MACLEN(tx_offload.l2_len);
3599f320614SJiawen Wu 
36059b46438SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_VLAN) {
36159b46438SJiawen Wu 		tx_offload_mask.vlan_tci |= ~0;
36259b46438SJiawen Wu 		vlan_macip_lens |= NGBE_TXD_VLAN(tx_offload.vlan_tci);
36359b46438SJiawen Wu 	}
36459b46438SJiawen Wu 
365fa402b1eSJiawen Wu 	tunnel_seed = 0;
366fa402b1eSJiawen Wu 
3679f320614SJiawen Wu 	txq->ctx_cache[ctx_idx].flags = ol_flags;
3689f320614SJiawen Wu 	txq->ctx_cache[ctx_idx].tx_offload.data[0] =
3699f320614SJiawen Wu 		tx_offload_mask.data[0] & tx_offload.data[0];
3709f320614SJiawen Wu 	txq->ctx_cache[ctx_idx].tx_offload.data[1] =
3719f320614SJiawen Wu 		tx_offload_mask.data[1] & tx_offload.data[1];
3729f320614SJiawen Wu 	txq->ctx_cache[ctx_idx].tx_offload_mask = tx_offload_mask;
3739f320614SJiawen Wu 
3749f320614SJiawen Wu 	ctx_txd->dw0 = rte_cpu_to_le_32(vlan_macip_lens);
3759f320614SJiawen Wu 	ctx_txd->dw1 = rte_cpu_to_le_32(tunnel_seed);
3769f320614SJiawen Wu 	ctx_txd->dw2 = rte_cpu_to_le_32(type_tucmd_mlhl);
3779f320614SJiawen Wu 	ctx_txd->dw3 = rte_cpu_to_le_32(mss_l4len_idx);
3789f320614SJiawen Wu }
3799f320614SJiawen Wu 
3809f320614SJiawen Wu /*
3819f320614SJiawen Wu  * Check which hardware context can be used. Use the existing match
3829f320614SJiawen Wu  * or create a new context descriptor.
3839f320614SJiawen Wu  */
3849f320614SJiawen Wu static inline uint32_t
3859f320614SJiawen Wu what_ctx_update(struct ngbe_tx_queue *txq, uint64_t flags,
3869f320614SJiawen Wu 		   union ngbe_tx_offload tx_offload)
3879f320614SJiawen Wu {
3889f320614SJiawen Wu 	/* If match with the current used context */
3899f320614SJiawen Wu 	if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags &&
3909f320614SJiawen Wu 		   (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] ==
3919f320614SJiawen Wu 		    (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0]
3929f320614SJiawen Wu 		     & tx_offload.data[0])) &&
3939f320614SJiawen Wu 		   (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] ==
3949f320614SJiawen Wu 		    (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1]
3959f320614SJiawen Wu 		     & tx_offload.data[1]))))
3969f320614SJiawen Wu 		return txq->ctx_curr;
3979f320614SJiawen Wu 
3989f320614SJiawen Wu 	/* What if match with the next context  */
3999f320614SJiawen Wu 	txq->ctx_curr ^= 1;
4009f320614SJiawen Wu 	if (likely(txq->ctx_cache[txq->ctx_curr].flags == flags &&
4019f320614SJiawen Wu 		   (txq->ctx_cache[txq->ctx_curr].tx_offload.data[0] ==
4029f320614SJiawen Wu 		    (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[0]
4039f320614SJiawen Wu 		     & tx_offload.data[0])) &&
4049f320614SJiawen Wu 		   (txq->ctx_cache[txq->ctx_curr].tx_offload.data[1] ==
4059f320614SJiawen Wu 		    (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data[1]
4069f320614SJiawen Wu 		     & tx_offload.data[1]))))
4079f320614SJiawen Wu 		return txq->ctx_curr;
4089f320614SJiawen Wu 
4099f320614SJiawen Wu 	/* Mismatch, use the previous context */
4109f320614SJiawen Wu 	return NGBE_CTX_NUM;
4119f320614SJiawen Wu }
4129f320614SJiawen Wu 
4139f320614SJiawen Wu static inline uint32_t
4149f320614SJiawen Wu tx_desc_cksum_flags_to_olinfo(uint64_t ol_flags)
4159f320614SJiawen Wu {
4169f320614SJiawen Wu 	uint32_t tmp = 0;
4179f320614SJiawen Wu 
4189f320614SJiawen Wu 	if ((ol_flags & RTE_MBUF_F_TX_L4_MASK) != RTE_MBUF_F_TX_L4_NO_CKSUM) {
4199f320614SJiawen Wu 		tmp |= NGBE_TXD_CC;
4209f320614SJiawen Wu 		tmp |= NGBE_TXD_L4CS;
4219f320614SJiawen Wu 	}
4229f320614SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
4239f320614SJiawen Wu 		tmp |= NGBE_TXD_CC;
4249f320614SJiawen Wu 		tmp |= NGBE_TXD_IPCS;
4259f320614SJiawen Wu 	}
4269f320614SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) {
4279f320614SJiawen Wu 		tmp |= NGBE_TXD_CC;
4289f320614SJiawen Wu 		tmp |= NGBE_TXD_EIPCS;
4299f320614SJiawen Wu 	}
4309f320614SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
4319f320614SJiawen Wu 		tmp |= NGBE_TXD_CC;
4329f320614SJiawen Wu 		/* implies IPv4 cksum */
4339f320614SJiawen Wu 		if (ol_flags & RTE_MBUF_F_TX_IPV4)
4349f320614SJiawen Wu 			tmp |= NGBE_TXD_IPCS;
4359f320614SJiawen Wu 		tmp |= NGBE_TXD_L4CS;
4369f320614SJiawen Wu 	}
43759b46438SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_VLAN)
43859b46438SJiawen Wu 		tmp |= NGBE_TXD_CC;
4399f320614SJiawen Wu 
4409f320614SJiawen Wu 	return tmp;
4419f320614SJiawen Wu }
4429f320614SJiawen Wu 
4439f320614SJiawen Wu static inline uint32_t
4449f320614SJiawen Wu tx_desc_ol_flags_to_cmdtype(uint64_t ol_flags)
4459f320614SJiawen Wu {
4469f320614SJiawen Wu 	uint32_t cmdtype = 0;
4479f320614SJiawen Wu 
44859b46438SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_VLAN)
44959b46438SJiawen Wu 		cmdtype |= NGBE_TXD_VLE;
4509f320614SJiawen Wu 	if (ol_flags & RTE_MBUF_F_TX_TCP_SEG)
4519f320614SJiawen Wu 		cmdtype |= NGBE_TXD_TSE;
4529f320614SJiawen Wu 	return cmdtype;
4539f320614SJiawen Wu }
4549f320614SJiawen Wu 
455fa402b1eSJiawen Wu static inline uint32_t
456fa402b1eSJiawen Wu tx_desc_ol_flags_to_ptype(uint64_t oflags)
4579f320614SJiawen Wu {
458fa402b1eSJiawen Wu 	uint32_t ptype;
4599f320614SJiawen Wu 
4609f320614SJiawen Wu 	/* L2 level */
4619f320614SJiawen Wu 	ptype = RTE_PTYPE_L2_ETHER;
46259b46438SJiawen Wu 	if (oflags & RTE_MBUF_F_TX_VLAN)
46359b46438SJiawen Wu 		ptype |= RTE_PTYPE_L2_ETHER_VLAN;
4649f320614SJiawen Wu 
4659f320614SJiawen Wu 	/* L3 level */
4669f320614SJiawen Wu 	if (oflags & (RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM))
467fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L3_IPV4;
4689f320614SJiawen Wu 	else if (oflags & (RTE_MBUF_F_TX_IPV6))
469fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L3_IPV6;
4709f320614SJiawen Wu 
4719f320614SJiawen Wu 	/* L4 level */
4729f320614SJiawen Wu 	switch (oflags & (RTE_MBUF_F_TX_L4_MASK)) {
4739f320614SJiawen Wu 	case RTE_MBUF_F_TX_TCP_CKSUM:
474fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L4_TCP;
4759f320614SJiawen Wu 		break;
4769f320614SJiawen Wu 	case RTE_MBUF_F_TX_UDP_CKSUM:
477fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L4_UDP;
4789f320614SJiawen Wu 		break;
4799f320614SJiawen Wu 	case RTE_MBUF_F_TX_SCTP_CKSUM:
480fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L4_SCTP;
4819f320614SJiawen Wu 		break;
4829f320614SJiawen Wu 	}
4839f320614SJiawen Wu 
4849f320614SJiawen Wu 	if (oflags & RTE_MBUF_F_TX_TCP_SEG)
485fa402b1eSJiawen Wu 		ptype |= RTE_PTYPE_L4_TCP;
4869f320614SJiawen Wu 
487fa402b1eSJiawen Wu 	return ptype;
4889f320614SJiawen Wu }
4899f320614SJiawen Wu 
490fa402b1eSJiawen Wu static inline uint8_t
491fa402b1eSJiawen Wu tx_desc_ol_flags_to_ptid(uint64_t oflags)
492fa402b1eSJiawen Wu {
493fa402b1eSJiawen Wu 	uint32_t ptype;
494fa402b1eSJiawen Wu 
495fa402b1eSJiawen Wu 	ptype = tx_desc_ol_flags_to_ptype(oflags);
496fa402b1eSJiawen Wu 
4979f320614SJiawen Wu 	return ngbe_encode_ptype(ptype);
4989f320614SJiawen Wu }
4999f320614SJiawen Wu 
5009f320614SJiawen Wu /* Reset transmit descriptors after they have been used */
5019f320614SJiawen Wu static inline int
5029f320614SJiawen Wu ngbe_xmit_cleanup(struct ngbe_tx_queue *txq)
5039f320614SJiawen Wu {
5049f320614SJiawen Wu 	struct ngbe_tx_entry *sw_ring = txq->sw_ring;
5059f320614SJiawen Wu 	volatile struct ngbe_tx_desc *txr = txq->tx_ring;
5069f320614SJiawen Wu 	uint16_t last_desc_cleaned = txq->last_desc_cleaned;
5079f320614SJiawen Wu 	uint16_t nb_tx_desc = txq->nb_tx_desc;
5089f320614SJiawen Wu 	uint16_t desc_to_clean_to;
5099f320614SJiawen Wu 	uint16_t nb_tx_to_clean;
5109f320614SJiawen Wu 	uint32_t status;
5119f320614SJiawen Wu 
5129f320614SJiawen Wu 	/* Determine the last descriptor needing to be cleaned */
5139f320614SJiawen Wu 	desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_free_thresh);
5149f320614SJiawen Wu 	if (desc_to_clean_to >= nb_tx_desc)
5159f320614SJiawen Wu 		desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc);
5169f320614SJiawen Wu 
5179f320614SJiawen Wu 	/* Check to make sure the last descriptor to clean is done */
5189f320614SJiawen Wu 	desc_to_clean_to = sw_ring[desc_to_clean_to].last_id;
5199f320614SJiawen Wu 	status = txr[desc_to_clean_to].dw3;
5209f320614SJiawen Wu 	if (!(status & rte_cpu_to_le_32(NGBE_TXD_DD))) {
5219f320614SJiawen Wu 		PMD_TX_LOG(DEBUG,
5229f320614SJiawen Wu 			"Tx descriptor %4u is not done"
5239f320614SJiawen Wu 			"(port=%d queue=%d)",
5249f320614SJiawen Wu 			desc_to_clean_to,
5259f320614SJiawen Wu 			txq->port_id, txq->queue_id);
5269f320614SJiawen Wu 		if (txq->nb_tx_free >> 1 < txq->tx_free_thresh)
5279f320614SJiawen Wu 			ngbe_set32_masked(txq->tdc_reg_addr,
5289f320614SJiawen Wu 				NGBE_TXCFG_FLUSH, NGBE_TXCFG_FLUSH);
5299f320614SJiawen Wu 		/* Failed to clean any descriptors, better luck next time */
5309f320614SJiawen Wu 		return -(1);
5319f320614SJiawen Wu 	}
5329f320614SJiawen Wu 
5339f320614SJiawen Wu 	/* Figure out how many descriptors will be cleaned */
5349f320614SJiawen Wu 	if (last_desc_cleaned > desc_to_clean_to)
5359f320614SJiawen Wu 		nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) +
5369f320614SJiawen Wu 							desc_to_clean_to);
5379f320614SJiawen Wu 	else
5389f320614SJiawen Wu 		nb_tx_to_clean = (uint16_t)(desc_to_clean_to -
5399f320614SJiawen Wu 						last_desc_cleaned);
5409f320614SJiawen Wu 
5419f320614SJiawen Wu 	PMD_TX_LOG(DEBUG,
5429f320614SJiawen Wu 		"Cleaning %4u Tx descriptors: %4u to %4u (port=%d queue=%d)",
5439f320614SJiawen Wu 		nb_tx_to_clean, last_desc_cleaned, desc_to_clean_to,
5449f320614SJiawen Wu 		txq->port_id, txq->queue_id);
5459f320614SJiawen Wu 
5469f320614SJiawen Wu 	/*
5479f320614SJiawen Wu 	 * The last descriptor to clean is done, so that means all the
5489f320614SJiawen Wu 	 * descriptors from the last descriptor that was cleaned
5499f320614SJiawen Wu 	 * up to the last descriptor with the RS bit set
5509f320614SJiawen Wu 	 * are done. Only reset the threshold descriptor.
5519f320614SJiawen Wu 	 */
5529f320614SJiawen Wu 	txr[desc_to_clean_to].dw3 = 0;
5539f320614SJiawen Wu 
5549f320614SJiawen Wu 	/* Update the txq to reflect the last descriptor that was cleaned */
5559f320614SJiawen Wu 	txq->last_desc_cleaned = desc_to_clean_to;
5569f320614SJiawen Wu 	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean);
5579f320614SJiawen Wu 
5589f320614SJiawen Wu 	/* No Error */
5599f320614SJiawen Wu 	return 0;
5609f320614SJiawen Wu }
5619f320614SJiawen Wu 
5628d75bf03SJiawen Wu static inline bool
5638d75bf03SJiawen Wu ngbe_check_pkt_err(struct rte_mbuf *tx_pkt)
5648d75bf03SJiawen Wu {
5658d75bf03SJiawen Wu 	uint32_t total_len = 0, nb_seg = 0;
5668d75bf03SJiawen Wu 	struct rte_mbuf *mseg;
5678d75bf03SJiawen Wu 
5688d75bf03SJiawen Wu 	mseg = tx_pkt;
5698d75bf03SJiawen Wu 	do {
5708d75bf03SJiawen Wu 		if (mseg->data_len == 0)
5718d75bf03SJiawen Wu 			return true;
5728d75bf03SJiawen Wu 		total_len += mseg->data_len;
5738d75bf03SJiawen Wu 		nb_seg++;
5748d75bf03SJiawen Wu 		mseg = mseg->next;
5758d75bf03SJiawen Wu 	} while (mseg != NULL);
5768d75bf03SJiawen Wu 
5778d75bf03SJiawen Wu 	if (tx_pkt->pkt_len != total_len || tx_pkt->pkt_len == 0)
5788d75bf03SJiawen Wu 		return true;
5798d75bf03SJiawen Wu 
5808d75bf03SJiawen Wu 	if (tx_pkt->nb_segs != nb_seg || tx_pkt->nb_segs > 64)
5818d75bf03SJiawen Wu 		return true;
5828d75bf03SJiawen Wu 
5838d75bf03SJiawen Wu 	return false;
5848d75bf03SJiawen Wu }
5858d75bf03SJiawen Wu 
5869f320614SJiawen Wu uint16_t
5879f320614SJiawen Wu ngbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
5889f320614SJiawen Wu 		uint16_t nb_pkts)
5899f320614SJiawen Wu {
5909f320614SJiawen Wu 	struct ngbe_tx_queue *txq;
5919f320614SJiawen Wu 	struct ngbe_tx_entry *sw_ring;
5929f320614SJiawen Wu 	struct ngbe_tx_entry *txe, *txn;
5939f320614SJiawen Wu 	volatile struct ngbe_tx_desc *txr;
5949f320614SJiawen Wu 	volatile struct ngbe_tx_desc *txd;
5959f320614SJiawen Wu 	struct rte_mbuf     *tx_pkt;
5969f320614SJiawen Wu 	struct rte_mbuf     *m_seg;
5979f320614SJiawen Wu 	uint64_t buf_dma_addr;
5989f320614SJiawen Wu 	uint32_t olinfo_status;
5999f320614SJiawen Wu 	uint32_t cmd_type_len;
6009f320614SJiawen Wu 	uint32_t pkt_len;
6019f320614SJiawen Wu 	uint16_t slen;
6029f320614SJiawen Wu 	uint64_t ol_flags;
6039f320614SJiawen Wu 	uint16_t tx_id;
6049f320614SJiawen Wu 	uint16_t tx_last;
6059f320614SJiawen Wu 	uint16_t nb_tx;
6069f320614SJiawen Wu 	uint16_t nb_used;
6079f320614SJiawen Wu 	uint64_t tx_ol_req;
6089f320614SJiawen Wu 	uint32_t ctx = 0;
6099f320614SJiawen Wu 	uint32_t new_ctx;
6109f320614SJiawen Wu 	union ngbe_tx_offload tx_offload;
6119f320614SJiawen Wu 
6129f320614SJiawen Wu 	tx_offload.data[0] = 0;
6139f320614SJiawen Wu 	tx_offload.data[1] = 0;
6149f320614SJiawen Wu 	txq = tx_queue;
6159f320614SJiawen Wu 	sw_ring = txq->sw_ring;
6169f320614SJiawen Wu 	txr     = txq->tx_ring;
6179f320614SJiawen Wu 	tx_id   = txq->tx_tail;
6189f320614SJiawen Wu 	txe = &sw_ring[tx_id];
6199f320614SJiawen Wu 
6209f320614SJiawen Wu 	/* Determine if the descriptor ring needs to be cleaned. */
6219f320614SJiawen Wu 	if (txq->nb_tx_free < txq->tx_free_thresh)
6229f320614SJiawen Wu 		ngbe_xmit_cleanup(txq);
6239f320614SJiawen Wu 
6249f320614SJiawen Wu 	rte_prefetch0(&txe->mbuf->pool);
6259f320614SJiawen Wu 
6269f320614SJiawen Wu 	/* Tx loop */
6279f320614SJiawen Wu 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
6289f320614SJiawen Wu 		new_ctx = 0;
6299f320614SJiawen Wu 		tx_pkt = *tx_pkts++;
6308d75bf03SJiawen Wu 		if (ngbe_check_pkt_err(tx_pkt)) {
6318d75bf03SJiawen Wu 			rte_pktmbuf_free(tx_pkt);
6323eba2f28SJiawen Wu 			txq->desc_error++;
6338d75bf03SJiawen Wu 			continue;
6348d75bf03SJiawen Wu 		}
6358d75bf03SJiawen Wu 
6369f320614SJiawen Wu 		pkt_len = tx_pkt->pkt_len;
6379f320614SJiawen Wu 
6389f320614SJiawen Wu 		/*
6399f320614SJiawen Wu 		 * Determine how many (if any) context descriptors
6409f320614SJiawen Wu 		 * are needed for offload functionality.
6419f320614SJiawen Wu 		 */
6429f320614SJiawen Wu 		ol_flags = tx_pkt->ol_flags;
6439f320614SJiawen Wu 
6449f320614SJiawen Wu 		/* If hardware offload required */
6459f320614SJiawen Wu 		tx_ol_req = ol_flags & NGBE_TX_OFFLOAD_MASK;
6469f320614SJiawen Wu 		if (tx_ol_req) {
647fa402b1eSJiawen Wu 			tx_offload.ptid = tx_desc_ol_flags_to_ptid(tx_ol_req);
6489f320614SJiawen Wu 			tx_offload.l2_len = tx_pkt->l2_len;
6499f320614SJiawen Wu 			tx_offload.l3_len = tx_pkt->l3_len;
6509f320614SJiawen Wu 			tx_offload.l4_len = tx_pkt->l4_len;
65159b46438SJiawen Wu 			tx_offload.vlan_tci = tx_pkt->vlan_tci;
6529f320614SJiawen Wu 			tx_offload.tso_segsz = tx_pkt->tso_segsz;
6539f320614SJiawen Wu 
6549f320614SJiawen Wu 			/* If new context need be built or reuse the exist ctx*/
6559f320614SJiawen Wu 			ctx = what_ctx_update(txq, tx_ol_req, tx_offload);
6569f320614SJiawen Wu 			/* Only allocate context descriptor if required */
6579f320614SJiawen Wu 			new_ctx = (ctx == NGBE_CTX_NUM);
6589f320614SJiawen Wu 			ctx = txq->ctx_curr;
6599f320614SJiawen Wu 		}
6609f320614SJiawen Wu 
6619f320614SJiawen Wu 		/*
6629f320614SJiawen Wu 		 * Keep track of how many descriptors are used this loop
6639f320614SJiawen Wu 		 * This will always be the number of segments + the number of
6649f320614SJiawen Wu 		 * Context descriptors required to transmit the packet
6659f320614SJiawen Wu 		 */
6669f320614SJiawen Wu 		nb_used = (uint16_t)(tx_pkt->nb_segs + new_ctx);
6679f320614SJiawen Wu 
6689f320614SJiawen Wu 		/*
6699f320614SJiawen Wu 		 * The number of descriptors that must be allocated for a
6709f320614SJiawen Wu 		 * packet is the number of segments of that packet, plus 1
6719f320614SJiawen Wu 		 * Context Descriptor for the hardware offload, if any.
6729f320614SJiawen Wu 		 * Determine the last Tx descriptor to allocate in the Tx ring
6739f320614SJiawen Wu 		 * for the packet, starting from the current position (tx_id)
6749f320614SJiawen Wu 		 * in the ring.
6759f320614SJiawen Wu 		 */
6769f320614SJiawen Wu 		tx_last = (uint16_t)(tx_id + nb_used - 1);
6779f320614SJiawen Wu 
6789f320614SJiawen Wu 		/* Circular ring */
6799f320614SJiawen Wu 		if (tx_last >= txq->nb_tx_desc)
6809f320614SJiawen Wu 			tx_last = (uint16_t)(tx_last - txq->nb_tx_desc);
6819f320614SJiawen Wu 
6829f320614SJiawen Wu 		PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u"
6839f320614SJiawen Wu 			   " tx_first=%u tx_last=%u",
6849f320614SJiawen Wu 			   (uint16_t)txq->port_id,
6859f320614SJiawen Wu 			   (uint16_t)txq->queue_id,
6869f320614SJiawen Wu 			   (uint32_t)pkt_len,
6879f320614SJiawen Wu 			   (uint16_t)tx_id,
6889f320614SJiawen Wu 			   (uint16_t)tx_last);
6899f320614SJiawen Wu 
6909f320614SJiawen Wu 		/*
6919f320614SJiawen Wu 		 * Make sure there are enough Tx descriptors available to
6929f320614SJiawen Wu 		 * transmit the entire packet.
6939f320614SJiawen Wu 		 * nb_used better be less than or equal to txq->tx_free_thresh
6949f320614SJiawen Wu 		 */
6959f320614SJiawen Wu 		if (nb_used > txq->nb_tx_free) {
6969f320614SJiawen Wu 			PMD_TX_LOG(DEBUG,
6979f320614SJiawen Wu 				"Not enough free Tx descriptors "
6989f320614SJiawen Wu 				"nb_used=%4u nb_free=%4u "
6999f320614SJiawen Wu 				"(port=%d queue=%d)",
7009f320614SJiawen Wu 				nb_used, txq->nb_tx_free,
7019f320614SJiawen Wu 				txq->port_id, txq->queue_id);
7029f320614SJiawen Wu 
7039f320614SJiawen Wu 			if (ngbe_xmit_cleanup(txq) != 0) {
7049f320614SJiawen Wu 				/* Could not clean any descriptors */
7059f320614SJiawen Wu 				if (nb_tx == 0)
7069f320614SJiawen Wu 					return 0;
7079f320614SJiawen Wu 				goto end_of_tx;
7089f320614SJiawen Wu 			}
7099f320614SJiawen Wu 
7109f320614SJiawen Wu 			/* nb_used better be <= txq->tx_free_thresh */
7119f320614SJiawen Wu 			if (unlikely(nb_used > txq->tx_free_thresh)) {
7129f320614SJiawen Wu 				PMD_TX_LOG(DEBUG,
7139f320614SJiawen Wu 					"The number of descriptors needed to "
7149f320614SJiawen Wu 					"transmit the packet exceeds the "
7159f320614SJiawen Wu 					"RS bit threshold. This will impact "
7169f320614SJiawen Wu 					"performance."
7179f320614SJiawen Wu 					"nb_used=%4u nb_free=%4u "
7189f320614SJiawen Wu 					"tx_free_thresh=%4u. "
7199f320614SJiawen Wu 					"(port=%d queue=%d)",
7209f320614SJiawen Wu 					nb_used, txq->nb_tx_free,
7219f320614SJiawen Wu 					txq->tx_free_thresh,
7229f320614SJiawen Wu 					txq->port_id, txq->queue_id);
7239f320614SJiawen Wu 				/*
7249f320614SJiawen Wu 				 * Loop here until there are enough Tx
7259f320614SJiawen Wu 				 * descriptors or until the ring cannot be
7269f320614SJiawen Wu 				 * cleaned.
7279f320614SJiawen Wu 				 */
7289f320614SJiawen Wu 				while (nb_used > txq->nb_tx_free) {
7299f320614SJiawen Wu 					if (ngbe_xmit_cleanup(txq) != 0) {
7309f320614SJiawen Wu 						/*
7319f320614SJiawen Wu 						 * Could not clean any
7329f320614SJiawen Wu 						 * descriptors
7339f320614SJiawen Wu 						 */
7349f320614SJiawen Wu 						if (nb_tx == 0)
7359f320614SJiawen Wu 							return 0;
7369f320614SJiawen Wu 						goto end_of_tx;
7379f320614SJiawen Wu 					}
7389f320614SJiawen Wu 				}
7399f320614SJiawen Wu 			}
7409f320614SJiawen Wu 		}
7419f320614SJiawen Wu 
7429f320614SJiawen Wu 		/*
7439f320614SJiawen Wu 		 * By now there are enough free Tx descriptors to transmit
7449f320614SJiawen Wu 		 * the packet.
7459f320614SJiawen Wu 		 */
7469f320614SJiawen Wu 
7479f320614SJiawen Wu 		/*
7489f320614SJiawen Wu 		 * Set common flags of all Tx Data Descriptors.
7499f320614SJiawen Wu 		 *
7509f320614SJiawen Wu 		 * The following bits must be set in the first Data Descriptor
7519f320614SJiawen Wu 		 * and are ignored in the other ones:
7529f320614SJiawen Wu 		 *   - NGBE_TXD_FCS
7539f320614SJiawen Wu 		 *
7549f320614SJiawen Wu 		 * The following bits must only be set in the last Data
7559f320614SJiawen Wu 		 * Descriptor:
7569f320614SJiawen Wu 		 *   - NGBE_TXD_EOP
7579f320614SJiawen Wu 		 */
7589f320614SJiawen Wu 		cmd_type_len = NGBE_TXD_FCS;
7599f320614SJiawen Wu 
76024cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588
76160ad04e2SGagandeep Singh 		if (ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
76224cd85f7SJiawen Wu 			cmd_type_len |= NGBE_TXD_1588;
76324cd85f7SJiawen Wu #endif
76424cd85f7SJiawen Wu 
7659f320614SJiawen Wu 		olinfo_status = 0;
7669f320614SJiawen Wu 		if (tx_ol_req) {
7679f320614SJiawen Wu 			if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
7689f320614SJiawen Wu 				/* when TSO is on, paylen in descriptor is the
7699f320614SJiawen Wu 				 * not the packet len but the tcp payload len
7709f320614SJiawen Wu 				 */
7719f320614SJiawen Wu 				pkt_len -= (tx_offload.l2_len +
7729f320614SJiawen Wu 					tx_offload.l3_len + tx_offload.l4_len);
7739f320614SJiawen Wu 			}
7749f320614SJiawen Wu 
7759f320614SJiawen Wu 			/*
7769f320614SJiawen Wu 			 * Setup the Tx Context Descriptor if required
7779f320614SJiawen Wu 			 */
7789f320614SJiawen Wu 			if (new_ctx) {
7799f320614SJiawen Wu 				volatile struct ngbe_tx_ctx_desc *ctx_txd;
7809f320614SJiawen Wu 
7819f320614SJiawen Wu 				ctx_txd = (volatile struct ngbe_tx_ctx_desc *)
7829f320614SJiawen Wu 				    &txr[tx_id];
7839f320614SJiawen Wu 
7849f320614SJiawen Wu 				txn = &sw_ring[txe->next_id];
7859f320614SJiawen Wu 				rte_prefetch0(&txn->mbuf->pool);
7869f320614SJiawen Wu 
7879f320614SJiawen Wu 				if (txe->mbuf != NULL) {
7889f320614SJiawen Wu 					rte_pktmbuf_free_seg(txe->mbuf);
7899f320614SJiawen Wu 					txe->mbuf = NULL;
7909f320614SJiawen Wu 				}
7919f320614SJiawen Wu 
7929f320614SJiawen Wu 				ngbe_set_xmit_ctx(txq, ctx_txd, tx_ol_req,
7939f320614SJiawen Wu 					tx_offload);
7949f320614SJiawen Wu 
7959f320614SJiawen Wu 				txe->last_id = tx_last;
7969f320614SJiawen Wu 				tx_id = txe->next_id;
7979f320614SJiawen Wu 				txe = txn;
7989f320614SJiawen Wu 			}
7999f320614SJiawen Wu 
8009f320614SJiawen Wu 			/*
8019f320614SJiawen Wu 			 * Setup the Tx Data Descriptor,
8029f320614SJiawen Wu 			 * This path will go through
8039f320614SJiawen Wu 			 * whatever new/reuse the context descriptor
8049f320614SJiawen Wu 			 */
8059f320614SJiawen Wu 			cmd_type_len  |= tx_desc_ol_flags_to_cmdtype(ol_flags);
8069f320614SJiawen Wu 			olinfo_status |=
8079f320614SJiawen Wu 				tx_desc_cksum_flags_to_olinfo(ol_flags);
8089f320614SJiawen Wu 			olinfo_status |= NGBE_TXD_IDX(ctx);
8099f320614SJiawen Wu 		}
8109f320614SJiawen Wu 
8119f320614SJiawen Wu 		olinfo_status |= NGBE_TXD_PAYLEN(pkt_len);
8129f320614SJiawen Wu 
8139f320614SJiawen Wu 		m_seg = tx_pkt;
8149f320614SJiawen Wu 		do {
8159f320614SJiawen Wu 			txd = &txr[tx_id];
8169f320614SJiawen Wu 			txn = &sw_ring[txe->next_id];
8179f320614SJiawen Wu 			rte_prefetch0(&txn->mbuf->pool);
8189f320614SJiawen Wu 
8199f320614SJiawen Wu 			if (txe->mbuf != NULL)
8209f320614SJiawen Wu 				rte_pktmbuf_free_seg(txe->mbuf);
8219f320614SJiawen Wu 			txe->mbuf = m_seg;
8229f320614SJiawen Wu 
8239f320614SJiawen Wu 			/*
8249f320614SJiawen Wu 			 * Set up Transmit Data Descriptor.
8259f320614SJiawen Wu 			 */
8269f320614SJiawen Wu 			slen = m_seg->data_len;
8279f320614SJiawen Wu 			buf_dma_addr = rte_mbuf_data_iova(m_seg);
8289f320614SJiawen Wu 			txd->qw0 = rte_cpu_to_le_64(buf_dma_addr);
8299f320614SJiawen Wu 			txd->dw2 = rte_cpu_to_le_32(cmd_type_len | slen);
8309f320614SJiawen Wu 			txd->dw3 = rte_cpu_to_le_32(olinfo_status);
8319f320614SJiawen Wu 			txe->last_id = tx_last;
8329f320614SJiawen Wu 			tx_id = txe->next_id;
8339f320614SJiawen Wu 			txe = txn;
8349f320614SJiawen Wu 			m_seg = m_seg->next;
8359f320614SJiawen Wu 		} while (m_seg != NULL);
8369f320614SJiawen Wu 
8379f320614SJiawen Wu 		/*
8389f320614SJiawen Wu 		 * The last packet data descriptor needs End Of Packet (EOP)
8399f320614SJiawen Wu 		 */
8409f320614SJiawen Wu 		cmd_type_len |= NGBE_TXD_EOP;
8419f320614SJiawen Wu 		txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used);
8429f320614SJiawen Wu 
8439f320614SJiawen Wu 		txd->dw2 |= rte_cpu_to_le_32(cmd_type_len);
8449f320614SJiawen Wu 	}
8459f320614SJiawen Wu 
8469f320614SJiawen Wu end_of_tx:
8479f320614SJiawen Wu 
8489f320614SJiawen Wu 	rte_wmb();
8499f320614SJiawen Wu 
8509f320614SJiawen Wu 	/*
8519f320614SJiawen Wu 	 * Set the Transmit Descriptor Tail (TDT)
8529f320614SJiawen Wu 	 */
8539f320614SJiawen Wu 	PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u",
8549f320614SJiawen Wu 		   (uint16_t)txq->port_id, (uint16_t)txq->queue_id,
8559f320614SJiawen Wu 		   (uint16_t)tx_id, (uint16_t)nb_tx);
8569f320614SJiawen Wu 	ngbe_set32_relaxed(txq->tdt_reg_addr, tx_id);
8579f320614SJiawen Wu 	txq->tx_tail = tx_id;
8589f320614SJiawen Wu 
8599f320614SJiawen Wu 	return nb_tx;
8609f320614SJiawen Wu }
8619f320614SJiawen Wu 
8629f320614SJiawen Wu /*********************************************************************
8639f320614SJiawen Wu  *
8649f320614SJiawen Wu  *  Tx prep functions
8659f320614SJiawen Wu  *
8669f320614SJiawen Wu  **********************************************************************/
8679f320614SJiawen Wu uint16_t
8689f320614SJiawen Wu ngbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
8699f320614SJiawen Wu {
8709f320614SJiawen Wu 	int i, ret;
8719f320614SJiawen Wu 	uint64_t ol_flags;
8729f320614SJiawen Wu 	struct rte_mbuf *m;
8739f320614SJiawen Wu 	struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue;
8749f320614SJiawen Wu 
8759f320614SJiawen Wu 	for (i = 0; i < nb_pkts; i++) {
8769f320614SJiawen Wu 		m = tx_pkts[i];
8779f320614SJiawen Wu 		ol_flags = m->ol_flags;
8789f320614SJiawen Wu 
8799f320614SJiawen Wu 		/**
8809f320614SJiawen Wu 		 * Check if packet meets requirements for number of segments
8819f320614SJiawen Wu 		 *
8829f320614SJiawen Wu 		 * NOTE: for ngbe it's always (40 - WTHRESH) for both TSO and
8839f320614SJiawen Wu 		 *       non-TSO
8849f320614SJiawen Wu 		 */
8859f320614SJiawen Wu 
8869f320614SJiawen Wu 		if (m->nb_segs > NGBE_TX_MAX_SEG - txq->wthresh) {
8879f320614SJiawen Wu 			rte_errno = -EINVAL;
8889f320614SJiawen Wu 			return i;
8899f320614SJiawen Wu 		}
8909f320614SJiawen Wu 
8919f320614SJiawen Wu 		if (ol_flags & NGBE_TX_OFFLOAD_NOTSUP_MASK) {
8929f320614SJiawen Wu 			rte_errno = -ENOTSUP;
8939f320614SJiawen Wu 			return i;
8949f320614SJiawen Wu 		}
8959f320614SJiawen Wu 
8969f320614SJiawen Wu #ifdef RTE_ETHDEV_DEBUG_TX
8979f320614SJiawen Wu 		ret = rte_validate_tx_offload(m);
8989f320614SJiawen Wu 		if (ret != 0) {
8999f320614SJiawen Wu 			rte_errno = ret;
9009f320614SJiawen Wu 			return i;
9019f320614SJiawen Wu 		}
9029f320614SJiawen Wu #endif
9039f320614SJiawen Wu 		ret = rte_net_intel_cksum_prepare(m);
9049f320614SJiawen Wu 		if (ret != 0) {
9059f320614SJiawen Wu 			rte_errno = ret;
9069f320614SJiawen Wu 			return i;
9079f320614SJiawen Wu 		}
9089f320614SJiawen Wu 	}
9099f320614SJiawen Wu 
9109f320614SJiawen Wu 	return i;
9119f320614SJiawen Wu }
9129f320614SJiawen Wu 
913aad91eddSJiawen Wu /*********************************************************************
914aad91eddSJiawen Wu  *
91593dfebd2SJiawen Wu  *  Rx functions
91693dfebd2SJiawen Wu  *
91793dfebd2SJiawen Wu  **********************************************************************/
918f6aef1daSJiawen Wu static inline uint32_t
919f6aef1daSJiawen Wu ngbe_rxd_pkt_info_to_pkt_type(uint32_t pkt_info, uint16_t ptid_mask)
920f6aef1daSJiawen Wu {
921f6aef1daSJiawen Wu 	uint16_t ptid = NGBE_RXD_PTID(pkt_info);
922f6aef1daSJiawen Wu 
923f6aef1daSJiawen Wu 	ptid &= ptid_mask;
924f6aef1daSJiawen Wu 
925f6aef1daSJiawen Wu 	return ngbe_decode_ptype(ptid);
926f6aef1daSJiawen Wu }
927f6aef1daSJiawen Wu 
928ffc959f5SJiawen Wu static inline uint64_t
9290779d7f6SJiawen Wu ngbe_rxd_pkt_info_to_pkt_flags(uint32_t pkt_info)
9300779d7f6SJiawen Wu {
93127595cd8STyler Retzlaff 	static alignas(RTE_CACHE_LINE_SIZE) uint64_t ip_rss_types_map[16] = {
9320779d7f6SJiawen Wu 		0, RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH,
9330779d7f6SJiawen Wu 		0, RTE_MBUF_F_RX_RSS_HASH, 0, RTE_MBUF_F_RX_RSS_HASH,
9340779d7f6SJiawen Wu 		RTE_MBUF_F_RX_RSS_HASH, 0, 0, 0,
9350779d7f6SJiawen Wu 		0, 0, 0,  RTE_MBUF_F_RX_FDIR,
9360779d7f6SJiawen Wu 	};
93724cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588
93824cd85f7SJiawen Wu 	static uint64_t ip_pkt_etqf_map[8] = {
93960ad04e2SGagandeep Singh 		0, 0, 0, RTE_MBUF_F_RX_IEEE1588_PTP,
94024cd85f7SJiawen Wu 		0, 0, 0, 0,
94124cd85f7SJiawen Wu 	};
94224cd85f7SJiawen Wu 	int etfid = ngbe_etflt_id(NGBE_RXD_PTID(pkt_info));
94324cd85f7SJiawen Wu 	if (likely(-1 != etfid))
94424cd85f7SJiawen Wu 		return ip_pkt_etqf_map[etfid] |
94524cd85f7SJiawen Wu 		       ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)];
94624cd85f7SJiawen Wu 	else
9470779d7f6SJiawen Wu 		return ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)];
94824cd85f7SJiawen Wu #else
94924cd85f7SJiawen Wu 	return ip_rss_types_map[NGBE_RXD_RSSTYPE(pkt_info)];
95024cd85f7SJiawen Wu #endif
9510779d7f6SJiawen Wu }
9520779d7f6SJiawen Wu 
9530779d7f6SJiawen Wu static inline uint64_t
95459b46438SJiawen Wu rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags)
95559b46438SJiawen Wu {
95659b46438SJiawen Wu 	uint64_t pkt_flags;
95759b46438SJiawen Wu 
95859b46438SJiawen Wu 	/*
95959b46438SJiawen Wu 	 * Check if VLAN present only.
96059b46438SJiawen Wu 	 * Do not check whether L3/L4 rx checksum done by NIC or not,
96159b46438SJiawen Wu 	 * That can be found from rte_eth_rxmode.offloads flag
96259b46438SJiawen Wu 	 */
96359b46438SJiawen Wu 	pkt_flags = (rx_status & NGBE_RXD_STAT_VLAN &&
96459b46438SJiawen Wu 		     vlan_flags & RTE_MBUF_F_RX_VLAN_STRIPPED)
96559b46438SJiawen Wu 		    ? vlan_flags : 0;
96659b46438SJiawen Wu 
96724cd85f7SJiawen Wu #ifdef RTE_LIBRTE_IEEE1588
96824cd85f7SJiawen Wu 	if (rx_status & NGBE_RXD_STAT_1588)
96960ad04e2SGagandeep Singh 		pkt_flags = pkt_flags | RTE_MBUF_F_RX_IEEE1588_TMST;
97024cd85f7SJiawen Wu #endif
97159b46438SJiawen Wu 	return pkt_flags;
97259b46438SJiawen Wu }
97359b46438SJiawen Wu 
97459b46438SJiawen Wu static inline uint64_t
975ffc959f5SJiawen Wu rx_desc_error_to_pkt_flags(uint32_t rx_status)
976ffc959f5SJiawen Wu {
977ffc959f5SJiawen Wu 	uint64_t pkt_flags = 0;
978ffc959f5SJiawen Wu 
979ffc959f5SJiawen Wu 	/* checksum offload can't be disabled */
980ffc959f5SJiawen Wu 	if (rx_status & NGBE_RXD_STAT_IPCS)
981ffc959f5SJiawen Wu 		pkt_flags |= (rx_status & NGBE_RXD_ERR_IPCS
982ffc959f5SJiawen Wu 				? RTE_MBUF_F_RX_IP_CKSUM_BAD : RTE_MBUF_F_RX_IP_CKSUM_GOOD);
983ffc959f5SJiawen Wu 
984ffc959f5SJiawen Wu 	if (rx_status & NGBE_RXD_STAT_L4CS)
985ffc959f5SJiawen Wu 		pkt_flags |= (rx_status & NGBE_RXD_ERR_L4CS
986ffc959f5SJiawen Wu 				? RTE_MBUF_F_RX_L4_CKSUM_BAD : RTE_MBUF_F_RX_L4_CKSUM_GOOD);
987ffc959f5SJiawen Wu 
988ffc959f5SJiawen Wu 	if (rx_status & NGBE_RXD_STAT_EIPCS &&
989ffc959f5SJiawen Wu 	    rx_status & NGBE_RXD_ERR_EIPCS)
990ffc959f5SJiawen Wu 		pkt_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
991ffc959f5SJiawen Wu 
992ffc959f5SJiawen Wu 	return pkt_flags;
993ffc959f5SJiawen Wu }
994ffc959f5SJiawen Wu 
99579f3128dSJiawen Wu /*
99679f3128dSJiawen Wu  * LOOK_AHEAD defines how many desc statuses to check beyond the
99779f3128dSJiawen Wu  * current descriptor.
99879f3128dSJiawen Wu  * It must be a pound define for optimal performance.
99979f3128dSJiawen Wu  * Do not change the value of LOOK_AHEAD, as the ngbe_rx_scan_hw_ring
100079f3128dSJiawen Wu  * function only works with LOOK_AHEAD=8.
100179f3128dSJiawen Wu  */
100279f3128dSJiawen Wu #define LOOK_AHEAD 8
100379f3128dSJiawen Wu #if (LOOK_AHEAD != 8)
100479f3128dSJiawen Wu #error "PMD NGBE: LOOK_AHEAD must be 8\n"
100579f3128dSJiawen Wu #endif
100679f3128dSJiawen Wu static inline int
100779f3128dSJiawen Wu ngbe_rx_scan_hw_ring(struct ngbe_rx_queue *rxq)
100879f3128dSJiawen Wu {
100979f3128dSJiawen Wu 	volatile struct ngbe_rx_desc *rxdp;
101079f3128dSJiawen Wu 	struct ngbe_rx_entry *rxep;
101179f3128dSJiawen Wu 	struct rte_mbuf *mb;
101279f3128dSJiawen Wu 	uint16_t pkt_len;
1013ffc959f5SJiawen Wu 	uint64_t pkt_flags;
101479f3128dSJiawen Wu 	int nb_dd;
101579f3128dSJiawen Wu 	uint32_t s[LOOK_AHEAD];
101679f3128dSJiawen Wu 	uint32_t pkt_info[LOOK_AHEAD];
101779f3128dSJiawen Wu 	int i, j, nb_rx = 0;
101879f3128dSJiawen Wu 	uint32_t status;
101979f3128dSJiawen Wu 
102079f3128dSJiawen Wu 	/* get references to current descriptor and S/W ring entry */
102179f3128dSJiawen Wu 	rxdp = &rxq->rx_ring[rxq->rx_tail];
102279f3128dSJiawen Wu 	rxep = &rxq->sw_ring[rxq->rx_tail];
102379f3128dSJiawen Wu 
102479f3128dSJiawen Wu 	status = rxdp->qw1.lo.status;
102579f3128dSJiawen Wu 	/* check to make sure there is at least 1 packet to receive */
102679f3128dSJiawen Wu 	if (!(status & rte_cpu_to_le_32(NGBE_RXD_STAT_DD)))
102779f3128dSJiawen Wu 		return 0;
102879f3128dSJiawen Wu 
102979f3128dSJiawen Wu 	/*
103079f3128dSJiawen Wu 	 * Scan LOOK_AHEAD descriptors at a time to determine which descriptors
103179f3128dSJiawen Wu 	 * reference packets that are ready to be received.
103279f3128dSJiawen Wu 	 */
103379f3128dSJiawen Wu 	for (i = 0; i < RTE_PMD_NGBE_RX_MAX_BURST;
103479f3128dSJiawen Wu 	     i += LOOK_AHEAD, rxdp += LOOK_AHEAD, rxep += LOOK_AHEAD) {
103579f3128dSJiawen Wu 		/* Read desc statuses backwards to avoid race condition */
103679f3128dSJiawen Wu 		for (j = 0; j < LOOK_AHEAD; j++)
103779f3128dSJiawen Wu 			s[j] = rte_le_to_cpu_32(rxdp[j].qw1.lo.status);
103879f3128dSJiawen Wu 
1039a74c5001SJiawen Wu 		rte_atomic_thread_fence(rte_memory_order_acquire);
104079f3128dSJiawen Wu 
104179f3128dSJiawen Wu 		/* Compute how many status bits were set */
104279f3128dSJiawen Wu 		for (nb_dd = 0; nb_dd < LOOK_AHEAD &&
104379f3128dSJiawen Wu 				(s[nb_dd] & NGBE_RXD_STAT_DD); nb_dd++)
104479f3128dSJiawen Wu 			;
104579f3128dSJiawen Wu 
104679f3128dSJiawen Wu 		for (j = 0; j < nb_dd; j++)
104779f3128dSJiawen Wu 			pkt_info[j] = rte_le_to_cpu_32(rxdp[j].qw0.dw0);
104879f3128dSJiawen Wu 
104979f3128dSJiawen Wu 		nb_rx += nb_dd;
105079f3128dSJiawen Wu 
105179f3128dSJiawen Wu 		/* Translate descriptor info to mbuf format */
105279f3128dSJiawen Wu 		for (j = 0; j < nb_dd; ++j) {
105379f3128dSJiawen Wu 			mb = rxep[j].mbuf;
105464b36e4aSJiawen Wu 			pkt_len = rte_le_to_cpu_16(rxdp[j].qw1.hi.len) -
105564b36e4aSJiawen Wu 				  rxq->crc_len;
105679f3128dSJiawen Wu 			mb->data_len = pkt_len;
105779f3128dSJiawen Wu 			mb->pkt_len = pkt_len;
105859b46438SJiawen Wu 			mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].qw1.hi.tag);
105979f3128dSJiawen Wu 
1060ffc959f5SJiawen Wu 			/* convert descriptor fields to rte mbuf flags */
106159b46438SJiawen Wu 			pkt_flags = rx_desc_status_to_pkt_flags(s[j],
106259b46438SJiawen Wu 					rxq->vlan_flags);
106359b46438SJiawen Wu 			pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
10640779d7f6SJiawen Wu 			pkt_flags |=
10650779d7f6SJiawen Wu 				ngbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]);
1066ffc959f5SJiawen Wu 			mb->ol_flags = pkt_flags;
106779f3128dSJiawen Wu 			mb->packet_type =
106879f3128dSJiawen Wu 				ngbe_rxd_pkt_info_to_pkt_type(pkt_info[j],
106979f3128dSJiawen Wu 				NGBE_PTID_MASK);
10700779d7f6SJiawen Wu 
10710779d7f6SJiawen Wu 			if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH))
10720779d7f6SJiawen Wu 				mb->hash.rss =
10730779d7f6SJiawen Wu 					rte_le_to_cpu_32(rxdp[j].qw0.dw1);
107479f3128dSJiawen Wu 		}
107579f3128dSJiawen Wu 
107679f3128dSJiawen Wu 		/* Move mbuf pointers from the S/W ring to the stage */
107779f3128dSJiawen Wu 		for (j = 0; j < LOOK_AHEAD; ++j)
107879f3128dSJiawen Wu 			rxq->rx_stage[i + j] = rxep[j].mbuf;
107979f3128dSJiawen Wu 
108079f3128dSJiawen Wu 		/* stop if all requested packets could not be received */
108179f3128dSJiawen Wu 		if (nb_dd != LOOK_AHEAD)
108279f3128dSJiawen Wu 			break;
108379f3128dSJiawen Wu 	}
108479f3128dSJiawen Wu 
108579f3128dSJiawen Wu 	/* clear software ring entries so we can cleanup correctly */
108679f3128dSJiawen Wu 	for (i = 0; i < nb_rx; ++i)
108779f3128dSJiawen Wu 		rxq->sw_ring[rxq->rx_tail + i].mbuf = NULL;
108879f3128dSJiawen Wu 
108979f3128dSJiawen Wu 	return nb_rx;
109079f3128dSJiawen Wu }
109179f3128dSJiawen Wu 
109279f3128dSJiawen Wu static inline int
109379f3128dSJiawen Wu ngbe_rx_alloc_bufs(struct ngbe_rx_queue *rxq, bool reset_mbuf)
109479f3128dSJiawen Wu {
109579f3128dSJiawen Wu 	volatile struct ngbe_rx_desc *rxdp;
109679f3128dSJiawen Wu 	struct ngbe_rx_entry *rxep;
109779f3128dSJiawen Wu 	struct rte_mbuf *mb;
109879f3128dSJiawen Wu 	uint16_t alloc_idx;
109979f3128dSJiawen Wu 	__le64 dma_addr;
110079f3128dSJiawen Wu 	int diag, i;
110179f3128dSJiawen Wu 
110279f3128dSJiawen Wu 	/* allocate buffers in bulk directly into the S/W ring */
110379f3128dSJiawen Wu 	alloc_idx = rxq->rx_free_trigger - (rxq->rx_free_thresh - 1);
110479f3128dSJiawen Wu 	rxep = &rxq->sw_ring[alloc_idx];
110579f3128dSJiawen Wu 	diag = rte_mempool_get_bulk(rxq->mb_pool, (void *)rxep,
110679f3128dSJiawen Wu 				    rxq->rx_free_thresh);
110779f3128dSJiawen Wu 	if (unlikely(diag != 0))
110879f3128dSJiawen Wu 		return -ENOMEM;
110979f3128dSJiawen Wu 
111079f3128dSJiawen Wu 	rxdp = &rxq->rx_ring[alloc_idx];
111179f3128dSJiawen Wu 	for (i = 0; i < rxq->rx_free_thresh; ++i) {
111279f3128dSJiawen Wu 		/* populate the static rte mbuf fields */
111379f3128dSJiawen Wu 		mb = rxep[i].mbuf;
111479f3128dSJiawen Wu 		if (reset_mbuf)
111579f3128dSJiawen Wu 			mb->port = rxq->port_id;
111679f3128dSJiawen Wu 
111779f3128dSJiawen Wu 		rte_mbuf_refcnt_set(mb, 1);
111879f3128dSJiawen Wu 		mb->data_off = RTE_PKTMBUF_HEADROOM;
111979f3128dSJiawen Wu 
112079f3128dSJiawen Wu 		/* populate the descriptors */
112179f3128dSJiawen Wu 		dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mb));
112279f3128dSJiawen Wu 		NGBE_RXD_HDRADDR(&rxdp[i], 0);
112379f3128dSJiawen Wu 		NGBE_RXD_PKTADDR(&rxdp[i], dma_addr);
112479f3128dSJiawen Wu 	}
112579f3128dSJiawen Wu 
112679f3128dSJiawen Wu 	/* update state of internal queue structure */
112779f3128dSJiawen Wu 	rxq->rx_free_trigger = rxq->rx_free_trigger + rxq->rx_free_thresh;
112879f3128dSJiawen Wu 	if (rxq->rx_free_trigger >= rxq->nb_rx_desc)
112979f3128dSJiawen Wu 		rxq->rx_free_trigger = rxq->rx_free_thresh - 1;
113079f3128dSJiawen Wu 
113179f3128dSJiawen Wu 	/* no errors */
113279f3128dSJiawen Wu 	return 0;
113379f3128dSJiawen Wu }
113479f3128dSJiawen Wu 
113579f3128dSJiawen Wu static inline uint16_t
113679f3128dSJiawen Wu ngbe_rx_fill_from_stage(struct ngbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
113779f3128dSJiawen Wu 			 uint16_t nb_pkts)
113879f3128dSJiawen Wu {
113979f3128dSJiawen Wu 	struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail];
114079f3128dSJiawen Wu 	int i;
114179f3128dSJiawen Wu 
114279f3128dSJiawen Wu 	/* how many packets are ready to return? */
114379f3128dSJiawen Wu 	nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail);
114479f3128dSJiawen Wu 
114579f3128dSJiawen Wu 	/* copy mbuf pointers to the application's packet list */
114679f3128dSJiawen Wu 	for (i = 0; i < nb_pkts; ++i)
114779f3128dSJiawen Wu 		rx_pkts[i] = stage[i];
114879f3128dSJiawen Wu 
114979f3128dSJiawen Wu 	/* update internal queue state */
115079f3128dSJiawen Wu 	rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts);
115179f3128dSJiawen Wu 	rxq->rx_next_avail = (uint16_t)(rxq->rx_next_avail + nb_pkts);
115279f3128dSJiawen Wu 
115379f3128dSJiawen Wu 	return nb_pkts;
115479f3128dSJiawen Wu }
115579f3128dSJiawen Wu 
115679f3128dSJiawen Wu static inline uint16_t
115779f3128dSJiawen Wu ngbe_rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
115879f3128dSJiawen Wu 	     uint16_t nb_pkts)
115979f3128dSJiawen Wu {
116079f3128dSJiawen Wu 	struct ngbe_rx_queue *rxq = (struct ngbe_rx_queue *)rx_queue;
116179f3128dSJiawen Wu 	struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
116279f3128dSJiawen Wu 	uint16_t nb_rx = 0;
116379f3128dSJiawen Wu 
116479f3128dSJiawen Wu 	/* Any previously recv'd pkts will be returned from the Rx stage */
116579f3128dSJiawen Wu 	if (rxq->rx_nb_avail)
116679f3128dSJiawen Wu 		return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts);
116779f3128dSJiawen Wu 
116879f3128dSJiawen Wu 	/* Scan the H/W ring for packets to receive */
116979f3128dSJiawen Wu 	nb_rx = (uint16_t)ngbe_rx_scan_hw_ring(rxq);
117079f3128dSJiawen Wu 
117179f3128dSJiawen Wu 	/* update internal queue state */
117279f3128dSJiawen Wu 	rxq->rx_next_avail = 0;
117379f3128dSJiawen Wu 	rxq->rx_nb_avail = nb_rx;
117479f3128dSJiawen Wu 	rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_rx);
117579f3128dSJiawen Wu 
117679f3128dSJiawen Wu 	/* if required, allocate new buffers to replenish descriptors */
117779f3128dSJiawen Wu 	if (rxq->rx_tail > rxq->rx_free_trigger) {
117879f3128dSJiawen Wu 		uint16_t cur_free_trigger = rxq->rx_free_trigger;
117979f3128dSJiawen Wu 
118079f3128dSJiawen Wu 		if (ngbe_rx_alloc_bufs(rxq, true) != 0) {
118179f3128dSJiawen Wu 			int i, j;
118279f3128dSJiawen Wu 
118379f3128dSJiawen Wu 			PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u "
118479f3128dSJiawen Wu 				   "queue_id=%u", (uint16_t)rxq->port_id,
118579f3128dSJiawen Wu 				   (uint16_t)rxq->queue_id);
118679f3128dSJiawen Wu 
118779f3128dSJiawen Wu 			dev->data->rx_mbuf_alloc_failed +=
118879f3128dSJiawen Wu 				rxq->rx_free_thresh;
118979f3128dSJiawen Wu 
119079f3128dSJiawen Wu 			/*
119179f3128dSJiawen Wu 			 * Need to rewind any previous receives if we cannot
119279f3128dSJiawen Wu 			 * allocate new buffers to replenish the old ones.
119379f3128dSJiawen Wu 			 */
119479f3128dSJiawen Wu 			rxq->rx_nb_avail = 0;
119579f3128dSJiawen Wu 			rxq->rx_tail = (uint16_t)(rxq->rx_tail - nb_rx);
119679f3128dSJiawen Wu 			for (i = 0, j = rxq->rx_tail; i < nb_rx; ++i, ++j)
119779f3128dSJiawen Wu 				rxq->sw_ring[j].mbuf = rxq->rx_stage[i];
119879f3128dSJiawen Wu 
119979f3128dSJiawen Wu 			return 0;
120079f3128dSJiawen Wu 		}
120179f3128dSJiawen Wu 
120279f3128dSJiawen Wu 		/* update tail pointer */
120379f3128dSJiawen Wu 		rte_wmb();
120479f3128dSJiawen Wu 		ngbe_set32_relaxed(rxq->rdt_reg_addr, cur_free_trigger);
120579f3128dSJiawen Wu 	}
120679f3128dSJiawen Wu 
120779f3128dSJiawen Wu 	if (rxq->rx_tail >= rxq->nb_rx_desc)
120879f3128dSJiawen Wu 		rxq->rx_tail = 0;
120979f3128dSJiawen Wu 
121079f3128dSJiawen Wu 	/* received any packets this loop? */
121179f3128dSJiawen Wu 	if (rxq->rx_nb_avail)
121279f3128dSJiawen Wu 		return ngbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts);
121379f3128dSJiawen Wu 
121479f3128dSJiawen Wu 	return 0;
121579f3128dSJiawen Wu }
121679f3128dSJiawen Wu 
121779f3128dSJiawen Wu /* split requests into chunks of size RTE_PMD_NGBE_RX_MAX_BURST */
121879f3128dSJiawen Wu uint16_t
121979f3128dSJiawen Wu ngbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts,
122079f3128dSJiawen Wu 			   uint16_t nb_pkts)
122179f3128dSJiawen Wu {
122279f3128dSJiawen Wu 	uint16_t nb_rx;
122379f3128dSJiawen Wu 
122479f3128dSJiawen Wu 	if (unlikely(nb_pkts == 0))
122579f3128dSJiawen Wu 		return 0;
122679f3128dSJiawen Wu 
122779f3128dSJiawen Wu 	if (likely(nb_pkts <= RTE_PMD_NGBE_RX_MAX_BURST))
122879f3128dSJiawen Wu 		return ngbe_rx_recv_pkts(rx_queue, rx_pkts, nb_pkts);
122979f3128dSJiawen Wu 
123079f3128dSJiawen Wu 	/* request is relatively large, chunk it up */
123179f3128dSJiawen Wu 	nb_rx = 0;
123279f3128dSJiawen Wu 	while (nb_pkts) {
123379f3128dSJiawen Wu 		uint16_t ret, n;
123479f3128dSJiawen Wu 
123579f3128dSJiawen Wu 		n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_NGBE_RX_MAX_BURST);
123679f3128dSJiawen Wu 		ret = ngbe_rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n);
123779f3128dSJiawen Wu 		nb_rx = (uint16_t)(nb_rx + ret);
123879f3128dSJiawen Wu 		nb_pkts = (uint16_t)(nb_pkts - ret);
123979f3128dSJiawen Wu 		if (ret < n)
124079f3128dSJiawen Wu 			break;
124179f3128dSJiawen Wu 	}
124279f3128dSJiawen Wu 
124379f3128dSJiawen Wu 	return nb_rx;
124479f3128dSJiawen Wu }
124579f3128dSJiawen Wu 
124693dfebd2SJiawen Wu uint16_t
124793dfebd2SJiawen Wu ngbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
124893dfebd2SJiawen Wu 		uint16_t nb_pkts)
124993dfebd2SJiawen Wu {
125093dfebd2SJiawen Wu 	struct ngbe_rx_queue *rxq;
125193dfebd2SJiawen Wu 	volatile struct ngbe_rx_desc *rx_ring;
125293dfebd2SJiawen Wu 	volatile struct ngbe_rx_desc *rxdp;
125393dfebd2SJiawen Wu 	struct ngbe_rx_entry *sw_ring;
125493dfebd2SJiawen Wu 	struct ngbe_rx_entry *rxe;
125593dfebd2SJiawen Wu 	struct rte_mbuf *rxm;
125693dfebd2SJiawen Wu 	struct rte_mbuf *nmb;
125793dfebd2SJiawen Wu 	struct ngbe_rx_desc rxd;
125893dfebd2SJiawen Wu 	uint64_t dma_addr;
125993dfebd2SJiawen Wu 	uint32_t staterr;
1260f6aef1daSJiawen Wu 	uint32_t pkt_info;
126193dfebd2SJiawen Wu 	uint16_t pkt_len;
126293dfebd2SJiawen Wu 	uint16_t rx_id;
126393dfebd2SJiawen Wu 	uint16_t nb_rx;
126493dfebd2SJiawen Wu 	uint16_t nb_hold;
1265ffc959f5SJiawen Wu 	uint64_t pkt_flags;
126693dfebd2SJiawen Wu 
126793dfebd2SJiawen Wu 	nb_rx = 0;
126893dfebd2SJiawen Wu 	nb_hold = 0;
126993dfebd2SJiawen Wu 	rxq = rx_queue;
127093dfebd2SJiawen Wu 	rx_id = rxq->rx_tail;
127193dfebd2SJiawen Wu 	rx_ring = rxq->rx_ring;
127293dfebd2SJiawen Wu 	sw_ring = rxq->sw_ring;
127393dfebd2SJiawen Wu 	struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
127493dfebd2SJiawen Wu 	while (nb_rx < nb_pkts) {
127593dfebd2SJiawen Wu 		/*
127693dfebd2SJiawen Wu 		 * The order of operations here is important as the DD status
127793dfebd2SJiawen Wu 		 * bit must not be read after any other descriptor fields.
127893dfebd2SJiawen Wu 		 * rx_ring and rxdp are pointing to volatile data so the order
127993dfebd2SJiawen Wu 		 * of accesses cannot be reordered by the compiler. If they were
128093dfebd2SJiawen Wu 		 * not volatile, they could be reordered which could lead to
128193dfebd2SJiawen Wu 		 * using invalid descriptor fields when read from rxd.
1282a74c5001SJiawen Wu 		 *
1283a74c5001SJiawen Wu 		 * Meanwhile, to prevent the CPU from executing out of order, we
1284a74c5001SJiawen Wu 		 * need to use a proper memory barrier to ensure the memory
1285a74c5001SJiawen Wu 		 * ordering below.
128693dfebd2SJiawen Wu 		 */
128793dfebd2SJiawen Wu 		rxdp = &rx_ring[rx_id];
128893dfebd2SJiawen Wu 		staterr = rxdp->qw1.lo.status;
128993dfebd2SJiawen Wu 		if (!(staterr & rte_cpu_to_le_32(NGBE_RXD_STAT_DD)))
129093dfebd2SJiawen Wu 			break;
1291a74c5001SJiawen Wu 
1292a74c5001SJiawen Wu 		/*
1293a74c5001SJiawen Wu 		 * Use acquire fence to ensure that status_error which includes
1294a74c5001SJiawen Wu 		 * DD bit is loaded before loading of other descriptor words.
1295a74c5001SJiawen Wu 		 */
1296a74c5001SJiawen Wu 		rte_atomic_thread_fence(rte_memory_order_acquire);
1297a74c5001SJiawen Wu 
129893dfebd2SJiawen Wu 		rxd = *rxdp;
129993dfebd2SJiawen Wu 
130093dfebd2SJiawen Wu 		/*
130193dfebd2SJiawen Wu 		 * End of packet.
130293dfebd2SJiawen Wu 		 *
130393dfebd2SJiawen Wu 		 * If the NGBE_RXD_STAT_EOP flag is not set, the Rx packet
130493dfebd2SJiawen Wu 		 * is likely to be invalid and to be dropped by the various
130593dfebd2SJiawen Wu 		 * validation checks performed by the network stack.
130693dfebd2SJiawen Wu 		 *
130793dfebd2SJiawen Wu 		 * Allocate a new mbuf to replenish the RX ring descriptor.
130893dfebd2SJiawen Wu 		 * If the allocation fails:
130993dfebd2SJiawen Wu 		 *    - arrange for that Rx descriptor to be the first one
131093dfebd2SJiawen Wu 		 *      being parsed the next time the receive function is
131193dfebd2SJiawen Wu 		 *      invoked [on the same queue].
131293dfebd2SJiawen Wu 		 *
131393dfebd2SJiawen Wu 		 *    - Stop parsing the Rx ring and return immediately.
131493dfebd2SJiawen Wu 		 *
131593dfebd2SJiawen Wu 		 * This policy do not drop the packet received in the Rx
131693dfebd2SJiawen Wu 		 * descriptor for which the allocation of a new mbuf failed.
131793dfebd2SJiawen Wu 		 * Thus, it allows that packet to be later retrieved if
131893dfebd2SJiawen Wu 		 * mbuf have been freed in the mean time.
131993dfebd2SJiawen Wu 		 * As a side effect, holding Rx descriptors instead of
132093dfebd2SJiawen Wu 		 * systematically giving them back to the NIC may lead to
132193dfebd2SJiawen Wu 		 * Rx ring exhaustion situations.
132293dfebd2SJiawen Wu 		 * However, the NIC can gracefully prevent such situations
132393dfebd2SJiawen Wu 		 * to happen by sending specific "back-pressure" flow control
132493dfebd2SJiawen Wu 		 * frames to its peer(s).
132593dfebd2SJiawen Wu 		 */
132693dfebd2SJiawen Wu 		PMD_RX_LOG(DEBUG,
132793dfebd2SJiawen Wu 			   "port_id=%u queue_id=%u rx_id=%u ext_err_stat=0x%08x pkt_len=%u",
132893dfebd2SJiawen Wu 			   (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id,
132993dfebd2SJiawen Wu 			   (uint16_t)rx_id, (uint32_t)staterr,
133093dfebd2SJiawen Wu 			   (uint16_t)rte_le_to_cpu_16(rxd.qw1.hi.len));
133193dfebd2SJiawen Wu 
133293dfebd2SJiawen Wu 		nmb = rte_mbuf_raw_alloc(rxq->mb_pool);
133393dfebd2SJiawen Wu 		if (nmb == NULL) {
133493dfebd2SJiawen Wu 			PMD_RX_LOG(DEBUG,
133593dfebd2SJiawen Wu 				   "Rx mbuf alloc failed port_id=%u queue_id=%u",
133693dfebd2SJiawen Wu 				   (uint16_t)rxq->port_id,
133793dfebd2SJiawen Wu 				   (uint16_t)rxq->queue_id);
133893dfebd2SJiawen Wu 			dev->data->rx_mbuf_alloc_failed++;
133993dfebd2SJiawen Wu 			break;
134093dfebd2SJiawen Wu 		}
134193dfebd2SJiawen Wu 
134293dfebd2SJiawen Wu 		nb_hold++;
134393dfebd2SJiawen Wu 		rxe = &sw_ring[rx_id];
134493dfebd2SJiawen Wu 		rx_id++;
134593dfebd2SJiawen Wu 		if (rx_id == rxq->nb_rx_desc)
134693dfebd2SJiawen Wu 			rx_id = 0;
134793dfebd2SJiawen Wu 
134893dfebd2SJiawen Wu 		/* Prefetch next mbuf while processing current one. */
134993dfebd2SJiawen Wu 		rte_ngbe_prefetch(sw_ring[rx_id].mbuf);
135093dfebd2SJiawen Wu 
135193dfebd2SJiawen Wu 		/*
135293dfebd2SJiawen Wu 		 * When next Rx descriptor is on a cache-line boundary,
135393dfebd2SJiawen Wu 		 * prefetch the next 4 Rx descriptors and the next 8 pointers
135493dfebd2SJiawen Wu 		 * to mbufs.
135593dfebd2SJiawen Wu 		 */
135693dfebd2SJiawen Wu 		if ((rx_id & 0x3) == 0) {
135793dfebd2SJiawen Wu 			rte_ngbe_prefetch(&rx_ring[rx_id]);
135893dfebd2SJiawen Wu 			rte_ngbe_prefetch(&sw_ring[rx_id]);
135993dfebd2SJiawen Wu 		}
136093dfebd2SJiawen Wu 
136193dfebd2SJiawen Wu 		rxm = rxe->mbuf;
136293dfebd2SJiawen Wu 		rxe->mbuf = nmb;
136393dfebd2SJiawen Wu 		dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb));
136493dfebd2SJiawen Wu 		NGBE_RXD_HDRADDR(rxdp, 0);
136593dfebd2SJiawen Wu 		NGBE_RXD_PKTADDR(rxdp, dma_addr);
136693dfebd2SJiawen Wu 
136793dfebd2SJiawen Wu 		/*
136893dfebd2SJiawen Wu 		 * Initialize the returned mbuf.
1369ffc959f5SJiawen Wu 		 * 1) setup generic mbuf fields:
137093dfebd2SJiawen Wu 		 *    - number of segments,
137193dfebd2SJiawen Wu 		 *    - next segment,
137293dfebd2SJiawen Wu 		 *    - packet length,
137393dfebd2SJiawen Wu 		 *    - Rx port identifier.
1374ffc959f5SJiawen Wu 		 * 2) integrate hardware offload data, if any:
13750779d7f6SJiawen Wu 		 *    - RSS flag & hash,
1376ffc959f5SJiawen Wu 		 *    - IP checksum flag,
137759b46438SJiawen Wu 		 *    - VLAN TCI, if any,
1378ffc959f5SJiawen Wu 		 *    - error flags.
137993dfebd2SJiawen Wu 		 */
138064b36e4aSJiawen Wu 		pkt_len = (uint16_t)(rte_le_to_cpu_16(rxd.qw1.hi.len) -
138164b36e4aSJiawen Wu 				      rxq->crc_len);
138293dfebd2SJiawen Wu 		rxm->data_off = RTE_PKTMBUF_HEADROOM;
138393dfebd2SJiawen Wu 		rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off);
138493dfebd2SJiawen Wu 		rxm->nb_segs = 1;
138593dfebd2SJiawen Wu 		rxm->next = NULL;
138693dfebd2SJiawen Wu 		rxm->pkt_len = pkt_len;
138793dfebd2SJiawen Wu 		rxm->data_len = pkt_len;
138893dfebd2SJiawen Wu 		rxm->port = rxq->port_id;
138993dfebd2SJiawen Wu 
1390f6aef1daSJiawen Wu 		pkt_info = rte_le_to_cpu_32(rxd.qw0.dw0);
139159b46438SJiawen Wu 		/* Only valid if RTE_MBUF_F_RX_VLAN set in pkt_flags */
139259b46438SJiawen Wu 		rxm->vlan_tci = rte_le_to_cpu_16(rxd.qw1.hi.tag);
139359b46438SJiawen Wu 
139459b46438SJiawen Wu 		pkt_flags = rx_desc_status_to_pkt_flags(staterr,
139559b46438SJiawen Wu 					rxq->vlan_flags);
139659b46438SJiawen Wu 		pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
13970779d7f6SJiawen Wu 		pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info);
1398ffc959f5SJiawen Wu 		rxm->ol_flags = pkt_flags;
1399f6aef1daSJiawen Wu 		rxm->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info,
1400f6aef1daSJiawen Wu 						       NGBE_PTID_MASK);
1401f6aef1daSJiawen Wu 
14020779d7f6SJiawen Wu 		if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH))
14030779d7f6SJiawen Wu 			rxm->hash.rss = rte_le_to_cpu_32(rxd.qw0.dw1);
14040779d7f6SJiawen Wu 
140593dfebd2SJiawen Wu 		/*
140693dfebd2SJiawen Wu 		 * Store the mbuf address into the next entry of the array
140793dfebd2SJiawen Wu 		 * of returned packets.
140893dfebd2SJiawen Wu 		 */
140993dfebd2SJiawen Wu 		rx_pkts[nb_rx++] = rxm;
141093dfebd2SJiawen Wu 	}
141193dfebd2SJiawen Wu 	rxq->rx_tail = rx_id;
141293dfebd2SJiawen Wu 
141393dfebd2SJiawen Wu 	/*
141493dfebd2SJiawen Wu 	 * If the number of free Rx descriptors is greater than the Rx free
141593dfebd2SJiawen Wu 	 * threshold of the queue, advance the Receive Descriptor Tail (RDT)
141693dfebd2SJiawen Wu 	 * register.
141793dfebd2SJiawen Wu 	 * Update the RDT with the value of the last processed Rx descriptor
141893dfebd2SJiawen Wu 	 * minus 1, to guarantee that the RDT register is never equal to the
141993dfebd2SJiawen Wu 	 * RDH register, which creates a "full" ring situation from the
142093dfebd2SJiawen Wu 	 * hardware point of view...
142193dfebd2SJiawen Wu 	 */
142293dfebd2SJiawen Wu 	nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold);
142393dfebd2SJiawen Wu 	if (nb_hold > rxq->rx_free_thresh) {
142493dfebd2SJiawen Wu 		PMD_RX_LOG(DEBUG,
142593dfebd2SJiawen Wu 			   "port_id=%u queue_id=%u rx_tail=%u nb_hold=%u nb_rx=%u",
142693dfebd2SJiawen Wu 			   (uint16_t)rxq->port_id, (uint16_t)rxq->queue_id,
142793dfebd2SJiawen Wu 			   (uint16_t)rx_id, (uint16_t)nb_hold,
142893dfebd2SJiawen Wu 			   (uint16_t)nb_rx);
142993dfebd2SJiawen Wu 		rx_id = (uint16_t)((rx_id == 0) ?
143093dfebd2SJiawen Wu 				(rxq->nb_rx_desc - 1) : (rx_id - 1));
143193dfebd2SJiawen Wu 		ngbe_set32(rxq->rdt_reg_addr, rx_id);
143293dfebd2SJiawen Wu 		nb_hold = 0;
143393dfebd2SJiawen Wu 	}
143493dfebd2SJiawen Wu 	rxq->nb_rx_hold = nb_hold;
143593dfebd2SJiawen Wu 	return nb_rx;
143693dfebd2SJiawen Wu }
143793dfebd2SJiawen Wu 
1438ffc959f5SJiawen Wu /**
1439ffc959f5SJiawen Wu  * ngbe_fill_cluster_head_buf - fill the first mbuf of the returned packet
1440ffc959f5SJiawen Wu  *
1441ffc959f5SJiawen Wu  * Fill the following info in the HEAD buffer of the Rx cluster:
1442ffc959f5SJiawen Wu  *    - RX port identifier
1443ffc959f5SJiawen Wu  *    - hardware offload data, if any:
14440779d7f6SJiawen Wu  *      - RSS flag & hash
1445ffc959f5SJiawen Wu  *      - IP checksum flag
144659b46438SJiawen Wu  *      - VLAN TCI, if any
1447ffc959f5SJiawen Wu  *      - error flags
1448ffc959f5SJiawen Wu  * @head HEAD of the packet cluster
1449ffc959f5SJiawen Wu  * @desc HW descriptor to get data from
1450ffc959f5SJiawen Wu  * @rxq Pointer to the Rx queue
1451ffc959f5SJiawen Wu  */
145279f3128dSJiawen Wu static inline void
145379f3128dSJiawen Wu ngbe_fill_cluster_head_buf(struct rte_mbuf *head, struct ngbe_rx_desc *desc,
145479f3128dSJiawen Wu 		struct ngbe_rx_queue *rxq, uint32_t staterr)
145579f3128dSJiawen Wu {
145679f3128dSJiawen Wu 	uint32_t pkt_info;
1457ffc959f5SJiawen Wu 	uint64_t pkt_flags;
145879f3128dSJiawen Wu 
145979f3128dSJiawen Wu 	head->port = rxq->port_id;
146079f3128dSJiawen Wu 
146159b46438SJiawen Wu 	/* The vlan_tci field is only valid when RTE_MBUF_F_RX_VLAN is
146259b46438SJiawen Wu 	 * set in the pkt_flags field.
146359b46438SJiawen Wu 	 */
146459b46438SJiawen Wu 	head->vlan_tci = rte_le_to_cpu_16(desc->qw1.hi.tag);
146579f3128dSJiawen Wu 	pkt_info = rte_le_to_cpu_32(desc->qw0.dw0);
146659b46438SJiawen Wu 	pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags);
146759b46438SJiawen Wu 	pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
14680779d7f6SJiawen Wu 	pkt_flags |= ngbe_rxd_pkt_info_to_pkt_flags(pkt_info);
1469ffc959f5SJiawen Wu 	head->ol_flags = pkt_flags;
147079f3128dSJiawen Wu 	head->packet_type = ngbe_rxd_pkt_info_to_pkt_type(pkt_info,
147179f3128dSJiawen Wu 						NGBE_PTID_MASK);
14720779d7f6SJiawen Wu 
14730779d7f6SJiawen Wu 	if (likely(pkt_flags & RTE_MBUF_F_RX_RSS_HASH))
14740779d7f6SJiawen Wu 		head->hash.rss = rte_le_to_cpu_32(desc->qw0.dw1);
147579f3128dSJiawen Wu }
147679f3128dSJiawen Wu 
147779f3128dSJiawen Wu /**
147879f3128dSJiawen Wu  * ngbe_recv_pkts_sc - receive handler for scatter case.
147979f3128dSJiawen Wu  *
148079f3128dSJiawen Wu  * @rx_queue Rx queue handle
148179f3128dSJiawen Wu  * @rx_pkts table of received packets
148279f3128dSJiawen Wu  * @nb_pkts size of rx_pkts table
148379f3128dSJiawen Wu  * @bulk_alloc if TRUE bulk allocation is used for a HW ring refilling
148479f3128dSJiawen Wu  *
148579f3128dSJiawen Wu  * Returns the number of received packets/clusters (according to the "bulk
148679f3128dSJiawen Wu  * receive" interface).
148779f3128dSJiawen Wu  */
148879f3128dSJiawen Wu static inline uint16_t
148979f3128dSJiawen Wu ngbe_recv_pkts_sc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts,
149079f3128dSJiawen Wu 		    bool bulk_alloc)
149179f3128dSJiawen Wu {
149279f3128dSJiawen Wu 	struct ngbe_rx_queue *rxq = rx_queue;
149379f3128dSJiawen Wu 	struct rte_eth_dev *dev = &rte_eth_devices[rxq->port_id];
149479f3128dSJiawen Wu 	volatile struct ngbe_rx_desc *rx_ring = rxq->rx_ring;
149579f3128dSJiawen Wu 	struct ngbe_rx_entry *sw_ring = rxq->sw_ring;
149679f3128dSJiawen Wu 	struct ngbe_scattered_rx_entry *sw_sc_ring = rxq->sw_sc_ring;
149779f3128dSJiawen Wu 	uint16_t rx_id = rxq->rx_tail;
149879f3128dSJiawen Wu 	uint16_t nb_rx = 0;
149979f3128dSJiawen Wu 	uint16_t nb_hold = rxq->nb_rx_hold;
150079f3128dSJiawen Wu 	uint16_t prev_id = rxq->rx_tail;
150179f3128dSJiawen Wu 
150279f3128dSJiawen Wu 	while (nb_rx < nb_pkts) {
150379f3128dSJiawen Wu 		bool eop;
150479f3128dSJiawen Wu 		struct ngbe_rx_entry *rxe;
150579f3128dSJiawen Wu 		struct ngbe_scattered_rx_entry *sc_entry;
150679f3128dSJiawen Wu 		struct ngbe_scattered_rx_entry *next_sc_entry = NULL;
150779f3128dSJiawen Wu 		struct ngbe_rx_entry *next_rxe = NULL;
150879f3128dSJiawen Wu 		struct rte_mbuf *first_seg;
150979f3128dSJiawen Wu 		struct rte_mbuf *rxm;
151079f3128dSJiawen Wu 		struct rte_mbuf *nmb = NULL;
151179f3128dSJiawen Wu 		struct ngbe_rx_desc rxd;
151279f3128dSJiawen Wu 		uint16_t data_len;
151379f3128dSJiawen Wu 		uint16_t next_id;
151479f3128dSJiawen Wu 		volatile struct ngbe_rx_desc *rxdp;
151579f3128dSJiawen Wu 		uint32_t staterr;
151679f3128dSJiawen Wu 
151779f3128dSJiawen Wu next_desc:
151879f3128dSJiawen Wu 		rxdp = &rx_ring[rx_id];
151979f3128dSJiawen Wu 		staterr = rte_le_to_cpu_32(rxdp->qw1.lo.status);
152079f3128dSJiawen Wu 
152179f3128dSJiawen Wu 		if (!(staterr & NGBE_RXD_STAT_DD))
152279f3128dSJiawen Wu 			break;
152379f3128dSJiawen Wu 
1524a74c5001SJiawen Wu 		/*
1525a74c5001SJiawen Wu 		 * Use acquire fence to ensure that status_error which includes
1526a74c5001SJiawen Wu 		 * DD bit is loaded before loading of other descriptor words.
1527a74c5001SJiawen Wu 		 */
1528a74c5001SJiawen Wu 		rte_atomic_thread_fence(rte_memory_order_acquire);
1529a74c5001SJiawen Wu 
153079f3128dSJiawen Wu 		rxd = *rxdp;
153179f3128dSJiawen Wu 
153279f3128dSJiawen Wu 		PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u "
153379f3128dSJiawen Wu 				  "staterr=0x%x data_len=%u",
153479f3128dSJiawen Wu 			   rxq->port_id, rxq->queue_id, rx_id, staterr,
153579f3128dSJiawen Wu 			   rte_le_to_cpu_16(rxd.qw1.hi.len));
153679f3128dSJiawen Wu 
153779f3128dSJiawen Wu 		if (!bulk_alloc) {
153879f3128dSJiawen Wu 			nmb = rte_mbuf_raw_alloc(rxq->mb_pool);
153979f3128dSJiawen Wu 			if (nmb == NULL) {
154079f3128dSJiawen Wu 				PMD_RX_LOG(DEBUG, "Rx mbuf alloc failed "
154179f3128dSJiawen Wu 						  "port_id=%u queue_id=%u",
154279f3128dSJiawen Wu 					   rxq->port_id, rxq->queue_id);
154379f3128dSJiawen Wu 
154479f3128dSJiawen Wu 				dev->data->rx_mbuf_alloc_failed++;
154579f3128dSJiawen Wu 				break;
154679f3128dSJiawen Wu 			}
154779f3128dSJiawen Wu 		} else if (nb_hold > rxq->rx_free_thresh) {
154879f3128dSJiawen Wu 			uint16_t next_rdt = rxq->rx_free_trigger;
154979f3128dSJiawen Wu 
155079f3128dSJiawen Wu 			if (!ngbe_rx_alloc_bufs(rxq, false)) {
155179f3128dSJiawen Wu 				rte_wmb();
155279f3128dSJiawen Wu 				ngbe_set32_relaxed(rxq->rdt_reg_addr,
155379f3128dSJiawen Wu 							    next_rdt);
155479f3128dSJiawen Wu 				nb_hold -= rxq->rx_free_thresh;
155579f3128dSJiawen Wu 			} else {
155679f3128dSJiawen Wu 				PMD_RX_LOG(DEBUG, "Rx bulk alloc failed "
155779f3128dSJiawen Wu 						  "port_id=%u queue_id=%u",
155879f3128dSJiawen Wu 					   rxq->port_id, rxq->queue_id);
155979f3128dSJiawen Wu 
156079f3128dSJiawen Wu 				dev->data->rx_mbuf_alloc_failed++;
156179f3128dSJiawen Wu 				break;
156279f3128dSJiawen Wu 			}
156379f3128dSJiawen Wu 		}
156479f3128dSJiawen Wu 
156579f3128dSJiawen Wu 		nb_hold++;
156679f3128dSJiawen Wu 		rxe = &sw_ring[rx_id];
156779f3128dSJiawen Wu 		eop = staterr & NGBE_RXD_STAT_EOP;
156879f3128dSJiawen Wu 
156979f3128dSJiawen Wu 		next_id = rx_id + 1;
157079f3128dSJiawen Wu 		if (next_id == rxq->nb_rx_desc)
157179f3128dSJiawen Wu 			next_id = 0;
157279f3128dSJiawen Wu 
157379f3128dSJiawen Wu 		/* Prefetch next mbuf while processing current one. */
157479f3128dSJiawen Wu 		rte_ngbe_prefetch(sw_ring[next_id].mbuf);
157579f3128dSJiawen Wu 
157679f3128dSJiawen Wu 		/*
157779f3128dSJiawen Wu 		 * When next Rx descriptor is on a cache-line boundary,
157879f3128dSJiawen Wu 		 * prefetch the next 4 RX descriptors and the next 4 pointers
157979f3128dSJiawen Wu 		 * to mbufs.
158079f3128dSJiawen Wu 		 */
158179f3128dSJiawen Wu 		if ((next_id & 0x3) == 0) {
158279f3128dSJiawen Wu 			rte_ngbe_prefetch(&rx_ring[next_id]);
158379f3128dSJiawen Wu 			rte_ngbe_prefetch(&sw_ring[next_id]);
158479f3128dSJiawen Wu 		}
158579f3128dSJiawen Wu 
158679f3128dSJiawen Wu 		rxm = rxe->mbuf;
158779f3128dSJiawen Wu 
158879f3128dSJiawen Wu 		if (!bulk_alloc) {
158979f3128dSJiawen Wu 			__le64 dma =
159079f3128dSJiawen Wu 			  rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb));
159179f3128dSJiawen Wu 			/*
159279f3128dSJiawen Wu 			 * Update Rx descriptor with the physical address of the
159379f3128dSJiawen Wu 			 * new data buffer of the new allocated mbuf.
159479f3128dSJiawen Wu 			 */
159579f3128dSJiawen Wu 			rxe->mbuf = nmb;
159679f3128dSJiawen Wu 
159779f3128dSJiawen Wu 			rxm->data_off = RTE_PKTMBUF_HEADROOM;
159879f3128dSJiawen Wu 			NGBE_RXD_HDRADDR(rxdp, 0);
159979f3128dSJiawen Wu 			NGBE_RXD_PKTADDR(rxdp, dma);
160079f3128dSJiawen Wu 		} else {
160179f3128dSJiawen Wu 			rxe->mbuf = NULL;
160279f3128dSJiawen Wu 		}
160379f3128dSJiawen Wu 
160479f3128dSJiawen Wu 		/*
160579f3128dSJiawen Wu 		 * Set data length & data buffer address of mbuf.
160679f3128dSJiawen Wu 		 */
160779f3128dSJiawen Wu 		data_len = rte_le_to_cpu_16(rxd.qw1.hi.len);
160879f3128dSJiawen Wu 		rxm->data_len = data_len;
160979f3128dSJiawen Wu 
161079f3128dSJiawen Wu 		if (!eop) {
161179f3128dSJiawen Wu 			uint16_t nextp_id;
161279f3128dSJiawen Wu 
161379f3128dSJiawen Wu 			nextp_id = next_id;
161479f3128dSJiawen Wu 			next_sc_entry = &sw_sc_ring[nextp_id];
161579f3128dSJiawen Wu 			next_rxe = &sw_ring[nextp_id];
161679f3128dSJiawen Wu 			rte_ngbe_prefetch(next_rxe);
161779f3128dSJiawen Wu 		}
161879f3128dSJiawen Wu 
161979f3128dSJiawen Wu 		sc_entry = &sw_sc_ring[rx_id];
162079f3128dSJiawen Wu 		first_seg = sc_entry->fbuf;
162179f3128dSJiawen Wu 		sc_entry->fbuf = NULL;
162279f3128dSJiawen Wu 
162379f3128dSJiawen Wu 		/*
162479f3128dSJiawen Wu 		 * If this is the first buffer of the received packet,
162579f3128dSJiawen Wu 		 * set the pointer to the first mbuf of the packet and
162679f3128dSJiawen Wu 		 * initialize its context.
162779f3128dSJiawen Wu 		 * Otherwise, update the total length and the number of segments
162879f3128dSJiawen Wu 		 * of the current scattered packet, and update the pointer to
162979f3128dSJiawen Wu 		 * the last mbuf of the current packet.
163079f3128dSJiawen Wu 		 */
163179f3128dSJiawen Wu 		if (first_seg == NULL) {
163279f3128dSJiawen Wu 			first_seg = rxm;
163379f3128dSJiawen Wu 			first_seg->pkt_len = data_len;
163479f3128dSJiawen Wu 			first_seg->nb_segs = 1;
163579f3128dSJiawen Wu 		} else {
163679f3128dSJiawen Wu 			first_seg->pkt_len += data_len;
163779f3128dSJiawen Wu 			first_seg->nb_segs++;
163879f3128dSJiawen Wu 		}
163979f3128dSJiawen Wu 
164079f3128dSJiawen Wu 		prev_id = rx_id;
164179f3128dSJiawen Wu 		rx_id = next_id;
164279f3128dSJiawen Wu 
164379f3128dSJiawen Wu 		/*
164479f3128dSJiawen Wu 		 * If this is not the last buffer of the received packet, update
164579f3128dSJiawen Wu 		 * the pointer to the first mbuf at the NEXTP entry in the
164679f3128dSJiawen Wu 		 * sw_sc_ring and continue to parse the Rx ring.
164779f3128dSJiawen Wu 		 */
164879f3128dSJiawen Wu 		if (!eop && next_rxe) {
164979f3128dSJiawen Wu 			rxm->next = next_rxe->mbuf;
165079f3128dSJiawen Wu 			next_sc_entry->fbuf = first_seg;
165179f3128dSJiawen Wu 			goto next_desc;
165279f3128dSJiawen Wu 		}
165379f3128dSJiawen Wu 
165479f3128dSJiawen Wu 		/* Initialize the first mbuf of the returned packet */
165579f3128dSJiawen Wu 		ngbe_fill_cluster_head_buf(first_seg, &rxd, rxq, staterr);
165679f3128dSJiawen Wu 
165764b36e4aSJiawen Wu 		/* Deal with the case, when HW CRC srip is disabled. */
165864b36e4aSJiawen Wu 		first_seg->pkt_len -= rxq->crc_len;
165964b36e4aSJiawen Wu 		if (unlikely(rxm->data_len <= rxq->crc_len)) {
166064b36e4aSJiawen Wu 			struct rte_mbuf *lp;
166164b36e4aSJiawen Wu 
166264b36e4aSJiawen Wu 			for (lp = first_seg; lp->next != rxm; lp = lp->next)
166364b36e4aSJiawen Wu 				;
166464b36e4aSJiawen Wu 
166564b36e4aSJiawen Wu 			first_seg->nb_segs--;
166664b36e4aSJiawen Wu 			lp->data_len -= rxq->crc_len - rxm->data_len;
166764b36e4aSJiawen Wu 			lp->next = NULL;
166864b36e4aSJiawen Wu 			rte_pktmbuf_free_seg(rxm);
166964b36e4aSJiawen Wu 		} else {
167064b36e4aSJiawen Wu 			rxm->data_len -= rxq->crc_len;
167164b36e4aSJiawen Wu 		}
167264b36e4aSJiawen Wu 
167379f3128dSJiawen Wu 		/* Prefetch data of first segment, if configured to do so. */
167479f3128dSJiawen Wu 		rte_packet_prefetch((char *)first_seg->buf_addr +
167579f3128dSJiawen Wu 			first_seg->data_off);
167679f3128dSJiawen Wu 
167779f3128dSJiawen Wu 		/*
167879f3128dSJiawen Wu 		 * Store the mbuf address into the next entry of the array
167979f3128dSJiawen Wu 		 * of returned packets.
168079f3128dSJiawen Wu 		 */
168179f3128dSJiawen Wu 		rx_pkts[nb_rx++] = first_seg;
168279f3128dSJiawen Wu 	}
168379f3128dSJiawen Wu 
168479f3128dSJiawen Wu 	/*
168579f3128dSJiawen Wu 	 * Record index of the next Rx descriptor to probe.
168679f3128dSJiawen Wu 	 */
168779f3128dSJiawen Wu 	rxq->rx_tail = rx_id;
168879f3128dSJiawen Wu 
168979f3128dSJiawen Wu 	/*
169079f3128dSJiawen Wu 	 * If the number of free Rx descriptors is greater than the Rx free
169179f3128dSJiawen Wu 	 * threshold of the queue, advance the Receive Descriptor Tail (RDT)
169279f3128dSJiawen Wu 	 * register.
169379f3128dSJiawen Wu 	 * Update the RDT with the value of the last processed Rx descriptor
169479f3128dSJiawen Wu 	 * minus 1, to guarantee that the RDT register is never equal to the
169579f3128dSJiawen Wu 	 * RDH register, which creates a "full" ring situation from the
169679f3128dSJiawen Wu 	 * hardware point of view...
169779f3128dSJiawen Wu 	 */
169879f3128dSJiawen Wu 	if (!bulk_alloc && nb_hold > rxq->rx_free_thresh) {
169979f3128dSJiawen Wu 		PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u "
170079f3128dSJiawen Wu 			   "nb_hold=%u nb_rx=%u",
170179f3128dSJiawen Wu 			   rxq->port_id, rxq->queue_id, rx_id, nb_hold, nb_rx);
170279f3128dSJiawen Wu 
170379f3128dSJiawen Wu 		rte_wmb();
170479f3128dSJiawen Wu 		ngbe_set32_relaxed(rxq->rdt_reg_addr, prev_id);
170579f3128dSJiawen Wu 		nb_hold = 0;
170679f3128dSJiawen Wu 	}
170779f3128dSJiawen Wu 
170879f3128dSJiawen Wu 	rxq->nb_rx_hold = nb_hold;
170979f3128dSJiawen Wu 	return nb_rx;
171079f3128dSJiawen Wu }
171179f3128dSJiawen Wu 
171279f3128dSJiawen Wu uint16_t
171379f3128dSJiawen Wu ngbe_recv_pkts_sc_single_alloc(void *rx_queue, struct rte_mbuf **rx_pkts,
171479f3128dSJiawen Wu 				 uint16_t nb_pkts)
171579f3128dSJiawen Wu {
171679f3128dSJiawen Wu 	return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, false);
171779f3128dSJiawen Wu }
171879f3128dSJiawen Wu 
171979f3128dSJiawen Wu uint16_t
172079f3128dSJiawen Wu ngbe_recv_pkts_sc_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts,
172179f3128dSJiawen Wu 			       uint16_t nb_pkts)
172279f3128dSJiawen Wu {
172379f3128dSJiawen Wu 	return ngbe_recv_pkts_sc(rx_queue, rx_pkts, nb_pkts, true);
172479f3128dSJiawen Wu }
172593dfebd2SJiawen Wu 
1726a58e7c31SJiawen Wu /*********************************************************************
1727a58e7c31SJiawen Wu  *
1728a58e7c31SJiawen Wu  *  Queue management functions
1729a58e7c31SJiawen Wu  *
1730a58e7c31SJiawen Wu  **********************************************************************/
1731a58e7c31SJiawen Wu 
1732a58e7c31SJiawen Wu static void
1733a58e7c31SJiawen Wu ngbe_tx_queue_release_mbufs(struct ngbe_tx_queue *txq)
1734a58e7c31SJiawen Wu {
1735a58e7c31SJiawen Wu 	unsigned int i;
1736a58e7c31SJiawen Wu 
1737a58e7c31SJiawen Wu 	if (txq->sw_ring != NULL) {
1738a58e7c31SJiawen Wu 		for (i = 0; i < txq->nb_tx_desc; i++) {
1739a58e7c31SJiawen Wu 			if (txq->sw_ring[i].mbuf != NULL) {
1740a58e7c31SJiawen Wu 				rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
1741a58e7c31SJiawen Wu 				txq->sw_ring[i].mbuf = NULL;
1742a58e7c31SJiawen Wu 			}
1743a58e7c31SJiawen Wu 		}
1744a58e7c31SJiawen Wu 	}
1745a58e7c31SJiawen Wu }
1746a58e7c31SJiawen Wu 
1747d0759b50SJiawen Wu static int
1748d0759b50SJiawen Wu ngbe_tx_done_cleanup_full(struct ngbe_tx_queue *txq, uint32_t free_cnt)
1749d0759b50SJiawen Wu {
1750d0759b50SJiawen Wu 	struct ngbe_tx_entry *swr_ring = txq->sw_ring;
1751d0759b50SJiawen Wu 	uint16_t i, tx_last, tx_id;
1752d0759b50SJiawen Wu 	uint16_t nb_tx_free_last;
1753d0759b50SJiawen Wu 	uint16_t nb_tx_to_clean;
1754d0759b50SJiawen Wu 	uint32_t pkt_cnt;
1755d0759b50SJiawen Wu 
1756d0759b50SJiawen Wu 	/* Start free mbuf from the next of tx_tail */
1757d0759b50SJiawen Wu 	tx_last = txq->tx_tail;
1758d0759b50SJiawen Wu 	tx_id  = swr_ring[tx_last].next_id;
1759d0759b50SJiawen Wu 
1760d0759b50SJiawen Wu 	if (txq->nb_tx_free == 0 && ngbe_xmit_cleanup(txq))
1761d0759b50SJiawen Wu 		return 0;
1762d0759b50SJiawen Wu 
1763d0759b50SJiawen Wu 	nb_tx_to_clean = txq->nb_tx_free;
1764d0759b50SJiawen Wu 	nb_tx_free_last = txq->nb_tx_free;
1765d0759b50SJiawen Wu 	if (!free_cnt)
1766d0759b50SJiawen Wu 		free_cnt = txq->nb_tx_desc;
1767d0759b50SJiawen Wu 
1768d0759b50SJiawen Wu 	/* Loop through swr_ring to count the amount of
1769d0759b50SJiawen Wu 	 * freeable mubfs and packets.
1770d0759b50SJiawen Wu 	 */
1771d0759b50SJiawen Wu 	for (pkt_cnt = 0; pkt_cnt < free_cnt; ) {
1772d0759b50SJiawen Wu 		for (i = 0; i < nb_tx_to_clean &&
1773d0759b50SJiawen Wu 			pkt_cnt < free_cnt &&
1774d0759b50SJiawen Wu 			tx_id != tx_last; i++) {
1775d0759b50SJiawen Wu 			if (swr_ring[tx_id].mbuf != NULL) {
1776d0759b50SJiawen Wu 				rte_pktmbuf_free_seg(swr_ring[tx_id].mbuf);
1777d0759b50SJiawen Wu 				swr_ring[tx_id].mbuf = NULL;
1778d0759b50SJiawen Wu 
1779d0759b50SJiawen Wu 				/*
1780d0759b50SJiawen Wu 				 * last segment in the packet,
1781d0759b50SJiawen Wu 				 * increment packet count
1782d0759b50SJiawen Wu 				 */
1783d0759b50SJiawen Wu 				pkt_cnt += (swr_ring[tx_id].last_id == tx_id);
1784d0759b50SJiawen Wu 			}
1785d0759b50SJiawen Wu 
1786d0759b50SJiawen Wu 			tx_id = swr_ring[tx_id].next_id;
1787d0759b50SJiawen Wu 		}
1788d0759b50SJiawen Wu 
1789d0759b50SJiawen Wu 		if (pkt_cnt < free_cnt) {
1790d0759b50SJiawen Wu 			if (ngbe_xmit_cleanup(txq))
1791d0759b50SJiawen Wu 				break;
1792d0759b50SJiawen Wu 
1793d0759b50SJiawen Wu 			nb_tx_to_clean = txq->nb_tx_free - nb_tx_free_last;
1794d0759b50SJiawen Wu 			nb_tx_free_last = txq->nb_tx_free;
1795d0759b50SJiawen Wu 		}
1796d0759b50SJiawen Wu 	}
1797d0759b50SJiawen Wu 
1798d0759b50SJiawen Wu 	return (int)pkt_cnt;
1799d0759b50SJiawen Wu }
1800d0759b50SJiawen Wu 
1801d0759b50SJiawen Wu static int
1802d0759b50SJiawen Wu ngbe_tx_done_cleanup_simple(struct ngbe_tx_queue *txq,
1803d0759b50SJiawen Wu 			uint32_t free_cnt)
1804d0759b50SJiawen Wu {
1805d0759b50SJiawen Wu 	int i, n, cnt;
1806d0759b50SJiawen Wu 
1807d0759b50SJiawen Wu 	if (free_cnt == 0 || free_cnt > txq->nb_tx_desc)
1808d0759b50SJiawen Wu 		free_cnt = txq->nb_tx_desc;
1809d0759b50SJiawen Wu 
1810d0759b50SJiawen Wu 	cnt = free_cnt - free_cnt % txq->tx_free_thresh;
1811d0759b50SJiawen Wu 
1812d0759b50SJiawen Wu 	for (i = 0; i < cnt; i += n) {
1813d0759b50SJiawen Wu 		if (txq->nb_tx_desc - txq->nb_tx_free < txq->tx_free_thresh)
1814d0759b50SJiawen Wu 			break;
1815d0759b50SJiawen Wu 
1816d0759b50SJiawen Wu 		n = ngbe_tx_free_bufs(txq);
1817d0759b50SJiawen Wu 
1818d0759b50SJiawen Wu 		if (n == 0)
1819d0759b50SJiawen Wu 			break;
1820d0759b50SJiawen Wu 	}
1821d0759b50SJiawen Wu 
1822d0759b50SJiawen Wu 	return i;
1823d0759b50SJiawen Wu }
1824d0759b50SJiawen Wu 
1825d0759b50SJiawen Wu int
1826d0759b50SJiawen Wu ngbe_dev_tx_done_cleanup(void *tx_queue, uint32_t free_cnt)
1827d0759b50SJiawen Wu {
1828d0759b50SJiawen Wu 	struct ngbe_tx_queue *txq = (struct ngbe_tx_queue *)tx_queue;
1829d0759b50SJiawen Wu 	if (txq->offloads == 0 &&
1830d0759b50SJiawen Wu 		txq->tx_free_thresh >= RTE_PMD_NGBE_TX_MAX_BURST)
1831d0759b50SJiawen Wu 		return ngbe_tx_done_cleanup_simple(txq, free_cnt);
1832d0759b50SJiawen Wu 
1833d0759b50SJiawen Wu 	return ngbe_tx_done_cleanup_full(txq, free_cnt);
1834d0759b50SJiawen Wu }
1835d0759b50SJiawen Wu 
1836a58e7c31SJiawen Wu static void
1837a58e7c31SJiawen Wu ngbe_tx_free_swring(struct ngbe_tx_queue *txq)
1838a58e7c31SJiawen Wu {
1839a58e7c31SJiawen Wu 	if (txq != NULL)
1840a58e7c31SJiawen Wu 		rte_free(txq->sw_ring);
1841a58e7c31SJiawen Wu }
1842a58e7c31SJiawen Wu 
1843a58e7c31SJiawen Wu static void
1844a58e7c31SJiawen Wu ngbe_tx_queue_release(struct ngbe_tx_queue *txq)
1845a58e7c31SJiawen Wu {
1846a58e7c31SJiawen Wu 	if (txq != NULL) {
1847a58e7c31SJiawen Wu 		if (txq->ops != NULL) {
1848a58e7c31SJiawen Wu 			txq->ops->release_mbufs(txq);
1849a58e7c31SJiawen Wu 			txq->ops->free_swring(txq);
1850fea7422fSJiawen Wu 			rte_memzone_free(txq->mz);
1851a58e7c31SJiawen Wu 		}
1852a58e7c31SJiawen Wu 		rte_free(txq);
1853a58e7c31SJiawen Wu 	}
1854a58e7c31SJiawen Wu }
1855a58e7c31SJiawen Wu 
1856a58e7c31SJiawen Wu void
18577483341aSXueming Li ngbe_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1858a58e7c31SJiawen Wu {
18597483341aSXueming Li 	ngbe_tx_queue_release(dev->data->tx_queues[qid]);
1860a58e7c31SJiawen Wu }
1861a58e7c31SJiawen Wu 
1862a58e7c31SJiawen Wu /* (Re)set dynamic ngbe_tx_queue fields to defaults */
1863a58e7c31SJiawen Wu static void
1864a58e7c31SJiawen Wu ngbe_reset_tx_queue(struct ngbe_tx_queue *txq)
1865a58e7c31SJiawen Wu {
1866a58e7c31SJiawen Wu 	static const struct ngbe_tx_desc zeroed_desc = {0};
1867a58e7c31SJiawen Wu 	struct ngbe_tx_entry *txe = txq->sw_ring;
1868a58e7c31SJiawen Wu 	uint16_t prev, i;
1869a58e7c31SJiawen Wu 
1870a58e7c31SJiawen Wu 	/* Zero out HW ring memory */
1871a58e7c31SJiawen Wu 	for (i = 0; i < txq->nb_tx_desc; i++)
1872a58e7c31SJiawen Wu 		txq->tx_ring[i] = zeroed_desc;
1873a58e7c31SJiawen Wu 
1874a58e7c31SJiawen Wu 	/* Initialize SW ring entries */
1875a58e7c31SJiawen Wu 	prev = (uint16_t)(txq->nb_tx_desc - 1);
1876a58e7c31SJiawen Wu 	for (i = 0; i < txq->nb_tx_desc; i++) {
1877a58e7c31SJiawen Wu 		/* the ring can also be modified by hardware */
1878a58e7c31SJiawen Wu 		volatile struct ngbe_tx_desc *txd = &txq->tx_ring[i];
1879a58e7c31SJiawen Wu 
1880a58e7c31SJiawen Wu 		txd->dw3 = rte_cpu_to_le_32(NGBE_TXD_DD);
1881a58e7c31SJiawen Wu 		txe[i].mbuf = NULL;
1882a58e7c31SJiawen Wu 		txe[i].last_id = i;
1883a58e7c31SJiawen Wu 		txe[prev].next_id = i;
1884a58e7c31SJiawen Wu 		prev = i;
1885a58e7c31SJiawen Wu 	}
1886a58e7c31SJiawen Wu 
1887a58e7c31SJiawen Wu 	txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1);
1888a58e7c31SJiawen Wu 	txq->tx_tail = 0;
1889a58e7c31SJiawen Wu 
1890a58e7c31SJiawen Wu 	/*
1891a58e7c31SJiawen Wu 	 * Always allow 1 descriptor to be un-allocated to avoid
1892a58e7c31SJiawen Wu 	 * a H/W race condition
1893a58e7c31SJiawen Wu 	 */
1894a58e7c31SJiawen Wu 	txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1);
1895a58e7c31SJiawen Wu 	txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1);
1896a58e7c31SJiawen Wu 	txq->ctx_curr = 0;
1897a58e7c31SJiawen Wu 	memset((void *)&txq->ctx_cache, 0,
1898a58e7c31SJiawen Wu 		NGBE_CTX_NUM * sizeof(struct ngbe_ctx_info));
1899a58e7c31SJiawen Wu }
1900a58e7c31SJiawen Wu 
1901a58e7c31SJiawen Wu static const struct ngbe_txq_ops def_txq_ops = {
1902a58e7c31SJiawen Wu 	.release_mbufs = ngbe_tx_queue_release_mbufs,
1903a58e7c31SJiawen Wu 	.free_swring = ngbe_tx_free_swring,
1904a58e7c31SJiawen Wu 	.reset = ngbe_reset_tx_queue,
1905a58e7c31SJiawen Wu };
1906a58e7c31SJiawen Wu 
19079f320614SJiawen Wu /* Takes an ethdev and a queue and sets up the tx function to be used based on
19089f320614SJiawen Wu  * the queue parameters. Used in tx_queue_setup by primary process and then
19099f320614SJiawen Wu  * in dev_init by secondary process when attaching to an existing ethdev.
19109f320614SJiawen Wu  */
19119f320614SJiawen Wu void
19129f320614SJiawen Wu ngbe_set_tx_function(struct rte_eth_dev *dev, struct ngbe_tx_queue *txq)
19139f320614SJiawen Wu {
19149f320614SJiawen Wu 	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
19159f320614SJiawen Wu 	if (txq->offloads == 0 &&
19169f320614SJiawen Wu 			txq->tx_free_thresh >= RTE_PMD_NGBE_TX_MAX_BURST) {
19179f320614SJiawen Wu 		PMD_INIT_LOG(DEBUG, "Using simple tx code path");
19189f320614SJiawen Wu 		dev->tx_pkt_prepare = NULL;
1919e94c20c3SJiawen Wu 		if (txq->tx_free_thresh <= RTE_NGBE_TX_MAX_FREE_BUF_SZ &&
1920e94c20c3SJiawen Wu 				rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128 &&
1921e94c20c3SJiawen Wu 				(rte_eal_process_type() != RTE_PROC_PRIMARY ||
1922e94c20c3SJiawen Wu 					ngbe_txq_vec_setup(txq) == 0)) {
1923e94c20c3SJiawen Wu 			PMD_INIT_LOG(DEBUG, "Vector tx enabled.");
1924e94c20c3SJiawen Wu 			dev->tx_pkt_burst = ngbe_xmit_pkts_vec;
1925e94c20c3SJiawen Wu 		} else {
1926e94c20c3SJiawen Wu 			dev->tx_pkt_burst = ngbe_xmit_pkts_simple;
1927e94c20c3SJiawen Wu 		}
19289f320614SJiawen Wu 	} else {
19299f320614SJiawen Wu 		PMD_INIT_LOG(DEBUG, "Using full-featured tx code path");
19309f320614SJiawen Wu 		PMD_INIT_LOG(DEBUG,
19319f320614SJiawen Wu 				" - offloads = 0x%" PRIx64,
19329f320614SJiawen Wu 				txq->offloads);
19339f320614SJiawen Wu 		PMD_INIT_LOG(DEBUG,
19349f320614SJiawen Wu 				" - tx_free_thresh = %lu [RTE_PMD_NGBE_TX_MAX_BURST=%lu]",
19359f320614SJiawen Wu 				(unsigned long)txq->tx_free_thresh,
19369f320614SJiawen Wu 				(unsigned long)RTE_PMD_NGBE_TX_MAX_BURST);
19379f320614SJiawen Wu 		dev->tx_pkt_burst = ngbe_xmit_pkts;
19389f320614SJiawen Wu 		dev->tx_pkt_prepare = ngbe_prep_pkts;
19399f320614SJiawen Wu 	}
19409f320614SJiawen Wu }
19419f320614SJiawen Wu 
1942d148a87eSJiawen Wu static const struct {
1943d148a87eSJiawen Wu 	eth_tx_burst_t pkt_burst;
1944d148a87eSJiawen Wu 	const char *info;
1945d148a87eSJiawen Wu } ngbe_tx_burst_infos[] = {
1946d148a87eSJiawen Wu 	{ ngbe_xmit_pkts_simple,   "Scalar Simple"},
1947d148a87eSJiawen Wu 	{ ngbe_xmit_pkts,          "Scalar"},
1948e94c20c3SJiawen Wu #ifdef RTE_ARCH_X86
1949e94c20c3SJiawen Wu 	{ ngbe_xmit_pkts_vec,      "Vector SSE" },
1950e94c20c3SJiawen Wu #elif defined(RTE_ARCH_ARM)
1951e94c20c3SJiawen Wu 	{ ngbe_xmit_pkts_vec,      "Vector Neon" },
1952e94c20c3SJiawen Wu #endif
1953d148a87eSJiawen Wu };
1954d148a87eSJiawen Wu 
1955d148a87eSJiawen Wu int
1956d148a87eSJiawen Wu ngbe_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,
1957d148a87eSJiawen Wu 		      struct rte_eth_burst_mode *mode)
1958d148a87eSJiawen Wu {
1959d148a87eSJiawen Wu 	eth_tx_burst_t pkt_burst = dev->tx_pkt_burst;
1960d148a87eSJiawen Wu 	int ret = -EINVAL;
1961d148a87eSJiawen Wu 	unsigned int i;
1962d148a87eSJiawen Wu 
1963d148a87eSJiawen Wu 	for (i = 0; i < RTE_DIM(ngbe_tx_burst_infos); ++i) {
1964d148a87eSJiawen Wu 		if (pkt_burst == ngbe_tx_burst_infos[i].pkt_burst) {
1965d148a87eSJiawen Wu 			snprintf(mode->info, sizeof(mode->info), "%s",
1966d148a87eSJiawen Wu 				 ngbe_tx_burst_infos[i].info);
1967d148a87eSJiawen Wu 			ret = 0;
1968d148a87eSJiawen Wu 			break;
1969d148a87eSJiawen Wu 		}
1970d148a87eSJiawen Wu 	}
1971d148a87eSJiawen Wu 
1972d148a87eSJiawen Wu 	return ret;
1973d148a87eSJiawen Wu }
1974d148a87eSJiawen Wu 
19759f320614SJiawen Wu uint64_t
19769f320614SJiawen Wu ngbe_get_tx_port_offloads(struct rte_eth_dev *dev)
19779f320614SJiawen Wu {
19789f320614SJiawen Wu 	uint64_t tx_offload_capa;
197959b46438SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
19809f320614SJiawen Wu 
19819f320614SJiawen Wu 	tx_offload_capa =
198259b46438SJiawen Wu 		RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
19839f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_IPV4_CKSUM  |
19849f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_UDP_CKSUM   |
19859f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_TCP_CKSUM   |
19869f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_SCTP_CKSUM  |
19879f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_TCP_TSO     |
19889f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_UDP_TSO	   |
19899f320614SJiawen Wu 		RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
19909f320614SJiawen Wu 
199159b46438SJiawen Wu 	if (hw->is_pf)
199259b46438SJiawen Wu 		tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
199359b46438SJiawen Wu 
19949f320614SJiawen Wu 	return tx_offload_capa;
19959f320614SJiawen Wu }
19969f320614SJiawen Wu 
1997a58e7c31SJiawen Wu int
1998a58e7c31SJiawen Wu ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
1999a58e7c31SJiawen Wu 			 uint16_t queue_idx,
2000a58e7c31SJiawen Wu 			 uint16_t nb_desc,
2001a58e7c31SJiawen Wu 			 unsigned int socket_id,
2002a58e7c31SJiawen Wu 			 const struct rte_eth_txconf *tx_conf)
2003a58e7c31SJiawen Wu {
2004a58e7c31SJiawen Wu 	const struct rte_memzone *tz;
2005a58e7c31SJiawen Wu 	struct ngbe_tx_queue *txq;
2006a58e7c31SJiawen Wu 	struct ngbe_hw     *hw;
2007a58e7c31SJiawen Wu 	uint16_t tx_free_thresh;
20089f320614SJiawen Wu 	uint64_t offloads;
2009a58e7c31SJiawen Wu 
2010a58e7c31SJiawen Wu 	PMD_INIT_FUNC_TRACE();
2011a58e7c31SJiawen Wu 	hw = ngbe_dev_hw(dev);
2012a58e7c31SJiawen Wu 
20139f320614SJiawen Wu 	offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
20149f320614SJiawen Wu 
2015a58e7c31SJiawen Wu 	/*
2016a58e7c31SJiawen Wu 	 * The Tx descriptor ring will be cleaned after txq->tx_free_thresh
2017a58e7c31SJiawen Wu 	 * descriptors are used or if the number of descriptors required
2018a58e7c31SJiawen Wu 	 * to transmit a packet is greater than the number of free Tx
2019a58e7c31SJiawen Wu 	 * descriptors.
2020a58e7c31SJiawen Wu 	 * One descriptor in the Tx ring is used as a sentinel to avoid a
2021a58e7c31SJiawen Wu 	 * H/W race condition, hence the maximum threshold constraints.
2022a58e7c31SJiawen Wu 	 * When set to zero use default values.
2023a58e7c31SJiawen Wu 	 */
2024a58e7c31SJiawen Wu 	tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ?
2025a58e7c31SJiawen Wu 			tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH);
2026a58e7c31SJiawen Wu 	if (tx_free_thresh >= (nb_desc - 3)) {
2027a58e7c31SJiawen Wu 		PMD_INIT_LOG(ERR,
2028a58e7c31SJiawen Wu 			     "tx_free_thresh must be less than the number of TX descriptors minus 3. (tx_free_thresh=%u port=%d queue=%d)",
2029a58e7c31SJiawen Wu 			     (unsigned int)tx_free_thresh,
2030a58e7c31SJiawen Wu 			     (int)dev->data->port_id, (int)queue_idx);
2031a58e7c31SJiawen Wu 		return -(EINVAL);
2032a58e7c31SJiawen Wu 	}
2033a58e7c31SJiawen Wu 
2034a58e7c31SJiawen Wu 	if (nb_desc % tx_free_thresh != 0) {
2035a58e7c31SJiawen Wu 		PMD_INIT_LOG(ERR,
2036a58e7c31SJiawen Wu 			     "tx_free_thresh must be a divisor of the number of Tx descriptors. (tx_free_thresh=%u port=%d queue=%d)",
2037a58e7c31SJiawen Wu 			     (unsigned int)tx_free_thresh,
2038a58e7c31SJiawen Wu 			     (int)dev->data->port_id, (int)queue_idx);
2039a58e7c31SJiawen Wu 		return -(EINVAL);
2040a58e7c31SJiawen Wu 	}
2041a58e7c31SJiawen Wu 
2042a58e7c31SJiawen Wu 	/* Free memory prior to re-allocation if needed... */
2043a58e7c31SJiawen Wu 	if (dev->data->tx_queues[queue_idx] != NULL) {
2044a58e7c31SJiawen Wu 		ngbe_tx_queue_release(dev->data->tx_queues[queue_idx]);
2045a58e7c31SJiawen Wu 		dev->data->tx_queues[queue_idx] = NULL;
2046a58e7c31SJiawen Wu 	}
2047a58e7c31SJiawen Wu 
2048a58e7c31SJiawen Wu 	/* First allocate the Tx queue data structure */
2049a58e7c31SJiawen Wu 	txq = rte_zmalloc_socket("ethdev Tx queue",
2050a58e7c31SJiawen Wu 				 sizeof(struct ngbe_tx_queue),
2051a58e7c31SJiawen Wu 				 RTE_CACHE_LINE_SIZE, socket_id);
2052a58e7c31SJiawen Wu 	if (txq == NULL)
2053a58e7c31SJiawen Wu 		return -ENOMEM;
2054a58e7c31SJiawen Wu 
2055a58e7c31SJiawen Wu 	/*
2056a58e7c31SJiawen Wu 	 * Allocate Tx ring hardware descriptors. A memzone large enough to
2057a58e7c31SJiawen Wu 	 * handle the maximum ring size is allocated in order to allow for
2058a58e7c31SJiawen Wu 	 * resizing in later calls to the queue setup function.
2059a58e7c31SJiawen Wu 	 */
2060a58e7c31SJiawen Wu 	tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx,
2061a58e7c31SJiawen Wu 			sizeof(struct ngbe_tx_desc) * NGBE_RING_DESC_MAX,
2062a58e7c31SJiawen Wu 			NGBE_ALIGN, socket_id);
2063a58e7c31SJiawen Wu 	if (tz == NULL) {
2064a58e7c31SJiawen Wu 		ngbe_tx_queue_release(txq);
2065a58e7c31SJiawen Wu 		return -ENOMEM;
2066a58e7c31SJiawen Wu 	}
2067a58e7c31SJiawen Wu 
2068fea7422fSJiawen Wu 	txq->mz = tz;
2069a58e7c31SJiawen Wu 	txq->nb_tx_desc = nb_desc;
2070a58e7c31SJiawen Wu 	txq->tx_free_thresh = tx_free_thresh;
2071a58e7c31SJiawen Wu 	txq->pthresh = tx_conf->tx_thresh.pthresh;
2072a58e7c31SJiawen Wu 	txq->hthresh = tx_conf->tx_thresh.hthresh;
2073a58e7c31SJiawen Wu 	txq->wthresh = tx_conf->tx_thresh.wthresh;
2074a58e7c31SJiawen Wu 	txq->queue_id = queue_idx;
207560229dcfSJiawen Wu 	txq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ?
207660229dcfSJiawen Wu 		queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx);
2077a58e7c31SJiawen Wu 	txq->port_id = dev->data->port_id;
20789f320614SJiawen Wu 	txq->offloads = offloads;
2079a58e7c31SJiawen Wu 	txq->ops = &def_txq_ops;
2080a58e7c31SJiawen Wu 	txq->tx_deferred_start = tx_conf->tx_deferred_start;
2081a58e7c31SJiawen Wu 
2082a58e7c31SJiawen Wu 	txq->tdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXWP(txq->reg_idx));
2083a58e7c31SJiawen Wu 	txq->tdc_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXCFG(txq->reg_idx));
2084a58e7c31SJiawen Wu 
2085a58e7c31SJiawen Wu 	txq->tx_ring_phys_addr = TMZ_PADDR(tz);
2086a58e7c31SJiawen Wu 	txq->tx_ring = (struct ngbe_tx_desc *)TMZ_VADDR(tz);
2087a58e7c31SJiawen Wu 
2088a58e7c31SJiawen Wu 	/* Allocate software ring */
2089a58e7c31SJiawen Wu 	txq->sw_ring = rte_zmalloc_socket("txq->sw_ring",
2090a58e7c31SJiawen Wu 				sizeof(struct ngbe_tx_entry) * nb_desc,
2091a58e7c31SJiawen Wu 				RTE_CACHE_LINE_SIZE, socket_id);
2092a58e7c31SJiawen Wu 	if (txq->sw_ring == NULL) {
2093a58e7c31SJiawen Wu 		ngbe_tx_queue_release(txq);
2094a58e7c31SJiawen Wu 		return -ENOMEM;
2095a58e7c31SJiawen Wu 	}
2096a58e7c31SJiawen Wu 	PMD_INIT_LOG(DEBUG,
2097a58e7c31SJiawen Wu 		     "sw_ring=%p hw_ring=%p dma_addr=0x%" PRIx64,
2098a58e7c31SJiawen Wu 		     txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr);
2099a58e7c31SJiawen Wu 
21009f320614SJiawen Wu 	/* set up scalar Tx function as appropriate */
21019f320614SJiawen Wu 	ngbe_set_tx_function(dev, txq);
21029f320614SJiawen Wu 
2103a58e7c31SJiawen Wu 	txq->ops->reset(txq);
21043eba2f28SJiawen Wu 	txq->desc_error = 0;
2105a58e7c31SJiawen Wu 
2106a58e7c31SJiawen Wu 	dev->data->tx_queues[queue_idx] = txq;
2107a58e7c31SJiawen Wu 
2108a58e7c31SJiawen Wu 	return 0;
2109a58e7c31SJiawen Wu }
2110a58e7c31SJiawen Wu 
211143b7e5eaSJiawen Wu /**
211243b7e5eaSJiawen Wu  * ngbe_free_sc_cluster - free the not-yet-completed scattered cluster
211343b7e5eaSJiawen Wu  *
211443b7e5eaSJiawen Wu  * The "next" pointer of the last segment of (not-yet-completed) RSC clusters
211543b7e5eaSJiawen Wu  * in the sw_sc_ring is not set to NULL but rather points to the next
211643b7e5eaSJiawen Wu  * mbuf of this RSC aggregation (that has not been completed yet and still
211743b7e5eaSJiawen Wu  * resides on the HW ring). So, instead of calling for rte_pktmbuf_free() we
211843b7e5eaSJiawen Wu  * will just free first "nb_segs" segments of the cluster explicitly by calling
211943b7e5eaSJiawen Wu  * an rte_pktmbuf_free_seg().
212043b7e5eaSJiawen Wu  *
212143b7e5eaSJiawen Wu  * @m scattered cluster head
212243b7e5eaSJiawen Wu  */
212343b7e5eaSJiawen Wu static void
212443b7e5eaSJiawen Wu ngbe_free_sc_cluster(struct rte_mbuf *m)
212543b7e5eaSJiawen Wu {
212643b7e5eaSJiawen Wu 	uint16_t i, nb_segs = m->nb_segs;
212743b7e5eaSJiawen Wu 	struct rte_mbuf *next_seg;
212843b7e5eaSJiawen Wu 
212943b7e5eaSJiawen Wu 	for (i = 0; i < nb_segs; i++) {
213043b7e5eaSJiawen Wu 		next_seg = m->next;
213143b7e5eaSJiawen Wu 		rte_pktmbuf_free_seg(m);
213243b7e5eaSJiawen Wu 		m = next_seg;
213343b7e5eaSJiawen Wu 	}
213443b7e5eaSJiawen Wu }
213543b7e5eaSJiawen Wu 
213643b7e5eaSJiawen Wu static void
213743b7e5eaSJiawen Wu ngbe_rx_queue_release_mbufs(struct ngbe_rx_queue *rxq)
213843b7e5eaSJiawen Wu {
213943b7e5eaSJiawen Wu 	unsigned int i;
214043b7e5eaSJiawen Wu 
2141e94c20c3SJiawen Wu 	/* SSE Vector driver has a different way of releasing mbufs. */
2142e94c20c3SJiawen Wu 	if (rxq->rx_using_sse) {
2143e94c20c3SJiawen Wu 		ngbe_rx_queue_release_mbufs_vec(rxq);
2144e94c20c3SJiawen Wu 		return;
2145e94c20c3SJiawen Wu 	}
2146e94c20c3SJiawen Wu 
214743b7e5eaSJiawen Wu 	if (rxq->sw_ring != NULL) {
214843b7e5eaSJiawen Wu 		for (i = 0; i < rxq->nb_rx_desc; i++) {
214943b7e5eaSJiawen Wu 			if (rxq->sw_ring[i].mbuf != NULL) {
215043b7e5eaSJiawen Wu 				rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
215143b7e5eaSJiawen Wu 				rxq->sw_ring[i].mbuf = NULL;
215243b7e5eaSJiawen Wu 			}
215343b7e5eaSJiawen Wu 		}
215443b7e5eaSJiawen Wu 		for (i = 0; i < rxq->rx_nb_avail; ++i) {
215543b7e5eaSJiawen Wu 			struct rte_mbuf *mb;
215643b7e5eaSJiawen Wu 
215743b7e5eaSJiawen Wu 			mb = rxq->rx_stage[rxq->rx_next_avail + i];
215843b7e5eaSJiawen Wu 			rte_pktmbuf_free_seg(mb);
215943b7e5eaSJiawen Wu 		}
216043b7e5eaSJiawen Wu 		rxq->rx_nb_avail = 0;
216143b7e5eaSJiawen Wu 	}
216243b7e5eaSJiawen Wu 
216343b7e5eaSJiawen Wu 	if (rxq->sw_sc_ring != NULL)
216443b7e5eaSJiawen Wu 		for (i = 0; i < rxq->nb_rx_desc; i++)
216543b7e5eaSJiawen Wu 			if (rxq->sw_sc_ring[i].fbuf != NULL) {
216643b7e5eaSJiawen Wu 				ngbe_free_sc_cluster(rxq->sw_sc_ring[i].fbuf);
216743b7e5eaSJiawen Wu 				rxq->sw_sc_ring[i].fbuf = NULL;
216843b7e5eaSJiawen Wu 			}
216943b7e5eaSJiawen Wu }
217043b7e5eaSJiawen Wu 
217143b7e5eaSJiawen Wu static void
217243b7e5eaSJiawen Wu ngbe_rx_queue_release(struct ngbe_rx_queue *rxq)
217343b7e5eaSJiawen Wu {
217443b7e5eaSJiawen Wu 	if (rxq != NULL) {
217543b7e5eaSJiawen Wu 		ngbe_rx_queue_release_mbufs(rxq);
217643b7e5eaSJiawen Wu 		rte_free(rxq->sw_ring);
217743b7e5eaSJiawen Wu 		rte_free(rxq->sw_sc_ring);
2178fea7422fSJiawen Wu 		rte_memzone_free(rxq->mz);
217943b7e5eaSJiawen Wu 		rte_free(rxq);
218043b7e5eaSJiawen Wu 	}
218143b7e5eaSJiawen Wu }
218243b7e5eaSJiawen Wu 
218343b7e5eaSJiawen Wu void
21847483341aSXueming Li ngbe_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
218543b7e5eaSJiawen Wu {
21867483341aSXueming Li 	ngbe_rx_queue_release(dev->data->rx_queues[qid]);
218743b7e5eaSJiawen Wu }
218843b7e5eaSJiawen Wu 
218943b7e5eaSJiawen Wu /*
219043b7e5eaSJiawen Wu  * Check if Rx Burst Bulk Alloc function can be used.
219143b7e5eaSJiawen Wu  * Return
219243b7e5eaSJiawen Wu  *        0: the preconditions are satisfied and the bulk allocation function
219343b7e5eaSJiawen Wu  *           can be used.
219443b7e5eaSJiawen Wu  *  -EINVAL: the preconditions are NOT satisfied and the default Rx burst
219543b7e5eaSJiawen Wu  *           function must be used.
219643b7e5eaSJiawen Wu  */
219743b7e5eaSJiawen Wu static inline int
219843b7e5eaSJiawen Wu check_rx_burst_bulk_alloc_preconditions(struct ngbe_rx_queue *rxq)
219943b7e5eaSJiawen Wu {
220043b7e5eaSJiawen Wu 	int ret = 0;
220143b7e5eaSJiawen Wu 
220243b7e5eaSJiawen Wu 	/*
220343b7e5eaSJiawen Wu 	 * Make sure the following pre-conditions are satisfied:
220443b7e5eaSJiawen Wu 	 *   rxq->rx_free_thresh >= RTE_PMD_NGBE_RX_MAX_BURST
220543b7e5eaSJiawen Wu 	 *   rxq->rx_free_thresh < rxq->nb_rx_desc
220643b7e5eaSJiawen Wu 	 *   (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0
220743b7e5eaSJiawen Wu 	 * Scattered packets are not supported.  This should be checked
220843b7e5eaSJiawen Wu 	 * outside of this function.
220943b7e5eaSJiawen Wu 	 */
221043b7e5eaSJiawen Wu 	if (rxq->rx_free_thresh < RTE_PMD_NGBE_RX_MAX_BURST) {
221143b7e5eaSJiawen Wu 		PMD_INIT_LOG(DEBUG,
221243b7e5eaSJiawen Wu 			     "Rx Burst Bulk Alloc Preconditions: rxq->rx_free_thresh=%d, RTE_PMD_NGBE_RX_MAX_BURST=%d",
221343b7e5eaSJiawen Wu 			     rxq->rx_free_thresh, RTE_PMD_NGBE_RX_MAX_BURST);
221443b7e5eaSJiawen Wu 		ret = -EINVAL;
221543b7e5eaSJiawen Wu 	} else if (rxq->rx_free_thresh >= rxq->nb_rx_desc) {
221643b7e5eaSJiawen Wu 		PMD_INIT_LOG(DEBUG,
221743b7e5eaSJiawen Wu 			     "Rx Burst Bulk Alloc Preconditions: rxq->rx_free_thresh=%d, rxq->nb_rx_desc=%d",
221843b7e5eaSJiawen Wu 			     rxq->rx_free_thresh, rxq->nb_rx_desc);
221943b7e5eaSJiawen Wu 		ret = -EINVAL;
222043b7e5eaSJiawen Wu 	} else if ((rxq->nb_rx_desc % rxq->rx_free_thresh) != 0) {
222143b7e5eaSJiawen Wu 		PMD_INIT_LOG(DEBUG,
222243b7e5eaSJiawen Wu 			     "Rx Burst Bulk Alloc Preconditions: rxq->nb_rx_desc=%d, rxq->rx_free_thresh=%d",
222343b7e5eaSJiawen Wu 			     rxq->nb_rx_desc, rxq->rx_free_thresh);
222443b7e5eaSJiawen Wu 		ret = -EINVAL;
222543b7e5eaSJiawen Wu 	}
222643b7e5eaSJiawen Wu 
222743b7e5eaSJiawen Wu 	return ret;
222843b7e5eaSJiawen Wu }
222943b7e5eaSJiawen Wu 
223043b7e5eaSJiawen Wu /* Reset dynamic ngbe_rx_queue fields back to defaults */
223143b7e5eaSJiawen Wu static void
223243b7e5eaSJiawen Wu ngbe_reset_rx_queue(struct ngbe_adapter *adapter, struct ngbe_rx_queue *rxq)
223343b7e5eaSJiawen Wu {
223443b7e5eaSJiawen Wu 	static const struct ngbe_rx_desc zeroed_desc = {
223543b7e5eaSJiawen Wu 						{{0}, {0} }, {{0}, {0} } };
223643b7e5eaSJiawen Wu 	unsigned int i;
223743b7e5eaSJiawen Wu 	uint16_t len = rxq->nb_rx_desc;
223843b7e5eaSJiawen Wu 
223943b7e5eaSJiawen Wu 	/*
224043b7e5eaSJiawen Wu 	 * By default, the Rx queue setup function allocates enough memory for
224143b7e5eaSJiawen Wu 	 * NGBE_RING_DESC_MAX.  The Rx Burst bulk allocation function requires
224243b7e5eaSJiawen Wu 	 * extra memory at the end of the descriptor ring to be zero'd out.
224343b7e5eaSJiawen Wu 	 */
224443b7e5eaSJiawen Wu 	if (adapter->rx_bulk_alloc_allowed)
224543b7e5eaSJiawen Wu 		/* zero out extra memory */
224643b7e5eaSJiawen Wu 		len += RTE_PMD_NGBE_RX_MAX_BURST;
224743b7e5eaSJiawen Wu 
224843b7e5eaSJiawen Wu 	/*
224943b7e5eaSJiawen Wu 	 * Zero out HW ring memory. Zero out extra memory at the end of
225043b7e5eaSJiawen Wu 	 * the H/W ring so look-ahead logic in Rx Burst bulk alloc function
225143b7e5eaSJiawen Wu 	 * reads extra memory as zeros.
225243b7e5eaSJiawen Wu 	 */
225343b7e5eaSJiawen Wu 	for (i = 0; i < len; i++)
225443b7e5eaSJiawen Wu 		rxq->rx_ring[i] = zeroed_desc;
225543b7e5eaSJiawen Wu 
225643b7e5eaSJiawen Wu 	/*
225743b7e5eaSJiawen Wu 	 * initialize extra software ring entries. Space for these extra
225843b7e5eaSJiawen Wu 	 * entries is always allocated
225943b7e5eaSJiawen Wu 	 */
226043b7e5eaSJiawen Wu 	memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf));
226143b7e5eaSJiawen Wu 	for (i = rxq->nb_rx_desc; i < len; ++i)
226243b7e5eaSJiawen Wu 		rxq->sw_ring[i].mbuf = &rxq->fake_mbuf;
226343b7e5eaSJiawen Wu 
226443b7e5eaSJiawen Wu 	rxq->rx_nb_avail = 0;
226543b7e5eaSJiawen Wu 	rxq->rx_next_avail = 0;
226643b7e5eaSJiawen Wu 	rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1);
226743b7e5eaSJiawen Wu 	rxq->rx_tail = 0;
226843b7e5eaSJiawen Wu 	rxq->nb_rx_hold = 0;
2269fea7422fSJiawen Wu 	rte_pktmbuf_free(rxq->pkt_first_seg);
227043b7e5eaSJiawen Wu 	rxq->pkt_first_seg = NULL;
227143b7e5eaSJiawen Wu 	rxq->pkt_last_seg = NULL;
2272e94c20c3SJiawen Wu 
2273e94c20c3SJiawen Wu #if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM)
2274e94c20c3SJiawen Wu 	rxq->rxrearm_start = 0;
2275e94c20c3SJiawen Wu 	rxq->rxrearm_nb = 0;
2276e94c20c3SJiawen Wu #endif
227743b7e5eaSJiawen Wu }
227843b7e5eaSJiawen Wu 
227979f3128dSJiawen Wu uint64_t
228059b46438SJiawen Wu ngbe_get_rx_queue_offloads(struct rte_eth_dev *dev __rte_unused)
228159b46438SJiawen Wu {
228259b46438SJiawen Wu 	return RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
228359b46438SJiawen Wu }
228459b46438SJiawen Wu 
228559b46438SJiawen Wu uint64_t
228659b46438SJiawen Wu ngbe_get_rx_port_offloads(struct rte_eth_dev *dev)
228779f3128dSJiawen Wu {
2288ffc959f5SJiawen Wu 	uint64_t offloads;
228959b46438SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
2290ffc959f5SJiawen Wu 
2291ffc959f5SJiawen Wu 	offloads = RTE_ETH_RX_OFFLOAD_IPV4_CKSUM  |
2292ffc959f5SJiawen Wu 		   RTE_ETH_RX_OFFLOAD_UDP_CKSUM   |
2293ffc959f5SJiawen Wu 		   RTE_ETH_RX_OFFLOAD_TCP_CKSUM   |
229464b36e4aSJiawen Wu 		   RTE_ETH_RX_OFFLOAD_KEEP_CRC    |
229559b46438SJiawen Wu 		   RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
22964fbb5f20SJiawen Wu 		   RTE_ETH_RX_OFFLOAD_RSS_HASH    |
2297ffc959f5SJiawen Wu 		   RTE_ETH_RX_OFFLOAD_SCATTER;
2298ffc959f5SJiawen Wu 
229959b46438SJiawen Wu 	if (hw->is_pf)
230059b46438SJiawen Wu 		offloads |= (RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
230159b46438SJiawen Wu 			     RTE_ETH_RX_OFFLOAD_VLAN_EXTEND);
230259b46438SJiawen Wu 
2303ffc959f5SJiawen Wu 	return offloads;
230479f3128dSJiawen Wu }
230579f3128dSJiawen Wu 
230643b7e5eaSJiawen Wu int
230743b7e5eaSJiawen Wu ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
230843b7e5eaSJiawen Wu 			 uint16_t queue_idx,
230943b7e5eaSJiawen Wu 			 uint16_t nb_desc,
231043b7e5eaSJiawen Wu 			 unsigned int socket_id,
231143b7e5eaSJiawen Wu 			 const struct rte_eth_rxconf *rx_conf,
231243b7e5eaSJiawen Wu 			 struct rte_mempool *mp)
231343b7e5eaSJiawen Wu {
231443b7e5eaSJiawen Wu 	const struct rte_memzone *rz;
231543b7e5eaSJiawen Wu 	struct ngbe_rx_queue *rxq;
231643b7e5eaSJiawen Wu 	struct ngbe_hw     *hw;
231743b7e5eaSJiawen Wu 	uint16_t len;
231843b7e5eaSJiawen Wu 	struct ngbe_adapter *adapter = ngbe_dev_adapter(dev);
231959b46438SJiawen Wu 	uint64_t offloads;
232043b7e5eaSJiawen Wu 
232143b7e5eaSJiawen Wu 	PMD_INIT_FUNC_TRACE();
232243b7e5eaSJiawen Wu 	hw = ngbe_dev_hw(dev);
232343b7e5eaSJiawen Wu 
232459b46438SJiawen Wu 	offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
232559b46438SJiawen Wu 
232643b7e5eaSJiawen Wu 	/* Free memory prior to re-allocation if needed... */
232743b7e5eaSJiawen Wu 	if (dev->data->rx_queues[queue_idx] != NULL) {
232843b7e5eaSJiawen Wu 		ngbe_rx_queue_release(dev->data->rx_queues[queue_idx]);
232943b7e5eaSJiawen Wu 		dev->data->rx_queues[queue_idx] = NULL;
233043b7e5eaSJiawen Wu 	}
233143b7e5eaSJiawen Wu 
233243b7e5eaSJiawen Wu 	/* First allocate the Rx queue data structure */
233343b7e5eaSJiawen Wu 	rxq = rte_zmalloc_socket("ethdev RX queue",
233443b7e5eaSJiawen Wu 				 sizeof(struct ngbe_rx_queue),
233543b7e5eaSJiawen Wu 				 RTE_CACHE_LINE_SIZE, socket_id);
233643b7e5eaSJiawen Wu 	if (rxq == NULL)
233743b7e5eaSJiawen Wu 		return -ENOMEM;
233843b7e5eaSJiawen Wu 	rxq->mb_pool = mp;
233943b7e5eaSJiawen Wu 	rxq->nb_rx_desc = nb_desc;
234043b7e5eaSJiawen Wu 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
234143b7e5eaSJiawen Wu 	rxq->queue_id = queue_idx;
234260229dcfSJiawen Wu 	rxq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ?
234360229dcfSJiawen Wu 		queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx);
234443b7e5eaSJiawen Wu 	rxq->port_id = dev->data->port_id;
234564b36e4aSJiawen Wu 	if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
234664b36e4aSJiawen Wu 		rxq->crc_len = RTE_ETHER_CRC_LEN;
234764b36e4aSJiawen Wu 	else
234864b36e4aSJiawen Wu 		rxq->crc_len = 0;
234943b7e5eaSJiawen Wu 	rxq->drop_en = rx_conf->rx_drop_en;
235043b7e5eaSJiawen Wu 	rxq->rx_deferred_start = rx_conf->rx_deferred_start;
235159b46438SJiawen Wu 	rxq->offloads = offloads;
235243b7e5eaSJiawen Wu 
235343b7e5eaSJiawen Wu 	/*
235443b7e5eaSJiawen Wu 	 * Allocate Rx ring hardware descriptors. A memzone large enough to
235543b7e5eaSJiawen Wu 	 * handle the maximum ring size is allocated in order to allow for
235643b7e5eaSJiawen Wu 	 * resizing in later calls to the queue setup function.
235743b7e5eaSJiawen Wu 	 */
235843b7e5eaSJiawen Wu 	rz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx,
235943b7e5eaSJiawen Wu 				      RX_RING_SZ, NGBE_ALIGN, socket_id);
236043b7e5eaSJiawen Wu 	if (rz == NULL) {
236143b7e5eaSJiawen Wu 		ngbe_rx_queue_release(rxq);
236243b7e5eaSJiawen Wu 		return -ENOMEM;
236343b7e5eaSJiawen Wu 	}
236443b7e5eaSJiawen Wu 
2365fea7422fSJiawen Wu 	rxq->mz = rz;
236643b7e5eaSJiawen Wu 	/*
236743b7e5eaSJiawen Wu 	 * Zero init all the descriptors in the ring.
236843b7e5eaSJiawen Wu 	 */
236943b7e5eaSJiawen Wu 	memset(rz->addr, 0, RX_RING_SZ);
237043b7e5eaSJiawen Wu 
237143b7e5eaSJiawen Wu 	rxq->rdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXWP(rxq->reg_idx));
237243b7e5eaSJiawen Wu 	rxq->rdh_reg_addr = NGBE_REG_ADDR(hw, NGBE_RXRP(rxq->reg_idx));
237343b7e5eaSJiawen Wu 
237443b7e5eaSJiawen Wu 	rxq->rx_ring_phys_addr = TMZ_PADDR(rz);
237543b7e5eaSJiawen Wu 	rxq->rx_ring = (struct ngbe_rx_desc *)TMZ_VADDR(rz);
237643b7e5eaSJiawen Wu 
237743b7e5eaSJiawen Wu 	/*
237843b7e5eaSJiawen Wu 	 * Certain constraints must be met in order to use the bulk buffer
237943b7e5eaSJiawen Wu 	 * allocation Rx burst function. If any of Rx queues doesn't meet them
238043b7e5eaSJiawen Wu 	 * the feature should be disabled for the whole port.
238143b7e5eaSJiawen Wu 	 */
238243b7e5eaSJiawen Wu 	if (check_rx_burst_bulk_alloc_preconditions(rxq)) {
238343b7e5eaSJiawen Wu 		PMD_INIT_LOG(DEBUG,
238443b7e5eaSJiawen Wu 			     "queue[%d] doesn't meet Rx Bulk Alloc preconditions - canceling the feature for the whole port[%d]",
238543b7e5eaSJiawen Wu 			     rxq->queue_id, rxq->port_id);
238643b7e5eaSJiawen Wu 		adapter->rx_bulk_alloc_allowed = false;
238743b7e5eaSJiawen Wu 	}
238843b7e5eaSJiawen Wu 
238943b7e5eaSJiawen Wu 	/*
239043b7e5eaSJiawen Wu 	 * Allocate software ring. Allow for space at the end of the
239143b7e5eaSJiawen Wu 	 * S/W ring to make sure look-ahead logic in bulk alloc Rx burst
239243b7e5eaSJiawen Wu 	 * function does not access an invalid memory region.
239343b7e5eaSJiawen Wu 	 */
239443b7e5eaSJiawen Wu 	len = nb_desc;
239543b7e5eaSJiawen Wu 	if (adapter->rx_bulk_alloc_allowed)
239643b7e5eaSJiawen Wu 		len += RTE_PMD_NGBE_RX_MAX_BURST;
239743b7e5eaSJiawen Wu 
239843b7e5eaSJiawen Wu 	rxq->sw_ring = rte_zmalloc_socket("rxq->sw_ring",
239943b7e5eaSJiawen Wu 					  sizeof(struct ngbe_rx_entry) * len,
240043b7e5eaSJiawen Wu 					  RTE_CACHE_LINE_SIZE, socket_id);
240143b7e5eaSJiawen Wu 	if (rxq->sw_ring == NULL) {
240243b7e5eaSJiawen Wu 		ngbe_rx_queue_release(rxq);
240343b7e5eaSJiawen Wu 		return -ENOMEM;
240443b7e5eaSJiawen Wu 	}
240543b7e5eaSJiawen Wu 
240643b7e5eaSJiawen Wu 	/*
240743b7e5eaSJiawen Wu 	 * Always allocate even if it's not going to be needed in order to
240843b7e5eaSJiawen Wu 	 * simplify the code.
240943b7e5eaSJiawen Wu 	 *
241043b7e5eaSJiawen Wu 	 * This ring is used in Scattered Rx cases and Scattered Rx may
241143b7e5eaSJiawen Wu 	 * be requested in ngbe_dev_rx_init(), which is called later from
241243b7e5eaSJiawen Wu 	 * dev_start() flow.
241343b7e5eaSJiawen Wu 	 */
241443b7e5eaSJiawen Wu 	rxq->sw_sc_ring =
241543b7e5eaSJiawen Wu 		rte_zmalloc_socket("rxq->sw_sc_ring",
241643b7e5eaSJiawen Wu 				  sizeof(struct ngbe_scattered_rx_entry) * len,
241743b7e5eaSJiawen Wu 				  RTE_CACHE_LINE_SIZE, socket_id);
241843b7e5eaSJiawen Wu 	if (rxq->sw_sc_ring == NULL) {
241943b7e5eaSJiawen Wu 		ngbe_rx_queue_release(rxq);
242043b7e5eaSJiawen Wu 		return -ENOMEM;
242143b7e5eaSJiawen Wu 	}
242243b7e5eaSJiawen Wu 
242343b7e5eaSJiawen Wu 	PMD_INIT_LOG(DEBUG,
242443b7e5eaSJiawen Wu 		     "sw_ring=%p sw_sc_ring=%p hw_ring=%p dma_addr=0x%" PRIx64,
242543b7e5eaSJiawen Wu 		     rxq->sw_ring, rxq->sw_sc_ring, rxq->rx_ring,
242643b7e5eaSJiawen Wu 		     rxq->rx_ring_phys_addr);
242743b7e5eaSJiawen Wu 
2428e94c20c3SJiawen Wu 	if (!rte_is_power_of_2(nb_desc)) {
2429e94c20c3SJiawen Wu 		PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Vector Rx "
2430e94c20c3SJiawen Wu 				    "preconditions - canceling the feature for "
2431e94c20c3SJiawen Wu 				    "the whole port[%d]",
2432e94c20c3SJiawen Wu 			     rxq->queue_id, rxq->port_id);
2433e94c20c3SJiawen Wu 		adapter->rx_vec_allowed = false;
2434e94c20c3SJiawen Wu 	} else {
2435e94c20c3SJiawen Wu 		ngbe_rxq_vec_setup(rxq);
2436e94c20c3SJiawen Wu 	}
2437e94c20c3SJiawen Wu 
243843b7e5eaSJiawen Wu 	dev->data->rx_queues[queue_idx] = rxq;
243943b7e5eaSJiawen Wu 
244043b7e5eaSJiawen Wu 	ngbe_reset_rx_queue(adapter, rxq);
244143b7e5eaSJiawen Wu 
244243b7e5eaSJiawen Wu 	return 0;
244343b7e5eaSJiawen Wu }
244443b7e5eaSJiawen Wu 
2445b7aad633SJiawen Wu uint32_t
2446b7aad633SJiawen Wu ngbe_dev_rx_queue_count(void *rx_queue)
2447b7aad633SJiawen Wu {
2448b7aad633SJiawen Wu #define NGBE_RXQ_SCAN_INTERVAL 4
2449b7aad633SJiawen Wu 	volatile struct ngbe_rx_desc *rxdp;
2450b7aad633SJiawen Wu 	struct ngbe_rx_queue *rxq = rx_queue;
2451b7aad633SJiawen Wu 	uint32_t desc = 0;
2452b7aad633SJiawen Wu 
2453b7aad633SJiawen Wu 	rxdp = &rxq->rx_ring[rxq->rx_tail];
2454b7aad633SJiawen Wu 
2455b7aad633SJiawen Wu 	while ((desc < rxq->nb_rx_desc) &&
2456b7aad633SJiawen Wu 		(rxdp->qw1.lo.status &
2457b7aad633SJiawen Wu 			rte_cpu_to_le_32(NGBE_RXD_STAT_DD))) {
2458b7aad633SJiawen Wu 		desc += NGBE_RXQ_SCAN_INTERVAL;
2459b7aad633SJiawen Wu 		rxdp += NGBE_RXQ_SCAN_INTERVAL;
2460b7aad633SJiawen Wu 		if (rxq->rx_tail + desc >= rxq->nb_rx_desc)
2461b7aad633SJiawen Wu 			rxdp = &(rxq->rx_ring[rxq->rx_tail +
2462b7aad633SJiawen Wu 				desc - rxq->nb_rx_desc]);
2463b7aad633SJiawen Wu 	}
2464b7aad633SJiawen Wu 
2465b7aad633SJiawen Wu 	return desc;
2466b7aad633SJiawen Wu }
2467b7aad633SJiawen Wu 
2468b7aad633SJiawen Wu int
2469b7aad633SJiawen Wu ngbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
2470b7aad633SJiawen Wu {
2471b7aad633SJiawen Wu 	struct ngbe_rx_queue *rxq = rx_queue;
2472b7aad633SJiawen Wu 	volatile uint32_t *status;
2473b7aad633SJiawen Wu 	uint32_t nb_hold, desc;
2474b7aad633SJiawen Wu 
2475b7aad633SJiawen Wu 	if (unlikely(offset >= rxq->nb_rx_desc))
2476b7aad633SJiawen Wu 		return -EINVAL;
2477b7aad633SJiawen Wu 
2478e94c20c3SJiawen Wu #if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM)
2479e94c20c3SJiawen Wu 	if (rxq->rx_using_sse)
2480e94c20c3SJiawen Wu 		nb_hold = rxq->rxrearm_nb;
2481e94c20c3SJiawen Wu 	else
2482e94c20c3SJiawen Wu #endif
2483b7aad633SJiawen Wu 		nb_hold = rxq->nb_rx_hold;
2484b7aad633SJiawen Wu 	if (offset >= rxq->nb_rx_desc - nb_hold)
2485b7aad633SJiawen Wu 		return RTE_ETH_RX_DESC_UNAVAIL;
2486b7aad633SJiawen Wu 
2487b7aad633SJiawen Wu 	desc = rxq->rx_tail + offset;
2488b7aad633SJiawen Wu 	if (desc >= rxq->nb_rx_desc)
2489b7aad633SJiawen Wu 		desc -= rxq->nb_rx_desc;
2490b7aad633SJiawen Wu 
2491b7aad633SJiawen Wu 	status = &rxq->rx_ring[desc].qw1.lo.status;
2492b7aad633SJiawen Wu 	if (*status & rte_cpu_to_le_32(NGBE_RXD_STAT_DD))
2493b7aad633SJiawen Wu 		return RTE_ETH_RX_DESC_DONE;
2494b7aad633SJiawen Wu 
2495b7aad633SJiawen Wu 	return RTE_ETH_RX_DESC_AVAIL;
2496b7aad633SJiawen Wu }
2497b7aad633SJiawen Wu 
2498b7aad633SJiawen Wu int
2499b7aad633SJiawen Wu ngbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
2500b7aad633SJiawen Wu {
2501b7aad633SJiawen Wu 	struct ngbe_tx_queue *txq = tx_queue;
2502b7aad633SJiawen Wu 	volatile uint32_t *status;
2503b7aad633SJiawen Wu 	uint32_t desc;
2504b7aad633SJiawen Wu 
2505b7aad633SJiawen Wu 	if (unlikely(offset >= txq->nb_tx_desc))
2506b7aad633SJiawen Wu 		return -EINVAL;
2507b7aad633SJiawen Wu 
2508b7aad633SJiawen Wu 	desc = txq->tx_tail + offset;
2509b7aad633SJiawen Wu 	if (desc >= txq->nb_tx_desc) {
2510b7aad633SJiawen Wu 		desc -= txq->nb_tx_desc;
2511b7aad633SJiawen Wu 		if (desc >= txq->nb_tx_desc)
2512b7aad633SJiawen Wu 			desc -= txq->nb_tx_desc;
2513b7aad633SJiawen Wu 	}
2514b7aad633SJiawen Wu 
2515b7aad633SJiawen Wu 	status = &txq->tx_ring[desc].dw3;
2516b7aad633SJiawen Wu 	if (*status & rte_cpu_to_le_32(NGBE_TXD_DD))
2517b7aad633SJiawen Wu 		return RTE_ETH_TX_DESC_DONE;
2518b7aad633SJiawen Wu 
2519b7aad633SJiawen Wu 	return RTE_ETH_TX_DESC_FULL;
2520b7aad633SJiawen Wu }
2521b7aad633SJiawen Wu 
25223518df57SJiawen Wu void
25233518df57SJiawen Wu ngbe_dev_clear_queues(struct rte_eth_dev *dev)
25243518df57SJiawen Wu {
25253518df57SJiawen Wu 	unsigned int i;
25263518df57SJiawen Wu 	struct ngbe_adapter *adapter = ngbe_dev_adapter(dev);
25273518df57SJiawen Wu 
25283518df57SJiawen Wu 	PMD_INIT_FUNC_TRACE();
25293518df57SJiawen Wu 
25303518df57SJiawen Wu 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
25313518df57SJiawen Wu 		struct ngbe_tx_queue *txq = dev->data->tx_queues[i];
25323518df57SJiawen Wu 
25333518df57SJiawen Wu 		if (txq != NULL) {
25343518df57SJiawen Wu 			txq->ops->release_mbufs(txq);
25353518df57SJiawen Wu 			txq->ops->reset(txq);
25369179018eSJie Hai 			dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
25373518df57SJiawen Wu 		}
25383518df57SJiawen Wu 	}
25393518df57SJiawen Wu 
25403518df57SJiawen Wu 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
25413518df57SJiawen Wu 		struct ngbe_rx_queue *rxq = dev->data->rx_queues[i];
25423518df57SJiawen Wu 
25433518df57SJiawen Wu 		if (rxq != NULL) {
25443518df57SJiawen Wu 			ngbe_rx_queue_release_mbufs(rxq);
25453518df57SJiawen Wu 			ngbe_reset_rx_queue(adapter, rxq);
25469179018eSJie Hai 			dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
25473518df57SJiawen Wu 		}
25483518df57SJiawen Wu 	}
25493518df57SJiawen Wu }
25503518df57SJiawen Wu 
2551cc63194eSJiawen Wu void
2552cc63194eSJiawen Wu ngbe_dev_free_queues(struct rte_eth_dev *dev)
2553cc63194eSJiawen Wu {
2554cc63194eSJiawen Wu 	unsigned int i;
2555cc63194eSJiawen Wu 
2556cc63194eSJiawen Wu 	PMD_INIT_FUNC_TRACE();
2557cc63194eSJiawen Wu 
2558cc63194eSJiawen Wu 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
25597483341aSXueming Li 		ngbe_dev_rx_queue_release(dev, i);
2560cc63194eSJiawen Wu 		dev->data->rx_queues[i] = NULL;
2561cc63194eSJiawen Wu 	}
2562cc63194eSJiawen Wu 	dev->data->nb_rx_queues = 0;
2563cc63194eSJiawen Wu 
2564cc63194eSJiawen Wu 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
25657483341aSXueming Li 		ngbe_dev_tx_queue_release(dev, i);
2566cc63194eSJiawen Wu 		dev->data->tx_queues[i] = NULL;
2567cc63194eSJiawen Wu 	}
2568cc63194eSJiawen Wu 	dev->data->nb_tx_queues = 0;
2569cc63194eSJiawen Wu }
2570cc63194eSJiawen Wu 
25710779d7f6SJiawen Wu /**
25720779d7f6SJiawen Wu  * Receive Side Scaling (RSS)
25730779d7f6SJiawen Wu  *
25740779d7f6SJiawen Wu  * Principles:
25750779d7f6SJiawen Wu  * The source and destination IP addresses of the IP header and the source
25760779d7f6SJiawen Wu  * and destination ports of TCP/UDP headers, if any, of received packets are
25770779d7f6SJiawen Wu  * hashed against a configurable random key to compute a 32-bit RSS hash result.
25780779d7f6SJiawen Wu  * The seven (7) LSBs of the 32-bit hash result are used as an index into a
25790779d7f6SJiawen Wu  * 128-entry redirection table (RETA).  Each entry of the RETA provides a 3-bit
25800779d7f6SJiawen Wu  * RSS output index which is used as the Rx queue index where to store the
25810779d7f6SJiawen Wu  * received packets.
25820779d7f6SJiawen Wu  * The following output is supplied in the Rx write-back descriptor:
25830779d7f6SJiawen Wu  *     - 32-bit result of the Microsoft RSS hash function,
25840779d7f6SJiawen Wu  *     - 4-bit RSS type field.
25850779d7f6SJiawen Wu  */
25860779d7f6SJiawen Wu 
25870779d7f6SJiawen Wu /*
25880779d7f6SJiawen Wu  * Used as the default key.
25890779d7f6SJiawen Wu  */
25900779d7f6SJiawen Wu static uint8_t rss_intel_key[40] = {
25910779d7f6SJiawen Wu 	0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
25920779d7f6SJiawen Wu 	0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
25930779d7f6SJiawen Wu 	0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
25940779d7f6SJiawen Wu 	0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
25950779d7f6SJiawen Wu 	0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
25960779d7f6SJiawen Wu };
25970779d7f6SJiawen Wu 
25980779d7f6SJiawen Wu static void
25990779d7f6SJiawen Wu ngbe_rss_disable(struct rte_eth_dev *dev)
26000779d7f6SJiawen Wu {
26010779d7f6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
26020779d7f6SJiawen Wu 
26030779d7f6SJiawen Wu 	wr32m(hw, NGBE_RACTL, NGBE_RACTL_RSSENA, 0);
26040779d7f6SJiawen Wu }
26050779d7f6SJiawen Wu 
26060779d7f6SJiawen Wu int
26070779d7f6SJiawen Wu ngbe_dev_rss_hash_update(struct rte_eth_dev *dev,
26080779d7f6SJiawen Wu 			  struct rte_eth_rss_conf *rss_conf)
26090779d7f6SJiawen Wu {
26100779d7f6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
26110779d7f6SJiawen Wu 	uint8_t  *hash_key;
26120779d7f6SJiawen Wu 	uint32_t mrqc;
26130779d7f6SJiawen Wu 	uint32_t rss_key;
26140779d7f6SJiawen Wu 	uint64_t rss_hf;
26150779d7f6SJiawen Wu 	uint16_t i;
26160779d7f6SJiawen Wu 
26170779d7f6SJiawen Wu 	if (!hw->is_pf) {
26180779d7f6SJiawen Wu 		PMD_DRV_LOG(ERR, "RSS hash update is not supported on this "
26190779d7f6SJiawen Wu 			"NIC.");
26200779d7f6SJiawen Wu 		return -ENOTSUP;
26210779d7f6SJiawen Wu 	}
26220779d7f6SJiawen Wu 
26230779d7f6SJiawen Wu 	hash_key = rss_conf->rss_key;
26240779d7f6SJiawen Wu 	if (hash_key) {
26250779d7f6SJiawen Wu 		/* Fill in RSS hash key */
26260779d7f6SJiawen Wu 		for (i = 0; i < 10; i++) {
26270779d7f6SJiawen Wu 			rss_key  = LS32(hash_key[(i * 4) + 0], 0, 0xFF);
26280779d7f6SJiawen Wu 			rss_key |= LS32(hash_key[(i * 4) + 1], 8, 0xFF);
26290779d7f6SJiawen Wu 			rss_key |= LS32(hash_key[(i * 4) + 2], 16, 0xFF);
26300779d7f6SJiawen Wu 			rss_key |= LS32(hash_key[(i * 4) + 3], 24, 0xFF);
26310779d7f6SJiawen Wu 			wr32a(hw, NGBE_REG_RSSKEY, i, rss_key);
26320779d7f6SJiawen Wu 		}
26330779d7f6SJiawen Wu 	}
26340779d7f6SJiawen Wu 
26350779d7f6SJiawen Wu 	/* Set configured hashing protocols */
26360779d7f6SJiawen Wu 	rss_hf = rss_conf->rss_hf & NGBE_RSS_OFFLOAD_ALL;
26370779d7f6SJiawen Wu 
26380779d7f6SJiawen Wu 	mrqc = rd32(hw, NGBE_RACTL);
26390779d7f6SJiawen Wu 	mrqc &= ~NGBE_RACTL_RSSMASK;
26400779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_IPV4)
26410779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV4;
26420779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
26430779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV4TCP;
26440779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_IPV6 ||
26450779d7f6SJiawen Wu 	    rss_hf & RTE_ETH_RSS_IPV6_EX)
26460779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV6;
26470779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP ||
26480779d7f6SJiawen Wu 	    rss_hf & RTE_ETH_RSS_IPV6_TCP_EX)
26490779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV6TCP;
26500779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
26510779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV4UDP;
26520779d7f6SJiawen Wu 	if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP ||
26530779d7f6SJiawen Wu 	    rss_hf & RTE_ETH_RSS_IPV6_UDP_EX)
26540779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSIPV6UDP;
26550779d7f6SJiawen Wu 
26560779d7f6SJiawen Wu 	if (rss_hf)
26570779d7f6SJiawen Wu 		mrqc |= NGBE_RACTL_RSSENA;
26580779d7f6SJiawen Wu 	else
26590779d7f6SJiawen Wu 		mrqc &= ~NGBE_RACTL_RSSENA;
26600779d7f6SJiawen Wu 
26610779d7f6SJiawen Wu 	wr32(hw, NGBE_RACTL, mrqc);
26620779d7f6SJiawen Wu 
26630779d7f6SJiawen Wu 	return 0;
26640779d7f6SJiawen Wu }
26650779d7f6SJiawen Wu 
26660779d7f6SJiawen Wu int
26670779d7f6SJiawen Wu ngbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
26680779d7f6SJiawen Wu 			    struct rte_eth_rss_conf *rss_conf)
26690779d7f6SJiawen Wu {
26700779d7f6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
26710779d7f6SJiawen Wu 	uint8_t *hash_key;
26720779d7f6SJiawen Wu 	uint32_t mrqc;
26730779d7f6SJiawen Wu 	uint32_t rss_key;
26740779d7f6SJiawen Wu 	uint64_t rss_hf;
26750779d7f6SJiawen Wu 	uint16_t i;
26760779d7f6SJiawen Wu 
26770779d7f6SJiawen Wu 	hash_key = rss_conf->rss_key;
26780779d7f6SJiawen Wu 	if (hash_key) {
26790779d7f6SJiawen Wu 		/* Return RSS hash key */
26800779d7f6SJiawen Wu 		for (i = 0; i < 10; i++) {
26810779d7f6SJiawen Wu 			rss_key = rd32a(hw, NGBE_REG_RSSKEY, i);
26820779d7f6SJiawen Wu 			hash_key[(i * 4) + 0] = RS32(rss_key, 0, 0xFF);
26830779d7f6SJiawen Wu 			hash_key[(i * 4) + 1] = RS32(rss_key, 8, 0xFF);
26840779d7f6SJiawen Wu 			hash_key[(i * 4) + 2] = RS32(rss_key, 16, 0xFF);
26850779d7f6SJiawen Wu 			hash_key[(i * 4) + 3] = RS32(rss_key, 24, 0xFF);
26860779d7f6SJiawen Wu 		}
26870779d7f6SJiawen Wu 	}
26880779d7f6SJiawen Wu 
26890779d7f6SJiawen Wu 	rss_hf = 0;
26900779d7f6SJiawen Wu 
26910779d7f6SJiawen Wu 	mrqc = rd32(hw, NGBE_RACTL);
26920779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV4)
26930779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_IPV4;
26940779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV4TCP)
26950779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
26960779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV6)
26970779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_IPV6 |
26980779d7f6SJiawen Wu 			  RTE_ETH_RSS_IPV6_EX;
26990779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV6TCP)
27000779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP |
27010779d7f6SJiawen Wu 			  RTE_ETH_RSS_IPV6_TCP_EX;
27020779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV4UDP)
27030779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
27040779d7f6SJiawen Wu 	if (mrqc & NGBE_RACTL_RSSIPV6UDP)
27050779d7f6SJiawen Wu 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP |
27060779d7f6SJiawen Wu 			  RTE_ETH_RSS_IPV6_UDP_EX;
27070779d7f6SJiawen Wu 	if (!(mrqc & NGBE_RACTL_RSSENA))
27080779d7f6SJiawen Wu 		rss_hf = 0;
27090779d7f6SJiawen Wu 
27100779d7f6SJiawen Wu 	rss_hf &= NGBE_RSS_OFFLOAD_ALL;
27110779d7f6SJiawen Wu 
27120779d7f6SJiawen Wu 	rss_conf->rss_hf = rss_hf;
27130779d7f6SJiawen Wu 	return 0;
27140779d7f6SJiawen Wu }
27150779d7f6SJiawen Wu 
27160779d7f6SJiawen Wu static void
27170779d7f6SJiawen Wu ngbe_rss_configure(struct rte_eth_dev *dev)
27180779d7f6SJiawen Wu {
27190779d7f6SJiawen Wu 	struct rte_eth_rss_conf rss_conf;
27200779d7f6SJiawen Wu 	struct ngbe_adapter *adapter = ngbe_dev_adapter(dev);
27210779d7f6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
27220779d7f6SJiawen Wu 	uint32_t reta;
27230779d7f6SJiawen Wu 	uint16_t i;
27240779d7f6SJiawen Wu 	uint16_t j;
27250779d7f6SJiawen Wu 
27260779d7f6SJiawen Wu 	PMD_INIT_FUNC_TRACE();
27270779d7f6SJiawen Wu 
27280779d7f6SJiawen Wu 	/*
27290779d7f6SJiawen Wu 	 * Fill in redirection table
27300779d7f6SJiawen Wu 	 * The byte-swap is needed because NIC registers are in
27310779d7f6SJiawen Wu 	 * little-endian order.
27320779d7f6SJiawen Wu 	 */
27330779d7f6SJiawen Wu 	if (adapter->rss_reta_updated == 0) {
27340779d7f6SJiawen Wu 		reta = 0;
27350779d7f6SJiawen Wu 		for (i = 0, j = 0; i < RTE_ETH_RSS_RETA_SIZE_128; i++, j++) {
27360779d7f6SJiawen Wu 			if (j == dev->data->nb_rx_queues)
27370779d7f6SJiawen Wu 				j = 0;
27380779d7f6SJiawen Wu 			reta = (reta >> 8) | LS32(j, 24, 0xFF);
27390779d7f6SJiawen Wu 			if ((i & 3) == 3)
27400779d7f6SJiawen Wu 				wr32a(hw, NGBE_REG_RSSTBL, i >> 2, reta);
27410779d7f6SJiawen Wu 		}
27420779d7f6SJiawen Wu 	}
27430779d7f6SJiawen Wu 	/*
27440779d7f6SJiawen Wu 	 * Configure the RSS key and the RSS protocols used to compute
27450779d7f6SJiawen Wu 	 * the RSS hash of input packets.
27460779d7f6SJiawen Wu 	 */
27470779d7f6SJiawen Wu 	rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
27480779d7f6SJiawen Wu 	if (rss_conf.rss_key == NULL)
27490779d7f6SJiawen Wu 		rss_conf.rss_key = rss_intel_key; /* Default hash key */
27500779d7f6SJiawen Wu 	ngbe_dev_rss_hash_update(dev, &rss_conf);
27510779d7f6SJiawen Wu }
27520779d7f6SJiawen Wu 
275359b46438SJiawen Wu void ngbe_configure_port(struct rte_eth_dev *dev)
275459b46438SJiawen Wu {
275559b46438SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
275659b46438SJiawen Wu 	int i = 0;
275759b46438SJiawen Wu 	uint16_t tpids[8] = {RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_QINQ,
275859b46438SJiawen Wu 				0x9100, 0x9200,
275959b46438SJiawen Wu 				0x0000, 0x0000,
276059b46438SJiawen Wu 				0x0000, 0x0000};
276159b46438SJiawen Wu 
276259b46438SJiawen Wu 	PMD_INIT_FUNC_TRACE();
276359b46438SJiawen Wu 
276459b46438SJiawen Wu 	/* default outer vlan tpid */
276559b46438SJiawen Wu 	wr32(hw, NGBE_EXTAG,
276659b46438SJiawen Wu 		NGBE_EXTAG_ETAG(RTE_ETHER_TYPE_ETAG) |
276759b46438SJiawen Wu 		NGBE_EXTAG_VLAN(RTE_ETHER_TYPE_QINQ));
276859b46438SJiawen Wu 
276959b46438SJiawen Wu 	/* default inner vlan tpid */
277059b46438SJiawen Wu 	wr32m(hw, NGBE_VLANCTL,
277159b46438SJiawen Wu 		NGBE_VLANCTL_TPID_MASK,
277259b46438SJiawen Wu 		NGBE_VLANCTL_TPID(RTE_ETHER_TYPE_VLAN));
277359b46438SJiawen Wu 	wr32m(hw, NGBE_DMATXCTRL,
277459b46438SJiawen Wu 		NGBE_DMATXCTRL_TPID_MASK,
277559b46438SJiawen Wu 		NGBE_DMATXCTRL_TPID(RTE_ETHER_TYPE_VLAN));
277659b46438SJiawen Wu 
277759b46438SJiawen Wu 	/* default vlan tpid filters */
277859b46438SJiawen Wu 	for (i = 0; i < 8; i++) {
277959b46438SJiawen Wu 		wr32m(hw, NGBE_TAGTPID(i / 2),
278059b46438SJiawen Wu 			(i % 2 ? NGBE_TAGTPID_MSB_MASK
278159b46438SJiawen Wu 			       : NGBE_TAGTPID_LSB_MASK),
278259b46438SJiawen Wu 			(i % 2 ? NGBE_TAGTPID_MSB(tpids[i])
278359b46438SJiawen Wu 			       : NGBE_TAGTPID_LSB(tpids[i])));
278459b46438SJiawen Wu 	}
278559b46438SJiawen Wu }
278659b46438SJiawen Wu 
278762fc35e6SJiawen Wu static int
278862fc35e6SJiawen Wu ngbe_alloc_rx_queue_mbufs(struct ngbe_rx_queue *rxq)
278962fc35e6SJiawen Wu {
279062fc35e6SJiawen Wu 	struct ngbe_rx_entry *rxe = rxq->sw_ring;
279162fc35e6SJiawen Wu 	uint64_t dma_addr;
279262fc35e6SJiawen Wu 	unsigned int i;
279362fc35e6SJiawen Wu 
279462fc35e6SJiawen Wu 	/* Initialize software ring entries */
279562fc35e6SJiawen Wu 	for (i = 0; i < rxq->nb_rx_desc; i++) {
279662fc35e6SJiawen Wu 		/* the ring can also be modified by hardware */
279762fc35e6SJiawen Wu 		volatile struct ngbe_rx_desc *rxd;
279862fc35e6SJiawen Wu 		struct rte_mbuf *mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
279962fc35e6SJiawen Wu 
280062fc35e6SJiawen Wu 		if (mbuf == NULL) {
280162fc35e6SJiawen Wu 			PMD_INIT_LOG(ERR, "Rx mbuf alloc failed queue_id=%u port_id=%u",
280262fc35e6SJiawen Wu 				     (unsigned int)rxq->queue_id,
280362fc35e6SJiawen Wu 				     (unsigned int)rxq->port_id);
280462fc35e6SJiawen Wu 			return -ENOMEM;
280562fc35e6SJiawen Wu 		}
280662fc35e6SJiawen Wu 
280762fc35e6SJiawen Wu 		mbuf->data_off = RTE_PKTMBUF_HEADROOM;
280862fc35e6SJiawen Wu 		mbuf->port = rxq->port_id;
280962fc35e6SJiawen Wu 
281062fc35e6SJiawen Wu 		dma_addr =
281162fc35e6SJiawen Wu 			rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
281262fc35e6SJiawen Wu 		rxd = &rxq->rx_ring[i];
281362fc35e6SJiawen Wu 		NGBE_RXD_HDRADDR(rxd, 0);
281462fc35e6SJiawen Wu 		NGBE_RXD_PKTADDR(rxd, dma_addr);
281562fc35e6SJiawen Wu 		rxe[i].mbuf = mbuf;
281662fc35e6SJiawen Wu 	}
281762fc35e6SJiawen Wu 
281862fc35e6SJiawen Wu 	return 0;
281962fc35e6SJiawen Wu }
282062fc35e6SJiawen Wu 
28210779d7f6SJiawen Wu static int
28220779d7f6SJiawen Wu ngbe_dev_mq_rx_configure(struct rte_eth_dev *dev)
28230779d7f6SJiawen Wu {
282460229dcfSJiawen Wu 	if (RTE_ETH_DEV_SRIOV(dev).active == 0) {
28250779d7f6SJiawen Wu 		switch (dev->data->dev_conf.rxmode.mq_mode) {
28260779d7f6SJiawen Wu 		case RTE_ETH_MQ_RX_RSS:
28270779d7f6SJiawen Wu 			ngbe_rss_configure(dev);
28280779d7f6SJiawen Wu 			break;
28290779d7f6SJiawen Wu 
28300779d7f6SJiawen Wu 		case RTE_ETH_MQ_RX_NONE:
28310779d7f6SJiawen Wu 		default:
28320779d7f6SJiawen Wu 			/* if mq_mode is none, disable rss mode.*/
28330779d7f6SJiawen Wu 			ngbe_rss_disable(dev);
28340779d7f6SJiawen Wu 			break;
28350779d7f6SJiawen Wu 		}
283660229dcfSJiawen Wu 	}
28370779d7f6SJiawen Wu 
28380779d7f6SJiawen Wu 	return 0;
28390779d7f6SJiawen Wu }
28400779d7f6SJiawen Wu 
284179f3128dSJiawen Wu void
284279f3128dSJiawen Wu ngbe_set_rx_function(struct rte_eth_dev *dev)
284379f3128dSJiawen Wu {
2844e94c20c3SJiawen Wu 	uint16_t i, rx_using_sse;
284579f3128dSJiawen Wu 	struct ngbe_adapter *adapter = ngbe_dev_adapter(dev);
284679f3128dSJiawen Wu 
2847e94c20c3SJiawen Wu 	/*
2848e94c20c3SJiawen Wu 	 * In order to allow Vector Rx there are a few configuration
2849e94c20c3SJiawen Wu 	 * conditions to be met and Rx Bulk Allocation should be allowed.
2850e94c20c3SJiawen Wu 	 */
2851e94c20c3SJiawen Wu 	if (ngbe_rx_vec_dev_conf_condition_check(dev) ||
2852e94c20c3SJiawen Wu 	    !adapter->rx_bulk_alloc_allowed ||
2853e94c20c3SJiawen Wu 			rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128) {
2854e94c20c3SJiawen Wu 		PMD_INIT_LOG(DEBUG,
2855e94c20c3SJiawen Wu 			     "Port[%d] doesn't meet Vector Rx preconditions",
2856e94c20c3SJiawen Wu 			     dev->data->port_id);
2857e94c20c3SJiawen Wu 		adapter->rx_vec_allowed = false;
2858e94c20c3SJiawen Wu 	}
2859e94c20c3SJiawen Wu 
286079f3128dSJiawen Wu 	if (dev->data->scattered_rx) {
286179f3128dSJiawen Wu 		/*
286279f3128dSJiawen Wu 		 * Set the scattered callback: there are bulk and
286379f3128dSJiawen Wu 		 * single allocation versions.
286479f3128dSJiawen Wu 		 */
2865e94c20c3SJiawen Wu 		if (adapter->rx_vec_allowed) {
2866e94c20c3SJiawen Wu 			PMD_INIT_LOG(DEBUG,
2867e94c20c3SJiawen Wu 				     "Using Vector Scattered Rx callback (port=%d).",
2868e94c20c3SJiawen Wu 				     dev->data->port_id);
2869e94c20c3SJiawen Wu 			dev->rx_pkt_burst = ngbe_recv_scattered_pkts_vec;
2870e94c20c3SJiawen Wu 		} else if (adapter->rx_bulk_alloc_allowed) {
287179f3128dSJiawen Wu 			PMD_INIT_LOG(DEBUG, "Using a Scattered with bulk "
287279f3128dSJiawen Wu 					   "allocation callback (port=%d).",
287379f3128dSJiawen Wu 				     dev->data->port_id);
287479f3128dSJiawen Wu 			dev->rx_pkt_burst = ngbe_recv_pkts_sc_bulk_alloc;
287579f3128dSJiawen Wu 		} else {
287679f3128dSJiawen Wu 			PMD_INIT_LOG(DEBUG, "Using Regular (non-vector, "
287779f3128dSJiawen Wu 					    "single allocation) "
287879f3128dSJiawen Wu 					    "Scattered Rx callback "
287979f3128dSJiawen Wu 					    "(port=%d).",
288079f3128dSJiawen Wu 				     dev->data->port_id);
288179f3128dSJiawen Wu 
288279f3128dSJiawen Wu 			dev->rx_pkt_burst = ngbe_recv_pkts_sc_single_alloc;
288379f3128dSJiawen Wu 		}
288479f3128dSJiawen Wu 	/*
288579f3128dSJiawen Wu 	 * Below we set "simple" callbacks according to port/queues parameters.
288679f3128dSJiawen Wu 	 * If parameters allow we are going to choose between the following
288779f3128dSJiawen Wu 	 * callbacks:
2888e94c20c3SJiawen Wu 	 *    - Vector
288979f3128dSJiawen Wu 	 *    - Bulk Allocation
289079f3128dSJiawen Wu 	 *    - Single buffer allocation (the simplest one)
289179f3128dSJiawen Wu 	 */
2892e94c20c3SJiawen Wu 	} else if (adapter->rx_vec_allowed) {
2893e94c20c3SJiawen Wu 		PMD_INIT_LOG(DEBUG, "Vector rx enabled, please make sure Rx "
2894e94c20c3SJiawen Wu 				    "burst size no less than %d (port=%d).",
2895e94c20c3SJiawen Wu 			     RTE_NGBE_DESCS_PER_LOOP,
2896e94c20c3SJiawen Wu 			     dev->data->port_id);
2897e94c20c3SJiawen Wu 		dev->rx_pkt_burst = ngbe_recv_pkts_vec;
289879f3128dSJiawen Wu 	} else if (adapter->rx_bulk_alloc_allowed) {
289979f3128dSJiawen Wu 		PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are "
290079f3128dSJiawen Wu 				    "satisfied. Rx Burst Bulk Alloc function "
290179f3128dSJiawen Wu 				    "will be used on port=%d.",
290279f3128dSJiawen Wu 			     dev->data->port_id);
290379f3128dSJiawen Wu 
290479f3128dSJiawen Wu 		dev->rx_pkt_burst = ngbe_recv_pkts_bulk_alloc;
290579f3128dSJiawen Wu 	} else {
290679f3128dSJiawen Wu 		PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are not "
290779f3128dSJiawen Wu 				    "satisfied, or Scattered Rx is requested "
290879f3128dSJiawen Wu 				    "(port=%d).",
290979f3128dSJiawen Wu 			     dev->data->port_id);
291079f3128dSJiawen Wu 
291179f3128dSJiawen Wu 		dev->rx_pkt_burst = ngbe_recv_pkts;
291279f3128dSJiawen Wu 	}
2913e94c20c3SJiawen Wu 
2914e94c20c3SJiawen Wu 	rx_using_sse = (dev->rx_pkt_burst == ngbe_recv_scattered_pkts_vec ||
2915e94c20c3SJiawen Wu 			dev->rx_pkt_burst == ngbe_recv_pkts_vec);
2916e94c20c3SJiawen Wu 
2917e94c20c3SJiawen Wu 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
2918e94c20c3SJiawen Wu 		struct ngbe_rx_queue *rxq = dev->data->rx_queues[i];
2919e94c20c3SJiawen Wu 
2920e94c20c3SJiawen Wu 		rxq->rx_using_sse = rx_using_sse;
2921e94c20c3SJiawen Wu 	}
292279f3128dSJiawen Wu }
292379f3128dSJiawen Wu 
2924d148a87eSJiawen Wu static const struct {
2925d148a87eSJiawen Wu 	eth_rx_burst_t pkt_burst;
2926d148a87eSJiawen Wu 	const char *info;
2927d148a87eSJiawen Wu } ngbe_rx_burst_infos[] = {
2928d148a87eSJiawen Wu 	{ ngbe_recv_pkts_sc_single_alloc,    "Scalar Scattered"},
2929d148a87eSJiawen Wu 	{ ngbe_recv_pkts_sc_bulk_alloc,      "Scalar Scattered Bulk Alloc"},
2930d148a87eSJiawen Wu 	{ ngbe_recv_pkts_bulk_alloc,         "Scalar Bulk Alloc"},
2931d148a87eSJiawen Wu 	{ ngbe_recv_pkts,                    "Scalar"},
2932e94c20c3SJiawen Wu #ifdef RTE_ARCH_X86
2933e94c20c3SJiawen Wu 	{ ngbe_recv_scattered_pkts_vec,      "Vector SSE Scattered" },
2934e94c20c3SJiawen Wu 	{ ngbe_recv_pkts_vec,                "Vector SSE" },
2935e94c20c3SJiawen Wu #elif defined(RTE_ARCH_ARM64)
2936e94c20c3SJiawen Wu 	{ ngbe_recv_scattered_pkts_vec,      "Vector Neon Scattered" },
2937e94c20c3SJiawen Wu 	{ ngbe_recv_pkts_vec,                "Vector Neon" },
2938e94c20c3SJiawen Wu #endif
2939d148a87eSJiawen Wu };
2940d148a87eSJiawen Wu 
2941d148a87eSJiawen Wu int
2942d148a87eSJiawen Wu ngbe_rx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,
2943d148a87eSJiawen Wu 		      struct rte_eth_burst_mode *mode)
2944d148a87eSJiawen Wu {
2945d148a87eSJiawen Wu 	eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
2946d148a87eSJiawen Wu 	int ret = -EINVAL;
2947d148a87eSJiawen Wu 	unsigned int i;
2948d148a87eSJiawen Wu 
2949d148a87eSJiawen Wu 	for (i = 0; i < RTE_DIM(ngbe_rx_burst_infos); ++i) {
2950d148a87eSJiawen Wu 		if (pkt_burst == ngbe_rx_burst_infos[i].pkt_burst) {
2951d148a87eSJiawen Wu 			snprintf(mode->info, sizeof(mode->info), "%s",
2952d148a87eSJiawen Wu 				 ngbe_rx_burst_infos[i].info);
2953d148a87eSJiawen Wu 			ret = 0;
2954d148a87eSJiawen Wu 			break;
2955d148a87eSJiawen Wu 		}
2956d148a87eSJiawen Wu 	}
2957d148a87eSJiawen Wu 
2958d148a87eSJiawen Wu 	return ret;
2959d148a87eSJiawen Wu }
2960d148a87eSJiawen Wu 
29613518df57SJiawen Wu /*
29623518df57SJiawen Wu  * Initializes Receive Unit.
29633518df57SJiawen Wu  */
29643518df57SJiawen Wu int
29653518df57SJiawen Wu ngbe_dev_rx_init(struct rte_eth_dev *dev)
29663518df57SJiawen Wu {
296762fc35e6SJiawen Wu 	struct ngbe_hw *hw;
296862fc35e6SJiawen Wu 	struct ngbe_rx_queue *rxq;
296962fc35e6SJiawen Wu 	uint64_t bus_addr;
297062fc35e6SJiawen Wu 	uint32_t fctrl;
297162fc35e6SJiawen Wu 	uint32_t hlreg0;
297262fc35e6SJiawen Wu 	uint32_t srrctl;
297364b36e4aSJiawen Wu 	uint32_t rdrxctl;
2974ffc959f5SJiawen Wu 	uint32_t rxcsum;
297562fc35e6SJiawen Wu 	uint16_t buf_size;
297662fc35e6SJiawen Wu 	uint16_t i;
297779f3128dSJiawen Wu 	struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode;
29783518df57SJiawen Wu 
297962fc35e6SJiawen Wu 	PMD_INIT_FUNC_TRACE();
298062fc35e6SJiawen Wu 	hw = ngbe_dev_hw(dev);
298162fc35e6SJiawen Wu 
298262fc35e6SJiawen Wu 	/*
298362fc35e6SJiawen Wu 	 * Make sure receives are disabled while setting
298462fc35e6SJiawen Wu 	 * up the Rx context (registers, descriptor rings, etc.).
298562fc35e6SJiawen Wu 	 */
29865f1ab0d5SJiawen Wu 
29875f1ab0d5SJiawen Wu 	if (!(hw->ncsi_enabled || hw->wol_enabled))
298862fc35e6SJiawen Wu 		wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0);
29895f1ab0d5SJiawen Wu 
299062fc35e6SJiawen Wu 	wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0);
299162fc35e6SJiawen Wu 
299262fc35e6SJiawen Wu 	/* Enable receipt of broadcasted frames */
299362fc35e6SJiawen Wu 	fctrl = rd32(hw, NGBE_PSRCTL);
299462fc35e6SJiawen Wu 	fctrl |= NGBE_PSRCTL_BCA;
299562fc35e6SJiawen Wu 	wr32(hw, NGBE_PSRCTL, fctrl);
299662fc35e6SJiawen Wu 
299764b36e4aSJiawen Wu 	/*
299864b36e4aSJiawen Wu 	 * Configure CRC stripping, if any.
299964b36e4aSJiawen Wu 	 */
300062fc35e6SJiawen Wu 	hlreg0 = rd32(hw, NGBE_SECRXCTL);
300164b36e4aSJiawen Wu 	if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
300264b36e4aSJiawen Wu 		hlreg0 &= ~NGBE_SECRXCTL_CRCSTRIP;
300364b36e4aSJiawen Wu 	else
300464b36e4aSJiawen Wu 		hlreg0 |= NGBE_SECRXCTL_CRCSTRIP;
300562fc35e6SJiawen Wu 	hlreg0 &= ~NGBE_SECRXCTL_XDSA;
300662fc35e6SJiawen Wu 	wr32(hw, NGBE_SECRXCTL, hlreg0);
300762fc35e6SJiawen Wu 
3008586e6028SJiawen Wu 	/*
3009586e6028SJiawen Wu 	 * Configure jumbo frame support, if any.
3010586e6028SJiawen Wu 	 */
301162fc35e6SJiawen Wu 	wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK,
3012586e6028SJiawen Wu 		NGBE_FRMSZ_MAX(dev->data->mtu + NGBE_ETH_OVERHEAD));
301362fc35e6SJiawen Wu 
301459b46438SJiawen Wu 	/*
3015d4a3fe69SJiawen Wu 	 * If loopback mode is configured, set LPBK bit.
3016d4a3fe69SJiawen Wu 	 */
3017d4a3fe69SJiawen Wu 	hlreg0 = rd32(hw, NGBE_PSRCTL);
3018d4a3fe69SJiawen Wu 	if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
3019d4a3fe69SJiawen Wu 		hlreg0 |= NGBE_PSRCTL_LBENA;
3020d4a3fe69SJiawen Wu 	else
3021d4a3fe69SJiawen Wu 		hlreg0 &= ~NGBE_PSRCTL_LBENA;
3022d4a3fe69SJiawen Wu 
3023d4a3fe69SJiawen Wu 	wr32(hw, NGBE_PSRCTL, hlreg0);
3024d4a3fe69SJiawen Wu 
3025d4a3fe69SJiawen Wu 	/*
302659b46438SJiawen Wu 	 * Assume no header split and no VLAN strip support
302759b46438SJiawen Wu 	 * on any Rx queue first .
302859b46438SJiawen Wu 	 */
302959b46438SJiawen Wu 	rx_conf->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
303059b46438SJiawen Wu 
303162fc35e6SJiawen Wu 	/* Setup Rx queues */
303262fc35e6SJiawen Wu 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
303362fc35e6SJiawen Wu 		rxq = dev->data->rx_queues[i];
303462fc35e6SJiawen Wu 
303564b36e4aSJiawen Wu 		/*
303664b36e4aSJiawen Wu 		 * Reset crc_len in case it was changed after queue setup by a
303764b36e4aSJiawen Wu 		 * call to configure.
303864b36e4aSJiawen Wu 		 */
303964b36e4aSJiawen Wu 		if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
304064b36e4aSJiawen Wu 			rxq->crc_len = RTE_ETHER_CRC_LEN;
304164b36e4aSJiawen Wu 		else
304264b36e4aSJiawen Wu 			rxq->crc_len = 0;
304364b36e4aSJiawen Wu 
304462fc35e6SJiawen Wu 		/* Setup the Base and Length of the Rx Descriptor Rings */
304562fc35e6SJiawen Wu 		bus_addr = rxq->rx_ring_phys_addr;
304662fc35e6SJiawen Wu 		wr32(hw, NGBE_RXBAL(rxq->reg_idx),
304762fc35e6SJiawen Wu 				(uint32_t)(bus_addr & BIT_MASK32));
304862fc35e6SJiawen Wu 		wr32(hw, NGBE_RXBAH(rxq->reg_idx),
304962fc35e6SJiawen Wu 				(uint32_t)(bus_addr >> 32));
305062fc35e6SJiawen Wu 		wr32(hw, NGBE_RXRP(rxq->reg_idx), 0);
305162fc35e6SJiawen Wu 		wr32(hw, NGBE_RXWP(rxq->reg_idx), 0);
305262fc35e6SJiawen Wu 
305362fc35e6SJiawen Wu 		srrctl = NGBE_RXCFG_RNGLEN(rxq->nb_rx_desc);
305462fc35e6SJiawen Wu 
305562fc35e6SJiawen Wu 		/* Set if packets are dropped when no descriptors available */
305662fc35e6SJiawen Wu 		if (rxq->drop_en)
305762fc35e6SJiawen Wu 			srrctl |= NGBE_RXCFG_DROP;
305862fc35e6SJiawen Wu 
305962fc35e6SJiawen Wu 		/*
306062fc35e6SJiawen Wu 		 * Configure the Rx buffer size in the PKTLEN field of
306162fc35e6SJiawen Wu 		 * the RXCFG register of the queue.
306262fc35e6SJiawen Wu 		 * The value is in 1 KB resolution. Valid values can be from
306362fc35e6SJiawen Wu 		 * 1 KB to 16 KB.
306462fc35e6SJiawen Wu 		 */
306562fc35e6SJiawen Wu 		buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) -
306662fc35e6SJiawen Wu 			RTE_PKTMBUF_HEADROOM);
306762fc35e6SJiawen Wu 		buf_size = ROUND_DOWN(buf_size, 0x1 << 10);
306862fc35e6SJiawen Wu 		srrctl |= NGBE_RXCFG_PKTLEN(buf_size);
306962fc35e6SJiawen Wu 
307062fc35e6SJiawen Wu 		wr32(hw, NGBE_RXCFG(rxq->reg_idx), srrctl);
307159b46438SJiawen Wu 
307259b46438SJiawen Wu 		/* It adds dual VLAN length for supporting dual VLAN */
307359b46438SJiawen Wu 		if (dev->data->mtu + NGBE_ETH_OVERHEAD +
307425cf2630SFerruh Yigit 				2 * RTE_VLAN_HLEN > buf_size)
307559b46438SJiawen Wu 			dev->data->scattered_rx = 1;
307659b46438SJiawen Wu 		if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
307759b46438SJiawen Wu 			rx_conf->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
307862fc35e6SJiawen Wu 	}
307962fc35e6SJiawen Wu 
308079f3128dSJiawen Wu 	if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_SCATTER)
308179f3128dSJiawen Wu 		dev->data->scattered_rx = 1;
30820779d7f6SJiawen Wu 
30830779d7f6SJiawen Wu 	/*
30840779d7f6SJiawen Wu 	 * Device configured with multiple RX queues.
30850779d7f6SJiawen Wu 	 */
30860779d7f6SJiawen Wu 	ngbe_dev_mq_rx_configure(dev);
30870779d7f6SJiawen Wu 
3088ffc959f5SJiawen Wu 	/*
3089ffc959f5SJiawen Wu 	 * Setup the Checksum Register.
30900779d7f6SJiawen Wu 	 * Disable Full-Packet Checksum which is mutually exclusive with RSS.
3091ffc959f5SJiawen Wu 	 * Enable IP/L4 checksum computation by hardware if requested to do so.
3092ffc959f5SJiawen Wu 	 */
3093ffc959f5SJiawen Wu 	rxcsum = rd32(hw, NGBE_PSRCTL);
3094ffc959f5SJiawen Wu 	rxcsum |= NGBE_PSRCTL_PCSD;
3095ffc959f5SJiawen Wu 	if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
3096ffc959f5SJiawen Wu 		rxcsum |= NGBE_PSRCTL_L4CSUM;
3097ffc959f5SJiawen Wu 	else
3098ffc959f5SJiawen Wu 		rxcsum &= ~NGBE_PSRCTL_L4CSUM;
3099ffc959f5SJiawen Wu 
3100ffc959f5SJiawen Wu 	wr32(hw, NGBE_PSRCTL, rxcsum);
310179f3128dSJiawen Wu 
310264b36e4aSJiawen Wu 	if (hw->is_pf) {
310364b36e4aSJiawen Wu 		rdrxctl = rd32(hw, NGBE_SECRXCTL);
310464b36e4aSJiawen Wu 		if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
310564b36e4aSJiawen Wu 			rdrxctl &= ~NGBE_SECRXCTL_CRCSTRIP;
310664b36e4aSJiawen Wu 		else
310764b36e4aSJiawen Wu 			rdrxctl |= NGBE_SECRXCTL_CRCSTRIP;
310864b36e4aSJiawen Wu 		wr32(hw, NGBE_SECRXCTL, rdrxctl);
310964b36e4aSJiawen Wu 	}
311064b36e4aSJiawen Wu 
311179f3128dSJiawen Wu 	ngbe_set_rx_function(dev);
311279f3128dSJiawen Wu 
311362fc35e6SJiawen Wu 	return 0;
31143518df57SJiawen Wu }
31153518df57SJiawen Wu 
31163518df57SJiawen Wu /*
31173518df57SJiawen Wu  * Initializes Transmit Unit.
31183518df57SJiawen Wu  */
31193518df57SJiawen Wu void
31203518df57SJiawen Wu ngbe_dev_tx_init(struct rte_eth_dev *dev)
31213518df57SJiawen Wu {
3122001c7823SJiawen Wu 	struct ngbe_hw     *hw;
3123001c7823SJiawen Wu 	struct ngbe_tx_queue *txq;
3124001c7823SJiawen Wu 	uint64_t bus_addr;
3125001c7823SJiawen Wu 	uint16_t i;
3126001c7823SJiawen Wu 
3127001c7823SJiawen Wu 	PMD_INIT_FUNC_TRACE();
3128001c7823SJiawen Wu 	hw = ngbe_dev_hw(dev);
3129001c7823SJiawen Wu 
3130001c7823SJiawen Wu 	wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_ODSA, NGBE_SECTXCTL_ODSA);
3131001c7823SJiawen Wu 	wr32m(hw, NGBE_SECTXCTL, NGBE_SECTXCTL_XDSA, 0);
3132001c7823SJiawen Wu 
3133001c7823SJiawen Wu 	/* Setup the Base and Length of the Tx Descriptor Rings */
3134001c7823SJiawen Wu 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3135001c7823SJiawen Wu 		txq = dev->data->tx_queues[i];
3136001c7823SJiawen Wu 
3137001c7823SJiawen Wu 		bus_addr = txq->tx_ring_phys_addr;
3138001c7823SJiawen Wu 		wr32(hw, NGBE_TXBAL(txq->reg_idx),
3139001c7823SJiawen Wu 				(uint32_t)(bus_addr & BIT_MASK32));
3140001c7823SJiawen Wu 		wr32(hw, NGBE_TXBAH(txq->reg_idx),
3141001c7823SJiawen Wu 				(uint32_t)(bus_addr >> 32));
3142001c7823SJiawen Wu 		wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_BUFLEN_MASK,
3143001c7823SJiawen Wu 			NGBE_TXCFG_BUFLEN(txq->nb_tx_desc));
3144001c7823SJiawen Wu 		/* Setup the HW Tx Head and TX Tail descriptor pointers */
3145001c7823SJiawen Wu 		wr32(hw, NGBE_TXRP(txq->reg_idx), 0);
3146001c7823SJiawen Wu 		wr32(hw, NGBE_TXWP(txq->reg_idx), 0);
3147001c7823SJiawen Wu 	}
31483518df57SJiawen Wu }
31493518df57SJiawen Wu 
31503518df57SJiawen Wu /*
3151d4a3fe69SJiawen Wu  * Set up link loopback mode Tx->Rx.
3152d4a3fe69SJiawen Wu  */
3153d4a3fe69SJiawen Wu static inline void
3154d4a3fe69SJiawen Wu ngbe_setup_loopback_link(struct ngbe_hw *hw)
3155d4a3fe69SJiawen Wu {
3156d4a3fe69SJiawen Wu 	PMD_INIT_FUNC_TRACE();
3157d4a3fe69SJiawen Wu 
3158d4a3fe69SJiawen Wu 	wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_LB, NGBE_MACRXCFG_LB);
3159d4a3fe69SJiawen Wu 
3160d4a3fe69SJiawen Wu 	msec_delay(50);
3161d4a3fe69SJiawen Wu }
3162d4a3fe69SJiawen Wu 
3163d4a3fe69SJiawen Wu /*
31643518df57SJiawen Wu  * Start Transmit and Receive Units.
31653518df57SJiawen Wu  */
31663518df57SJiawen Wu int
31673518df57SJiawen Wu ngbe_dev_rxtx_start(struct rte_eth_dev *dev)
31683518df57SJiawen Wu {
3169001c7823SJiawen Wu 	struct ngbe_hw     *hw;
3170001c7823SJiawen Wu 	struct ngbe_tx_queue *txq;
317162fc35e6SJiawen Wu 	struct ngbe_rx_queue *rxq;
3172001c7823SJiawen Wu 	uint32_t dmatxctl;
317362fc35e6SJiawen Wu 	uint32_t rxctrl;
3174001c7823SJiawen Wu 	uint16_t i;
3175001c7823SJiawen Wu 	int ret = 0;
3176001c7823SJiawen Wu 
3177001c7823SJiawen Wu 	PMD_INIT_FUNC_TRACE();
3178001c7823SJiawen Wu 	hw = ngbe_dev_hw(dev);
3179001c7823SJiawen Wu 
3180001c7823SJiawen Wu 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3181001c7823SJiawen Wu 		txq = dev->data->tx_queues[i];
3182001c7823SJiawen Wu 		/* Setup Transmit Threshold Registers */
3183001c7823SJiawen Wu 		wr32m(hw, NGBE_TXCFG(txq->reg_idx),
3184001c7823SJiawen Wu 		      NGBE_TXCFG_HTHRESH_MASK |
3185001c7823SJiawen Wu 		      NGBE_TXCFG_WTHRESH_MASK,
3186001c7823SJiawen Wu 		      NGBE_TXCFG_HTHRESH(txq->hthresh) |
3187001c7823SJiawen Wu 		      NGBE_TXCFG_WTHRESH(txq->wthresh));
3188001c7823SJiawen Wu 	}
3189001c7823SJiawen Wu 
3190001c7823SJiawen Wu 	dmatxctl = rd32(hw, NGBE_DMATXCTRL);
3191001c7823SJiawen Wu 	dmatxctl |= NGBE_DMATXCTRL_ENA;
3192001c7823SJiawen Wu 	wr32(hw, NGBE_DMATXCTRL, dmatxctl);
3193001c7823SJiawen Wu 
3194001c7823SJiawen Wu 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3195001c7823SJiawen Wu 		txq = dev->data->tx_queues[i];
3196001c7823SJiawen Wu 		if (txq->tx_deferred_start == 0) {
3197001c7823SJiawen Wu 			ret = ngbe_dev_tx_queue_start(dev, i);
3198001c7823SJiawen Wu 			if (ret < 0)
3199001c7823SJiawen Wu 				return ret;
3200001c7823SJiawen Wu 		}
3201001c7823SJiawen Wu 	}
32023518df57SJiawen Wu 
320362fc35e6SJiawen Wu 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
320462fc35e6SJiawen Wu 		rxq = dev->data->rx_queues[i];
320562fc35e6SJiawen Wu 		if (rxq->rx_deferred_start == 0) {
320662fc35e6SJiawen Wu 			ret = ngbe_dev_rx_queue_start(dev, i);
320762fc35e6SJiawen Wu 			if (ret < 0)
320862fc35e6SJiawen Wu 				return ret;
320962fc35e6SJiawen Wu 		}
321062fc35e6SJiawen Wu 	}
321162fc35e6SJiawen Wu 
321262fc35e6SJiawen Wu 	/* Enable Receive engine */
321362fc35e6SJiawen Wu 	rxctrl = rd32(hw, NGBE_PBRXCTL);
321462fc35e6SJiawen Wu 	rxctrl |= NGBE_PBRXCTL_ENA;
321562fc35e6SJiawen Wu 	hw->mac.enable_rx_dma(hw, rxctrl);
321662fc35e6SJiawen Wu 
3217d4a3fe69SJiawen Wu 	/* If loopback mode is enabled, set up the link accordingly */
3218d4a3fe69SJiawen Wu 	if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
3219d4a3fe69SJiawen Wu 		ngbe_setup_loopback_link(hw);
3220d4a3fe69SJiawen Wu 
322162fc35e6SJiawen Wu 	return 0;
322262fc35e6SJiawen Wu }
322362fc35e6SJiawen Wu 
322462fc35e6SJiawen Wu void
322562fc35e6SJiawen Wu ngbe_dev_save_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id)
322662fc35e6SJiawen Wu {
322762fc35e6SJiawen Wu 	u32 *reg = &hw->q_rx_regs[rx_queue_id * 8];
322862fc35e6SJiawen Wu 	*(reg++) = rd32(hw, NGBE_RXBAL(rx_queue_id));
322962fc35e6SJiawen Wu 	*(reg++) = rd32(hw, NGBE_RXBAH(rx_queue_id));
323062fc35e6SJiawen Wu 	*(reg++) = rd32(hw, NGBE_RXCFG(rx_queue_id));
323162fc35e6SJiawen Wu }
323262fc35e6SJiawen Wu 
323362fc35e6SJiawen Wu void
323462fc35e6SJiawen Wu ngbe_dev_store_rx_queue(struct ngbe_hw *hw, uint16_t rx_queue_id)
323562fc35e6SJiawen Wu {
323662fc35e6SJiawen Wu 	u32 *reg = &hw->q_rx_regs[rx_queue_id * 8];
323762fc35e6SJiawen Wu 	wr32(hw, NGBE_RXBAL(rx_queue_id), *(reg++));
323862fc35e6SJiawen Wu 	wr32(hw, NGBE_RXBAH(rx_queue_id), *(reg++));
323962fc35e6SJiawen Wu 	wr32(hw, NGBE_RXCFG(rx_queue_id), *(reg++) & ~NGBE_RXCFG_ENA);
32403518df57SJiawen Wu }
3241001c7823SJiawen Wu 
3242001c7823SJiawen Wu void
3243001c7823SJiawen Wu ngbe_dev_save_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id)
3244001c7823SJiawen Wu {
3245001c7823SJiawen Wu 	u32 *reg = &hw->q_tx_regs[tx_queue_id * 8];
3246001c7823SJiawen Wu 	*(reg++) = rd32(hw, NGBE_TXBAL(tx_queue_id));
3247001c7823SJiawen Wu 	*(reg++) = rd32(hw, NGBE_TXBAH(tx_queue_id));
3248001c7823SJiawen Wu 	*(reg++) = rd32(hw, NGBE_TXCFG(tx_queue_id));
3249001c7823SJiawen Wu }
3250001c7823SJiawen Wu 
3251001c7823SJiawen Wu void
3252001c7823SJiawen Wu ngbe_dev_store_tx_queue(struct ngbe_hw *hw, uint16_t tx_queue_id)
3253001c7823SJiawen Wu {
3254001c7823SJiawen Wu 	u32 *reg = &hw->q_tx_regs[tx_queue_id * 8];
3255001c7823SJiawen Wu 	wr32(hw, NGBE_TXBAL(tx_queue_id), *(reg++));
3256001c7823SJiawen Wu 	wr32(hw, NGBE_TXBAH(tx_queue_id), *(reg++));
3257001c7823SJiawen Wu 	wr32(hw, NGBE_TXCFG(tx_queue_id), *(reg++) & ~NGBE_TXCFG_ENA);
3258001c7823SJiawen Wu }
3259001c7823SJiawen Wu 
3260001c7823SJiawen Wu /*
326162fc35e6SJiawen Wu  * Start Receive Units for specified queue.
326262fc35e6SJiawen Wu  */
326362fc35e6SJiawen Wu int
326462fc35e6SJiawen Wu ngbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
326562fc35e6SJiawen Wu {
326662fc35e6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
326762fc35e6SJiawen Wu 	struct ngbe_rx_queue *rxq;
326862fc35e6SJiawen Wu 	uint32_t rxdctl;
326962fc35e6SJiawen Wu 	int poll_ms;
327062fc35e6SJiawen Wu 
327162fc35e6SJiawen Wu 	PMD_INIT_FUNC_TRACE();
327262fc35e6SJiawen Wu 
327362fc35e6SJiawen Wu 	rxq = dev->data->rx_queues[rx_queue_id];
327462fc35e6SJiawen Wu 
327562fc35e6SJiawen Wu 	/* Allocate buffers for descriptor rings */
327662fc35e6SJiawen Wu 	if (ngbe_alloc_rx_queue_mbufs(rxq) != 0) {
327762fc35e6SJiawen Wu 		PMD_INIT_LOG(ERR, "Could not alloc mbuf for queue:%d",
327862fc35e6SJiawen Wu 			     rx_queue_id);
327962fc35e6SJiawen Wu 		return -1;
328062fc35e6SJiawen Wu 	}
328162fc35e6SJiawen Wu 	rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx));
328262fc35e6SJiawen Wu 	rxdctl |= NGBE_RXCFG_ENA;
328362fc35e6SJiawen Wu 	wr32(hw, NGBE_RXCFG(rxq->reg_idx), rxdctl);
328462fc35e6SJiawen Wu 
328562fc35e6SJiawen Wu 	/* Wait until Rx Enable ready */
328662fc35e6SJiawen Wu 	poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS;
328762fc35e6SJiawen Wu 	do {
328862fc35e6SJiawen Wu 		rte_delay_ms(1);
328962fc35e6SJiawen Wu 		rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx));
329062fc35e6SJiawen Wu 	} while (--poll_ms && !(rxdctl & NGBE_RXCFG_ENA));
329162fc35e6SJiawen Wu 	if (poll_ms == 0)
329262fc35e6SJiawen Wu 		PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", rx_queue_id);
329362fc35e6SJiawen Wu 	rte_wmb();
329462fc35e6SJiawen Wu 	wr32(hw, NGBE_RXRP(rxq->reg_idx), 0);
329562fc35e6SJiawen Wu 	wr32(hw, NGBE_RXWP(rxq->reg_idx), rxq->nb_rx_desc - 1);
329662fc35e6SJiawen Wu 	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
329762fc35e6SJiawen Wu 
329862fc35e6SJiawen Wu 	return 0;
329962fc35e6SJiawen Wu }
330062fc35e6SJiawen Wu 
330162fc35e6SJiawen Wu /*
330262fc35e6SJiawen Wu  * Stop Receive Units for specified queue.
330362fc35e6SJiawen Wu  */
330462fc35e6SJiawen Wu int
330562fc35e6SJiawen Wu ngbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
330662fc35e6SJiawen Wu {
330762fc35e6SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
330862fc35e6SJiawen Wu 	struct ngbe_adapter *adapter = ngbe_dev_adapter(dev);
330962fc35e6SJiawen Wu 	struct ngbe_rx_queue *rxq;
331062fc35e6SJiawen Wu 	uint32_t rxdctl;
331162fc35e6SJiawen Wu 	int poll_ms;
331262fc35e6SJiawen Wu 
331362fc35e6SJiawen Wu 	PMD_INIT_FUNC_TRACE();
331462fc35e6SJiawen Wu 
331562fc35e6SJiawen Wu 	rxq = dev->data->rx_queues[rx_queue_id];
331662fc35e6SJiawen Wu 
331762fc35e6SJiawen Wu 	ngbe_dev_save_rx_queue(hw, rxq->reg_idx);
331862fc35e6SJiawen Wu 	wr32m(hw, NGBE_RXCFG(rxq->reg_idx), NGBE_RXCFG_ENA, 0);
331962fc35e6SJiawen Wu 
332062fc35e6SJiawen Wu 	/* Wait until Rx Enable bit clear */
332162fc35e6SJiawen Wu 	poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS;
332262fc35e6SJiawen Wu 	do {
332362fc35e6SJiawen Wu 		rte_delay_ms(1);
332462fc35e6SJiawen Wu 		rxdctl = rd32(hw, NGBE_RXCFG(rxq->reg_idx));
332562fc35e6SJiawen Wu 	} while (--poll_ms && (rxdctl & NGBE_RXCFG_ENA));
332662fc35e6SJiawen Wu 	if (poll_ms == 0)
332762fc35e6SJiawen Wu 		PMD_INIT_LOG(ERR, "Could not disable Rx Queue %d", rx_queue_id);
332862fc35e6SJiawen Wu 
332962fc35e6SJiawen Wu 	rte_delay_us(RTE_NGBE_WAIT_100_US);
333062fc35e6SJiawen Wu 	ngbe_dev_store_rx_queue(hw, rxq->reg_idx);
333162fc35e6SJiawen Wu 
333262fc35e6SJiawen Wu 	ngbe_rx_queue_release_mbufs(rxq);
333362fc35e6SJiawen Wu 	ngbe_reset_rx_queue(adapter, rxq);
333462fc35e6SJiawen Wu 	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
333562fc35e6SJiawen Wu 
333662fc35e6SJiawen Wu 	return 0;
333762fc35e6SJiawen Wu }
333862fc35e6SJiawen Wu 
333962fc35e6SJiawen Wu /*
3340001c7823SJiawen Wu  * Start Transmit Units for specified queue.
3341001c7823SJiawen Wu  */
3342001c7823SJiawen Wu int
3343001c7823SJiawen Wu ngbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
3344001c7823SJiawen Wu {
3345001c7823SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
3346001c7823SJiawen Wu 	struct ngbe_tx_queue *txq;
3347001c7823SJiawen Wu 	uint32_t txdctl;
3348001c7823SJiawen Wu 	int poll_ms;
3349001c7823SJiawen Wu 
3350001c7823SJiawen Wu 	PMD_INIT_FUNC_TRACE();
3351001c7823SJiawen Wu 
3352001c7823SJiawen Wu 	txq = dev->data->tx_queues[tx_queue_id];
3353001c7823SJiawen Wu 	wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, NGBE_TXCFG_ENA);
3354001c7823SJiawen Wu 
3355001c7823SJiawen Wu 	/* Wait until Tx Enable ready */
3356001c7823SJiawen Wu 	poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS;
3357001c7823SJiawen Wu 	do {
3358001c7823SJiawen Wu 		rte_delay_ms(1);
3359001c7823SJiawen Wu 		txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx));
3360001c7823SJiawen Wu 	} while (--poll_ms && !(txdctl & NGBE_TXCFG_ENA));
3361001c7823SJiawen Wu 	if (poll_ms == 0)
3362001c7823SJiawen Wu 		PMD_INIT_LOG(ERR, "Could not enable Tx Queue %d",
3363001c7823SJiawen Wu 			     tx_queue_id);
3364001c7823SJiawen Wu 
3365001c7823SJiawen Wu 	rte_wmb();
3366001c7823SJiawen Wu 	wr32(hw, NGBE_TXWP(txq->reg_idx), txq->tx_tail);
3367001c7823SJiawen Wu 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
3368001c7823SJiawen Wu 
3369001c7823SJiawen Wu 	return 0;
3370001c7823SJiawen Wu }
3371001c7823SJiawen Wu 
3372001c7823SJiawen Wu /*
3373001c7823SJiawen Wu  * Stop Transmit Units for specified queue.
3374001c7823SJiawen Wu  */
3375001c7823SJiawen Wu int
3376001c7823SJiawen Wu ngbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
3377001c7823SJiawen Wu {
3378001c7823SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
3379001c7823SJiawen Wu 	struct ngbe_tx_queue *txq;
3380001c7823SJiawen Wu 	uint32_t txdctl;
3381001c7823SJiawen Wu 	uint32_t txtdh, txtdt;
3382001c7823SJiawen Wu 	int poll_ms;
3383001c7823SJiawen Wu 
3384001c7823SJiawen Wu 	PMD_INIT_FUNC_TRACE();
3385001c7823SJiawen Wu 
3386001c7823SJiawen Wu 	txq = dev->data->tx_queues[tx_queue_id];
3387001c7823SJiawen Wu 
3388001c7823SJiawen Wu 	/* Wait until Tx queue is empty */
3389001c7823SJiawen Wu 	poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS;
3390001c7823SJiawen Wu 	do {
3391001c7823SJiawen Wu 		rte_delay_us(RTE_NGBE_WAIT_100_US);
3392001c7823SJiawen Wu 		txtdh = rd32(hw, NGBE_TXRP(txq->reg_idx));
3393001c7823SJiawen Wu 		txtdt = rd32(hw, NGBE_TXWP(txq->reg_idx));
3394001c7823SJiawen Wu 	} while (--poll_ms && (txtdh != txtdt));
3395001c7823SJiawen Wu 	if (poll_ms == 0)
3396001c7823SJiawen Wu 		PMD_INIT_LOG(ERR, "Tx Queue %d is not empty when stopping.",
3397001c7823SJiawen Wu 			     tx_queue_id);
3398001c7823SJiawen Wu 
3399001c7823SJiawen Wu 	ngbe_dev_save_tx_queue(hw, txq->reg_idx);
3400001c7823SJiawen Wu 	wr32m(hw, NGBE_TXCFG(txq->reg_idx), NGBE_TXCFG_ENA, 0);
3401001c7823SJiawen Wu 
3402001c7823SJiawen Wu 	/* Wait until Tx Enable bit clear */
3403001c7823SJiawen Wu 	poll_ms = RTE_NGBE_REGISTER_POLL_WAIT_10_MS;
3404001c7823SJiawen Wu 	do {
3405001c7823SJiawen Wu 		rte_delay_ms(1);
3406001c7823SJiawen Wu 		txdctl = rd32(hw, NGBE_TXCFG(txq->reg_idx));
3407001c7823SJiawen Wu 	} while (--poll_ms && (txdctl & NGBE_TXCFG_ENA));
3408001c7823SJiawen Wu 	if (poll_ms == 0)
3409001c7823SJiawen Wu 		PMD_INIT_LOG(ERR, "Could not disable Tx Queue %d",
3410001c7823SJiawen Wu 			     tx_queue_id);
3411001c7823SJiawen Wu 
3412001c7823SJiawen Wu 	rte_delay_us(RTE_NGBE_WAIT_100_US);
3413001c7823SJiawen Wu 	ngbe_dev_store_tx_queue(hw, txq->reg_idx);
3414001c7823SJiawen Wu 
3415001c7823SJiawen Wu 	if (txq->ops != NULL) {
3416001c7823SJiawen Wu 		txq->ops->release_mbufs(txq);
3417001c7823SJiawen Wu 		txq->ops->reset(txq);
3418001c7823SJiawen Wu 	}
3419001c7823SJiawen Wu 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
3420001c7823SJiawen Wu 
3421001c7823SJiawen Wu 	return 0;
3422001c7823SJiawen Wu }
3423eec3e736SJiawen Wu 
3424eec3e736SJiawen Wu void
3425eec3e736SJiawen Wu ngbe_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
3426eec3e736SJiawen Wu 	struct rte_eth_rxq_info *qinfo)
3427eec3e736SJiawen Wu {
3428eec3e736SJiawen Wu 	struct ngbe_rx_queue *rxq;
3429eec3e736SJiawen Wu 
3430eec3e736SJiawen Wu 	rxq = dev->data->rx_queues[queue_id];
3431eec3e736SJiawen Wu 
3432eec3e736SJiawen Wu 	qinfo->mp = rxq->mb_pool;
3433eec3e736SJiawen Wu 	qinfo->scattered_rx = dev->data->scattered_rx;
3434eec3e736SJiawen Wu 	qinfo->nb_desc = rxq->nb_rx_desc;
3435eec3e736SJiawen Wu 
3436eec3e736SJiawen Wu 	qinfo->conf.rx_free_thresh = rxq->rx_free_thresh;
3437eec3e736SJiawen Wu 	qinfo->conf.rx_drop_en = rxq->drop_en;
3438eec3e736SJiawen Wu 	qinfo->conf.rx_deferred_start = rxq->rx_deferred_start;
3439eec3e736SJiawen Wu 	qinfo->conf.offloads = rxq->offloads;
3440eec3e736SJiawen Wu }
3441eec3e736SJiawen Wu 
3442eec3e736SJiawen Wu void
3443eec3e736SJiawen Wu ngbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
3444eec3e736SJiawen Wu 	struct rte_eth_txq_info *qinfo)
3445eec3e736SJiawen Wu {
3446eec3e736SJiawen Wu 	struct ngbe_tx_queue *txq;
3447eec3e736SJiawen Wu 
3448eec3e736SJiawen Wu 	txq = dev->data->tx_queues[queue_id];
3449eec3e736SJiawen Wu 
3450eec3e736SJiawen Wu 	qinfo->nb_desc = txq->nb_tx_desc;
3451eec3e736SJiawen Wu 
3452eec3e736SJiawen Wu 	qinfo->conf.tx_thresh.pthresh = txq->pthresh;
3453eec3e736SJiawen Wu 	qinfo->conf.tx_thresh.hthresh = txq->hthresh;
3454eec3e736SJiawen Wu 	qinfo->conf.tx_thresh.wthresh = txq->wthresh;
3455eec3e736SJiawen Wu 
3456eec3e736SJiawen Wu 	qinfo->conf.tx_free_thresh = txq->tx_free_thresh;
3457eec3e736SJiawen Wu 	qinfo->conf.offloads = txq->offloads;
3458eec3e736SJiawen Wu 	qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
3459eec3e736SJiawen Wu }
3460e94c20c3SJiawen Wu 
3461*711a06e8SZaiyu Wang /*
3462*711a06e8SZaiyu Wang  * [VF] Initializes Receive Unit.
3463*711a06e8SZaiyu Wang  */
3464*711a06e8SZaiyu Wang int
3465*711a06e8SZaiyu Wang ngbevf_dev_rx_init(struct rte_eth_dev *dev)
3466*711a06e8SZaiyu Wang {
3467*711a06e8SZaiyu Wang 	struct ngbe_hw     *hw;
3468*711a06e8SZaiyu Wang 	struct ngbe_rx_queue *rxq;
3469*711a06e8SZaiyu Wang 	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
3470*711a06e8SZaiyu Wang 	uint64_t bus_addr;
3471*711a06e8SZaiyu Wang 	uint32_t srrctl;
3472*711a06e8SZaiyu Wang 	uint16_t buf_size;
3473*711a06e8SZaiyu Wang 	uint16_t i;
3474*711a06e8SZaiyu Wang 	int ret;
3475*711a06e8SZaiyu Wang 
3476*711a06e8SZaiyu Wang 	PMD_INIT_FUNC_TRACE();
3477*711a06e8SZaiyu Wang 	hw = ngbe_dev_hw(dev);
3478*711a06e8SZaiyu Wang 
3479*711a06e8SZaiyu Wang 	if (rte_is_power_of_2(dev->data->nb_rx_queues) == 0) {
3480*711a06e8SZaiyu Wang 		PMD_INIT_LOG(ERR, "The number of Rx queue invalid, "
3481*711a06e8SZaiyu Wang 			"it should be power of 2");
3482*711a06e8SZaiyu Wang 		return -1;
3483*711a06e8SZaiyu Wang 	}
3484*711a06e8SZaiyu Wang 
3485*711a06e8SZaiyu Wang 	if (dev->data->nb_rx_queues > hw->mac.max_rx_queues) {
3486*711a06e8SZaiyu Wang 		PMD_INIT_LOG(ERR, "The number of Rx queue invalid, "
3487*711a06e8SZaiyu Wang 			"it should be equal to or less than %d",
3488*711a06e8SZaiyu Wang 			hw->mac.max_rx_queues);
3489*711a06e8SZaiyu Wang 		return -1;
3490*711a06e8SZaiyu Wang 	}
3491*711a06e8SZaiyu Wang 
3492*711a06e8SZaiyu Wang 	/*
3493*711a06e8SZaiyu Wang 	 * When the VF driver issues a NGBE_VF_RESET request, the PF driver
3494*711a06e8SZaiyu Wang 	 * disables the VF receipt of packets if the PF MTU is > 1500.
3495*711a06e8SZaiyu Wang 	 * This is done to deal with limitations that imposes
3496*711a06e8SZaiyu Wang 	 * the PF and all VFs to share the same MTU.
3497*711a06e8SZaiyu Wang 	 * Then, the PF driver enables again the VF receipt of packet when
3498*711a06e8SZaiyu Wang 	 * the VF driver issues a NGBE_VF_SET_LPE request.
3499*711a06e8SZaiyu Wang 	 * In the meantime, the VF device cannot be used, even if the VF driver
3500*711a06e8SZaiyu Wang 	 * and the Guest VM network stack are ready to accept packets with a
3501*711a06e8SZaiyu Wang 	 * size up to the PF MTU.
3502*711a06e8SZaiyu Wang 	 * As a work-around to this PF behaviour, force the call to
3503*711a06e8SZaiyu Wang 	 * ngbevf_rlpml_set_vf even if jumbo frames are not used. This way,
3504*711a06e8SZaiyu Wang 	 * VF packets received can work in all cases.
3505*711a06e8SZaiyu Wang 	 */
3506*711a06e8SZaiyu Wang 	if (ngbevf_rlpml_set_vf(hw,
3507*711a06e8SZaiyu Wang 	    (uint16_t)dev->data->mtu + NGBE_ETH_OVERHEAD)) {
3508*711a06e8SZaiyu Wang 		PMD_INIT_LOG(ERR, "Set max packet length to %d failed.",
3509*711a06e8SZaiyu Wang 			     dev->data->mtu + NGBE_ETH_OVERHEAD);
3510*711a06e8SZaiyu Wang 
3511*711a06e8SZaiyu Wang 		return -EINVAL;
3512*711a06e8SZaiyu Wang 	}
3513*711a06e8SZaiyu Wang 
3514*711a06e8SZaiyu Wang 	/*
3515*711a06e8SZaiyu Wang 	 * Assume no header split and no VLAN strip support
3516*711a06e8SZaiyu Wang 	 * on any Rx queue first .
3517*711a06e8SZaiyu Wang 	 */
3518*711a06e8SZaiyu Wang 	rxmode->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
3519*711a06e8SZaiyu Wang 	/* Setup RX queues */
3520*711a06e8SZaiyu Wang 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
3521*711a06e8SZaiyu Wang 		rxq = dev->data->rx_queues[i];
3522*711a06e8SZaiyu Wang 
3523*711a06e8SZaiyu Wang 		/* Allocate buffers for descriptor rings */
3524*711a06e8SZaiyu Wang 		ret = ngbe_alloc_rx_queue_mbufs(rxq);
3525*711a06e8SZaiyu Wang 		if (ret)
3526*711a06e8SZaiyu Wang 			return ret;
3527*711a06e8SZaiyu Wang 
3528*711a06e8SZaiyu Wang 		/* Setup the Base and Length of the Rx Descriptor Rings */
3529*711a06e8SZaiyu Wang 		bus_addr = rxq->rx_ring_phys_addr;
3530*711a06e8SZaiyu Wang 
3531*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXBAL(i),
3532*711a06e8SZaiyu Wang 				(uint32_t)(bus_addr & BIT_MASK32));
3533*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXBAH(i),
3534*711a06e8SZaiyu Wang 				(uint32_t)(bus_addr >> 32));
3535*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXRP(i), 0);
3536*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXWP(i), 0);
3537*711a06e8SZaiyu Wang 
3538*711a06e8SZaiyu Wang 		/* Configure the RXCFG register */
3539*711a06e8SZaiyu Wang 		srrctl = NGBE_RXCFG_RNGLEN(rxq->nb_rx_desc);
3540*711a06e8SZaiyu Wang 
3541*711a06e8SZaiyu Wang 		/* Set if packets are dropped when no descriptors available */
3542*711a06e8SZaiyu Wang 		if (rxq->drop_en)
3543*711a06e8SZaiyu Wang 			srrctl |= NGBE_RXCFG_DROP;
3544*711a06e8SZaiyu Wang 
3545*711a06e8SZaiyu Wang 		/*
3546*711a06e8SZaiyu Wang 		 * Configure the RX buffer size in the PKTLEN field of
3547*711a06e8SZaiyu Wang 		 * the RXCFG register of the queue.
3548*711a06e8SZaiyu Wang 		 * The value is in 1 KB resolution. Valid values can be from
3549*711a06e8SZaiyu Wang 		 * 1 KB to 16 KB.
3550*711a06e8SZaiyu Wang 		 */
3551*711a06e8SZaiyu Wang 		buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) -
3552*711a06e8SZaiyu Wang 			RTE_PKTMBUF_HEADROOM);
3553*711a06e8SZaiyu Wang 		buf_size = ROUND_UP(buf_size, 1 << 10);
3554*711a06e8SZaiyu Wang 		srrctl |= NGBE_RXCFG_PKTLEN(buf_size);
3555*711a06e8SZaiyu Wang 
3556*711a06e8SZaiyu Wang 		/*
3557*711a06e8SZaiyu Wang 		 * VF modification to write virtual function RXCFG register
3558*711a06e8SZaiyu Wang 		 */
3559*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXCFG(i), srrctl);
3560*711a06e8SZaiyu Wang 
3561*711a06e8SZaiyu Wang 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER ||
3562*711a06e8SZaiyu Wang 		    /* It adds dual VLAN length for supporting dual VLAN */
3563*711a06e8SZaiyu Wang 		    (dev->data->mtu + NGBE_ETH_OVERHEAD +
3564*711a06e8SZaiyu Wang 				2 * RTE_VLAN_HLEN) > buf_size) {
3565*711a06e8SZaiyu Wang 			if (!dev->data->scattered_rx)
3566*711a06e8SZaiyu Wang 				PMD_INIT_LOG(DEBUG, "forcing scatter mode");
3567*711a06e8SZaiyu Wang 			dev->data->scattered_rx = 1;
3568*711a06e8SZaiyu Wang 		}
3569*711a06e8SZaiyu Wang 
3570*711a06e8SZaiyu Wang 		if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
3571*711a06e8SZaiyu Wang 			rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
3572*711a06e8SZaiyu Wang 	}
3573*711a06e8SZaiyu Wang 
3574*711a06e8SZaiyu Wang 	ngbe_set_rx_function(dev);
3575*711a06e8SZaiyu Wang 
3576*711a06e8SZaiyu Wang 	return 0;
3577*711a06e8SZaiyu Wang }
3578*711a06e8SZaiyu Wang 
3579*711a06e8SZaiyu Wang /*
3580*711a06e8SZaiyu Wang  * [VF] Initializes Transmit Unit.
3581*711a06e8SZaiyu Wang  */
3582*711a06e8SZaiyu Wang void
3583*711a06e8SZaiyu Wang ngbevf_dev_tx_init(struct rte_eth_dev *dev)
3584*711a06e8SZaiyu Wang {
3585*711a06e8SZaiyu Wang 	struct ngbe_hw     *hw;
3586*711a06e8SZaiyu Wang 	struct ngbe_tx_queue *txq;
3587*711a06e8SZaiyu Wang 	uint64_t bus_addr;
3588*711a06e8SZaiyu Wang 	uint16_t i;
3589*711a06e8SZaiyu Wang 
3590*711a06e8SZaiyu Wang 	PMD_INIT_FUNC_TRACE();
3591*711a06e8SZaiyu Wang 	hw = ngbe_dev_hw(dev);
3592*711a06e8SZaiyu Wang 
3593*711a06e8SZaiyu Wang 	/* Setup the Base and Length of the Tx Descriptor Rings */
3594*711a06e8SZaiyu Wang 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3595*711a06e8SZaiyu Wang 		txq = dev->data->tx_queues[i];
3596*711a06e8SZaiyu Wang 		bus_addr = txq->tx_ring_phys_addr;
3597*711a06e8SZaiyu Wang 		wr32(hw, NGBE_TXBAL(i),
3598*711a06e8SZaiyu Wang 				(uint32_t)(bus_addr & BIT_MASK32));
3599*711a06e8SZaiyu Wang 		wr32(hw, NGBE_TXBAH(i),
3600*711a06e8SZaiyu Wang 				(uint32_t)(bus_addr >> 32));
3601*711a06e8SZaiyu Wang 		wr32m(hw, NGBE_TXCFG(i), NGBE_TXCFG_BUFLEN_MASK,
3602*711a06e8SZaiyu Wang 			NGBE_TXCFG_BUFLEN(txq->nb_tx_desc));
3603*711a06e8SZaiyu Wang 		/* Setup the HW Tx Head and TX Tail descriptor pointers */
3604*711a06e8SZaiyu Wang 		wr32(hw, NGBE_TXRP(i), 0);
3605*711a06e8SZaiyu Wang 		wr32(hw, NGBE_TXWP(i), 0);
3606*711a06e8SZaiyu Wang 	}
3607*711a06e8SZaiyu Wang }
3608*711a06e8SZaiyu Wang 
3609*711a06e8SZaiyu Wang /*
3610*711a06e8SZaiyu Wang  * [VF] Start Transmit and Receive Units.
3611*711a06e8SZaiyu Wang  */
3612*711a06e8SZaiyu Wang void
3613*711a06e8SZaiyu Wang ngbevf_dev_rxtx_start(struct rte_eth_dev *dev)
3614*711a06e8SZaiyu Wang {
3615*711a06e8SZaiyu Wang 	struct ngbe_hw     *hw;
3616*711a06e8SZaiyu Wang 	struct ngbe_tx_queue *txq;
3617*711a06e8SZaiyu Wang 	struct ngbe_rx_queue *rxq;
3618*711a06e8SZaiyu Wang 	uint32_t txdctl;
3619*711a06e8SZaiyu Wang 	uint32_t rxdctl;
3620*711a06e8SZaiyu Wang 	uint16_t i;
3621*711a06e8SZaiyu Wang 	int poll_ms;
3622*711a06e8SZaiyu Wang 
3623*711a06e8SZaiyu Wang 	PMD_INIT_FUNC_TRACE();
3624*711a06e8SZaiyu Wang 	hw = ngbe_dev_hw(dev);
3625*711a06e8SZaiyu Wang 
3626*711a06e8SZaiyu Wang 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3627*711a06e8SZaiyu Wang 		txq = dev->data->tx_queues[i];
3628*711a06e8SZaiyu Wang 		/* Setup Transmit Threshold Registers */
3629*711a06e8SZaiyu Wang 		wr32m(hw, NGBE_TXCFG(txq->reg_idx),
3630*711a06e8SZaiyu Wang 		      NGBE_TXCFG_HTHRESH_MASK |
3631*711a06e8SZaiyu Wang 		      NGBE_TXCFG_WTHRESH_MASK,
3632*711a06e8SZaiyu Wang 		      NGBE_TXCFG_HTHRESH(txq->hthresh) |
3633*711a06e8SZaiyu Wang 		      NGBE_TXCFG_WTHRESH(txq->wthresh));
3634*711a06e8SZaiyu Wang 	}
3635*711a06e8SZaiyu Wang 
3636*711a06e8SZaiyu Wang 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
3637*711a06e8SZaiyu Wang 		wr32m(hw, NGBE_TXCFG(i), NGBE_TXCFG_ENA, NGBE_TXCFG_ENA);
3638*711a06e8SZaiyu Wang 
3639*711a06e8SZaiyu Wang 		poll_ms = 10;
3640*711a06e8SZaiyu Wang 		/* Wait until TX Enable ready */
3641*711a06e8SZaiyu Wang 		do {
3642*711a06e8SZaiyu Wang 			rte_delay_ms(1);
3643*711a06e8SZaiyu Wang 			txdctl = rd32(hw, NGBE_TXCFG(i));
3644*711a06e8SZaiyu Wang 		} while (--poll_ms && !(txdctl & NGBE_TXCFG_ENA));
3645*711a06e8SZaiyu Wang 		if (!poll_ms)
3646*711a06e8SZaiyu Wang 			PMD_INIT_LOG(ERR, "Could not enable Tx Queue %d", i);
3647*711a06e8SZaiyu Wang 		else
3648*711a06e8SZaiyu Wang 			dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
3649*711a06e8SZaiyu Wang 	}
3650*711a06e8SZaiyu Wang 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
3651*711a06e8SZaiyu Wang 		rxq = dev->data->rx_queues[i];
3652*711a06e8SZaiyu Wang 
3653*711a06e8SZaiyu Wang 		wr32m(hw, NGBE_RXCFG(i), NGBE_RXCFG_ENA, NGBE_RXCFG_ENA);
3654*711a06e8SZaiyu Wang 
3655*711a06e8SZaiyu Wang 		/* Wait until RX Enable ready */
3656*711a06e8SZaiyu Wang 		poll_ms = 10;
3657*711a06e8SZaiyu Wang 		do {
3658*711a06e8SZaiyu Wang 			rte_delay_ms(1);
3659*711a06e8SZaiyu Wang 			rxdctl = rd32(hw, NGBE_RXCFG(i));
3660*711a06e8SZaiyu Wang 		} while (--poll_ms && !(rxdctl & NGBE_RXCFG_ENA));
3661*711a06e8SZaiyu Wang 		if (!poll_ms)
3662*711a06e8SZaiyu Wang 			PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", i);
3663*711a06e8SZaiyu Wang 		else
3664*711a06e8SZaiyu Wang 			dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
3665*711a06e8SZaiyu Wang 		rte_wmb();
3666*711a06e8SZaiyu Wang 		wr32(hw, NGBE_RXWP(i), rxq->nb_rx_desc - 1);
3667*711a06e8SZaiyu Wang 	}
3668*711a06e8SZaiyu Wang }
3669*711a06e8SZaiyu Wang 
3670e94c20c3SJiawen Wu /* Stubs needed for linkage when RTE_ARCH_PPC_64, RTE_ARCH_RISCV or
3671e94c20c3SJiawen Wu  * RTE_ARCH_LOONGARCH is set.
3672e94c20c3SJiawen Wu  */
3673e94c20c3SJiawen Wu #if defined(RTE_ARCH_PPC_64) || defined(RTE_ARCH_RISCV) || \
3674e94c20c3SJiawen Wu 	defined(RTE_ARCH_LOONGARCH)
3675e94c20c3SJiawen Wu int
3676e94c20c3SJiawen Wu ngbe_rx_vec_dev_conf_condition_check(__rte_unused struct rte_eth_dev *dev)
3677e94c20c3SJiawen Wu {
3678e94c20c3SJiawen Wu 	return -1;
3679e94c20c3SJiawen Wu }
3680e94c20c3SJiawen Wu 
3681e94c20c3SJiawen Wu uint16_t
3682e94c20c3SJiawen Wu ngbe_recv_pkts_vec(__rte_unused void *rx_queue,
3683e94c20c3SJiawen Wu 		   __rte_unused struct rte_mbuf **rx_pkts,
3684e94c20c3SJiawen Wu 		   __rte_unused uint16_t nb_pkts)
3685e94c20c3SJiawen Wu {
3686e94c20c3SJiawen Wu 	return 0;
3687e94c20c3SJiawen Wu }
3688e94c20c3SJiawen Wu 
3689e94c20c3SJiawen Wu uint16_t
3690e94c20c3SJiawen Wu ngbe_recv_scattered_pkts_vec(__rte_unused void *rx_queue,
3691e94c20c3SJiawen Wu 			     __rte_unused struct rte_mbuf **rx_pkts,
3692e94c20c3SJiawen Wu 			     __rte_unused uint16_t nb_pkts)
3693e94c20c3SJiawen Wu {
3694e94c20c3SJiawen Wu 	return 0;
3695e94c20c3SJiawen Wu }
3696e94c20c3SJiawen Wu 
3697e94c20c3SJiawen Wu int
3698e94c20c3SJiawen Wu ngbe_rxq_vec_setup(__rte_unused struct ngbe_rx_queue *rxq)
3699e94c20c3SJiawen Wu {
3700e94c20c3SJiawen Wu 	return -1;
3701e94c20c3SJiawen Wu }
3702e94c20c3SJiawen Wu 
3703e94c20c3SJiawen Wu uint16_t
3704e94c20c3SJiawen Wu ngbe_xmit_fixed_burst_vec(__rte_unused void *tx_queue,
3705e94c20c3SJiawen Wu 			  __rte_unused struct rte_mbuf **tx_pkts,
3706e94c20c3SJiawen Wu 			  __rte_unused uint16_t nb_pkts)
3707e94c20c3SJiawen Wu {
3708e94c20c3SJiawen Wu 	return 0;
3709e94c20c3SJiawen Wu }
3710e94c20c3SJiawen Wu 
3711e94c20c3SJiawen Wu int
3712e94c20c3SJiawen Wu ngbe_txq_vec_setup(__rte_unused struct ngbe_tx_queue *txq)
3713e94c20c3SJiawen Wu {
3714e94c20c3SJiawen Wu 	return -1;
3715e94c20c3SJiawen Wu }
3716e94c20c3SJiawen Wu 
3717e94c20c3SJiawen Wu void
3718e94c20c3SJiawen Wu ngbe_rx_queue_release_mbufs_vec(__rte_unused struct ngbe_rx_queue *rxq)
3719e94c20c3SJiawen Wu {
3720e94c20c3SJiawen Wu }
3721e94c20c3SJiawen Wu #endif
3722