xref: /dpdk/drivers/net/mlx5/mlx5_rxtx.c (revision 67fa62bc672decbd48bf0b4c19eb89dead4e90a4)
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
422e22920bSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic"
432e22920bSAdrien Mazarguil #endif
442e22920bSAdrien Mazarguil #include <infiniband/verbs.h>
452e22920bSAdrien Mazarguil #ifdef PEDANTIC
462e22920bSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic"
472e22920bSAdrien Mazarguil #endif
482e22920bSAdrien Mazarguil 
492e22920bSAdrien Mazarguil /* DPDK headers don't like -pedantic. */
502e22920bSAdrien Mazarguil #ifdef PEDANTIC
512e22920bSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic"
522e22920bSAdrien Mazarguil #endif
532e22920bSAdrien Mazarguil #include <rte_mbuf.h>
542e22920bSAdrien Mazarguil #include <rte_mempool.h>
552e22920bSAdrien Mazarguil #include <rte_prefetch.h>
562e22920bSAdrien Mazarguil #include <rte_common.h>
572e22920bSAdrien Mazarguil #include <rte_branch_prediction.h>
582e22920bSAdrien Mazarguil #ifdef PEDANTIC
592e22920bSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic"
602e22920bSAdrien Mazarguil #endif
612e22920bSAdrien Mazarguil 
622e22920bSAdrien Mazarguil #include "mlx5.h"
632e22920bSAdrien Mazarguil #include "mlx5_utils.h"
642e22920bSAdrien Mazarguil #include "mlx5_rxtx.h"
652e22920bSAdrien Mazarguil #include "mlx5_defs.h"
662e22920bSAdrien Mazarguil 
672e22920bSAdrien Mazarguil /**
682e22920bSAdrien Mazarguil  * Manage TX completions.
692e22920bSAdrien Mazarguil  *
702e22920bSAdrien Mazarguil  * When sending a burst, mlx5_tx_burst() posts several WRs.
712e22920bSAdrien Mazarguil  * To improve performance, a completion event is only required once every
722e22920bSAdrien Mazarguil  * MLX5_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information
732e22920bSAdrien Mazarguil  * for other WRs, but this information would not be used anyway.
742e22920bSAdrien Mazarguil  *
752e22920bSAdrien Mazarguil  * @param txq
762e22920bSAdrien Mazarguil  *   Pointer to TX queue structure.
772e22920bSAdrien Mazarguil  *
782e22920bSAdrien Mazarguil  * @return
792e22920bSAdrien Mazarguil  *   0 on success, -1 on failure.
802e22920bSAdrien Mazarguil  */
812e22920bSAdrien Mazarguil static int
822e22920bSAdrien Mazarguil txq_complete(struct txq *txq)
832e22920bSAdrien Mazarguil {
842e22920bSAdrien Mazarguil 	unsigned int elts_comp = txq->elts_comp;
852e22920bSAdrien Mazarguil 	unsigned int elts_tail = txq->elts_tail;
862e22920bSAdrien Mazarguil 	const unsigned int elts_n = txq->elts_n;
872e22920bSAdrien Mazarguil 	int wcs_n;
882e22920bSAdrien Mazarguil 
892e22920bSAdrien Mazarguil 	if (unlikely(elts_comp == 0))
902e22920bSAdrien Mazarguil 		return 0;
912e22920bSAdrien Mazarguil #ifdef DEBUG_SEND
922e22920bSAdrien Mazarguil 	DEBUG("%p: processing %u work requests completions",
932e22920bSAdrien Mazarguil 	      (void *)txq, elts_comp);
942e22920bSAdrien Mazarguil #endif
952e22920bSAdrien Mazarguil 	wcs_n = txq->if_cq->poll_cnt(txq->cq, elts_comp);
962e22920bSAdrien Mazarguil 	if (unlikely(wcs_n == 0))
972e22920bSAdrien Mazarguil 		return 0;
982e22920bSAdrien Mazarguil 	if (unlikely(wcs_n < 0)) {
992e22920bSAdrien Mazarguil 		DEBUG("%p: ibv_poll_cq() failed (wcs_n=%d)",
1002e22920bSAdrien Mazarguil 		      (void *)txq, wcs_n);
1012e22920bSAdrien Mazarguil 		return -1;
1022e22920bSAdrien Mazarguil 	}
1032e22920bSAdrien Mazarguil 	elts_comp -= wcs_n;
1042e22920bSAdrien Mazarguil 	assert(elts_comp <= txq->elts_comp);
1052e22920bSAdrien Mazarguil 	/*
1062e22920bSAdrien Mazarguil 	 * Assume WC status is successful as nothing can be done about it
1072e22920bSAdrien Mazarguil 	 * anyway.
1082e22920bSAdrien Mazarguil 	 */
1092e22920bSAdrien Mazarguil 	elts_tail += wcs_n * txq->elts_comp_cd_init;
1102e22920bSAdrien Mazarguil 	if (elts_tail >= elts_n)
1112e22920bSAdrien Mazarguil 		elts_tail -= elts_n;
1122e22920bSAdrien Mazarguil 	txq->elts_tail = elts_tail;
1132e22920bSAdrien Mazarguil 	txq->elts_comp = elts_comp;
1142e22920bSAdrien Mazarguil 	return 0;
1152e22920bSAdrien Mazarguil }
1162e22920bSAdrien Mazarguil 
1172e22920bSAdrien Mazarguil /**
1182e22920bSAdrien Mazarguil  * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
1192e22920bSAdrien Mazarguil  * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
1202e22920bSAdrien Mazarguil  * remove an entry first.
1212e22920bSAdrien Mazarguil  *
1222e22920bSAdrien Mazarguil  * @param txq
1232e22920bSAdrien Mazarguil  *   Pointer to TX queue structure.
1242e22920bSAdrien Mazarguil  * @param[in] mp
1252e22920bSAdrien Mazarguil  *   Memory Pool for which a Memory Region lkey must be returned.
1262e22920bSAdrien Mazarguil  *
1272e22920bSAdrien Mazarguil  * @return
1282e22920bSAdrien Mazarguil  *   mr->lkey on success, (uint32_t)-1 on failure.
1292e22920bSAdrien Mazarguil  */
1302e22920bSAdrien Mazarguil static uint32_t
1312e22920bSAdrien Mazarguil txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
1322e22920bSAdrien Mazarguil {
1332e22920bSAdrien Mazarguil 	unsigned int i;
1342e22920bSAdrien Mazarguil 	struct ibv_mr *mr;
1352e22920bSAdrien Mazarguil 
1362e22920bSAdrien Mazarguil 	for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
1372e22920bSAdrien Mazarguil 		if (unlikely(txq->mp2mr[i].mp == NULL)) {
1382e22920bSAdrien Mazarguil 			/* Unknown MP, add a new MR for it. */
1392e22920bSAdrien Mazarguil 			break;
1402e22920bSAdrien Mazarguil 		}
1412e22920bSAdrien Mazarguil 		if (txq->mp2mr[i].mp == mp) {
1422e22920bSAdrien Mazarguil 			assert(txq->mp2mr[i].lkey != (uint32_t)-1);
1432e22920bSAdrien Mazarguil 			assert(txq->mp2mr[i].mr->lkey == txq->mp2mr[i].lkey);
1442e22920bSAdrien Mazarguil 			return txq->mp2mr[i].lkey;
1452e22920bSAdrien Mazarguil 		}
1462e22920bSAdrien Mazarguil 	}
1472e22920bSAdrien Mazarguil 	/* Add a new entry, register MR first. */
1482e22920bSAdrien Mazarguil 	DEBUG("%p: discovered new memory pool %p", (void *)txq, (void *)mp);
1492e22920bSAdrien Mazarguil 	mr = ibv_reg_mr(txq->priv->pd,
1502e22920bSAdrien Mazarguil 			(void *)mp->elt_va_start,
1512e22920bSAdrien Mazarguil 			(mp->elt_va_end - mp->elt_va_start),
1522e22920bSAdrien Mazarguil 			(IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE));
1532e22920bSAdrien Mazarguil 	if (unlikely(mr == NULL)) {
1542e22920bSAdrien Mazarguil 		DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.",
1552e22920bSAdrien Mazarguil 		      (void *)txq);
1562e22920bSAdrien Mazarguil 		return (uint32_t)-1;
1572e22920bSAdrien Mazarguil 	}
1582e22920bSAdrien Mazarguil 	if (unlikely(i == RTE_DIM(txq->mp2mr))) {
1592e22920bSAdrien Mazarguil 		/* Table is full, remove oldest entry. */
1602e22920bSAdrien Mazarguil 		DEBUG("%p: MR <-> MP table full, dropping oldest entry.",
1612e22920bSAdrien Mazarguil 		      (void *)txq);
1622e22920bSAdrien Mazarguil 		--i;
1632e22920bSAdrien Mazarguil 		claim_zero(ibv_dereg_mr(txq->mp2mr[i].mr));
1642e22920bSAdrien Mazarguil 		memmove(&txq->mp2mr[0], &txq->mp2mr[1],
1652e22920bSAdrien Mazarguil 			(sizeof(txq->mp2mr) - sizeof(txq->mp2mr[0])));
1662e22920bSAdrien Mazarguil 	}
1672e22920bSAdrien Mazarguil 	/* Store the new entry. */
1682e22920bSAdrien Mazarguil 	txq->mp2mr[i].mp = mp;
1692e22920bSAdrien Mazarguil 	txq->mp2mr[i].mr = mr;
1702e22920bSAdrien Mazarguil 	txq->mp2mr[i].lkey = mr->lkey;
1712e22920bSAdrien Mazarguil 	DEBUG("%p: new MR lkey for MP %p: 0x%08" PRIu32,
1722e22920bSAdrien Mazarguil 	      (void *)txq, (void *)mp, txq->mp2mr[i].lkey);
1732e22920bSAdrien Mazarguil 	return txq->mp2mr[i].lkey;
1742e22920bSAdrien Mazarguil }
1752e22920bSAdrien Mazarguil 
1763ee84446SAdrien Mazarguil #if MLX5_PMD_SGE_WR_N > 1
1773ee84446SAdrien Mazarguil 
1783ee84446SAdrien Mazarguil /**
1793ee84446SAdrien Mazarguil  * Copy scattered mbuf contents to a single linear buffer.
1803ee84446SAdrien Mazarguil  *
1813ee84446SAdrien Mazarguil  * @param[out] linear
1823ee84446SAdrien Mazarguil  *   Linear output buffer.
1833ee84446SAdrien Mazarguil  * @param[in] buf
1843ee84446SAdrien Mazarguil  *   Scattered input buffer.
1853ee84446SAdrien Mazarguil  *
1863ee84446SAdrien Mazarguil  * @return
1873ee84446SAdrien Mazarguil  *   Number of bytes copied to the output buffer or 0 if not large enough.
1883ee84446SAdrien Mazarguil  */
1893ee84446SAdrien Mazarguil static unsigned int
1903ee84446SAdrien Mazarguil linearize_mbuf(linear_t *linear, struct rte_mbuf *buf)
1913ee84446SAdrien Mazarguil {
1923ee84446SAdrien Mazarguil 	unsigned int size = 0;
1933ee84446SAdrien Mazarguil 	unsigned int offset;
1943ee84446SAdrien Mazarguil 
1953ee84446SAdrien Mazarguil 	do {
1963ee84446SAdrien Mazarguil 		unsigned int len = DATA_LEN(buf);
1973ee84446SAdrien Mazarguil 
1983ee84446SAdrien Mazarguil 		offset = size;
1993ee84446SAdrien Mazarguil 		size += len;
2003ee84446SAdrien Mazarguil 		if (unlikely(size > sizeof(*linear)))
2013ee84446SAdrien Mazarguil 			return 0;
2023ee84446SAdrien Mazarguil 		memcpy(&(*linear)[offset],
2033ee84446SAdrien Mazarguil 		       rte_pktmbuf_mtod(buf, uint8_t *),
2043ee84446SAdrien Mazarguil 		       len);
2053ee84446SAdrien Mazarguil 		buf = NEXT(buf);
2063ee84446SAdrien Mazarguil 	} while (buf != NULL);
2073ee84446SAdrien Mazarguil 	return size;
2083ee84446SAdrien Mazarguil }
2093ee84446SAdrien Mazarguil 
2103ee84446SAdrien Mazarguil /**
2113ee84446SAdrien Mazarguil  * Handle scattered buffers for mlx5_tx_burst().
2123ee84446SAdrien Mazarguil  *
2133ee84446SAdrien Mazarguil  * @param txq
2143ee84446SAdrien Mazarguil  *   TX queue structure.
2153ee84446SAdrien Mazarguil  * @param segs
2163ee84446SAdrien Mazarguil  *   Number of segments in buf.
2173ee84446SAdrien Mazarguil  * @param elt
2183ee84446SAdrien Mazarguil  *   TX queue element to fill.
2193ee84446SAdrien Mazarguil  * @param[in] buf
2203ee84446SAdrien Mazarguil  *   Buffer to process.
2213ee84446SAdrien Mazarguil  * @param elts_head
2223ee84446SAdrien Mazarguil  *   Index of the linear buffer to use if necessary (normally txq->elts_head).
2233ee84446SAdrien Mazarguil  * @param[out] sges
2243ee84446SAdrien Mazarguil  *   Array filled with SGEs on success.
2253ee84446SAdrien Mazarguil  *
2263ee84446SAdrien Mazarguil  * @return
2273ee84446SAdrien Mazarguil  *   A structure containing the processed packet size in bytes and the
2283ee84446SAdrien Mazarguil  *   number of SGEs. Both fields are set to (unsigned int)-1 in case of
2293ee84446SAdrien Mazarguil  *   failure.
2303ee84446SAdrien Mazarguil  */
2313ee84446SAdrien Mazarguil static struct tx_burst_sg_ret {
2323ee84446SAdrien Mazarguil 	unsigned int length;
2333ee84446SAdrien Mazarguil 	unsigned int num;
2343ee84446SAdrien Mazarguil }
2353ee84446SAdrien Mazarguil tx_burst_sg(struct txq *txq, unsigned int segs, struct txq_elt *elt,
2363ee84446SAdrien Mazarguil 	    struct rte_mbuf *buf, unsigned int elts_head,
2373ee84446SAdrien Mazarguil 	    struct ibv_sge (*sges)[MLX5_PMD_SGE_WR_N])
2383ee84446SAdrien Mazarguil {
2393ee84446SAdrien Mazarguil 	unsigned int sent_size = 0;
2403ee84446SAdrien Mazarguil 	unsigned int j;
2413ee84446SAdrien Mazarguil 	int linearize = 0;
2423ee84446SAdrien Mazarguil 
2433ee84446SAdrien Mazarguil 	/* When there are too many segments, extra segments are
2443ee84446SAdrien Mazarguil 	 * linearized in the last SGE. */
2453ee84446SAdrien Mazarguil 	if (unlikely(segs > RTE_DIM(*sges))) {
2463ee84446SAdrien Mazarguil 		segs = (RTE_DIM(*sges) - 1);
2473ee84446SAdrien Mazarguil 		linearize = 1;
2483ee84446SAdrien Mazarguil 	}
2493ee84446SAdrien Mazarguil 	/* Update element. */
2503ee84446SAdrien Mazarguil 	elt->buf = buf;
2513ee84446SAdrien Mazarguil 	/* Register segments as SGEs. */
2523ee84446SAdrien Mazarguil 	for (j = 0; (j != segs); ++j) {
2533ee84446SAdrien Mazarguil 		struct ibv_sge *sge = &(*sges)[j];
2543ee84446SAdrien Mazarguil 		uint32_t lkey;
2553ee84446SAdrien Mazarguil 
2563ee84446SAdrien Mazarguil 		/* Retrieve Memory Region key for this memory pool. */
2573ee84446SAdrien Mazarguil 		lkey = txq_mp2mr(txq, buf->pool);
2583ee84446SAdrien Mazarguil 		if (unlikely(lkey == (uint32_t)-1)) {
2593ee84446SAdrien Mazarguil 			/* MR does not exist. */
2603ee84446SAdrien Mazarguil 			DEBUG("%p: unable to get MP <-> MR association",
2613ee84446SAdrien Mazarguil 			      (void *)txq);
2623ee84446SAdrien Mazarguil 			/* Clean up TX element. */
2633ee84446SAdrien Mazarguil 			elt->buf = NULL;
2643ee84446SAdrien Mazarguil 			goto stop;
2653ee84446SAdrien Mazarguil 		}
2663ee84446SAdrien Mazarguil 		/* Update SGE. */
2673ee84446SAdrien Mazarguil 		sge->addr = rte_pktmbuf_mtod(buf, uintptr_t);
2683ee84446SAdrien Mazarguil 		if (txq->priv->vf)
2693ee84446SAdrien Mazarguil 			rte_prefetch0((volatile void *)
2703ee84446SAdrien Mazarguil 				      (uintptr_t)sge->addr);
2713ee84446SAdrien Mazarguil 		sge->length = DATA_LEN(buf);
2723ee84446SAdrien Mazarguil 		sge->lkey = lkey;
2733ee84446SAdrien Mazarguil 		sent_size += sge->length;
2743ee84446SAdrien Mazarguil 		buf = NEXT(buf);
2753ee84446SAdrien Mazarguil 	}
2763ee84446SAdrien Mazarguil 	/* If buf is not NULL here and is not going to be linearized,
2773ee84446SAdrien Mazarguil 	 * nb_segs is not valid. */
2783ee84446SAdrien Mazarguil 	assert(j == segs);
2793ee84446SAdrien Mazarguil 	assert((buf == NULL) || (linearize));
2803ee84446SAdrien Mazarguil 	/* Linearize extra segments. */
2813ee84446SAdrien Mazarguil 	if (linearize) {
2823ee84446SAdrien Mazarguil 		struct ibv_sge *sge = &(*sges)[segs];
2833ee84446SAdrien Mazarguil 		linear_t *linear = &(*txq->elts_linear)[elts_head];
2843ee84446SAdrien Mazarguil 		unsigned int size = linearize_mbuf(linear, buf);
2853ee84446SAdrien Mazarguil 
2863ee84446SAdrien Mazarguil 		assert(segs == (RTE_DIM(*sges) - 1));
2873ee84446SAdrien Mazarguil 		if (size == 0) {
2883ee84446SAdrien Mazarguil 			/* Invalid packet. */
2893ee84446SAdrien Mazarguil 			DEBUG("%p: packet too large to be linearized.",
2903ee84446SAdrien Mazarguil 			      (void *)txq);
2913ee84446SAdrien Mazarguil 			/* Clean up TX element. */
2923ee84446SAdrien Mazarguil 			elt->buf = NULL;
2933ee84446SAdrien Mazarguil 			goto stop;
2943ee84446SAdrien Mazarguil 		}
2953ee84446SAdrien Mazarguil 		/* If MLX5_PMD_SGE_WR_N is 1, free mbuf immediately. */
2963ee84446SAdrien Mazarguil 		if (RTE_DIM(*sges) == 1) {
2973ee84446SAdrien Mazarguil 			do {
2983ee84446SAdrien Mazarguil 				struct rte_mbuf *next = NEXT(buf);
2993ee84446SAdrien Mazarguil 
3003ee84446SAdrien Mazarguil 				rte_pktmbuf_free_seg(buf);
3013ee84446SAdrien Mazarguil 				buf = next;
3023ee84446SAdrien Mazarguil 			} while (buf != NULL);
3033ee84446SAdrien Mazarguil 			elt->buf = NULL;
3043ee84446SAdrien Mazarguil 		}
3053ee84446SAdrien Mazarguil 		/* Update SGE. */
3063ee84446SAdrien Mazarguil 		sge->addr = (uintptr_t)&(*linear)[0];
3073ee84446SAdrien Mazarguil 		sge->length = size;
3083ee84446SAdrien Mazarguil 		sge->lkey = txq->mr_linear->lkey;
3093ee84446SAdrien Mazarguil 		sent_size += size;
3103ee84446SAdrien Mazarguil 	}
3113ee84446SAdrien Mazarguil 	return (struct tx_burst_sg_ret){
3123ee84446SAdrien Mazarguil 		.length = sent_size,
3133ee84446SAdrien Mazarguil 		.num = segs,
3143ee84446SAdrien Mazarguil 	};
3153ee84446SAdrien Mazarguil stop:
3163ee84446SAdrien Mazarguil 	return (struct tx_burst_sg_ret){
3173ee84446SAdrien Mazarguil 		.length = -1,
3183ee84446SAdrien Mazarguil 		.num = -1,
3193ee84446SAdrien Mazarguil 	};
3203ee84446SAdrien Mazarguil }
3213ee84446SAdrien Mazarguil 
3223ee84446SAdrien Mazarguil #endif /* MLX5_PMD_SGE_WR_N > 1 */
3233ee84446SAdrien Mazarguil 
3242e22920bSAdrien Mazarguil /**
3252e22920bSAdrien Mazarguil  * DPDK callback for TX.
3262e22920bSAdrien Mazarguil  *
3272e22920bSAdrien Mazarguil  * @param dpdk_txq
3282e22920bSAdrien Mazarguil  *   Generic pointer to TX queue structure.
3292e22920bSAdrien Mazarguil  * @param[in] pkts
3302e22920bSAdrien Mazarguil  *   Packets to transmit.
3312e22920bSAdrien Mazarguil  * @param pkts_n
3322e22920bSAdrien Mazarguil  *   Number of packets in array.
3332e22920bSAdrien Mazarguil  *
3342e22920bSAdrien Mazarguil  * @return
3352e22920bSAdrien Mazarguil  *   Number of packets successfully transmitted (<= pkts_n).
3362e22920bSAdrien Mazarguil  */
3372e22920bSAdrien Mazarguil uint16_t
3382e22920bSAdrien Mazarguil mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
3392e22920bSAdrien Mazarguil {
3402e22920bSAdrien Mazarguil 	struct txq *txq = (struct txq *)dpdk_txq;
3412e22920bSAdrien Mazarguil 	unsigned int elts_head = txq->elts_head;
3422e22920bSAdrien Mazarguil 	const unsigned int elts_tail = txq->elts_tail;
3432e22920bSAdrien Mazarguil 	const unsigned int elts_n = txq->elts_n;
3442e22920bSAdrien Mazarguil 	unsigned int elts_comp_cd = txq->elts_comp_cd;
3452e22920bSAdrien Mazarguil 	unsigned int elts_comp = 0;
3462e22920bSAdrien Mazarguil 	unsigned int i;
3472e22920bSAdrien Mazarguil 	unsigned int max;
3482e22920bSAdrien Mazarguil 	int err;
3492e22920bSAdrien Mazarguil 
3502e22920bSAdrien Mazarguil 	assert(elts_comp_cd != 0);
3512e22920bSAdrien Mazarguil 	txq_complete(txq);
3522e22920bSAdrien Mazarguil 	max = (elts_n - (elts_head - elts_tail));
3532e22920bSAdrien Mazarguil 	if (max > elts_n)
3542e22920bSAdrien Mazarguil 		max -= elts_n;
3552e22920bSAdrien Mazarguil 	assert(max >= 1);
3562e22920bSAdrien Mazarguil 	assert(max <= elts_n);
3572e22920bSAdrien Mazarguil 	/* Always leave one free entry in the ring. */
3582e22920bSAdrien Mazarguil 	--max;
3592e22920bSAdrien Mazarguil 	if (max == 0)
3602e22920bSAdrien Mazarguil 		return 0;
3612e22920bSAdrien Mazarguil 	if (max > pkts_n)
3622e22920bSAdrien Mazarguil 		max = pkts_n;
3632e22920bSAdrien Mazarguil 	for (i = 0; (i != max); ++i) {
3642e22920bSAdrien Mazarguil 		struct rte_mbuf *buf = pkts[i];
3652e22920bSAdrien Mazarguil 		unsigned int elts_head_next =
3662e22920bSAdrien Mazarguil 			(((elts_head + 1) == elts_n) ? 0 : elts_head + 1);
3672e22920bSAdrien Mazarguil 		struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];
3682e22920bSAdrien Mazarguil 		struct txq_elt *elt = &(*txq->elts)[elts_head];
3692e22920bSAdrien Mazarguil 		unsigned int segs = NB_SEGS(buf);
37087011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
37187011737SAdrien Mazarguil 		unsigned int sent_size = 0;
37287011737SAdrien Mazarguil #endif
3732e22920bSAdrien Mazarguil 		uint32_t send_flags = 0;
3742e22920bSAdrien Mazarguil 
3752e22920bSAdrien Mazarguil 		/* Clean up old buffer. */
3762e22920bSAdrien Mazarguil 		if (likely(elt->buf != NULL)) {
3772e22920bSAdrien Mazarguil 			struct rte_mbuf *tmp = elt->buf;
3782e22920bSAdrien Mazarguil 
3792e22920bSAdrien Mazarguil 			/* Faster than rte_pktmbuf_free(). */
3802e22920bSAdrien Mazarguil 			do {
3812e22920bSAdrien Mazarguil 				struct rte_mbuf *next = NEXT(tmp);
3822e22920bSAdrien Mazarguil 
3832e22920bSAdrien Mazarguil 				rte_pktmbuf_free_seg(tmp);
3842e22920bSAdrien Mazarguil 				tmp = next;
3852e22920bSAdrien Mazarguil 			} while (tmp != NULL);
3862e22920bSAdrien Mazarguil 		}
3872e22920bSAdrien Mazarguil 		/* Request TX completion. */
3882e22920bSAdrien Mazarguil 		if (unlikely(--elts_comp_cd == 0)) {
3892e22920bSAdrien Mazarguil 			elts_comp_cd = txq->elts_comp_cd_init;
3902e22920bSAdrien Mazarguil 			++elts_comp;
3912e22920bSAdrien Mazarguil 			send_flags |= IBV_EXP_QP_BURST_SIGNALED;
3922e22920bSAdrien Mazarguil 		}
393*67fa62bcSAdrien Mazarguil 		/* Should we enable HW CKSUM offload */
394*67fa62bcSAdrien Mazarguil 		if (buf->ol_flags &
395*67fa62bcSAdrien Mazarguil 		    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {
396*67fa62bcSAdrien Mazarguil 			send_flags |= IBV_EXP_QP_BURST_IP_CSUM;
397*67fa62bcSAdrien Mazarguil 			/* HW does not support checksum offloads at arbitrary
398*67fa62bcSAdrien Mazarguil 			 * offsets but automatically recognizes the packet
399*67fa62bcSAdrien Mazarguil 			 * type. For inner L3/L4 checksums, only VXLAN (UDP)
400*67fa62bcSAdrien Mazarguil 			 * tunnels are currently supported. */
401*67fa62bcSAdrien Mazarguil 			if (RTE_ETH_IS_TUNNEL_PKT(buf->packet_type))
402*67fa62bcSAdrien Mazarguil 				send_flags |= IBV_EXP_QP_BURST_TUNNEL;
403*67fa62bcSAdrien Mazarguil 		}
4042e22920bSAdrien Mazarguil 		if (likely(segs == 1)) {
4052e22920bSAdrien Mazarguil 			uintptr_t addr;
4062e22920bSAdrien Mazarguil 			uint32_t length;
4072e22920bSAdrien Mazarguil 			uint32_t lkey;
4082e22920bSAdrien Mazarguil 
4092e22920bSAdrien Mazarguil 			/* Retrieve buffer information. */
4102e22920bSAdrien Mazarguil 			addr = rte_pktmbuf_mtod(buf, uintptr_t);
4112e22920bSAdrien Mazarguil 			length = DATA_LEN(buf);
4122e22920bSAdrien Mazarguil 			/* Retrieve Memory Region key for this memory pool. */
4132e22920bSAdrien Mazarguil 			lkey = txq_mp2mr(txq, buf->pool);
4142e22920bSAdrien Mazarguil 			if (unlikely(lkey == (uint32_t)-1)) {
4152e22920bSAdrien Mazarguil 				/* MR does not exist. */
4162e22920bSAdrien Mazarguil 				DEBUG("%p: unable to get MP <-> MR"
4172e22920bSAdrien Mazarguil 				      " association", (void *)txq);
4182e22920bSAdrien Mazarguil 				/* Clean up TX element. */
4192e22920bSAdrien Mazarguil 				elt->buf = NULL;
4202e22920bSAdrien Mazarguil 				goto stop;
4212e22920bSAdrien Mazarguil 			}
4222e22920bSAdrien Mazarguil 			/* Update element. */
4232e22920bSAdrien Mazarguil 			elt->buf = buf;
4242e22920bSAdrien Mazarguil 			if (txq->priv->vf)
4252e22920bSAdrien Mazarguil 				rte_prefetch0((volatile void *)
4262e22920bSAdrien Mazarguil 					      (uintptr_t)addr);
4272e22920bSAdrien Mazarguil 			RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf);
4282e22920bSAdrien Mazarguil 			/* Put packet into send queue. */
4292e22920bSAdrien Mazarguil #if MLX5_PMD_MAX_INLINE > 0
4302e22920bSAdrien Mazarguil 			if (length <= txq->max_inline)
4312e22920bSAdrien Mazarguil 				err = txq->if_qp->send_pending_inline
4322e22920bSAdrien Mazarguil 					(txq->qp,
4332e22920bSAdrien Mazarguil 					 (void *)addr,
4342e22920bSAdrien Mazarguil 					 length,
4352e22920bSAdrien Mazarguil 					 send_flags);
4362e22920bSAdrien Mazarguil 			else
4372e22920bSAdrien Mazarguil #endif
4382e22920bSAdrien Mazarguil 				err = txq->if_qp->send_pending
4392e22920bSAdrien Mazarguil 					(txq->qp,
4402e22920bSAdrien Mazarguil 					 addr,
4412e22920bSAdrien Mazarguil 					 length,
4422e22920bSAdrien Mazarguil 					 lkey,
4432e22920bSAdrien Mazarguil 					 send_flags);
4442e22920bSAdrien Mazarguil 			if (unlikely(err))
4452e22920bSAdrien Mazarguil 				goto stop;
44687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
44787011737SAdrien Mazarguil 			sent_size += length;
44887011737SAdrien Mazarguil #endif
4492e22920bSAdrien Mazarguil 		} else {
4503ee84446SAdrien Mazarguil #if MLX5_PMD_SGE_WR_N > 1
4513ee84446SAdrien Mazarguil 			struct ibv_sge sges[MLX5_PMD_SGE_WR_N];
4523ee84446SAdrien Mazarguil 			struct tx_burst_sg_ret ret;
4533ee84446SAdrien Mazarguil 
4543ee84446SAdrien Mazarguil 			ret = tx_burst_sg(txq, segs, elt, buf, elts_head,
4553ee84446SAdrien Mazarguil 					  &sges);
4563ee84446SAdrien Mazarguil 			if (ret.length == (unsigned int)-1)
4573ee84446SAdrien Mazarguil 				goto stop;
4583ee84446SAdrien Mazarguil 			RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf);
4593ee84446SAdrien Mazarguil 			/* Put SG list into send queue. */
4603ee84446SAdrien Mazarguil 			err = txq->if_qp->send_pending_sg_list
4613ee84446SAdrien Mazarguil 				(txq->qp,
4623ee84446SAdrien Mazarguil 				 sges,
4633ee84446SAdrien Mazarguil 				 ret.num,
4643ee84446SAdrien Mazarguil 				 send_flags);
4653ee84446SAdrien Mazarguil 			if (unlikely(err))
4663ee84446SAdrien Mazarguil 				goto stop;
46787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
46887011737SAdrien Mazarguil 			sent_size += ret.length;
46987011737SAdrien Mazarguil #endif
4703ee84446SAdrien Mazarguil #else /* MLX5_PMD_SGE_WR_N > 1 */
4712e22920bSAdrien Mazarguil 			DEBUG("%p: TX scattered buffers support not"
4722e22920bSAdrien Mazarguil 			      " compiled in", (void *)txq);
4732e22920bSAdrien Mazarguil 			goto stop;
4743ee84446SAdrien Mazarguil #endif /* MLX5_PMD_SGE_WR_N > 1 */
4752e22920bSAdrien Mazarguil 		}
4762e22920bSAdrien Mazarguil 		elts_head = elts_head_next;
47787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
47887011737SAdrien Mazarguil 		/* Increment sent bytes counter. */
47987011737SAdrien Mazarguil 		txq->stats.obytes += sent_size;
48087011737SAdrien Mazarguil #endif
4812e22920bSAdrien Mazarguil 	}
4822e22920bSAdrien Mazarguil stop:
4832e22920bSAdrien Mazarguil 	/* Take a shortcut if nothing must be sent. */
4842e22920bSAdrien Mazarguil 	if (unlikely(i == 0))
4852e22920bSAdrien Mazarguil 		return 0;
48687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
48787011737SAdrien Mazarguil 	/* Increment sent packets counter. */
48887011737SAdrien Mazarguil 	txq->stats.opackets += i;
48987011737SAdrien Mazarguil #endif
4902e22920bSAdrien Mazarguil 	/* Ring QP doorbell. */
4912e22920bSAdrien Mazarguil 	err = txq->if_qp->send_flush(txq->qp);
4922e22920bSAdrien Mazarguil 	if (unlikely(err)) {
4932e22920bSAdrien Mazarguil 		/* A nonzero value is not supposed to be returned.
4942e22920bSAdrien Mazarguil 		 * Nothing can be done about it. */
4952e22920bSAdrien Mazarguil 		DEBUG("%p: send_flush() failed with error %d",
4962e22920bSAdrien Mazarguil 		      (void *)txq, err);
4972e22920bSAdrien Mazarguil 	}
4982e22920bSAdrien Mazarguil 	txq->elts_head = elts_head;
4992e22920bSAdrien Mazarguil 	txq->elts_comp += elts_comp;
5002e22920bSAdrien Mazarguil 	txq->elts_comp_cd = elts_comp_cd;
5012e22920bSAdrien Mazarguil 	return i;
5022e22920bSAdrien Mazarguil }
5032e22920bSAdrien Mazarguil 
5042e22920bSAdrien Mazarguil /**
505*67fa62bcSAdrien Mazarguil  * Translate RX completion flags to packet type.
506*67fa62bcSAdrien Mazarguil  *
507*67fa62bcSAdrien Mazarguil  * @param flags
508*67fa62bcSAdrien Mazarguil  *   RX completion flags returned by poll_length_flags().
509*67fa62bcSAdrien Mazarguil  *
510*67fa62bcSAdrien Mazarguil  * @return
511*67fa62bcSAdrien Mazarguil  *   Packet type for struct rte_mbuf.
512*67fa62bcSAdrien Mazarguil  */
513*67fa62bcSAdrien Mazarguil static inline uint32_t
514*67fa62bcSAdrien Mazarguil rxq_cq_to_pkt_type(uint32_t flags)
515*67fa62bcSAdrien Mazarguil {
516*67fa62bcSAdrien Mazarguil 	uint32_t pkt_type;
517*67fa62bcSAdrien Mazarguil 
518*67fa62bcSAdrien Mazarguil 	if (flags & IBV_EXP_CQ_RX_TUNNEL_PACKET)
519*67fa62bcSAdrien Mazarguil 		pkt_type =
520*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
521*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_OUTER_IPV4_PACKET,
522*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_L3_IPV4) |
523*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
524*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_OUTER_IPV6_PACKET,
525*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_L3_IPV6) |
526*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
527*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_IPV4_PACKET,
528*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_INNER_L3_IPV4) |
529*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
530*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_IPV6_PACKET,
531*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_INNER_L3_IPV6);
532*67fa62bcSAdrien Mazarguil 	else
533*67fa62bcSAdrien Mazarguil 		pkt_type =
534*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
535*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_IPV4_PACKET,
536*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_L3_IPV4) |
537*67fa62bcSAdrien Mazarguil 			TRANSPOSE(flags,
538*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_IPV6_PACKET,
539*67fa62bcSAdrien Mazarguil 				  RTE_PTYPE_L3_IPV6);
540*67fa62bcSAdrien Mazarguil 	return pkt_type;
541*67fa62bcSAdrien Mazarguil }
542*67fa62bcSAdrien Mazarguil 
543*67fa62bcSAdrien Mazarguil /**
544*67fa62bcSAdrien Mazarguil  * Translate RX completion flags to offload flags.
545*67fa62bcSAdrien Mazarguil  *
546*67fa62bcSAdrien Mazarguil  * @param[in] rxq
547*67fa62bcSAdrien Mazarguil  *   Pointer to RX queue structure.
548*67fa62bcSAdrien Mazarguil  * @param flags
549*67fa62bcSAdrien Mazarguil  *   RX completion flags returned by poll_length_flags().
550*67fa62bcSAdrien Mazarguil  *
551*67fa62bcSAdrien Mazarguil  * @return
552*67fa62bcSAdrien Mazarguil  *   Offload flags (ol_flags) for struct rte_mbuf.
553*67fa62bcSAdrien Mazarguil  */
554*67fa62bcSAdrien Mazarguil static inline uint32_t
555*67fa62bcSAdrien Mazarguil rxq_cq_to_ol_flags(const struct rxq *rxq, uint32_t flags)
556*67fa62bcSAdrien Mazarguil {
557*67fa62bcSAdrien Mazarguil 	uint32_t ol_flags = 0;
558*67fa62bcSAdrien Mazarguil 
559*67fa62bcSAdrien Mazarguil 	if (rxq->csum)
560*67fa62bcSAdrien Mazarguil 		ol_flags |=
561*67fa62bcSAdrien Mazarguil 			TRANSPOSE(~flags,
562*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_IP_CSUM_OK,
563*67fa62bcSAdrien Mazarguil 				  PKT_RX_IP_CKSUM_BAD) |
564*67fa62bcSAdrien Mazarguil 			TRANSPOSE(~flags,
565*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_TCP_UDP_CSUM_OK,
566*67fa62bcSAdrien Mazarguil 				  PKT_RX_L4_CKSUM_BAD);
567*67fa62bcSAdrien Mazarguil 	/*
568*67fa62bcSAdrien Mazarguil 	 * PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD are used in place
569*67fa62bcSAdrien Mazarguil 	 * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional
570*67fa62bcSAdrien Mazarguil 	 * (its value is 0).
571*67fa62bcSAdrien Mazarguil 	 */
572*67fa62bcSAdrien Mazarguil 	if ((flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) && (rxq->csum_l2tun))
573*67fa62bcSAdrien Mazarguil 		ol_flags |=
574*67fa62bcSAdrien Mazarguil 			TRANSPOSE(~flags,
575*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_OUTER_IP_CSUM_OK,
576*67fa62bcSAdrien Mazarguil 				  PKT_RX_IP_CKSUM_BAD) |
577*67fa62bcSAdrien Mazarguil 			TRANSPOSE(~flags,
578*67fa62bcSAdrien Mazarguil 				  IBV_EXP_CQ_RX_OUTER_TCP_UDP_CSUM_OK,
579*67fa62bcSAdrien Mazarguil 				  PKT_RX_L4_CKSUM_BAD);
580*67fa62bcSAdrien Mazarguil 	return ol_flags;
581*67fa62bcSAdrien Mazarguil }
582*67fa62bcSAdrien Mazarguil 
583*67fa62bcSAdrien Mazarguil /**
5843ee84446SAdrien Mazarguil  * DPDK callback for RX with scattered packets support.
5853ee84446SAdrien Mazarguil  *
5863ee84446SAdrien Mazarguil  * @param dpdk_rxq
5873ee84446SAdrien Mazarguil  *   Generic pointer to RX queue structure.
5883ee84446SAdrien Mazarguil  * @param[out] pkts
5893ee84446SAdrien Mazarguil  *   Array to store received packets.
5903ee84446SAdrien Mazarguil  * @param pkts_n
5913ee84446SAdrien Mazarguil  *   Maximum number of packets in array.
5923ee84446SAdrien Mazarguil  *
5933ee84446SAdrien Mazarguil  * @return
5943ee84446SAdrien Mazarguil  *   Number of packets successfully received (<= pkts_n).
5953ee84446SAdrien Mazarguil  */
5963ee84446SAdrien Mazarguil uint16_t
5973ee84446SAdrien Mazarguil mlx5_rx_burst_sp(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
5983ee84446SAdrien Mazarguil {
5993ee84446SAdrien Mazarguil 	struct rxq *rxq = (struct rxq *)dpdk_rxq;
6003ee84446SAdrien Mazarguil 	struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp;
6013ee84446SAdrien Mazarguil 	const unsigned int elts_n = rxq->elts_n;
6023ee84446SAdrien Mazarguil 	unsigned int elts_head = rxq->elts_head;
6033ee84446SAdrien Mazarguil 	struct ibv_recv_wr head;
6043ee84446SAdrien Mazarguil 	struct ibv_recv_wr **next = &head.next;
6053ee84446SAdrien Mazarguil 	struct ibv_recv_wr *bad_wr;
6063ee84446SAdrien Mazarguil 	unsigned int i;
6073ee84446SAdrien Mazarguil 	unsigned int pkts_ret = 0;
6083ee84446SAdrien Mazarguil 	int ret;
6093ee84446SAdrien Mazarguil 
6103ee84446SAdrien Mazarguil 	if (unlikely(!rxq->sp))
6113ee84446SAdrien Mazarguil 		return mlx5_rx_burst(dpdk_rxq, pkts, pkts_n);
6123ee84446SAdrien Mazarguil 	if (unlikely(elts == NULL)) /* See RTE_DEV_CMD_SET_MTU. */
6133ee84446SAdrien Mazarguil 		return 0;
6143ee84446SAdrien Mazarguil 	for (i = 0; (i != pkts_n); ++i) {
6153ee84446SAdrien Mazarguil 		struct rxq_elt_sp *elt = &(*elts)[elts_head];
6163ee84446SAdrien Mazarguil 		struct ibv_recv_wr *wr = &elt->wr;
6173ee84446SAdrien Mazarguil 		uint64_t wr_id = wr->wr_id;
6183ee84446SAdrien Mazarguil 		unsigned int len;
6193ee84446SAdrien Mazarguil 		unsigned int pkt_buf_len;
6203ee84446SAdrien Mazarguil 		struct rte_mbuf *pkt_buf = NULL; /* Buffer returned in pkts. */
6213ee84446SAdrien Mazarguil 		struct rte_mbuf **pkt_buf_next = &pkt_buf;
6223ee84446SAdrien Mazarguil 		unsigned int seg_headroom = RTE_PKTMBUF_HEADROOM;
6233ee84446SAdrien Mazarguil 		unsigned int j = 0;
6243ee84446SAdrien Mazarguil 		uint32_t flags;
6253ee84446SAdrien Mazarguil 
6263ee84446SAdrien Mazarguil 		/* Sanity checks. */
6273ee84446SAdrien Mazarguil #ifdef NDEBUG
6283ee84446SAdrien Mazarguil 		(void)wr_id;
6293ee84446SAdrien Mazarguil #endif
6303ee84446SAdrien Mazarguil 		assert(wr_id < rxq->elts_n);
6313ee84446SAdrien Mazarguil 		assert(wr->sg_list == elt->sges);
6323ee84446SAdrien Mazarguil 		assert(wr->num_sge == RTE_DIM(elt->sges));
6333ee84446SAdrien Mazarguil 		assert(elts_head < rxq->elts_n);
6343ee84446SAdrien Mazarguil 		assert(rxq->elts_head < rxq->elts_n);
6353ee84446SAdrien Mazarguil 		ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL,
6363ee84446SAdrien Mazarguil 						    &flags);
6373ee84446SAdrien Mazarguil 		if (unlikely(ret < 0)) {
6383ee84446SAdrien Mazarguil 			struct ibv_wc wc;
6393ee84446SAdrien Mazarguil 			int wcs_n;
6403ee84446SAdrien Mazarguil 
6413ee84446SAdrien Mazarguil 			DEBUG("rxq=%p, poll_length() failed (ret=%d)",
6423ee84446SAdrien Mazarguil 			      (void *)rxq, ret);
6433ee84446SAdrien Mazarguil 			/* ibv_poll_cq() must be used in case of failure. */
6443ee84446SAdrien Mazarguil 			wcs_n = ibv_poll_cq(rxq->cq, 1, &wc);
6453ee84446SAdrien Mazarguil 			if (unlikely(wcs_n == 0))
6463ee84446SAdrien Mazarguil 				break;
6473ee84446SAdrien Mazarguil 			if (unlikely(wcs_n < 0)) {
6483ee84446SAdrien Mazarguil 				DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)",
6493ee84446SAdrien Mazarguil 				      (void *)rxq, wcs_n);
6503ee84446SAdrien Mazarguil 				break;
6513ee84446SAdrien Mazarguil 			}
6523ee84446SAdrien Mazarguil 			assert(wcs_n == 1);
6533ee84446SAdrien Mazarguil 			if (unlikely(wc.status != IBV_WC_SUCCESS)) {
6543ee84446SAdrien Mazarguil 				/* Whatever, just repost the offending WR. */
6553ee84446SAdrien Mazarguil 				DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work"
6563ee84446SAdrien Mazarguil 				      " completion status (%d): %s",
6573ee84446SAdrien Mazarguil 				      (void *)rxq, wc.wr_id, wc.status,
6583ee84446SAdrien Mazarguil 				      ibv_wc_status_str(wc.status));
65987011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
66087011737SAdrien Mazarguil 				/* Increment dropped packets counter. */
66187011737SAdrien Mazarguil 				++rxq->stats.idropped;
66287011737SAdrien Mazarguil #endif
6633ee84446SAdrien Mazarguil 				/* Link completed WRs together for repost. */
6643ee84446SAdrien Mazarguil 				*next = wr;
6653ee84446SAdrien Mazarguil 				next = &wr->next;
6663ee84446SAdrien Mazarguil 				goto repost;
6673ee84446SAdrien Mazarguil 			}
6683ee84446SAdrien Mazarguil 			ret = wc.byte_len;
6693ee84446SAdrien Mazarguil 		}
6703ee84446SAdrien Mazarguil 		if (ret == 0)
6713ee84446SAdrien Mazarguil 			break;
6723ee84446SAdrien Mazarguil 		len = ret;
6733ee84446SAdrien Mazarguil 		pkt_buf_len = len;
6743ee84446SAdrien Mazarguil 		/* Link completed WRs together for repost. */
6753ee84446SAdrien Mazarguil 		*next = wr;
6763ee84446SAdrien Mazarguil 		next = &wr->next;
6773ee84446SAdrien Mazarguil 		/*
6783ee84446SAdrien Mazarguil 		 * Replace spent segments with new ones, concatenate and
6793ee84446SAdrien Mazarguil 		 * return them as pkt_buf.
6803ee84446SAdrien Mazarguil 		 */
6813ee84446SAdrien Mazarguil 		while (1) {
6823ee84446SAdrien Mazarguil 			struct ibv_sge *sge = &elt->sges[j];
6833ee84446SAdrien Mazarguil 			struct rte_mbuf *seg = elt->bufs[j];
6843ee84446SAdrien Mazarguil 			struct rte_mbuf *rep;
6853ee84446SAdrien Mazarguil 			unsigned int seg_tailroom;
6863ee84446SAdrien Mazarguil 
6873ee84446SAdrien Mazarguil 			/*
6883ee84446SAdrien Mazarguil 			 * Fetch initial bytes of packet descriptor into a
6893ee84446SAdrien Mazarguil 			 * cacheline while allocating rep.
6903ee84446SAdrien Mazarguil 			 */
6913ee84446SAdrien Mazarguil 			rte_prefetch0(seg);
6923ee84446SAdrien Mazarguil 			rep = __rte_mbuf_raw_alloc(rxq->mp);
6933ee84446SAdrien Mazarguil 			if (unlikely(rep == NULL)) {
6943ee84446SAdrien Mazarguil 				/*
6953ee84446SAdrien Mazarguil 				 * Unable to allocate a replacement mbuf,
6963ee84446SAdrien Mazarguil 				 * repost WR.
6973ee84446SAdrien Mazarguil 				 */
6983ee84446SAdrien Mazarguil 				DEBUG("rxq=%p, wr_id=%" PRIu64 ":"
6993ee84446SAdrien Mazarguil 				      " can't allocate a new mbuf",
7003ee84446SAdrien Mazarguil 				      (void *)rxq, wr_id);
7013ee84446SAdrien Mazarguil 				if (pkt_buf != NULL) {
7023ee84446SAdrien Mazarguil 					*pkt_buf_next = NULL;
7033ee84446SAdrien Mazarguil 					rte_pktmbuf_free(pkt_buf);
7043ee84446SAdrien Mazarguil 				}
7053ee84446SAdrien Mazarguil 				/* Increment out of memory counters. */
70687011737SAdrien Mazarguil 				++rxq->stats.rx_nombuf;
7073ee84446SAdrien Mazarguil 				++rxq->priv->dev->data->rx_mbuf_alloc_failed;
7083ee84446SAdrien Mazarguil 				goto repost;
7093ee84446SAdrien Mazarguil 			}
7103ee84446SAdrien Mazarguil #ifndef NDEBUG
7113ee84446SAdrien Mazarguil 			/* Poison user-modifiable fields in rep. */
7123ee84446SAdrien Mazarguil 			NEXT(rep) = (void *)((uintptr_t)-1);
7133ee84446SAdrien Mazarguil 			SET_DATA_OFF(rep, 0xdead);
7143ee84446SAdrien Mazarguil 			DATA_LEN(rep) = 0xd00d;
7153ee84446SAdrien Mazarguil 			PKT_LEN(rep) = 0xdeadd00d;
7163ee84446SAdrien Mazarguil 			NB_SEGS(rep) = 0x2a;
7173ee84446SAdrien Mazarguil 			PORT(rep) = 0x2a;
7183ee84446SAdrien Mazarguil 			rep->ol_flags = -1;
7193ee84446SAdrien Mazarguil #endif
7203ee84446SAdrien Mazarguil 			assert(rep->buf_len == seg->buf_len);
7213ee84446SAdrien Mazarguil 			assert(rep->buf_len == rxq->mb_len);
7223ee84446SAdrien Mazarguil 			/* Reconfigure sge to use rep instead of seg. */
7233ee84446SAdrien Mazarguil 			assert(sge->lkey == rxq->mr->lkey);
7243ee84446SAdrien Mazarguil 			sge->addr = ((uintptr_t)rep->buf_addr + seg_headroom);
7253ee84446SAdrien Mazarguil 			elt->bufs[j] = rep;
7263ee84446SAdrien Mazarguil 			++j;
7273ee84446SAdrien Mazarguil 			/* Update pkt_buf if it's the first segment, or link
7283ee84446SAdrien Mazarguil 			 * seg to the previous one and update pkt_buf_next. */
7293ee84446SAdrien Mazarguil 			*pkt_buf_next = seg;
7303ee84446SAdrien Mazarguil 			pkt_buf_next = &NEXT(seg);
7313ee84446SAdrien Mazarguil 			/* Update seg information. */
7323ee84446SAdrien Mazarguil 			seg_tailroom = (seg->buf_len - seg_headroom);
7333ee84446SAdrien Mazarguil 			assert(sge->length == seg_tailroom);
7343ee84446SAdrien Mazarguil 			SET_DATA_OFF(seg, seg_headroom);
7353ee84446SAdrien Mazarguil 			if (likely(len <= seg_tailroom)) {
7363ee84446SAdrien Mazarguil 				/* Last segment. */
7373ee84446SAdrien Mazarguil 				DATA_LEN(seg) = len;
7383ee84446SAdrien Mazarguil 				PKT_LEN(seg) = len;
7393ee84446SAdrien Mazarguil 				/* Sanity check. */
7403ee84446SAdrien Mazarguil 				assert(rte_pktmbuf_headroom(seg) ==
7413ee84446SAdrien Mazarguil 				       seg_headroom);
7423ee84446SAdrien Mazarguil 				assert(rte_pktmbuf_tailroom(seg) ==
7433ee84446SAdrien Mazarguil 				       (seg_tailroom - len));
7443ee84446SAdrien Mazarguil 				break;
7453ee84446SAdrien Mazarguil 			}
7463ee84446SAdrien Mazarguil 			DATA_LEN(seg) = seg_tailroom;
7473ee84446SAdrien Mazarguil 			PKT_LEN(seg) = seg_tailroom;
7483ee84446SAdrien Mazarguil 			/* Sanity check. */
7493ee84446SAdrien Mazarguil 			assert(rte_pktmbuf_headroom(seg) == seg_headroom);
7503ee84446SAdrien Mazarguil 			assert(rte_pktmbuf_tailroom(seg) == 0);
7513ee84446SAdrien Mazarguil 			/* Fix len and clear headroom for next segments. */
7523ee84446SAdrien Mazarguil 			len -= seg_tailroom;
7533ee84446SAdrien Mazarguil 			seg_headroom = 0;
7543ee84446SAdrien Mazarguil 		}
7553ee84446SAdrien Mazarguil 		/* Update head and tail segments. */
7563ee84446SAdrien Mazarguil 		*pkt_buf_next = NULL;
7573ee84446SAdrien Mazarguil 		assert(pkt_buf != NULL);
7583ee84446SAdrien Mazarguil 		assert(j != 0);
7593ee84446SAdrien Mazarguil 		NB_SEGS(pkt_buf) = j;
7603ee84446SAdrien Mazarguil 		PORT(pkt_buf) = rxq->port_id;
7613ee84446SAdrien Mazarguil 		PKT_LEN(pkt_buf) = pkt_buf_len;
762*67fa62bcSAdrien Mazarguil 		pkt_buf->packet_type = rxq_cq_to_pkt_type(flags);
763*67fa62bcSAdrien Mazarguil 		pkt_buf->ol_flags = rxq_cq_to_ol_flags(rxq, flags);
7643ee84446SAdrien Mazarguil 
7653ee84446SAdrien Mazarguil 		/* Return packet. */
7663ee84446SAdrien Mazarguil 		*(pkts++) = pkt_buf;
7673ee84446SAdrien Mazarguil 		++pkts_ret;
76887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
76987011737SAdrien Mazarguil 		/* Increment bytes counter. */
77087011737SAdrien Mazarguil 		rxq->stats.ibytes += pkt_buf_len;
77187011737SAdrien Mazarguil #endif
7723ee84446SAdrien Mazarguil repost:
7733ee84446SAdrien Mazarguil 		if (++elts_head >= elts_n)
7743ee84446SAdrien Mazarguil 			elts_head = 0;
7753ee84446SAdrien Mazarguil 		continue;
7763ee84446SAdrien Mazarguil 	}
7773ee84446SAdrien Mazarguil 	if (unlikely(i == 0))
7783ee84446SAdrien Mazarguil 		return 0;
7793ee84446SAdrien Mazarguil 	*next = NULL;
7803ee84446SAdrien Mazarguil 	/* Repost WRs. */
7813ee84446SAdrien Mazarguil #ifdef DEBUG_RECV
7823ee84446SAdrien Mazarguil 	DEBUG("%p: reposting %d WRs", (void *)rxq, i);
7833ee84446SAdrien Mazarguil #endif
7843ee84446SAdrien Mazarguil 	ret = ibv_post_recv(rxq->qp, head.next, &bad_wr);
7853ee84446SAdrien Mazarguil 	if (unlikely(ret)) {
7863ee84446SAdrien Mazarguil 		/* Inability to repost WRs is fatal. */
7873ee84446SAdrien Mazarguil 		DEBUG("%p: ibv_post_recv(): failed for WR %p: %s",
7883ee84446SAdrien Mazarguil 		      (void *)rxq->priv,
7893ee84446SAdrien Mazarguil 		      (void *)bad_wr,
7903ee84446SAdrien Mazarguil 		      strerror(ret));
7913ee84446SAdrien Mazarguil 		abort();
7923ee84446SAdrien Mazarguil 	}
7933ee84446SAdrien Mazarguil 	rxq->elts_head = elts_head;
79487011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
79587011737SAdrien Mazarguil 	/* Increment packets counter. */
79687011737SAdrien Mazarguil 	rxq->stats.ipackets += pkts_ret;
79787011737SAdrien Mazarguil #endif
7983ee84446SAdrien Mazarguil 	return pkts_ret;
7993ee84446SAdrien Mazarguil }
8003ee84446SAdrien Mazarguil 
8013ee84446SAdrien Mazarguil /**
8022e22920bSAdrien Mazarguil  * DPDK callback for RX.
8032e22920bSAdrien Mazarguil  *
8043ee84446SAdrien Mazarguil  * The following function is the same as mlx5_rx_burst_sp(), except it doesn't
8053ee84446SAdrien Mazarguil  * manage scattered packets. Improves performance when MRU is lower than the
8063ee84446SAdrien Mazarguil  * size of the first segment.
8073ee84446SAdrien Mazarguil  *
8082e22920bSAdrien Mazarguil  * @param dpdk_rxq
8092e22920bSAdrien Mazarguil  *   Generic pointer to RX queue structure.
8102e22920bSAdrien Mazarguil  * @param[out] pkts
8112e22920bSAdrien Mazarguil  *   Array to store received packets.
8122e22920bSAdrien Mazarguil  * @param pkts_n
8132e22920bSAdrien Mazarguil  *   Maximum number of packets in array.
8142e22920bSAdrien Mazarguil  *
8152e22920bSAdrien Mazarguil  * @return
8162e22920bSAdrien Mazarguil  *   Number of packets successfully received (<= pkts_n).
8172e22920bSAdrien Mazarguil  */
8182e22920bSAdrien Mazarguil uint16_t
8192e22920bSAdrien Mazarguil mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
8202e22920bSAdrien Mazarguil {
8212e22920bSAdrien Mazarguil 	struct rxq *rxq = (struct rxq *)dpdk_rxq;
8222e22920bSAdrien Mazarguil 	struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp;
8232e22920bSAdrien Mazarguil 	const unsigned int elts_n = rxq->elts_n;
8242e22920bSAdrien Mazarguil 	unsigned int elts_head = rxq->elts_head;
8252e22920bSAdrien Mazarguil 	struct ibv_sge sges[pkts_n];
8262e22920bSAdrien Mazarguil 	unsigned int i;
8272e22920bSAdrien Mazarguil 	unsigned int pkts_ret = 0;
8282e22920bSAdrien Mazarguil 	int ret;
8292e22920bSAdrien Mazarguil 
8303ee84446SAdrien Mazarguil 	if (unlikely(rxq->sp))
8313ee84446SAdrien Mazarguil 		return mlx5_rx_burst_sp(dpdk_rxq, pkts, pkts_n);
8322e22920bSAdrien Mazarguil 	for (i = 0; (i != pkts_n); ++i) {
8332e22920bSAdrien Mazarguil 		struct rxq_elt *elt = &(*elts)[elts_head];
8342e22920bSAdrien Mazarguil 		struct ibv_recv_wr *wr = &elt->wr;
8352e22920bSAdrien Mazarguil 		uint64_t wr_id = wr->wr_id;
8362e22920bSAdrien Mazarguil 		unsigned int len;
8372e22920bSAdrien Mazarguil 		struct rte_mbuf *seg = (void *)((uintptr_t)elt->sge.addr -
8382e22920bSAdrien Mazarguil 			WR_ID(wr_id).offset);
8392e22920bSAdrien Mazarguil 		struct rte_mbuf *rep;
8402e22920bSAdrien Mazarguil 		uint32_t flags;
8412e22920bSAdrien Mazarguil 
8422e22920bSAdrien Mazarguil 		/* Sanity checks. */
8432e22920bSAdrien Mazarguil 		assert(WR_ID(wr_id).id < rxq->elts_n);
8442e22920bSAdrien Mazarguil 		assert(wr->sg_list == &elt->sge);
8452e22920bSAdrien Mazarguil 		assert(wr->num_sge == 1);
8462e22920bSAdrien Mazarguil 		assert(elts_head < rxq->elts_n);
8472e22920bSAdrien Mazarguil 		assert(rxq->elts_head < rxq->elts_n);
8482e22920bSAdrien Mazarguil 		/*
8492e22920bSAdrien Mazarguil 		 * Fetch initial bytes of packet descriptor into a
8502e22920bSAdrien Mazarguil 		 * cacheline while allocating rep.
8512e22920bSAdrien Mazarguil 		 */
8522e22920bSAdrien Mazarguil 		rte_prefetch0(seg);
8532e22920bSAdrien Mazarguil 		rte_prefetch0(&seg->cacheline1);
8542e22920bSAdrien Mazarguil 		ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL,
8552e22920bSAdrien Mazarguil 						    &flags);
8562e22920bSAdrien Mazarguil 		if (unlikely(ret < 0)) {
8572e22920bSAdrien Mazarguil 			struct ibv_wc wc;
8582e22920bSAdrien Mazarguil 			int wcs_n;
8592e22920bSAdrien Mazarguil 
8602e22920bSAdrien Mazarguil 			DEBUG("rxq=%p, poll_length() failed (ret=%d)",
8612e22920bSAdrien Mazarguil 			      (void *)rxq, ret);
8622e22920bSAdrien Mazarguil 			/* ibv_poll_cq() must be used in case of failure. */
8632e22920bSAdrien Mazarguil 			wcs_n = ibv_poll_cq(rxq->cq, 1, &wc);
8642e22920bSAdrien Mazarguil 			if (unlikely(wcs_n == 0))
8652e22920bSAdrien Mazarguil 				break;
8662e22920bSAdrien Mazarguil 			if (unlikely(wcs_n < 0)) {
8672e22920bSAdrien Mazarguil 				DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)",
8682e22920bSAdrien Mazarguil 				      (void *)rxq, wcs_n);
8692e22920bSAdrien Mazarguil 				break;
8702e22920bSAdrien Mazarguil 			}
8712e22920bSAdrien Mazarguil 			assert(wcs_n == 1);
8722e22920bSAdrien Mazarguil 			if (unlikely(wc.status != IBV_WC_SUCCESS)) {
8732e22920bSAdrien Mazarguil 				/* Whatever, just repost the offending WR. */
8742e22920bSAdrien Mazarguil 				DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work"
8752e22920bSAdrien Mazarguil 				      " completion status (%d): %s",
8762e22920bSAdrien Mazarguil 				      (void *)rxq, wc.wr_id, wc.status,
8772e22920bSAdrien Mazarguil 				      ibv_wc_status_str(wc.status));
87887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
87987011737SAdrien Mazarguil 				/* Increment dropped packets counter. */
88087011737SAdrien Mazarguil 				++rxq->stats.idropped;
88187011737SAdrien Mazarguil #endif
8822e22920bSAdrien Mazarguil 				/* Add SGE to array for repost. */
8832e22920bSAdrien Mazarguil 				sges[i] = elt->sge;
8842e22920bSAdrien Mazarguil 				goto repost;
8852e22920bSAdrien Mazarguil 			}
8862e22920bSAdrien Mazarguil 			ret = wc.byte_len;
8872e22920bSAdrien Mazarguil 		}
8882e22920bSAdrien Mazarguil 		if (ret == 0)
8892e22920bSAdrien Mazarguil 			break;
8902e22920bSAdrien Mazarguil 		len = ret;
8912e22920bSAdrien Mazarguil 		rep = __rte_mbuf_raw_alloc(rxq->mp);
8922e22920bSAdrien Mazarguil 		if (unlikely(rep == NULL)) {
8932e22920bSAdrien Mazarguil 			/*
8942e22920bSAdrien Mazarguil 			 * Unable to allocate a replacement mbuf,
8952e22920bSAdrien Mazarguil 			 * repost WR.
8962e22920bSAdrien Mazarguil 			 */
8972e22920bSAdrien Mazarguil 			DEBUG("rxq=%p, wr_id=%" PRIu32 ":"
8982e22920bSAdrien Mazarguil 			      " can't allocate a new mbuf",
8992e22920bSAdrien Mazarguil 			      (void *)rxq, WR_ID(wr_id).id);
9002e22920bSAdrien Mazarguil 			/* Increment out of memory counters. */
90187011737SAdrien Mazarguil 			++rxq->stats.rx_nombuf;
9022e22920bSAdrien Mazarguil 			++rxq->priv->dev->data->rx_mbuf_alloc_failed;
9032e22920bSAdrien Mazarguil 			goto repost;
9042e22920bSAdrien Mazarguil 		}
9052e22920bSAdrien Mazarguil 
9062e22920bSAdrien Mazarguil 		/* Reconfigure sge to use rep instead of seg. */
9072e22920bSAdrien Mazarguil 		elt->sge.addr = (uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM;
9082e22920bSAdrien Mazarguil 		assert(elt->sge.lkey == rxq->mr->lkey);
9092e22920bSAdrien Mazarguil 		WR_ID(wr->wr_id).offset =
9102e22920bSAdrien Mazarguil 			(((uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM) -
9112e22920bSAdrien Mazarguil 			 (uintptr_t)rep);
9122e22920bSAdrien Mazarguil 		assert(WR_ID(wr->wr_id).id == WR_ID(wr_id).id);
9132e22920bSAdrien Mazarguil 
9142e22920bSAdrien Mazarguil 		/* Add SGE to array for repost. */
9152e22920bSAdrien Mazarguil 		sges[i] = elt->sge;
9162e22920bSAdrien Mazarguil 
9172e22920bSAdrien Mazarguil 		/* Update seg information. */
9182e22920bSAdrien Mazarguil 		SET_DATA_OFF(seg, RTE_PKTMBUF_HEADROOM);
9192e22920bSAdrien Mazarguil 		NB_SEGS(seg) = 1;
9202e22920bSAdrien Mazarguil 		PORT(seg) = rxq->port_id;
9212e22920bSAdrien Mazarguil 		NEXT(seg) = NULL;
9222e22920bSAdrien Mazarguil 		PKT_LEN(seg) = len;
9232e22920bSAdrien Mazarguil 		DATA_LEN(seg) = len;
924*67fa62bcSAdrien Mazarguil 		seg->packet_type = rxq_cq_to_pkt_type(flags);
925*67fa62bcSAdrien Mazarguil 		seg->ol_flags = rxq_cq_to_ol_flags(rxq, flags);
9262e22920bSAdrien Mazarguil 
9272e22920bSAdrien Mazarguil 		/* Return packet. */
9282e22920bSAdrien Mazarguil 		*(pkts++) = seg;
9292e22920bSAdrien Mazarguil 		++pkts_ret;
93087011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
93187011737SAdrien Mazarguil 		/* Increment bytes counter. */
93287011737SAdrien Mazarguil 		rxq->stats.ibytes += len;
93387011737SAdrien Mazarguil #endif
9342e22920bSAdrien Mazarguil repost:
9352e22920bSAdrien Mazarguil 		if (++elts_head >= elts_n)
9362e22920bSAdrien Mazarguil 			elts_head = 0;
9372e22920bSAdrien Mazarguil 		continue;
9382e22920bSAdrien Mazarguil 	}
9392e22920bSAdrien Mazarguil 	if (unlikely(i == 0))
9402e22920bSAdrien Mazarguil 		return 0;
9412e22920bSAdrien Mazarguil 	/* Repost WRs. */
9422e22920bSAdrien Mazarguil #ifdef DEBUG_RECV
9432e22920bSAdrien Mazarguil 	DEBUG("%p: reposting %u WRs", (void *)rxq, i);
9442e22920bSAdrien Mazarguil #endif
9452e22920bSAdrien Mazarguil 	ret = rxq->if_qp->recv_burst(rxq->qp, sges, i);
9462e22920bSAdrien Mazarguil 	if (unlikely(ret)) {
9472e22920bSAdrien Mazarguil 		/* Inability to repost WRs is fatal. */
9482e22920bSAdrien Mazarguil 		DEBUG("%p: recv_burst(): failed (ret=%d)",
9492e22920bSAdrien Mazarguil 		      (void *)rxq->priv,
9502e22920bSAdrien Mazarguil 		      ret);
9512e22920bSAdrien Mazarguil 		abort();
9522e22920bSAdrien Mazarguil 	}
9532e22920bSAdrien Mazarguil 	rxq->elts_head = elts_head;
95487011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
95587011737SAdrien Mazarguil 	/* Increment packets counter. */
95687011737SAdrien Mazarguil 	rxq->stats.ipackets += pkts_ret;
95787011737SAdrien Mazarguil #endif
9582e22920bSAdrien Mazarguil 	return pkts_ret;
9592e22920bSAdrien Mazarguil }
9602e22920bSAdrien Mazarguil 
9612e22920bSAdrien Mazarguil /**
9622e22920bSAdrien Mazarguil  * Dummy DPDK callback for TX.
9632e22920bSAdrien Mazarguil  *
9642e22920bSAdrien Mazarguil  * This function is used to temporarily replace the real callback during
9652e22920bSAdrien Mazarguil  * unsafe control operations on the queue, or in case of error.
9662e22920bSAdrien Mazarguil  *
9672e22920bSAdrien Mazarguil  * @param dpdk_txq
9682e22920bSAdrien Mazarguil  *   Generic pointer to TX queue structure.
9692e22920bSAdrien Mazarguil  * @param[in] pkts
9702e22920bSAdrien Mazarguil  *   Packets to transmit.
9712e22920bSAdrien Mazarguil  * @param pkts_n
9722e22920bSAdrien Mazarguil  *   Number of packets in array.
9732e22920bSAdrien Mazarguil  *
9742e22920bSAdrien Mazarguil  * @return
9752e22920bSAdrien Mazarguil  *   Number of packets successfully transmitted (<= pkts_n).
9762e22920bSAdrien Mazarguil  */
9772e22920bSAdrien Mazarguil uint16_t
9782e22920bSAdrien Mazarguil removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
9792e22920bSAdrien Mazarguil {
9802e22920bSAdrien Mazarguil 	(void)dpdk_txq;
9812e22920bSAdrien Mazarguil 	(void)pkts;
9822e22920bSAdrien Mazarguil 	(void)pkts_n;
9832e22920bSAdrien Mazarguil 	return 0;
9842e22920bSAdrien Mazarguil }
9852e22920bSAdrien Mazarguil 
9862e22920bSAdrien Mazarguil /**
9872e22920bSAdrien Mazarguil  * Dummy DPDK callback for RX.
9882e22920bSAdrien Mazarguil  *
9892e22920bSAdrien Mazarguil  * This function is used to temporarily replace the real callback during
9902e22920bSAdrien Mazarguil  * unsafe control operations on the queue, or in case of error.
9912e22920bSAdrien Mazarguil  *
9922e22920bSAdrien Mazarguil  * @param dpdk_rxq
9932e22920bSAdrien Mazarguil  *   Generic pointer to RX queue structure.
9942e22920bSAdrien Mazarguil  * @param[out] pkts
9952e22920bSAdrien Mazarguil  *   Array to store received packets.
9962e22920bSAdrien Mazarguil  * @param pkts_n
9972e22920bSAdrien Mazarguil  *   Maximum number of packets in array.
9982e22920bSAdrien Mazarguil  *
9992e22920bSAdrien Mazarguil  * @return
10002e22920bSAdrien Mazarguil  *   Number of packets successfully received (<= pkts_n).
10012e22920bSAdrien Mazarguil  */
10022e22920bSAdrien Mazarguil uint16_t
10032e22920bSAdrien Mazarguil removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
10042e22920bSAdrien Mazarguil {
10052e22920bSAdrien Mazarguil 	(void)dpdk_rxq;
10062e22920bSAdrien Mazarguil 	(void)pkts;
10072e22920bSAdrien Mazarguil 	(void)pkts_n;
10082e22920bSAdrien Mazarguil 	return 0;
10092e22920bSAdrien Mazarguil }
1010