xref: /dpdk/drivers/net/mlx5/mlx5_rxtx.c (revision 9514fa2d1adb3d18ce803c77c8df90c8e2d8bd11)
12e22920bSAdrien Mazarguil /*-
22e22920bSAdrien Mazarguil  *   BSD LICENSE
32e22920bSAdrien Mazarguil  *
42e22920bSAdrien Mazarguil  *   Copyright 2015 6WIND S.A.
52e22920bSAdrien Mazarguil  *   Copyright 2015 Mellanox.
62e22920bSAdrien Mazarguil  *
72e22920bSAdrien Mazarguil  *   Redistribution and use in source and binary forms, with or without
82e22920bSAdrien Mazarguil  *   modification, are permitted provided that the following conditions
92e22920bSAdrien Mazarguil  *   are met:
102e22920bSAdrien Mazarguil  *
112e22920bSAdrien Mazarguil  *     * Redistributions of source code must retain the above copyright
122e22920bSAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer.
132e22920bSAdrien Mazarguil  *     * Redistributions in binary form must reproduce the above copyright
142e22920bSAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer in
152e22920bSAdrien Mazarguil  *       the documentation and/or other materials provided with the
162e22920bSAdrien Mazarguil  *       distribution.
172e22920bSAdrien Mazarguil  *     * Neither the name of 6WIND S.A. nor the names of its
182e22920bSAdrien Mazarguil  *       contributors may be used to endorse or promote products derived
192e22920bSAdrien Mazarguil  *       from this software without specific prior written permission.
202e22920bSAdrien Mazarguil  *
212e22920bSAdrien Mazarguil  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
222e22920bSAdrien Mazarguil  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
232e22920bSAdrien Mazarguil  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
242e22920bSAdrien Mazarguil  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
252e22920bSAdrien Mazarguil  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
262e22920bSAdrien Mazarguil  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
272e22920bSAdrien Mazarguil  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
282e22920bSAdrien Mazarguil  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
292e22920bSAdrien Mazarguil  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
302e22920bSAdrien Mazarguil  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
312e22920bSAdrien Mazarguil  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322e22920bSAdrien Mazarguil  */
332e22920bSAdrien Mazarguil 
342e22920bSAdrien Mazarguil #include <assert.h>
352e22920bSAdrien Mazarguil #include <stdint.h>
362e22920bSAdrien Mazarguil #include <string.h>
372e22920bSAdrien Mazarguil #include <stdlib.h>
382e22920bSAdrien Mazarguil 
392e22920bSAdrien Mazarguil /* Verbs header. */
402e22920bSAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
412e22920bSAdrien Mazarguil #ifdef PEDANTIC
42fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
432e22920bSAdrien Mazarguil #endif
442e22920bSAdrien Mazarguil #include <infiniband/verbs.h>
456218063bSNélio Laranjeiro #include <infiniband/mlx5_hw.h>
466218063bSNélio Laranjeiro #include <infiniband/arch.h>
472e22920bSAdrien Mazarguil #ifdef PEDANTIC
48fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
492e22920bSAdrien Mazarguil #endif
502e22920bSAdrien Mazarguil 
512e22920bSAdrien Mazarguil /* DPDK headers don't like -pedantic. */
522e22920bSAdrien Mazarguil #ifdef PEDANTIC
53fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
542e22920bSAdrien Mazarguil #endif
552e22920bSAdrien Mazarguil #include <rte_mbuf.h>
562e22920bSAdrien Mazarguil #include <rte_mempool.h>
572e22920bSAdrien Mazarguil #include <rte_prefetch.h>
582e22920bSAdrien Mazarguil #include <rte_common.h>
592e22920bSAdrien Mazarguil #include <rte_branch_prediction.h>
606218063bSNélio Laranjeiro #include <rte_ether.h>
612e22920bSAdrien Mazarguil #ifdef PEDANTIC
62fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
632e22920bSAdrien Mazarguil #endif
642e22920bSAdrien Mazarguil 
652e22920bSAdrien Mazarguil #include "mlx5.h"
662e22920bSAdrien Mazarguil #include "mlx5_utils.h"
672e22920bSAdrien Mazarguil #include "mlx5_rxtx.h"
68f3db9489SYaacov Hazan #include "mlx5_autoconf.h"
692e22920bSAdrien Mazarguil #include "mlx5_defs.h"
706218063bSNélio Laranjeiro #include "mlx5_prm.h"
716218063bSNélio Laranjeiro 
72ff1807a3SNélio Laranjeiro static inline int
73ff1807a3SNélio Laranjeiro check_cqe(volatile struct mlx5_cqe *cqe,
74ff1807a3SNélio Laranjeiro 	  unsigned int cqes_n, const uint16_t ci)
75ff1807a3SNélio Laranjeiro 	  __attribute__((always_inline));
76ff1807a3SNélio Laranjeiro 
7761b09ae4SNélio Laranjeiro static inline void
7861b09ae4SNélio Laranjeiro txq_complete(struct txq *txq) __attribute__((always_inline));
7961b09ae4SNélio Laranjeiro 
80ff1807a3SNélio Laranjeiro static inline uint32_t
81ff1807a3SNélio Laranjeiro txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
82ff1807a3SNélio Laranjeiro 	__attribute__((always_inline));
83ff1807a3SNélio Laranjeiro 
84ff1807a3SNélio Laranjeiro static inline void
8530807f62SNélio Laranjeiro mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
8630807f62SNélio Laranjeiro 	__attribute__((always_inline));
87ff1807a3SNélio Laranjeiro 
88ff1807a3SNélio Laranjeiro static inline uint32_t
89ff1807a3SNélio Laranjeiro rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
90ff1807a3SNélio Laranjeiro 	__attribute__((always_inline));
91ff1807a3SNélio Laranjeiro 
92ff1807a3SNélio Laranjeiro static inline int
93ff1807a3SNélio Laranjeiro mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe *cqe,
94ff1807a3SNélio Laranjeiro 		 uint16_t cqe_cnt, uint32_t *rss_hash)
95ff1807a3SNélio Laranjeiro 		 __attribute__((always_inline));
96ff1807a3SNélio Laranjeiro 
97ff1807a3SNélio Laranjeiro static inline uint32_t
98ff1807a3SNélio Laranjeiro rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe *cqe)
99ff1807a3SNélio Laranjeiro 		   __attribute__((always_inline));
100ff1807a3SNélio Laranjeiro 
10199c12dccSNélio Laranjeiro #ifndef NDEBUG
10299c12dccSNélio Laranjeiro 
10399c12dccSNélio Laranjeiro /**
10499c12dccSNélio Laranjeiro  * Verify or set magic value in CQE.
10599c12dccSNélio Laranjeiro  *
10699c12dccSNélio Laranjeiro  * @param cqe
10799c12dccSNélio Laranjeiro  *   Pointer to CQE.
10899c12dccSNélio Laranjeiro  *
10999c12dccSNélio Laranjeiro  * @return
11099c12dccSNélio Laranjeiro  *   0 the first time.
11199c12dccSNélio Laranjeiro  */
11299c12dccSNélio Laranjeiro static inline int
11397267b8eSNelio Laranjeiro check_cqe_seen(volatile struct mlx5_cqe *cqe)
11499c12dccSNélio Laranjeiro {
11599c12dccSNélio Laranjeiro 	static const uint8_t magic[] = "seen";
116ea3bc3b1SNélio Laranjeiro 	volatile uint8_t (*buf)[sizeof(cqe->rsvd0)] = &cqe->rsvd0;
11799c12dccSNélio Laranjeiro 	int ret = 1;
11899c12dccSNélio Laranjeiro 	unsigned int i;
11999c12dccSNélio Laranjeiro 
12099c12dccSNélio Laranjeiro 	for (i = 0; i < sizeof(magic) && i < sizeof(*buf); ++i)
12199c12dccSNélio Laranjeiro 		if (!ret || (*buf)[i] != magic[i]) {
12299c12dccSNélio Laranjeiro 			ret = 0;
12399c12dccSNélio Laranjeiro 			(*buf)[i] = magic[i];
12499c12dccSNélio Laranjeiro 		}
12599c12dccSNélio Laranjeiro 	return ret;
12699c12dccSNélio Laranjeiro }
12799c12dccSNélio Laranjeiro 
12899c12dccSNélio Laranjeiro #endif /* NDEBUG */
1296218063bSNélio Laranjeiro 
13099c12dccSNélio Laranjeiro /**
13199c12dccSNélio Laranjeiro  * Check whether CQE is valid.
13299c12dccSNélio Laranjeiro  *
13399c12dccSNélio Laranjeiro  * @param cqe
13499c12dccSNélio Laranjeiro  *   Pointer to CQE.
13599c12dccSNélio Laranjeiro  * @param cqes_n
13699c12dccSNélio Laranjeiro  *   Size of completion queue.
13799c12dccSNélio Laranjeiro  * @param ci
13899c12dccSNélio Laranjeiro  *   Consumer index.
13999c12dccSNélio Laranjeiro  *
14099c12dccSNélio Laranjeiro  * @return
14199c12dccSNélio Laranjeiro  *   0 on success, 1 on failure.
14299c12dccSNélio Laranjeiro  */
14399c12dccSNélio Laranjeiro static inline int
14497267b8eSNelio Laranjeiro check_cqe(volatile struct mlx5_cqe *cqe,
14599c12dccSNélio Laranjeiro 	  unsigned int cqes_n, const uint16_t ci)
1466218063bSNélio Laranjeiro {
14799c12dccSNélio Laranjeiro 	uint16_t idx = ci & cqes_n;
14899c12dccSNélio Laranjeiro 	uint8_t op_own = cqe->op_own;
14999c12dccSNélio Laranjeiro 	uint8_t op_owner = MLX5_CQE_OWNER(op_own);
15099c12dccSNélio Laranjeiro 	uint8_t op_code = MLX5_CQE_OPCODE(op_own);
1516218063bSNélio Laranjeiro 
15299c12dccSNélio Laranjeiro 	if (unlikely((op_owner != (!!(idx))) || (op_code == MLX5_CQE_INVALID)))
15399c12dccSNélio Laranjeiro 		return 1; /* No CQE. */
15499c12dccSNélio Laranjeiro #ifndef NDEBUG
15599c12dccSNélio Laranjeiro 	if ((op_code == MLX5_CQE_RESP_ERR) ||
15699c12dccSNélio Laranjeiro 	    (op_code == MLX5_CQE_REQ_ERR)) {
15799c12dccSNélio Laranjeiro 		volatile struct mlx5_err_cqe *err_cqe = (volatile void *)cqe;
15899c12dccSNélio Laranjeiro 		uint8_t syndrome = err_cqe->syndrome;
15999c12dccSNélio Laranjeiro 
16099c12dccSNélio Laranjeiro 		if ((syndrome == MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR) ||
16199c12dccSNélio Laranjeiro 		    (syndrome == MLX5_CQE_SYNDROME_REMOTE_ABORTED_ERR))
16299c12dccSNélio Laranjeiro 			return 0;
16397267b8eSNelio Laranjeiro 		if (!check_cqe_seen(cqe))
16499c12dccSNélio Laranjeiro 			ERROR("unexpected CQE error %u (0x%02x)"
16599c12dccSNélio Laranjeiro 			      " syndrome 0x%02x",
16699c12dccSNélio Laranjeiro 			      op_code, op_code, syndrome);
16799c12dccSNélio Laranjeiro 		return 1;
16899c12dccSNélio Laranjeiro 	} else if ((op_code != MLX5_CQE_RESP_SEND) &&
16999c12dccSNélio Laranjeiro 		   (op_code != MLX5_CQE_REQ)) {
17097267b8eSNelio Laranjeiro 		if (!check_cqe_seen(cqe))
17199c12dccSNélio Laranjeiro 			ERROR("unexpected CQE opcode %u (0x%02x)",
17299c12dccSNélio Laranjeiro 			      op_code, op_code);
17399c12dccSNélio Laranjeiro 		return 1;
1746218063bSNélio Laranjeiro 	}
17599c12dccSNélio Laranjeiro #endif /* NDEBUG */
17699c12dccSNélio Laranjeiro 	return 0;
1776218063bSNélio Laranjeiro }
1782e22920bSAdrien Mazarguil 
179fdcb0f53SNélio Laranjeiro /**
180fdcb0f53SNélio Laranjeiro  * Return the address of the WQE.
181fdcb0f53SNélio Laranjeiro  *
182fdcb0f53SNélio Laranjeiro  * @param txq
183fdcb0f53SNélio Laranjeiro  *   Pointer to TX queue structure.
184fdcb0f53SNélio Laranjeiro  * @param  wqe_ci
185fdcb0f53SNélio Laranjeiro  *   WQE consumer index.
186fdcb0f53SNélio Laranjeiro  *
187fdcb0f53SNélio Laranjeiro  * @return
188fdcb0f53SNélio Laranjeiro  *   WQE address.
189fdcb0f53SNélio Laranjeiro  */
190fdcb0f53SNélio Laranjeiro static inline uintptr_t *
191fdcb0f53SNélio Laranjeiro tx_mlx5_wqe(struct txq *txq, uint16_t ci)
192fdcb0f53SNélio Laranjeiro {
193fdcb0f53SNélio Laranjeiro 	ci &= ((1 << txq->wqe_n) - 1);
194fdcb0f53SNélio Laranjeiro 	return (uintptr_t *)((uintptr_t)txq->wqes + ci * MLX5_WQE_SIZE);
195fdcb0f53SNélio Laranjeiro }
196fdcb0f53SNélio Laranjeiro 
1972e22920bSAdrien Mazarguil /**
1982e22920bSAdrien Mazarguil  * Manage TX completions.
1992e22920bSAdrien Mazarguil  *
2002e22920bSAdrien Mazarguil  * When sending a burst, mlx5_tx_burst() posts several WRs.
2012e22920bSAdrien Mazarguil  *
2022e22920bSAdrien Mazarguil  * @param txq
2032e22920bSAdrien Mazarguil  *   Pointer to TX queue structure.
2042e22920bSAdrien Mazarguil  */
205a6ca35aaSNélio Laranjeiro static inline void
2062e22920bSAdrien Mazarguil txq_complete(struct txq *txq)
2072e22920bSAdrien Mazarguil {
208b4b12e55SNélio Laranjeiro 	const unsigned int elts_n = 1 << txq->elts_n;
209e2f116eeSNélio Laranjeiro 	const unsigned int cqe_n = 1 << txq->cqe_n;
21099c12dccSNélio Laranjeiro 	const unsigned int cqe_cnt = cqe_n - 1;
2111d88ba17SNélio Laranjeiro 	uint16_t elts_free = txq->elts_tail;
2121d88ba17SNélio Laranjeiro 	uint16_t elts_tail;
2131d88ba17SNélio Laranjeiro 	uint16_t cq_ci = txq->cq_ci;
21497267b8eSNelio Laranjeiro 	volatile struct mlx5_cqe *cqe = NULL;
215fdcb0f53SNélio Laranjeiro 	volatile struct mlx5_wqe_ctrl *ctrl;
2162e22920bSAdrien Mazarguil 
21799c12dccSNélio Laranjeiro 	do {
21897267b8eSNelio Laranjeiro 		volatile struct mlx5_cqe *tmp;
2191d88ba17SNélio Laranjeiro 
22097267b8eSNelio Laranjeiro 		tmp = &(*txq->cqes)[cq_ci & cqe_cnt];
22197267b8eSNelio Laranjeiro 		if (check_cqe(tmp, cqe_n, cq_ci))
2221d88ba17SNélio Laranjeiro 			break;
223c305090bSAdrien Mazarguil 		cqe = tmp;
22499c12dccSNélio Laranjeiro #ifndef NDEBUG
22599c12dccSNélio Laranjeiro 		if (MLX5_CQE_FORMAT(cqe->op_own) == MLX5_COMPRESSED) {
22697267b8eSNelio Laranjeiro 			if (!check_cqe_seen(cqe))
22799c12dccSNélio Laranjeiro 				ERROR("unexpected compressed CQE, TX stopped");
22899c12dccSNélio Laranjeiro 			return;
2292e22920bSAdrien Mazarguil 		}
23099c12dccSNélio Laranjeiro 		if ((MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_RESP_ERR) ||
23199c12dccSNélio Laranjeiro 		    (MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_REQ_ERR)) {
23297267b8eSNelio Laranjeiro 			if (!check_cqe_seen(cqe))
23399c12dccSNélio Laranjeiro 				ERROR("unexpected error CQE, TX stopped");
23499c12dccSNélio Laranjeiro 			return;
23599c12dccSNélio Laranjeiro 		}
23699c12dccSNélio Laranjeiro #endif /* NDEBUG */
23799c12dccSNélio Laranjeiro 		++cq_ci;
23899c12dccSNélio Laranjeiro 	} while (1);
239c305090bSAdrien Mazarguil 	if (unlikely(cqe == NULL))
2401d88ba17SNélio Laranjeiro 		return;
241f04f1d51SNélio Laranjeiro 	txq->wqe_pi = ntohs(cqe->wqe_counter);
242fdcb0f53SNélio Laranjeiro 	ctrl = (volatile struct mlx5_wqe_ctrl *)
243f04f1d51SNélio Laranjeiro 		tx_mlx5_wqe(txq, txq->wqe_pi);
244fdcb0f53SNélio Laranjeiro 	elts_tail = ctrl->ctrl3;
245a821d09dSNélio Laranjeiro 	assert(elts_tail < (1 << txq->wqe_n));
2461d88ba17SNélio Laranjeiro 	/* Free buffers. */
247c305090bSAdrien Mazarguil 	while (elts_free != elts_tail) {
2481d88ba17SNélio Laranjeiro 		struct rte_mbuf *elt = (*txq->elts)[elts_free];
249a859e8a9SNelio Laranjeiro 		unsigned int elts_free_next =
2501d88ba17SNélio Laranjeiro 			(elts_free + 1) & (elts_n - 1);
2511d88ba17SNélio Laranjeiro 		struct rte_mbuf *elt_next = (*txq->elts)[elts_free_next];
252a859e8a9SNelio Laranjeiro 
253b185e63fSAdrien Mazarguil #ifndef NDEBUG
254b185e63fSAdrien Mazarguil 		/* Poisoning. */
2551d88ba17SNélio Laranjeiro 		memset(&(*txq->elts)[elts_free],
2561d88ba17SNélio Laranjeiro 		       0x66,
2571d88ba17SNélio Laranjeiro 		       sizeof((*txq->elts)[elts_free]));
258b185e63fSAdrien Mazarguil #endif
2591d88ba17SNélio Laranjeiro 		RTE_MBUF_PREFETCH_TO_FREE(elt_next);
2601d88ba17SNélio Laranjeiro 		/* Only one segment needs to be freed. */
2611d88ba17SNélio Laranjeiro 		rte_pktmbuf_free_seg(elt);
262a859e8a9SNelio Laranjeiro 		elts_free = elts_free_next;
263c305090bSAdrien Mazarguil 	}
2641d88ba17SNélio Laranjeiro 	txq->cq_ci = cq_ci;
2652e22920bSAdrien Mazarguil 	txq->elts_tail = elts_tail;
2661d88ba17SNélio Laranjeiro 	/* Update the consumer index. */
2671d88ba17SNélio Laranjeiro 	rte_wmb();
2681d88ba17SNélio Laranjeiro 	*txq->cq_db = htonl(cq_ci);
2692e22920bSAdrien Mazarguil }
2702e22920bSAdrien Mazarguil 
2712e22920bSAdrien Mazarguil /**
2728340392eSAdrien Mazarguil  * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which
2738340392eSAdrien Mazarguil  * the cloned mbuf is allocated is returned instead.
2748340392eSAdrien Mazarguil  *
2758340392eSAdrien Mazarguil  * @param buf
2768340392eSAdrien Mazarguil  *   Pointer to mbuf.
2778340392eSAdrien Mazarguil  *
2788340392eSAdrien Mazarguil  * @return
2798340392eSAdrien Mazarguil  *   Memory pool where data is located for given mbuf.
2808340392eSAdrien Mazarguil  */
2818340392eSAdrien Mazarguil static struct rte_mempool *
2828340392eSAdrien Mazarguil txq_mb2mp(struct rte_mbuf *buf)
2838340392eSAdrien Mazarguil {
2848340392eSAdrien Mazarguil 	if (unlikely(RTE_MBUF_INDIRECT(buf)))
2858340392eSAdrien Mazarguil 		return rte_mbuf_from_indirect(buf)->pool;
2868340392eSAdrien Mazarguil 	return buf->pool;
2878340392eSAdrien Mazarguil }
2888340392eSAdrien Mazarguil 
2898340392eSAdrien Mazarguil /**
2902e22920bSAdrien Mazarguil  * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
2912e22920bSAdrien Mazarguil  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
2922e22920bSAdrien Mazarguil  * remove an entry first.
2932e22920bSAdrien Mazarguil  *
2942e22920bSAdrien Mazarguil  * @param txq
2952e22920bSAdrien Mazarguil  *   Pointer to TX queue structure.
2962e22920bSAdrien Mazarguil  * @param[in] mp
2972e22920bSAdrien Mazarguil  *   Memory Pool for which a Memory Region lkey must be returned.
2982e22920bSAdrien Mazarguil  *
2992e22920bSAdrien Mazarguil  * @return
3002e22920bSAdrien Mazarguil  *   mr->lkey on success, (uint32_t)-1 on failure.
3012e22920bSAdrien Mazarguil  */
302491770faSNélio Laranjeiro static inline uint32_t
303d1d914ebSOlivier Matz txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
3042e22920bSAdrien Mazarguil {
3052e22920bSAdrien Mazarguil 	unsigned int i;
306491770faSNélio Laranjeiro 	uint32_t lkey = (uint32_t)-1;
3072e22920bSAdrien Mazarguil 
3082e22920bSAdrien Mazarguil 	for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
3092e22920bSAdrien Mazarguil 		if (unlikely(txq->mp2mr[i].mp == NULL)) {
3102e22920bSAdrien Mazarguil 			/* Unknown MP, add a new MR for it. */
3112e22920bSAdrien Mazarguil 			break;
3122e22920bSAdrien Mazarguil 		}
3132e22920bSAdrien Mazarguil 		if (txq->mp2mr[i].mp == mp) {
3142e22920bSAdrien Mazarguil 			assert(txq->mp2mr[i].lkey != (uint32_t)-1);
3151d88ba17SNélio Laranjeiro 			assert(htonl(txq->mp2mr[i].mr->lkey) ==
3161d88ba17SNélio Laranjeiro 			       txq->mp2mr[i].lkey);
317491770faSNélio Laranjeiro 			lkey = txq->mp2mr[i].lkey;
318491770faSNélio Laranjeiro 			break;
3192e22920bSAdrien Mazarguil 		}
3202e22920bSAdrien Mazarguil 	}
321491770faSNélio Laranjeiro 	if (unlikely(lkey == (uint32_t)-1))
322491770faSNélio Laranjeiro 		lkey = txq_mp2mr_reg(txq, mp, i);
323491770faSNélio Laranjeiro 	return lkey;
3240a3b350dSOlga Shern }
3250a3b350dSOlga Shern 
326e192ef80SYaacov Hazan /**
3271d88ba17SNélio Laranjeiro  * Ring TX queue doorbell.
3281d88ba17SNélio Laranjeiro  *
3291d88ba17SNélio Laranjeiro  * @param txq
3301d88ba17SNélio Laranjeiro  *   Pointer to TX queue structure.
33130807f62SNélio Laranjeiro  * @param wqe
33230807f62SNélio Laranjeiro  *   Pointer to the last WQE posted in the NIC.
3331d88ba17SNélio Laranjeiro  */
3341d88ba17SNélio Laranjeiro static inline void
33530807f62SNélio Laranjeiro mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
3361d88ba17SNélio Laranjeiro {
33730807f62SNélio Laranjeiro 	uint64_t *dst = (uint64_t *)((uintptr_t)txq->bf_reg);
33830807f62SNélio Laranjeiro 	volatile uint64_t *src = ((volatile uint64_t *)wqe);
33930807f62SNélio Laranjeiro 
3401d88ba17SNélio Laranjeiro 	rte_wmb();
3411d88ba17SNélio Laranjeiro 	*txq->qp_db = htonl(txq->wqe_ci);
3421d88ba17SNélio Laranjeiro 	/* Ensure ordering between DB record and BF copy. */
3431d88ba17SNélio Laranjeiro 	rte_wmb();
34430807f62SNélio Laranjeiro 	*dst = *src;
3451d88ba17SNélio Laranjeiro }
346e192ef80SYaacov Hazan 
3471d88ba17SNélio Laranjeiro /**
3488788fec1SOlivier Matz  * DPDK callback to check the status of a tx descriptor.
3498788fec1SOlivier Matz  *
3508788fec1SOlivier Matz  * @param tx_queue
3518788fec1SOlivier Matz  *   The tx queue.
3528788fec1SOlivier Matz  * @param[in] offset
3538788fec1SOlivier Matz  *   The index of the descriptor in the ring.
3548788fec1SOlivier Matz  *
3558788fec1SOlivier Matz  * @return
3568788fec1SOlivier Matz  *   The status of the tx descriptor.
3578788fec1SOlivier Matz  */
3588788fec1SOlivier Matz int
3598788fec1SOlivier Matz mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset)
3608788fec1SOlivier Matz {
3618788fec1SOlivier Matz 	struct txq *txq = tx_queue;
3628788fec1SOlivier Matz 	const unsigned int elts_n = 1 << txq->elts_n;
3638788fec1SOlivier Matz 	const unsigned int elts_cnt = elts_n - 1;
3648788fec1SOlivier Matz 	unsigned int used;
3658788fec1SOlivier Matz 
3668788fec1SOlivier Matz 	txq_complete(txq);
3678788fec1SOlivier Matz 	used = (txq->elts_head - txq->elts_tail) & elts_cnt;
3688788fec1SOlivier Matz 	if (offset < used)
3698788fec1SOlivier Matz 		return RTE_ETH_TX_DESC_FULL;
3708788fec1SOlivier Matz 	return RTE_ETH_TX_DESC_DONE;
3718788fec1SOlivier Matz }
3728788fec1SOlivier Matz 
3738788fec1SOlivier Matz /**
3748788fec1SOlivier Matz  * DPDK callback to check the status of a rx descriptor.
3758788fec1SOlivier Matz  *
3768788fec1SOlivier Matz  * @param rx_queue
3778788fec1SOlivier Matz  *   The rx queue.
3788788fec1SOlivier Matz  * @param[in] offset
3798788fec1SOlivier Matz  *   The index of the descriptor in the ring.
3808788fec1SOlivier Matz  *
3818788fec1SOlivier Matz  * @return
3828788fec1SOlivier Matz  *   The status of the tx descriptor.
3838788fec1SOlivier Matz  */
3848788fec1SOlivier Matz int
3858788fec1SOlivier Matz mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
3868788fec1SOlivier Matz {
3878788fec1SOlivier Matz 	struct rxq *rxq = rx_queue;
3888788fec1SOlivier Matz 	struct rxq_zip *zip = &rxq->zip;
3898788fec1SOlivier Matz 	volatile struct mlx5_cqe *cqe;
3908788fec1SOlivier Matz 	const unsigned int cqe_n = (1 << rxq->cqe_n);
3918788fec1SOlivier Matz 	const unsigned int cqe_cnt = cqe_n - 1;
3928788fec1SOlivier Matz 	unsigned int cq_ci;
3938788fec1SOlivier Matz 	unsigned int used;
3948788fec1SOlivier Matz 
3958788fec1SOlivier Matz 	/* if we are processing a compressed cqe */
3968788fec1SOlivier Matz 	if (zip->ai) {
3978788fec1SOlivier Matz 		used = zip->cqe_cnt - zip->ca;
3988788fec1SOlivier Matz 		cq_ci = zip->cq_ci;
3998788fec1SOlivier Matz 	} else {
4008788fec1SOlivier Matz 		used = 0;
4018788fec1SOlivier Matz 		cq_ci = rxq->cq_ci;
4028788fec1SOlivier Matz 	}
4038788fec1SOlivier Matz 	cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
4048788fec1SOlivier Matz 	while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
4058788fec1SOlivier Matz 		int8_t op_own;
4068788fec1SOlivier Matz 		unsigned int n;
4078788fec1SOlivier Matz 
4088788fec1SOlivier Matz 		op_own = cqe->op_own;
4098788fec1SOlivier Matz 		if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
4108788fec1SOlivier Matz 			n = ntohl(cqe->byte_cnt);
4118788fec1SOlivier Matz 		else
4128788fec1SOlivier Matz 			n = 1;
4138788fec1SOlivier Matz 		cq_ci += n;
4148788fec1SOlivier Matz 		used += n;
4158788fec1SOlivier Matz 		cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
4168788fec1SOlivier Matz 	}
4178788fec1SOlivier Matz 	used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
4188788fec1SOlivier Matz 	if (offset < used)
4198788fec1SOlivier Matz 		return RTE_ETH_RX_DESC_DONE;
4208788fec1SOlivier Matz 	return RTE_ETH_RX_DESC_AVAIL;
4218788fec1SOlivier Matz }
4228788fec1SOlivier Matz 
4238788fec1SOlivier Matz /**
4242e22920bSAdrien Mazarguil  * DPDK callback for TX.
4252e22920bSAdrien Mazarguil  *
4262e22920bSAdrien Mazarguil  * @param dpdk_txq
4272e22920bSAdrien Mazarguil  *   Generic pointer to TX queue structure.
4282e22920bSAdrien Mazarguil  * @param[in] pkts
4292e22920bSAdrien Mazarguil  *   Packets to transmit.
4302e22920bSAdrien Mazarguil  * @param pkts_n
4312e22920bSAdrien Mazarguil  *   Number of packets in array.
4322e22920bSAdrien Mazarguil  *
4332e22920bSAdrien Mazarguil  * @return
4342e22920bSAdrien Mazarguil  *   Number of packets successfully transmitted (<= pkts_n).
4352e22920bSAdrien Mazarguil  */
4362e22920bSAdrien Mazarguil uint16_t
4372e22920bSAdrien Mazarguil mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
4382e22920bSAdrien Mazarguil {
4392e22920bSAdrien Mazarguil 	struct txq *txq = (struct txq *)dpdk_txq;
4401d88ba17SNélio Laranjeiro 	uint16_t elts_head = txq->elts_head;
441b4b12e55SNélio Laranjeiro 	const unsigned int elts_n = 1 << txq->elts_n;
442c3d62cc9SAdrien Mazarguil 	unsigned int i = 0;
443a5bf6af9SAdrien Mazarguil 	unsigned int j = 0;
4442e22920bSAdrien Mazarguil 	unsigned int max;
445f04f1d51SNélio Laranjeiro 	uint16_t max_wqe;
446c305090bSAdrien Mazarguil 	unsigned int comp;
4479a7fa9f7SNélio Laranjeiro 	volatile struct mlx5_wqe_v *wqe = NULL;
4486579c27cSNélio Laranjeiro 	unsigned int segs_n = 0;
4496579c27cSNélio Laranjeiro 	struct rte_mbuf *buf = NULL;
4506579c27cSNélio Laranjeiro 	uint8_t *raw;
4512e22920bSAdrien Mazarguil 
4521d88ba17SNélio Laranjeiro 	if (unlikely(!pkts_n))
4531d88ba17SNélio Laranjeiro 		return 0;
4545e1d11ecSNelio Laranjeiro 	/* Prefetch first packet cacheline. */
455c3d62cc9SAdrien Mazarguil 	rte_prefetch0(*pkts);
4561d88ba17SNélio Laranjeiro 	/* Start processing. */
4572e22920bSAdrien Mazarguil 	txq_complete(txq);
4584f52bbfbSNelio Laranjeiro 	max = (elts_n - (elts_head - txq->elts_tail));
4592e22920bSAdrien Mazarguil 	if (max > elts_n)
4602e22920bSAdrien Mazarguil 		max -= elts_n;
461f04f1d51SNélio Laranjeiro 	max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
462f04f1d51SNélio Laranjeiro 	if (unlikely(!max_wqe))
463f04f1d51SNélio Laranjeiro 		return 0;
464c3d62cc9SAdrien Mazarguil 	do {
4659a7fa9f7SNélio Laranjeiro 		volatile rte_v128u32_t *dseg = NULL;
466573f54afSNélio Laranjeiro 		uint32_t length;
4678688b2f8SNélio Laranjeiro 		unsigned int ds = 0;
4686579c27cSNélio Laranjeiro 		uintptr_t addr;
4699a7fa9f7SNélio Laranjeiro 		uint64_t naddr;
4700d637a34SNélio Laranjeiro 		uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE + 2;
471eef822ddSNélio Laranjeiro 		uint16_t ehdr;
4729a7fa9f7SNélio Laranjeiro 		uint8_t cs_flags = 0;
4736579c27cSNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
4746579c27cSNélio Laranjeiro 		uint32_t total_length = 0;
4756579c27cSNélio Laranjeiro #endif
4762e22920bSAdrien Mazarguil 
4776579c27cSNélio Laranjeiro 		/* first_seg */
4786579c27cSNélio Laranjeiro 		buf = *(pkts++);
4796579c27cSNélio Laranjeiro 		segs_n = buf->nb_segs;
480c3d62cc9SAdrien Mazarguil 		/*
481c3d62cc9SAdrien Mazarguil 		 * Make sure there is enough room to store this packet and
482c3d62cc9SAdrien Mazarguil 		 * that one ring entry remains unused.
483c3d62cc9SAdrien Mazarguil 		 */
484a5bf6af9SAdrien Mazarguil 		assert(segs_n);
485a5bf6af9SAdrien Mazarguil 		if (max < segs_n + 1)
486c3d62cc9SAdrien Mazarguil 			break;
487a5bf6af9SAdrien Mazarguil 		max -= segs_n;
4886579c27cSNélio Laranjeiro 		--segs_n;
4896579c27cSNélio Laranjeiro 		if (!segs_n)
490c3d62cc9SAdrien Mazarguil 			--pkts_n;
491f04f1d51SNélio Laranjeiro 		if (unlikely(--max_wqe == 0))
492f04f1d51SNélio Laranjeiro 			break;
4939a7fa9f7SNélio Laranjeiro 		wqe = (volatile struct mlx5_wqe_v *)
494fdcb0f53SNélio Laranjeiro 			tx_mlx5_wqe(txq, txq->wqe_ci);
495fdcb0f53SNélio Laranjeiro 		rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
4966579c27cSNélio Laranjeiro 		if (pkts_n > 1)
497c3d62cc9SAdrien Mazarguil 			rte_prefetch0(*pkts);
4986579c27cSNélio Laranjeiro 		addr = rte_pktmbuf_mtod(buf, uintptr_t);
4992e22920bSAdrien Mazarguil 		length = DATA_LEN(buf);
500eef822ddSNélio Laranjeiro 		ehdr = (((uint8_t *)addr)[1] << 8) |
501eef822ddSNélio Laranjeiro 		       ((uint8_t *)addr)[0];
5026579c27cSNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
5036579c27cSNélio Laranjeiro 		total_length = length;
5046579c27cSNélio Laranjeiro #endif
5056579c27cSNélio Laranjeiro 		assert(length >= MLX5_WQE_DWORD_SIZE);
5062e22920bSAdrien Mazarguil 		/* Update element. */
5071d88ba17SNélio Laranjeiro 		(*txq->elts)[elts_head] = buf;
5086579c27cSNélio Laranjeiro 		elts_head = (elts_head + 1) & (elts_n - 1);
5095e1d11ecSNelio Laranjeiro 		/* Prefetch next buffer data. */
5106579c27cSNélio Laranjeiro 		if (pkts_n > 1) {
5116579c27cSNélio Laranjeiro 			volatile void *pkt_addr;
5126579c27cSNélio Laranjeiro 
5136579c27cSNélio Laranjeiro 			pkt_addr = rte_pktmbuf_mtod(*pkts, volatile void *);
5146579c27cSNélio Laranjeiro 			rte_prefetch0(pkt_addr);
5156579c27cSNélio Laranjeiro 		}
5161d88ba17SNélio Laranjeiro 		/* Should we enable HW CKSUM offload */
5171d88ba17SNélio Laranjeiro 		if (buf->ol_flags &
5181d88ba17SNélio Laranjeiro 		    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
5199a7fa9f7SNélio Laranjeiro 			cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
5201d88ba17SNélio Laranjeiro 		}
521b8fe952eSNélio Laranjeiro 		raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE;
5226579c27cSNélio Laranjeiro 		/* Replace the Ethernet type by the VLAN if necessary. */
5236579c27cSNélio Laranjeiro 		if (buf->ol_flags & PKT_TX_VLAN_PKT) {
5246579c27cSNélio Laranjeiro 			uint32_t vlan = htonl(0x81000000 | buf->vlan_tci);
5250d637a34SNélio Laranjeiro 			unsigned int len = 2 * ETHER_ADDR_LEN - 2;
5266579c27cSNélio Laranjeiro 
5270d637a34SNélio Laranjeiro 			addr += 2;
5280d637a34SNélio Laranjeiro 			length -= 2;
5290d637a34SNélio Laranjeiro 			/* Copy Destination and source mac address. */
5300d637a34SNélio Laranjeiro 			memcpy((uint8_t *)raw, ((uint8_t *)addr), len);
5310d637a34SNélio Laranjeiro 			/* Copy VLAN. */
5320d637a34SNélio Laranjeiro 			memcpy((uint8_t *)raw + len, &vlan, sizeof(vlan));
5330d637a34SNélio Laranjeiro 			/* Copy missing two bytes to end the DSeg. */
5340d637a34SNélio Laranjeiro 			memcpy((uint8_t *)raw + len + sizeof(vlan),
5350d637a34SNélio Laranjeiro 			       ((uint8_t *)addr) + len, 2);
5360d637a34SNélio Laranjeiro 			addr += len + 2;
5370d637a34SNélio Laranjeiro 			length -= (len + 2);
5380d637a34SNélio Laranjeiro 		} else {
5390d637a34SNélio Laranjeiro 			memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2,
5400d637a34SNélio Laranjeiro 			       MLX5_WQE_DWORD_SIZE);
5410d637a34SNélio Laranjeiro 			length -= pkt_inline_sz;
5420d637a34SNélio Laranjeiro 			addr += pkt_inline_sz;
5436579c27cSNélio Laranjeiro 		}
5446579c27cSNélio Laranjeiro 		/* Inline if enough room. */
5458fcd6c2cSNélio Laranjeiro 		if (txq->max_inline) {
546fdcb0f53SNélio Laranjeiro 			uintptr_t end = (uintptr_t)
547fdcb0f53SNélio Laranjeiro 				(((uintptr_t)txq->wqes) +
548fdcb0f53SNélio Laranjeiro 				 (1 << txq->wqe_n) * MLX5_WQE_SIZE);
5498fcd6c2cSNélio Laranjeiro 			unsigned int max_inline = txq->max_inline *
5508fcd6c2cSNélio Laranjeiro 						  RTE_CACHE_LINE_SIZE -
5518fcd6c2cSNélio Laranjeiro 						  MLX5_WQE_DWORD_SIZE;
5526579c27cSNélio Laranjeiro 			uintptr_t addr_end = (addr + max_inline) &
5536579c27cSNélio Laranjeiro 					     ~(RTE_CACHE_LINE_SIZE - 1);
5548fcd6c2cSNélio Laranjeiro 			unsigned int copy_b = (addr_end > addr) ?
5558fcd6c2cSNélio Laranjeiro 				RTE_MIN((addr_end - addr), length) :
5568fcd6c2cSNélio Laranjeiro 				0;
5576579c27cSNélio Laranjeiro 
5588fcd6c2cSNélio Laranjeiro 			raw += MLX5_WQE_DWORD_SIZE;
5598fcd6c2cSNélio Laranjeiro 			if (copy_b && ((end - (uintptr_t)raw) > copy_b)) {
560f04f1d51SNélio Laranjeiro 				/*
561f04f1d51SNélio Laranjeiro 				 * One Dseg remains in the current WQE.  To
562f04f1d51SNélio Laranjeiro 				 * keep the computation positive, it is
563f04f1d51SNélio Laranjeiro 				 * removed after the bytes to Dseg conversion.
564f04f1d51SNélio Laranjeiro 				 */
5658fcd6c2cSNélio Laranjeiro 				uint16_t n = (MLX5_WQE_DS(copy_b) - 1 + 3) / 4;
5668fcd6c2cSNélio Laranjeiro 
567f04f1d51SNélio Laranjeiro 				if (unlikely(max_wqe < n))
568f04f1d51SNélio Laranjeiro 					break;
569f04f1d51SNélio Laranjeiro 				max_wqe -= n;
5706579c27cSNélio Laranjeiro 				rte_memcpy((void *)raw, (void *)addr, copy_b);
5716579c27cSNélio Laranjeiro 				addr += copy_b;
5726579c27cSNélio Laranjeiro 				length -= copy_b;
5736579c27cSNélio Laranjeiro 				pkt_inline_sz += copy_b;
5746579c27cSNélio Laranjeiro 			}
5756579c27cSNélio Laranjeiro 			/*
576786b5c2dSShahaf Shuler 			 * 2 DWORDs consumed by the WQE header + ETH segment +
5776579c27cSNélio Laranjeiro 			 * the size of the inline part of the packet.
5786579c27cSNélio Laranjeiro 			 */
5796579c27cSNélio Laranjeiro 			ds = 2 + MLX5_WQE_DS(pkt_inline_sz - 2);
5806579c27cSNélio Laranjeiro 			if (length > 0) {
581f04f1d51SNélio Laranjeiro 				if (ds % (MLX5_WQE_SIZE /
582f04f1d51SNélio Laranjeiro 					  MLX5_WQE_DWORD_SIZE) == 0) {
583f04f1d51SNélio Laranjeiro 					if (unlikely(--max_wqe == 0))
584f04f1d51SNélio Laranjeiro 						break;
585f04f1d51SNélio Laranjeiro 					dseg = (volatile rte_v128u32_t *)
586f04f1d51SNélio Laranjeiro 					       tx_mlx5_wqe(txq, txq->wqe_ci +
587f04f1d51SNélio Laranjeiro 							   ds / 4);
588f04f1d51SNélio Laranjeiro 				} else {
5899a7fa9f7SNélio Laranjeiro 					dseg = (volatile rte_v128u32_t *)
5906579c27cSNélio Laranjeiro 						((uintptr_t)wqe +
5916579c27cSNélio Laranjeiro 						 (ds * MLX5_WQE_DWORD_SIZE));
592f04f1d51SNélio Laranjeiro 				}
5936579c27cSNélio Laranjeiro 				goto use_dseg;
5946579c27cSNélio Laranjeiro 			} else if (!segs_n) {
5956579c27cSNélio Laranjeiro 				goto next_pkt;
5966579c27cSNélio Laranjeiro 			} else {
597786b5c2dSShahaf Shuler 				/* dseg will be advance as part of next_seg */
598786b5c2dSShahaf Shuler 				dseg = (volatile rte_v128u32_t *)
599786b5c2dSShahaf Shuler 					((uintptr_t)wqe +
600786b5c2dSShahaf Shuler 					 ((ds - 1) * MLX5_WQE_DWORD_SIZE));
6016579c27cSNélio Laranjeiro 				goto next_seg;
6026579c27cSNélio Laranjeiro 			}
6036579c27cSNélio Laranjeiro 		} else {
6046579c27cSNélio Laranjeiro 			/*
6056579c27cSNélio Laranjeiro 			 * No inline has been done in the packet, only the
6066579c27cSNélio Laranjeiro 			 * Ethernet Header as been stored.
6076579c27cSNélio Laranjeiro 			 */
6089a7fa9f7SNélio Laranjeiro 			dseg = (volatile rte_v128u32_t *)
6096579c27cSNélio Laranjeiro 				((uintptr_t)wqe + (3 * MLX5_WQE_DWORD_SIZE));
6106579c27cSNélio Laranjeiro 			ds = 3;
6116579c27cSNélio Laranjeiro use_dseg:
6126579c27cSNélio Laranjeiro 			/* Add the remaining packet as a simple ds. */
6139a7fa9f7SNélio Laranjeiro 			naddr = htonll(addr);
6149a7fa9f7SNélio Laranjeiro 			*dseg = (rte_v128u32_t){
6159a7fa9f7SNélio Laranjeiro 				htonl(length),
6169a7fa9f7SNélio Laranjeiro 				txq_mp2mr(txq, txq_mb2mp(buf)),
6179a7fa9f7SNélio Laranjeiro 				naddr,
6189a7fa9f7SNélio Laranjeiro 				naddr >> 32,
6196579c27cSNélio Laranjeiro 			};
6206579c27cSNélio Laranjeiro 			++ds;
6216579c27cSNélio Laranjeiro 			if (!segs_n)
6226579c27cSNélio Laranjeiro 				goto next_pkt;
6236579c27cSNélio Laranjeiro 		}
6246579c27cSNélio Laranjeiro next_seg:
6256579c27cSNélio Laranjeiro 		assert(buf);
6266579c27cSNélio Laranjeiro 		assert(ds);
6276579c27cSNélio Laranjeiro 		assert(wqe);
628a5bf6af9SAdrien Mazarguil 		/*
629a5bf6af9SAdrien Mazarguil 		 * Spill on next WQE when the current one does not have
630a5bf6af9SAdrien Mazarguil 		 * enough room left. Size of WQE must a be a multiple
631a5bf6af9SAdrien Mazarguil 		 * of data segment size.
632a5bf6af9SAdrien Mazarguil 		 */
6338688b2f8SNélio Laranjeiro 		assert(!(MLX5_WQE_SIZE % MLX5_WQE_DWORD_SIZE));
6346579c27cSNélio Laranjeiro 		if (!(ds % (MLX5_WQE_SIZE / MLX5_WQE_DWORD_SIZE))) {
635f04f1d51SNélio Laranjeiro 			if (unlikely(--max_wqe == 0))
636f04f1d51SNélio Laranjeiro 				break;
6379a7fa9f7SNélio Laranjeiro 			dseg = (volatile rte_v128u32_t *)
638f04f1d51SNélio Laranjeiro 			       tx_mlx5_wqe(txq, txq->wqe_ci + ds / 4);
639f04f1d51SNélio Laranjeiro 			rte_prefetch0(tx_mlx5_wqe(txq,
640f04f1d51SNélio Laranjeiro 						  txq->wqe_ci + ds / 4 + 1));
6416579c27cSNélio Laranjeiro 		} else {
642a5bf6af9SAdrien Mazarguil 			++dseg;
6436579c27cSNélio Laranjeiro 		}
644a5bf6af9SAdrien Mazarguil 		++ds;
645a5bf6af9SAdrien Mazarguil 		buf = buf->next;
646a5bf6af9SAdrien Mazarguil 		assert(buf);
6476579c27cSNélio Laranjeiro 		length = DATA_LEN(buf);
648a5bf6af9SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
6496579c27cSNélio Laranjeiro 		total_length += length;
650a5bf6af9SAdrien Mazarguil #endif
6516579c27cSNélio Laranjeiro 		/* Store segment information. */
6529a7fa9f7SNélio Laranjeiro 		naddr = htonll(rte_pktmbuf_mtod(buf, uintptr_t));
6539a7fa9f7SNélio Laranjeiro 		*dseg = (rte_v128u32_t){
6549a7fa9f7SNélio Laranjeiro 			htonl(length),
6559a7fa9f7SNélio Laranjeiro 			txq_mp2mr(txq, txq_mb2mp(buf)),
6569a7fa9f7SNélio Laranjeiro 			naddr,
6579a7fa9f7SNélio Laranjeiro 			naddr >> 32,
6586579c27cSNélio Laranjeiro 		};
6596579c27cSNélio Laranjeiro 		(*txq->elts)[elts_head] = buf;
6606579c27cSNélio Laranjeiro 		elts_head = (elts_head + 1) & (elts_n - 1);
661a5bf6af9SAdrien Mazarguil 		++j;
6626579c27cSNélio Laranjeiro 		--segs_n;
6636579c27cSNélio Laranjeiro 		if (segs_n)
6646579c27cSNélio Laranjeiro 			goto next_seg;
6656579c27cSNélio Laranjeiro 		else
6666579c27cSNélio Laranjeiro 			--pkts_n;
6676579c27cSNélio Laranjeiro next_pkt:
6686579c27cSNélio Laranjeiro 		++i;
669b8fe952eSNélio Laranjeiro 		/* Initialize known and common part of the WQE structure. */
6709a7fa9f7SNélio Laranjeiro 		wqe->ctrl = (rte_v128u32_t){
6719a7fa9f7SNélio Laranjeiro 			htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND),
6729a7fa9f7SNélio Laranjeiro 			htonl(txq->qp_num_8s | ds),
6739a7fa9f7SNélio Laranjeiro 			0,
6749a7fa9f7SNélio Laranjeiro 			0,
6759a7fa9f7SNélio Laranjeiro 		};
6769a7fa9f7SNélio Laranjeiro 		wqe->eseg = (rte_v128u32_t){
6779a7fa9f7SNélio Laranjeiro 			0,
6789a7fa9f7SNélio Laranjeiro 			cs_flags,
6799a7fa9f7SNélio Laranjeiro 			0,
680eef822ddSNélio Laranjeiro 			(ehdr << 16) | htons(pkt_inline_sz),
6819a7fa9f7SNélio Laranjeiro 		};
6826579c27cSNélio Laranjeiro 		txq->wqe_ci += (ds + 3) / 4;
68387011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
684573f54afSNélio Laranjeiro 		/* Increment sent bytes counter. */
6856579c27cSNélio Laranjeiro 		txq->stats.obytes += total_length;
68687011737SAdrien Mazarguil #endif
687c3d62cc9SAdrien Mazarguil 	} while (pkts_n);
6882e22920bSAdrien Mazarguil 	/* Take a shortcut if nothing must be sent. */
6892e22920bSAdrien Mazarguil 	if (unlikely(i == 0))
6902e22920bSAdrien Mazarguil 		return 0;
691c305090bSAdrien Mazarguil 	/* Check whether completion threshold has been reached. */
692a5bf6af9SAdrien Mazarguil 	comp = txq->elts_comp + i + j;
693c305090bSAdrien Mazarguil 	if (comp >= MLX5_TX_COMP_THRESH) {
6949a7fa9f7SNélio Laranjeiro 		volatile struct mlx5_wqe_ctrl *w =
6959a7fa9f7SNélio Laranjeiro 			(volatile struct mlx5_wqe_ctrl *)wqe;
6969a7fa9f7SNélio Laranjeiro 
697c305090bSAdrien Mazarguil 		/* Request completion on last WQE. */
6989a7fa9f7SNélio Laranjeiro 		w->ctrl2 = htonl(8);
699c305090bSAdrien Mazarguil 		/* Save elts_head in unused "immediate" field of WQE. */
7009a7fa9f7SNélio Laranjeiro 		w->ctrl3 = elts_head;
701c305090bSAdrien Mazarguil 		txq->elts_comp = 0;
702c305090bSAdrien Mazarguil 	} else {
703c305090bSAdrien Mazarguil 		txq->elts_comp = comp;
704c305090bSAdrien Mazarguil 	}
70587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
70687011737SAdrien Mazarguil 	/* Increment sent packets counter. */
70787011737SAdrien Mazarguil 	txq->stats.opackets += i;
70887011737SAdrien Mazarguil #endif
7092e22920bSAdrien Mazarguil 	/* Ring QP doorbell. */
71030807f62SNélio Laranjeiro 	mlx5_tx_dbrec(txq, (volatile struct mlx5_wqe *)wqe);
7112e22920bSAdrien Mazarguil 	txq->elts_head = elts_head;
7122e22920bSAdrien Mazarguil 	return i;
7132e22920bSAdrien Mazarguil }
7142e22920bSAdrien Mazarguil 
7152e22920bSAdrien Mazarguil /**
716230189d9SNélio Laranjeiro  * Open a MPW session.
717230189d9SNélio Laranjeiro  *
718230189d9SNélio Laranjeiro  * @param txq
719230189d9SNélio Laranjeiro  *   Pointer to TX queue structure.
720230189d9SNélio Laranjeiro  * @param mpw
721230189d9SNélio Laranjeiro  *   Pointer to MPW session structure.
722230189d9SNélio Laranjeiro  * @param length
723230189d9SNélio Laranjeiro  *   Packet length.
724230189d9SNélio Laranjeiro  */
725230189d9SNélio Laranjeiro static inline void
726230189d9SNélio Laranjeiro mlx5_mpw_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
727230189d9SNélio Laranjeiro {
728a821d09dSNélio Laranjeiro 	uint16_t idx = txq->wqe_ci & ((1 << txq->wqe_n) - 1);
729230189d9SNélio Laranjeiro 	volatile struct mlx5_wqe_data_seg (*dseg)[MLX5_MPW_DSEG_MAX] =
730230189d9SNélio Laranjeiro 		(volatile struct mlx5_wqe_data_seg (*)[])
731fdcb0f53SNélio Laranjeiro 		tx_mlx5_wqe(txq, idx + 1);
732230189d9SNélio Laranjeiro 
733230189d9SNélio Laranjeiro 	mpw->state = MLX5_MPW_STATE_OPENED;
734230189d9SNélio Laranjeiro 	mpw->pkts_n = 0;
735230189d9SNélio Laranjeiro 	mpw->len = length;
736230189d9SNélio Laranjeiro 	mpw->total_len = 0;
737fdcb0f53SNélio Laranjeiro 	mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
7388688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.mss = htons(length);
7398688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.inline_hdr_sz = 0;
7408688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd0 = 0;
7418688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd1 = 0;
7428688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd2 = 0;
7438688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
744c904ae25SNélio Laranjeiro 				  (txq->wqe_ci << 8) | MLX5_OPCODE_TSO);
7458688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[2] = 0;
7468688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[3] = 0;
7478688b2f8SNélio Laranjeiro 	mpw->data.dseg[0] = (volatile struct mlx5_wqe_data_seg *)
7488688b2f8SNélio Laranjeiro 		(((uintptr_t)mpw->wqe) + (2 * MLX5_WQE_DWORD_SIZE));
7498688b2f8SNélio Laranjeiro 	mpw->data.dseg[1] = (volatile struct mlx5_wqe_data_seg *)
7508688b2f8SNélio Laranjeiro 		(((uintptr_t)mpw->wqe) + (3 * MLX5_WQE_DWORD_SIZE));
751230189d9SNélio Laranjeiro 	mpw->data.dseg[2] = &(*dseg)[0];
752230189d9SNélio Laranjeiro 	mpw->data.dseg[3] = &(*dseg)[1];
753230189d9SNélio Laranjeiro 	mpw->data.dseg[4] = &(*dseg)[2];
754230189d9SNélio Laranjeiro }
755230189d9SNélio Laranjeiro 
756230189d9SNélio Laranjeiro /**
757230189d9SNélio Laranjeiro  * Close a MPW session.
758230189d9SNélio Laranjeiro  *
759230189d9SNélio Laranjeiro  * @param txq
760230189d9SNélio Laranjeiro  *   Pointer to TX queue structure.
761230189d9SNélio Laranjeiro  * @param mpw
762230189d9SNélio Laranjeiro  *   Pointer to MPW session structure.
763230189d9SNélio Laranjeiro  */
764230189d9SNélio Laranjeiro static inline void
765230189d9SNélio Laranjeiro mlx5_mpw_close(struct txq *txq, struct mlx5_mpw *mpw)
766230189d9SNélio Laranjeiro {
767230189d9SNélio Laranjeiro 	unsigned int num = mpw->pkts_n;
768230189d9SNélio Laranjeiro 
769230189d9SNélio Laranjeiro 	/*
770230189d9SNélio Laranjeiro 	 * Store size in multiple of 16 bytes. Control and Ethernet segments
771230189d9SNélio Laranjeiro 	 * count as 2.
772230189d9SNélio Laranjeiro 	 */
7738688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[1] = htonl(txq->qp_num_8s | (2 + num));
774230189d9SNélio Laranjeiro 	mpw->state = MLX5_MPW_STATE_CLOSED;
775230189d9SNélio Laranjeiro 	if (num < 3)
776230189d9SNélio Laranjeiro 		++txq->wqe_ci;
777230189d9SNélio Laranjeiro 	else
778230189d9SNélio Laranjeiro 		txq->wqe_ci += 2;
779fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
780fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
781230189d9SNélio Laranjeiro }
782230189d9SNélio Laranjeiro 
783230189d9SNélio Laranjeiro /**
784230189d9SNélio Laranjeiro  * DPDK callback for TX with MPW support.
785230189d9SNélio Laranjeiro  *
786230189d9SNélio Laranjeiro  * @param dpdk_txq
787230189d9SNélio Laranjeiro  *   Generic pointer to TX queue structure.
788230189d9SNélio Laranjeiro  * @param[in] pkts
789230189d9SNélio Laranjeiro  *   Packets to transmit.
790230189d9SNélio Laranjeiro  * @param pkts_n
791230189d9SNélio Laranjeiro  *   Number of packets in array.
792230189d9SNélio Laranjeiro  *
793230189d9SNélio Laranjeiro  * @return
794230189d9SNélio Laranjeiro  *   Number of packets successfully transmitted (<= pkts_n).
795230189d9SNélio Laranjeiro  */
796230189d9SNélio Laranjeiro uint16_t
797230189d9SNélio Laranjeiro mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
798230189d9SNélio Laranjeiro {
799230189d9SNélio Laranjeiro 	struct txq *txq = (struct txq *)dpdk_txq;
800230189d9SNélio Laranjeiro 	uint16_t elts_head = txq->elts_head;
801b4b12e55SNélio Laranjeiro 	const unsigned int elts_n = 1 << txq->elts_n;
802c3d62cc9SAdrien Mazarguil 	unsigned int i = 0;
803a5bf6af9SAdrien Mazarguil 	unsigned int j = 0;
804230189d9SNélio Laranjeiro 	unsigned int max;
805f04f1d51SNélio Laranjeiro 	uint16_t max_wqe;
806230189d9SNélio Laranjeiro 	unsigned int comp;
807230189d9SNélio Laranjeiro 	struct mlx5_mpw mpw = {
808230189d9SNélio Laranjeiro 		.state = MLX5_MPW_STATE_CLOSED,
809230189d9SNélio Laranjeiro 	};
810230189d9SNélio Laranjeiro 
811c3d62cc9SAdrien Mazarguil 	if (unlikely(!pkts_n))
812c3d62cc9SAdrien Mazarguil 		return 0;
813230189d9SNélio Laranjeiro 	/* Prefetch first packet cacheline. */
814fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
815fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
816230189d9SNélio Laranjeiro 	/* Start processing. */
817230189d9SNélio Laranjeiro 	txq_complete(txq);
818230189d9SNélio Laranjeiro 	max = (elts_n - (elts_head - txq->elts_tail));
819230189d9SNélio Laranjeiro 	if (max > elts_n)
820230189d9SNélio Laranjeiro 		max -= elts_n;
821f04f1d51SNélio Laranjeiro 	max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
822f04f1d51SNélio Laranjeiro 	if (unlikely(!max_wqe))
823f04f1d51SNélio Laranjeiro 		return 0;
824c3d62cc9SAdrien Mazarguil 	do {
825a5bf6af9SAdrien Mazarguil 		struct rte_mbuf *buf = *(pkts++);
826c3d62cc9SAdrien Mazarguil 		unsigned int elts_head_next;
827230189d9SNélio Laranjeiro 		uint32_t length;
828a5bf6af9SAdrien Mazarguil 		unsigned int segs_n = buf->nb_segs;
829230189d9SNélio Laranjeiro 		uint32_t cs_flags = 0;
830230189d9SNélio Laranjeiro 
831c3d62cc9SAdrien Mazarguil 		/*
832c3d62cc9SAdrien Mazarguil 		 * Make sure there is enough room to store this packet and
833c3d62cc9SAdrien Mazarguil 		 * that one ring entry remains unused.
834c3d62cc9SAdrien Mazarguil 		 */
835a5bf6af9SAdrien Mazarguil 		assert(segs_n);
836a5bf6af9SAdrien Mazarguil 		if (max < segs_n + 1)
837c3d62cc9SAdrien Mazarguil 			break;
838a5bf6af9SAdrien Mazarguil 		/* Do not bother with large packets MPW cannot handle. */
839a5bf6af9SAdrien Mazarguil 		if (segs_n > MLX5_MPW_DSEG_MAX)
840a5bf6af9SAdrien Mazarguil 			break;
841a5bf6af9SAdrien Mazarguil 		max -= segs_n;
842c3d62cc9SAdrien Mazarguil 		--pkts_n;
843230189d9SNélio Laranjeiro 		/* Should we enable HW CKSUM offload */
844230189d9SNélio Laranjeiro 		if (buf->ol_flags &
845230189d9SNélio Laranjeiro 		    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
846230189d9SNélio Laranjeiro 			cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
847a5bf6af9SAdrien Mazarguil 		/* Retrieve packet information. */
848a5bf6af9SAdrien Mazarguil 		length = PKT_LEN(buf);
849a5bf6af9SAdrien Mazarguil 		assert(length);
850230189d9SNélio Laranjeiro 		/* Start new session if packet differs. */
851230189d9SNélio Laranjeiro 		if ((mpw.state == MLX5_MPW_STATE_OPENED) &&
852230189d9SNélio Laranjeiro 		    ((mpw.len != length) ||
853a5bf6af9SAdrien Mazarguil 		     (segs_n != 1) ||
8548688b2f8SNélio Laranjeiro 		     (mpw.wqe->eseg.cs_flags != cs_flags)))
855230189d9SNélio Laranjeiro 			mlx5_mpw_close(txq, &mpw);
856230189d9SNélio Laranjeiro 		if (mpw.state == MLX5_MPW_STATE_CLOSED) {
857f04f1d51SNélio Laranjeiro 			/*
858f04f1d51SNélio Laranjeiro 			 * Multi-Packet WQE consumes at most two WQE.
859f04f1d51SNélio Laranjeiro 			 * mlx5_mpw_new() expects to be able to use such
860f04f1d51SNélio Laranjeiro 			 * resources.
861f04f1d51SNélio Laranjeiro 			 */
862f04f1d51SNélio Laranjeiro 			if (unlikely(max_wqe < 2))
863f04f1d51SNélio Laranjeiro 				break;
864f04f1d51SNélio Laranjeiro 			max_wqe -= 2;
865230189d9SNélio Laranjeiro 			mlx5_mpw_new(txq, &mpw, length);
8668688b2f8SNélio Laranjeiro 			mpw.wqe->eseg.cs_flags = cs_flags;
867230189d9SNélio Laranjeiro 		}
868a5bf6af9SAdrien Mazarguil 		/* Multi-segment packets must be alone in their MPW. */
869a5bf6af9SAdrien Mazarguil 		assert((segs_n == 1) || (mpw.pkts_n == 0));
870a5bf6af9SAdrien Mazarguil #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
871a5bf6af9SAdrien Mazarguil 		length = 0;
872a5bf6af9SAdrien Mazarguil #endif
873a5bf6af9SAdrien Mazarguil 		do {
874a5bf6af9SAdrien Mazarguil 			volatile struct mlx5_wqe_data_seg *dseg;
875a5bf6af9SAdrien Mazarguil 			uintptr_t addr;
876a5bf6af9SAdrien Mazarguil 
877a5bf6af9SAdrien Mazarguil 			elts_head_next = (elts_head + 1) & (elts_n - 1);
878a5bf6af9SAdrien Mazarguil 			assert(buf);
879a5bf6af9SAdrien Mazarguil 			(*txq->elts)[elts_head] = buf;
880230189d9SNélio Laranjeiro 			dseg = mpw.data.dseg[mpw.pkts_n];
881a5bf6af9SAdrien Mazarguil 			addr = rte_pktmbuf_mtod(buf, uintptr_t);
882230189d9SNélio Laranjeiro 			*dseg = (struct mlx5_wqe_data_seg){
883a5bf6af9SAdrien Mazarguil 				.byte_count = htonl(DATA_LEN(buf)),
884230189d9SNélio Laranjeiro 				.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
885230189d9SNélio Laranjeiro 				.addr = htonll(addr),
886230189d9SNélio Laranjeiro 			};
887a5bf6af9SAdrien Mazarguil 			elts_head = elts_head_next;
888a5bf6af9SAdrien Mazarguil #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
889a5bf6af9SAdrien Mazarguil 			length += DATA_LEN(buf);
890a5bf6af9SAdrien Mazarguil #endif
891a5bf6af9SAdrien Mazarguil 			buf = buf->next;
892230189d9SNélio Laranjeiro 			++mpw.pkts_n;
893a5bf6af9SAdrien Mazarguil 			++j;
894a5bf6af9SAdrien Mazarguil 		} while (--segs_n);
895a5bf6af9SAdrien Mazarguil 		assert(length == mpw.len);
896230189d9SNélio Laranjeiro 		if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
897230189d9SNélio Laranjeiro 			mlx5_mpw_close(txq, &mpw);
898230189d9SNélio Laranjeiro 		elts_head = elts_head_next;
899230189d9SNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
900230189d9SNélio Laranjeiro 		/* Increment sent bytes counter. */
901230189d9SNélio Laranjeiro 		txq->stats.obytes += length;
902230189d9SNélio Laranjeiro #endif
903c3d62cc9SAdrien Mazarguil 		++i;
904c3d62cc9SAdrien Mazarguil 	} while (pkts_n);
905230189d9SNélio Laranjeiro 	/* Take a shortcut if nothing must be sent. */
906230189d9SNélio Laranjeiro 	if (unlikely(i == 0))
907230189d9SNélio Laranjeiro 		return 0;
908230189d9SNélio Laranjeiro 	/* Check whether completion threshold has been reached. */
909a5bf6af9SAdrien Mazarguil 	/* "j" includes both packets and segments. */
910a5bf6af9SAdrien Mazarguil 	comp = txq->elts_comp + j;
911230189d9SNélio Laranjeiro 	if (comp >= MLX5_TX_COMP_THRESH) {
9128688b2f8SNélio Laranjeiro 		volatile struct mlx5_wqe *wqe = mpw.wqe;
913230189d9SNélio Laranjeiro 
914230189d9SNélio Laranjeiro 		/* Request completion on last WQE. */
9158688b2f8SNélio Laranjeiro 		wqe->ctrl[2] = htonl(8);
916230189d9SNélio Laranjeiro 		/* Save elts_head in unused "immediate" field of WQE. */
9178688b2f8SNélio Laranjeiro 		wqe->ctrl[3] = elts_head;
918230189d9SNélio Laranjeiro 		txq->elts_comp = 0;
919230189d9SNélio Laranjeiro 	} else {
920230189d9SNélio Laranjeiro 		txq->elts_comp = comp;
921230189d9SNélio Laranjeiro 	}
922230189d9SNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
923230189d9SNélio Laranjeiro 	/* Increment sent packets counter. */
924230189d9SNélio Laranjeiro 	txq->stats.opackets += i;
925230189d9SNélio Laranjeiro #endif
926230189d9SNélio Laranjeiro 	/* Ring QP doorbell. */
927230189d9SNélio Laranjeiro 	if (mpw.state == MLX5_MPW_STATE_OPENED)
928230189d9SNélio Laranjeiro 		mlx5_mpw_close(txq, &mpw);
92930807f62SNélio Laranjeiro 	mlx5_tx_dbrec(txq, mpw.wqe);
930230189d9SNélio Laranjeiro 	txq->elts_head = elts_head;
931230189d9SNélio Laranjeiro 	return i;
932230189d9SNélio Laranjeiro }
933230189d9SNélio Laranjeiro 
934230189d9SNélio Laranjeiro /**
935230189d9SNélio Laranjeiro  * Open a MPW inline session.
936230189d9SNélio Laranjeiro  *
937230189d9SNélio Laranjeiro  * @param txq
938230189d9SNélio Laranjeiro  *   Pointer to TX queue structure.
939230189d9SNélio Laranjeiro  * @param mpw
940230189d9SNélio Laranjeiro  *   Pointer to MPW session structure.
941230189d9SNélio Laranjeiro  * @param length
942230189d9SNélio Laranjeiro  *   Packet length.
943230189d9SNélio Laranjeiro  */
944230189d9SNélio Laranjeiro static inline void
945230189d9SNélio Laranjeiro mlx5_mpw_inline_new(struct txq *txq, struct mlx5_mpw *mpw, uint32_t length)
946230189d9SNélio Laranjeiro {
947a821d09dSNélio Laranjeiro 	uint16_t idx = txq->wqe_ci & ((1 << txq->wqe_n) - 1);
9488688b2f8SNélio Laranjeiro 	struct mlx5_wqe_inl_small *inl;
949230189d9SNélio Laranjeiro 
950230189d9SNélio Laranjeiro 	mpw->state = MLX5_MPW_INL_STATE_OPENED;
951230189d9SNélio Laranjeiro 	mpw->pkts_n = 0;
952230189d9SNélio Laranjeiro 	mpw->len = length;
953230189d9SNélio Laranjeiro 	mpw->total_len = 0;
954fdcb0f53SNélio Laranjeiro 	mpw->wqe = (volatile struct mlx5_wqe *)tx_mlx5_wqe(txq, idx);
9558688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[0] = htonl((MLX5_OPC_MOD_MPW << 24) |
956230189d9SNélio Laranjeiro 				  (txq->wqe_ci << 8) |
957c904ae25SNélio Laranjeiro 				  MLX5_OPCODE_TSO);
9588688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[2] = 0;
9598688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[3] = 0;
9608688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.mss = htons(length);
9618688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.inline_hdr_sz = 0;
9628688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.cs_flags = 0;
9638688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd0 = 0;
9648688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd1 = 0;
9658688b2f8SNélio Laranjeiro 	mpw->wqe->eseg.rsvd2 = 0;
9668688b2f8SNélio Laranjeiro 	inl = (struct mlx5_wqe_inl_small *)
9678688b2f8SNélio Laranjeiro 		(((uintptr_t)mpw->wqe) + 2 * MLX5_WQE_DWORD_SIZE);
9688688b2f8SNélio Laranjeiro 	mpw->data.raw = (uint8_t *)&inl->raw;
969230189d9SNélio Laranjeiro }
970230189d9SNélio Laranjeiro 
971230189d9SNélio Laranjeiro /**
972230189d9SNélio Laranjeiro  * Close a MPW inline session.
973230189d9SNélio Laranjeiro  *
974230189d9SNélio Laranjeiro  * @param txq
975230189d9SNélio Laranjeiro  *   Pointer to TX queue structure.
976230189d9SNélio Laranjeiro  * @param mpw
977230189d9SNélio Laranjeiro  *   Pointer to MPW session structure.
978230189d9SNélio Laranjeiro  */
979230189d9SNélio Laranjeiro static inline void
980230189d9SNélio Laranjeiro mlx5_mpw_inline_close(struct txq *txq, struct mlx5_mpw *mpw)
981230189d9SNélio Laranjeiro {
982230189d9SNélio Laranjeiro 	unsigned int size;
9838688b2f8SNélio Laranjeiro 	struct mlx5_wqe_inl_small *inl = (struct mlx5_wqe_inl_small *)
9848688b2f8SNélio Laranjeiro 		(((uintptr_t)mpw->wqe) + (2 * MLX5_WQE_DWORD_SIZE));
985230189d9SNélio Laranjeiro 
9868688b2f8SNélio Laranjeiro 	size = MLX5_WQE_SIZE - MLX5_MWQE64_INL_DATA + mpw->total_len;
987230189d9SNélio Laranjeiro 	/*
988230189d9SNélio Laranjeiro 	 * Store size in multiple of 16 bytes. Control and Ethernet segments
989230189d9SNélio Laranjeiro 	 * count as 2.
990230189d9SNélio Laranjeiro 	 */
9918688b2f8SNélio Laranjeiro 	mpw->wqe->ctrl[1] = htonl(txq->qp_num_8s | MLX5_WQE_DS(size));
992230189d9SNélio Laranjeiro 	mpw->state = MLX5_MPW_STATE_CLOSED;
9938688b2f8SNélio Laranjeiro 	inl->byte_cnt = htonl(mpw->total_len | MLX5_INLINE_SEG);
9948688b2f8SNélio Laranjeiro 	txq->wqe_ci += (size + (MLX5_WQE_SIZE - 1)) / MLX5_WQE_SIZE;
995230189d9SNélio Laranjeiro }
996230189d9SNélio Laranjeiro 
997230189d9SNélio Laranjeiro /**
998230189d9SNélio Laranjeiro  * DPDK callback for TX with MPW inline support.
999230189d9SNélio Laranjeiro  *
1000230189d9SNélio Laranjeiro  * @param dpdk_txq
1001230189d9SNélio Laranjeiro  *   Generic pointer to TX queue structure.
1002230189d9SNélio Laranjeiro  * @param[in] pkts
1003230189d9SNélio Laranjeiro  *   Packets to transmit.
1004230189d9SNélio Laranjeiro  * @param pkts_n
1005230189d9SNélio Laranjeiro  *   Number of packets in array.
1006230189d9SNélio Laranjeiro  *
1007230189d9SNélio Laranjeiro  * @return
1008230189d9SNélio Laranjeiro  *   Number of packets successfully transmitted (<= pkts_n).
1009230189d9SNélio Laranjeiro  */
1010230189d9SNélio Laranjeiro uint16_t
1011230189d9SNélio Laranjeiro mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts,
1012230189d9SNélio Laranjeiro 			 uint16_t pkts_n)
1013230189d9SNélio Laranjeiro {
1014230189d9SNélio Laranjeiro 	struct txq *txq = (struct txq *)dpdk_txq;
1015230189d9SNélio Laranjeiro 	uint16_t elts_head = txq->elts_head;
1016b4b12e55SNélio Laranjeiro 	const unsigned int elts_n = 1 << txq->elts_n;
1017c3d62cc9SAdrien Mazarguil 	unsigned int i = 0;
1018a5bf6af9SAdrien Mazarguil 	unsigned int j = 0;
1019230189d9SNélio Laranjeiro 	unsigned int max;
1020f04f1d51SNélio Laranjeiro 	uint16_t max_wqe;
1021230189d9SNélio Laranjeiro 	unsigned int comp;
10220e8679fcSNélio Laranjeiro 	unsigned int inline_room = txq->max_inline * RTE_CACHE_LINE_SIZE;
1023230189d9SNélio Laranjeiro 	struct mlx5_mpw mpw = {
1024230189d9SNélio Laranjeiro 		.state = MLX5_MPW_STATE_CLOSED,
1025230189d9SNélio Laranjeiro 	};
1026f04f1d51SNélio Laranjeiro 	/*
1027f04f1d51SNélio Laranjeiro 	 * Compute the maximum number of WQE which can be consumed by inline
1028f04f1d51SNélio Laranjeiro 	 * code.
1029f04f1d51SNélio Laranjeiro 	 * - 2 DSEG for:
1030f04f1d51SNélio Laranjeiro 	 *   - 1 control segment,
1031f04f1d51SNélio Laranjeiro 	 *   - 1 Ethernet segment,
1032f04f1d51SNélio Laranjeiro 	 * - N Dseg from the inline request.
1033f04f1d51SNélio Laranjeiro 	 */
1034f04f1d51SNélio Laranjeiro 	const unsigned int wqe_inl_n =
1035f04f1d51SNélio Laranjeiro 		((2 * MLX5_WQE_DWORD_SIZE +
1036f04f1d51SNélio Laranjeiro 		  txq->max_inline * RTE_CACHE_LINE_SIZE) +
1037f04f1d51SNélio Laranjeiro 		 RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE;
1038230189d9SNélio Laranjeiro 
1039c3d62cc9SAdrien Mazarguil 	if (unlikely(!pkts_n))
1040c3d62cc9SAdrien Mazarguil 		return 0;
1041230189d9SNélio Laranjeiro 	/* Prefetch first packet cacheline. */
1042fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci));
1043fdcb0f53SNélio Laranjeiro 	rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1));
1044230189d9SNélio Laranjeiro 	/* Start processing. */
1045230189d9SNélio Laranjeiro 	txq_complete(txq);
1046230189d9SNélio Laranjeiro 	max = (elts_n - (elts_head - txq->elts_tail));
1047230189d9SNélio Laranjeiro 	if (max > elts_n)
1048230189d9SNélio Laranjeiro 		max -= elts_n;
1049c3d62cc9SAdrien Mazarguil 	do {
1050a5bf6af9SAdrien Mazarguil 		struct rte_mbuf *buf = *(pkts++);
1051c3d62cc9SAdrien Mazarguil 		unsigned int elts_head_next;
1052230189d9SNélio Laranjeiro 		uintptr_t addr;
1053230189d9SNélio Laranjeiro 		uint32_t length;
1054a5bf6af9SAdrien Mazarguil 		unsigned int segs_n = buf->nb_segs;
1055230189d9SNélio Laranjeiro 		uint32_t cs_flags = 0;
1056230189d9SNélio Laranjeiro 
1057c3d62cc9SAdrien Mazarguil 		/*
1058c3d62cc9SAdrien Mazarguil 		 * Make sure there is enough room to store this packet and
1059c3d62cc9SAdrien Mazarguil 		 * that one ring entry remains unused.
1060c3d62cc9SAdrien Mazarguil 		 */
1061a5bf6af9SAdrien Mazarguil 		assert(segs_n);
1062a5bf6af9SAdrien Mazarguil 		if (max < segs_n + 1)
1063c3d62cc9SAdrien Mazarguil 			break;
1064a5bf6af9SAdrien Mazarguil 		/* Do not bother with large packets MPW cannot handle. */
1065a5bf6af9SAdrien Mazarguil 		if (segs_n > MLX5_MPW_DSEG_MAX)
1066a5bf6af9SAdrien Mazarguil 			break;
1067a5bf6af9SAdrien Mazarguil 		max -= segs_n;
1068c3d62cc9SAdrien Mazarguil 		--pkts_n;
1069f04f1d51SNélio Laranjeiro 		/*
1070f04f1d51SNélio Laranjeiro 		 * Compute max_wqe in case less WQE were consumed in previous
1071f04f1d51SNélio Laranjeiro 		 * iteration.
1072f04f1d51SNélio Laranjeiro 		 */
1073f04f1d51SNélio Laranjeiro 		max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi);
1074230189d9SNélio Laranjeiro 		/* Should we enable HW CKSUM offload */
1075230189d9SNélio Laranjeiro 		if (buf->ol_flags &
1076230189d9SNélio Laranjeiro 		    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))
1077230189d9SNélio Laranjeiro 			cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
1078a5bf6af9SAdrien Mazarguil 		/* Retrieve packet information. */
1079a5bf6af9SAdrien Mazarguil 		length = PKT_LEN(buf);
1080230189d9SNélio Laranjeiro 		/* Start new session if packet differs. */
1081230189d9SNélio Laranjeiro 		if (mpw.state == MLX5_MPW_STATE_OPENED) {
1082230189d9SNélio Laranjeiro 			if ((mpw.len != length) ||
1083a5bf6af9SAdrien Mazarguil 			    (segs_n != 1) ||
10848688b2f8SNélio Laranjeiro 			    (mpw.wqe->eseg.cs_flags != cs_flags))
1085230189d9SNélio Laranjeiro 				mlx5_mpw_close(txq, &mpw);
1086230189d9SNélio Laranjeiro 		} else if (mpw.state == MLX5_MPW_INL_STATE_OPENED) {
1087230189d9SNélio Laranjeiro 			if ((mpw.len != length) ||
1088a5bf6af9SAdrien Mazarguil 			    (segs_n != 1) ||
1089230189d9SNélio Laranjeiro 			    (length > inline_room) ||
10908688b2f8SNélio Laranjeiro 			    (mpw.wqe->eseg.cs_flags != cs_flags)) {
1091230189d9SNélio Laranjeiro 				mlx5_mpw_inline_close(txq, &mpw);
10920e8679fcSNélio Laranjeiro 				inline_room =
10930e8679fcSNélio Laranjeiro 					txq->max_inline * RTE_CACHE_LINE_SIZE;
1094230189d9SNélio Laranjeiro 			}
1095230189d9SNélio Laranjeiro 		}
1096230189d9SNélio Laranjeiro 		if (mpw.state == MLX5_MPW_STATE_CLOSED) {
1097a5bf6af9SAdrien Mazarguil 			if ((segs_n != 1) ||
1098a5bf6af9SAdrien Mazarguil 			    (length > inline_room)) {
1099f04f1d51SNélio Laranjeiro 				/*
1100f04f1d51SNélio Laranjeiro 				 * Multi-Packet WQE consumes at most two WQE.
1101f04f1d51SNélio Laranjeiro 				 * mlx5_mpw_new() expects to be able to use
1102f04f1d51SNélio Laranjeiro 				 * such resources.
1103f04f1d51SNélio Laranjeiro 				 */
1104f04f1d51SNélio Laranjeiro 				if (unlikely(max_wqe < 2))
1105f04f1d51SNélio Laranjeiro 					break;
1106f04f1d51SNélio Laranjeiro 				max_wqe -= 2;
1107230189d9SNélio Laranjeiro 				mlx5_mpw_new(txq, &mpw, length);
11088688b2f8SNélio Laranjeiro 				mpw.wqe->eseg.cs_flags = cs_flags;
1109230189d9SNélio Laranjeiro 			} else {
1110f04f1d51SNélio Laranjeiro 				if (unlikely(max_wqe < wqe_inl_n))
1111f04f1d51SNélio Laranjeiro 					break;
1112f04f1d51SNélio Laranjeiro 				max_wqe -= wqe_inl_n;
1113230189d9SNélio Laranjeiro 				mlx5_mpw_inline_new(txq, &mpw, length);
11148688b2f8SNélio Laranjeiro 				mpw.wqe->eseg.cs_flags = cs_flags;
1115230189d9SNélio Laranjeiro 			}
1116230189d9SNélio Laranjeiro 		}
1117a5bf6af9SAdrien Mazarguil 		/* Multi-segment packets must be alone in their MPW. */
1118a5bf6af9SAdrien Mazarguil 		assert((segs_n == 1) || (mpw.pkts_n == 0));
1119230189d9SNélio Laranjeiro 		if (mpw.state == MLX5_MPW_STATE_OPENED) {
11200e8679fcSNélio Laranjeiro 			assert(inline_room ==
11210e8679fcSNélio Laranjeiro 			       txq->max_inline * RTE_CACHE_LINE_SIZE);
1122a5bf6af9SAdrien Mazarguil #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
1123a5bf6af9SAdrien Mazarguil 			length = 0;
1124a5bf6af9SAdrien Mazarguil #endif
1125a5bf6af9SAdrien Mazarguil 			do {
1126230189d9SNélio Laranjeiro 				volatile struct mlx5_wqe_data_seg *dseg;
1127230189d9SNélio Laranjeiro 
1128a5bf6af9SAdrien Mazarguil 				elts_head_next =
1129a5bf6af9SAdrien Mazarguil 					(elts_head + 1) & (elts_n - 1);
1130a5bf6af9SAdrien Mazarguil 				assert(buf);
1131a5bf6af9SAdrien Mazarguil 				(*txq->elts)[elts_head] = buf;
1132230189d9SNélio Laranjeiro 				dseg = mpw.data.dseg[mpw.pkts_n];
1133a5bf6af9SAdrien Mazarguil 				addr = rte_pktmbuf_mtod(buf, uintptr_t);
1134230189d9SNélio Laranjeiro 				*dseg = (struct mlx5_wqe_data_seg){
1135a5bf6af9SAdrien Mazarguil 					.byte_count = htonl(DATA_LEN(buf)),
1136230189d9SNélio Laranjeiro 					.lkey = txq_mp2mr(txq, txq_mb2mp(buf)),
1137230189d9SNélio Laranjeiro 					.addr = htonll(addr),
1138230189d9SNélio Laranjeiro 				};
1139a5bf6af9SAdrien Mazarguil 				elts_head = elts_head_next;
1140a5bf6af9SAdrien Mazarguil #if defined(MLX5_PMD_SOFT_COUNTERS) || !defined(NDEBUG)
1141a5bf6af9SAdrien Mazarguil 				length += DATA_LEN(buf);
1142a5bf6af9SAdrien Mazarguil #endif
1143a5bf6af9SAdrien Mazarguil 				buf = buf->next;
1144230189d9SNélio Laranjeiro 				++mpw.pkts_n;
1145a5bf6af9SAdrien Mazarguil 				++j;
1146a5bf6af9SAdrien Mazarguil 			} while (--segs_n);
1147a5bf6af9SAdrien Mazarguil 			assert(length == mpw.len);
1148230189d9SNélio Laranjeiro 			if (mpw.pkts_n == MLX5_MPW_DSEG_MAX)
1149230189d9SNélio Laranjeiro 				mlx5_mpw_close(txq, &mpw);
1150230189d9SNélio Laranjeiro 		} else {
1151230189d9SNélio Laranjeiro 			unsigned int max;
1152230189d9SNélio Laranjeiro 
1153230189d9SNélio Laranjeiro 			assert(mpw.state == MLX5_MPW_INL_STATE_OPENED);
1154230189d9SNélio Laranjeiro 			assert(length <= inline_room);
1155a5bf6af9SAdrien Mazarguil 			assert(length == DATA_LEN(buf));
1156a5bf6af9SAdrien Mazarguil 			elts_head_next = (elts_head + 1) & (elts_n - 1);
1157a5bf6af9SAdrien Mazarguil 			addr = rte_pktmbuf_mtod(buf, uintptr_t);
1158a5bf6af9SAdrien Mazarguil 			(*txq->elts)[elts_head] = buf;
1159230189d9SNélio Laranjeiro 			/* Maximum number of bytes before wrapping. */
1160fdcb0f53SNélio Laranjeiro 			max = ((((uintptr_t)(txq->wqes)) +
1161fdcb0f53SNélio Laranjeiro 				(1 << txq->wqe_n) *
1162fdcb0f53SNélio Laranjeiro 				MLX5_WQE_SIZE) -
1163230189d9SNélio Laranjeiro 			       (uintptr_t)mpw.data.raw);
1164230189d9SNélio Laranjeiro 			if (length > max) {
1165230189d9SNélio Laranjeiro 				rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1166230189d9SNélio Laranjeiro 					   (void *)addr,
1167230189d9SNélio Laranjeiro 					   max);
1168fdcb0f53SNélio Laranjeiro 				mpw.data.raw = (volatile void *)txq->wqes;
1169230189d9SNélio Laranjeiro 				rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1170230189d9SNélio Laranjeiro 					   (void *)(addr + max),
1171230189d9SNélio Laranjeiro 					   length - max);
1172230189d9SNélio Laranjeiro 				mpw.data.raw += length - max;
1173230189d9SNélio Laranjeiro 			} else {
1174230189d9SNélio Laranjeiro 				rte_memcpy((void *)(uintptr_t)mpw.data.raw,
1175230189d9SNélio Laranjeiro 					   (void *)addr,
1176230189d9SNélio Laranjeiro 					   length);
117716c64768SYongseok Koh 
117816c64768SYongseok Koh 				if (length == max)
117916c64768SYongseok Koh 					mpw.data.raw =
118016c64768SYongseok Koh 						(volatile void *)txq->wqes;
118116c64768SYongseok Koh 				else
1182230189d9SNélio Laranjeiro 					mpw.data.raw += length;
1183230189d9SNélio Laranjeiro 			}
1184230189d9SNélio Laranjeiro 			++mpw.pkts_n;
118576bf1574SYongseok Koh 			mpw.total_len += length;
1186a5bf6af9SAdrien Mazarguil 			++j;
1187230189d9SNélio Laranjeiro 			if (mpw.pkts_n == MLX5_MPW_DSEG_MAX) {
1188230189d9SNélio Laranjeiro 				mlx5_mpw_inline_close(txq, &mpw);
11890e8679fcSNélio Laranjeiro 				inline_room =
11900e8679fcSNélio Laranjeiro 					txq->max_inline * RTE_CACHE_LINE_SIZE;
1191230189d9SNélio Laranjeiro 			} else {
1192230189d9SNélio Laranjeiro 				inline_room -= length;
1193230189d9SNélio Laranjeiro 			}
1194230189d9SNélio Laranjeiro 		}
1195230189d9SNélio Laranjeiro 		elts_head = elts_head_next;
1196230189d9SNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
1197230189d9SNélio Laranjeiro 		/* Increment sent bytes counter. */
1198230189d9SNélio Laranjeiro 		txq->stats.obytes += length;
1199230189d9SNélio Laranjeiro #endif
1200c3d62cc9SAdrien Mazarguil 		++i;
1201c3d62cc9SAdrien Mazarguil 	} while (pkts_n);
1202230189d9SNélio Laranjeiro 	/* Take a shortcut if nothing must be sent. */
1203230189d9SNélio Laranjeiro 	if (unlikely(i == 0))
1204230189d9SNélio Laranjeiro 		return 0;
1205230189d9SNélio Laranjeiro 	/* Check whether completion threshold has been reached. */
1206a5bf6af9SAdrien Mazarguil 	/* "j" includes both packets and segments. */
1207a5bf6af9SAdrien Mazarguil 	comp = txq->elts_comp + j;
1208230189d9SNélio Laranjeiro 	if (comp >= MLX5_TX_COMP_THRESH) {
12098688b2f8SNélio Laranjeiro 		volatile struct mlx5_wqe *wqe = mpw.wqe;
1210230189d9SNélio Laranjeiro 
1211230189d9SNélio Laranjeiro 		/* Request completion on last WQE. */
12128688b2f8SNélio Laranjeiro 		wqe->ctrl[2] = htonl(8);
1213230189d9SNélio Laranjeiro 		/* Save elts_head in unused "immediate" field of WQE. */
12148688b2f8SNélio Laranjeiro 		wqe->ctrl[3] = elts_head;
1215230189d9SNélio Laranjeiro 		txq->elts_comp = 0;
1216230189d9SNélio Laranjeiro 	} else {
1217230189d9SNélio Laranjeiro 		txq->elts_comp = comp;
1218230189d9SNélio Laranjeiro 	}
1219230189d9SNélio Laranjeiro #ifdef MLX5_PMD_SOFT_COUNTERS
1220230189d9SNélio Laranjeiro 	/* Increment sent packets counter. */
1221230189d9SNélio Laranjeiro 	txq->stats.opackets += i;
1222230189d9SNélio Laranjeiro #endif
1223230189d9SNélio Laranjeiro 	/* Ring QP doorbell. */
1224230189d9SNélio Laranjeiro 	if (mpw.state == MLX5_MPW_INL_STATE_OPENED)
1225230189d9SNélio Laranjeiro 		mlx5_mpw_inline_close(txq, &mpw);
1226230189d9SNélio Laranjeiro 	else if (mpw.state == MLX5_MPW_STATE_OPENED)
1227230189d9SNélio Laranjeiro 		mlx5_mpw_close(txq, &mpw);
122830807f62SNélio Laranjeiro 	mlx5_tx_dbrec(txq, mpw.wqe);
1229230189d9SNélio Laranjeiro 	txq->elts_head = elts_head;
1230230189d9SNélio Laranjeiro 	return i;
1231230189d9SNélio Laranjeiro }
1232230189d9SNélio Laranjeiro 
1233230189d9SNélio Laranjeiro /**
123467fa62bcSAdrien Mazarguil  * Translate RX completion flags to packet type.
123567fa62bcSAdrien Mazarguil  *
12366218063bSNélio Laranjeiro  * @param[in] cqe
12376218063bSNélio Laranjeiro  *   Pointer to CQE.
123867fa62bcSAdrien Mazarguil  *
123978a38edfSJianfeng Tan  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
124078a38edfSJianfeng Tan  *
124167fa62bcSAdrien Mazarguil  * @return
124267fa62bcSAdrien Mazarguil  *   Packet type for struct rte_mbuf.
124367fa62bcSAdrien Mazarguil  */
124467fa62bcSAdrien Mazarguil static inline uint32_t
124597267b8eSNelio Laranjeiro rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
124667fa62bcSAdrien Mazarguil {
124767fa62bcSAdrien Mazarguil 	uint32_t pkt_type;
12480603df73SNélio Laranjeiro 	uint16_t flags = ntohs(cqe->hdr_type_etc);
124967fa62bcSAdrien Mazarguil 
12500603df73SNélio Laranjeiro 	if (cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) {
125167fa62bcSAdrien Mazarguil 		pkt_type =
125267fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
1253350f4c48SNelio Laranjeiro 				  MLX5_CQE_RX_IPV4_PACKET,
1254501505c5SMatthieu Ternisien d'Ouville 				  RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN) |
125567fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
1256350f4c48SNelio Laranjeiro 				  MLX5_CQE_RX_IPV6_PACKET,
1257501505c5SMatthieu Ternisien d'Ouville 				  RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN);
12580603df73SNélio Laranjeiro 		pkt_type |= ((cqe->pkt_info & MLX5_CQE_RX_OUTER_PACKET) ?
12590603df73SNélio Laranjeiro 			     RTE_PTYPE_L3_IPV6_EXT_UNKNOWN :
12600603df73SNélio Laranjeiro 			     RTE_PTYPE_L3_IPV4_EXT_UNKNOWN);
12610603df73SNélio Laranjeiro 	} else {
126267fa62bcSAdrien Mazarguil 		pkt_type =
126367fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
12646218063bSNélio Laranjeiro 				  MLX5_CQE_L3_HDR_TYPE_IPV6,
1265501505c5SMatthieu Ternisien d'Ouville 				  RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) |
126667fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
12676218063bSNélio Laranjeiro 				  MLX5_CQE_L3_HDR_TYPE_IPV4,
1268501505c5SMatthieu Ternisien d'Ouville 				  RTE_PTYPE_L3_IPV4_EXT_UNKNOWN);
12690603df73SNélio Laranjeiro 	}
127067fa62bcSAdrien Mazarguil 	return pkt_type;
127167fa62bcSAdrien Mazarguil }
127267fa62bcSAdrien Mazarguil 
127367fa62bcSAdrien Mazarguil /**
127499c12dccSNélio Laranjeiro  * Get size of the next packet for a given CQE. For compressed CQEs, the
127599c12dccSNélio Laranjeiro  * consumer index is updated only once all packets of the current one have
127699c12dccSNélio Laranjeiro  * been processed.
127799c12dccSNélio Laranjeiro  *
127899c12dccSNélio Laranjeiro  * @param rxq
127999c12dccSNélio Laranjeiro  *   Pointer to RX queue.
128099c12dccSNélio Laranjeiro  * @param cqe
128199c12dccSNélio Laranjeiro  *   CQE to process.
1282ecf60761SNélio Laranjeiro  * @param[out] rss_hash
1283ecf60761SNélio Laranjeiro  *   Packet RSS Hash result.
128499c12dccSNélio Laranjeiro  *
128599c12dccSNélio Laranjeiro  * @return
128699c12dccSNélio Laranjeiro  *   Packet size in bytes (0 if there is none), -1 in case of completion
128799c12dccSNélio Laranjeiro  *   with error.
128899c12dccSNélio Laranjeiro  */
128999c12dccSNélio Laranjeiro static inline int
129097267b8eSNelio Laranjeiro mlx5_rx_poll_len(struct rxq *rxq, volatile struct mlx5_cqe *cqe,
1291ecf60761SNélio Laranjeiro 		 uint16_t cqe_cnt, uint32_t *rss_hash)
129299c12dccSNélio Laranjeiro {
129399c12dccSNélio Laranjeiro 	struct rxq_zip *zip = &rxq->zip;
129499c12dccSNélio Laranjeiro 	uint16_t cqe_n = cqe_cnt + 1;
129599c12dccSNélio Laranjeiro 	int len = 0;
1296d2e842d0SYongseok Koh 	uint16_t idx, end;
129799c12dccSNélio Laranjeiro 
129899c12dccSNélio Laranjeiro 	/* Process compressed data in the CQE and mini arrays. */
129999c12dccSNélio Laranjeiro 	if (zip->ai) {
130099c12dccSNélio Laranjeiro 		volatile struct mlx5_mini_cqe8 (*mc)[8] =
130199c12dccSNélio Laranjeiro 			(volatile struct mlx5_mini_cqe8 (*)[8])
130297267b8eSNelio Laranjeiro 			(uintptr_t)(&(*rxq->cqes)[zip->ca & cqe_cnt]);
130399c12dccSNélio Laranjeiro 
130499c12dccSNélio Laranjeiro 		len = ntohl((*mc)[zip->ai & 7].byte_cnt);
1305ecf60761SNélio Laranjeiro 		*rss_hash = ntohl((*mc)[zip->ai & 7].rx_hash_result);
130699c12dccSNélio Laranjeiro 		if ((++zip->ai & 7) == 0) {
1307d2e842d0SYongseok Koh 			/* Invalidate consumed CQEs */
1308d2e842d0SYongseok Koh 			idx = zip->ca;
1309d2e842d0SYongseok Koh 			end = zip->na;
1310d2e842d0SYongseok Koh 			while (idx != end) {
1311d2e842d0SYongseok Koh 				(*rxq->cqes)[idx & cqe_cnt].op_own =
1312d2e842d0SYongseok Koh 					MLX5_CQE_INVALIDATE;
1313d2e842d0SYongseok Koh 				++idx;
1314d2e842d0SYongseok Koh 			}
131599c12dccSNélio Laranjeiro 			/*
131699c12dccSNélio Laranjeiro 			 * Increment consumer index to skip the number of
131799c12dccSNélio Laranjeiro 			 * CQEs consumed. Hardware leaves holes in the CQ
131899c12dccSNélio Laranjeiro 			 * ring for software use.
131999c12dccSNélio Laranjeiro 			 */
132099c12dccSNélio Laranjeiro 			zip->ca = zip->na;
132199c12dccSNélio Laranjeiro 			zip->na += 8;
132299c12dccSNélio Laranjeiro 		}
132399c12dccSNélio Laranjeiro 		if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
1324d2e842d0SYongseok Koh 			/* Invalidate the rest */
1325d2e842d0SYongseok Koh 			idx = zip->ca;
1326d2e842d0SYongseok Koh 			end = zip->cq_ci;
132799c12dccSNélio Laranjeiro 
132899c12dccSNélio Laranjeiro 			while (idx != end) {
132997267b8eSNelio Laranjeiro 				(*rxq->cqes)[idx & cqe_cnt].op_own =
133099c12dccSNélio Laranjeiro 					MLX5_CQE_INVALIDATE;
133199c12dccSNélio Laranjeiro 				++idx;
133299c12dccSNélio Laranjeiro 			}
133399c12dccSNélio Laranjeiro 			rxq->cq_ci = zip->cq_ci;
133499c12dccSNélio Laranjeiro 			zip->ai = 0;
133599c12dccSNélio Laranjeiro 		}
133699c12dccSNélio Laranjeiro 	/* No compressed data, get next CQE and verify if it is compressed. */
133799c12dccSNélio Laranjeiro 	} else {
133899c12dccSNélio Laranjeiro 		int ret;
133999c12dccSNélio Laranjeiro 		int8_t op_own;
134099c12dccSNélio Laranjeiro 
134197267b8eSNelio Laranjeiro 		ret = check_cqe(cqe, cqe_n, rxq->cq_ci);
134299c12dccSNélio Laranjeiro 		if (unlikely(ret == 1))
134399c12dccSNélio Laranjeiro 			return 0;
134499c12dccSNélio Laranjeiro 		++rxq->cq_ci;
134599c12dccSNélio Laranjeiro 		op_own = cqe->op_own;
134699c12dccSNélio Laranjeiro 		if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
134799c12dccSNélio Laranjeiro 			volatile struct mlx5_mini_cqe8 (*mc)[8] =
134899c12dccSNélio Laranjeiro 				(volatile struct mlx5_mini_cqe8 (*)[8])
134999c12dccSNélio Laranjeiro 				(uintptr_t)(&(*rxq->cqes)[rxq->cq_ci &
135097267b8eSNelio Laranjeiro 							  cqe_cnt]);
135199c12dccSNélio Laranjeiro 
135299c12dccSNélio Laranjeiro 			/* Fix endianness. */
135399c12dccSNélio Laranjeiro 			zip->cqe_cnt = ntohl(cqe->byte_cnt);
135499c12dccSNélio Laranjeiro 			/*
135599c12dccSNélio Laranjeiro 			 * Current mini array position is the one returned by
135699c12dccSNélio Laranjeiro 			 * check_cqe64().
135799c12dccSNélio Laranjeiro 			 *
135899c12dccSNélio Laranjeiro 			 * If completion comprises several mini arrays, as a
135999c12dccSNélio Laranjeiro 			 * special case the second one is located 7 CQEs after
136099c12dccSNélio Laranjeiro 			 * the initial CQE instead of 8 for subsequent ones.
136199c12dccSNélio Laranjeiro 			 */
1362d2e842d0SYongseok Koh 			zip->ca = rxq->cq_ci;
136399c12dccSNélio Laranjeiro 			zip->na = zip->ca + 7;
136499c12dccSNélio Laranjeiro 			/* Compute the next non compressed CQE. */
136599c12dccSNélio Laranjeiro 			--rxq->cq_ci;
136699c12dccSNélio Laranjeiro 			zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
136799c12dccSNélio Laranjeiro 			/* Get packet size to return. */
136899c12dccSNélio Laranjeiro 			len = ntohl((*mc)[0].byte_cnt);
1369ecf60761SNélio Laranjeiro 			*rss_hash = ntohl((*mc)[0].rx_hash_result);
137099c12dccSNélio Laranjeiro 			zip->ai = 1;
1371d2e842d0SYongseok Koh 			/* Prefetch all the entries to be invalidated */
1372d2e842d0SYongseok Koh 			idx = zip->ca;
1373d2e842d0SYongseok Koh 			end = zip->cq_ci;
1374d2e842d0SYongseok Koh 			while (idx != end) {
1375d2e842d0SYongseok Koh 				rte_prefetch0(&(*rxq->cqes)[(idx) & cqe_cnt]);
1376d2e842d0SYongseok Koh 				++idx;
1377d2e842d0SYongseok Koh 			}
137899c12dccSNélio Laranjeiro 		} else {
137999c12dccSNélio Laranjeiro 			len = ntohl(cqe->byte_cnt);
1380ecf60761SNélio Laranjeiro 			*rss_hash = ntohl(cqe->rx_hash_res);
138199c12dccSNélio Laranjeiro 		}
138299c12dccSNélio Laranjeiro 		/* Error while receiving packet. */
138399c12dccSNélio Laranjeiro 		if (unlikely(MLX5_CQE_OPCODE(op_own) == MLX5_CQE_RESP_ERR))
138499c12dccSNélio Laranjeiro 			return -1;
138599c12dccSNélio Laranjeiro 	}
138699c12dccSNélio Laranjeiro 	return len;
138799c12dccSNélio Laranjeiro }
138899c12dccSNélio Laranjeiro 
138999c12dccSNélio Laranjeiro /**
139067fa62bcSAdrien Mazarguil  * Translate RX completion flags to offload flags.
139167fa62bcSAdrien Mazarguil  *
139267fa62bcSAdrien Mazarguil  * @param[in] rxq
139367fa62bcSAdrien Mazarguil  *   Pointer to RX queue structure.
13946218063bSNélio Laranjeiro  * @param[in] cqe
13956218063bSNélio Laranjeiro  *   Pointer to CQE.
139667fa62bcSAdrien Mazarguil  *
139767fa62bcSAdrien Mazarguil  * @return
139867fa62bcSAdrien Mazarguil  *   Offload flags (ol_flags) for struct rte_mbuf.
139967fa62bcSAdrien Mazarguil  */
140067fa62bcSAdrien Mazarguil static inline uint32_t
140197267b8eSNelio Laranjeiro rxq_cq_to_ol_flags(struct rxq *rxq, volatile struct mlx5_cqe *cqe)
140267fa62bcSAdrien Mazarguil {
140367fa62bcSAdrien Mazarguil 	uint32_t ol_flags = 0;
14040603df73SNélio Laranjeiro 	uint16_t flags = ntohs(cqe->hdr_type_etc);
140567fa62bcSAdrien Mazarguil 
14060603df73SNélio Laranjeiro 	ol_flags =
14070603df73SNélio Laranjeiro 		TRANSPOSE(flags,
14080603df73SNélio Laranjeiro 			  MLX5_CQE_RX_L3_HDR_VALID,
14090603df73SNélio Laranjeiro 			  PKT_RX_IP_CKSUM_GOOD) |
14100603df73SNélio Laranjeiro 		TRANSPOSE(flags,
14110603df73SNélio Laranjeiro 			  MLX5_CQE_RX_L4_HDR_VALID,
141283e9d9a3SNelio Laranjeiro 			  PKT_RX_L4_CKSUM_GOOD);
141397267b8eSNelio Laranjeiro 	if ((cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
141467fa62bcSAdrien Mazarguil 		ol_flags |=
14150603df73SNélio Laranjeiro 			TRANSPOSE(flags,
14160603df73SNélio Laranjeiro 				  MLX5_CQE_RX_L3_HDR_VALID,
141783e9d9a3SNelio Laranjeiro 				  PKT_RX_IP_CKSUM_GOOD) |
14180603df73SNélio Laranjeiro 			TRANSPOSE(flags,
14190603df73SNélio Laranjeiro 				  MLX5_CQE_RX_L4_HDR_VALID,
142083e9d9a3SNelio Laranjeiro 				  PKT_RX_L4_CKSUM_GOOD);
142167fa62bcSAdrien Mazarguil 	return ol_flags;
142267fa62bcSAdrien Mazarguil }
142367fa62bcSAdrien Mazarguil 
142467fa62bcSAdrien Mazarguil /**
14252e22920bSAdrien Mazarguil  * DPDK callback for RX.
14262e22920bSAdrien Mazarguil  *
14272e22920bSAdrien Mazarguil  * @param dpdk_rxq
14282e22920bSAdrien Mazarguil  *   Generic pointer to RX queue structure.
14292e22920bSAdrien Mazarguil  * @param[out] pkts
14302e22920bSAdrien Mazarguil  *   Array to store received packets.
14312e22920bSAdrien Mazarguil  * @param pkts_n
14322e22920bSAdrien Mazarguil  *   Maximum number of packets in array.
14332e22920bSAdrien Mazarguil  *
14342e22920bSAdrien Mazarguil  * @return
14352e22920bSAdrien Mazarguil  *   Number of packets successfully received (<= pkts_n).
14362e22920bSAdrien Mazarguil  */
14372e22920bSAdrien Mazarguil uint16_t
14382e22920bSAdrien Mazarguil mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
14392e22920bSAdrien Mazarguil {
14406218063bSNélio Laranjeiro 	struct rxq *rxq = dpdk_rxq;
1441b4b12e55SNélio Laranjeiro 	const unsigned int wqe_cnt = (1 << rxq->elts_n) - 1;
1442e2f116eeSNélio Laranjeiro 	const unsigned int cqe_cnt = (1 << rxq->cqe_n) - 1;
14439964b965SNélio Laranjeiro 	const unsigned int sges_n = rxq->sges_n;
14449964b965SNélio Laranjeiro 	struct rte_mbuf *pkt = NULL;
14459964b965SNélio Laranjeiro 	struct rte_mbuf *seg = NULL;
144697267b8eSNelio Laranjeiro 	volatile struct mlx5_cqe *cqe =
144797267b8eSNelio Laranjeiro 		&(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
14489964b965SNélio Laranjeiro 	unsigned int i = 0;
14499964b965SNélio Laranjeiro 	unsigned int rq_ci = rxq->rq_ci << sges_n;
1450ecf60761SNélio Laranjeiro 	int len; /* keep its value across iterations. */
14512e22920bSAdrien Mazarguil 
14529964b965SNélio Laranjeiro 	while (pkts_n) {
14539964b965SNélio Laranjeiro 		unsigned int idx = rq_ci & wqe_cnt;
14549964b965SNélio Laranjeiro 		volatile struct mlx5_wqe_data_seg *wqe = &(*rxq->wqes)[idx];
14559964b965SNélio Laranjeiro 		struct rte_mbuf *rep = (*rxq->elts)[idx];
1456ecf60761SNélio Laranjeiro 		uint32_t rss_hash_res = 0;
14579964b965SNélio Laranjeiro 
14589964b965SNélio Laranjeiro 		if (pkt)
14599964b965SNélio Laranjeiro 			NEXT(seg) = rep;
14609964b965SNélio Laranjeiro 		seg = rep;
14619964b965SNélio Laranjeiro 		rte_prefetch0(seg);
14626218063bSNélio Laranjeiro 		rte_prefetch0(cqe);
14639964b965SNélio Laranjeiro 		rte_prefetch0(wqe);
1464fbfd9955SOlivier Matz 		rep = rte_mbuf_raw_alloc(rxq->mp);
14652e22920bSAdrien Mazarguil 		if (unlikely(rep == NULL)) {
146615a756b6SSagi Grimberg 			++rxq->stats.rx_nombuf;
146715a756b6SSagi Grimberg 			if (!pkt) {
146815a756b6SSagi Grimberg 				/*
146915a756b6SSagi Grimberg 				 * no buffers before we even started,
147015a756b6SSagi Grimberg 				 * bail out silently.
147115a756b6SSagi Grimberg 				 */
147215a756b6SSagi Grimberg 				break;
147315a756b6SSagi Grimberg 			}
1474a1bdb71aSNélio Laranjeiro 			while (pkt != seg) {
1475a1bdb71aSNélio Laranjeiro 				assert(pkt != (*rxq->elts)[idx]);
1476fe5fe382SNélio Laranjeiro 				rep = NEXT(pkt);
14779964b965SNélio Laranjeiro 				rte_mbuf_refcnt_set(pkt, 0);
14789964b965SNélio Laranjeiro 				__rte_mbuf_raw_free(pkt);
1479fe5fe382SNélio Laranjeiro 				pkt = rep;
14809964b965SNélio Laranjeiro 			}
14816218063bSNélio Laranjeiro 			break;
14822e22920bSAdrien Mazarguil 		}
14839964b965SNélio Laranjeiro 		if (!pkt) {
148497267b8eSNelio Laranjeiro 			cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt];
1485ecf60761SNélio Laranjeiro 			len = mlx5_rx_poll_len(rxq, cqe, cqe_cnt,
1486ecf60761SNélio Laranjeiro 					       &rss_hash_res);
1487ecf60761SNélio Laranjeiro 			if (!len) {
14886218063bSNélio Laranjeiro 				rte_mbuf_refcnt_set(rep, 0);
14896218063bSNélio Laranjeiro 				__rte_mbuf_raw_free(rep);
14906218063bSNélio Laranjeiro 				break;
14916218063bSNélio Laranjeiro 			}
149299c12dccSNélio Laranjeiro 			if (unlikely(len == -1)) {
149399c12dccSNélio Laranjeiro 				/* RX error, packet is likely too large. */
149499c12dccSNélio Laranjeiro 				rte_mbuf_refcnt_set(rep, 0);
149599c12dccSNélio Laranjeiro 				__rte_mbuf_raw_free(rep);
149699c12dccSNélio Laranjeiro 				++rxq->stats.idropped;
149799c12dccSNélio Laranjeiro 				goto skip;
149899c12dccSNélio Laranjeiro 			}
14999964b965SNélio Laranjeiro 			pkt = seg;
15009964b965SNélio Laranjeiro 			assert(len >= (rxq->crc_present << 2));
15019964b965SNélio Laranjeiro 			/* Update packet information. */
15020ac64846SMaxime Leroy 			pkt->packet_type = 0;
15030ac64846SMaxime Leroy 			pkt->ol_flags = 0;
150436ba0c00SNélio Laranjeiro 			if (rss_hash_res && rxq->rss_hash) {
1505ecf60761SNélio Laranjeiro 				pkt->hash.rss = rss_hash_res;
1506ecf60761SNélio Laranjeiro 				pkt->ol_flags = PKT_RX_RSS_HASH;
1507ecf60761SNélio Laranjeiro 			}
1508ea3bc3b1SNélio Laranjeiro 			if (rxq->mark &&
1509ea3bc3b1SNélio Laranjeiro 			    ((cqe->sop_drop_qpn !=
1510ea3bc3b1SNélio Laranjeiro 			      htonl(MLX5_FLOW_MARK_INVALID)) ||
1511ea3bc3b1SNélio Laranjeiro 			     (cqe->sop_drop_qpn !=
1512ea3bc3b1SNélio Laranjeiro 			      htonl(MLX5_FLOW_MARK_DEFAULT)))) {
1513ea3bc3b1SNélio Laranjeiro 				pkt->hash.fdir.hi =
1514ea3bc3b1SNélio Laranjeiro 					mlx5_flow_mark_get(cqe->sop_drop_qpn);
1515ea3bc3b1SNélio Laranjeiro 				pkt->ol_flags &= ~PKT_RX_RSS_HASH;
1516ea3bc3b1SNélio Laranjeiro 				pkt->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
1517ea3bc3b1SNélio Laranjeiro 			}
15186218063bSNélio Laranjeiro 			if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip |
15196218063bSNélio Laranjeiro 			    rxq->crc_present) {
15206218063bSNélio Laranjeiro 				if (rxq->csum) {
15219964b965SNélio Laranjeiro 					pkt->packet_type =
15229964b965SNélio Laranjeiro 						rxq_cq_to_pkt_type(cqe);
1523ecf60761SNélio Laranjeiro 					pkt->ol_flags |=
15249964b965SNélio Laranjeiro 						rxq_cq_to_ol_flags(rxq, cqe);
15256218063bSNélio Laranjeiro 				}
1526*9514fa2dSShahaf Shuler 				if (ntohs(cqe->hdr_type_etc) &
15279964b965SNélio Laranjeiro 				    MLX5_CQE_VLAN_STRIPPED) {
15286218063bSNélio Laranjeiro 					pkt->ol_flags |= PKT_RX_VLAN_PKT |
1529b37b528dSOlivier Matz 						PKT_RX_VLAN_STRIPPED;
15306218063bSNélio Laranjeiro 					pkt->vlan_tci = ntohs(cqe->vlan_info);
1531f3db9489SYaacov Hazan 				}
15326218063bSNélio Laranjeiro 				if (rxq->crc_present)
15336218063bSNélio Laranjeiro 					len -= ETHER_CRC_LEN;
1534081f7eaeSNelio Laranjeiro 			}
15356218063bSNélio Laranjeiro 			PKT_LEN(pkt) = len;
15369964b965SNélio Laranjeiro 		}
15379964b965SNélio Laranjeiro 		DATA_LEN(rep) = DATA_LEN(seg);
15389964b965SNélio Laranjeiro 		PKT_LEN(rep) = PKT_LEN(seg);
15399964b965SNélio Laranjeiro 		SET_DATA_OFF(rep, DATA_OFF(seg));
15409964b965SNélio Laranjeiro 		NB_SEGS(rep) = NB_SEGS(seg);
15419964b965SNélio Laranjeiro 		PORT(rep) = PORT(seg);
15429964b965SNélio Laranjeiro 		NEXT(rep) = NULL;
15439964b965SNélio Laranjeiro 		(*rxq->elts)[idx] = rep;
15449964b965SNélio Laranjeiro 		/*
15459964b965SNélio Laranjeiro 		 * Fill NIC descriptor with the new buffer.  The lkey and size
15469964b965SNélio Laranjeiro 		 * of the buffers are already known, only the buffer address
15479964b965SNélio Laranjeiro 		 * changes.
15489964b965SNélio Laranjeiro 		 */
15499964b965SNélio Laranjeiro 		wqe->addr = htonll(rte_pktmbuf_mtod(rep, uintptr_t));
15509964b965SNélio Laranjeiro 		if (len > DATA_LEN(seg)) {
15519964b965SNélio Laranjeiro 			len -= DATA_LEN(seg);
15529964b965SNélio Laranjeiro 			++NB_SEGS(pkt);
15539964b965SNélio Laranjeiro 			++rq_ci;
15549964b965SNélio Laranjeiro 			continue;
15559964b965SNélio Laranjeiro 		}
15569964b965SNélio Laranjeiro 		DATA_LEN(seg) = len;
155787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
155887011737SAdrien Mazarguil 		/* Increment bytes counter. */
15599964b965SNélio Laranjeiro 		rxq->stats.ibytes += PKT_LEN(pkt);
156087011737SAdrien Mazarguil #endif
15616218063bSNélio Laranjeiro 		/* Return packet. */
15626218063bSNélio Laranjeiro 		*(pkts++) = pkt;
15639964b965SNélio Laranjeiro 		pkt = NULL;
15649964b965SNélio Laranjeiro 		--pkts_n;
15659964b965SNélio Laranjeiro 		++i;
156699c12dccSNélio Laranjeiro skip:
15679964b965SNélio Laranjeiro 		/* Align consumer index to the next stride. */
15689964b965SNélio Laranjeiro 		rq_ci >>= sges_n;
15696218063bSNélio Laranjeiro 		++rq_ci;
15709964b965SNélio Laranjeiro 		rq_ci <<= sges_n;
15712e22920bSAdrien Mazarguil 	}
15729964b965SNélio Laranjeiro 	if (unlikely((i == 0) && ((rq_ci >> sges_n) == rxq->rq_ci)))
15732e22920bSAdrien Mazarguil 		return 0;
15746218063bSNélio Laranjeiro 	/* Update the consumer index. */
15759964b965SNélio Laranjeiro 	rxq->rq_ci = rq_ci >> sges_n;
15766218063bSNélio Laranjeiro 	rte_wmb();
15776218063bSNélio Laranjeiro 	*rxq->cq_db = htonl(rxq->cq_ci);
15786218063bSNélio Laranjeiro 	rte_wmb();
15796218063bSNélio Laranjeiro 	*rxq->rq_db = htonl(rxq->rq_ci);
158087011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
158187011737SAdrien Mazarguil 	/* Increment packets counter. */
15829964b965SNélio Laranjeiro 	rxq->stats.ipackets += i;
158387011737SAdrien Mazarguil #endif
15849964b965SNélio Laranjeiro 	return i;
15852e22920bSAdrien Mazarguil }
15862e22920bSAdrien Mazarguil 
15872e22920bSAdrien Mazarguil /**
15882e22920bSAdrien Mazarguil  * Dummy DPDK callback for TX.
15892e22920bSAdrien Mazarguil  *
15902e22920bSAdrien Mazarguil  * This function is used to temporarily replace the real callback during
15912e22920bSAdrien Mazarguil  * unsafe control operations on the queue, or in case of error.
15922e22920bSAdrien Mazarguil  *
15932e22920bSAdrien Mazarguil  * @param dpdk_txq
15942e22920bSAdrien Mazarguil  *   Generic pointer to TX queue structure.
15952e22920bSAdrien Mazarguil  * @param[in] pkts
15962e22920bSAdrien Mazarguil  *   Packets to transmit.
15972e22920bSAdrien Mazarguil  * @param pkts_n
15982e22920bSAdrien Mazarguil  *   Number of packets in array.
15992e22920bSAdrien Mazarguil  *
16002e22920bSAdrien Mazarguil  * @return
16012e22920bSAdrien Mazarguil  *   Number of packets successfully transmitted (<= pkts_n).
16022e22920bSAdrien Mazarguil  */
16032e22920bSAdrien Mazarguil uint16_t
16042e22920bSAdrien Mazarguil removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
16052e22920bSAdrien Mazarguil {
16062e22920bSAdrien Mazarguil 	(void)dpdk_txq;
16072e22920bSAdrien Mazarguil 	(void)pkts;
16082e22920bSAdrien Mazarguil 	(void)pkts_n;
16092e22920bSAdrien Mazarguil 	return 0;
16102e22920bSAdrien Mazarguil }
16112e22920bSAdrien Mazarguil 
16122e22920bSAdrien Mazarguil /**
16132e22920bSAdrien Mazarguil  * Dummy DPDK callback for RX.
16142e22920bSAdrien Mazarguil  *
16152e22920bSAdrien Mazarguil  * This function is used to temporarily replace the real callback during
16162e22920bSAdrien Mazarguil  * unsafe control operations on the queue, or in case of error.
16172e22920bSAdrien Mazarguil  *
16182e22920bSAdrien Mazarguil  * @param dpdk_rxq
16192e22920bSAdrien Mazarguil  *   Generic pointer to RX queue structure.
16202e22920bSAdrien Mazarguil  * @param[out] pkts
16212e22920bSAdrien Mazarguil  *   Array to store received packets.
16222e22920bSAdrien Mazarguil  * @param pkts_n
16232e22920bSAdrien Mazarguil  *   Maximum number of packets in array.
16242e22920bSAdrien Mazarguil  *
16252e22920bSAdrien Mazarguil  * @return
16262e22920bSAdrien Mazarguil  *   Number of packets successfully received (<= pkts_n).
16272e22920bSAdrien Mazarguil  */
16282e22920bSAdrien Mazarguil uint16_t
16292e22920bSAdrien Mazarguil removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
16302e22920bSAdrien Mazarguil {
16312e22920bSAdrien Mazarguil 	(void)dpdk_rxq;
16322e22920bSAdrien Mazarguil 	(void)pkts;
16332e22920bSAdrien Mazarguil 	(void)pkts_n;
16342e22920bSAdrien Mazarguil 	return 0;
16352e22920bSAdrien Mazarguil }
1636