18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 22e22920bSAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 42e22920bSAdrien Mazarguil */ 52e22920bSAdrien Mazarguil 62e22920bSAdrien Mazarguil #include <assert.h> 72e22920bSAdrien Mazarguil #include <stdint.h> 82e22920bSAdrien Mazarguil #include <string.h> 92e22920bSAdrien Mazarguil #include <stdlib.h> 102e22920bSAdrien Mazarguil 112e22920bSAdrien Mazarguil /* Verbs header. */ 122e22920bSAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 132e22920bSAdrien Mazarguil #ifdef PEDANTIC 14fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 152e22920bSAdrien Mazarguil #endif 162e22920bSAdrien Mazarguil #include <infiniband/verbs.h> 1743e9d979SShachar Beiser #include <infiniband/mlx5dv.h> 182e22920bSAdrien Mazarguil #ifdef PEDANTIC 19fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 202e22920bSAdrien Mazarguil #endif 212e22920bSAdrien Mazarguil 222e22920bSAdrien Mazarguil #include <rte_mbuf.h> 232e22920bSAdrien Mazarguil #include <rte_mempool.h> 242e22920bSAdrien Mazarguil #include <rte_prefetch.h> 252e22920bSAdrien Mazarguil #include <rte_common.h> 262e22920bSAdrien Mazarguil #include <rte_branch_prediction.h> 276218063bSNélio Laranjeiro #include <rte_ether.h> 2888c07335SMatan Azrad #include <rte_cycles.h> 292e22920bSAdrien Mazarguil 302e22920bSAdrien Mazarguil #include "mlx5.h" 312e22920bSAdrien Mazarguil #include "mlx5_utils.h" 322e22920bSAdrien Mazarguil #include "mlx5_rxtx.h" 33f3db9489SYaacov Hazan #include "mlx5_autoconf.h" 342e22920bSAdrien Mazarguil #include "mlx5_defs.h" 356218063bSNélio Laranjeiro #include "mlx5_prm.h" 366218063bSNélio Laranjeiro 37c0583d98SJerin Jacob static __rte_always_inline uint32_t 383cc08bc6SXueming Li rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe); 39ff1807a3SNélio Laranjeiro 40c0583d98SJerin Jacob static __rte_always_inline int 4178142aacSNélio Laranjeiro mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe, 422e633f1fSYongseok Koh uint16_t cqe_cnt, volatile struct mlx5_mini_cqe8 **mcqe); 43ff1807a3SNélio Laranjeiro 44c0583d98SJerin Jacob static __rte_always_inline uint32_t 456ba07449SXueming Li rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe); 46ff1807a3SNélio Laranjeiro 473e1f82a1SYongseok Koh static __rte_always_inline void 483e1f82a1SYongseok Koh rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt, 493e1f82a1SYongseok Koh volatile struct mlx5_cqe *cqe, uint32_t rss_hash_res); 503e1f82a1SYongseok Koh 517d6bf6b8SYongseok Koh static __rte_always_inline void 527d6bf6b8SYongseok Koh mprq_buf_replace(struct mlx5_rxq_data *rxq, uint16_t rq_idx); 537d6bf6b8SYongseok Koh 5435c090eaSMatan Azrad static int 5535c090eaSMatan Azrad mlx5_queue_state_modify(struct rte_eth_dev *dev, 5635c090eaSMatan Azrad struct mlx5_mp_arg_queue_state_modify *sm); 5735c090eaSMatan Azrad 58ea16068cSYongseok Koh uint32_t mlx5_ptype_table[] __rte_cache_aligned = { 59ea16068cSYongseok Koh [0xff] = RTE_PTYPE_ALL_MASK, /* Last entry for errored packet. */ 60ea16068cSYongseok Koh }; 61ea16068cSYongseok Koh 625f8ba81cSXueming Li uint8_t mlx5_cksum_table[1 << 10] __rte_cache_aligned; 635f8ba81cSXueming Li uint8_t mlx5_swp_types_table[1 << 10] __rte_cache_aligned; 645f8ba81cSXueming Li 65ea16068cSYongseok Koh /** 66ea16068cSYongseok Koh * Build a table to translate Rx completion flags to packet type. 67ea16068cSYongseok Koh * 68ea16068cSYongseok Koh * @note: fix mlx5_dev_supported_ptypes_get() if any change here. 69ea16068cSYongseok Koh */ 70ea16068cSYongseok Koh void 71ea16068cSYongseok Koh mlx5_set_ptype_table(void) 72ea16068cSYongseok Koh { 73ea16068cSYongseok Koh unsigned int i; 74ea16068cSYongseok Koh uint32_t (*p)[RTE_DIM(mlx5_ptype_table)] = &mlx5_ptype_table; 75ea16068cSYongseok Koh 769807f113SYongseok Koh /* Last entry must not be overwritten, reserved for errored packet. */ 779807f113SYongseok Koh for (i = 0; i < RTE_DIM(mlx5_ptype_table) - 1; ++i) 78ea16068cSYongseok Koh (*p)[i] = RTE_PTYPE_UNKNOWN; 796cb559d6SYongseok Koh /* 806cb559d6SYongseok Koh * The index to the array should have: 81ea16068cSYongseok Koh * bit[1:0] = l3_hdr_type 82ea16068cSYongseok Koh * bit[4:2] = l4_hdr_type 83ea16068cSYongseok Koh * bit[5] = ip_frag 84ea16068cSYongseok Koh * bit[6] = tunneled 85ea16068cSYongseok Koh * bit[7] = outer_l3_type 8699c12dccSNélio Laranjeiro */ 873ca63b88SShahaf Shuler /* L2 */ 883ca63b88SShahaf Shuler (*p)[0x00] = RTE_PTYPE_L2_ETHER; 89ea16068cSYongseok Koh /* L3 */ 90ea16068cSYongseok Koh (*p)[0x01] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 91ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG; 92ea16068cSYongseok Koh (*p)[0x02] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 93ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG; 94ea16068cSYongseok Koh /* Fragmented */ 95ea16068cSYongseok Koh (*p)[0x21] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 96ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG; 97ea16068cSYongseok Koh (*p)[0x22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 98ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG; 99ea16068cSYongseok Koh /* TCP */ 100ea16068cSYongseok Koh (*p)[0x05] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 101ea16068cSYongseok Koh RTE_PTYPE_L4_TCP; 102ea16068cSYongseok Koh (*p)[0x06] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 103ea16068cSYongseok Koh RTE_PTYPE_L4_TCP; 1040915e287SBin Huang (*p)[0x0d] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1050915e287SBin Huang RTE_PTYPE_L4_TCP; 1060915e287SBin Huang (*p)[0x0e] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1070915e287SBin Huang RTE_PTYPE_L4_TCP; 1080915e287SBin Huang (*p)[0x11] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1090915e287SBin Huang RTE_PTYPE_L4_TCP; 1100915e287SBin Huang (*p)[0x12] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1110915e287SBin Huang RTE_PTYPE_L4_TCP; 112ea16068cSYongseok Koh /* UDP */ 113ea16068cSYongseok Koh (*p)[0x09] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 114ea16068cSYongseok Koh RTE_PTYPE_L4_UDP; 115ea16068cSYongseok Koh (*p)[0x0a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 116ea16068cSYongseok Koh RTE_PTYPE_L4_UDP; 117ea16068cSYongseok Koh /* Repeat with outer_l3_type being set. Just in case. */ 118ea16068cSYongseok Koh (*p)[0x81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 119ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG; 120ea16068cSYongseok Koh (*p)[0x82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 121ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG; 122ea16068cSYongseok Koh (*p)[0xa1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 123ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG; 124ea16068cSYongseok Koh (*p)[0xa2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 125ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG; 126ea16068cSYongseok Koh (*p)[0x85] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 127ea16068cSYongseok Koh RTE_PTYPE_L4_TCP; 128ea16068cSYongseok Koh (*p)[0x86] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 129ea16068cSYongseok Koh RTE_PTYPE_L4_TCP; 1300915e287SBin Huang (*p)[0x8d] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1310915e287SBin Huang RTE_PTYPE_L4_TCP; 1320915e287SBin Huang (*p)[0x8e] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1330915e287SBin Huang RTE_PTYPE_L4_TCP; 1340915e287SBin Huang (*p)[0x91] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1350915e287SBin Huang RTE_PTYPE_L4_TCP; 1360915e287SBin Huang (*p)[0x92] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1370915e287SBin Huang RTE_PTYPE_L4_TCP; 138ea16068cSYongseok Koh (*p)[0x89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 139ea16068cSYongseok Koh RTE_PTYPE_L4_UDP; 140ea16068cSYongseok Koh (*p)[0x8a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 141ea16068cSYongseok Koh RTE_PTYPE_L4_UDP; 142ea16068cSYongseok Koh /* Tunneled - L3 */ 1433cc08bc6SXueming Li (*p)[0x40] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN; 144ea16068cSYongseok Koh (*p)[0x41] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 145ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 146ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG; 147ea16068cSYongseok Koh (*p)[0x42] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 148ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 149ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG; 1503cc08bc6SXueming Li (*p)[0xc0] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; 151ea16068cSYongseok Koh (*p)[0xc1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 152ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 153ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG; 154ea16068cSYongseok Koh (*p)[0xc2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 155ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 156ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG; 157ea16068cSYongseok Koh /* Tunneled - Fragmented */ 158ea16068cSYongseok Koh (*p)[0x61] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 159ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 160ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG; 161ea16068cSYongseok Koh (*p)[0x62] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 162ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 163ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG; 164ea16068cSYongseok Koh (*p)[0xe1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 165ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 166ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG; 167ea16068cSYongseok Koh (*p)[0xe2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 168ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 169ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG; 170ea16068cSYongseok Koh /* Tunneled - TCP */ 171ea16068cSYongseok Koh (*p)[0x45] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 172ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 1736c897093SYongseok Koh RTE_PTYPE_INNER_L4_TCP; 174ea16068cSYongseok Koh (*p)[0x46] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 175ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 1766c897093SYongseok Koh RTE_PTYPE_INNER_L4_TCP; 1770915e287SBin Huang (*p)[0x4d] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1780915e287SBin Huang RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 1790915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 1800915e287SBin Huang (*p)[0x4e] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1810915e287SBin Huang RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 1820915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 1830915e287SBin Huang (*p)[0x51] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1840915e287SBin Huang RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 1850915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 1860915e287SBin Huang (*p)[0x52] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 1870915e287SBin Huang RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 1880915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 189ea16068cSYongseok Koh (*p)[0xc5] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 190ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 1916c897093SYongseok Koh RTE_PTYPE_INNER_L4_TCP; 192ea16068cSYongseok Koh (*p)[0xc6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 193ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 1946c897093SYongseok Koh RTE_PTYPE_INNER_L4_TCP; 1950915e287SBin Huang (*p)[0xcd] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1960915e287SBin Huang RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 1970915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 1980915e287SBin Huang (*p)[0xce] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 1990915e287SBin Huang RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 2000915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 2010915e287SBin Huang (*p)[0xd1] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 2020915e287SBin Huang RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 2030915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 2040915e287SBin Huang (*p)[0xd2] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 2050915e287SBin Huang RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 2060915e287SBin Huang RTE_PTYPE_INNER_L4_TCP; 207ea16068cSYongseok Koh /* Tunneled - UDP */ 208ea16068cSYongseok Koh (*p)[0x49] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 209ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 2106c897093SYongseok Koh RTE_PTYPE_INNER_L4_UDP; 211ea16068cSYongseok Koh (*p)[0x4a] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 212ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 2136c897093SYongseok Koh RTE_PTYPE_INNER_L4_UDP; 214ea16068cSYongseok Koh (*p)[0xc9] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 215ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 2166c897093SYongseok Koh RTE_PTYPE_INNER_L4_UDP; 217ea16068cSYongseok Koh (*p)[0xca] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 218ea16068cSYongseok Koh RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | 2196c897093SYongseok Koh RTE_PTYPE_INNER_L4_UDP; 220ea16068cSYongseok Koh } 221fdcb0f53SNélio Laranjeiro 2222e22920bSAdrien Mazarguil /** 2235f8ba81cSXueming Li * Build a table to translate packet to checksum type of Verbs. 2245f8ba81cSXueming Li */ 2255f8ba81cSXueming Li void 2265f8ba81cSXueming Li mlx5_set_cksum_table(void) 2275f8ba81cSXueming Li { 2285f8ba81cSXueming Li unsigned int i; 2295f8ba81cSXueming Li uint8_t v; 2305f8ba81cSXueming Li 2315f8ba81cSXueming Li /* 2325f8ba81cSXueming Li * The index should have: 2335f8ba81cSXueming Li * bit[0] = PKT_TX_TCP_SEG 2345f8ba81cSXueming Li * bit[2:3] = PKT_TX_UDP_CKSUM, PKT_TX_TCP_CKSUM 2355f8ba81cSXueming Li * bit[4] = PKT_TX_IP_CKSUM 2365f8ba81cSXueming Li * bit[8] = PKT_TX_OUTER_IP_CKSUM 2375f8ba81cSXueming Li * bit[9] = tunnel 2385f8ba81cSXueming Li */ 2395f8ba81cSXueming Li for (i = 0; i < RTE_DIM(mlx5_cksum_table); ++i) { 2405f8ba81cSXueming Li v = 0; 2415f8ba81cSXueming Li if (i & (1 << 9)) { 2425f8ba81cSXueming Li /* Tunneled packet. */ 2435f8ba81cSXueming Li if (i & (1 << 8)) /* Outer IP. */ 2445f8ba81cSXueming Li v |= MLX5_ETH_WQE_L3_CSUM; 2455f8ba81cSXueming Li if (i & (1 << 4)) /* Inner IP. */ 2465f8ba81cSXueming Li v |= MLX5_ETH_WQE_L3_INNER_CSUM; 2475f8ba81cSXueming Li if (i & (3 << 2 | 1 << 0)) /* L4 or TSO. */ 2485f8ba81cSXueming Li v |= MLX5_ETH_WQE_L4_INNER_CSUM; 2495f8ba81cSXueming Li } else { 2505f8ba81cSXueming Li /* No tunnel. */ 2515f8ba81cSXueming Li if (i & (1 << 4)) /* IP. */ 2525f8ba81cSXueming Li v |= MLX5_ETH_WQE_L3_CSUM; 2535f8ba81cSXueming Li if (i & (3 << 2 | 1 << 0)) /* L4 or TSO. */ 2545f8ba81cSXueming Li v |= MLX5_ETH_WQE_L4_CSUM; 2555f8ba81cSXueming Li } 2565f8ba81cSXueming Li mlx5_cksum_table[i] = v; 2575f8ba81cSXueming Li } 2585f8ba81cSXueming Li } 2595f8ba81cSXueming Li 2605f8ba81cSXueming Li /** 2615f8ba81cSXueming Li * Build a table to translate packet type of mbuf to SWP type of Verbs. 2625f8ba81cSXueming Li */ 2635f8ba81cSXueming Li void 2645f8ba81cSXueming Li mlx5_set_swp_types_table(void) 2655f8ba81cSXueming Li { 2665f8ba81cSXueming Li unsigned int i; 2675f8ba81cSXueming Li uint8_t v; 2685f8ba81cSXueming Li 2695f8ba81cSXueming Li /* 2705f8ba81cSXueming Li * The index should have: 2715f8ba81cSXueming Li * bit[0:1] = PKT_TX_L4_MASK 2725f8ba81cSXueming Li * bit[4] = PKT_TX_IPV6 2735f8ba81cSXueming Li * bit[8] = PKT_TX_OUTER_IPV6 2745f8ba81cSXueming Li * bit[9] = PKT_TX_OUTER_UDP 2755f8ba81cSXueming Li */ 2765f8ba81cSXueming Li for (i = 0; i < RTE_DIM(mlx5_swp_types_table); ++i) { 2775f8ba81cSXueming Li v = 0; 2785f8ba81cSXueming Li if (i & (1 << 8)) 2795f8ba81cSXueming Li v |= MLX5_ETH_WQE_L3_OUTER_IPV6; 2805f8ba81cSXueming Li if (i & (1 << 9)) 2815f8ba81cSXueming Li v |= MLX5_ETH_WQE_L4_OUTER_UDP; 2825f8ba81cSXueming Li if (i & (1 << 4)) 2835f8ba81cSXueming Li v |= MLX5_ETH_WQE_L3_INNER_IPV6; 2845f8ba81cSXueming Li if ((i & 3) == (PKT_TX_UDP_CKSUM >> 52)) 2855f8ba81cSXueming Li v |= MLX5_ETH_WQE_L4_INNER_UDP; 2865f8ba81cSXueming Li mlx5_swp_types_table[i] = v; 2875f8ba81cSXueming Li } 2885f8ba81cSXueming Li } 2895f8ba81cSXueming Li 2905f8ba81cSXueming Li /** 29126f04883STom Barbette * Internal function to compute the number of used descriptors in an RX queue 2928788fec1SOlivier Matz * 29326f04883STom Barbette * @param rxq 29426f04883STom Barbette * The Rx queue. 2958788fec1SOlivier Matz * 2968788fec1SOlivier Matz * @return 29726f04883STom Barbette * The number of used rx descriptor. 2988788fec1SOlivier Matz */ 29926f04883STom Barbette static uint32_t 30026f04883STom Barbette rx_queue_count(struct mlx5_rxq_data *rxq) 3018788fec1SOlivier Matz { 3028788fec1SOlivier Matz struct rxq_zip *zip = &rxq->zip; 3038788fec1SOlivier Matz volatile struct mlx5_cqe *cqe; 3048788fec1SOlivier Matz const unsigned int cqe_n = (1 << rxq->cqe_n); 3058788fec1SOlivier Matz const unsigned int cqe_cnt = cqe_n - 1; 3068788fec1SOlivier Matz unsigned int cq_ci; 3078788fec1SOlivier Matz unsigned int used; 3088788fec1SOlivier Matz 3098788fec1SOlivier Matz /* if we are processing a compressed cqe */ 3108788fec1SOlivier Matz if (zip->ai) { 3118788fec1SOlivier Matz used = zip->cqe_cnt - zip->ca; 3128788fec1SOlivier Matz cq_ci = zip->cq_ci; 3138788fec1SOlivier Matz } else { 3148788fec1SOlivier Matz used = 0; 3158788fec1SOlivier Matz cq_ci = rxq->cq_ci; 3168788fec1SOlivier Matz } 3178788fec1SOlivier Matz cqe = &(*rxq->cqes)[cq_ci & cqe_cnt]; 31888c07335SMatan Azrad while (check_cqe(cqe, cqe_n, cq_ci) != MLX5_CQE_STATUS_HW_OWN) { 3198788fec1SOlivier Matz int8_t op_own; 3208788fec1SOlivier Matz unsigned int n; 3218788fec1SOlivier Matz 3228788fec1SOlivier Matz op_own = cqe->op_own; 3238788fec1SOlivier Matz if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) 3246b30a6a8SShachar Beiser n = rte_be_to_cpu_32(cqe->byte_cnt); 3258788fec1SOlivier Matz else 3268788fec1SOlivier Matz n = 1; 3278788fec1SOlivier Matz cq_ci += n; 3288788fec1SOlivier Matz used += n; 3298788fec1SOlivier Matz cqe = &(*rxq->cqes)[cq_ci & cqe_cnt]; 3308788fec1SOlivier Matz } 3318788fec1SOlivier Matz used = RTE_MIN(used, (1U << rxq->elts_n) - 1); 33226f04883STom Barbette return used; 33326f04883STom Barbette } 33426f04883STom Barbette 33526f04883STom Barbette /** 33626f04883STom Barbette * DPDK callback to check the status of a rx descriptor. 33726f04883STom Barbette * 33826f04883STom Barbette * @param rx_queue 33926f04883STom Barbette * The Rx queue. 34026f04883STom Barbette * @param[in] offset 34126f04883STom Barbette * The index of the descriptor in the ring. 34226f04883STom Barbette * 34326f04883STom Barbette * @return 34426f04883STom Barbette * The status of the tx descriptor. 34526f04883STom Barbette */ 34626f04883STom Barbette int 34726f04883STom Barbette mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset) 34826f04883STom Barbette { 34926f04883STom Barbette struct mlx5_rxq_data *rxq = rx_queue; 35026f04883STom Barbette struct mlx5_rxq_ctrl *rxq_ctrl = 35126f04883STom Barbette container_of(rxq, struct mlx5_rxq_ctrl, rxq); 35226f04883STom Barbette struct rte_eth_dev *dev = ETH_DEV(rxq_ctrl->priv); 35326f04883STom Barbette 35426f04883STom Barbette if (dev->rx_pkt_burst != mlx5_rx_burst) { 35526f04883STom Barbette rte_errno = ENOTSUP; 35626f04883STom Barbette return -rte_errno; 35726f04883STom Barbette } 35826f04883STom Barbette if (offset >= (1 << rxq->elts_n)) { 35926f04883STom Barbette rte_errno = EINVAL; 36026f04883STom Barbette return -rte_errno; 36126f04883STom Barbette } 36226f04883STom Barbette if (offset < rx_queue_count(rxq)) 3638788fec1SOlivier Matz return RTE_ETH_RX_DESC_DONE; 3648788fec1SOlivier Matz return RTE_ETH_RX_DESC_AVAIL; 3658788fec1SOlivier Matz } 3668788fec1SOlivier Matz 3678788fec1SOlivier Matz /** 36826f04883STom Barbette * DPDK callback to get the number of used descriptors in a RX queue 36926f04883STom Barbette * 37026f04883STom Barbette * @param dev 37126f04883STom Barbette * Pointer to the device structure. 37226f04883STom Barbette * 37326f04883STom Barbette * @param rx_queue_id 37426f04883STom Barbette * The Rx queue. 37526f04883STom Barbette * 37626f04883STom Barbette * @return 37726f04883STom Barbette * The number of used rx descriptor. 37826f04883STom Barbette * -EINVAL if the queue is invalid 37926f04883STom Barbette */ 38026f04883STom Barbette uint32_t 38126f04883STom Barbette mlx5_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) 38226f04883STom Barbette { 383dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 38426f04883STom Barbette struct mlx5_rxq_data *rxq; 38526f04883STom Barbette 38626f04883STom Barbette if (dev->rx_pkt_burst != mlx5_rx_burst) { 38726f04883STom Barbette rte_errno = ENOTSUP; 38826f04883STom Barbette return -rte_errno; 38926f04883STom Barbette } 39026f04883STom Barbette rxq = (*priv->rxqs)[rx_queue_id]; 39126f04883STom Barbette if (!rxq) { 39226f04883STom Barbette rte_errno = EINVAL; 39326f04883STom Barbette return -rte_errno; 39426f04883STom Barbette } 39526f04883STom Barbette return rx_queue_count(rxq); 39626f04883STom Barbette } 39726f04883STom Barbette 398066cfecdSMatan Azrad #define MLX5_SYSTEM_LOG_DIR "/var/log" 399066cfecdSMatan Azrad /** 400066cfecdSMatan Azrad * Dump debug information to log file. 401066cfecdSMatan Azrad * 402066cfecdSMatan Azrad * @param fname 403066cfecdSMatan Azrad * The file name. 404066cfecdSMatan Azrad * @param hex_title 405066cfecdSMatan Azrad * If not NULL this string is printed as a header to the output 406066cfecdSMatan Azrad * and the output will be in hexadecimal view. 407066cfecdSMatan Azrad * @param buf 408066cfecdSMatan Azrad * This is the buffer address to print out. 409066cfecdSMatan Azrad * @param len 410066cfecdSMatan Azrad * The number of bytes to dump out. 411066cfecdSMatan Azrad */ 412066cfecdSMatan Azrad void 413066cfecdSMatan Azrad mlx5_dump_debug_information(const char *fname, const char *hex_title, 414066cfecdSMatan Azrad const void *buf, unsigned int hex_len) 415066cfecdSMatan Azrad { 416066cfecdSMatan Azrad FILE *fd; 417066cfecdSMatan Azrad 418066cfecdSMatan Azrad MKSTR(path, "%s/%s", MLX5_SYSTEM_LOG_DIR, fname); 419066cfecdSMatan Azrad fd = fopen(path, "a+"); 420066cfecdSMatan Azrad if (!fd) { 421066cfecdSMatan Azrad DRV_LOG(WARNING, "cannot open %s for debug dump\n", 422066cfecdSMatan Azrad path); 423066cfecdSMatan Azrad MKSTR(path2, "./%s", fname); 424066cfecdSMatan Azrad fd = fopen(path2, "a+"); 425066cfecdSMatan Azrad if (!fd) { 426066cfecdSMatan Azrad DRV_LOG(ERR, "cannot open %s for debug dump\n", 427066cfecdSMatan Azrad path2); 428066cfecdSMatan Azrad return; 429066cfecdSMatan Azrad } 430066cfecdSMatan Azrad DRV_LOG(INFO, "New debug dump in file %s\n", path2); 431066cfecdSMatan Azrad } else { 432066cfecdSMatan Azrad DRV_LOG(INFO, "New debug dump in file %s\n", path); 433066cfecdSMatan Azrad } 434066cfecdSMatan Azrad if (hex_title) 435066cfecdSMatan Azrad rte_hexdump(fd, hex_title, buf, hex_len); 436066cfecdSMatan Azrad else 437066cfecdSMatan Azrad fprintf(fd, "%s", (const char *)buf); 438066cfecdSMatan Azrad fprintf(fd, "\n\n\n"); 439066cfecdSMatan Azrad fclose(fd); 440066cfecdSMatan Azrad } 441066cfecdSMatan Azrad 44226f04883STom Barbette /** 44335c090eaSMatan Azrad * Move QP from error state to running state and initialize indexes. 444957e45fbSMatan Azrad * 44535c090eaSMatan Azrad * @param txq_ctrl 44635c090eaSMatan Azrad * Pointer to TX queue control structure. 447957e45fbSMatan Azrad * 448957e45fbSMatan Azrad * @return 44935c090eaSMatan Azrad * 0 on success, else -1. 450957e45fbSMatan Azrad */ 451957e45fbSMatan Azrad static int 45235c090eaSMatan Azrad tx_recover_qp(struct mlx5_txq_ctrl *txq_ctrl) 453957e45fbSMatan Azrad { 45435c090eaSMatan Azrad struct mlx5_mp_arg_queue_state_modify sm = { 45535c090eaSMatan Azrad .is_wq = 0, 45635c090eaSMatan Azrad .queue_id = txq_ctrl->txq.idx, 457957e45fbSMatan Azrad }; 45835c090eaSMatan Azrad 45935c090eaSMatan Azrad if (mlx5_queue_state_modify(ETH_DEV(txq_ctrl->priv), &sm)) 46035c090eaSMatan Azrad return -1; 46135c090eaSMatan Azrad txq_ctrl->txq.wqe_ci = 0; 46235c090eaSMatan Azrad txq_ctrl->txq.wqe_pi = 0; 46335c090eaSMatan Azrad txq_ctrl->txq.elts_comp = 0; 464957e45fbSMatan Azrad return 0; 465957e45fbSMatan Azrad } 466957e45fbSMatan Azrad 467957e45fbSMatan Azrad /* Return 1 if the error CQE is signed otherwise, sign it and return 0. */ 468957e45fbSMatan Azrad static int 469957e45fbSMatan Azrad check_err_cqe_seen(volatile struct mlx5_err_cqe *err_cqe) 470957e45fbSMatan Azrad { 471957e45fbSMatan Azrad static const uint8_t magic[] = "seen"; 472957e45fbSMatan Azrad int ret = 1; 473957e45fbSMatan Azrad unsigned int i; 474957e45fbSMatan Azrad 475957e45fbSMatan Azrad for (i = 0; i < sizeof(magic); ++i) 476957e45fbSMatan Azrad if (!ret || err_cqe->rsvd1[i] != magic[i]) { 477957e45fbSMatan Azrad ret = 0; 478957e45fbSMatan Azrad err_cqe->rsvd1[i] = magic[i]; 479957e45fbSMatan Azrad } 480957e45fbSMatan Azrad return ret; 481957e45fbSMatan Azrad } 482957e45fbSMatan Azrad 483957e45fbSMatan Azrad /** 484957e45fbSMatan Azrad * Handle error CQE. 485957e45fbSMatan Azrad * 486957e45fbSMatan Azrad * @param txq 487957e45fbSMatan Azrad * Pointer to TX queue structure. 488957e45fbSMatan Azrad * @param error_cqe 489957e45fbSMatan Azrad * Pointer to the error CQE. 490957e45fbSMatan Azrad * 491957e45fbSMatan Azrad * @return 492957e45fbSMatan Azrad * The last Tx buffer element to free. 493957e45fbSMatan Azrad */ 494957e45fbSMatan Azrad uint16_t 495957e45fbSMatan Azrad mlx5_tx_error_cqe_handle(struct mlx5_txq_data *txq, 496957e45fbSMatan Azrad volatile struct mlx5_err_cqe *err_cqe) 497957e45fbSMatan Azrad { 498957e45fbSMatan Azrad if (err_cqe->syndrome != MLX5_CQE_SYNDROME_WR_FLUSH_ERR) { 499957e45fbSMatan Azrad const uint16_t wqe_m = ((1 << txq->wqe_n) - 1); 500957e45fbSMatan Azrad struct mlx5_txq_ctrl *txq_ctrl = 501957e45fbSMatan Azrad container_of(txq, struct mlx5_txq_ctrl, txq); 502957e45fbSMatan Azrad uint16_t new_wqe_pi = rte_be_to_cpu_16(err_cqe->wqe_counter); 503957e45fbSMatan Azrad int seen = check_err_cqe_seen(err_cqe); 504957e45fbSMatan Azrad 505957e45fbSMatan Azrad if (!seen && txq_ctrl->dump_file_n < 506957e45fbSMatan Azrad txq_ctrl->priv->config.max_dump_files_num) { 507957e45fbSMatan Azrad MKSTR(err_str, "Unexpected CQE error syndrome " 508957e45fbSMatan Azrad "0x%02x CQN = %u SQN = %u wqe_counter = %u " 509957e45fbSMatan Azrad "wq_ci = %u cq_ci = %u", err_cqe->syndrome, 510*38b4b397SViacheslav Ovsiienko txq->cqe_s, txq->qp_num_8s >> 8, 511957e45fbSMatan Azrad rte_be_to_cpu_16(err_cqe->wqe_counter), 512957e45fbSMatan Azrad txq->wqe_ci, txq->cq_ci); 513957e45fbSMatan Azrad MKSTR(name, "dpdk_mlx5_port_%u_txq_%u_index_%u_%u", 514957e45fbSMatan Azrad PORT_ID(txq_ctrl->priv), txq->idx, 515957e45fbSMatan Azrad txq_ctrl->dump_file_n, (uint32_t)rte_rdtsc()); 516957e45fbSMatan Azrad mlx5_dump_debug_information(name, NULL, err_str, 0); 517957e45fbSMatan Azrad mlx5_dump_debug_information(name, "MLX5 Error CQ:", 518957e45fbSMatan Azrad (const void *)((uintptr_t) 519*38b4b397SViacheslav Ovsiienko txq->cqes), 520957e45fbSMatan Azrad sizeof(*err_cqe) * 521957e45fbSMatan Azrad (1 << txq->cqe_n)); 522957e45fbSMatan Azrad mlx5_dump_debug_information(name, "MLX5 Error SQ:", 523957e45fbSMatan Azrad (const void *)((uintptr_t) 524a6bd4911SViacheslav Ovsiienko txq->wqes), 525957e45fbSMatan Azrad MLX5_WQE_SIZE * 526957e45fbSMatan Azrad (1 << txq->wqe_n)); 527957e45fbSMatan Azrad txq_ctrl->dump_file_n++; 528957e45fbSMatan Azrad } 529957e45fbSMatan Azrad if (!seen) 530957e45fbSMatan Azrad /* 531957e45fbSMatan Azrad * Count errors in WQEs units. 532957e45fbSMatan Azrad * Later it can be improved to count error packets, 533957e45fbSMatan Azrad * for example, by SQ parsing to find how much packets 534957e45fbSMatan Azrad * should be counted for each WQE. 535957e45fbSMatan Azrad */ 536957e45fbSMatan Azrad txq->stats.oerrors += ((txq->wqe_ci & wqe_m) - 537957e45fbSMatan Azrad new_wqe_pi) & wqe_m; 53835c090eaSMatan Azrad if (tx_recover_qp(txq_ctrl) == 0) { 539957e45fbSMatan Azrad txq->cq_ci++; 540957e45fbSMatan Azrad /* Release all the remaining buffers. */ 541957e45fbSMatan Azrad return txq->elts_head; 542957e45fbSMatan Azrad } 543957e45fbSMatan Azrad /* Recovering failed - try again later on the same WQE. */ 544957e45fbSMatan Azrad } else { 545957e45fbSMatan Azrad txq->cq_ci++; 546957e45fbSMatan Azrad } 547957e45fbSMatan Azrad /* Do not release buffers. */ 548957e45fbSMatan Azrad return txq->elts_tail; 549957e45fbSMatan Azrad } 550957e45fbSMatan Azrad 551957e45fbSMatan Azrad /** 55267fa62bcSAdrien Mazarguil * Translate RX completion flags to packet type. 55367fa62bcSAdrien Mazarguil * 5543cc08bc6SXueming Li * @param[in] rxq 5553cc08bc6SXueming Li * Pointer to RX queue structure. 5566218063bSNélio Laranjeiro * @param[in] cqe 5576218063bSNélio Laranjeiro * Pointer to CQE. 55867fa62bcSAdrien Mazarguil * 55978a38edfSJianfeng Tan * @note: fix mlx5_dev_supported_ptypes_get() if any change here. 56078a38edfSJianfeng Tan * 56167fa62bcSAdrien Mazarguil * @return 56267fa62bcSAdrien Mazarguil * Packet type for struct rte_mbuf. 56367fa62bcSAdrien Mazarguil */ 56467fa62bcSAdrien Mazarguil static inline uint32_t 5653cc08bc6SXueming Li rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe) 56667fa62bcSAdrien Mazarguil { 567ea16068cSYongseok Koh uint8_t idx; 568ea16068cSYongseok Koh uint8_t pinfo = cqe->pkt_info; 569ea16068cSYongseok Koh uint16_t ptype = cqe->hdr_type_etc; 57067fa62bcSAdrien Mazarguil 571ea16068cSYongseok Koh /* 572ea16068cSYongseok Koh * The index to the array should have: 573ea16068cSYongseok Koh * bit[1:0] = l3_hdr_type 574ea16068cSYongseok Koh * bit[4:2] = l4_hdr_type 575ea16068cSYongseok Koh * bit[5] = ip_frag 576ea16068cSYongseok Koh * bit[6] = tunneled 577ea16068cSYongseok Koh * bit[7] = outer_l3_type 578ea16068cSYongseok Koh */ 579ea16068cSYongseok Koh idx = ((pinfo & 0x3) << 6) | ((ptype & 0xfc00) >> 10); 5803cc08bc6SXueming Li return mlx5_ptype_table[idx] | rxq->tunnel * !!(idx & (1 << 6)); 58167fa62bcSAdrien Mazarguil } 58267fa62bcSAdrien Mazarguil 58367fa62bcSAdrien Mazarguil /** 5846bb506ccSMatan Azrad * Initialize Rx WQ and indexes. 5856bb506ccSMatan Azrad * 5866bb506ccSMatan Azrad * @param[in] rxq 5876bb506ccSMatan Azrad * Pointer to RX queue structure. 5886bb506ccSMatan Azrad */ 5896bb506ccSMatan Azrad void 5906bb506ccSMatan Azrad mlx5_rxq_initialize(struct mlx5_rxq_data *rxq) 5916bb506ccSMatan Azrad { 5926bb506ccSMatan Azrad const unsigned int wqe_n = 1 << rxq->elts_n; 5936bb506ccSMatan Azrad unsigned int i; 5946bb506ccSMatan Azrad 5956bb506ccSMatan Azrad for (i = 0; (i != wqe_n); ++i) { 5966bb506ccSMatan Azrad volatile struct mlx5_wqe_data_seg *scat; 5976bb506ccSMatan Azrad uintptr_t addr; 5986bb506ccSMatan Azrad uint32_t byte_count; 5996bb506ccSMatan Azrad 6006bb506ccSMatan Azrad if (mlx5_rxq_mprq_enabled(rxq)) { 6016bb506ccSMatan Azrad struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[i]; 6026bb506ccSMatan Azrad 6036bb506ccSMatan Azrad scat = &((volatile struct mlx5_wqe_mprq *) 6046bb506ccSMatan Azrad rxq->wqes)[i].dseg; 6056bb506ccSMatan Azrad addr = (uintptr_t)mlx5_mprq_buf_addr(buf); 6066bb506ccSMatan Azrad byte_count = (1 << rxq->strd_sz_n) * 6076bb506ccSMatan Azrad (1 << rxq->strd_num_n); 6086bb506ccSMatan Azrad } else { 6096bb506ccSMatan Azrad struct rte_mbuf *buf = (*rxq->elts)[i]; 6106bb506ccSMatan Azrad 6116bb506ccSMatan Azrad scat = &((volatile struct mlx5_wqe_data_seg *) 6126bb506ccSMatan Azrad rxq->wqes)[i]; 6136bb506ccSMatan Azrad addr = rte_pktmbuf_mtod(buf, uintptr_t); 6146bb506ccSMatan Azrad byte_count = DATA_LEN(buf); 6156bb506ccSMatan Azrad } 6166bb506ccSMatan Azrad /* scat->addr must be able to store a pointer. */ 6176bb506ccSMatan Azrad assert(sizeof(scat->addr) >= sizeof(uintptr_t)); 6186bb506ccSMatan Azrad *scat = (struct mlx5_wqe_data_seg){ 6196bb506ccSMatan Azrad .addr = rte_cpu_to_be_64(addr), 6206bb506ccSMatan Azrad .byte_count = rte_cpu_to_be_32(byte_count), 6216bb506ccSMatan Azrad .lkey = mlx5_rx_addr2mr(rxq, addr), 6226bb506ccSMatan Azrad }; 6236bb506ccSMatan Azrad } 6246bb506ccSMatan Azrad rxq->consumed_strd = 0; 6256bb506ccSMatan Azrad rxq->decompressed = 0; 6266bb506ccSMatan Azrad rxq->rq_pi = 0; 6276bb506ccSMatan Azrad rxq->zip = (struct rxq_zip){ 6286bb506ccSMatan Azrad .ai = 0, 6296bb506ccSMatan Azrad }; 6306bb506ccSMatan Azrad /* Update doorbell counter. */ 6316bb506ccSMatan Azrad rxq->rq_ci = wqe_n >> rxq->sges_n; 6326bb506ccSMatan Azrad rte_cio_wmb(); 6336bb506ccSMatan Azrad *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci); 6346bb506ccSMatan Azrad } 6356bb506ccSMatan Azrad 6366bb506ccSMatan Azrad /** 6372d77cb61SMatan Azrad * Modify a Verbs queue state. 6382d77cb61SMatan Azrad * This must be called from the primary process. 6392d77cb61SMatan Azrad * 6402d77cb61SMatan Azrad * @param dev 6412d77cb61SMatan Azrad * Pointer to Ethernet device. 6422d77cb61SMatan Azrad * @param sm 6432d77cb61SMatan Azrad * State modify request parameters. 6442d77cb61SMatan Azrad * 6452d77cb61SMatan Azrad * @return 6462d77cb61SMatan Azrad * 0 in case of success else non-zero value and rte_errno is set. 6472d77cb61SMatan Azrad */ 6482d77cb61SMatan Azrad int 6492d77cb61SMatan Azrad mlx5_queue_state_modify_primary(struct rte_eth_dev *dev, 6502d77cb61SMatan Azrad const struct mlx5_mp_arg_queue_state_modify *sm) 6512d77cb61SMatan Azrad { 6522d77cb61SMatan Azrad int ret; 6532d77cb61SMatan Azrad struct mlx5_priv *priv = dev->data->dev_private; 6542d77cb61SMatan Azrad 6552d77cb61SMatan Azrad if (sm->is_wq) { 6562d77cb61SMatan Azrad struct ibv_wq_attr mod = { 6572d77cb61SMatan Azrad .attr_mask = IBV_WQ_ATTR_STATE, 6582d77cb61SMatan Azrad .wq_state = sm->state, 6592d77cb61SMatan Azrad }; 6602d77cb61SMatan Azrad struct mlx5_rxq_data *rxq = (*priv->rxqs)[sm->queue_id]; 6612d77cb61SMatan Azrad struct mlx5_rxq_ctrl *rxq_ctrl = 6622d77cb61SMatan Azrad container_of(rxq, struct mlx5_rxq_ctrl, rxq); 6632d77cb61SMatan Azrad 6642d77cb61SMatan Azrad ret = mlx5_glue->modify_wq(rxq_ctrl->ibv->wq, &mod); 6652d77cb61SMatan Azrad if (ret) { 6662d77cb61SMatan Azrad DRV_LOG(ERR, "Cannot change Rx WQ state to %u - %s\n", 6672d77cb61SMatan Azrad sm->state, strerror(errno)); 6682d77cb61SMatan Azrad rte_errno = errno; 6692d77cb61SMatan Azrad return ret; 6702d77cb61SMatan Azrad } 67135c090eaSMatan Azrad } else { 67235c090eaSMatan Azrad struct mlx5_txq_data *txq = (*priv->txqs)[sm->queue_id]; 67335c090eaSMatan Azrad struct mlx5_txq_ctrl *txq_ctrl = 67435c090eaSMatan Azrad container_of(txq, struct mlx5_txq_ctrl, txq); 67535c090eaSMatan Azrad struct ibv_qp_attr mod = { 67635c090eaSMatan Azrad .qp_state = IBV_QPS_RESET, 67735c090eaSMatan Azrad .port_num = (uint8_t)priv->ibv_port, 67835c090eaSMatan Azrad }; 67935c090eaSMatan Azrad struct ibv_qp *qp = txq_ctrl->ibv->qp; 68035c090eaSMatan Azrad 68135c090eaSMatan Azrad ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE); 68235c090eaSMatan Azrad if (ret) { 68335c090eaSMatan Azrad DRV_LOG(ERR, "Cannot change the Tx QP state to RESET " 68435c090eaSMatan Azrad "%s\n", strerror(errno)); 68535c090eaSMatan Azrad rte_errno = errno; 68635c090eaSMatan Azrad return ret; 68735c090eaSMatan Azrad } 68835c090eaSMatan Azrad mod.qp_state = IBV_QPS_INIT; 68935c090eaSMatan Azrad ret = mlx5_glue->modify_qp(qp, &mod, 69035c090eaSMatan Azrad (IBV_QP_STATE | IBV_QP_PORT)); 69135c090eaSMatan Azrad if (ret) { 69235c090eaSMatan Azrad DRV_LOG(ERR, "Cannot change Tx QP state to INIT %s\n", 69335c090eaSMatan Azrad strerror(errno)); 69435c090eaSMatan Azrad rte_errno = errno; 69535c090eaSMatan Azrad return ret; 69635c090eaSMatan Azrad } 69735c090eaSMatan Azrad mod.qp_state = IBV_QPS_RTR; 69835c090eaSMatan Azrad ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE); 69935c090eaSMatan Azrad if (ret) { 70035c090eaSMatan Azrad DRV_LOG(ERR, "Cannot change Tx QP state to RTR %s\n", 70135c090eaSMatan Azrad strerror(errno)); 70235c090eaSMatan Azrad rte_errno = errno; 70335c090eaSMatan Azrad return ret; 70435c090eaSMatan Azrad } 70535c090eaSMatan Azrad mod.qp_state = IBV_QPS_RTS; 70635c090eaSMatan Azrad ret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE); 70735c090eaSMatan Azrad if (ret) { 70835c090eaSMatan Azrad DRV_LOG(ERR, "Cannot change Tx QP state to RTS %s\n", 70935c090eaSMatan Azrad strerror(errno)); 71035c090eaSMatan Azrad rte_errno = errno; 71135c090eaSMatan Azrad return ret; 71235c090eaSMatan Azrad } 7132d77cb61SMatan Azrad } 7142d77cb61SMatan Azrad return 0; 7152d77cb61SMatan Azrad } 7162d77cb61SMatan Azrad 7172d77cb61SMatan Azrad /** 7182d77cb61SMatan Azrad * Modify a Verbs queue state. 7192d77cb61SMatan Azrad * 7202d77cb61SMatan Azrad * @param dev 7212d77cb61SMatan Azrad * Pointer to Ethernet device. 7222d77cb61SMatan Azrad * @param sm 7232d77cb61SMatan Azrad * State modify request parameters. 7242d77cb61SMatan Azrad * 7252d77cb61SMatan Azrad * @return 7262d77cb61SMatan Azrad * 0 in case of success else non-zero value. 7272d77cb61SMatan Azrad */ 7282d77cb61SMatan Azrad static int 7292d77cb61SMatan Azrad mlx5_queue_state_modify(struct rte_eth_dev *dev, 7302d77cb61SMatan Azrad struct mlx5_mp_arg_queue_state_modify *sm) 7312d77cb61SMatan Azrad { 7322d77cb61SMatan Azrad int ret = 0; 7332d77cb61SMatan Azrad 7342d77cb61SMatan Azrad switch (rte_eal_process_type()) { 7352d77cb61SMatan Azrad case RTE_PROC_PRIMARY: 7362d77cb61SMatan Azrad ret = mlx5_queue_state_modify_primary(dev, sm); 7372d77cb61SMatan Azrad break; 7382d77cb61SMatan Azrad case RTE_PROC_SECONDARY: 7392d77cb61SMatan Azrad ret = mlx5_mp_req_queue_state_modify(dev, sm); 7402d77cb61SMatan Azrad break; 7412d77cb61SMatan Azrad default: 7422d77cb61SMatan Azrad break; 7432d77cb61SMatan Azrad } 7442d77cb61SMatan Azrad return ret; 7452d77cb61SMatan Azrad } 7462d77cb61SMatan Azrad 7472d77cb61SMatan Azrad /** 74888c07335SMatan Azrad * Handle a Rx error. 74988c07335SMatan Azrad * The function inserts the RQ state to reset when the first error CQE is 75088c07335SMatan Azrad * shown, then drains the CQ by the caller function loop. When the CQ is empty, 75188c07335SMatan Azrad * it moves the RQ state to ready and initializes the RQ. 75288c07335SMatan Azrad * Next CQE identification and error counting are in the caller responsibility. 75388c07335SMatan Azrad * 75488c07335SMatan Azrad * @param[in] rxq 75588c07335SMatan Azrad * Pointer to RX queue structure. 75688c07335SMatan Azrad * @param[in] mbuf_prepare 75788c07335SMatan Azrad * Whether to prepare mbufs for the RQ. 75888c07335SMatan Azrad * 75988c07335SMatan Azrad * @return 76088c07335SMatan Azrad * -1 in case of recovery error, otherwise the CQE status. 76188c07335SMatan Azrad */ 76288c07335SMatan Azrad int 76388c07335SMatan Azrad mlx5_rx_err_handle(struct mlx5_rxq_data *rxq, uint8_t mbuf_prepare) 76488c07335SMatan Azrad { 76588c07335SMatan Azrad const uint16_t cqe_n = 1 << rxq->cqe_n; 76688c07335SMatan Azrad const uint16_t cqe_mask = cqe_n - 1; 76788c07335SMatan Azrad const unsigned int wqe_n = 1 << rxq->elts_n; 76888c07335SMatan Azrad struct mlx5_rxq_ctrl *rxq_ctrl = 76988c07335SMatan Azrad container_of(rxq, struct mlx5_rxq_ctrl, rxq); 77088c07335SMatan Azrad union { 77188c07335SMatan Azrad volatile struct mlx5_cqe *cqe; 77288c07335SMatan Azrad volatile struct mlx5_err_cqe *err_cqe; 77388c07335SMatan Azrad } u = { 77488c07335SMatan Azrad .cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask], 77588c07335SMatan Azrad }; 7762d77cb61SMatan Azrad struct mlx5_mp_arg_queue_state_modify sm; 77788c07335SMatan Azrad int ret; 77888c07335SMatan Azrad 77988c07335SMatan Azrad switch (rxq->err_state) { 78088c07335SMatan Azrad case MLX5_RXQ_ERR_STATE_NO_ERROR: 78188c07335SMatan Azrad rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_RESET; 78288c07335SMatan Azrad /* Fall-through */ 78388c07335SMatan Azrad case MLX5_RXQ_ERR_STATE_NEED_RESET: 7842d77cb61SMatan Azrad sm.is_wq = 1; 7852d77cb61SMatan Azrad sm.queue_id = rxq->idx; 7862d77cb61SMatan Azrad sm.state = IBV_WQS_RESET; 7872d77cb61SMatan Azrad if (mlx5_queue_state_modify(ETH_DEV(rxq_ctrl->priv), &sm)) 78888c07335SMatan Azrad return -1; 78988c07335SMatan Azrad if (rxq_ctrl->dump_file_n < 79088c07335SMatan Azrad rxq_ctrl->priv->config.max_dump_files_num) { 79188c07335SMatan Azrad MKSTR(err_str, "Unexpected CQE error syndrome " 79288c07335SMatan Azrad "0x%02x CQN = %u RQN = %u wqe_counter = %u" 79388c07335SMatan Azrad " rq_ci = %u cq_ci = %u", u.err_cqe->syndrome, 7942d77cb61SMatan Azrad rxq->cqn, rxq_ctrl->wqn, 79588c07335SMatan Azrad rte_be_to_cpu_16(u.err_cqe->wqe_counter), 79688c07335SMatan Azrad rxq->rq_ci << rxq->sges_n, rxq->cq_ci); 79788c07335SMatan Azrad MKSTR(name, "dpdk_mlx5_port_%u_rxq_%u_%u", 79888c07335SMatan Azrad rxq->port_id, rxq->idx, (uint32_t)rte_rdtsc()); 79988c07335SMatan Azrad mlx5_dump_debug_information(name, NULL, err_str, 0); 80088c07335SMatan Azrad mlx5_dump_debug_information(name, "MLX5 Error CQ:", 80188c07335SMatan Azrad (const void *)((uintptr_t) 80288c07335SMatan Azrad rxq->cqes), 80388c07335SMatan Azrad sizeof(*u.cqe) * cqe_n); 80488c07335SMatan Azrad mlx5_dump_debug_information(name, "MLX5 Error RQ:", 80588c07335SMatan Azrad (const void *)((uintptr_t) 80688c07335SMatan Azrad rxq->wqes), 80788c07335SMatan Azrad 16 * wqe_n); 80888c07335SMatan Azrad rxq_ctrl->dump_file_n++; 80988c07335SMatan Azrad } 81088c07335SMatan Azrad rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_READY; 81188c07335SMatan Azrad /* Fall-through */ 81288c07335SMatan Azrad case MLX5_RXQ_ERR_STATE_NEED_READY: 81388c07335SMatan Azrad ret = check_cqe(u.cqe, cqe_n, rxq->cq_ci); 81488c07335SMatan Azrad if (ret == MLX5_CQE_STATUS_HW_OWN) { 81588c07335SMatan Azrad rte_cio_wmb(); 81688c07335SMatan Azrad *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci); 81788c07335SMatan Azrad rte_cio_wmb(); 81888c07335SMatan Azrad /* 81988c07335SMatan Azrad * The RQ consumer index must be zeroed while moving 82088c07335SMatan Azrad * from RESET state to RDY state. 82188c07335SMatan Azrad */ 82288c07335SMatan Azrad *rxq->rq_db = rte_cpu_to_be_32(0); 82388c07335SMatan Azrad rte_cio_wmb(); 8242d77cb61SMatan Azrad sm.is_wq = 1; 8252d77cb61SMatan Azrad sm.queue_id = rxq->idx; 8262d77cb61SMatan Azrad sm.state = IBV_WQS_RDY; 8272d77cb61SMatan Azrad if (mlx5_queue_state_modify(ETH_DEV(rxq_ctrl->priv), 8282d77cb61SMatan Azrad &sm)) 82988c07335SMatan Azrad return -1; 83088c07335SMatan Azrad if (mbuf_prepare) { 83188c07335SMatan Azrad const uint16_t q_mask = wqe_n - 1; 83288c07335SMatan Azrad uint16_t elt_idx; 83388c07335SMatan Azrad struct rte_mbuf **elt; 83488c07335SMatan Azrad int i; 83588c07335SMatan Azrad unsigned int n = wqe_n - (rxq->rq_ci - 83688c07335SMatan Azrad rxq->rq_pi); 83788c07335SMatan Azrad 83888c07335SMatan Azrad for (i = 0; i < (int)n; ++i) { 83988c07335SMatan Azrad elt_idx = (rxq->rq_ci + i) & q_mask; 84088c07335SMatan Azrad elt = &(*rxq->elts)[elt_idx]; 84188c07335SMatan Azrad *elt = rte_mbuf_raw_alloc(rxq->mp); 84288c07335SMatan Azrad if (!*elt) { 84388c07335SMatan Azrad for (i--; i >= 0; --i) { 84488c07335SMatan Azrad elt_idx = (rxq->rq_ci + 84588c07335SMatan Azrad i) & q_mask; 84688c07335SMatan Azrad elt = &(*rxq->elts) 84788c07335SMatan Azrad [elt_idx]; 84888c07335SMatan Azrad rte_pktmbuf_free_seg 84988c07335SMatan Azrad (*elt); 85088c07335SMatan Azrad } 85188c07335SMatan Azrad return -1; 85288c07335SMatan Azrad } 85388c07335SMatan Azrad } 85488c07335SMatan Azrad } 85588c07335SMatan Azrad mlx5_rxq_initialize(rxq); 85688c07335SMatan Azrad rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR; 85788c07335SMatan Azrad } 85888c07335SMatan Azrad return ret; 85988c07335SMatan Azrad default: 86088c07335SMatan Azrad return -1; 86188c07335SMatan Azrad } 86288c07335SMatan Azrad } 86388c07335SMatan Azrad 86488c07335SMatan Azrad /** 86599c12dccSNélio Laranjeiro * Get size of the next packet for a given CQE. For compressed CQEs, the 86699c12dccSNélio Laranjeiro * consumer index is updated only once all packets of the current one have 86799c12dccSNélio Laranjeiro * been processed. 86899c12dccSNélio Laranjeiro * 86999c12dccSNélio Laranjeiro * @param rxq 87099c12dccSNélio Laranjeiro * Pointer to RX queue. 87199c12dccSNélio Laranjeiro * @param cqe 87299c12dccSNélio Laranjeiro * CQE to process. 8732e633f1fSYongseok Koh * @param[out] mcqe 8742e633f1fSYongseok Koh * Store pointer to mini-CQE if compressed. Otherwise, the pointer is not 8752e633f1fSYongseok Koh * written. 87699c12dccSNélio Laranjeiro * 87799c12dccSNélio Laranjeiro * @return 87888c07335SMatan Azrad * 0 in case of empty CQE, otherwise the packet size in bytes. 87999c12dccSNélio Laranjeiro */ 88099c12dccSNélio Laranjeiro static inline int 88178142aacSNélio Laranjeiro mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe, 8822e633f1fSYongseok Koh uint16_t cqe_cnt, volatile struct mlx5_mini_cqe8 **mcqe) 88399c12dccSNélio Laranjeiro { 88499c12dccSNélio Laranjeiro struct rxq_zip *zip = &rxq->zip; 88599c12dccSNélio Laranjeiro uint16_t cqe_n = cqe_cnt + 1; 88688c07335SMatan Azrad int len; 887d2e842d0SYongseok Koh uint16_t idx, end; 88899c12dccSNélio Laranjeiro 88988c07335SMatan Azrad do { 89088c07335SMatan Azrad len = 0; 89199c12dccSNélio Laranjeiro /* Process compressed data in the CQE and mini arrays. */ 89299c12dccSNélio Laranjeiro if (zip->ai) { 89399c12dccSNélio Laranjeiro volatile struct mlx5_mini_cqe8 (*mc)[8] = 89499c12dccSNélio Laranjeiro (volatile struct mlx5_mini_cqe8 (*)[8]) 89588c07335SMatan Azrad (uintptr_t)(&(*rxq->cqes)[zip->ca & 89688c07335SMatan Azrad cqe_cnt].pkt_info); 89799c12dccSNélio Laranjeiro 8986b30a6a8SShachar Beiser len = rte_be_to_cpu_32((*mc)[zip->ai & 7].byte_cnt); 8992e633f1fSYongseok Koh *mcqe = &(*mc)[zip->ai & 7]; 90099c12dccSNélio Laranjeiro if ((++zip->ai & 7) == 0) { 901d2e842d0SYongseok Koh /* Invalidate consumed CQEs */ 902d2e842d0SYongseok Koh idx = zip->ca; 903d2e842d0SYongseok Koh end = zip->na; 904d2e842d0SYongseok Koh while (idx != end) { 905d2e842d0SYongseok Koh (*rxq->cqes)[idx & cqe_cnt].op_own = 906d2e842d0SYongseok Koh MLX5_CQE_INVALIDATE; 907d2e842d0SYongseok Koh ++idx; 908d2e842d0SYongseok Koh } 90999c12dccSNélio Laranjeiro /* 91088c07335SMatan Azrad * Increment consumer index to skip the number 91188c07335SMatan Azrad * of CQEs consumed. Hardware leaves holes in 91288c07335SMatan Azrad * the CQ ring for software use. 91399c12dccSNélio Laranjeiro */ 91499c12dccSNélio Laranjeiro zip->ca = zip->na; 91599c12dccSNélio Laranjeiro zip->na += 8; 91699c12dccSNélio Laranjeiro } 91799c12dccSNélio Laranjeiro if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) { 918d2e842d0SYongseok Koh /* Invalidate the rest */ 919d2e842d0SYongseok Koh idx = zip->ca; 920d2e842d0SYongseok Koh end = zip->cq_ci; 92199c12dccSNélio Laranjeiro 92299c12dccSNélio Laranjeiro while (idx != end) { 92397267b8eSNelio Laranjeiro (*rxq->cqes)[idx & cqe_cnt].op_own = 92499c12dccSNélio Laranjeiro MLX5_CQE_INVALIDATE; 92599c12dccSNélio Laranjeiro ++idx; 92699c12dccSNélio Laranjeiro } 92799c12dccSNélio Laranjeiro rxq->cq_ci = zip->cq_ci; 92899c12dccSNélio Laranjeiro zip->ai = 0; 92999c12dccSNélio Laranjeiro } 93088c07335SMatan Azrad /* 93188c07335SMatan Azrad * No compressed data, get next CQE and verify if it is 93288c07335SMatan Azrad * compressed. 93388c07335SMatan Azrad */ 93499c12dccSNélio Laranjeiro } else { 93599c12dccSNélio Laranjeiro int ret; 93699c12dccSNélio Laranjeiro int8_t op_own; 93799c12dccSNélio Laranjeiro 93897267b8eSNelio Laranjeiro ret = check_cqe(cqe, cqe_n, rxq->cq_ci); 93988c07335SMatan Azrad if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) { 94088c07335SMatan Azrad if (unlikely(ret == MLX5_CQE_STATUS_ERR || 94188c07335SMatan Azrad rxq->err_state)) { 94288c07335SMatan Azrad ret = mlx5_rx_err_handle(rxq, 0); 94388c07335SMatan Azrad if (ret == MLX5_CQE_STATUS_HW_OWN || 94488c07335SMatan Azrad ret == -1) 94599c12dccSNélio Laranjeiro return 0; 94688c07335SMatan Azrad } else { 94788c07335SMatan Azrad return 0; 94888c07335SMatan Azrad } 94988c07335SMatan Azrad } 95099c12dccSNélio Laranjeiro ++rxq->cq_ci; 95199c12dccSNélio Laranjeiro op_own = cqe->op_own; 95299c12dccSNélio Laranjeiro if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) { 95399c12dccSNélio Laranjeiro volatile struct mlx5_mini_cqe8 (*mc)[8] = 95499c12dccSNélio Laranjeiro (volatile struct mlx5_mini_cqe8 (*)[8]) 95588c07335SMatan Azrad (uintptr_t)(&(*rxq->cqes) 95688c07335SMatan Azrad [rxq->cq_ci & 9574aff4bcbSYongseok Koh cqe_cnt].pkt_info); 95899c12dccSNélio Laranjeiro 95999c12dccSNélio Laranjeiro /* Fix endianness. */ 9606b30a6a8SShachar Beiser zip->cqe_cnt = rte_be_to_cpu_32(cqe->byte_cnt); 96199c12dccSNélio Laranjeiro /* 96288c07335SMatan Azrad * Current mini array position is the one 96388c07335SMatan Azrad * returned by check_cqe64(). 96499c12dccSNélio Laranjeiro * 96588c07335SMatan Azrad * If completion comprises several mini arrays, 96688c07335SMatan Azrad * as a special case the second one is located 96788c07335SMatan Azrad * 7 CQEs after the initial CQE instead of 8 96888c07335SMatan Azrad * for subsequent ones. 96999c12dccSNélio Laranjeiro */ 970d2e842d0SYongseok Koh zip->ca = rxq->cq_ci; 97199c12dccSNélio Laranjeiro zip->na = zip->ca + 7; 97299c12dccSNélio Laranjeiro /* Compute the next non compressed CQE. */ 97399c12dccSNélio Laranjeiro --rxq->cq_ci; 97499c12dccSNélio Laranjeiro zip->cq_ci = rxq->cq_ci + zip->cqe_cnt; 97599c12dccSNélio Laranjeiro /* Get packet size to return. */ 9766b30a6a8SShachar Beiser len = rte_be_to_cpu_32((*mc)[0].byte_cnt); 9772e633f1fSYongseok Koh *mcqe = &(*mc)[0]; 97899c12dccSNélio Laranjeiro zip->ai = 1; 97988c07335SMatan Azrad /* Prefetch all to be invalidated */ 980d2e842d0SYongseok Koh idx = zip->ca; 981d2e842d0SYongseok Koh end = zip->cq_ci; 982d2e842d0SYongseok Koh while (idx != end) { 98388c07335SMatan Azrad rte_prefetch0(&(*rxq->cqes)[(idx) & 98488c07335SMatan Azrad cqe_cnt]); 985d2e842d0SYongseok Koh ++idx; 986d2e842d0SYongseok Koh } 98799c12dccSNélio Laranjeiro } else { 9886b30a6a8SShachar Beiser len = rte_be_to_cpu_32(cqe->byte_cnt); 98999c12dccSNélio Laranjeiro } 99099c12dccSNélio Laranjeiro } 99188c07335SMatan Azrad if (unlikely(rxq->err_state)) { 99288c07335SMatan Azrad cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt]; 99388c07335SMatan Azrad ++rxq->stats.idropped; 99488c07335SMatan Azrad } else { 99599c12dccSNélio Laranjeiro return len; 99699c12dccSNélio Laranjeiro } 99788c07335SMatan Azrad } while (1); 99888c07335SMatan Azrad } 99999c12dccSNélio Laranjeiro 100099c12dccSNélio Laranjeiro /** 100167fa62bcSAdrien Mazarguil * Translate RX completion flags to offload flags. 100267fa62bcSAdrien Mazarguil * 10036218063bSNélio Laranjeiro * @param[in] cqe 10046218063bSNélio Laranjeiro * Pointer to CQE. 100567fa62bcSAdrien Mazarguil * 100667fa62bcSAdrien Mazarguil * @return 100767fa62bcSAdrien Mazarguil * Offload flags (ol_flags) for struct rte_mbuf. 100867fa62bcSAdrien Mazarguil */ 100967fa62bcSAdrien Mazarguil static inline uint32_t 10106ba07449SXueming Li rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe) 101167fa62bcSAdrien Mazarguil { 101267fa62bcSAdrien Mazarguil uint32_t ol_flags = 0; 10136b30a6a8SShachar Beiser uint16_t flags = rte_be_to_cpu_16(cqe->hdr_type_etc); 101467fa62bcSAdrien Mazarguil 10150603df73SNélio Laranjeiro ol_flags = 10160603df73SNélio Laranjeiro TRANSPOSE(flags, 10170603df73SNélio Laranjeiro MLX5_CQE_RX_L3_HDR_VALID, 10180603df73SNélio Laranjeiro PKT_RX_IP_CKSUM_GOOD) | 10190603df73SNélio Laranjeiro TRANSPOSE(flags, 10200603df73SNélio Laranjeiro MLX5_CQE_RX_L4_HDR_VALID, 102183e9d9a3SNelio Laranjeiro PKT_RX_L4_CKSUM_GOOD); 102267fa62bcSAdrien Mazarguil return ol_flags; 102367fa62bcSAdrien Mazarguil } 102467fa62bcSAdrien Mazarguil 102567fa62bcSAdrien Mazarguil /** 10263e1f82a1SYongseok Koh * Fill in mbuf fields from RX completion flags. 10273e1f82a1SYongseok Koh * Note that pkt->ol_flags should be initialized outside of this function. 10283e1f82a1SYongseok Koh * 10293e1f82a1SYongseok Koh * @param rxq 10303e1f82a1SYongseok Koh * Pointer to RX queue. 10313e1f82a1SYongseok Koh * @param pkt 10323e1f82a1SYongseok Koh * mbuf to fill. 10333e1f82a1SYongseok Koh * @param cqe 10343e1f82a1SYongseok Koh * CQE to process. 10353e1f82a1SYongseok Koh * @param rss_hash_res 10363e1f82a1SYongseok Koh * Packet RSS Hash result. 10373e1f82a1SYongseok Koh */ 10383e1f82a1SYongseok Koh static inline void 10393e1f82a1SYongseok Koh rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt, 10403e1f82a1SYongseok Koh volatile struct mlx5_cqe *cqe, uint32_t rss_hash_res) 10413e1f82a1SYongseok Koh { 10423e1f82a1SYongseok Koh /* Update packet information. */ 10433e1f82a1SYongseok Koh pkt->packet_type = rxq_cq_to_pkt_type(rxq, cqe); 10443e1f82a1SYongseok Koh if (rss_hash_res && rxq->rss_hash) { 10453e1f82a1SYongseok Koh pkt->hash.rss = rss_hash_res; 10463e1f82a1SYongseok Koh pkt->ol_flags |= PKT_RX_RSS_HASH; 10473e1f82a1SYongseok Koh } 10483e1f82a1SYongseok Koh if (rxq->mark && MLX5_FLOW_MARK_IS_VALID(cqe->sop_drop_qpn)) { 10493e1f82a1SYongseok Koh pkt->ol_flags |= PKT_RX_FDIR; 10503e1f82a1SYongseok Koh if (cqe->sop_drop_qpn != 10513e1f82a1SYongseok Koh rte_cpu_to_be_32(MLX5_FLOW_MARK_DEFAULT)) { 10523e1f82a1SYongseok Koh uint32_t mark = cqe->sop_drop_qpn; 10533e1f82a1SYongseok Koh 10543e1f82a1SYongseok Koh pkt->ol_flags |= PKT_RX_FDIR_ID; 10553e1f82a1SYongseok Koh pkt->hash.fdir.hi = mlx5_flow_mark_get(mark); 10563e1f82a1SYongseok Koh } 10573e1f82a1SYongseok Koh } 10583e1f82a1SYongseok Koh if (rxq->csum) 10593e1f82a1SYongseok Koh pkt->ol_flags |= rxq_cq_to_ol_flags(cqe); 10603e1f82a1SYongseok Koh if (rxq->vlan_strip && 10613e1f82a1SYongseok Koh (cqe->hdr_type_etc & rte_cpu_to_be_16(MLX5_CQE_VLAN_STRIPPED))) { 10623e1f82a1SYongseok Koh pkt->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; 10633e1f82a1SYongseok Koh pkt->vlan_tci = rte_be_to_cpu_16(cqe->vlan_info); 10643e1f82a1SYongseok Koh } 10653e1f82a1SYongseok Koh if (rxq->hw_timestamp) { 10663e1f82a1SYongseok Koh pkt->timestamp = rte_be_to_cpu_64(cqe->timestamp); 10673e1f82a1SYongseok Koh pkt->ol_flags |= PKT_RX_TIMESTAMP; 10683e1f82a1SYongseok Koh } 10693e1f82a1SYongseok Koh } 10703e1f82a1SYongseok Koh 10713e1f82a1SYongseok Koh /** 10722e22920bSAdrien Mazarguil * DPDK callback for RX. 10732e22920bSAdrien Mazarguil * 10742e22920bSAdrien Mazarguil * @param dpdk_rxq 10752e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 10762e22920bSAdrien Mazarguil * @param[out] pkts 10772e22920bSAdrien Mazarguil * Array to store received packets. 10782e22920bSAdrien Mazarguil * @param pkts_n 10792e22920bSAdrien Mazarguil * Maximum number of packets in array. 10802e22920bSAdrien Mazarguil * 10812e22920bSAdrien Mazarguil * @return 10822e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 10832e22920bSAdrien Mazarguil */ 10842e22920bSAdrien Mazarguil uint16_t 10852e22920bSAdrien Mazarguil mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 10862e22920bSAdrien Mazarguil { 108778142aacSNélio Laranjeiro struct mlx5_rxq_data *rxq = dpdk_rxq; 1088b4b12e55SNélio Laranjeiro const unsigned int wqe_cnt = (1 << rxq->elts_n) - 1; 1089e2f116eeSNélio Laranjeiro const unsigned int cqe_cnt = (1 << rxq->cqe_n) - 1; 10909964b965SNélio Laranjeiro const unsigned int sges_n = rxq->sges_n; 10919964b965SNélio Laranjeiro struct rte_mbuf *pkt = NULL; 10929964b965SNélio Laranjeiro struct rte_mbuf *seg = NULL; 109397267b8eSNelio Laranjeiro volatile struct mlx5_cqe *cqe = 109497267b8eSNelio Laranjeiro &(*rxq->cqes)[rxq->cq_ci & cqe_cnt]; 10959964b965SNélio Laranjeiro unsigned int i = 0; 10969964b965SNélio Laranjeiro unsigned int rq_ci = rxq->rq_ci << sges_n; 10974e66a6feSNelio Laranjeiro int len = 0; /* keep its value across iterations. */ 10982e22920bSAdrien Mazarguil 10999964b965SNélio Laranjeiro while (pkts_n) { 11009964b965SNélio Laranjeiro unsigned int idx = rq_ci & wqe_cnt; 11017d6bf6b8SYongseok Koh volatile struct mlx5_wqe_data_seg *wqe = 11027d6bf6b8SYongseok Koh &((volatile struct mlx5_wqe_data_seg *)rxq->wqes)[idx]; 11039964b965SNélio Laranjeiro struct rte_mbuf *rep = (*rxq->elts)[idx]; 11042e633f1fSYongseok Koh volatile struct mlx5_mini_cqe8 *mcqe = NULL; 11052e633f1fSYongseok Koh uint32_t rss_hash_res; 11069964b965SNélio Laranjeiro 11079964b965SNélio Laranjeiro if (pkt) 11089964b965SNélio Laranjeiro NEXT(seg) = rep; 11099964b965SNélio Laranjeiro seg = rep; 11109964b965SNélio Laranjeiro rte_prefetch0(seg); 11116218063bSNélio Laranjeiro rte_prefetch0(cqe); 11129964b965SNélio Laranjeiro rte_prefetch0(wqe); 1113fbfd9955SOlivier Matz rep = rte_mbuf_raw_alloc(rxq->mp); 11142e22920bSAdrien Mazarguil if (unlikely(rep == NULL)) { 111515a756b6SSagi Grimberg ++rxq->stats.rx_nombuf; 111615a756b6SSagi Grimberg if (!pkt) { 111715a756b6SSagi Grimberg /* 111815a756b6SSagi Grimberg * no buffers before we even started, 111915a756b6SSagi Grimberg * bail out silently. 112015a756b6SSagi Grimberg */ 112115a756b6SSagi Grimberg break; 112215a756b6SSagi Grimberg } 1123a1bdb71aSNélio Laranjeiro while (pkt != seg) { 1124a1bdb71aSNélio Laranjeiro assert(pkt != (*rxq->elts)[idx]); 1125fe5fe382SNélio Laranjeiro rep = NEXT(pkt); 11268f094a9aSOlivier Matz NEXT(pkt) = NULL; 11278f094a9aSOlivier Matz NB_SEGS(pkt) = 1; 11281f88c0a2SOlivier Matz rte_mbuf_raw_free(pkt); 1129fe5fe382SNélio Laranjeiro pkt = rep; 11309964b965SNélio Laranjeiro } 11316218063bSNélio Laranjeiro break; 11322e22920bSAdrien Mazarguil } 11339964b965SNélio Laranjeiro if (!pkt) { 113497267b8eSNelio Laranjeiro cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_cnt]; 11352e633f1fSYongseok Koh len = mlx5_rx_poll_len(rxq, cqe, cqe_cnt, &mcqe); 1136ecf60761SNélio Laranjeiro if (!len) { 11371f88c0a2SOlivier Matz rte_mbuf_raw_free(rep); 11386218063bSNélio Laranjeiro break; 11396218063bSNélio Laranjeiro } 11409964b965SNélio Laranjeiro pkt = seg; 11419964b965SNélio Laranjeiro assert(len >= (rxq->crc_present << 2)); 11420ac64846SMaxime Leroy pkt->ol_flags = 0; 11432e633f1fSYongseok Koh /* If compressed, take hash result from mini-CQE. */ 11442e633f1fSYongseok Koh rss_hash_res = rte_be_to_cpu_32(mcqe == NULL ? 11452e633f1fSYongseok Koh cqe->rx_hash_res : 11462e633f1fSYongseok Koh mcqe->rx_hash_result); 11473e1f82a1SYongseok Koh rxq_cq_to_mbuf(rxq, pkt, cqe, rss_hash_res); 11486218063bSNélio Laranjeiro if (rxq->crc_present) 114935b2d13fSOlivier Matz len -= RTE_ETHER_CRC_LEN; 11506218063bSNélio Laranjeiro PKT_LEN(pkt) = len; 11519964b965SNélio Laranjeiro } 11529964b965SNélio Laranjeiro DATA_LEN(rep) = DATA_LEN(seg); 11539964b965SNélio Laranjeiro PKT_LEN(rep) = PKT_LEN(seg); 11549964b965SNélio Laranjeiro SET_DATA_OFF(rep, DATA_OFF(seg)); 11559964b965SNélio Laranjeiro PORT(rep) = PORT(seg); 11569964b965SNélio Laranjeiro (*rxq->elts)[idx] = rep; 11579964b965SNélio Laranjeiro /* 11589964b965SNélio Laranjeiro * Fill NIC descriptor with the new buffer. The lkey and size 11599964b965SNélio Laranjeiro * of the buffers are already known, only the buffer address 11609964b965SNélio Laranjeiro * changes. 11619964b965SNélio Laranjeiro */ 11626b30a6a8SShachar Beiser wqe->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t)); 1163974f1e7eSYongseok Koh /* If there's only one MR, no need to replace LKey in WQE. */ 1164974f1e7eSYongseok Koh if (unlikely(mlx5_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1)) 1165974f1e7eSYongseok Koh wqe->lkey = mlx5_rx_mb2mr(rxq, rep); 11669964b965SNélio Laranjeiro if (len > DATA_LEN(seg)) { 11679964b965SNélio Laranjeiro len -= DATA_LEN(seg); 11689964b965SNélio Laranjeiro ++NB_SEGS(pkt); 11699964b965SNélio Laranjeiro ++rq_ci; 11709964b965SNélio Laranjeiro continue; 11719964b965SNélio Laranjeiro } 11729964b965SNélio Laranjeiro DATA_LEN(seg) = len; 117387011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 117487011737SAdrien Mazarguil /* Increment bytes counter. */ 11759964b965SNélio Laranjeiro rxq->stats.ibytes += PKT_LEN(pkt); 117687011737SAdrien Mazarguil #endif 11776218063bSNélio Laranjeiro /* Return packet. */ 11786218063bSNélio Laranjeiro *(pkts++) = pkt; 11799964b965SNélio Laranjeiro pkt = NULL; 11809964b965SNélio Laranjeiro --pkts_n; 11819964b965SNélio Laranjeiro ++i; 11829964b965SNélio Laranjeiro /* Align consumer index to the next stride. */ 11839964b965SNélio Laranjeiro rq_ci >>= sges_n; 11846218063bSNélio Laranjeiro ++rq_ci; 11859964b965SNélio Laranjeiro rq_ci <<= sges_n; 11862e22920bSAdrien Mazarguil } 11879964b965SNélio Laranjeiro if (unlikely((i == 0) && ((rq_ci >> sges_n) == rxq->rq_ci))) 11882e22920bSAdrien Mazarguil return 0; 11896218063bSNélio Laranjeiro /* Update the consumer index. */ 11909964b965SNélio Laranjeiro rxq->rq_ci = rq_ci >> sges_n; 11914fe7f662SYongseok Koh rte_cio_wmb(); 11926b30a6a8SShachar Beiser *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci); 11934fe7f662SYongseok Koh rte_cio_wmb(); 11946b30a6a8SShachar Beiser *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci); 119587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 119687011737SAdrien Mazarguil /* Increment packets counter. */ 11979964b965SNélio Laranjeiro rxq->stats.ipackets += i; 119887011737SAdrien Mazarguil #endif 11999964b965SNélio Laranjeiro return i; 12002e22920bSAdrien Mazarguil } 12012e22920bSAdrien Mazarguil 12027d6bf6b8SYongseok Koh void 12037d6bf6b8SYongseok Koh mlx5_mprq_buf_free_cb(void *addr __rte_unused, void *opaque) 12047d6bf6b8SYongseok Koh { 12057d6bf6b8SYongseok Koh struct mlx5_mprq_buf *buf = opaque; 12067d6bf6b8SYongseok Koh 12077d6bf6b8SYongseok Koh if (rte_atomic16_read(&buf->refcnt) == 1) { 12087d6bf6b8SYongseok Koh rte_mempool_put(buf->mp, buf); 12097d6bf6b8SYongseok Koh } else if (rte_atomic16_add_return(&buf->refcnt, -1) == 0) { 12107d6bf6b8SYongseok Koh rte_atomic16_set(&buf->refcnt, 1); 12117d6bf6b8SYongseok Koh rte_mempool_put(buf->mp, buf); 12127d6bf6b8SYongseok Koh } 12137d6bf6b8SYongseok Koh } 12147d6bf6b8SYongseok Koh 12157d6bf6b8SYongseok Koh void 12167d6bf6b8SYongseok Koh mlx5_mprq_buf_free(struct mlx5_mprq_buf *buf) 12177d6bf6b8SYongseok Koh { 12187d6bf6b8SYongseok Koh mlx5_mprq_buf_free_cb(NULL, buf); 12197d6bf6b8SYongseok Koh } 12207d6bf6b8SYongseok Koh 12217d6bf6b8SYongseok Koh static inline void 12227d6bf6b8SYongseok Koh mprq_buf_replace(struct mlx5_rxq_data *rxq, uint16_t rq_idx) 12237d6bf6b8SYongseok Koh { 12247d6bf6b8SYongseok Koh struct mlx5_mprq_buf *rep = rxq->mprq_repl; 12257d6bf6b8SYongseok Koh volatile struct mlx5_wqe_data_seg *wqe = 12267d6bf6b8SYongseok Koh &((volatile struct mlx5_wqe_mprq *)rxq->wqes)[rq_idx].dseg; 12277d6bf6b8SYongseok Koh void *addr; 12287d6bf6b8SYongseok Koh 12297d6bf6b8SYongseok Koh assert(rep != NULL); 12307d6bf6b8SYongseok Koh /* Replace MPRQ buf. */ 12317d6bf6b8SYongseok Koh (*rxq->mprq_bufs)[rq_idx] = rep; 12327d6bf6b8SYongseok Koh /* Replace WQE. */ 12337d6bf6b8SYongseok Koh addr = mlx5_mprq_buf_addr(rep); 12347d6bf6b8SYongseok Koh wqe->addr = rte_cpu_to_be_64((uintptr_t)addr); 12357d6bf6b8SYongseok Koh /* If there's only one MR, no need to replace LKey in WQE. */ 12367d6bf6b8SYongseok Koh if (unlikely(mlx5_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1)) 12377d6bf6b8SYongseok Koh wqe->lkey = mlx5_rx_addr2mr(rxq, (uintptr_t)addr); 12387d6bf6b8SYongseok Koh /* Stash a mbuf for next replacement. */ 12397d6bf6b8SYongseok Koh if (likely(!rte_mempool_get(rxq->mprq_mp, (void **)&rep))) 12407d6bf6b8SYongseok Koh rxq->mprq_repl = rep; 12417d6bf6b8SYongseok Koh else 12427d6bf6b8SYongseok Koh rxq->mprq_repl = NULL; 12437d6bf6b8SYongseok Koh } 12447d6bf6b8SYongseok Koh 12457d6bf6b8SYongseok Koh /** 12467d6bf6b8SYongseok Koh * DPDK callback for RX with Multi-Packet RQ support. 12477d6bf6b8SYongseok Koh * 12487d6bf6b8SYongseok Koh * @param dpdk_rxq 12497d6bf6b8SYongseok Koh * Generic pointer to RX queue structure. 12507d6bf6b8SYongseok Koh * @param[out] pkts 12517d6bf6b8SYongseok Koh * Array to store received packets. 12527d6bf6b8SYongseok Koh * @param pkts_n 12537d6bf6b8SYongseok Koh * Maximum number of packets in array. 12547d6bf6b8SYongseok Koh * 12557d6bf6b8SYongseok Koh * @return 12567d6bf6b8SYongseok Koh * Number of packets successfully received (<= pkts_n). 12577d6bf6b8SYongseok Koh */ 12587d6bf6b8SYongseok Koh uint16_t 12597d6bf6b8SYongseok Koh mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 12607d6bf6b8SYongseok Koh { 12617d6bf6b8SYongseok Koh struct mlx5_rxq_data *rxq = dpdk_rxq; 12627d6bf6b8SYongseok Koh const unsigned int strd_n = 1 << rxq->strd_num_n; 12637d6bf6b8SYongseok Koh const unsigned int strd_sz = 1 << rxq->strd_sz_n; 12647d6bf6b8SYongseok Koh const unsigned int strd_shift = 12657d6bf6b8SYongseok Koh MLX5_MPRQ_STRIDE_SHIFT_BYTE * rxq->strd_shift_en; 12667d6bf6b8SYongseok Koh const unsigned int cq_mask = (1 << rxq->cqe_n) - 1; 12677d6bf6b8SYongseok Koh const unsigned int wq_mask = (1 << rxq->elts_n) - 1; 12687d6bf6b8SYongseok Koh volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask]; 12697d6bf6b8SYongseok Koh unsigned int i = 0; 12703afdf157SXueming Li uint32_t rq_ci = rxq->rq_ci; 12711787eb7bSYongseok Koh uint16_t consumed_strd = rxq->consumed_strd; 12727d6bf6b8SYongseok Koh struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[rq_ci & wq_mask]; 12737d6bf6b8SYongseok Koh 12747d6bf6b8SYongseok Koh while (i < pkts_n) { 12757d6bf6b8SYongseok Koh struct rte_mbuf *pkt; 12767d6bf6b8SYongseok Koh void *addr; 12777d6bf6b8SYongseok Koh int ret; 12787d6bf6b8SYongseok Koh unsigned int len; 12791787eb7bSYongseok Koh uint16_t strd_cnt; 12801787eb7bSYongseok Koh uint16_t strd_idx; 12817d6bf6b8SYongseok Koh uint32_t offset; 12827d6bf6b8SYongseok Koh uint32_t byte_cnt; 12832e633f1fSYongseok Koh volatile struct mlx5_mini_cqe8 *mcqe = NULL; 12841787eb7bSYongseok Koh uint32_t rss_hash_res = 0; 12857d6bf6b8SYongseok Koh 12861787eb7bSYongseok Koh if (consumed_strd == strd_n) { 12877d6bf6b8SYongseok Koh /* Replace WQE only if the buffer is still in use. */ 12887d6bf6b8SYongseok Koh if (rte_atomic16_read(&buf->refcnt) > 1) { 12897d6bf6b8SYongseok Koh mprq_buf_replace(rxq, rq_ci & wq_mask); 12907d6bf6b8SYongseok Koh /* Release the old buffer. */ 12917d6bf6b8SYongseok Koh mlx5_mprq_buf_free(buf); 12927d6bf6b8SYongseok Koh } else if (unlikely(rxq->mprq_repl == NULL)) { 12937d6bf6b8SYongseok Koh struct mlx5_mprq_buf *rep; 12947d6bf6b8SYongseok Koh 12957d6bf6b8SYongseok Koh /* 12967d6bf6b8SYongseok Koh * Currently, the MPRQ mempool is out of buffer 12977d6bf6b8SYongseok Koh * and doing memcpy regardless of the size of Rx 12987d6bf6b8SYongseok Koh * packet. Retry allocation to get back to 12997d6bf6b8SYongseok Koh * normal. 13007d6bf6b8SYongseok Koh */ 13017d6bf6b8SYongseok Koh if (!rte_mempool_get(rxq->mprq_mp, 13027d6bf6b8SYongseok Koh (void **)&rep)) 13037d6bf6b8SYongseok Koh rxq->mprq_repl = rep; 13047d6bf6b8SYongseok Koh } 13057d6bf6b8SYongseok Koh /* Advance to the next WQE. */ 13061787eb7bSYongseok Koh consumed_strd = 0; 13077d6bf6b8SYongseok Koh ++rq_ci; 13087d6bf6b8SYongseok Koh buf = (*rxq->mprq_bufs)[rq_ci & wq_mask]; 13097d6bf6b8SYongseok Koh } 13107d6bf6b8SYongseok Koh cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask]; 13112e633f1fSYongseok Koh ret = mlx5_rx_poll_len(rxq, cqe, cq_mask, &mcqe); 13127d6bf6b8SYongseok Koh if (!ret) 13137d6bf6b8SYongseok Koh break; 13147d6bf6b8SYongseok Koh byte_cnt = ret; 13151787eb7bSYongseok Koh strd_cnt = (byte_cnt & MLX5_MPRQ_STRIDE_NUM_MASK) >> 13167d6bf6b8SYongseok Koh MLX5_MPRQ_STRIDE_NUM_SHIFT; 13171787eb7bSYongseok Koh assert(strd_cnt); 13181787eb7bSYongseok Koh consumed_strd += strd_cnt; 13197d6bf6b8SYongseok Koh if (byte_cnt & MLX5_MPRQ_FILLER_MASK) 13207d6bf6b8SYongseok Koh continue; 13211787eb7bSYongseok Koh if (mcqe == NULL) { 13221787eb7bSYongseok Koh rss_hash_res = rte_be_to_cpu_32(cqe->rx_hash_res); 13231787eb7bSYongseok Koh strd_idx = rte_be_to_cpu_16(cqe->wqe_counter); 13241787eb7bSYongseok Koh } else { 13251787eb7bSYongseok Koh /* mini-CQE for MPRQ doesn't have hash result. */ 13261787eb7bSYongseok Koh strd_idx = rte_be_to_cpu_16(mcqe->stride_idx); 13271787eb7bSYongseok Koh } 13281787eb7bSYongseok Koh assert(strd_idx < strd_n); 13291787eb7bSYongseok Koh assert(!((rte_be_to_cpu_16(cqe->wqe_id) ^ rq_ci) & wq_mask)); 13307d6bf6b8SYongseok Koh /* 13317d6bf6b8SYongseok Koh * Currently configured to receive a packet per a stride. But if 13327d6bf6b8SYongseok Koh * MTU is adjusted through kernel interface, device could 13337d6bf6b8SYongseok Koh * consume multiple strides without raising an error. In this 13347d6bf6b8SYongseok Koh * case, the packet should be dropped because it is bigger than 13357d6bf6b8SYongseok Koh * the max_rx_pkt_len. 13367d6bf6b8SYongseok Koh */ 13371787eb7bSYongseok Koh if (unlikely(strd_cnt > 1)) { 13387d6bf6b8SYongseok Koh ++rxq->stats.idropped; 13397d6bf6b8SYongseok Koh continue; 13407d6bf6b8SYongseok Koh } 13417d6bf6b8SYongseok Koh pkt = rte_pktmbuf_alloc(rxq->mp); 13427d6bf6b8SYongseok Koh if (unlikely(pkt == NULL)) { 13437d6bf6b8SYongseok Koh ++rxq->stats.rx_nombuf; 13447d6bf6b8SYongseok Koh break; 13457d6bf6b8SYongseok Koh } 13467d6bf6b8SYongseok Koh len = (byte_cnt & MLX5_MPRQ_LEN_MASK) >> MLX5_MPRQ_LEN_SHIFT; 13477d6bf6b8SYongseok Koh assert((int)len >= (rxq->crc_present << 2)); 13487d6bf6b8SYongseok Koh if (rxq->crc_present) 134935b2d13fSOlivier Matz len -= RTE_ETHER_CRC_LEN; 13501787eb7bSYongseok Koh offset = strd_idx * strd_sz + strd_shift; 13517d6bf6b8SYongseok Koh addr = RTE_PTR_ADD(mlx5_mprq_buf_addr(buf), offset); 13527d6bf6b8SYongseok Koh /* Initialize the offload flag. */ 13537d6bf6b8SYongseok Koh pkt->ol_flags = 0; 13547d6bf6b8SYongseok Koh /* 13557d6bf6b8SYongseok Koh * Memcpy packets to the target mbuf if: 13567d6bf6b8SYongseok Koh * - The size of packet is smaller than mprq_max_memcpy_len. 13577d6bf6b8SYongseok Koh * - Out of buffer in the Mempool for Multi-Packet RQ. 13587d6bf6b8SYongseok Koh */ 13597d6bf6b8SYongseok Koh if (len <= rxq->mprq_max_memcpy_len || rxq->mprq_repl == NULL) { 13607d6bf6b8SYongseok Koh /* 13617d6bf6b8SYongseok Koh * When memcpy'ing packet due to out-of-buffer, the 13627d6bf6b8SYongseok Koh * packet must be smaller than the target mbuf. 13637d6bf6b8SYongseok Koh */ 13647d6bf6b8SYongseok Koh if (unlikely(rte_pktmbuf_tailroom(pkt) < len)) { 13657d6bf6b8SYongseok Koh rte_pktmbuf_free_seg(pkt); 13667d6bf6b8SYongseok Koh ++rxq->stats.idropped; 13677d6bf6b8SYongseok Koh continue; 13687d6bf6b8SYongseok Koh } 13697d6bf6b8SYongseok Koh rte_memcpy(rte_pktmbuf_mtod(pkt, void *), addr, len); 13707d6bf6b8SYongseok Koh } else { 13717d6bf6b8SYongseok Koh rte_iova_t buf_iova; 13727d6bf6b8SYongseok Koh struct rte_mbuf_ext_shared_info *shinfo; 13731787eb7bSYongseok Koh uint16_t buf_len = strd_cnt * strd_sz; 13747d6bf6b8SYongseok Koh 13757d6bf6b8SYongseok Koh /* Increment the refcnt of the whole chunk. */ 13767d6bf6b8SYongseok Koh rte_atomic16_add_return(&buf->refcnt, 1); 13777d6bf6b8SYongseok Koh assert((uint16_t)rte_atomic16_read(&buf->refcnt) <= 13787d6bf6b8SYongseok Koh strd_n + 1); 13797d6bf6b8SYongseok Koh addr = RTE_PTR_SUB(addr, RTE_PKTMBUF_HEADROOM); 13807d6bf6b8SYongseok Koh /* 13817d6bf6b8SYongseok Koh * MLX5 device doesn't use iova but it is necessary in a 13827d6bf6b8SYongseok Koh * case where the Rx packet is transmitted via a 13837d6bf6b8SYongseok Koh * different PMD. 13847d6bf6b8SYongseok Koh */ 13857d6bf6b8SYongseok Koh buf_iova = rte_mempool_virt2iova(buf) + 13867d6bf6b8SYongseok Koh RTE_PTR_DIFF(addr, buf); 13877d6bf6b8SYongseok Koh shinfo = rte_pktmbuf_ext_shinfo_init_helper(addr, 13887d6bf6b8SYongseok Koh &buf_len, mlx5_mprq_buf_free_cb, buf); 13897d6bf6b8SYongseok Koh /* 13907d6bf6b8SYongseok Koh * EXT_ATTACHED_MBUF will be set to pkt->ol_flags when 13917d6bf6b8SYongseok Koh * attaching the stride to mbuf and more offload flags 13927d6bf6b8SYongseok Koh * will be added below by calling rxq_cq_to_mbuf(). 13937d6bf6b8SYongseok Koh * Other fields will be overwritten. 13947d6bf6b8SYongseok Koh */ 13957d6bf6b8SYongseok Koh rte_pktmbuf_attach_extbuf(pkt, addr, buf_iova, buf_len, 13967d6bf6b8SYongseok Koh shinfo); 13977d6bf6b8SYongseok Koh rte_pktmbuf_reset_headroom(pkt); 13987d6bf6b8SYongseok Koh assert(pkt->ol_flags == EXT_ATTACHED_MBUF); 13997d6bf6b8SYongseok Koh /* 14007d6bf6b8SYongseok Koh * Prevent potential overflow due to MTU change through 14017d6bf6b8SYongseok Koh * kernel interface. 14027d6bf6b8SYongseok Koh */ 14037d6bf6b8SYongseok Koh if (unlikely(rte_pktmbuf_tailroom(pkt) < len)) { 14047d6bf6b8SYongseok Koh rte_pktmbuf_free_seg(pkt); 14057d6bf6b8SYongseok Koh ++rxq->stats.idropped; 14067d6bf6b8SYongseok Koh continue; 14077d6bf6b8SYongseok Koh } 14087d6bf6b8SYongseok Koh } 14097d6bf6b8SYongseok Koh rxq_cq_to_mbuf(rxq, pkt, cqe, rss_hash_res); 14107d6bf6b8SYongseok Koh PKT_LEN(pkt) = len; 14117d6bf6b8SYongseok Koh DATA_LEN(pkt) = len; 14127d6bf6b8SYongseok Koh PORT(pkt) = rxq->port_id; 14137d6bf6b8SYongseok Koh #ifdef MLX5_PMD_SOFT_COUNTERS 14147d6bf6b8SYongseok Koh /* Increment bytes counter. */ 14157d6bf6b8SYongseok Koh rxq->stats.ibytes += PKT_LEN(pkt); 14167d6bf6b8SYongseok Koh #endif 14177d6bf6b8SYongseok Koh /* Return packet. */ 14187d6bf6b8SYongseok Koh *(pkts++) = pkt; 14197d6bf6b8SYongseok Koh ++i; 14207d6bf6b8SYongseok Koh } 14217d6bf6b8SYongseok Koh /* Update the consumer indexes. */ 14221787eb7bSYongseok Koh rxq->consumed_strd = consumed_strd; 14230cfdc180SYongseok Koh rte_cio_wmb(); 14247d6bf6b8SYongseok Koh *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci); 14257d6bf6b8SYongseok Koh if (rq_ci != rxq->rq_ci) { 14267d6bf6b8SYongseok Koh rxq->rq_ci = rq_ci; 14270cfdc180SYongseok Koh rte_cio_wmb(); 14287d6bf6b8SYongseok Koh *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci); 14297d6bf6b8SYongseok Koh } 14307d6bf6b8SYongseok Koh #ifdef MLX5_PMD_SOFT_COUNTERS 14317d6bf6b8SYongseok Koh /* Increment packets counter. */ 14327d6bf6b8SYongseok Koh rxq->stats.ipackets += i; 14337d6bf6b8SYongseok Koh #endif 14347d6bf6b8SYongseok Koh return i; 14357d6bf6b8SYongseok Koh } 14367d6bf6b8SYongseok Koh 14372e22920bSAdrien Mazarguil /** 14382e22920bSAdrien Mazarguil * Dummy DPDK callback for TX. 14392e22920bSAdrien Mazarguil * 14402e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 14412e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 14422e22920bSAdrien Mazarguil * 14432e22920bSAdrien Mazarguil * @param dpdk_txq 14442e22920bSAdrien Mazarguil * Generic pointer to TX queue structure. 14452e22920bSAdrien Mazarguil * @param[in] pkts 14462e22920bSAdrien Mazarguil * Packets to transmit. 14472e22920bSAdrien Mazarguil * @param pkts_n 14482e22920bSAdrien Mazarguil * Number of packets in array. 14492e22920bSAdrien Mazarguil * 14502e22920bSAdrien Mazarguil * @return 14512e22920bSAdrien Mazarguil * Number of packets successfully transmitted (<= pkts_n). 14522e22920bSAdrien Mazarguil */ 14532e22920bSAdrien Mazarguil uint16_t 145456f08e16SNélio Laranjeiro removed_tx_burst(void *dpdk_txq __rte_unused, 145556f08e16SNélio Laranjeiro struct rte_mbuf **pkts __rte_unused, 145656f08e16SNélio Laranjeiro uint16_t pkts_n __rte_unused) 14572e22920bSAdrien Mazarguil { 14582aac5b5dSYongseok Koh rte_mb(); 14592e22920bSAdrien Mazarguil return 0; 14602e22920bSAdrien Mazarguil } 14612e22920bSAdrien Mazarguil 14622e22920bSAdrien Mazarguil /** 14632e22920bSAdrien Mazarguil * Dummy DPDK callback for RX. 14642e22920bSAdrien Mazarguil * 14652e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 14662e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 14672e22920bSAdrien Mazarguil * 14682e22920bSAdrien Mazarguil * @param dpdk_rxq 14692e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 14702e22920bSAdrien Mazarguil * @param[out] pkts 14712e22920bSAdrien Mazarguil * Array to store received packets. 14722e22920bSAdrien Mazarguil * @param pkts_n 14732e22920bSAdrien Mazarguil * Maximum number of packets in array. 14742e22920bSAdrien Mazarguil * 14752e22920bSAdrien Mazarguil * @return 14762e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 14772e22920bSAdrien Mazarguil */ 14782e22920bSAdrien Mazarguil uint16_t 147956f08e16SNélio Laranjeiro removed_rx_burst(void *dpdk_txq __rte_unused, 148056f08e16SNélio Laranjeiro struct rte_mbuf **pkts __rte_unused, 148156f08e16SNélio Laranjeiro uint16_t pkts_n __rte_unused) 14822e22920bSAdrien Mazarguil { 14832aac5b5dSYongseok Koh rte_mb(); 14842e22920bSAdrien Mazarguil return 0; 14852e22920bSAdrien Mazarguil } 14866cb559d6SYongseok Koh 14876cb559d6SYongseok Koh /* 14886cb559d6SYongseok Koh * Vectorized Rx/Tx routines are not compiled in when required vector 14896cb559d6SYongseok Koh * instructions are not supported on a target architecture. The following null 14906cb559d6SYongseok Koh * stubs are needed for linkage when those are not included outside of this file 14916cb559d6SYongseok Koh * (e.g. mlx5_rxtx_vec_sse.c for x86). 14926cb559d6SYongseok Koh */ 14936cb559d6SYongseok Koh 149481bede55SKeith Wiles __rte_weak uint16_t 149556f08e16SNélio Laranjeiro mlx5_rx_burst_vec(void *dpdk_txq __rte_unused, 149656f08e16SNélio Laranjeiro struct rte_mbuf **pkts __rte_unused, 149756f08e16SNélio Laranjeiro uint16_t pkts_n __rte_unused) 14986cb559d6SYongseok Koh { 14996cb559d6SYongseok Koh return 0; 15006cb559d6SYongseok Koh } 15016cb559d6SYongseok Koh 150281bede55SKeith Wiles __rte_weak int 1503af4f09f2SNélio Laranjeiro mlx5_rxq_check_vec_support(struct mlx5_rxq_data *rxq __rte_unused) 15046cb559d6SYongseok Koh { 15056cb559d6SYongseok Koh return -ENOTSUP; 15066cb559d6SYongseok Koh } 15076cb559d6SYongseok Koh 150881bede55SKeith Wiles __rte_weak int 1509af4f09f2SNélio Laranjeiro mlx5_check_vec_rx_support(struct rte_eth_dev *dev __rte_unused) 15106cb559d6SYongseok Koh { 15116cb559d6SYongseok Koh return -ENOTSUP; 15126cb559d6SYongseok Koh } 1513a6bd4911SViacheslav Ovsiienko 1514a6bd4911SViacheslav Ovsiienko /** 1515a6bd4911SViacheslav Ovsiienko * DPDK callback to check the status of a tx descriptor. 1516a6bd4911SViacheslav Ovsiienko * 1517a6bd4911SViacheslav Ovsiienko * @param tx_queue 1518a6bd4911SViacheslav Ovsiienko * The tx queue. 1519a6bd4911SViacheslav Ovsiienko * @param[in] offset 1520a6bd4911SViacheslav Ovsiienko * The index of the descriptor in the ring. 1521a6bd4911SViacheslav Ovsiienko * 1522a6bd4911SViacheslav Ovsiienko * @return 1523a6bd4911SViacheslav Ovsiienko * The status of the tx descriptor. 1524a6bd4911SViacheslav Ovsiienko */ 1525a6bd4911SViacheslav Ovsiienko int 1526a6bd4911SViacheslav Ovsiienko mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset) 1527a6bd4911SViacheslav Ovsiienko { 1528a6bd4911SViacheslav Ovsiienko (void)tx_queue; 1529a6bd4911SViacheslav Ovsiienko (void)offset; 1530a6bd4911SViacheslav Ovsiienko return RTE_ETH_TX_DESC_FULL; 1531a6bd4911SViacheslav Ovsiienko } 1532a6bd4911SViacheslav Ovsiienko 1533a6bd4911SViacheslav Ovsiienko /** 1534a6bd4911SViacheslav Ovsiienko * Configure the TX function to use. 1535a6bd4911SViacheslav Ovsiienko * 1536a6bd4911SViacheslav Ovsiienko * @param dev 1537a6bd4911SViacheslav Ovsiienko * Pointer to private data structure. 1538a6bd4911SViacheslav Ovsiienko * 1539a6bd4911SViacheslav Ovsiienko * @return 1540a6bd4911SViacheslav Ovsiienko * Pointer to selected Tx burst function. 1541a6bd4911SViacheslav Ovsiienko */ 1542a6bd4911SViacheslav Ovsiienko eth_tx_burst_t 1543a6bd4911SViacheslav Ovsiienko mlx5_select_tx_function(struct rte_eth_dev *dev) 1544a6bd4911SViacheslav Ovsiienko { 1545a6bd4911SViacheslav Ovsiienko (void)dev; 1546a6bd4911SViacheslav Ovsiienko return removed_tx_burst; 1547a6bd4911SViacheslav Ovsiienko } 1548a6bd4911SViacheslav Ovsiienko 1549a6bd4911SViacheslav Ovsiienko 1550