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" 65f3db9489SYaacov Hazan #include "mlx5_autoconf.h" 662e22920bSAdrien Mazarguil #include "mlx5_defs.h" 672e22920bSAdrien Mazarguil 682e22920bSAdrien Mazarguil /** 692e22920bSAdrien Mazarguil * Manage TX completions. 702e22920bSAdrien Mazarguil * 712e22920bSAdrien Mazarguil * When sending a burst, mlx5_tx_burst() posts several WRs. 722e22920bSAdrien Mazarguil * To improve performance, a completion event is only required once every 732e22920bSAdrien Mazarguil * MLX5_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information 742e22920bSAdrien Mazarguil * for other WRs, but this information would not be used anyway. 752e22920bSAdrien Mazarguil * 762e22920bSAdrien Mazarguil * @param txq 772e22920bSAdrien Mazarguil * Pointer to TX queue structure. 782e22920bSAdrien Mazarguil * 792e22920bSAdrien Mazarguil * @return 802e22920bSAdrien Mazarguil * 0 on success, -1 on failure. 812e22920bSAdrien Mazarguil */ 822e22920bSAdrien Mazarguil static int 832e22920bSAdrien Mazarguil txq_complete(struct txq *txq) 842e22920bSAdrien Mazarguil { 852e22920bSAdrien Mazarguil unsigned int elts_comp = txq->elts_comp; 862e22920bSAdrien Mazarguil unsigned int elts_tail = txq->elts_tail; 87*a859e8a9SNelio Laranjeiro unsigned int elts_free = txq->elts_tail; 882e22920bSAdrien Mazarguil const unsigned int elts_n = txq->elts_n; 892e22920bSAdrien Mazarguil int wcs_n; 902e22920bSAdrien Mazarguil 912e22920bSAdrien Mazarguil if (unlikely(elts_comp == 0)) 922e22920bSAdrien Mazarguil return 0; 932e22920bSAdrien Mazarguil #ifdef DEBUG_SEND 942e22920bSAdrien Mazarguil DEBUG("%p: processing %u work requests completions", 952e22920bSAdrien Mazarguil (void *)txq, elts_comp); 962e22920bSAdrien Mazarguil #endif 97e1682023SNelio Laranjeiro wcs_n = txq->poll_cnt(txq->cq, elts_comp); 982e22920bSAdrien Mazarguil if (unlikely(wcs_n == 0)) 992e22920bSAdrien Mazarguil return 0; 1002e22920bSAdrien Mazarguil if (unlikely(wcs_n < 0)) { 1012e22920bSAdrien Mazarguil DEBUG("%p: ibv_poll_cq() failed (wcs_n=%d)", 1022e22920bSAdrien Mazarguil (void *)txq, wcs_n); 1032e22920bSAdrien Mazarguil return -1; 1042e22920bSAdrien Mazarguil } 1052e22920bSAdrien Mazarguil elts_comp -= wcs_n; 1062e22920bSAdrien Mazarguil assert(elts_comp <= txq->elts_comp); 1072e22920bSAdrien Mazarguil /* 1082e22920bSAdrien Mazarguil * Assume WC status is successful as nothing can be done about it 1092e22920bSAdrien Mazarguil * anyway. 1102e22920bSAdrien Mazarguil */ 1112e22920bSAdrien Mazarguil elts_tail += wcs_n * txq->elts_comp_cd_init; 1122e22920bSAdrien Mazarguil if (elts_tail >= elts_n) 1132e22920bSAdrien Mazarguil elts_tail -= elts_n; 114*a859e8a9SNelio Laranjeiro 115*a859e8a9SNelio Laranjeiro while (elts_free != elts_tail) { 116*a859e8a9SNelio Laranjeiro struct txq_elt *elt = &(*txq->elts)[elts_free]; 117*a859e8a9SNelio Laranjeiro unsigned int elts_free_next = 118*a859e8a9SNelio Laranjeiro (((elts_free + 1) == elts_n) ? 0 : elts_free + 1); 119*a859e8a9SNelio Laranjeiro struct rte_mbuf *tmp = elt->buf; 120*a859e8a9SNelio Laranjeiro struct txq_elt *elt_next = &(*txq->elts)[elts_free_next]; 121*a859e8a9SNelio Laranjeiro 122*a859e8a9SNelio Laranjeiro RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf); 123*a859e8a9SNelio Laranjeiro /* Faster than rte_pktmbuf_free(). */ 124*a859e8a9SNelio Laranjeiro do { 125*a859e8a9SNelio Laranjeiro struct rte_mbuf *next = NEXT(tmp); 126*a859e8a9SNelio Laranjeiro 127*a859e8a9SNelio Laranjeiro rte_pktmbuf_free_seg(tmp); 128*a859e8a9SNelio Laranjeiro tmp = next; 129*a859e8a9SNelio Laranjeiro } while (tmp != NULL); 130*a859e8a9SNelio Laranjeiro elts_free = elts_free_next; 131*a859e8a9SNelio Laranjeiro } 132*a859e8a9SNelio Laranjeiro 1332e22920bSAdrien Mazarguil txq->elts_tail = elts_tail; 1342e22920bSAdrien Mazarguil txq->elts_comp = elts_comp; 1352e22920bSAdrien Mazarguil return 0; 1362e22920bSAdrien Mazarguil } 1372e22920bSAdrien Mazarguil 1382e22920bSAdrien Mazarguil /** 1398340392eSAdrien Mazarguil * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which 1408340392eSAdrien Mazarguil * the cloned mbuf is allocated is returned instead. 1418340392eSAdrien Mazarguil * 1428340392eSAdrien Mazarguil * @param buf 1438340392eSAdrien Mazarguil * Pointer to mbuf. 1448340392eSAdrien Mazarguil * 1458340392eSAdrien Mazarguil * @return 1468340392eSAdrien Mazarguil * Memory pool where data is located for given mbuf. 1478340392eSAdrien Mazarguil */ 1488340392eSAdrien Mazarguil static struct rte_mempool * 1498340392eSAdrien Mazarguil txq_mb2mp(struct rte_mbuf *buf) 1508340392eSAdrien Mazarguil { 1518340392eSAdrien Mazarguil if (unlikely(RTE_MBUF_INDIRECT(buf))) 1528340392eSAdrien Mazarguil return rte_mbuf_from_indirect(buf)->pool; 1538340392eSAdrien Mazarguil return buf->pool; 1548340392eSAdrien Mazarguil } 1558340392eSAdrien Mazarguil 1568340392eSAdrien Mazarguil /** 1572e22920bSAdrien Mazarguil * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[]. 1582e22920bSAdrien Mazarguil * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full, 1592e22920bSAdrien Mazarguil * remove an entry first. 1602e22920bSAdrien Mazarguil * 1612e22920bSAdrien Mazarguil * @param txq 1622e22920bSAdrien Mazarguil * Pointer to TX queue structure. 1632e22920bSAdrien Mazarguil * @param[in] mp 1642e22920bSAdrien Mazarguil * Memory Pool for which a Memory Region lkey must be returned. 1652e22920bSAdrien Mazarguil * 1662e22920bSAdrien Mazarguil * @return 1672e22920bSAdrien Mazarguil * mr->lkey on success, (uint32_t)-1 on failure. 1682e22920bSAdrien Mazarguil */ 1692e22920bSAdrien Mazarguil static uint32_t 1700a3b350dSOlga Shern txq_mp2mr(struct txq *txq, const struct rte_mempool *mp) 1712e22920bSAdrien Mazarguil { 1722e22920bSAdrien Mazarguil unsigned int i; 1732e22920bSAdrien Mazarguil struct ibv_mr *mr; 1742e22920bSAdrien Mazarguil 1752e22920bSAdrien Mazarguil for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) { 1762e22920bSAdrien Mazarguil if (unlikely(txq->mp2mr[i].mp == NULL)) { 1772e22920bSAdrien Mazarguil /* Unknown MP, add a new MR for it. */ 1782e22920bSAdrien Mazarguil break; 1792e22920bSAdrien Mazarguil } 1802e22920bSAdrien Mazarguil if (txq->mp2mr[i].mp == mp) { 1812e22920bSAdrien Mazarguil assert(txq->mp2mr[i].lkey != (uint32_t)-1); 1822e22920bSAdrien Mazarguil assert(txq->mp2mr[i].mr->lkey == txq->mp2mr[i].lkey); 1832e22920bSAdrien Mazarguil return txq->mp2mr[i].lkey; 1842e22920bSAdrien Mazarguil } 1852e22920bSAdrien Mazarguil } 1862e22920bSAdrien Mazarguil /* Add a new entry, register MR first. */ 1870a3b350dSOlga Shern DEBUG("%p: discovered new memory pool \"%s\" (%p)", 1880a3b350dSOlga Shern (void *)txq, mp->name, (const void *)mp); 1892e22920bSAdrien Mazarguil mr = ibv_reg_mr(txq->priv->pd, 1902e22920bSAdrien Mazarguil (void *)mp->elt_va_start, 1912e22920bSAdrien Mazarguil (mp->elt_va_end - mp->elt_va_start), 1922e22920bSAdrien Mazarguil (IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE)); 1932e22920bSAdrien Mazarguil if (unlikely(mr == NULL)) { 1942e22920bSAdrien Mazarguil DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.", 1952e22920bSAdrien Mazarguil (void *)txq); 1962e22920bSAdrien Mazarguil return (uint32_t)-1; 1972e22920bSAdrien Mazarguil } 1982e22920bSAdrien Mazarguil if (unlikely(i == RTE_DIM(txq->mp2mr))) { 1992e22920bSAdrien Mazarguil /* Table is full, remove oldest entry. */ 2002e22920bSAdrien Mazarguil DEBUG("%p: MR <-> MP table full, dropping oldest entry.", 2012e22920bSAdrien Mazarguil (void *)txq); 2022e22920bSAdrien Mazarguil --i; 203ecbfdbadSOlga Shern claim_zero(ibv_dereg_mr(txq->mp2mr[0].mr)); 2042e22920bSAdrien Mazarguil memmove(&txq->mp2mr[0], &txq->mp2mr[1], 2052e22920bSAdrien Mazarguil (sizeof(txq->mp2mr) - sizeof(txq->mp2mr[0]))); 2062e22920bSAdrien Mazarguil } 2072e22920bSAdrien Mazarguil /* Store the new entry. */ 2082e22920bSAdrien Mazarguil txq->mp2mr[i].mp = mp; 2092e22920bSAdrien Mazarguil txq->mp2mr[i].mr = mr; 2102e22920bSAdrien Mazarguil txq->mp2mr[i].lkey = mr->lkey; 2110a3b350dSOlga Shern DEBUG("%p: new MR lkey for MP \"%s\" (%p): 0x%08" PRIu32, 2120a3b350dSOlga Shern (void *)txq, mp->name, (const void *)mp, txq->mp2mr[i].lkey); 2132e22920bSAdrien Mazarguil return txq->mp2mr[i].lkey; 2142e22920bSAdrien Mazarguil } 2152e22920bSAdrien Mazarguil 2160a3b350dSOlga Shern struct txq_mp2mr_mbuf_check_data { 2170a3b350dSOlga Shern const struct rte_mempool *mp; 2180a3b350dSOlga Shern int ret; 2190a3b350dSOlga Shern }; 2200a3b350dSOlga Shern 2210a3b350dSOlga Shern /** 2220a3b350dSOlga Shern * Callback function for rte_mempool_obj_iter() to check whether a given 2230a3b350dSOlga Shern * mempool object looks like a mbuf. 2240a3b350dSOlga Shern * 2250a3b350dSOlga Shern * @param[in, out] arg 2260a3b350dSOlga Shern * Context data (struct txq_mp2mr_mbuf_check_data). Contains mempool pointer 2270a3b350dSOlga Shern * and return value. 2280a3b350dSOlga Shern * @param[in] start 2290a3b350dSOlga Shern * Object start address. 2300a3b350dSOlga Shern * @param[in] end 2310a3b350dSOlga Shern * Object end address. 2320a3b350dSOlga Shern * @param index 2330a3b350dSOlga Shern * Unused. 2340a3b350dSOlga Shern * 2350a3b350dSOlga Shern * @return 2360a3b350dSOlga Shern * Nonzero value when object is not a mbuf. 2370a3b350dSOlga Shern */ 2380a3b350dSOlga Shern static void 2390a3b350dSOlga Shern txq_mp2mr_mbuf_check(void *arg, void *start, void *end, 2400a3b350dSOlga Shern uint32_t index __rte_unused) 2410a3b350dSOlga Shern { 2420a3b350dSOlga Shern struct txq_mp2mr_mbuf_check_data *data = arg; 2430a3b350dSOlga Shern struct rte_mbuf *buf = 2440a3b350dSOlga Shern (void *)((uintptr_t)start + data->mp->header_size); 2450a3b350dSOlga Shern 2460a3b350dSOlga Shern (void)index; 2470a3b350dSOlga Shern /* Check whether mbuf structure fits element size and whether mempool 2480a3b350dSOlga Shern * pointer is valid. */ 2490a3b350dSOlga Shern if (((uintptr_t)end >= (uintptr_t)(buf + 1)) && 2500a3b350dSOlga Shern (buf->pool == data->mp)) 2510a3b350dSOlga Shern data->ret = 0; 2520a3b350dSOlga Shern else 2530a3b350dSOlga Shern data->ret = -1; 2540a3b350dSOlga Shern } 2550a3b350dSOlga Shern 2560a3b350dSOlga Shern /** 2570a3b350dSOlga Shern * Iterator function for rte_mempool_walk() to register existing mempools and 2580a3b350dSOlga Shern * fill the MP to MR cache of a TX queue. 2590a3b350dSOlga Shern * 2600a3b350dSOlga Shern * @param[in] mp 2610a3b350dSOlga Shern * Memory Pool to register. 2620a3b350dSOlga Shern * @param *arg 2630a3b350dSOlga Shern * Pointer to TX queue structure. 2640a3b350dSOlga Shern */ 2650a3b350dSOlga Shern void 2660a3b350dSOlga Shern txq_mp2mr_iter(const struct rte_mempool *mp, void *arg) 2670a3b350dSOlga Shern { 2680a3b350dSOlga Shern struct txq *txq = arg; 2690a3b350dSOlga Shern struct txq_mp2mr_mbuf_check_data data = { 2700a3b350dSOlga Shern .mp = mp, 2710a3b350dSOlga Shern .ret = -1, 2720a3b350dSOlga Shern }; 2730a3b350dSOlga Shern 2740a3b350dSOlga Shern /* Discard empty mempools. */ 2750a3b350dSOlga Shern if (mp->size == 0) 2760a3b350dSOlga Shern return; 2770a3b350dSOlga Shern /* Register mempool only if the first element looks like a mbuf. */ 2780a3b350dSOlga Shern rte_mempool_obj_iter((void *)mp->elt_va_start, 2790a3b350dSOlga Shern 1, 2800a3b350dSOlga Shern mp->header_size + mp->elt_size + mp->trailer_size, 2810a3b350dSOlga Shern 1, 2820a3b350dSOlga Shern mp->elt_pa, 2830a3b350dSOlga Shern mp->pg_num, 2840a3b350dSOlga Shern mp->pg_shift, 2850a3b350dSOlga Shern txq_mp2mr_mbuf_check, 2860a3b350dSOlga Shern &data); 2870a3b350dSOlga Shern if (data.ret) 2880a3b350dSOlga Shern return; 2890a3b350dSOlga Shern txq_mp2mr(txq, mp); 2900a3b350dSOlga Shern } 2910a3b350dSOlga Shern 2923ee84446SAdrien Mazarguil #if MLX5_PMD_SGE_WR_N > 1 2933ee84446SAdrien Mazarguil 2943ee84446SAdrien Mazarguil /** 2953ee84446SAdrien Mazarguil * Copy scattered mbuf contents to a single linear buffer. 2963ee84446SAdrien Mazarguil * 2973ee84446SAdrien Mazarguil * @param[out] linear 2983ee84446SAdrien Mazarguil * Linear output buffer. 2993ee84446SAdrien Mazarguil * @param[in] buf 3003ee84446SAdrien Mazarguil * Scattered input buffer. 3013ee84446SAdrien Mazarguil * 3023ee84446SAdrien Mazarguil * @return 3033ee84446SAdrien Mazarguil * Number of bytes copied to the output buffer or 0 if not large enough. 3043ee84446SAdrien Mazarguil */ 3053ee84446SAdrien Mazarguil static unsigned int 3063ee84446SAdrien Mazarguil linearize_mbuf(linear_t *linear, struct rte_mbuf *buf) 3073ee84446SAdrien Mazarguil { 3083ee84446SAdrien Mazarguil unsigned int size = 0; 3093ee84446SAdrien Mazarguil unsigned int offset; 3103ee84446SAdrien Mazarguil 3113ee84446SAdrien Mazarguil do { 3123ee84446SAdrien Mazarguil unsigned int len = DATA_LEN(buf); 3133ee84446SAdrien Mazarguil 3143ee84446SAdrien Mazarguil offset = size; 3153ee84446SAdrien Mazarguil size += len; 3163ee84446SAdrien Mazarguil if (unlikely(size > sizeof(*linear))) 3173ee84446SAdrien Mazarguil return 0; 3183ee84446SAdrien Mazarguil memcpy(&(*linear)[offset], 3193ee84446SAdrien Mazarguil rte_pktmbuf_mtod(buf, uint8_t *), 3203ee84446SAdrien Mazarguil len); 3213ee84446SAdrien Mazarguil buf = NEXT(buf); 3223ee84446SAdrien Mazarguil } while (buf != NULL); 3233ee84446SAdrien Mazarguil return size; 3243ee84446SAdrien Mazarguil } 3253ee84446SAdrien Mazarguil 3263ee84446SAdrien Mazarguil /** 3273ee84446SAdrien Mazarguil * Handle scattered buffers for mlx5_tx_burst(). 3283ee84446SAdrien Mazarguil * 3293ee84446SAdrien Mazarguil * @param txq 3303ee84446SAdrien Mazarguil * TX queue structure. 3313ee84446SAdrien Mazarguil * @param segs 3323ee84446SAdrien Mazarguil * Number of segments in buf. 3333ee84446SAdrien Mazarguil * @param elt 3343ee84446SAdrien Mazarguil * TX queue element to fill. 3353ee84446SAdrien Mazarguil * @param[in] buf 3363ee84446SAdrien Mazarguil * Buffer to process. 3373ee84446SAdrien Mazarguil * @param elts_head 3383ee84446SAdrien Mazarguil * Index of the linear buffer to use if necessary (normally txq->elts_head). 3393ee84446SAdrien Mazarguil * @param[out] sges 3403ee84446SAdrien Mazarguil * Array filled with SGEs on success. 3413ee84446SAdrien Mazarguil * 3423ee84446SAdrien Mazarguil * @return 3433ee84446SAdrien Mazarguil * A structure containing the processed packet size in bytes and the 3443ee84446SAdrien Mazarguil * number of SGEs. Both fields are set to (unsigned int)-1 in case of 3453ee84446SAdrien Mazarguil * failure. 3463ee84446SAdrien Mazarguil */ 3473ee84446SAdrien Mazarguil static struct tx_burst_sg_ret { 3483ee84446SAdrien Mazarguil unsigned int length; 3493ee84446SAdrien Mazarguil unsigned int num; 3503ee84446SAdrien Mazarguil } 3513ee84446SAdrien Mazarguil tx_burst_sg(struct txq *txq, unsigned int segs, struct txq_elt *elt, 3523ee84446SAdrien Mazarguil struct rte_mbuf *buf, unsigned int elts_head, 3533ee84446SAdrien Mazarguil struct ibv_sge (*sges)[MLX5_PMD_SGE_WR_N]) 3543ee84446SAdrien Mazarguil { 3553ee84446SAdrien Mazarguil unsigned int sent_size = 0; 3563ee84446SAdrien Mazarguil unsigned int j; 3573ee84446SAdrien Mazarguil int linearize = 0; 3583ee84446SAdrien Mazarguil 3593ee84446SAdrien Mazarguil /* When there are too many segments, extra segments are 3603ee84446SAdrien Mazarguil * linearized in the last SGE. */ 3613ee84446SAdrien Mazarguil if (unlikely(segs > RTE_DIM(*sges))) { 3623ee84446SAdrien Mazarguil segs = (RTE_DIM(*sges) - 1); 3633ee84446SAdrien Mazarguil linearize = 1; 3643ee84446SAdrien Mazarguil } 3653ee84446SAdrien Mazarguil /* Update element. */ 3663ee84446SAdrien Mazarguil elt->buf = buf; 3673ee84446SAdrien Mazarguil /* Register segments as SGEs. */ 3683ee84446SAdrien Mazarguil for (j = 0; (j != segs); ++j) { 3693ee84446SAdrien Mazarguil struct ibv_sge *sge = &(*sges)[j]; 3703ee84446SAdrien Mazarguil uint32_t lkey; 3713ee84446SAdrien Mazarguil 3723ee84446SAdrien Mazarguil /* Retrieve Memory Region key for this memory pool. */ 3738340392eSAdrien Mazarguil lkey = txq_mp2mr(txq, txq_mb2mp(buf)); 3743ee84446SAdrien Mazarguil if (unlikely(lkey == (uint32_t)-1)) { 3753ee84446SAdrien Mazarguil /* MR does not exist. */ 3763ee84446SAdrien Mazarguil DEBUG("%p: unable to get MP <-> MR association", 3773ee84446SAdrien Mazarguil (void *)txq); 3783ee84446SAdrien Mazarguil /* Clean up TX element. */ 3793ee84446SAdrien Mazarguil elt->buf = NULL; 3803ee84446SAdrien Mazarguil goto stop; 3813ee84446SAdrien Mazarguil } 3823ee84446SAdrien Mazarguil /* Update SGE. */ 3833ee84446SAdrien Mazarguil sge->addr = rte_pktmbuf_mtod(buf, uintptr_t); 3843ee84446SAdrien Mazarguil if (txq->priv->vf) 3853ee84446SAdrien Mazarguil rte_prefetch0((volatile void *) 3863ee84446SAdrien Mazarguil (uintptr_t)sge->addr); 3873ee84446SAdrien Mazarguil sge->length = DATA_LEN(buf); 3883ee84446SAdrien Mazarguil sge->lkey = lkey; 3893ee84446SAdrien Mazarguil sent_size += sge->length; 3903ee84446SAdrien Mazarguil buf = NEXT(buf); 3913ee84446SAdrien Mazarguil } 3923ee84446SAdrien Mazarguil /* If buf is not NULL here and is not going to be linearized, 3933ee84446SAdrien Mazarguil * nb_segs is not valid. */ 3943ee84446SAdrien Mazarguil assert(j == segs); 3953ee84446SAdrien Mazarguil assert((buf == NULL) || (linearize)); 3963ee84446SAdrien Mazarguil /* Linearize extra segments. */ 3973ee84446SAdrien Mazarguil if (linearize) { 3983ee84446SAdrien Mazarguil struct ibv_sge *sge = &(*sges)[segs]; 3993ee84446SAdrien Mazarguil linear_t *linear = &(*txq->elts_linear)[elts_head]; 4003ee84446SAdrien Mazarguil unsigned int size = linearize_mbuf(linear, buf); 4013ee84446SAdrien Mazarguil 4023ee84446SAdrien Mazarguil assert(segs == (RTE_DIM(*sges) - 1)); 4033ee84446SAdrien Mazarguil if (size == 0) { 4043ee84446SAdrien Mazarguil /* Invalid packet. */ 4053ee84446SAdrien Mazarguil DEBUG("%p: packet too large to be linearized.", 4063ee84446SAdrien Mazarguil (void *)txq); 4073ee84446SAdrien Mazarguil /* Clean up TX element. */ 4083ee84446SAdrien Mazarguil elt->buf = NULL; 4093ee84446SAdrien Mazarguil goto stop; 4103ee84446SAdrien Mazarguil } 4113ee84446SAdrien Mazarguil /* If MLX5_PMD_SGE_WR_N is 1, free mbuf immediately. */ 4123ee84446SAdrien Mazarguil if (RTE_DIM(*sges) == 1) { 4133ee84446SAdrien Mazarguil do { 4143ee84446SAdrien Mazarguil struct rte_mbuf *next = NEXT(buf); 4153ee84446SAdrien Mazarguil 4163ee84446SAdrien Mazarguil rte_pktmbuf_free_seg(buf); 4173ee84446SAdrien Mazarguil buf = next; 4183ee84446SAdrien Mazarguil } while (buf != NULL); 4193ee84446SAdrien Mazarguil elt->buf = NULL; 4203ee84446SAdrien Mazarguil } 4213ee84446SAdrien Mazarguil /* Update SGE. */ 4223ee84446SAdrien Mazarguil sge->addr = (uintptr_t)&(*linear)[0]; 4233ee84446SAdrien Mazarguil sge->length = size; 4243ee84446SAdrien Mazarguil sge->lkey = txq->mr_linear->lkey; 4253ee84446SAdrien Mazarguil sent_size += size; 42634d06263SAdrien Mazarguil /* Include last segment. */ 42734d06263SAdrien Mazarguil segs++; 4283ee84446SAdrien Mazarguil } 4293ee84446SAdrien Mazarguil return (struct tx_burst_sg_ret){ 4303ee84446SAdrien Mazarguil .length = sent_size, 4313ee84446SAdrien Mazarguil .num = segs, 4323ee84446SAdrien Mazarguil }; 4333ee84446SAdrien Mazarguil stop: 4343ee84446SAdrien Mazarguil return (struct tx_burst_sg_ret){ 4353ee84446SAdrien Mazarguil .length = -1, 4363ee84446SAdrien Mazarguil .num = -1, 4373ee84446SAdrien Mazarguil }; 4383ee84446SAdrien Mazarguil } 4393ee84446SAdrien Mazarguil 4403ee84446SAdrien Mazarguil #endif /* MLX5_PMD_SGE_WR_N > 1 */ 4413ee84446SAdrien Mazarguil 4422e22920bSAdrien Mazarguil /** 4432e22920bSAdrien Mazarguil * DPDK callback for TX. 4442e22920bSAdrien Mazarguil * 4452e22920bSAdrien Mazarguil * @param dpdk_txq 4462e22920bSAdrien Mazarguil * Generic pointer to TX queue structure. 4472e22920bSAdrien Mazarguil * @param[in] pkts 4482e22920bSAdrien Mazarguil * Packets to transmit. 4492e22920bSAdrien Mazarguil * @param pkts_n 4502e22920bSAdrien Mazarguil * Number of packets in array. 4512e22920bSAdrien Mazarguil * 4522e22920bSAdrien Mazarguil * @return 4532e22920bSAdrien Mazarguil * Number of packets successfully transmitted (<= pkts_n). 4542e22920bSAdrien Mazarguil */ 4552e22920bSAdrien Mazarguil uint16_t 4562e22920bSAdrien Mazarguil mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) 4572e22920bSAdrien Mazarguil { 4582e22920bSAdrien Mazarguil struct txq *txq = (struct txq *)dpdk_txq; 4592e22920bSAdrien Mazarguil unsigned int elts_head = txq->elts_head; 4602e22920bSAdrien Mazarguil const unsigned int elts_n = txq->elts_n; 4612e22920bSAdrien Mazarguil unsigned int elts_comp_cd = txq->elts_comp_cd; 4622e22920bSAdrien Mazarguil unsigned int elts_comp = 0; 4632e22920bSAdrien Mazarguil unsigned int i; 4642e22920bSAdrien Mazarguil unsigned int max; 4652e22920bSAdrien Mazarguil int err; 4665e1d11ecSNelio Laranjeiro struct rte_mbuf *buf = pkts[0]; 4672e22920bSAdrien Mazarguil 4682e22920bSAdrien Mazarguil assert(elts_comp_cd != 0); 4695e1d11ecSNelio Laranjeiro /* Prefetch first packet cacheline. */ 4705e1d11ecSNelio Laranjeiro rte_prefetch0(buf); 4712e22920bSAdrien Mazarguil txq_complete(txq); 4724f52bbfbSNelio Laranjeiro max = (elts_n - (elts_head - txq->elts_tail)); 4732e22920bSAdrien Mazarguil if (max > elts_n) 4742e22920bSAdrien Mazarguil max -= elts_n; 4752e22920bSAdrien Mazarguil assert(max >= 1); 4762e22920bSAdrien Mazarguil assert(max <= elts_n); 4772e22920bSAdrien Mazarguil /* Always leave one free entry in the ring. */ 4782e22920bSAdrien Mazarguil --max; 4792e22920bSAdrien Mazarguil if (max == 0) 4802e22920bSAdrien Mazarguil return 0; 4812e22920bSAdrien Mazarguil if (max > pkts_n) 4822e22920bSAdrien Mazarguil max = pkts_n; 4832e22920bSAdrien Mazarguil for (i = 0; (i != max); ++i) { 4845e1d11ecSNelio Laranjeiro struct rte_mbuf *buf_next = pkts[i + 1]; 4852e22920bSAdrien Mazarguil unsigned int elts_head_next = 4862e22920bSAdrien Mazarguil (((elts_head + 1) == elts_n) ? 0 : elts_head + 1); 4872e22920bSAdrien Mazarguil struct txq_elt *elt = &(*txq->elts)[elts_head]; 4882e22920bSAdrien Mazarguil unsigned int segs = NB_SEGS(buf); 48987011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 49087011737SAdrien Mazarguil unsigned int sent_size = 0; 49187011737SAdrien Mazarguil #endif 4922e22920bSAdrien Mazarguil uint32_t send_flags = 0; 4932e22920bSAdrien Mazarguil 4945e1d11ecSNelio Laranjeiro if (i + 1 < max) 4955e1d11ecSNelio Laranjeiro rte_prefetch0(buf_next); 4962e22920bSAdrien Mazarguil /* Request TX completion. */ 4972e22920bSAdrien Mazarguil if (unlikely(--elts_comp_cd == 0)) { 4982e22920bSAdrien Mazarguil elts_comp_cd = txq->elts_comp_cd_init; 4992e22920bSAdrien Mazarguil ++elts_comp; 5002e22920bSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_SIGNALED; 5012e22920bSAdrien Mazarguil } 50267fa62bcSAdrien Mazarguil /* Should we enable HW CKSUM offload */ 50367fa62bcSAdrien Mazarguil if (buf->ol_flags & 50467fa62bcSAdrien Mazarguil (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) { 50567fa62bcSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_IP_CSUM; 50667fa62bcSAdrien Mazarguil /* HW does not support checksum offloads at arbitrary 50767fa62bcSAdrien Mazarguil * offsets but automatically recognizes the packet 50867fa62bcSAdrien Mazarguil * type. For inner L3/L4 checksums, only VXLAN (UDP) 50967fa62bcSAdrien Mazarguil * tunnels are currently supported. */ 51067fa62bcSAdrien Mazarguil if (RTE_ETH_IS_TUNNEL_PKT(buf->packet_type)) 51167fa62bcSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_TUNNEL; 51267fa62bcSAdrien Mazarguil } 5132e22920bSAdrien Mazarguil if (likely(segs == 1)) { 5142e22920bSAdrien Mazarguil uintptr_t addr; 5152e22920bSAdrien Mazarguil uint32_t length; 5162e22920bSAdrien Mazarguil uint32_t lkey; 5175e1d11ecSNelio Laranjeiro uintptr_t buf_next_addr; 5182e22920bSAdrien Mazarguil 5192e22920bSAdrien Mazarguil /* Retrieve buffer information. */ 5202e22920bSAdrien Mazarguil addr = rte_pktmbuf_mtod(buf, uintptr_t); 5212e22920bSAdrien Mazarguil length = DATA_LEN(buf); 5222e22920bSAdrien Mazarguil /* Update element. */ 5232e22920bSAdrien Mazarguil elt->buf = buf; 5242e22920bSAdrien Mazarguil if (txq->priv->vf) 5252e22920bSAdrien Mazarguil rte_prefetch0((volatile void *) 5262e22920bSAdrien Mazarguil (uintptr_t)addr); 5275e1d11ecSNelio Laranjeiro /* Prefetch next buffer data. */ 5285e1d11ecSNelio Laranjeiro if (i + 1 < max) { 5295e1d11ecSNelio Laranjeiro buf_next_addr = 5305e1d11ecSNelio Laranjeiro rte_pktmbuf_mtod(buf_next, uintptr_t); 5315e1d11ecSNelio Laranjeiro rte_prefetch0((volatile void *) 5325e1d11ecSNelio Laranjeiro (uintptr_t)buf_next_addr); 5335e1d11ecSNelio Laranjeiro } 5342e22920bSAdrien Mazarguil /* Put packet into send queue. */ 5352e22920bSAdrien Mazarguil #if MLX5_PMD_MAX_INLINE > 0 5362e22920bSAdrien Mazarguil if (length <= txq->max_inline) 537e1682023SNelio Laranjeiro err = txq->send_pending_inline 5382e22920bSAdrien Mazarguil (txq->qp, 5392e22920bSAdrien Mazarguil (void *)addr, 5402e22920bSAdrien Mazarguil length, 5412e22920bSAdrien Mazarguil send_flags); 5422e22920bSAdrien Mazarguil else 5432e22920bSAdrien Mazarguil #endif 544d970e992SNelio Laranjeiro { 545d970e992SNelio Laranjeiro /* Retrieve Memory Region key for this 546d970e992SNelio Laranjeiro * memory pool. */ 547d970e992SNelio Laranjeiro lkey = txq_mp2mr(txq, txq_mb2mp(buf)); 548d970e992SNelio Laranjeiro if (unlikely(lkey == (uint32_t)-1)) { 549d970e992SNelio Laranjeiro /* MR does not exist. */ 550d970e992SNelio Laranjeiro DEBUG("%p: unable to get MP <-> MR" 551d970e992SNelio Laranjeiro " association", (void *)txq); 552d970e992SNelio Laranjeiro /* Clean up TX element. */ 553d970e992SNelio Laranjeiro elt->buf = NULL; 554d970e992SNelio Laranjeiro goto stop; 555d970e992SNelio Laranjeiro } 556e1682023SNelio Laranjeiro err = txq->send_pending 5572e22920bSAdrien Mazarguil (txq->qp, 5582e22920bSAdrien Mazarguil addr, 5592e22920bSAdrien Mazarguil length, 5602e22920bSAdrien Mazarguil lkey, 5612e22920bSAdrien Mazarguil send_flags); 562d970e992SNelio Laranjeiro } 5632e22920bSAdrien Mazarguil if (unlikely(err)) 5642e22920bSAdrien Mazarguil goto stop; 56587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 56687011737SAdrien Mazarguil sent_size += length; 56787011737SAdrien Mazarguil #endif 5682e22920bSAdrien Mazarguil } else { 5693ee84446SAdrien Mazarguil #if MLX5_PMD_SGE_WR_N > 1 5703ee84446SAdrien Mazarguil struct ibv_sge sges[MLX5_PMD_SGE_WR_N]; 5713ee84446SAdrien Mazarguil struct tx_burst_sg_ret ret; 5723ee84446SAdrien Mazarguil 5733ee84446SAdrien Mazarguil ret = tx_burst_sg(txq, segs, elt, buf, elts_head, 5743ee84446SAdrien Mazarguil &sges); 5753ee84446SAdrien Mazarguil if (ret.length == (unsigned int)-1) 5763ee84446SAdrien Mazarguil goto stop; 5773ee84446SAdrien Mazarguil /* Put SG list into send queue. */ 578e1682023SNelio Laranjeiro err = txq->send_pending_sg_list 5793ee84446SAdrien Mazarguil (txq->qp, 5803ee84446SAdrien Mazarguil sges, 5813ee84446SAdrien Mazarguil ret.num, 5823ee84446SAdrien Mazarguil send_flags); 5833ee84446SAdrien Mazarguil if (unlikely(err)) 5843ee84446SAdrien Mazarguil goto stop; 58587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 58687011737SAdrien Mazarguil sent_size += ret.length; 58787011737SAdrien Mazarguil #endif 5883ee84446SAdrien Mazarguil #else /* MLX5_PMD_SGE_WR_N > 1 */ 5892e22920bSAdrien Mazarguil DEBUG("%p: TX scattered buffers support not" 5902e22920bSAdrien Mazarguil " compiled in", (void *)txq); 5912e22920bSAdrien Mazarguil goto stop; 5923ee84446SAdrien Mazarguil #endif /* MLX5_PMD_SGE_WR_N > 1 */ 5932e22920bSAdrien Mazarguil } 5942e22920bSAdrien Mazarguil elts_head = elts_head_next; 5955e1d11ecSNelio Laranjeiro buf = buf_next; 59687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 59787011737SAdrien Mazarguil /* Increment sent bytes counter. */ 59887011737SAdrien Mazarguil txq->stats.obytes += sent_size; 59987011737SAdrien Mazarguil #endif 6002e22920bSAdrien Mazarguil } 6012e22920bSAdrien Mazarguil stop: 6022e22920bSAdrien Mazarguil /* Take a shortcut if nothing must be sent. */ 6032e22920bSAdrien Mazarguil if (unlikely(i == 0)) 6042e22920bSAdrien Mazarguil return 0; 60587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 60687011737SAdrien Mazarguil /* Increment sent packets counter. */ 60787011737SAdrien Mazarguil txq->stats.opackets += i; 60887011737SAdrien Mazarguil #endif 6092e22920bSAdrien Mazarguil /* Ring QP doorbell. */ 610e1682023SNelio Laranjeiro err = txq->send_flush(txq->qp); 6112e22920bSAdrien Mazarguil if (unlikely(err)) { 6122e22920bSAdrien Mazarguil /* A nonzero value is not supposed to be returned. 6132e22920bSAdrien Mazarguil * Nothing can be done about it. */ 6142e22920bSAdrien Mazarguil DEBUG("%p: send_flush() failed with error %d", 6152e22920bSAdrien Mazarguil (void *)txq, err); 6162e22920bSAdrien Mazarguil } 6172e22920bSAdrien Mazarguil txq->elts_head = elts_head; 6182e22920bSAdrien Mazarguil txq->elts_comp += elts_comp; 6192e22920bSAdrien Mazarguil txq->elts_comp_cd = elts_comp_cd; 6202e22920bSAdrien Mazarguil return i; 6212e22920bSAdrien Mazarguil } 6222e22920bSAdrien Mazarguil 6232e22920bSAdrien Mazarguil /** 62467fa62bcSAdrien Mazarguil * Translate RX completion flags to packet type. 62567fa62bcSAdrien Mazarguil * 62667fa62bcSAdrien Mazarguil * @param flags 62767fa62bcSAdrien Mazarguil * RX completion flags returned by poll_length_flags(). 62867fa62bcSAdrien Mazarguil * 62967fa62bcSAdrien Mazarguil * @return 63067fa62bcSAdrien Mazarguil * Packet type for struct rte_mbuf. 63167fa62bcSAdrien Mazarguil */ 63267fa62bcSAdrien Mazarguil static inline uint32_t 63367fa62bcSAdrien Mazarguil rxq_cq_to_pkt_type(uint32_t flags) 63467fa62bcSAdrien Mazarguil { 63567fa62bcSAdrien Mazarguil uint32_t pkt_type; 63667fa62bcSAdrien Mazarguil 63767fa62bcSAdrien Mazarguil if (flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) 63867fa62bcSAdrien Mazarguil pkt_type = 63967fa62bcSAdrien Mazarguil TRANSPOSE(flags, 64067fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IPV4_PACKET, 64167fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV4) | 64267fa62bcSAdrien Mazarguil TRANSPOSE(flags, 64367fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IPV6_PACKET, 64467fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV6) | 64567fa62bcSAdrien Mazarguil TRANSPOSE(flags, 64667fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV4_PACKET, 64767fa62bcSAdrien Mazarguil RTE_PTYPE_INNER_L3_IPV4) | 64867fa62bcSAdrien Mazarguil TRANSPOSE(flags, 64967fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV6_PACKET, 65067fa62bcSAdrien Mazarguil RTE_PTYPE_INNER_L3_IPV6); 65167fa62bcSAdrien Mazarguil else 65267fa62bcSAdrien Mazarguil pkt_type = 65367fa62bcSAdrien Mazarguil TRANSPOSE(flags, 65467fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV4_PACKET, 65567fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV4) | 65667fa62bcSAdrien Mazarguil TRANSPOSE(flags, 65767fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV6_PACKET, 65867fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV6); 65967fa62bcSAdrien Mazarguil return pkt_type; 66067fa62bcSAdrien Mazarguil } 66167fa62bcSAdrien Mazarguil 66267fa62bcSAdrien Mazarguil /** 66367fa62bcSAdrien Mazarguil * Translate RX completion flags to offload flags. 66467fa62bcSAdrien Mazarguil * 66567fa62bcSAdrien Mazarguil * @param[in] rxq 66667fa62bcSAdrien Mazarguil * Pointer to RX queue structure. 66767fa62bcSAdrien Mazarguil * @param flags 66867fa62bcSAdrien Mazarguil * RX completion flags returned by poll_length_flags(). 66967fa62bcSAdrien Mazarguil * 67067fa62bcSAdrien Mazarguil * @return 67167fa62bcSAdrien Mazarguil * Offload flags (ol_flags) for struct rte_mbuf. 67267fa62bcSAdrien Mazarguil */ 67367fa62bcSAdrien Mazarguil static inline uint32_t 67467fa62bcSAdrien Mazarguil rxq_cq_to_ol_flags(const struct rxq *rxq, uint32_t flags) 67567fa62bcSAdrien Mazarguil { 67667fa62bcSAdrien Mazarguil uint32_t ol_flags = 0; 67767fa62bcSAdrien Mazarguil 67867fa62bcSAdrien Mazarguil if (rxq->csum) 67967fa62bcSAdrien Mazarguil ol_flags |= 68067fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 68167fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IP_CSUM_OK, 68267fa62bcSAdrien Mazarguil PKT_RX_IP_CKSUM_BAD) | 68367fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 68467fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_TCP_UDP_CSUM_OK, 68567fa62bcSAdrien Mazarguil PKT_RX_L4_CKSUM_BAD); 68667fa62bcSAdrien Mazarguil /* 68767fa62bcSAdrien Mazarguil * PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD are used in place 68867fa62bcSAdrien Mazarguil * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional 68967fa62bcSAdrien Mazarguil * (its value is 0). 69067fa62bcSAdrien Mazarguil */ 69167fa62bcSAdrien Mazarguil if ((flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) && (rxq->csum_l2tun)) 69267fa62bcSAdrien Mazarguil ol_flags |= 69367fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 69467fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IP_CSUM_OK, 69567fa62bcSAdrien Mazarguil PKT_RX_IP_CKSUM_BAD) | 69667fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 69767fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_TCP_UDP_CSUM_OK, 69867fa62bcSAdrien Mazarguil PKT_RX_L4_CKSUM_BAD); 69967fa62bcSAdrien Mazarguil return ol_flags; 70067fa62bcSAdrien Mazarguil } 70167fa62bcSAdrien Mazarguil 70267fa62bcSAdrien Mazarguil /** 7033ee84446SAdrien Mazarguil * DPDK callback for RX with scattered packets support. 7043ee84446SAdrien Mazarguil * 7053ee84446SAdrien Mazarguil * @param dpdk_rxq 7063ee84446SAdrien Mazarguil * Generic pointer to RX queue structure. 7073ee84446SAdrien Mazarguil * @param[out] pkts 7083ee84446SAdrien Mazarguil * Array to store received packets. 7093ee84446SAdrien Mazarguil * @param pkts_n 7103ee84446SAdrien Mazarguil * Maximum number of packets in array. 7113ee84446SAdrien Mazarguil * 7123ee84446SAdrien Mazarguil * @return 7133ee84446SAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 7143ee84446SAdrien Mazarguil */ 7153ee84446SAdrien Mazarguil uint16_t 7163ee84446SAdrien Mazarguil mlx5_rx_burst_sp(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 7173ee84446SAdrien Mazarguil { 7183ee84446SAdrien Mazarguil struct rxq *rxq = (struct rxq *)dpdk_rxq; 7193ee84446SAdrien Mazarguil struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp; 7203ee84446SAdrien Mazarguil const unsigned int elts_n = rxq->elts_n; 7213ee84446SAdrien Mazarguil unsigned int elts_head = rxq->elts_head; 7223ee84446SAdrien Mazarguil unsigned int i; 7233ee84446SAdrien Mazarguil unsigned int pkts_ret = 0; 7243ee84446SAdrien Mazarguil int ret; 7253ee84446SAdrien Mazarguil 7263ee84446SAdrien Mazarguil if (unlikely(!rxq->sp)) 7273ee84446SAdrien Mazarguil return mlx5_rx_burst(dpdk_rxq, pkts, pkts_n); 7283ee84446SAdrien Mazarguil if (unlikely(elts == NULL)) /* See RTE_DEV_CMD_SET_MTU. */ 7293ee84446SAdrien Mazarguil return 0; 7303ee84446SAdrien Mazarguil for (i = 0; (i != pkts_n); ++i) { 7313ee84446SAdrien Mazarguil struct rxq_elt_sp *elt = &(*elts)[elts_head]; 7323ee84446SAdrien Mazarguil unsigned int len; 7333ee84446SAdrien Mazarguil unsigned int pkt_buf_len; 7343ee84446SAdrien Mazarguil struct rte_mbuf *pkt_buf = NULL; /* Buffer returned in pkts. */ 7353ee84446SAdrien Mazarguil struct rte_mbuf **pkt_buf_next = &pkt_buf; 7363ee84446SAdrien Mazarguil unsigned int seg_headroom = RTE_PKTMBUF_HEADROOM; 7373ee84446SAdrien Mazarguil unsigned int j = 0; 7383ee84446SAdrien Mazarguil uint32_t flags; 739f3db9489SYaacov Hazan uint16_t vlan_tci; 7403ee84446SAdrien Mazarguil 7413ee84446SAdrien Mazarguil /* Sanity checks. */ 7423ee84446SAdrien Mazarguil assert(elts_head < rxq->elts_n); 7433ee84446SAdrien Mazarguil assert(rxq->elts_head < rxq->elts_n); 744e1682023SNelio Laranjeiro ret = rxq->poll(rxq->cq, NULL, NULL, &flags, &vlan_tci); 7453ee84446SAdrien Mazarguil if (unlikely(ret < 0)) { 7463ee84446SAdrien Mazarguil struct ibv_wc wc; 7473ee84446SAdrien Mazarguil int wcs_n; 7483ee84446SAdrien Mazarguil 7493ee84446SAdrien Mazarguil DEBUG("rxq=%p, poll_length() failed (ret=%d)", 7503ee84446SAdrien Mazarguil (void *)rxq, ret); 7513ee84446SAdrien Mazarguil /* ibv_poll_cq() must be used in case of failure. */ 7523ee84446SAdrien Mazarguil wcs_n = ibv_poll_cq(rxq->cq, 1, &wc); 7533ee84446SAdrien Mazarguil if (unlikely(wcs_n == 0)) 7543ee84446SAdrien Mazarguil break; 7553ee84446SAdrien Mazarguil if (unlikely(wcs_n < 0)) { 7563ee84446SAdrien Mazarguil DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)", 7573ee84446SAdrien Mazarguil (void *)rxq, wcs_n); 7583ee84446SAdrien Mazarguil break; 7593ee84446SAdrien Mazarguil } 7603ee84446SAdrien Mazarguil assert(wcs_n == 1); 7613ee84446SAdrien Mazarguil if (unlikely(wc.status != IBV_WC_SUCCESS)) { 7623ee84446SAdrien Mazarguil /* Whatever, just repost the offending WR. */ 7633ee84446SAdrien Mazarguil DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work" 7643ee84446SAdrien Mazarguil " completion status (%d): %s", 7653ee84446SAdrien Mazarguil (void *)rxq, wc.wr_id, wc.status, 7663ee84446SAdrien Mazarguil ibv_wc_status_str(wc.status)); 76787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 76887011737SAdrien Mazarguil /* Increment dropped packets counter. */ 76987011737SAdrien Mazarguil ++rxq->stats.idropped; 77087011737SAdrien Mazarguil #endif 7713ee84446SAdrien Mazarguil goto repost; 7723ee84446SAdrien Mazarguil } 7733ee84446SAdrien Mazarguil ret = wc.byte_len; 7743ee84446SAdrien Mazarguil } 7753ee84446SAdrien Mazarguil if (ret == 0) 7763ee84446SAdrien Mazarguil break; 7773ee84446SAdrien Mazarguil len = ret; 7783ee84446SAdrien Mazarguil pkt_buf_len = len; 7793ee84446SAdrien Mazarguil /* 7803ee84446SAdrien Mazarguil * Replace spent segments with new ones, concatenate and 7813ee84446SAdrien Mazarguil * return them as pkt_buf. 7823ee84446SAdrien Mazarguil */ 7833ee84446SAdrien Mazarguil while (1) { 7843ee84446SAdrien Mazarguil struct ibv_sge *sge = &elt->sges[j]; 7853ee84446SAdrien Mazarguil struct rte_mbuf *seg = elt->bufs[j]; 7863ee84446SAdrien Mazarguil struct rte_mbuf *rep; 7873ee84446SAdrien Mazarguil unsigned int seg_tailroom; 7883ee84446SAdrien Mazarguil 789aa7f63abSAdrien Mazarguil assert(seg != NULL); 7903ee84446SAdrien Mazarguil /* 7913ee84446SAdrien Mazarguil * Fetch initial bytes of packet descriptor into a 7923ee84446SAdrien Mazarguil * cacheline while allocating rep. 7933ee84446SAdrien Mazarguil */ 7943ee84446SAdrien Mazarguil rte_prefetch0(seg); 7953ee84446SAdrien Mazarguil rep = __rte_mbuf_raw_alloc(rxq->mp); 7963ee84446SAdrien Mazarguil if (unlikely(rep == NULL)) { 7973ee84446SAdrien Mazarguil /* 7983ee84446SAdrien Mazarguil * Unable to allocate a replacement mbuf, 7993ee84446SAdrien Mazarguil * repost WR. 8003ee84446SAdrien Mazarguil */ 801aa7f63abSAdrien Mazarguil DEBUG("rxq=%p: can't allocate a new mbuf", 802aa7f63abSAdrien Mazarguil (void *)rxq); 8033ee84446SAdrien Mazarguil if (pkt_buf != NULL) { 8043ee84446SAdrien Mazarguil *pkt_buf_next = NULL; 8053ee84446SAdrien Mazarguil rte_pktmbuf_free(pkt_buf); 8063ee84446SAdrien Mazarguil } 8073ee84446SAdrien Mazarguil /* Increment out of memory counters. */ 80887011737SAdrien Mazarguil ++rxq->stats.rx_nombuf; 8093ee84446SAdrien Mazarguil ++rxq->priv->dev->data->rx_mbuf_alloc_failed; 8103ee84446SAdrien Mazarguil goto repost; 8113ee84446SAdrien Mazarguil } 8123ee84446SAdrien Mazarguil #ifndef NDEBUG 8133ee84446SAdrien Mazarguil /* Poison user-modifiable fields in rep. */ 8143ee84446SAdrien Mazarguil NEXT(rep) = (void *)((uintptr_t)-1); 8153ee84446SAdrien Mazarguil SET_DATA_OFF(rep, 0xdead); 8163ee84446SAdrien Mazarguil DATA_LEN(rep) = 0xd00d; 8173ee84446SAdrien Mazarguil PKT_LEN(rep) = 0xdeadd00d; 8183ee84446SAdrien Mazarguil NB_SEGS(rep) = 0x2a; 8193ee84446SAdrien Mazarguil PORT(rep) = 0x2a; 8203ee84446SAdrien Mazarguil rep->ol_flags = -1; 8213ee84446SAdrien Mazarguil #endif 8223ee84446SAdrien Mazarguil assert(rep->buf_len == seg->buf_len); 8233ee84446SAdrien Mazarguil assert(rep->buf_len == rxq->mb_len); 8243ee84446SAdrien Mazarguil /* Reconfigure sge to use rep instead of seg. */ 8253ee84446SAdrien Mazarguil assert(sge->lkey == rxq->mr->lkey); 8263ee84446SAdrien Mazarguil sge->addr = ((uintptr_t)rep->buf_addr + seg_headroom); 8273ee84446SAdrien Mazarguil elt->bufs[j] = rep; 8283ee84446SAdrien Mazarguil ++j; 8293ee84446SAdrien Mazarguil /* Update pkt_buf if it's the first segment, or link 8303ee84446SAdrien Mazarguil * seg to the previous one and update pkt_buf_next. */ 8313ee84446SAdrien Mazarguil *pkt_buf_next = seg; 8323ee84446SAdrien Mazarguil pkt_buf_next = &NEXT(seg); 8333ee84446SAdrien Mazarguil /* Update seg information. */ 8343ee84446SAdrien Mazarguil seg_tailroom = (seg->buf_len - seg_headroom); 8353ee84446SAdrien Mazarguil assert(sge->length == seg_tailroom); 8363ee84446SAdrien Mazarguil SET_DATA_OFF(seg, seg_headroom); 8373ee84446SAdrien Mazarguil if (likely(len <= seg_tailroom)) { 8383ee84446SAdrien Mazarguil /* Last segment. */ 8393ee84446SAdrien Mazarguil DATA_LEN(seg) = len; 8403ee84446SAdrien Mazarguil PKT_LEN(seg) = len; 8413ee84446SAdrien Mazarguil /* Sanity check. */ 8423ee84446SAdrien Mazarguil assert(rte_pktmbuf_headroom(seg) == 8433ee84446SAdrien Mazarguil seg_headroom); 8443ee84446SAdrien Mazarguil assert(rte_pktmbuf_tailroom(seg) == 8453ee84446SAdrien Mazarguil (seg_tailroom - len)); 8463ee84446SAdrien Mazarguil break; 8473ee84446SAdrien Mazarguil } 8483ee84446SAdrien Mazarguil DATA_LEN(seg) = seg_tailroom; 8493ee84446SAdrien Mazarguil PKT_LEN(seg) = seg_tailroom; 8503ee84446SAdrien Mazarguil /* Sanity check. */ 8513ee84446SAdrien Mazarguil assert(rte_pktmbuf_headroom(seg) == seg_headroom); 8523ee84446SAdrien Mazarguil assert(rte_pktmbuf_tailroom(seg) == 0); 8533ee84446SAdrien Mazarguil /* Fix len and clear headroom for next segments. */ 8543ee84446SAdrien Mazarguil len -= seg_tailroom; 8553ee84446SAdrien Mazarguil seg_headroom = 0; 8563ee84446SAdrien Mazarguil } 8573ee84446SAdrien Mazarguil /* Update head and tail segments. */ 8583ee84446SAdrien Mazarguil *pkt_buf_next = NULL; 8593ee84446SAdrien Mazarguil assert(pkt_buf != NULL); 8603ee84446SAdrien Mazarguil assert(j != 0); 8613ee84446SAdrien Mazarguil NB_SEGS(pkt_buf) = j; 8623ee84446SAdrien Mazarguil PORT(pkt_buf) = rxq->port_id; 8633ee84446SAdrien Mazarguil PKT_LEN(pkt_buf) = pkt_buf_len; 864081f7eaeSNelio Laranjeiro if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip) { 86567fa62bcSAdrien Mazarguil pkt_buf->packet_type = rxq_cq_to_pkt_type(flags); 86667fa62bcSAdrien Mazarguil pkt_buf->ol_flags = rxq_cq_to_ol_flags(rxq, flags); 867f3db9489SYaacov Hazan #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS 868f3db9489SYaacov Hazan if (flags & IBV_EXP_CQ_RX_CVLAN_STRIPPED_V1) { 869f3db9489SYaacov Hazan pkt_buf->ol_flags |= PKT_RX_VLAN_PKT; 870f3db9489SYaacov Hazan pkt_buf->vlan_tci = vlan_tci; 871f3db9489SYaacov Hazan } 872f3db9489SYaacov Hazan #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ 873081f7eaeSNelio Laranjeiro } 8743ee84446SAdrien Mazarguil 8753ee84446SAdrien Mazarguil /* Return packet. */ 8763ee84446SAdrien Mazarguil *(pkts++) = pkt_buf; 8773ee84446SAdrien Mazarguil ++pkts_ret; 87887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 87987011737SAdrien Mazarguil /* Increment bytes counter. */ 88087011737SAdrien Mazarguil rxq->stats.ibytes += pkt_buf_len; 88187011737SAdrien Mazarguil #endif 8823ee84446SAdrien Mazarguil repost: 883e1682023SNelio Laranjeiro ret = rxq->recv(rxq->wq, elt->sges, RTE_DIM(elt->sges)); 88461bdf1e0SAdrien Mazarguil if (unlikely(ret)) { 88561bdf1e0SAdrien Mazarguil /* Inability to repost WRs is fatal. */ 88661bdf1e0SAdrien Mazarguil DEBUG("%p: recv_sg_list(): failed (ret=%d)", 88761bdf1e0SAdrien Mazarguil (void *)rxq->priv, 88861bdf1e0SAdrien Mazarguil ret); 88961bdf1e0SAdrien Mazarguil abort(); 89061bdf1e0SAdrien Mazarguil } 8913ee84446SAdrien Mazarguil if (++elts_head >= elts_n) 8923ee84446SAdrien Mazarguil elts_head = 0; 8933ee84446SAdrien Mazarguil continue; 8943ee84446SAdrien Mazarguil } 8953ee84446SAdrien Mazarguil if (unlikely(i == 0)) 8963ee84446SAdrien Mazarguil return 0; 8973ee84446SAdrien Mazarguil rxq->elts_head = elts_head; 89887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 89987011737SAdrien Mazarguil /* Increment packets counter. */ 90087011737SAdrien Mazarguil rxq->stats.ipackets += pkts_ret; 90187011737SAdrien Mazarguil #endif 9023ee84446SAdrien Mazarguil return pkts_ret; 9033ee84446SAdrien Mazarguil } 9043ee84446SAdrien Mazarguil 9053ee84446SAdrien Mazarguil /** 9062e22920bSAdrien Mazarguil * DPDK callback for RX. 9072e22920bSAdrien Mazarguil * 9083ee84446SAdrien Mazarguil * The following function is the same as mlx5_rx_burst_sp(), except it doesn't 9093ee84446SAdrien Mazarguil * manage scattered packets. Improves performance when MRU is lower than the 9103ee84446SAdrien Mazarguil * size of the first segment. 9113ee84446SAdrien Mazarguil * 9122e22920bSAdrien Mazarguil * @param dpdk_rxq 9132e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 9142e22920bSAdrien Mazarguil * @param[out] pkts 9152e22920bSAdrien Mazarguil * Array to store received packets. 9162e22920bSAdrien Mazarguil * @param pkts_n 9172e22920bSAdrien Mazarguil * Maximum number of packets in array. 9182e22920bSAdrien Mazarguil * 9192e22920bSAdrien Mazarguil * @return 9202e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 9212e22920bSAdrien Mazarguil */ 9222e22920bSAdrien Mazarguil uint16_t 9232e22920bSAdrien Mazarguil mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 9242e22920bSAdrien Mazarguil { 9252e22920bSAdrien Mazarguil struct rxq *rxq = (struct rxq *)dpdk_rxq; 9262e22920bSAdrien Mazarguil struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp; 9272e22920bSAdrien Mazarguil const unsigned int elts_n = rxq->elts_n; 9282e22920bSAdrien Mazarguil unsigned int elts_head = rxq->elts_head; 9292e22920bSAdrien Mazarguil struct ibv_sge sges[pkts_n]; 9302e22920bSAdrien Mazarguil unsigned int i; 9312e22920bSAdrien Mazarguil unsigned int pkts_ret = 0; 9322e22920bSAdrien Mazarguil int ret; 9332e22920bSAdrien Mazarguil 9343ee84446SAdrien Mazarguil if (unlikely(rxq->sp)) 9353ee84446SAdrien Mazarguil return mlx5_rx_burst_sp(dpdk_rxq, pkts, pkts_n); 9362e22920bSAdrien Mazarguil for (i = 0; (i != pkts_n); ++i) { 9372e22920bSAdrien Mazarguil struct rxq_elt *elt = &(*elts)[elts_head]; 9382e22920bSAdrien Mazarguil unsigned int len; 939aa7f63abSAdrien Mazarguil struct rte_mbuf *seg = elt->buf; 9402e22920bSAdrien Mazarguil struct rte_mbuf *rep; 9412e22920bSAdrien Mazarguil uint32_t flags; 942f3db9489SYaacov Hazan uint16_t vlan_tci; 9432e22920bSAdrien Mazarguil 9442e22920bSAdrien Mazarguil /* Sanity checks. */ 945aa7f63abSAdrien Mazarguil assert(seg != NULL); 9462e22920bSAdrien Mazarguil assert(elts_head < rxq->elts_n); 9472e22920bSAdrien Mazarguil assert(rxq->elts_head < rxq->elts_n); 9482e22920bSAdrien Mazarguil /* 9492e22920bSAdrien Mazarguil * Fetch initial bytes of packet descriptor into a 9502e22920bSAdrien Mazarguil * cacheline while allocating rep. 9512e22920bSAdrien Mazarguil */ 9522e22920bSAdrien Mazarguil rte_prefetch0(seg); 9532e22920bSAdrien Mazarguil rte_prefetch0(&seg->cacheline1); 954e1682023SNelio Laranjeiro ret = rxq->poll(rxq->cq, NULL, NULL, &flags, &vlan_tci); 9552e22920bSAdrien Mazarguil if (unlikely(ret < 0)) { 9562e22920bSAdrien Mazarguil struct ibv_wc wc; 9572e22920bSAdrien Mazarguil int wcs_n; 9582e22920bSAdrien Mazarguil 9592e22920bSAdrien Mazarguil DEBUG("rxq=%p, poll_length() failed (ret=%d)", 9602e22920bSAdrien Mazarguil (void *)rxq, ret); 9612e22920bSAdrien Mazarguil /* ibv_poll_cq() must be used in case of failure. */ 9622e22920bSAdrien Mazarguil wcs_n = ibv_poll_cq(rxq->cq, 1, &wc); 9632e22920bSAdrien Mazarguil if (unlikely(wcs_n == 0)) 9642e22920bSAdrien Mazarguil break; 9652e22920bSAdrien Mazarguil if (unlikely(wcs_n < 0)) { 9662e22920bSAdrien Mazarguil DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)", 9672e22920bSAdrien Mazarguil (void *)rxq, wcs_n); 9682e22920bSAdrien Mazarguil break; 9692e22920bSAdrien Mazarguil } 9702e22920bSAdrien Mazarguil assert(wcs_n == 1); 9712e22920bSAdrien Mazarguil if (unlikely(wc.status != IBV_WC_SUCCESS)) { 9722e22920bSAdrien Mazarguil /* Whatever, just repost the offending WR. */ 9732e22920bSAdrien Mazarguil DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work" 9742e22920bSAdrien Mazarguil " completion status (%d): %s", 9752e22920bSAdrien Mazarguil (void *)rxq, wc.wr_id, wc.status, 9762e22920bSAdrien Mazarguil ibv_wc_status_str(wc.status)); 97787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 97887011737SAdrien Mazarguil /* Increment dropped packets counter. */ 97987011737SAdrien Mazarguil ++rxq->stats.idropped; 98087011737SAdrien Mazarguil #endif 9812e22920bSAdrien Mazarguil /* Add SGE to array for repost. */ 9822e22920bSAdrien Mazarguil sges[i] = elt->sge; 9832e22920bSAdrien Mazarguil goto repost; 9842e22920bSAdrien Mazarguil } 9852e22920bSAdrien Mazarguil ret = wc.byte_len; 9862e22920bSAdrien Mazarguil } 9872e22920bSAdrien Mazarguil if (ret == 0) 9882e22920bSAdrien Mazarguil break; 9892e22920bSAdrien Mazarguil len = ret; 9902e22920bSAdrien Mazarguil rep = __rte_mbuf_raw_alloc(rxq->mp); 9912e22920bSAdrien Mazarguil if (unlikely(rep == NULL)) { 9922e22920bSAdrien Mazarguil /* 9932e22920bSAdrien Mazarguil * Unable to allocate a replacement mbuf, 9942e22920bSAdrien Mazarguil * repost WR. 9952e22920bSAdrien Mazarguil */ 996aa7f63abSAdrien Mazarguil DEBUG("rxq=%p: can't allocate a new mbuf", 997aa7f63abSAdrien Mazarguil (void *)rxq); 9982e22920bSAdrien Mazarguil /* Increment out of memory counters. */ 99987011737SAdrien Mazarguil ++rxq->stats.rx_nombuf; 10002e22920bSAdrien Mazarguil ++rxq->priv->dev->data->rx_mbuf_alloc_failed; 10012e22920bSAdrien Mazarguil goto repost; 10022e22920bSAdrien Mazarguil } 10032e22920bSAdrien Mazarguil 10042e22920bSAdrien Mazarguil /* Reconfigure sge to use rep instead of seg. */ 10052e22920bSAdrien Mazarguil elt->sge.addr = (uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM; 10062e22920bSAdrien Mazarguil assert(elt->sge.lkey == rxq->mr->lkey); 1007aa7f63abSAdrien Mazarguil elt->buf = rep; 10082e22920bSAdrien Mazarguil 10092e22920bSAdrien Mazarguil /* Add SGE to array for repost. */ 10102e22920bSAdrien Mazarguil sges[i] = elt->sge; 10112e22920bSAdrien Mazarguil 10122e22920bSAdrien Mazarguil /* Update seg information. */ 10132e22920bSAdrien Mazarguil SET_DATA_OFF(seg, RTE_PKTMBUF_HEADROOM); 10142e22920bSAdrien Mazarguil NB_SEGS(seg) = 1; 10152e22920bSAdrien Mazarguil PORT(seg) = rxq->port_id; 10162e22920bSAdrien Mazarguil NEXT(seg) = NULL; 10172e22920bSAdrien Mazarguil PKT_LEN(seg) = len; 10182e22920bSAdrien Mazarguil DATA_LEN(seg) = len; 1019081f7eaeSNelio Laranjeiro if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip) { 102067fa62bcSAdrien Mazarguil seg->packet_type = rxq_cq_to_pkt_type(flags); 102167fa62bcSAdrien Mazarguil seg->ol_flags = rxq_cq_to_ol_flags(rxq, flags); 1022f3db9489SYaacov Hazan #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS 1023f3db9489SYaacov Hazan if (flags & IBV_EXP_CQ_RX_CVLAN_STRIPPED_V1) { 1024f3db9489SYaacov Hazan seg->ol_flags |= PKT_RX_VLAN_PKT; 1025f3db9489SYaacov Hazan seg->vlan_tci = vlan_tci; 1026f3db9489SYaacov Hazan } 1027f3db9489SYaacov Hazan #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ 1028081f7eaeSNelio Laranjeiro } 10292e22920bSAdrien Mazarguil /* Return packet. */ 10302e22920bSAdrien Mazarguil *(pkts++) = seg; 10312e22920bSAdrien Mazarguil ++pkts_ret; 103287011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 103387011737SAdrien Mazarguil /* Increment bytes counter. */ 103487011737SAdrien Mazarguil rxq->stats.ibytes += len; 103587011737SAdrien Mazarguil #endif 10362e22920bSAdrien Mazarguil repost: 10372e22920bSAdrien Mazarguil if (++elts_head >= elts_n) 10382e22920bSAdrien Mazarguil elts_head = 0; 10392e22920bSAdrien Mazarguil continue; 10402e22920bSAdrien Mazarguil } 10412e22920bSAdrien Mazarguil if (unlikely(i == 0)) 10422e22920bSAdrien Mazarguil return 0; 10432e22920bSAdrien Mazarguil /* Repost WRs. */ 10442e22920bSAdrien Mazarguil #ifdef DEBUG_RECV 10452e22920bSAdrien Mazarguil DEBUG("%p: reposting %u WRs", (void *)rxq, i); 10462e22920bSAdrien Mazarguil #endif 1047e1682023SNelio Laranjeiro ret = rxq->recv(rxq->wq, sges, i); 10482e22920bSAdrien Mazarguil if (unlikely(ret)) { 10492e22920bSAdrien Mazarguil /* Inability to repost WRs is fatal. */ 10502e22920bSAdrien Mazarguil DEBUG("%p: recv_burst(): failed (ret=%d)", 10512e22920bSAdrien Mazarguil (void *)rxq->priv, 10522e22920bSAdrien Mazarguil ret); 10532e22920bSAdrien Mazarguil abort(); 10542e22920bSAdrien Mazarguil } 10552e22920bSAdrien Mazarguil rxq->elts_head = elts_head; 105687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 105787011737SAdrien Mazarguil /* Increment packets counter. */ 105887011737SAdrien Mazarguil rxq->stats.ipackets += pkts_ret; 105987011737SAdrien Mazarguil #endif 10602e22920bSAdrien Mazarguil return pkts_ret; 10612e22920bSAdrien Mazarguil } 10622e22920bSAdrien Mazarguil 10632e22920bSAdrien Mazarguil /** 10642e22920bSAdrien Mazarguil * Dummy DPDK callback for TX. 10652e22920bSAdrien Mazarguil * 10662e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 10672e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 10682e22920bSAdrien Mazarguil * 10692e22920bSAdrien Mazarguil * @param dpdk_txq 10702e22920bSAdrien Mazarguil * Generic pointer to TX queue structure. 10712e22920bSAdrien Mazarguil * @param[in] pkts 10722e22920bSAdrien Mazarguil * Packets to transmit. 10732e22920bSAdrien Mazarguil * @param pkts_n 10742e22920bSAdrien Mazarguil * Number of packets in array. 10752e22920bSAdrien Mazarguil * 10762e22920bSAdrien Mazarguil * @return 10772e22920bSAdrien Mazarguil * Number of packets successfully transmitted (<= pkts_n). 10782e22920bSAdrien Mazarguil */ 10792e22920bSAdrien Mazarguil uint16_t 10802e22920bSAdrien Mazarguil removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) 10812e22920bSAdrien Mazarguil { 10822e22920bSAdrien Mazarguil (void)dpdk_txq; 10832e22920bSAdrien Mazarguil (void)pkts; 10842e22920bSAdrien Mazarguil (void)pkts_n; 10852e22920bSAdrien Mazarguil return 0; 10862e22920bSAdrien Mazarguil } 10872e22920bSAdrien Mazarguil 10882e22920bSAdrien Mazarguil /** 10892e22920bSAdrien Mazarguil * Dummy DPDK callback for RX. 10902e22920bSAdrien Mazarguil * 10912e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 10922e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 10932e22920bSAdrien Mazarguil * 10942e22920bSAdrien Mazarguil * @param dpdk_rxq 10952e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 10962e22920bSAdrien Mazarguil * @param[out] pkts 10972e22920bSAdrien Mazarguil * Array to store received packets. 10982e22920bSAdrien Mazarguil * @param pkts_n 10992e22920bSAdrien Mazarguil * Maximum number of packets in array. 11002e22920bSAdrien Mazarguil * 11012e22920bSAdrien Mazarguil * @return 11022e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 11032e22920bSAdrien Mazarguil */ 11042e22920bSAdrien Mazarguil uint16_t 11052e22920bSAdrien Mazarguil removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 11062e22920bSAdrien Mazarguil { 11072e22920bSAdrien Mazarguil (void)dpdk_rxq; 11082e22920bSAdrien Mazarguil (void)pkts; 11092e22920bSAdrien Mazarguil (void)pkts_n; 11102e22920bSAdrien Mazarguil return 0; 11112e22920bSAdrien Mazarguil } 1112