18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6771fa900SAdrien Mazarguil #include <stddef.h> 7771fa900SAdrien Mazarguil #include <unistd.h> 8771fa900SAdrien Mazarguil #include <string.h> 9771fa900SAdrien Mazarguil #include <stdint.h> 10771fa900SAdrien Mazarguil #include <stdlib.h> 11e72dd09bSNélio Laranjeiro #include <errno.h> 12771fa900SAdrien Mazarguil #include <net/if.h> 134a984153SXueming Li #include <sys/mman.h> 14ccdcba53SNélio Laranjeiro #include <linux/rtnetlink.h> 15771fa900SAdrien Mazarguil 16771fa900SAdrien Mazarguil /* Verbs header. */ 17771fa900SAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 18771fa900SAdrien Mazarguil #ifdef PEDANTIC 19fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 20771fa900SAdrien Mazarguil #endif 21771fa900SAdrien Mazarguil #include <infiniband/verbs.h> 22771fa900SAdrien Mazarguil #ifdef PEDANTIC 23fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 24771fa900SAdrien Mazarguil #endif 25771fa900SAdrien Mazarguil 26771fa900SAdrien Mazarguil #include <rte_malloc.h> 27ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 28fdf91e0fSJan Blunck #include <rte_ethdev_pci.h> 29771fa900SAdrien Mazarguil #include <rte_pci.h> 30c752998bSGaetan Rivet #include <rte_bus_pci.h> 31771fa900SAdrien Mazarguil #include <rte_common.h> 32e72dd09bSNélio Laranjeiro #include <rte_kvargs.h> 33e89c15b6SAdrien Mazarguil #include <rte_rwlock.h> 34e89c15b6SAdrien Mazarguil #include <rte_spinlock.h> 35f38c5457SAdrien Mazarguil #include <rte_string_fns.h> 36f15db67dSMatan Azrad #include <rte_alarm.h> 37771fa900SAdrien Mazarguil 387b4f1e6bSMatan Azrad #include <mlx5_glue.h> 397b4f1e6bSMatan Azrad #include <mlx5_devx_cmds.h> 4093e30982SMatan Azrad #include <mlx5_common.h> 41a4de9586SVu Pham #include <mlx5_common_mp.h> 427b4f1e6bSMatan Azrad 437b4f1e6bSMatan Azrad #include "mlx5_defs.h" 44771fa900SAdrien Mazarguil #include "mlx5.h" 45771fa900SAdrien Mazarguil #include "mlx5_utils.h" 462e22920bSAdrien Mazarguil #include "mlx5_rxtx.h" 47771fa900SAdrien Mazarguil #include "mlx5_autoconf.h" 48974f1e7eSYongseok Koh #include "mlx5_mr.h" 4984c406e7SOri Kam #include "mlx5_flow.h" 50efa79e68SOri Kam #include "rte_pmd_mlx5.h" 51771fa900SAdrien Mazarguil 5299c12dccSNélio Laranjeiro /* Device parameter to enable RX completion queue compression. */ 5399c12dccSNélio Laranjeiro #define MLX5_RXQ_CQE_COMP_EN "rxq_cqe_comp_en" 5499c12dccSNélio Laranjeiro 55bc91e8dbSYongseok Koh /* Device parameter to enable RX completion entry padding to 128B. */ 56bc91e8dbSYongseok Koh #define MLX5_RXQ_CQE_PAD_EN "rxq_cqe_pad_en" 57bc91e8dbSYongseok Koh 5878c7a16dSYongseok Koh /* Device parameter to enable padding Rx packet to cacheline size. */ 5978c7a16dSYongseok Koh #define MLX5_RXQ_PKT_PAD_EN "rxq_pkt_pad_en" 6078c7a16dSYongseok Koh 617d6bf6b8SYongseok Koh /* Device parameter to enable Multi-Packet Rx queue. */ 627d6bf6b8SYongseok Koh #define MLX5_RX_MPRQ_EN "mprq_en" 637d6bf6b8SYongseok Koh 647d6bf6b8SYongseok Koh /* Device parameter to configure log 2 of the number of strides for MPRQ. */ 657d6bf6b8SYongseok Koh #define MLX5_RX_MPRQ_LOG_STRIDE_NUM "mprq_log_stride_num" 667d6bf6b8SYongseok Koh 67ecb16045SAlexander Kozyrev /* Device parameter to configure log 2 of the stride size for MPRQ. */ 68ecb16045SAlexander Kozyrev #define MLX5_RX_MPRQ_LOG_STRIDE_SIZE "mprq_log_stride_size" 69ecb16045SAlexander Kozyrev 707d6bf6b8SYongseok Koh /* Device parameter to limit the size of memcpy'd packet for MPRQ. */ 717d6bf6b8SYongseok Koh #define MLX5_RX_MPRQ_MAX_MEMCPY_LEN "mprq_max_memcpy_len" 727d6bf6b8SYongseok Koh 737d6bf6b8SYongseok Koh /* Device parameter to set the minimum number of Rx queues to enable MPRQ. */ 747d6bf6b8SYongseok Koh #define MLX5_RXQS_MIN_MPRQ "rxqs_min_mprq" 757d6bf6b8SYongseok Koh 76a6bd4911SViacheslav Ovsiienko /* Device parameter to configure inline send. Deprecated, ignored.*/ 772a66cf37SYaacov Hazan #define MLX5_TXQ_INLINE "txq_inline" 782a66cf37SYaacov Hazan 79505f1fe4SViacheslav Ovsiienko /* Device parameter to limit packet size to inline with ordinary SEND. */ 80505f1fe4SViacheslav Ovsiienko #define MLX5_TXQ_INLINE_MAX "txq_inline_max" 81505f1fe4SViacheslav Ovsiienko 82505f1fe4SViacheslav Ovsiienko /* Device parameter to configure minimal data size to inline. */ 83505f1fe4SViacheslav Ovsiienko #define MLX5_TXQ_INLINE_MIN "txq_inline_min" 84505f1fe4SViacheslav Ovsiienko 85505f1fe4SViacheslav Ovsiienko /* Device parameter to limit packet size to inline with Enhanced MPW. */ 86505f1fe4SViacheslav Ovsiienko #define MLX5_TXQ_INLINE_MPW "txq_inline_mpw" 87505f1fe4SViacheslav Ovsiienko 882a66cf37SYaacov Hazan /* 892a66cf37SYaacov Hazan * Device parameter to configure the number of TX queues threshold for 902a66cf37SYaacov Hazan * enabling inline send. 912a66cf37SYaacov Hazan */ 922a66cf37SYaacov Hazan #define MLX5_TXQS_MIN_INLINE "txqs_min_inline" 932a66cf37SYaacov Hazan 9409d8b416SYongseok Koh /* 9509d8b416SYongseok Koh * Device parameter to configure the number of TX queues threshold for 96a6bd4911SViacheslav Ovsiienko * enabling vectorized Tx, deprecated, ignored (no vectorized Tx routines). 9709d8b416SYongseok Koh */ 9809d8b416SYongseok Koh #define MLX5_TXQS_MAX_VEC "txqs_max_vec" 9909d8b416SYongseok Koh 100230189d9SNélio Laranjeiro /* Device parameter to enable multi-packet send WQEs. */ 101230189d9SNélio Laranjeiro #define MLX5_TXQ_MPW_EN "txq_mpw_en" 102230189d9SNélio Laranjeiro 103a6bd4911SViacheslav Ovsiienko /* 1048409a285SViacheslav Ovsiienko * Device parameter to force doorbell register mapping 1058409a285SViacheslav Ovsiienko * to non-cahed region eliminating the extra write memory barrier. 1068409a285SViacheslav Ovsiienko */ 1078409a285SViacheslav Ovsiienko #define MLX5_TX_DB_NC "tx_db_nc" 1088409a285SViacheslav Ovsiienko 1098409a285SViacheslav Ovsiienko /* 110a6bd4911SViacheslav Ovsiienko * Device parameter to include 2 dsegs in the title WQEBB. 111a6bd4911SViacheslav Ovsiienko * Deprecated, ignored. 112a6bd4911SViacheslav Ovsiienko */ 1136ce84bd8SYongseok Koh #define MLX5_TXQ_MPW_HDR_DSEG_EN "txq_mpw_hdr_dseg_en" 1146ce84bd8SYongseok Koh 115a6bd4911SViacheslav Ovsiienko /* 116a6bd4911SViacheslav Ovsiienko * Device parameter to limit the size of inlining packet. 117a6bd4911SViacheslav Ovsiienko * Deprecated, ignored. 118a6bd4911SViacheslav Ovsiienko */ 1196ce84bd8SYongseok Koh #define MLX5_TXQ_MAX_INLINE_LEN "txq_max_inline_len" 1206ce84bd8SYongseok Koh 121a6bd4911SViacheslav Ovsiienko /* 122a6bd4911SViacheslav Ovsiienko * Device parameter to enable hardware Tx vector. 123a6bd4911SViacheslav Ovsiienko * Deprecated, ignored (no vectorized Tx routines anymore). 124a6bd4911SViacheslav Ovsiienko */ 1255644d5b9SNelio Laranjeiro #define MLX5_TX_VEC_EN "tx_vec_en" 1265644d5b9SNelio Laranjeiro 1275644d5b9SNelio Laranjeiro /* Device parameter to enable hardware Rx vector. */ 1285644d5b9SNelio Laranjeiro #define MLX5_RX_VEC_EN "rx_vec_en" 1295644d5b9SNelio Laranjeiro 13078a54648SXueming Li /* Allow L3 VXLAN flow creation. */ 13178a54648SXueming Li #define MLX5_L3_VXLAN_EN "l3_vxlan_en" 13278a54648SXueming Li 133e2b4925eSOri Kam /* Activate DV E-Switch flow steering. */ 134e2b4925eSOri Kam #define MLX5_DV_ESW_EN "dv_esw_en" 135e2b4925eSOri Kam 13651e72d38SOri Kam /* Activate DV flow steering. */ 13751e72d38SOri Kam #define MLX5_DV_FLOW_EN "dv_flow_en" 13851e72d38SOri Kam 1392d241515SViacheslav Ovsiienko /* Enable extensive flow metadata support. */ 1402d241515SViacheslav Ovsiienko #define MLX5_DV_XMETA_EN "dv_xmeta_en" 1412d241515SViacheslav Ovsiienko 142db209cc3SNélio Laranjeiro /* Activate Netlink support in VF mode. */ 143db209cc3SNélio Laranjeiro #define MLX5_VF_NL_EN "vf_nl_en" 144db209cc3SNélio Laranjeiro 145dceb5029SYongseok Koh /* Enable extending memsegs when creating a MR. */ 146dceb5029SYongseok Koh #define MLX5_MR_EXT_MEMSEG_EN "mr_ext_memseg_en" 147dceb5029SYongseok Koh 1486de569f5SAdrien Mazarguil /* Select port representors to instantiate. */ 1496de569f5SAdrien Mazarguil #define MLX5_REPRESENTOR "representor" 1506de569f5SAdrien Mazarguil 151066cfecdSMatan Azrad /* Device parameter to configure the maximum number of dump files per queue. */ 152066cfecdSMatan Azrad #define MLX5_MAX_DUMP_FILES_NUM "max_dump_files_num" 153066cfecdSMatan Azrad 15421bb6c7eSDekel Peled /* Configure timeout of LRO session (in microseconds). */ 15521bb6c7eSDekel Peled #define MLX5_LRO_TIMEOUT_USEC "lro_timeout_usec" 15621bb6c7eSDekel Peled 1571ad9a3d0SBing Zhao /* 1581ad9a3d0SBing Zhao * Device parameter to configure the total data buffer size for a single 1591ad9a3d0SBing Zhao * hairpin queue (logarithm value). 1601ad9a3d0SBing Zhao */ 1611ad9a3d0SBing Zhao #define MLX5_HP_BUF_SIZE "hp_buf_log_sz" 1621ad9a3d0SBing Zhao 16343e9d979SShachar Beiser #ifndef HAVE_IBV_MLX5_MOD_MPW 16443e9d979SShachar Beiser #define MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED (1 << 2) 16543e9d979SShachar Beiser #define MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW (1 << 3) 16643e9d979SShachar Beiser #endif 16743e9d979SShachar Beiser 168523f5a74SYongseok Koh #ifndef HAVE_IBV_MLX5_MOD_CQE_128B_COMP 169523f5a74SYongseok Koh #define MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP (1 << 4) 170523f5a74SYongseok Koh #endif 171523f5a74SYongseok Koh 172974f1e7eSYongseok Koh static const char *MZ_MLX5_PMD_SHARED_DATA = "mlx5_pmd_shared_data"; 173974f1e7eSYongseok Koh 174974f1e7eSYongseok Koh /* Shared memory between primary and secondary processes. */ 175974f1e7eSYongseok Koh struct mlx5_shared_data *mlx5_shared_data; 176974f1e7eSYongseok Koh 177974f1e7eSYongseok Koh /* Spinlock for mlx5_shared_data allocation. */ 178974f1e7eSYongseok Koh static rte_spinlock_t mlx5_shared_data_lock = RTE_SPINLOCK_INITIALIZER; 179974f1e7eSYongseok Koh 1807be600c8SYongseok Koh /* Process local data for secondary processes. */ 1817be600c8SYongseok Koh static struct mlx5_local_data mlx5_local_data; 1827be600c8SYongseok Koh 183a170a30dSNélio Laranjeiro /** Driver-specific log messages type. */ 184a170a30dSNélio Laranjeiro int mlx5_logtype; 185a170a30dSNélio Laranjeiro 186ad74bc61SViacheslav Ovsiienko /** Data associated with devices to spawn. */ 187ad74bc61SViacheslav Ovsiienko struct mlx5_dev_spawn_data { 188ad74bc61SViacheslav Ovsiienko uint32_t ifindex; /**< Network interface index. */ 189ad74bc61SViacheslav Ovsiienko uint32_t max_port; /**< IB device maximal port index. */ 190ad74bc61SViacheslav Ovsiienko uint32_t ibv_port; /**< IB device physical port index. */ 1912e569a37SViacheslav Ovsiienko int pf_bond; /**< bonding device PF index. < 0 - no bonding */ 192ad74bc61SViacheslav Ovsiienko struct mlx5_switch_info info; /**< Switch information. */ 193ad74bc61SViacheslav Ovsiienko struct ibv_device *ibv_dev; /**< Associated IB device. */ 194ad74bc61SViacheslav Ovsiienko struct rte_eth_dev *eth_dev; /**< Associated Ethernet device. */ 195ab3cffcfSViacheslav Ovsiienko struct rte_pci_device *pci_dev; /**< Backend PCI device. */ 196ad74bc61SViacheslav Ovsiienko }; 197ad74bc61SViacheslav Ovsiienko 19817e19bc4SViacheslav Ovsiienko static LIST_HEAD(, mlx5_ibv_shared) mlx5_ibv_list = LIST_HEAD_INITIALIZER(); 19917e19bc4SViacheslav Ovsiienko static pthread_mutex_t mlx5_ibv_list_mutex = PTHREAD_MUTEX_INITIALIZER; 20017e19bc4SViacheslav Ovsiienko 201014d1cbeSSuanming Mou static struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = { 202b88341caSSuanming Mou #ifdef HAVE_IBV_FLOW_DV_SUPPORT 203014d1cbeSSuanming Mou { 204014d1cbeSSuanming Mou .size = sizeof(struct mlx5_flow_dv_encap_decap_resource), 205014d1cbeSSuanming Mou .trunk_size = 64, 206014d1cbeSSuanming Mou .grow_trunk = 3, 207014d1cbeSSuanming Mou .grow_shift = 2, 208014d1cbeSSuanming Mou .need_lock = 0, 209014d1cbeSSuanming Mou .release_mem_en = 1, 210014d1cbeSSuanming Mou .malloc = rte_malloc_socket, 211014d1cbeSSuanming Mou .free = rte_free, 212014d1cbeSSuanming Mou .type = "mlx5_encap_decap_ipool", 213014d1cbeSSuanming Mou }, 2148acf8ac9SSuanming Mou { 2158acf8ac9SSuanming Mou .size = sizeof(struct mlx5_flow_dv_push_vlan_action_resource), 2168acf8ac9SSuanming Mou .trunk_size = 64, 2178acf8ac9SSuanming Mou .grow_trunk = 3, 2188acf8ac9SSuanming Mou .grow_shift = 2, 2198acf8ac9SSuanming Mou .need_lock = 0, 2208acf8ac9SSuanming Mou .release_mem_en = 1, 2218acf8ac9SSuanming Mou .malloc = rte_malloc_socket, 2228acf8ac9SSuanming Mou .free = rte_free, 2238acf8ac9SSuanming Mou .type = "mlx5_push_vlan_ipool", 2248acf8ac9SSuanming Mou }, 2255f114269SSuanming Mou { 2265f114269SSuanming Mou .size = sizeof(struct mlx5_flow_dv_tag_resource), 2275f114269SSuanming Mou .trunk_size = 64, 2285f114269SSuanming Mou .grow_trunk = 3, 2295f114269SSuanming Mou .grow_shift = 2, 2305f114269SSuanming Mou .need_lock = 0, 2315f114269SSuanming Mou .release_mem_en = 1, 2325f114269SSuanming Mou .malloc = rte_malloc_socket, 2335f114269SSuanming Mou .free = rte_free, 2345f114269SSuanming Mou .type = "mlx5_tag_ipool", 2355f114269SSuanming Mou }, 236f3faf9eaSSuanming Mou { 237f3faf9eaSSuanming Mou .size = sizeof(struct mlx5_flow_dv_port_id_action_resource), 238f3faf9eaSSuanming Mou .trunk_size = 64, 239f3faf9eaSSuanming Mou .grow_trunk = 3, 240f3faf9eaSSuanming Mou .grow_shift = 2, 241f3faf9eaSSuanming Mou .need_lock = 0, 242f3faf9eaSSuanming Mou .release_mem_en = 1, 243f3faf9eaSSuanming Mou .malloc = rte_malloc_socket, 244f3faf9eaSSuanming Mou .free = rte_free, 245f3faf9eaSSuanming Mou .type = "mlx5_port_id_ipool", 246f3faf9eaSSuanming Mou }, 2477ac99475SSuanming Mou { 2487ac99475SSuanming Mou .size = sizeof(struct mlx5_flow_tbl_data_entry), 2497ac99475SSuanming Mou .trunk_size = 64, 2507ac99475SSuanming Mou .grow_trunk = 3, 2517ac99475SSuanming Mou .grow_shift = 2, 2527ac99475SSuanming Mou .need_lock = 0, 2537ac99475SSuanming Mou .release_mem_en = 1, 2547ac99475SSuanming Mou .malloc = rte_malloc_socket, 2557ac99475SSuanming Mou .free = rte_free, 2567ac99475SSuanming Mou .type = "mlx5_jump_ipool", 2577ac99475SSuanming Mou }, 258b88341caSSuanming Mou #endif 259772dc0ebSSuanming Mou { 2608638e2b0SSuanming Mou .size = sizeof(struct mlx5_flow_meter), 2618638e2b0SSuanming Mou .trunk_size = 64, 2628638e2b0SSuanming Mou .grow_trunk = 3, 2638638e2b0SSuanming Mou .grow_shift = 2, 2648638e2b0SSuanming Mou .need_lock = 0, 2658638e2b0SSuanming Mou .release_mem_en = 1, 2668638e2b0SSuanming Mou .malloc = rte_malloc_socket, 2678638e2b0SSuanming Mou .free = rte_free, 2688638e2b0SSuanming Mou .type = "mlx5_meter_ipool", 2698638e2b0SSuanming Mou }, 2708638e2b0SSuanming Mou { 27190e6053aSSuanming Mou .size = sizeof(struct mlx5_flow_mreg_copy_resource), 27290e6053aSSuanming Mou .trunk_size = 64, 27390e6053aSSuanming Mou .grow_trunk = 3, 27490e6053aSSuanming Mou .grow_shift = 2, 27590e6053aSSuanming Mou .need_lock = 0, 27690e6053aSSuanming Mou .release_mem_en = 1, 27790e6053aSSuanming Mou .malloc = rte_malloc_socket, 27890e6053aSSuanming Mou .free = rte_free, 27990e6053aSSuanming Mou .type = "mlx5_mcp_ipool", 28090e6053aSSuanming Mou }, 28190e6053aSSuanming Mou { 282772dc0ebSSuanming Mou .size = (sizeof(struct mlx5_hrxq) + MLX5_RSS_HASH_KEY_LEN), 283772dc0ebSSuanming Mou .trunk_size = 64, 284772dc0ebSSuanming Mou .grow_trunk = 3, 285772dc0ebSSuanming Mou .grow_shift = 2, 286772dc0ebSSuanming Mou .need_lock = 0, 287772dc0ebSSuanming Mou .release_mem_en = 1, 288772dc0ebSSuanming Mou .malloc = rte_malloc_socket, 289772dc0ebSSuanming Mou .free = rte_free, 290772dc0ebSSuanming Mou .type = "mlx5_hrxq_ipool", 291772dc0ebSSuanming Mou }, 292b88341caSSuanming Mou { 293b88341caSSuanming Mou .size = sizeof(struct mlx5_flow_handle), 294b88341caSSuanming Mou .trunk_size = 64, 295b88341caSSuanming Mou .grow_trunk = 3, 296b88341caSSuanming Mou .grow_shift = 2, 297b88341caSSuanming Mou .need_lock = 0, 298b88341caSSuanming Mou .release_mem_en = 1, 299b88341caSSuanming Mou .malloc = rte_malloc_socket, 300b88341caSSuanming Mou .free = rte_free, 301b88341caSSuanming Mou .type = "mlx5_flow_handle_ipool", 302b88341caSSuanming Mou }, 303ab612adcSSuanming Mou { 304ab612adcSSuanming Mou .size = sizeof(struct rte_flow), 305ab612adcSSuanming Mou .trunk_size = 4096, 306ab612adcSSuanming Mou .need_lock = 1, 307ab612adcSSuanming Mou .release_mem_en = 1, 308ab612adcSSuanming Mou .malloc = rte_malloc_socket, 309ab612adcSSuanming Mou .free = rte_free, 310ab612adcSSuanming Mou .type = "rte_flow_ipool", 311ab612adcSSuanming Mou }, 312014d1cbeSSuanming Mou }; 313014d1cbeSSuanming Mou 314014d1cbeSSuanming Mou 315830d2091SOri Kam #define MLX5_FLOW_MIN_ID_POOL_SIZE 512 316830d2091SOri Kam #define MLX5_ID_GENERATION_ARRAY_FACTOR 16 317830d2091SOri Kam 318860897d2SBing Zhao #define MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE 4096 319e484e403SBing Zhao #define MLX5_TAGS_HLIST_ARRAY_SIZE 8192 320860897d2SBing Zhao 321830d2091SOri Kam /** 322830d2091SOri Kam * Allocate ID pool structure. 323830d2091SOri Kam * 32430a3687dSSuanming Mou * @param[in] max_id 32530a3687dSSuanming Mou * The maximum id can be allocated from the pool. 32630a3687dSSuanming Mou * 327830d2091SOri Kam * @return 328830d2091SOri Kam * Pointer to pool object, NULL value otherwise. 329830d2091SOri Kam */ 330830d2091SOri Kam struct mlx5_flow_id_pool * 33130a3687dSSuanming Mou mlx5_flow_id_pool_alloc(uint32_t max_id) 332830d2091SOri Kam { 333830d2091SOri Kam struct mlx5_flow_id_pool *pool; 334830d2091SOri Kam void *mem; 335830d2091SOri Kam 336830d2091SOri Kam pool = rte_zmalloc("id pool allocation", sizeof(*pool), 337830d2091SOri Kam RTE_CACHE_LINE_SIZE); 338830d2091SOri Kam if (!pool) { 339830d2091SOri Kam DRV_LOG(ERR, "can't allocate id pool"); 340830d2091SOri Kam rte_errno = ENOMEM; 341830d2091SOri Kam return NULL; 342830d2091SOri Kam } 343830d2091SOri Kam mem = rte_zmalloc("", MLX5_FLOW_MIN_ID_POOL_SIZE * sizeof(uint32_t), 344830d2091SOri Kam RTE_CACHE_LINE_SIZE); 345830d2091SOri Kam if (!mem) { 346830d2091SOri Kam DRV_LOG(ERR, "can't allocate mem for id pool"); 347830d2091SOri Kam rte_errno = ENOMEM; 348830d2091SOri Kam goto error; 349830d2091SOri Kam } 350830d2091SOri Kam pool->free_arr = mem; 351830d2091SOri Kam pool->curr = pool->free_arr; 352830d2091SOri Kam pool->last = pool->free_arr + MLX5_FLOW_MIN_ID_POOL_SIZE; 353830d2091SOri Kam pool->base_index = 0; 35430a3687dSSuanming Mou pool->max_id = max_id; 355830d2091SOri Kam return pool; 356830d2091SOri Kam error: 357830d2091SOri Kam rte_free(pool); 358830d2091SOri Kam return NULL; 359830d2091SOri Kam } 360830d2091SOri Kam 361830d2091SOri Kam /** 362830d2091SOri Kam * Release ID pool structure. 363830d2091SOri Kam * 364830d2091SOri Kam * @param[in] pool 365830d2091SOri Kam * Pointer to flow id pool object to free. 366830d2091SOri Kam */ 367830d2091SOri Kam void 368830d2091SOri Kam mlx5_flow_id_pool_release(struct mlx5_flow_id_pool *pool) 369830d2091SOri Kam { 370830d2091SOri Kam rte_free(pool->free_arr); 371830d2091SOri Kam rte_free(pool); 372830d2091SOri Kam } 373830d2091SOri Kam 374830d2091SOri Kam /** 375830d2091SOri Kam * Generate ID. 376830d2091SOri Kam * 377830d2091SOri Kam * @param[in] pool 378830d2091SOri Kam * Pointer to flow id pool. 379830d2091SOri Kam * @param[out] id 380830d2091SOri Kam * The generated ID. 381830d2091SOri Kam * 382830d2091SOri Kam * @return 383830d2091SOri Kam * 0 on success, error value otherwise. 384830d2091SOri Kam */ 385830d2091SOri Kam uint32_t 386830d2091SOri Kam mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id) 387830d2091SOri Kam { 388830d2091SOri Kam if (pool->curr == pool->free_arr) { 38930a3687dSSuanming Mou if (pool->base_index == pool->max_id) { 390830d2091SOri Kam rte_errno = ENOMEM; 391830d2091SOri Kam DRV_LOG(ERR, "no free id"); 392830d2091SOri Kam return -rte_errno; 393830d2091SOri Kam } 394830d2091SOri Kam *id = ++pool->base_index; 395830d2091SOri Kam return 0; 396830d2091SOri Kam } 397830d2091SOri Kam *id = *(--pool->curr); 398830d2091SOri Kam return 0; 399830d2091SOri Kam } 400830d2091SOri Kam 401830d2091SOri Kam /** 402830d2091SOri Kam * Release ID. 403830d2091SOri Kam * 404830d2091SOri Kam * @param[in] pool 405830d2091SOri Kam * Pointer to flow id pool. 406830d2091SOri Kam * @param[out] id 407830d2091SOri Kam * The generated ID. 408830d2091SOri Kam * 409830d2091SOri Kam * @return 410830d2091SOri Kam * 0 on success, error value otherwise. 411830d2091SOri Kam */ 412830d2091SOri Kam uint32_t 413830d2091SOri Kam mlx5_flow_id_release(struct mlx5_flow_id_pool *pool, uint32_t id) 414830d2091SOri Kam { 415830d2091SOri Kam uint32_t size; 416830d2091SOri Kam uint32_t size2; 417830d2091SOri Kam void *mem; 418830d2091SOri Kam 419830d2091SOri Kam if (pool->curr == pool->last) { 420830d2091SOri Kam size = pool->curr - pool->free_arr; 421830d2091SOri Kam size2 = size * MLX5_ID_GENERATION_ARRAY_FACTOR; 4228e46d4e1SAlexander Kozyrev MLX5_ASSERT(size2 > size); 423830d2091SOri Kam mem = rte_malloc("", size2 * sizeof(uint32_t), 0); 424830d2091SOri Kam if (!mem) { 425830d2091SOri Kam DRV_LOG(ERR, "can't allocate mem for id pool"); 426830d2091SOri Kam rte_errno = ENOMEM; 427830d2091SOri Kam return -rte_errno; 428830d2091SOri Kam } 429830d2091SOri Kam memcpy(mem, pool->free_arr, size * sizeof(uint32_t)); 430830d2091SOri Kam rte_free(pool->free_arr); 431830d2091SOri Kam pool->free_arr = mem; 432830d2091SOri Kam pool->curr = pool->free_arr + size; 433830d2091SOri Kam pool->last = pool->free_arr + size2; 434830d2091SOri Kam } 435830d2091SOri Kam *pool->curr = id; 436830d2091SOri Kam pool->curr++; 437830d2091SOri Kam return 0; 438830d2091SOri Kam } 439830d2091SOri Kam 44017e19bc4SViacheslav Ovsiienko /** 4415382d28cSMatan Azrad * Initialize the counters management structure. 4425382d28cSMatan Azrad * 4435382d28cSMatan Azrad * @param[in] sh 4445382d28cSMatan Azrad * Pointer to mlx5_ibv_shared object to free 4455382d28cSMatan Azrad */ 4465382d28cSMatan Azrad static void 4475382d28cSMatan Azrad mlx5_flow_counters_mng_init(struct mlx5_ibv_shared *sh) 4485382d28cSMatan Azrad { 4495382d28cSMatan Azrad uint8_t i; 4505382d28cSMatan Azrad 4515382d28cSMatan Azrad TAILQ_INIT(&sh->cmng.flow_counters); 4525382d28cSMatan Azrad for (i = 0; i < RTE_DIM(sh->cmng.ccont); ++i) 4535382d28cSMatan Azrad TAILQ_INIT(&sh->cmng.ccont[i].pool_list); 4545382d28cSMatan Azrad } 4555382d28cSMatan Azrad 4565382d28cSMatan Azrad /** 4575382d28cSMatan Azrad * Destroy all the resources allocated for a counter memory management. 4585382d28cSMatan Azrad * 4595382d28cSMatan Azrad * @param[in] mng 4605382d28cSMatan Azrad * Pointer to the memory management structure. 4615382d28cSMatan Azrad */ 4625382d28cSMatan Azrad static void 4635382d28cSMatan Azrad mlx5_flow_destroy_counter_stat_mem_mng(struct mlx5_counter_stats_mem_mng *mng) 4645382d28cSMatan Azrad { 4655382d28cSMatan Azrad uint8_t *mem = (uint8_t *)(uintptr_t)mng->raws[0].data; 4665382d28cSMatan Azrad 4675382d28cSMatan Azrad LIST_REMOVE(mng, next); 4685382d28cSMatan Azrad claim_zero(mlx5_devx_cmd_destroy(mng->dm)); 4695382d28cSMatan Azrad claim_zero(mlx5_glue->devx_umem_dereg(mng->umem)); 4705382d28cSMatan Azrad rte_free(mem); 4715382d28cSMatan Azrad } 4725382d28cSMatan Azrad 4735382d28cSMatan Azrad /** 4745382d28cSMatan Azrad * Close and release all the resources of the counters management. 4755382d28cSMatan Azrad * 4765382d28cSMatan Azrad * @param[in] sh 4775382d28cSMatan Azrad * Pointer to mlx5_ibv_shared object to free. 4785382d28cSMatan Azrad */ 4795382d28cSMatan Azrad static void 4805382d28cSMatan Azrad mlx5_flow_counters_mng_close(struct mlx5_ibv_shared *sh) 4815382d28cSMatan Azrad { 4825382d28cSMatan Azrad struct mlx5_counter_stats_mem_mng *mng; 4835382d28cSMatan Azrad uint8_t i; 4845382d28cSMatan Azrad int j; 485f15db67dSMatan Azrad int retries = 1024; 4865382d28cSMatan Azrad 487f15db67dSMatan Azrad rte_errno = 0; 488f15db67dSMatan Azrad while (--retries) { 489f15db67dSMatan Azrad rte_eal_alarm_cancel(mlx5_flow_query_alarm, sh); 490f15db67dSMatan Azrad if (rte_errno != EINPROGRESS) 491f15db67dSMatan Azrad break; 492f15db67dSMatan Azrad rte_pause(); 493f15db67dSMatan Azrad } 4945382d28cSMatan Azrad for (i = 0; i < RTE_DIM(sh->cmng.ccont); ++i) { 4955382d28cSMatan Azrad struct mlx5_flow_counter_pool *pool; 4965382d28cSMatan Azrad uint32_t batch = !!(i % 2); 4975382d28cSMatan Azrad 4985382d28cSMatan Azrad if (!sh->cmng.ccont[i].pools) 4995382d28cSMatan Azrad continue; 5005382d28cSMatan Azrad pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 5015382d28cSMatan Azrad while (pool) { 5025382d28cSMatan Azrad if (batch) { 5035382d28cSMatan Azrad if (pool->min_dcs) 5045382d28cSMatan Azrad claim_zero 5055382d28cSMatan Azrad (mlx5_devx_cmd_destroy(pool->min_dcs)); 5065382d28cSMatan Azrad } 5075382d28cSMatan Azrad for (j = 0; j < MLX5_COUNTERS_PER_POOL; ++j) { 5085382d28cSMatan Azrad if (pool->counters_raw[j].action) 5095382d28cSMatan Azrad claim_zero 5105382d28cSMatan Azrad (mlx5_glue->destroy_flow_action 5115382d28cSMatan Azrad (pool->counters_raw[j].action)); 512826b8a87SSuanming Mou if (!batch && MLX5_GET_POOL_CNT_EXT 513826b8a87SSuanming Mou (pool, j)->dcs) 5145382d28cSMatan Azrad claim_zero(mlx5_devx_cmd_destroy 515826b8a87SSuanming Mou (MLX5_GET_POOL_CNT_EXT 516826b8a87SSuanming Mou (pool, j)->dcs)); 5175382d28cSMatan Azrad } 5185382d28cSMatan Azrad TAILQ_REMOVE(&sh->cmng.ccont[i].pool_list, pool, 5195382d28cSMatan Azrad next); 5205382d28cSMatan Azrad rte_free(pool); 5215382d28cSMatan Azrad pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 5225382d28cSMatan Azrad } 5235382d28cSMatan Azrad rte_free(sh->cmng.ccont[i].pools); 5245382d28cSMatan Azrad } 5255382d28cSMatan Azrad mng = LIST_FIRST(&sh->cmng.mem_mngs); 5265382d28cSMatan Azrad while (mng) { 5275382d28cSMatan Azrad mlx5_flow_destroy_counter_stat_mem_mng(mng); 5285382d28cSMatan Azrad mng = LIST_FIRST(&sh->cmng.mem_mngs); 5295382d28cSMatan Azrad } 5305382d28cSMatan Azrad memset(&sh->cmng, 0, sizeof(sh->cmng)); 5315382d28cSMatan Azrad } 5325382d28cSMatan Azrad 5335382d28cSMatan Azrad /** 534014d1cbeSSuanming Mou * Initialize the flow resources' indexed mempool. 535014d1cbeSSuanming Mou * 536014d1cbeSSuanming Mou * @param[in] sh 537014d1cbeSSuanming Mou * Pointer to mlx5_ibv_shared object. 538b88341caSSuanming Mou * @param[in] sh 539b88341caSSuanming Mou * Pointer to user dev config. 540014d1cbeSSuanming Mou */ 541014d1cbeSSuanming Mou static void 542b88341caSSuanming Mou mlx5_flow_ipool_create(struct mlx5_ibv_shared *sh, 543b88341caSSuanming Mou const struct mlx5_dev_config *config __rte_unused) 544014d1cbeSSuanming Mou { 545014d1cbeSSuanming Mou uint8_t i; 546014d1cbeSSuanming Mou 547b88341caSSuanming Mou #ifdef HAVE_IBV_FLOW_DV_SUPPORT 548b88341caSSuanming Mou /* 549b88341caSSuanming Mou * While DV is supported, user chooses the verbs mode, 550b88341caSSuanming Mou * the mlx5 flow handle size is different with the 551b88341caSSuanming Mou * MLX5_FLOW_HANDLE_VERBS_SIZE. 552b88341caSSuanming Mou */ 553b88341caSSuanming Mou if (!config->dv_flow_en) 554b88341caSSuanming Mou mlx5_ipool_cfg[MLX5_IPOOL_MLX5_FLOW].size = 555b88341caSSuanming Mou MLX5_FLOW_HANDLE_VERBS_SIZE; 556b88341caSSuanming Mou #endif 557014d1cbeSSuanming Mou for (i = 0; i < MLX5_IPOOL_MAX; ++i) 558014d1cbeSSuanming Mou sh->ipool[i] = mlx5_ipool_create(&mlx5_ipool_cfg[i]); 559014d1cbeSSuanming Mou } 560014d1cbeSSuanming Mou 561014d1cbeSSuanming Mou /** 562014d1cbeSSuanming Mou * Release the flow resources' indexed mempool. 563014d1cbeSSuanming Mou * 564014d1cbeSSuanming Mou * @param[in] sh 565014d1cbeSSuanming Mou * Pointer to mlx5_ibv_shared object. 566014d1cbeSSuanming Mou */ 567014d1cbeSSuanming Mou static void 568014d1cbeSSuanming Mou mlx5_flow_ipool_destroy(struct mlx5_ibv_shared *sh) 569014d1cbeSSuanming Mou { 570014d1cbeSSuanming Mou uint8_t i; 571014d1cbeSSuanming Mou 572014d1cbeSSuanming Mou for (i = 0; i < MLX5_IPOOL_MAX; ++i) 573014d1cbeSSuanming Mou mlx5_ipool_destroy(sh->ipool[i]); 574014d1cbeSSuanming Mou } 575014d1cbeSSuanming Mou 576014d1cbeSSuanming Mou /** 577b9d86122SDekel Peled * Extract pdn of PD object using DV API. 578b9d86122SDekel Peled * 579b9d86122SDekel Peled * @param[in] pd 580b9d86122SDekel Peled * Pointer to the verbs PD object. 581b9d86122SDekel Peled * @param[out] pdn 582b9d86122SDekel Peled * Pointer to the PD object number variable. 583b9d86122SDekel Peled * 584b9d86122SDekel Peled * @return 585b9d86122SDekel Peled * 0 on success, error value otherwise. 586b9d86122SDekel Peled */ 587b9d86122SDekel Peled #ifdef HAVE_IBV_FLOW_DV_SUPPORT 588b9d86122SDekel Peled static int 589b9d86122SDekel Peled mlx5_get_pdn(struct ibv_pd *pd __rte_unused, uint32_t *pdn __rte_unused) 590b9d86122SDekel Peled { 591b9d86122SDekel Peled struct mlx5dv_obj obj; 592b9d86122SDekel Peled struct mlx5dv_pd pd_info; 593b9d86122SDekel Peled int ret = 0; 594b9d86122SDekel Peled 595b9d86122SDekel Peled obj.pd.in = pd; 596b9d86122SDekel Peled obj.pd.out = &pd_info; 597b9d86122SDekel Peled ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD); 598b9d86122SDekel Peled if (ret) { 599b9d86122SDekel Peled DRV_LOG(DEBUG, "Fail to get PD object info"); 600b9d86122SDekel Peled return ret; 601b9d86122SDekel Peled } 602b9d86122SDekel Peled *pdn = pd_info.pdn; 603b9d86122SDekel Peled return 0; 604b9d86122SDekel Peled } 605b9d86122SDekel Peled #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 606b9d86122SDekel Peled 6078409a285SViacheslav Ovsiienko static int 6088409a285SViacheslav Ovsiienko mlx5_config_doorbell_mapping_env(const struct mlx5_dev_config *config) 6098409a285SViacheslav Ovsiienko { 6108409a285SViacheslav Ovsiienko char *env; 6118409a285SViacheslav Ovsiienko int value; 6128409a285SViacheslav Ovsiienko 6138e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 6148409a285SViacheslav Ovsiienko /* Get environment variable to store. */ 6158409a285SViacheslav Ovsiienko env = getenv(MLX5_SHUT_UP_BF); 6168409a285SViacheslav Ovsiienko value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET; 6178409a285SViacheslav Ovsiienko if (config->dbnc == MLX5_ARG_UNSET) 6188409a285SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1); 6198409a285SViacheslav Ovsiienko else 620f078ceb6SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, 621f078ceb6SViacheslav Ovsiienko config->dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1); 6228409a285SViacheslav Ovsiienko return value; 6238409a285SViacheslav Ovsiienko } 6248409a285SViacheslav Ovsiienko 6258409a285SViacheslav Ovsiienko static void 62606f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(int value) 6278409a285SViacheslav Ovsiienko { 6288e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 6298409a285SViacheslav Ovsiienko /* Restore the original environment variable state. */ 6308409a285SViacheslav Ovsiienko if (value == MLX5_ARG_UNSET) 6318409a285SViacheslav Ovsiienko unsetenv(MLX5_SHUT_UP_BF); 6328409a285SViacheslav Ovsiienko else 6338409a285SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1); 6348409a285SViacheslav Ovsiienko } 6358409a285SViacheslav Ovsiienko 636b9d86122SDekel Peled /** 63717e19bc4SViacheslav Ovsiienko * Allocate shared IB device context. If there is multiport device the 63817e19bc4SViacheslav Ovsiienko * master and representors will share this context, if there is single 63917e19bc4SViacheslav Ovsiienko * port dedicated IB device, the context will be used by only given 64017e19bc4SViacheslav Ovsiienko * port due to unification. 64117e19bc4SViacheslav Ovsiienko * 642ae4eb7dcSViacheslav Ovsiienko * Routine first searches the context for the specified IB device name, 64317e19bc4SViacheslav Ovsiienko * if found the shared context assumed and reference counter is incremented. 64417e19bc4SViacheslav Ovsiienko * If no context found the new one is created and initialized with specified 64517e19bc4SViacheslav Ovsiienko * IB device context and parameters. 64617e19bc4SViacheslav Ovsiienko * 64717e19bc4SViacheslav Ovsiienko * @param[in] spawn 64817e19bc4SViacheslav Ovsiienko * Pointer to the IB device attributes (name, port, etc). 6498409a285SViacheslav Ovsiienko * @param[in] config 6508409a285SViacheslav Ovsiienko * Pointer to device configuration structure. 65117e19bc4SViacheslav Ovsiienko * 65217e19bc4SViacheslav Ovsiienko * @return 65317e19bc4SViacheslav Ovsiienko * Pointer to mlx5_ibv_shared object on success, 65417e19bc4SViacheslav Ovsiienko * otherwise NULL and rte_errno is set. 65517e19bc4SViacheslav Ovsiienko */ 65617e19bc4SViacheslav Ovsiienko static struct mlx5_ibv_shared * 6578409a285SViacheslav Ovsiienko mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn, 6588409a285SViacheslav Ovsiienko const struct mlx5_dev_config *config) 65917e19bc4SViacheslav Ovsiienko { 66017e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *sh; 6618409a285SViacheslav Ovsiienko int dbmap_env; 66217e19bc4SViacheslav Ovsiienko int err = 0; 66353e5a82fSViacheslav Ovsiienko uint32_t i; 664ae18a1aeSOri Kam #ifdef HAVE_IBV_FLOW_DV_SUPPORT 665ae18a1aeSOri Kam struct mlx5_devx_tis_attr tis_attr = { 0 }; 666ae18a1aeSOri Kam #endif 66717e19bc4SViacheslav Ovsiienko 6688e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn); 66917e19bc4SViacheslav Ovsiienko /* Secondary process should not create the shared context. */ 6708e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 67117e19bc4SViacheslav Ovsiienko pthread_mutex_lock(&mlx5_ibv_list_mutex); 67217e19bc4SViacheslav Ovsiienko /* Search for IB context by device name. */ 67317e19bc4SViacheslav Ovsiienko LIST_FOREACH(sh, &mlx5_ibv_list, next) { 67417e19bc4SViacheslav Ovsiienko if (!strcmp(sh->ibdev_name, spawn->ibv_dev->name)) { 67517e19bc4SViacheslav Ovsiienko sh->refcnt++; 67617e19bc4SViacheslav Ovsiienko goto exit; 67717e19bc4SViacheslav Ovsiienko } 67817e19bc4SViacheslav Ovsiienko } 679ae4eb7dcSViacheslav Ovsiienko /* No device found, we have to create new shared context. */ 6808e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn->max_port); 68117e19bc4SViacheslav Ovsiienko sh = rte_zmalloc("ethdev shared ib context", 68217e19bc4SViacheslav Ovsiienko sizeof(struct mlx5_ibv_shared) + 68317e19bc4SViacheslav Ovsiienko spawn->max_port * 68417e19bc4SViacheslav Ovsiienko sizeof(struct mlx5_ibv_shared_port), 68517e19bc4SViacheslav Ovsiienko RTE_CACHE_LINE_SIZE); 68617e19bc4SViacheslav Ovsiienko if (!sh) { 68717e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "shared context allocation failure"); 68817e19bc4SViacheslav Ovsiienko rte_errno = ENOMEM; 68917e19bc4SViacheslav Ovsiienko goto exit; 69017e19bc4SViacheslav Ovsiienko } 6918409a285SViacheslav Ovsiienko /* 6928409a285SViacheslav Ovsiienko * Configure environment variable "MLX5_BF_SHUT_UP" 6938409a285SViacheslav Ovsiienko * before the device creation. The rdma_core library 6948409a285SViacheslav Ovsiienko * checks the variable at device creation and 6958409a285SViacheslav Ovsiienko * stores the result internally. 6968409a285SViacheslav Ovsiienko */ 6978409a285SViacheslav Ovsiienko dbmap_env = mlx5_config_doorbell_mapping_env(config); 69817e19bc4SViacheslav Ovsiienko /* Try to open IB device with DV first, then usual Verbs. */ 69917e19bc4SViacheslav Ovsiienko errno = 0; 70017e19bc4SViacheslav Ovsiienko sh->ctx = mlx5_glue->dv_open_device(spawn->ibv_dev); 70117e19bc4SViacheslav Ovsiienko if (sh->ctx) { 70217e19bc4SViacheslav Ovsiienko sh->devx = 1; 70317e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "DevX is supported"); 7048409a285SViacheslav Ovsiienko /* The device is created, no need for environment. */ 70506f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(dbmap_env); 70617e19bc4SViacheslav Ovsiienko } else { 7078409a285SViacheslav Ovsiienko /* The environment variable is still configured. */ 70817e19bc4SViacheslav Ovsiienko sh->ctx = mlx5_glue->open_device(spawn->ibv_dev); 70917e19bc4SViacheslav Ovsiienko err = errno ? errno : ENODEV; 7108409a285SViacheslav Ovsiienko /* 7118409a285SViacheslav Ovsiienko * The environment variable is not needed anymore, 7128409a285SViacheslav Ovsiienko * all device creation attempts are completed. 7138409a285SViacheslav Ovsiienko */ 71406f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(dbmap_env); 71506f78b5eSViacheslav Ovsiienko if (!sh->ctx) 71617e19bc4SViacheslav Ovsiienko goto error; 71717e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "DevX is NOT supported"); 71817e19bc4SViacheslav Ovsiienko } 71917e19bc4SViacheslav Ovsiienko err = mlx5_glue->query_device_ex(sh->ctx, NULL, &sh->device_attr); 72017e19bc4SViacheslav Ovsiienko if (err) { 72117e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "ibv_query_device_ex() failed"); 72217e19bc4SViacheslav Ovsiienko goto error; 72317e19bc4SViacheslav Ovsiienko } 72417e19bc4SViacheslav Ovsiienko sh->refcnt = 1; 72517e19bc4SViacheslav Ovsiienko sh->max_port = spawn->max_port; 72617e19bc4SViacheslav Ovsiienko strncpy(sh->ibdev_name, sh->ctx->device->name, 72717e19bc4SViacheslav Ovsiienko sizeof(sh->ibdev_name)); 72817e19bc4SViacheslav Ovsiienko strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path, 72917e19bc4SViacheslav Ovsiienko sizeof(sh->ibdev_path)); 73053e5a82fSViacheslav Ovsiienko pthread_mutex_init(&sh->intr_mutex, NULL); 73153e5a82fSViacheslav Ovsiienko /* 73253e5a82fSViacheslav Ovsiienko * Setting port_id to max unallowed value means 73353e5a82fSViacheslav Ovsiienko * there is no interrupt subhandler installed for 73453e5a82fSViacheslav Ovsiienko * the given port index i. 73553e5a82fSViacheslav Ovsiienko */ 73623242063SMatan Azrad for (i = 0; i < sh->max_port; i++) { 73753e5a82fSViacheslav Ovsiienko sh->port[i].ih_port_id = RTE_MAX_ETHPORTS; 73823242063SMatan Azrad sh->port[i].devx_ih_port_id = RTE_MAX_ETHPORTS; 73923242063SMatan Azrad } 74017e19bc4SViacheslav Ovsiienko sh->pd = mlx5_glue->alloc_pd(sh->ctx); 74117e19bc4SViacheslav Ovsiienko if (sh->pd == NULL) { 74217e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "PD allocation failure"); 74317e19bc4SViacheslav Ovsiienko err = ENOMEM; 74417e19bc4SViacheslav Ovsiienko goto error; 74517e19bc4SViacheslav Ovsiienko } 746b9d86122SDekel Peled #ifdef HAVE_IBV_FLOW_DV_SUPPORT 747ae18a1aeSOri Kam if (sh->devx) { 748b9d86122SDekel Peled err = mlx5_get_pdn(sh->pd, &sh->pdn); 749b9d86122SDekel Peled if (err) { 750b9d86122SDekel Peled DRV_LOG(ERR, "Fail to extract pdn from PD"); 751b9d86122SDekel Peled goto error; 752b9d86122SDekel Peled } 753ae18a1aeSOri Kam sh->td = mlx5_devx_cmd_create_td(sh->ctx); 754ae18a1aeSOri Kam if (!sh->td) { 755ae18a1aeSOri Kam DRV_LOG(ERR, "TD allocation failure"); 756ae18a1aeSOri Kam err = ENOMEM; 757ae18a1aeSOri Kam goto error; 758ae18a1aeSOri Kam } 759ae18a1aeSOri Kam tis_attr.transport_domain = sh->td->id; 760ae18a1aeSOri Kam sh->tis = mlx5_devx_cmd_create_tis(sh->ctx, &tis_attr); 761ae18a1aeSOri Kam if (!sh->tis) { 762ae18a1aeSOri Kam DRV_LOG(ERR, "TIS allocation failure"); 763ae18a1aeSOri Kam err = ENOMEM; 764ae18a1aeSOri Kam goto error; 765ae18a1aeSOri Kam } 766ae18a1aeSOri Kam } 7670136df99SSuanming Mou sh->flow_id_pool = mlx5_flow_id_pool_alloc 7680136df99SSuanming Mou ((1 << HAIRPIN_FLOW_ID_BITS) - 1); 769d85c7b5eSOri Kam if (!sh->flow_id_pool) { 770d85c7b5eSOri Kam DRV_LOG(ERR, "can't create flow id pool"); 771d85c7b5eSOri Kam err = ENOMEM; 772d85c7b5eSOri Kam goto error; 773d85c7b5eSOri Kam } 774b9d86122SDekel Peled #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 775ab3cffcfSViacheslav Ovsiienko /* 776ab3cffcfSViacheslav Ovsiienko * Once the device is added to the list of memory event 777ab3cffcfSViacheslav Ovsiienko * callback, its global MR cache table cannot be expanded 778ab3cffcfSViacheslav Ovsiienko * on the fly because of deadlock. If it overflows, lookup 779ab3cffcfSViacheslav Ovsiienko * should be done by searching MR list linearly, which is slow. 780ab3cffcfSViacheslav Ovsiienko * 781ab3cffcfSViacheslav Ovsiienko * At this point the device is not added to the memory 782ab3cffcfSViacheslav Ovsiienko * event list yet, context is just being created. 783ab3cffcfSViacheslav Ovsiienko */ 784b8dc6b0eSVu Pham err = mlx5_mr_btree_init(&sh->share_cache.cache, 785ab3cffcfSViacheslav Ovsiienko MLX5_MR_BTREE_CACHE_N * 2, 78646e10a4cSViacheslav Ovsiienko spawn->pci_dev->device.numa_node); 787ab3cffcfSViacheslav Ovsiienko if (err) { 788ab3cffcfSViacheslav Ovsiienko err = rte_errno; 789ab3cffcfSViacheslav Ovsiienko goto error; 790ab3cffcfSViacheslav Ovsiienko } 7915382d28cSMatan Azrad mlx5_flow_counters_mng_init(sh); 792b88341caSSuanming Mou mlx5_flow_ipool_create(sh, config); 7930e3d0525SViacheslav Ovsiienko /* Add device to memory callback list. */ 7940e3d0525SViacheslav Ovsiienko rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 7950e3d0525SViacheslav Ovsiienko LIST_INSERT_HEAD(&mlx5_shared_data->mem_event_cb_list, 7960e3d0525SViacheslav Ovsiienko sh, mem_event_cb); 7970e3d0525SViacheslav Ovsiienko rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 7980e3d0525SViacheslav Ovsiienko /* Add context to the global device list. */ 79917e19bc4SViacheslav Ovsiienko LIST_INSERT_HEAD(&mlx5_ibv_list, sh, next); 80017e19bc4SViacheslav Ovsiienko exit: 80117e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 80217e19bc4SViacheslav Ovsiienko return sh; 80317e19bc4SViacheslav Ovsiienko error: 80417e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 8058e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 806ae18a1aeSOri Kam if (sh->tis) 807ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 808ae18a1aeSOri Kam if (sh->td) 809ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->td)); 81017e19bc4SViacheslav Ovsiienko if (sh->pd) 81117e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 81217e19bc4SViacheslav Ovsiienko if (sh->ctx) 81317e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->close_device(sh->ctx)); 814d85c7b5eSOri Kam if (sh->flow_id_pool) 815d85c7b5eSOri Kam mlx5_flow_id_pool_release(sh->flow_id_pool); 81617e19bc4SViacheslav Ovsiienko rte_free(sh); 8178e46d4e1SAlexander Kozyrev MLX5_ASSERT(err > 0); 81817e19bc4SViacheslav Ovsiienko rte_errno = err; 81917e19bc4SViacheslav Ovsiienko return NULL; 82017e19bc4SViacheslav Ovsiienko } 82117e19bc4SViacheslav Ovsiienko 82217e19bc4SViacheslav Ovsiienko /** 82317e19bc4SViacheslav Ovsiienko * Free shared IB device context. Decrement counter and if zero free 82417e19bc4SViacheslav Ovsiienko * all allocated resources and close handles. 82517e19bc4SViacheslav Ovsiienko * 82617e19bc4SViacheslav Ovsiienko * @param[in] sh 82717e19bc4SViacheslav Ovsiienko * Pointer to mlx5_ibv_shared object to free 82817e19bc4SViacheslav Ovsiienko */ 82917e19bc4SViacheslav Ovsiienko static void 83017e19bc4SViacheslav Ovsiienko mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh) 83117e19bc4SViacheslav Ovsiienko { 83217e19bc4SViacheslav Ovsiienko pthread_mutex_lock(&mlx5_ibv_list_mutex); 8330afacb04SAlexander Kozyrev #ifdef RTE_LIBRTE_MLX5_DEBUG 83417e19bc4SViacheslav Ovsiienko /* Check the object presence in the list. */ 83517e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *lctx; 83617e19bc4SViacheslav Ovsiienko 83717e19bc4SViacheslav Ovsiienko LIST_FOREACH(lctx, &mlx5_ibv_list, next) 83817e19bc4SViacheslav Ovsiienko if (lctx == sh) 83917e19bc4SViacheslav Ovsiienko break; 8408e46d4e1SAlexander Kozyrev MLX5_ASSERT(lctx); 84117e19bc4SViacheslav Ovsiienko if (lctx != sh) { 84217e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "Freeing non-existing shared IB context"); 84317e19bc4SViacheslav Ovsiienko goto exit; 84417e19bc4SViacheslav Ovsiienko } 84517e19bc4SViacheslav Ovsiienko #endif 8468e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 8478e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh->refcnt); 84817e19bc4SViacheslav Ovsiienko /* Secondary process should not free the shared context. */ 8498e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 85017e19bc4SViacheslav Ovsiienko if (--sh->refcnt) 85117e19bc4SViacheslav Ovsiienko goto exit; 8520e3d0525SViacheslav Ovsiienko /* Remove from memory callback device list. */ 8530e3d0525SViacheslav Ovsiienko rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 8540e3d0525SViacheslav Ovsiienko LIST_REMOVE(sh, mem_event_cb); 8550e3d0525SViacheslav Ovsiienko rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 8564f8e6befSMichael Baum /* Release created Memory Regions. */ 857b8dc6b0eSVu Pham mlx5_mr_release_cache(&sh->share_cache); 8580e3d0525SViacheslav Ovsiienko /* Remove context from the global device list. */ 85917e19bc4SViacheslav Ovsiienko LIST_REMOVE(sh, next); 86053e5a82fSViacheslav Ovsiienko /* 86153e5a82fSViacheslav Ovsiienko * Ensure there is no async event handler installed. 86253e5a82fSViacheslav Ovsiienko * Only primary process handles async device events. 86353e5a82fSViacheslav Ovsiienko **/ 8645382d28cSMatan Azrad mlx5_flow_counters_mng_close(sh); 865014d1cbeSSuanming Mou mlx5_flow_ipool_destroy(sh); 8668e46d4e1SAlexander Kozyrev MLX5_ASSERT(!sh->intr_cnt); 86753e5a82fSViacheslav Ovsiienko if (sh->intr_cnt) 8685897ac13SViacheslav Ovsiienko mlx5_intr_callback_unregister 86953e5a82fSViacheslav Ovsiienko (&sh->intr_handle, mlx5_dev_interrupt_handler, sh); 87023242063SMatan Azrad #ifdef HAVE_MLX5_DEVX_ASYNC_SUPPORT 87123242063SMatan Azrad if (sh->devx_intr_cnt) { 87223242063SMatan Azrad if (sh->intr_handle_devx.fd) 87323242063SMatan Azrad rte_intr_callback_unregister(&sh->intr_handle_devx, 87423242063SMatan Azrad mlx5_dev_interrupt_handler_devx, sh); 87523242063SMatan Azrad if (sh->devx_comp) 87623242063SMatan Azrad mlx5dv_devx_destroy_cmd_comp(sh->devx_comp); 87723242063SMatan Azrad } 87823242063SMatan Azrad #endif 87953e5a82fSViacheslav Ovsiienko pthread_mutex_destroy(&sh->intr_mutex); 88017e19bc4SViacheslav Ovsiienko if (sh->pd) 88117e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 882ae18a1aeSOri Kam if (sh->tis) 883ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 884ae18a1aeSOri Kam if (sh->td) 885ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->td)); 88617e19bc4SViacheslav Ovsiienko if (sh->ctx) 88717e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->close_device(sh->ctx)); 888d85c7b5eSOri Kam if (sh->flow_id_pool) 889d85c7b5eSOri Kam mlx5_flow_id_pool_release(sh->flow_id_pool); 89017e19bc4SViacheslav Ovsiienko rte_free(sh); 89117e19bc4SViacheslav Ovsiienko exit: 89217e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 89317e19bc4SViacheslav Ovsiienko } 89417e19bc4SViacheslav Ovsiienko 895771fa900SAdrien Mazarguil /** 89654534725SMatan Azrad * Destroy table hash list and all the root entries per domain. 89754534725SMatan Azrad * 89854534725SMatan Azrad * @param[in] priv 89954534725SMatan Azrad * Pointer to the private device data structure. 90054534725SMatan Azrad */ 90154534725SMatan Azrad static void 90254534725SMatan Azrad mlx5_free_table_hash_list(struct mlx5_priv *priv) 90354534725SMatan Azrad { 90454534725SMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 90554534725SMatan Azrad struct mlx5_flow_tbl_data_entry *tbl_data; 90654534725SMatan Azrad union mlx5_flow_tbl_key table_key = { 90754534725SMatan Azrad { 90854534725SMatan Azrad .table_id = 0, 90954534725SMatan Azrad .reserved = 0, 91054534725SMatan Azrad .domain = 0, 91154534725SMatan Azrad .direction = 0, 91254534725SMatan Azrad } 91354534725SMatan Azrad }; 91454534725SMatan Azrad struct mlx5_hlist_entry *pos; 91554534725SMatan Azrad 91654534725SMatan Azrad if (!sh->flow_tbls) 91754534725SMatan Azrad return; 91854534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 91954534725SMatan Azrad if (pos) { 92054534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 92154534725SMatan Azrad entry); 9228e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 92354534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 92454534725SMatan Azrad rte_free(tbl_data); 92554534725SMatan Azrad } 92654534725SMatan Azrad table_key.direction = 1; 92754534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 92854534725SMatan Azrad if (pos) { 92954534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 93054534725SMatan Azrad entry); 9318e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 93254534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 93354534725SMatan Azrad rte_free(tbl_data); 93454534725SMatan Azrad } 93554534725SMatan Azrad table_key.direction = 0; 93654534725SMatan Azrad table_key.domain = 1; 93754534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 93854534725SMatan Azrad if (pos) { 93954534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 94054534725SMatan Azrad entry); 9418e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 94254534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 94354534725SMatan Azrad rte_free(tbl_data); 94454534725SMatan Azrad } 94554534725SMatan Azrad mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL); 94654534725SMatan Azrad } 94754534725SMatan Azrad 94854534725SMatan Azrad /** 94954534725SMatan Azrad * Initialize flow table hash list and create the root tables entry 95054534725SMatan Azrad * for each domain. 95154534725SMatan Azrad * 95254534725SMatan Azrad * @param[in] priv 95354534725SMatan Azrad * Pointer to the private device data structure. 95454534725SMatan Azrad * 95554534725SMatan Azrad * @return 95654534725SMatan Azrad * Zero on success, positive error code otherwise. 95754534725SMatan Azrad */ 95854534725SMatan Azrad static int 95954534725SMatan Azrad mlx5_alloc_table_hash_list(struct mlx5_priv *priv) 96054534725SMatan Azrad { 96154534725SMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 96254534725SMatan Azrad char s[MLX5_HLIST_NAMESIZE]; 96354534725SMatan Azrad int err = 0; 96454534725SMatan Azrad 9658e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 96654534725SMatan Azrad snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name); 96754534725SMatan Azrad sh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE); 96854534725SMatan Azrad if (!sh->flow_tbls) { 96954534725SMatan Azrad DRV_LOG(ERR, "flow tables with hash creation failed.\n"); 97054534725SMatan Azrad err = ENOMEM; 97154534725SMatan Azrad return err; 97254534725SMatan Azrad } 97354534725SMatan Azrad #ifndef HAVE_MLX5DV_DR 97454534725SMatan Azrad /* 97554534725SMatan Azrad * In case we have not DR support, the zero tables should be created 97654534725SMatan Azrad * because DV expect to see them even if they cannot be created by 97754534725SMatan Azrad * RDMA-CORE. 97854534725SMatan Azrad */ 97954534725SMatan Azrad union mlx5_flow_tbl_key table_key = { 98054534725SMatan Azrad { 98154534725SMatan Azrad .table_id = 0, 98254534725SMatan Azrad .reserved = 0, 98354534725SMatan Azrad .domain = 0, 98454534725SMatan Azrad .direction = 0, 98554534725SMatan Azrad } 98654534725SMatan Azrad }; 98754534725SMatan Azrad struct mlx5_flow_tbl_data_entry *tbl_data = rte_zmalloc(NULL, 98854534725SMatan Azrad sizeof(*tbl_data), 0); 98954534725SMatan Azrad 99054534725SMatan Azrad if (!tbl_data) { 99154534725SMatan Azrad err = ENOMEM; 99254534725SMatan Azrad goto error; 99354534725SMatan Azrad } 99454534725SMatan Azrad tbl_data->entry.key = table_key.v64; 99554534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 99654534725SMatan Azrad if (err) 99754534725SMatan Azrad goto error; 99854534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 99954534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 100054534725SMatan Azrad table_key.direction = 1; 100154534725SMatan Azrad tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0); 100254534725SMatan Azrad if (!tbl_data) { 100354534725SMatan Azrad err = ENOMEM; 100454534725SMatan Azrad goto error; 100554534725SMatan Azrad } 100654534725SMatan Azrad tbl_data->entry.key = table_key.v64; 100754534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 100854534725SMatan Azrad if (err) 100954534725SMatan Azrad goto error; 101054534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 101154534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 101254534725SMatan Azrad table_key.direction = 0; 101354534725SMatan Azrad table_key.domain = 1; 101454534725SMatan Azrad tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0); 101554534725SMatan Azrad if (!tbl_data) { 101654534725SMatan Azrad err = ENOMEM; 101754534725SMatan Azrad goto error; 101854534725SMatan Azrad } 101954534725SMatan Azrad tbl_data->entry.key = table_key.v64; 102054534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 102154534725SMatan Azrad if (err) 102254534725SMatan Azrad goto error; 102354534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 102454534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 102554534725SMatan Azrad return err; 102654534725SMatan Azrad error: 102754534725SMatan Azrad mlx5_free_table_hash_list(priv); 102854534725SMatan Azrad #endif /* HAVE_MLX5DV_DR */ 102954534725SMatan Azrad return err; 103054534725SMatan Azrad } 103154534725SMatan Azrad 103254534725SMatan Azrad /** 1033b2177648SViacheslav Ovsiienko * Initialize DR related data within private structure. 1034b2177648SViacheslav Ovsiienko * Routine checks the reference counter and does actual 1035ae4eb7dcSViacheslav Ovsiienko * resources creation/initialization only if counter is zero. 1036b2177648SViacheslav Ovsiienko * 1037b2177648SViacheslav Ovsiienko * @param[in] priv 1038b2177648SViacheslav Ovsiienko * Pointer to the private device data structure. 1039b2177648SViacheslav Ovsiienko * 1040b2177648SViacheslav Ovsiienko * @return 1041b2177648SViacheslav Ovsiienko * Zero on success, positive error code otherwise. 1042b2177648SViacheslav Ovsiienko */ 1043b2177648SViacheslav Ovsiienko static int 1044b2177648SViacheslav Ovsiienko mlx5_alloc_shared_dr(struct mlx5_priv *priv) 1045b2177648SViacheslav Ovsiienko { 10461ef4cdefSMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 10471ef4cdefSMatan Azrad char s[MLX5_HLIST_NAMESIZE]; 104868011166SXiaoyu Min int err = 0; 104954534725SMatan Azrad 105068011166SXiaoyu Min if (!sh->flow_tbls) 105168011166SXiaoyu Min err = mlx5_alloc_table_hash_list(priv); 105268011166SXiaoyu Min else 105368011166SXiaoyu Min DRV_LOG(DEBUG, "sh->flow_tbls[%p] already created, reuse\n", 105468011166SXiaoyu Min (void *)sh->flow_tbls); 105554534725SMatan Azrad if (err) 105654534725SMatan Azrad return err; 10571ef4cdefSMatan Azrad /* Create tags hash list table. */ 10581ef4cdefSMatan Azrad snprintf(s, sizeof(s), "%s_tags", sh->ibdev_name); 10591ef4cdefSMatan Azrad sh->tag_table = mlx5_hlist_create(s, MLX5_TAGS_HLIST_ARRAY_SIZE); 10601ef4cdefSMatan Azrad if (!sh->tag_table) { 10611ef4cdefSMatan Azrad DRV_LOG(ERR, "tags with hash creation failed.\n"); 10621ef4cdefSMatan Azrad err = ENOMEM; 10631ef4cdefSMatan Azrad goto error; 10641ef4cdefSMatan Azrad } 1065b2177648SViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR 106654534725SMatan Azrad void *domain; 1067b2177648SViacheslav Ovsiienko 1068b2177648SViacheslav Ovsiienko if (sh->dv_refcnt) { 1069b2177648SViacheslav Ovsiienko /* Shared DV/DR structures is already initialized. */ 1070b2177648SViacheslav Ovsiienko sh->dv_refcnt++; 1071b2177648SViacheslav Ovsiienko priv->dr_shared = 1; 1072b2177648SViacheslav Ovsiienko return 0; 1073b2177648SViacheslav Ovsiienko } 1074b2177648SViacheslav Ovsiienko /* Reference counter is zero, we should initialize structures. */ 1075d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain(sh->ctx, 1076d1e64fbfSOri Kam MLX5DV_DR_DOMAIN_TYPE_NIC_RX); 1077d1e64fbfSOri Kam if (!domain) { 1078d1e64fbfSOri Kam DRV_LOG(ERR, "ingress mlx5dv_dr_create_domain failed"); 1079b2177648SViacheslav Ovsiienko err = errno; 1080b2177648SViacheslav Ovsiienko goto error; 1081b2177648SViacheslav Ovsiienko } 1082d1e64fbfSOri Kam sh->rx_domain = domain; 1083d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain(sh->ctx, 1084d1e64fbfSOri Kam MLX5DV_DR_DOMAIN_TYPE_NIC_TX); 1085d1e64fbfSOri Kam if (!domain) { 1086d1e64fbfSOri Kam DRV_LOG(ERR, "egress mlx5dv_dr_create_domain failed"); 1087b2177648SViacheslav Ovsiienko err = errno; 1088b2177648SViacheslav Ovsiienko goto error; 1089b2177648SViacheslav Ovsiienko } 109079e35d0dSViacheslav Ovsiienko pthread_mutex_init(&sh->dv_mutex, NULL); 1091d1e64fbfSOri Kam sh->tx_domain = domain; 1092e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 1093e2b4925eSOri Kam if (priv->config.dv_esw_en) { 1094d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain 1095d1e64fbfSOri Kam (sh->ctx, MLX5DV_DR_DOMAIN_TYPE_FDB); 1096d1e64fbfSOri Kam if (!domain) { 1097d1e64fbfSOri Kam DRV_LOG(ERR, "FDB mlx5dv_dr_create_domain failed"); 1098e2b4925eSOri Kam err = errno; 1099e2b4925eSOri Kam goto error; 1100e2b4925eSOri Kam } 1101d1e64fbfSOri Kam sh->fdb_domain = domain; 110234fa7c02SOri Kam sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop(); 1103e2b4925eSOri Kam } 1104e2b4925eSOri Kam #endif 1105b41e47daSMoti Haimovsky sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan(); 11061ef4cdefSMatan Azrad #endif /* HAVE_MLX5DV_DR */ 1107b2177648SViacheslav Ovsiienko sh->dv_refcnt++; 1108b2177648SViacheslav Ovsiienko priv->dr_shared = 1; 1109b2177648SViacheslav Ovsiienko return 0; 1110b2177648SViacheslav Ovsiienko error: 1111b2177648SViacheslav Ovsiienko /* Rollback the created objects. */ 1112d1e64fbfSOri Kam if (sh->rx_domain) { 1113d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->rx_domain); 1114d1e64fbfSOri Kam sh->rx_domain = NULL; 1115b2177648SViacheslav Ovsiienko } 1116d1e64fbfSOri Kam if (sh->tx_domain) { 1117d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->tx_domain); 1118d1e64fbfSOri Kam sh->tx_domain = NULL; 1119b2177648SViacheslav Ovsiienko } 1120d1e64fbfSOri Kam if (sh->fdb_domain) { 1121d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->fdb_domain); 1122d1e64fbfSOri Kam sh->fdb_domain = NULL; 1123e2b4925eSOri Kam } 112434fa7c02SOri Kam if (sh->esw_drop_action) { 112534fa7c02SOri Kam mlx5_glue->destroy_flow_action(sh->esw_drop_action); 112634fa7c02SOri Kam sh->esw_drop_action = NULL; 112734fa7c02SOri Kam } 1128b41e47daSMoti Haimovsky if (sh->pop_vlan_action) { 1129b41e47daSMoti Haimovsky mlx5_glue->destroy_flow_action(sh->pop_vlan_action); 1130b41e47daSMoti Haimovsky sh->pop_vlan_action = NULL; 1131b41e47daSMoti Haimovsky } 11321ef4cdefSMatan Azrad if (sh->tag_table) { 11331ef4cdefSMatan Azrad /* tags should be destroyed with flow before. */ 11341ef4cdefSMatan Azrad mlx5_hlist_destroy(sh->tag_table, NULL, NULL); 11351ef4cdefSMatan Azrad sh->tag_table = NULL; 11361ef4cdefSMatan Azrad } 113754534725SMatan Azrad mlx5_free_table_hash_list(priv); 113854534725SMatan Azrad return err; 1139b2177648SViacheslav Ovsiienko } 1140b2177648SViacheslav Ovsiienko 1141b2177648SViacheslav Ovsiienko /** 1142b2177648SViacheslav Ovsiienko * Destroy DR related data within private structure. 1143b2177648SViacheslav Ovsiienko * 1144b2177648SViacheslav Ovsiienko * @param[in] priv 1145b2177648SViacheslav Ovsiienko * Pointer to the private device data structure. 1146b2177648SViacheslav Ovsiienko */ 1147b2177648SViacheslav Ovsiienko static void 1148b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(struct mlx5_priv *priv) 1149b2177648SViacheslav Ovsiienko { 1150b2177648SViacheslav Ovsiienko struct mlx5_ibv_shared *sh; 1151b2177648SViacheslav Ovsiienko 1152b2177648SViacheslav Ovsiienko if (!priv->dr_shared) 1153b2177648SViacheslav Ovsiienko return; 1154b2177648SViacheslav Ovsiienko priv->dr_shared = 0; 1155b2177648SViacheslav Ovsiienko sh = priv->sh; 11568e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 11571ef4cdefSMatan Azrad #ifdef HAVE_MLX5DV_DR 11588e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh->dv_refcnt); 1159b2177648SViacheslav Ovsiienko if (sh->dv_refcnt && --sh->dv_refcnt) 1160b2177648SViacheslav Ovsiienko return; 1161d1e64fbfSOri Kam if (sh->rx_domain) { 1162d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->rx_domain); 1163d1e64fbfSOri Kam sh->rx_domain = NULL; 1164b2177648SViacheslav Ovsiienko } 1165d1e64fbfSOri Kam if (sh->tx_domain) { 1166d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->tx_domain); 1167d1e64fbfSOri Kam sh->tx_domain = NULL; 1168b2177648SViacheslav Ovsiienko } 1169e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 1170d1e64fbfSOri Kam if (sh->fdb_domain) { 1171d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->fdb_domain); 1172d1e64fbfSOri Kam sh->fdb_domain = NULL; 1173e2b4925eSOri Kam } 117434fa7c02SOri Kam if (sh->esw_drop_action) { 117534fa7c02SOri Kam mlx5_glue->destroy_flow_action(sh->esw_drop_action); 117634fa7c02SOri Kam sh->esw_drop_action = NULL; 117734fa7c02SOri Kam } 1178e2b4925eSOri Kam #endif 1179b41e47daSMoti Haimovsky if (sh->pop_vlan_action) { 1180b41e47daSMoti Haimovsky mlx5_glue->destroy_flow_action(sh->pop_vlan_action); 1181b41e47daSMoti Haimovsky sh->pop_vlan_action = NULL; 1182b41e47daSMoti Haimovsky } 118379e35d0dSViacheslav Ovsiienko pthread_mutex_destroy(&sh->dv_mutex); 118454534725SMatan Azrad #endif /* HAVE_MLX5DV_DR */ 11851ef4cdefSMatan Azrad if (sh->tag_table) { 11861ef4cdefSMatan Azrad /* tags should be destroyed with flow before. */ 11871ef4cdefSMatan Azrad mlx5_hlist_destroy(sh->tag_table, NULL, NULL); 11881ef4cdefSMatan Azrad sh->tag_table = NULL; 11891ef4cdefSMatan Azrad } 119054534725SMatan Azrad mlx5_free_table_hash_list(priv); 1191b2177648SViacheslav Ovsiienko } 1192b2177648SViacheslav Ovsiienko 1193b2177648SViacheslav Ovsiienko /** 11947be600c8SYongseok Koh * Initialize shared data between primary and secondary process. 11957be600c8SYongseok Koh * 11967be600c8SYongseok Koh * A memzone is reserved by primary process and secondary processes attach to 11977be600c8SYongseok Koh * the memzone. 11987be600c8SYongseok Koh * 11997be600c8SYongseok Koh * @return 12007be600c8SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 1201974f1e7eSYongseok Koh */ 12027be600c8SYongseok Koh static int 12037be600c8SYongseok Koh mlx5_init_shared_data(void) 1204974f1e7eSYongseok Koh { 1205974f1e7eSYongseok Koh const struct rte_memzone *mz; 12067be600c8SYongseok Koh int ret = 0; 1207974f1e7eSYongseok Koh 1208974f1e7eSYongseok Koh rte_spinlock_lock(&mlx5_shared_data_lock); 1209974f1e7eSYongseok Koh if (mlx5_shared_data == NULL) { 1210974f1e7eSYongseok Koh if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 1211974f1e7eSYongseok Koh /* Allocate shared memory. */ 1212974f1e7eSYongseok Koh mz = rte_memzone_reserve(MZ_MLX5_PMD_SHARED_DATA, 1213974f1e7eSYongseok Koh sizeof(*mlx5_shared_data), 1214974f1e7eSYongseok Koh SOCKET_ID_ANY, 0); 12157be600c8SYongseok Koh if (mz == NULL) { 12167be600c8SYongseok Koh DRV_LOG(ERR, 121706fa6988SDekel Peled "Cannot allocate mlx5 shared data"); 12187be600c8SYongseok Koh ret = -rte_errno; 12197be600c8SYongseok Koh goto error; 12207be600c8SYongseok Koh } 12217be600c8SYongseok Koh mlx5_shared_data = mz->addr; 12227be600c8SYongseok Koh memset(mlx5_shared_data, 0, sizeof(*mlx5_shared_data)); 12237be600c8SYongseok Koh rte_spinlock_init(&mlx5_shared_data->lock); 1224974f1e7eSYongseok Koh } else { 1225974f1e7eSYongseok Koh /* Lookup allocated shared memory. */ 1226974f1e7eSYongseok Koh mz = rte_memzone_lookup(MZ_MLX5_PMD_SHARED_DATA); 12277be600c8SYongseok Koh if (mz == NULL) { 12287be600c8SYongseok Koh DRV_LOG(ERR, 122906fa6988SDekel Peled "Cannot attach mlx5 shared data"); 12307be600c8SYongseok Koh ret = -rte_errno; 12317be600c8SYongseok Koh goto error; 1232974f1e7eSYongseok Koh } 1233974f1e7eSYongseok Koh mlx5_shared_data = mz->addr; 12347be600c8SYongseok Koh memset(&mlx5_local_data, 0, sizeof(mlx5_local_data)); 12353ebe6580SYongseok Koh } 1236974f1e7eSYongseok Koh } 12377be600c8SYongseok Koh error: 12387be600c8SYongseok Koh rte_spinlock_unlock(&mlx5_shared_data_lock); 12397be600c8SYongseok Koh return ret; 12407be600c8SYongseok Koh } 12417be600c8SYongseok Koh 12427be600c8SYongseok Koh /** 12434d803a72SOlga Shern * Retrieve integer value from environment variable. 12444d803a72SOlga Shern * 12454d803a72SOlga Shern * @param[in] name 12464d803a72SOlga Shern * Environment variable name. 12474d803a72SOlga Shern * 12484d803a72SOlga Shern * @return 12494d803a72SOlga Shern * Integer value, 0 if the variable is not set. 12504d803a72SOlga Shern */ 12514d803a72SOlga Shern int 12524d803a72SOlga Shern mlx5_getenv_int(const char *name) 12534d803a72SOlga Shern { 12544d803a72SOlga Shern const char *val = getenv(name); 12554d803a72SOlga Shern 12564d803a72SOlga Shern if (val == NULL) 12574d803a72SOlga Shern return 0; 12584d803a72SOlga Shern return atoi(val); 12594d803a72SOlga Shern } 12604d803a72SOlga Shern 12614d803a72SOlga Shern /** 12621e3a39f7SXueming Li * Verbs callback to allocate a memory. This function should allocate the space 12631e3a39f7SXueming Li * according to the size provided residing inside a huge page. 12641e3a39f7SXueming Li * Please note that all allocation must respect the alignment from libmlx5 12651e3a39f7SXueming Li * (i.e. currently sysconf(_SC_PAGESIZE)). 12661e3a39f7SXueming Li * 12671e3a39f7SXueming Li * @param[in] size 12681e3a39f7SXueming Li * The size in bytes of the memory to allocate. 12691e3a39f7SXueming Li * @param[in] data 12701e3a39f7SXueming Li * A pointer to the callback data. 12711e3a39f7SXueming Li * 12721e3a39f7SXueming Li * @return 1273a6d83b6aSNélio Laranjeiro * Allocated buffer, NULL otherwise and rte_errno is set. 12741e3a39f7SXueming Li */ 12751e3a39f7SXueming Li static void * 12761e3a39f7SXueming Li mlx5_alloc_verbs_buf(size_t size, void *data) 12771e3a39f7SXueming Li { 1278dbeba4cfSThomas Monjalon struct mlx5_priv *priv = data; 12791e3a39f7SXueming Li void *ret; 12801e3a39f7SXueming Li size_t alignment = sysconf(_SC_PAGESIZE); 1281d10b09dbSOlivier Matz unsigned int socket = SOCKET_ID_ANY; 12821e3a39f7SXueming Li 1283d10b09dbSOlivier Matz if (priv->verbs_alloc_ctx.type == MLX5_VERBS_ALLOC_TYPE_TX_QUEUE) { 1284d10b09dbSOlivier Matz const struct mlx5_txq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 1285d10b09dbSOlivier Matz 1286d10b09dbSOlivier Matz socket = ctrl->socket; 1287d10b09dbSOlivier Matz } else if (priv->verbs_alloc_ctx.type == 1288d10b09dbSOlivier Matz MLX5_VERBS_ALLOC_TYPE_RX_QUEUE) { 1289d10b09dbSOlivier Matz const struct mlx5_rxq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 1290d10b09dbSOlivier Matz 1291d10b09dbSOlivier Matz socket = ctrl->socket; 1292d10b09dbSOlivier Matz } 12938e46d4e1SAlexander Kozyrev MLX5_ASSERT(data != NULL); 1294d10b09dbSOlivier Matz ret = rte_malloc_socket(__func__, size, alignment, socket); 1295a6d83b6aSNélio Laranjeiro if (!ret && size) 1296a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 12971e3a39f7SXueming Li return ret; 12981e3a39f7SXueming Li } 12991e3a39f7SXueming Li 13001e3a39f7SXueming Li /** 13011e3a39f7SXueming Li * Verbs callback to free a memory. 13021e3a39f7SXueming Li * 13031e3a39f7SXueming Li * @param[in] ptr 13041e3a39f7SXueming Li * A pointer to the memory to free. 13051e3a39f7SXueming Li * @param[in] data 13061e3a39f7SXueming Li * A pointer to the callback data. 13071e3a39f7SXueming Li */ 13081e3a39f7SXueming Li static void 13091e3a39f7SXueming Li mlx5_free_verbs_buf(void *ptr, void *data __rte_unused) 13101e3a39f7SXueming Li { 13118e46d4e1SAlexander Kozyrev MLX5_ASSERT(data != NULL); 13121e3a39f7SXueming Li rte_free(ptr); 13131e3a39f7SXueming Li } 13141e3a39f7SXueming Li 13151e3a39f7SXueming Li /** 1316c9ba7523SRaslan Darawsheh * DPDK callback to add udp tunnel port 1317c9ba7523SRaslan Darawsheh * 1318c9ba7523SRaslan Darawsheh * @param[in] dev 1319c9ba7523SRaslan Darawsheh * A pointer to eth_dev 1320c9ba7523SRaslan Darawsheh * @param[in] udp_tunnel 1321c9ba7523SRaslan Darawsheh * A pointer to udp tunnel 1322c9ba7523SRaslan Darawsheh * 1323c9ba7523SRaslan Darawsheh * @return 1324c9ba7523SRaslan Darawsheh * 0 on valid udp ports and tunnels, -ENOTSUP otherwise. 1325c9ba7523SRaslan Darawsheh */ 1326c9ba7523SRaslan Darawsheh int 1327c9ba7523SRaslan Darawsheh mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev __rte_unused, 1328c9ba7523SRaslan Darawsheh struct rte_eth_udp_tunnel *udp_tunnel) 1329c9ba7523SRaslan Darawsheh { 13308e46d4e1SAlexander Kozyrev MLX5_ASSERT(udp_tunnel != NULL); 1331c9ba7523SRaslan Darawsheh if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN && 1332c9ba7523SRaslan Darawsheh udp_tunnel->udp_port == 4789) 1333c9ba7523SRaslan Darawsheh return 0; 1334c9ba7523SRaslan Darawsheh if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN_GPE && 1335c9ba7523SRaslan Darawsheh udp_tunnel->udp_port == 4790) 1336c9ba7523SRaslan Darawsheh return 0; 1337c9ba7523SRaslan Darawsheh return -ENOTSUP; 1338c9ba7523SRaslan Darawsheh } 1339c9ba7523SRaslan Darawsheh 1340c9ba7523SRaslan Darawsheh /** 1341120dc4a7SYongseok Koh * Initialize process private data structure. 1342120dc4a7SYongseok Koh * 1343120dc4a7SYongseok Koh * @param dev 1344120dc4a7SYongseok Koh * Pointer to Ethernet device structure. 1345120dc4a7SYongseok Koh * 1346120dc4a7SYongseok Koh * @return 1347120dc4a7SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 1348120dc4a7SYongseok Koh */ 1349120dc4a7SYongseok Koh int 1350120dc4a7SYongseok Koh mlx5_proc_priv_init(struct rte_eth_dev *dev) 1351120dc4a7SYongseok Koh { 1352120dc4a7SYongseok Koh struct mlx5_priv *priv = dev->data->dev_private; 1353120dc4a7SYongseok Koh struct mlx5_proc_priv *ppriv; 1354120dc4a7SYongseok Koh size_t ppriv_size; 1355120dc4a7SYongseok Koh 1356120dc4a7SYongseok Koh /* 1357120dc4a7SYongseok Koh * UAR register table follows the process private structure. BlueFlame 1358120dc4a7SYongseok Koh * registers for Tx queues are stored in the table. 1359120dc4a7SYongseok Koh */ 1360120dc4a7SYongseok Koh ppriv_size = 1361120dc4a7SYongseok Koh sizeof(struct mlx5_proc_priv) + priv->txqs_n * sizeof(void *); 1362120dc4a7SYongseok Koh ppriv = rte_malloc_socket("mlx5_proc_priv", ppriv_size, 1363120dc4a7SYongseok Koh RTE_CACHE_LINE_SIZE, dev->device->numa_node); 1364120dc4a7SYongseok Koh if (!ppriv) { 1365120dc4a7SYongseok Koh rte_errno = ENOMEM; 1366120dc4a7SYongseok Koh return -rte_errno; 1367120dc4a7SYongseok Koh } 1368120dc4a7SYongseok Koh ppriv->uar_table_sz = ppriv_size; 1369120dc4a7SYongseok Koh dev->process_private = ppriv; 1370120dc4a7SYongseok Koh return 0; 1371120dc4a7SYongseok Koh } 1372120dc4a7SYongseok Koh 1373120dc4a7SYongseok Koh /** 1374120dc4a7SYongseok Koh * Un-initialize process private data structure. 1375120dc4a7SYongseok Koh * 1376120dc4a7SYongseok Koh * @param dev 1377120dc4a7SYongseok Koh * Pointer to Ethernet device structure. 1378120dc4a7SYongseok Koh */ 1379120dc4a7SYongseok Koh static void 1380120dc4a7SYongseok Koh mlx5_proc_priv_uninit(struct rte_eth_dev *dev) 1381120dc4a7SYongseok Koh { 1382120dc4a7SYongseok Koh if (!dev->process_private) 1383120dc4a7SYongseok Koh return; 1384120dc4a7SYongseok Koh rte_free(dev->process_private); 1385120dc4a7SYongseok Koh dev->process_private = NULL; 1386120dc4a7SYongseok Koh } 1387120dc4a7SYongseok Koh 1388120dc4a7SYongseok Koh /** 1389771fa900SAdrien Mazarguil * DPDK callback to close the device. 1390771fa900SAdrien Mazarguil * 1391771fa900SAdrien Mazarguil * Destroy all queues and objects, free memory. 1392771fa900SAdrien Mazarguil * 1393771fa900SAdrien Mazarguil * @param dev 1394771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 1395771fa900SAdrien Mazarguil */ 1396771fa900SAdrien Mazarguil static void 1397771fa900SAdrien Mazarguil mlx5_dev_close(struct rte_eth_dev *dev) 1398771fa900SAdrien Mazarguil { 1399dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 14002e22920bSAdrien Mazarguil unsigned int i; 14016af6b973SNélio Laranjeiro int ret; 1402771fa900SAdrien Mazarguil 1403a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u closing device \"%s\"", 14040f99970bSNélio Laranjeiro dev->data->port_id, 1405f048f3d4SViacheslav Ovsiienko ((priv->sh->ctx != NULL) ? priv->sh->ctx->device->name : "")); 1406ecc1c29dSAdrien Mazarguil /* In case mlx5_dev_stop() has not been called. */ 1407af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(dev); 140823242063SMatan Azrad mlx5_dev_interrupt_handler_devx_uninstall(dev); 14098db7e3b6SBing Zhao /* 14108db7e3b6SBing Zhao * If default mreg copy action is removed at the stop stage, 14118db7e3b6SBing Zhao * the search will return none and nothing will be done anymore. 14128db7e3b6SBing Zhao */ 14138db7e3b6SBing Zhao mlx5_flow_stop_default(dev); 1414af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 14158db7e3b6SBing Zhao /* 14168db7e3b6SBing Zhao * If all the flows are already flushed in the device stop stage, 14178db7e3b6SBing Zhao * then this will return directly without any action. 14188db7e3b6SBing Zhao */ 14198db7e3b6SBing Zhao mlx5_flow_list_flush(dev, &priv->flows, true); 142002e76468SSuanming Mou mlx5_flow_meter_flush(dev, NULL); 1421e7bfa359SBing Zhao /* Free the intermediate buffers for flow creation. */ 1422e7bfa359SBing Zhao mlx5_flow_free_intermediate(dev); 14232e22920bSAdrien Mazarguil /* Prevent crashes when queues are still in use. */ 14242e22920bSAdrien Mazarguil dev->rx_pkt_burst = removed_rx_burst; 14252e22920bSAdrien Mazarguil dev->tx_pkt_burst = removed_tx_burst; 14262aac5b5dSYongseok Koh rte_wmb(); 14272aac5b5dSYongseok Koh /* Disable datapath on secondary process. */ 14282aac5b5dSYongseok Koh mlx5_mp_req_stop_rxtx(dev); 14292e22920bSAdrien Mazarguil if (priv->rxqs != NULL) { 14302e22920bSAdrien Mazarguil /* XXX race condition if mlx5_rx_burst() is still running. */ 14312e22920bSAdrien Mazarguil usleep(1000); 1432a1366b1aSNélio Laranjeiro for (i = 0; (i != priv->rxqs_n); ++i) 1433af4f09f2SNélio Laranjeiro mlx5_rxq_release(dev, i); 14342e22920bSAdrien Mazarguil priv->rxqs_n = 0; 14352e22920bSAdrien Mazarguil priv->rxqs = NULL; 14362e22920bSAdrien Mazarguil } 14372e22920bSAdrien Mazarguil if (priv->txqs != NULL) { 14382e22920bSAdrien Mazarguil /* XXX race condition if mlx5_tx_burst() is still running. */ 14392e22920bSAdrien Mazarguil usleep(1000); 14406e78005aSNélio Laranjeiro for (i = 0; (i != priv->txqs_n); ++i) 1441af4f09f2SNélio Laranjeiro mlx5_txq_release(dev, i); 14422e22920bSAdrien Mazarguil priv->txqs_n = 0; 14432e22920bSAdrien Mazarguil priv->txqs = NULL; 14442e22920bSAdrien Mazarguil } 1445120dc4a7SYongseok Koh mlx5_proc_priv_uninit(dev); 1446dd3c774fSViacheslav Ovsiienko if (priv->mreg_cp_tbl) 1447dd3c774fSViacheslav Ovsiienko mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL); 14487d6bf6b8SYongseok Koh mlx5_mprq_free_mp(dev); 1449b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(priv); 145029c1d8bbSNélio Laranjeiro if (priv->rss_conf.rss_key != NULL) 145129c1d8bbSNélio Laranjeiro rte_free(priv->rss_conf.rss_key); 1452634efbc2SNelio Laranjeiro if (priv->reta_idx != NULL) 1453634efbc2SNelio Laranjeiro rte_free(priv->reta_idx); 1454ccdcba53SNélio Laranjeiro if (priv->config.vf) 1455f22442cbSMatan Azrad mlx5_nl_mac_addr_flush(priv->nl_socket_route, mlx5_ifindex(dev), 1456f22442cbSMatan Azrad dev->data->mac_addrs, 1457f22442cbSMatan Azrad MLX5_MAX_MAC_ADDRESSES, priv->mac_own); 145826c08b97SAdrien Mazarguil if (priv->nl_socket_route >= 0) 145926c08b97SAdrien Mazarguil close(priv->nl_socket_route); 146026c08b97SAdrien Mazarguil if (priv->nl_socket_rdma >= 0) 146126c08b97SAdrien Mazarguil close(priv->nl_socket_rdma); 1462dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context) 1463dfedf3e3SViacheslav Ovsiienko mlx5_vlan_vmwa_exit(priv->vmwa_context); 146423820a79SDekel Peled ret = mlx5_hrxq_verify(dev); 1465f5479b68SNélio Laranjeiro if (ret) 1466a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some hash Rx queue still remain", 14670f99970bSNélio Laranjeiro dev->data->port_id); 146815c80a12SDekel Peled ret = mlx5_ind_table_obj_verify(dev); 14694c7a0f5fSNélio Laranjeiro if (ret) 1470a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some indirection table still remain", 14710f99970bSNélio Laranjeiro dev->data->port_id); 147293403560SDekel Peled ret = mlx5_rxq_obj_verify(dev); 147309cb5b58SNélio Laranjeiro if (ret) 147493403560SDekel Peled DRV_LOG(WARNING, "port %u some Rx queue objects still remain", 14750f99970bSNélio Laranjeiro dev->data->port_id); 1476af4f09f2SNélio Laranjeiro ret = mlx5_rxq_verify(dev); 1477a1366b1aSNélio Laranjeiro if (ret) 1478a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Rx queues still remain", 14790f99970bSNélio Laranjeiro dev->data->port_id); 1480894c4a8eSOri Kam ret = mlx5_txq_obj_verify(dev); 1481faf2667fSNélio Laranjeiro if (ret) 1482a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Verbs Tx queue still remain", 14830f99970bSNélio Laranjeiro dev->data->port_id); 1484af4f09f2SNélio Laranjeiro ret = mlx5_txq_verify(dev); 14856e78005aSNélio Laranjeiro if (ret) 1486a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Tx queues still remain", 14870f99970bSNélio Laranjeiro dev->data->port_id); 1488af4f09f2SNélio Laranjeiro ret = mlx5_flow_verify(dev); 14896af6b973SNélio Laranjeiro if (ret) 1490a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some flows still remain", 1491a170a30dSNélio Laranjeiro dev->data->port_id); 1492772dc0ebSSuanming Mou if (priv->sh) { 1493772dc0ebSSuanming Mou /* 1494772dc0ebSSuanming Mou * Free the shared context in last turn, because the cleanup 1495772dc0ebSSuanming Mou * routines above may use some shared fields, like 1496772dc0ebSSuanming Mou * mlx5_nl_mac_addr_flush() uses ibdev_path for retrieveing 1497772dc0ebSSuanming Mou * ifindex if Netlink fails. 1498772dc0ebSSuanming Mou */ 1499772dc0ebSSuanming Mou mlx5_free_shared_ibctx(priv->sh); 1500772dc0ebSSuanming Mou priv->sh = NULL; 1501772dc0ebSSuanming Mou } 15022b730263SAdrien Mazarguil if (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 15032b730263SAdrien Mazarguil unsigned int c = 0; 1504d874a4eeSThomas Monjalon uint16_t port_id; 15052b730263SAdrien Mazarguil 1506fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 1507dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 1508d874a4eeSThomas Monjalon rte_eth_devices[port_id].data->dev_private; 15092b730263SAdrien Mazarguil 15102b730263SAdrien Mazarguil if (!opriv || 15112b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id || 1512d874a4eeSThomas Monjalon &rte_eth_devices[port_id] == dev) 15132b730263SAdrien Mazarguil continue; 15142b730263SAdrien Mazarguil ++c; 1515f7e95215SViacheslav Ovsiienko break; 15162b730263SAdrien Mazarguil } 15172b730263SAdrien Mazarguil if (!c) 15182b730263SAdrien Mazarguil claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 15192b730263SAdrien Mazarguil } 1520771fa900SAdrien Mazarguil memset(priv, 0, sizeof(*priv)); 15212b730263SAdrien Mazarguil priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 152242603bbdSOphir Munk /* 152342603bbdSOphir Munk * Reset mac_addrs to NULL such that it is not freed as part of 152442603bbdSOphir Munk * rte_eth_dev_release_port(). mac_addrs is part of dev_private so 152542603bbdSOphir Munk * it is freed when dev_private is freed. 152642603bbdSOphir Munk */ 152742603bbdSOphir Munk dev->data->mac_addrs = NULL; 1528771fa900SAdrien Mazarguil } 1529771fa900SAdrien Mazarguil 15300887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops = { 1531e60fbd5bSAdrien Mazarguil .dev_configure = mlx5_dev_configure, 1532e60fbd5bSAdrien Mazarguil .dev_start = mlx5_dev_start, 1533e60fbd5bSAdrien Mazarguil .dev_stop = mlx5_dev_stop, 153462072098SOr Ami .dev_set_link_down = mlx5_set_link_down, 153562072098SOr Ami .dev_set_link_up = mlx5_set_link_up, 1536771fa900SAdrien Mazarguil .dev_close = mlx5_dev_close, 15371bdbe1afSAdrien Mazarguil .promiscuous_enable = mlx5_promiscuous_enable, 15381bdbe1afSAdrien Mazarguil .promiscuous_disable = mlx5_promiscuous_disable, 15391bdbe1afSAdrien Mazarguil .allmulticast_enable = mlx5_allmulticast_enable, 15401bdbe1afSAdrien Mazarguil .allmulticast_disable = mlx5_allmulticast_disable, 1541cb8faed7SAdrien Mazarguil .link_update = mlx5_link_update, 154287011737SAdrien Mazarguil .stats_get = mlx5_stats_get, 154387011737SAdrien Mazarguil .stats_reset = mlx5_stats_reset, 1544a4193ae3SShahaf Shuler .xstats_get = mlx5_xstats_get, 1545a4193ae3SShahaf Shuler .xstats_reset = mlx5_xstats_reset, 1546a4193ae3SShahaf Shuler .xstats_get_names = mlx5_xstats_get_names, 1547714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 1548e60fbd5bSAdrien Mazarguil .dev_infos_get = mlx5_dev_infos_get, 1549e571ad55STom Barbette .read_clock = mlx5_read_clock, 155078a38edfSJianfeng Tan .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 1551e9086978SAdrien Mazarguil .vlan_filter_set = mlx5_vlan_filter_set, 15522e22920bSAdrien Mazarguil .rx_queue_setup = mlx5_rx_queue_setup, 1553e79c9be9SOri Kam .rx_hairpin_queue_setup = mlx5_rx_hairpin_queue_setup, 15542e22920bSAdrien Mazarguil .tx_queue_setup = mlx5_tx_queue_setup, 1555ae18a1aeSOri Kam .tx_hairpin_queue_setup = mlx5_tx_hairpin_queue_setup, 15562e22920bSAdrien Mazarguil .rx_queue_release = mlx5_rx_queue_release, 15572e22920bSAdrien Mazarguil .tx_queue_release = mlx5_tx_queue_release, 155802d75430SAdrien Mazarguil .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 155902d75430SAdrien Mazarguil .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 15603318aef7SAdrien Mazarguil .mac_addr_remove = mlx5_mac_addr_remove, 15613318aef7SAdrien Mazarguil .mac_addr_add = mlx5_mac_addr_add, 156286977fccSDavid Marchand .mac_addr_set = mlx5_mac_addr_set, 1563e0586a8dSNélio Laranjeiro .set_mc_addr_list = mlx5_set_mc_addr_list, 1564cf37ca95SAdrien Mazarguil .mtu_set = mlx5_dev_set_mtu, 1565f3db9489SYaacov Hazan .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 1566f3db9489SYaacov Hazan .vlan_offload_set = mlx5_vlan_offload_set, 1567634efbc2SNelio Laranjeiro .reta_update = mlx5_dev_rss_reta_update, 1568634efbc2SNelio Laranjeiro .reta_query = mlx5_dev_rss_reta_query, 15692f97422eSNelio Laranjeiro .rss_hash_update = mlx5_rss_hash_update, 15702f97422eSNelio Laranjeiro .rss_hash_conf_get = mlx5_rss_hash_conf_get, 157176f5c99eSYaacov Hazan .filter_ctrl = mlx5_dev_filter_ctrl, 15728788fec1SOlivier Matz .rx_descriptor_status = mlx5_rx_descriptor_status, 15738788fec1SOlivier Matz .tx_descriptor_status = mlx5_tx_descriptor_status, 157426f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 157526f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 157626f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 157726f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 157826f04883STom Barbette .rx_queue_count = mlx5_rx_queue_count, 15793c7d44afSShahaf Shuler .rx_queue_intr_enable = mlx5_rx_intr_enable, 15803c7d44afSShahaf Shuler .rx_queue_intr_disable = mlx5_rx_intr_disable, 1581d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 1582c9ba7523SRaslan Darawsheh .udp_tunnel_port_add = mlx5_udp_tunnel_port_add, 15838a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 15848a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 1585b6b3bf86SOri Kam .hairpin_cap_get = mlx5_hairpin_cap_get, 1586d740eb50SSuanming Mou .mtr_ops_get = mlx5_flow_meter_ops_get, 1587771fa900SAdrien Mazarguil }; 1588771fa900SAdrien Mazarguil 1589714bf46eSThomas Monjalon /* Available operations from secondary process. */ 159087ec44ceSXueming Li static const struct eth_dev_ops mlx5_dev_sec_ops = { 159187ec44ceSXueming Li .stats_get = mlx5_stats_get, 159287ec44ceSXueming Li .stats_reset = mlx5_stats_reset, 159387ec44ceSXueming Li .xstats_get = mlx5_xstats_get, 159487ec44ceSXueming Li .xstats_reset = mlx5_xstats_reset, 159587ec44ceSXueming Li .xstats_get_names = mlx5_xstats_get_names, 1596714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 159787ec44ceSXueming Li .dev_infos_get = mlx5_dev_infos_get, 159887ec44ceSXueming Li .rx_descriptor_status = mlx5_rx_descriptor_status, 159987ec44ceSXueming Li .tx_descriptor_status = mlx5_tx_descriptor_status, 160026f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 160126f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 160226f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 160326f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 16048a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 16058a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 160687ec44ceSXueming Li }; 160787ec44ceSXueming Li 1608714bf46eSThomas Monjalon /* Available operations in flow isolated mode. */ 16090887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops_isolate = { 16100887aa7fSNélio Laranjeiro .dev_configure = mlx5_dev_configure, 16110887aa7fSNélio Laranjeiro .dev_start = mlx5_dev_start, 16120887aa7fSNélio Laranjeiro .dev_stop = mlx5_dev_stop, 16130887aa7fSNélio Laranjeiro .dev_set_link_down = mlx5_set_link_down, 16140887aa7fSNélio Laranjeiro .dev_set_link_up = mlx5_set_link_up, 16150887aa7fSNélio Laranjeiro .dev_close = mlx5_dev_close, 161624b068adSYongseok Koh .promiscuous_enable = mlx5_promiscuous_enable, 161724b068adSYongseok Koh .promiscuous_disable = mlx5_promiscuous_disable, 16182547ee74SYongseok Koh .allmulticast_enable = mlx5_allmulticast_enable, 16192547ee74SYongseok Koh .allmulticast_disable = mlx5_allmulticast_disable, 16200887aa7fSNélio Laranjeiro .link_update = mlx5_link_update, 16210887aa7fSNélio Laranjeiro .stats_get = mlx5_stats_get, 16220887aa7fSNélio Laranjeiro .stats_reset = mlx5_stats_reset, 16230887aa7fSNélio Laranjeiro .xstats_get = mlx5_xstats_get, 16240887aa7fSNélio Laranjeiro .xstats_reset = mlx5_xstats_reset, 16250887aa7fSNélio Laranjeiro .xstats_get_names = mlx5_xstats_get_names, 1626714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 16270887aa7fSNélio Laranjeiro .dev_infos_get = mlx5_dev_infos_get, 16280887aa7fSNélio Laranjeiro .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 16290887aa7fSNélio Laranjeiro .vlan_filter_set = mlx5_vlan_filter_set, 16300887aa7fSNélio Laranjeiro .rx_queue_setup = mlx5_rx_queue_setup, 1631e79c9be9SOri Kam .rx_hairpin_queue_setup = mlx5_rx_hairpin_queue_setup, 16320887aa7fSNélio Laranjeiro .tx_queue_setup = mlx5_tx_queue_setup, 1633ae18a1aeSOri Kam .tx_hairpin_queue_setup = mlx5_tx_hairpin_queue_setup, 16340887aa7fSNélio Laranjeiro .rx_queue_release = mlx5_rx_queue_release, 16350887aa7fSNélio Laranjeiro .tx_queue_release = mlx5_tx_queue_release, 16360887aa7fSNélio Laranjeiro .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 16370887aa7fSNélio Laranjeiro .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 16380887aa7fSNélio Laranjeiro .mac_addr_remove = mlx5_mac_addr_remove, 16390887aa7fSNélio Laranjeiro .mac_addr_add = mlx5_mac_addr_add, 16400887aa7fSNélio Laranjeiro .mac_addr_set = mlx5_mac_addr_set, 1641e0586a8dSNélio Laranjeiro .set_mc_addr_list = mlx5_set_mc_addr_list, 16420887aa7fSNélio Laranjeiro .mtu_set = mlx5_dev_set_mtu, 16430887aa7fSNélio Laranjeiro .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 16440887aa7fSNélio Laranjeiro .vlan_offload_set = mlx5_vlan_offload_set, 16450887aa7fSNélio Laranjeiro .filter_ctrl = mlx5_dev_filter_ctrl, 16460887aa7fSNélio Laranjeiro .rx_descriptor_status = mlx5_rx_descriptor_status, 16470887aa7fSNélio Laranjeiro .tx_descriptor_status = mlx5_tx_descriptor_status, 164826f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 164926f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 165026f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 165126f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 16520887aa7fSNélio Laranjeiro .rx_queue_intr_enable = mlx5_rx_intr_enable, 16530887aa7fSNélio Laranjeiro .rx_queue_intr_disable = mlx5_rx_intr_disable, 1654d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 16558a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 16568a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 1657b6b3bf86SOri Kam .hairpin_cap_get = mlx5_hairpin_cap_get, 1658d740eb50SSuanming Mou .mtr_ops_get = mlx5_flow_meter_ops_get, 16590887aa7fSNélio Laranjeiro }; 16600887aa7fSNélio Laranjeiro 1661e72dd09bSNélio Laranjeiro /** 1662e72dd09bSNélio Laranjeiro * Verify and store value for device argument. 1663e72dd09bSNélio Laranjeiro * 1664e72dd09bSNélio Laranjeiro * @param[in] key 1665e72dd09bSNélio Laranjeiro * Key argument to verify. 1666e72dd09bSNélio Laranjeiro * @param[in] val 1667e72dd09bSNélio Laranjeiro * Value associated with key. 1668e72dd09bSNélio Laranjeiro * @param opaque 1669e72dd09bSNélio Laranjeiro * User data. 1670e72dd09bSNélio Laranjeiro * 1671e72dd09bSNélio Laranjeiro * @return 1672a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1673e72dd09bSNélio Laranjeiro */ 1674e72dd09bSNélio Laranjeiro static int 1675e72dd09bSNélio Laranjeiro mlx5_args_check(const char *key, const char *val, void *opaque) 1676e72dd09bSNélio Laranjeiro { 16777fe24446SShahaf Shuler struct mlx5_dev_config *config = opaque; 167899c12dccSNélio Laranjeiro unsigned long tmp; 1679e72dd09bSNélio Laranjeiro 16806de569f5SAdrien Mazarguil /* No-op, port representors are processed in mlx5_dev_spawn(). */ 16816de569f5SAdrien Mazarguil if (!strcmp(MLX5_REPRESENTOR, key)) 16826de569f5SAdrien Mazarguil return 0; 168399c12dccSNélio Laranjeiro errno = 0; 168499c12dccSNélio Laranjeiro tmp = strtoul(val, NULL, 0); 168599c12dccSNélio Laranjeiro if (errno) { 1686a6d83b6aSNélio Laranjeiro rte_errno = errno; 1687a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "%s: \"%s\" is not a valid integer", key, val); 1688a6d83b6aSNélio Laranjeiro return -rte_errno; 168999c12dccSNélio Laranjeiro } 169099c12dccSNélio Laranjeiro if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) { 16917fe24446SShahaf Shuler config->cqe_comp = !!tmp; 1692bc91e8dbSYongseok Koh } else if (strcmp(MLX5_RXQ_CQE_PAD_EN, key) == 0) { 1693bc91e8dbSYongseok Koh config->cqe_pad = !!tmp; 169478c7a16dSYongseok Koh } else if (strcmp(MLX5_RXQ_PKT_PAD_EN, key) == 0) { 169578c7a16dSYongseok Koh config->hw_padding = !!tmp; 16967d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_EN, key) == 0) { 16977d6bf6b8SYongseok Koh config->mprq.enabled = !!tmp; 16987d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_NUM, key) == 0) { 16997d6bf6b8SYongseok Koh config->mprq.stride_num_n = tmp; 1700ecb16045SAlexander Kozyrev } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_SIZE, key) == 0) { 1701ecb16045SAlexander Kozyrev config->mprq.stride_size_n = tmp; 17027d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_MAX_MEMCPY_LEN, key) == 0) { 17037d6bf6b8SYongseok Koh config->mprq.max_memcpy_len = tmp; 17047d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RXQS_MIN_MPRQ, key) == 0) { 17057d6bf6b8SYongseok Koh config->mprq.min_rxqs_num = tmp; 17062a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { 1707505f1fe4SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter," 1708505f1fe4SViacheslav Ovsiienko " converted to txq_inline_max", key); 1709505f1fe4SViacheslav Ovsiienko config->txq_inline_max = tmp; 1710505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MAX, key) == 0) { 1711505f1fe4SViacheslav Ovsiienko config->txq_inline_max = tmp; 1712505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MIN, key) == 0) { 1713505f1fe4SViacheslav Ovsiienko config->txq_inline_min = tmp; 1714505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MPW, key) == 0) { 1715505f1fe4SViacheslav Ovsiienko config->txq_inline_mpw = tmp; 17162a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { 17177fe24446SShahaf Shuler config->txqs_inline = tmp; 171809d8b416SYongseok Koh } else if (strcmp(MLX5_TXQS_MAX_VEC, key) == 0) { 1719a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 1720230189d9SNélio Laranjeiro } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { 1721f9de8718SShahaf Shuler config->mps = !!tmp; 17228409a285SViacheslav Ovsiienko } else if (strcmp(MLX5_TX_DB_NC, key) == 0) { 1723f078ceb6SViacheslav Ovsiienko if (tmp != MLX5_TXDB_CACHED && 1724f078ceb6SViacheslav Ovsiienko tmp != MLX5_TXDB_NCACHED && 1725f078ceb6SViacheslav Ovsiienko tmp != MLX5_TXDB_HEURISTIC) { 1726f078ceb6SViacheslav Ovsiienko DRV_LOG(ERR, "invalid Tx doorbell " 1727f078ceb6SViacheslav Ovsiienko "mapping parameter"); 1728f078ceb6SViacheslav Ovsiienko rte_errno = EINVAL; 1729f078ceb6SViacheslav Ovsiienko return -rte_errno; 1730f078ceb6SViacheslav Ovsiienko } 1731f078ceb6SViacheslav Ovsiienko config->dbnc = tmp; 17326ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) { 1733a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 17346ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) { 1735505f1fe4SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter," 1736505f1fe4SViacheslav Ovsiienko " converted to txq_inline_mpw", key); 1737505f1fe4SViacheslav Ovsiienko config->txq_inline_mpw = tmp; 17385644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { 1739a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 17405644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { 17417fe24446SShahaf Shuler config->rx_vec_en = !!tmp; 174278a54648SXueming Li } else if (strcmp(MLX5_L3_VXLAN_EN, key) == 0) { 174378a54648SXueming Li config->l3_vxlan_en = !!tmp; 1744db209cc3SNélio Laranjeiro } else if (strcmp(MLX5_VF_NL_EN, key) == 0) { 1745db209cc3SNélio Laranjeiro config->vf_nl_en = !!tmp; 1746e2b4925eSOri Kam } else if (strcmp(MLX5_DV_ESW_EN, key) == 0) { 1747e2b4925eSOri Kam config->dv_esw_en = !!tmp; 174851e72d38SOri Kam } else if (strcmp(MLX5_DV_FLOW_EN, key) == 0) { 174951e72d38SOri Kam config->dv_flow_en = !!tmp; 17502d241515SViacheslav Ovsiienko } else if (strcmp(MLX5_DV_XMETA_EN, key) == 0) { 17512d241515SViacheslav Ovsiienko if (tmp != MLX5_XMETA_MODE_LEGACY && 17522d241515SViacheslav Ovsiienko tmp != MLX5_XMETA_MODE_META16 && 17532d241515SViacheslav Ovsiienko tmp != MLX5_XMETA_MODE_META32) { 1754f078ceb6SViacheslav Ovsiienko DRV_LOG(ERR, "invalid extensive " 17552d241515SViacheslav Ovsiienko "metadata parameter"); 17562d241515SViacheslav Ovsiienko rte_errno = EINVAL; 17572d241515SViacheslav Ovsiienko return -rte_errno; 17582d241515SViacheslav Ovsiienko } 17592d241515SViacheslav Ovsiienko config->dv_xmeta_en = tmp; 1760dceb5029SYongseok Koh } else if (strcmp(MLX5_MR_EXT_MEMSEG_EN, key) == 0) { 1761dceb5029SYongseok Koh config->mr_ext_memseg_en = !!tmp; 1762066cfecdSMatan Azrad } else if (strcmp(MLX5_MAX_DUMP_FILES_NUM, key) == 0) { 1763066cfecdSMatan Azrad config->max_dump_files_num = tmp; 176421bb6c7eSDekel Peled } else if (strcmp(MLX5_LRO_TIMEOUT_USEC, key) == 0) { 176521bb6c7eSDekel Peled config->lro.timeout = tmp; 1766d768f324SMatan Azrad } else if (strcmp(MLX5_CLASS_ARG_NAME, key) == 0) { 1767d768f324SMatan Azrad DRV_LOG(DEBUG, "class argument is %s.", val); 17681ad9a3d0SBing Zhao } else if (strcmp(MLX5_HP_BUF_SIZE, key) == 0) { 17691ad9a3d0SBing Zhao config->log_hp_size = tmp; 177099c12dccSNélio Laranjeiro } else { 1771a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "%s: unknown parameter", key); 1772a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 1773a6d83b6aSNélio Laranjeiro return -rte_errno; 1774e72dd09bSNélio Laranjeiro } 177599c12dccSNélio Laranjeiro return 0; 177699c12dccSNélio Laranjeiro } 1777e72dd09bSNélio Laranjeiro 1778e72dd09bSNélio Laranjeiro /** 1779e72dd09bSNélio Laranjeiro * Parse device parameters. 1780e72dd09bSNélio Laranjeiro * 17817fe24446SShahaf Shuler * @param config 17827fe24446SShahaf Shuler * Pointer to device configuration structure. 1783e72dd09bSNélio Laranjeiro * @param devargs 1784e72dd09bSNélio Laranjeiro * Device arguments structure. 1785e72dd09bSNélio Laranjeiro * 1786e72dd09bSNélio Laranjeiro * @return 1787a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1788e72dd09bSNélio Laranjeiro */ 1789e72dd09bSNélio Laranjeiro static int 17907fe24446SShahaf Shuler mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) 1791e72dd09bSNélio Laranjeiro { 1792e72dd09bSNélio Laranjeiro const char **params = (const char *[]){ 179399c12dccSNélio Laranjeiro MLX5_RXQ_CQE_COMP_EN, 1794bc91e8dbSYongseok Koh MLX5_RXQ_CQE_PAD_EN, 179578c7a16dSYongseok Koh MLX5_RXQ_PKT_PAD_EN, 17967d6bf6b8SYongseok Koh MLX5_RX_MPRQ_EN, 17977d6bf6b8SYongseok Koh MLX5_RX_MPRQ_LOG_STRIDE_NUM, 1798ecb16045SAlexander Kozyrev MLX5_RX_MPRQ_LOG_STRIDE_SIZE, 17997d6bf6b8SYongseok Koh MLX5_RX_MPRQ_MAX_MEMCPY_LEN, 18007d6bf6b8SYongseok Koh MLX5_RXQS_MIN_MPRQ, 18012a66cf37SYaacov Hazan MLX5_TXQ_INLINE, 1802505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MIN, 1803505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MAX, 1804505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MPW, 18052a66cf37SYaacov Hazan MLX5_TXQS_MIN_INLINE, 180609d8b416SYongseok Koh MLX5_TXQS_MAX_VEC, 1807230189d9SNélio Laranjeiro MLX5_TXQ_MPW_EN, 18086ce84bd8SYongseok Koh MLX5_TXQ_MPW_HDR_DSEG_EN, 18096ce84bd8SYongseok Koh MLX5_TXQ_MAX_INLINE_LEN, 18108409a285SViacheslav Ovsiienko MLX5_TX_DB_NC, 18115644d5b9SNelio Laranjeiro MLX5_TX_VEC_EN, 18125644d5b9SNelio Laranjeiro MLX5_RX_VEC_EN, 181378a54648SXueming Li MLX5_L3_VXLAN_EN, 1814db209cc3SNélio Laranjeiro MLX5_VF_NL_EN, 1815e2b4925eSOri Kam MLX5_DV_ESW_EN, 181651e72d38SOri Kam MLX5_DV_FLOW_EN, 18172d241515SViacheslav Ovsiienko MLX5_DV_XMETA_EN, 1818dceb5029SYongseok Koh MLX5_MR_EXT_MEMSEG_EN, 18196de569f5SAdrien Mazarguil MLX5_REPRESENTOR, 1820066cfecdSMatan Azrad MLX5_MAX_DUMP_FILES_NUM, 182121bb6c7eSDekel Peled MLX5_LRO_TIMEOUT_USEC, 1822d768f324SMatan Azrad MLX5_CLASS_ARG_NAME, 18231ad9a3d0SBing Zhao MLX5_HP_BUF_SIZE, 1824e72dd09bSNélio Laranjeiro NULL, 1825e72dd09bSNélio Laranjeiro }; 1826e72dd09bSNélio Laranjeiro struct rte_kvargs *kvlist; 1827e72dd09bSNélio Laranjeiro int ret = 0; 1828e72dd09bSNélio Laranjeiro int i; 1829e72dd09bSNélio Laranjeiro 1830e72dd09bSNélio Laranjeiro if (devargs == NULL) 1831e72dd09bSNélio Laranjeiro return 0; 1832e72dd09bSNélio Laranjeiro /* Following UGLY cast is done to pass checkpatch. */ 1833e72dd09bSNélio Laranjeiro kvlist = rte_kvargs_parse(devargs->args, params); 183415b0ea00SMatan Azrad if (kvlist == NULL) { 183515b0ea00SMatan Azrad rte_errno = EINVAL; 183615b0ea00SMatan Azrad return -rte_errno; 183715b0ea00SMatan Azrad } 1838e72dd09bSNélio Laranjeiro /* Process parameters. */ 1839e72dd09bSNélio Laranjeiro for (i = 0; (params[i] != NULL); ++i) { 1840e72dd09bSNélio Laranjeiro if (rte_kvargs_count(kvlist, params[i])) { 1841e72dd09bSNélio Laranjeiro ret = rte_kvargs_process(kvlist, params[i], 18427fe24446SShahaf Shuler mlx5_args_check, config); 1843a6d83b6aSNélio Laranjeiro if (ret) { 1844a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 1845a67323e4SShahaf Shuler rte_kvargs_free(kvlist); 1846a6d83b6aSNélio Laranjeiro return -rte_errno; 1847e72dd09bSNélio Laranjeiro } 1848e72dd09bSNélio Laranjeiro } 1849a67323e4SShahaf Shuler } 1850e72dd09bSNélio Laranjeiro rte_kvargs_free(kvlist); 1851e72dd09bSNélio Laranjeiro return 0; 1852e72dd09bSNélio Laranjeiro } 1853e72dd09bSNélio Laranjeiro 1854fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver; 1855771fa900SAdrien Mazarguil 18567be600c8SYongseok Koh /** 18577be600c8SYongseok Koh * PMD global initialization. 18587be600c8SYongseok Koh * 18597be600c8SYongseok Koh * Independent from individual device, this function initializes global 18607be600c8SYongseok Koh * per-PMD data structures distinguishing primary and secondary processes. 18617be600c8SYongseok Koh * Hence, each initialization is called once per a process. 18627be600c8SYongseok Koh * 18637be600c8SYongseok Koh * @return 18647be600c8SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 18657be600c8SYongseok Koh */ 18667be600c8SYongseok Koh static int 18677be600c8SYongseok Koh mlx5_init_once(void) 18687be600c8SYongseok Koh { 18697be600c8SYongseok Koh struct mlx5_shared_data *sd; 18707be600c8SYongseok Koh struct mlx5_local_data *ld = &mlx5_local_data; 1871edf73dd3SAnatoly Burakov int ret = 0; 18727be600c8SYongseok Koh 18737be600c8SYongseok Koh if (mlx5_init_shared_data()) 18747be600c8SYongseok Koh return -rte_errno; 18757be600c8SYongseok Koh sd = mlx5_shared_data; 18768e46d4e1SAlexander Kozyrev MLX5_ASSERT(sd); 18777be600c8SYongseok Koh rte_spinlock_lock(&sd->lock); 18787be600c8SYongseok Koh switch (rte_eal_process_type()) { 18797be600c8SYongseok Koh case RTE_PROC_PRIMARY: 18807be600c8SYongseok Koh if (sd->init_done) 18817be600c8SYongseok Koh break; 18827be600c8SYongseok Koh LIST_INIT(&sd->mem_event_cb_list); 18837be600c8SYongseok Koh rte_rwlock_init(&sd->mem_event_rwlock); 18847be600c8SYongseok Koh rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 18857be600c8SYongseok Koh mlx5_mr_mem_event_cb, NULL); 1886a4de9586SVu Pham ret = mlx5_mp_init_primary(MLX5_MP_NAME, 1887a4de9586SVu Pham mlx5_mp_primary_handle); 1888edf73dd3SAnatoly Burakov if (ret) 1889edf73dd3SAnatoly Burakov goto out; 18907be600c8SYongseok Koh sd->init_done = true; 18917be600c8SYongseok Koh break; 18927be600c8SYongseok Koh case RTE_PROC_SECONDARY: 18937be600c8SYongseok Koh if (ld->init_done) 18947be600c8SYongseok Koh break; 1895a4de9586SVu Pham ret = mlx5_mp_init_secondary(MLX5_MP_NAME, 1896a4de9586SVu Pham mlx5_mp_secondary_handle); 1897edf73dd3SAnatoly Burakov if (ret) 1898edf73dd3SAnatoly Burakov goto out; 18997be600c8SYongseok Koh ++sd->secondary_cnt; 19007be600c8SYongseok Koh ld->init_done = true; 19017be600c8SYongseok Koh break; 19027be600c8SYongseok Koh default: 19037be600c8SYongseok Koh break; 19047be600c8SYongseok Koh } 1905edf73dd3SAnatoly Burakov out: 19067be600c8SYongseok Koh rte_spinlock_unlock(&sd->lock); 1907edf73dd3SAnatoly Burakov return ret; 19087be600c8SYongseok Koh } 19097be600c8SYongseok Koh 19107be600c8SYongseok Koh /** 191138b4b397SViacheslav Ovsiienko * Configures the minimal amount of data to inline into WQE 191238b4b397SViacheslav Ovsiienko * while sending packets. 191338b4b397SViacheslav Ovsiienko * 191438b4b397SViacheslav Ovsiienko * - the txq_inline_min has the maximal priority, if this 191538b4b397SViacheslav Ovsiienko * key is specified in devargs 191638b4b397SViacheslav Ovsiienko * - if DevX is enabled the inline mode is queried from the 191738b4b397SViacheslav Ovsiienko * device (HCA attributes and NIC vport context if needed). 1918ee76bddcSThomas Monjalon * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4 Lx 191938b4b397SViacheslav Ovsiienko * and none (0 bytes) for other NICs 192038b4b397SViacheslav Ovsiienko * 192138b4b397SViacheslav Ovsiienko * @param spawn 192238b4b397SViacheslav Ovsiienko * Verbs device parameters (name, port, switch_info) to spawn. 192338b4b397SViacheslav Ovsiienko * @param config 192438b4b397SViacheslav Ovsiienko * Device configuration parameters. 192538b4b397SViacheslav Ovsiienko */ 192638b4b397SViacheslav Ovsiienko static void 192738b4b397SViacheslav Ovsiienko mlx5_set_min_inline(struct mlx5_dev_spawn_data *spawn, 192838b4b397SViacheslav Ovsiienko struct mlx5_dev_config *config) 192938b4b397SViacheslav Ovsiienko { 193038b4b397SViacheslav Ovsiienko if (config->txq_inline_min != MLX5_ARG_UNSET) { 193138b4b397SViacheslav Ovsiienko /* Application defines size of inlined data explicitly. */ 193238b4b397SViacheslav Ovsiienko switch (spawn->pci_dev->id.device_id) { 193338b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 193438b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 193538b4b397SViacheslav Ovsiienko if (config->txq_inline_min < 193638b4b397SViacheslav Ovsiienko (int)MLX5_INLINE_HSIZE_L2) { 193738b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, 193838b4b397SViacheslav Ovsiienko "txq_inline_mix aligned to minimal" 193938b4b397SViacheslav Ovsiienko " ConnectX-4 required value %d", 194038b4b397SViacheslav Ovsiienko (int)MLX5_INLINE_HSIZE_L2); 194138b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 194238b4b397SViacheslav Ovsiienko } 194338b4b397SViacheslav Ovsiienko break; 194438b4b397SViacheslav Ovsiienko } 194538b4b397SViacheslav Ovsiienko goto exit; 194638b4b397SViacheslav Ovsiienko } 194738b4b397SViacheslav Ovsiienko if (config->hca_attr.eth_net_offloads) { 194838b4b397SViacheslav Ovsiienko /* We have DevX enabled, inline mode queried successfully. */ 194938b4b397SViacheslav Ovsiienko switch (config->hca_attr.wqe_inline_mode) { 195038b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_L2: 195138b4b397SViacheslav Ovsiienko /* outer L2 header must be inlined. */ 195238b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 195338b4b397SViacheslav Ovsiienko goto exit; 195438b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: 195538b4b397SViacheslav Ovsiienko /* No inline data are required by NIC. */ 195638b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 195738b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 195838b4b397SViacheslav Ovsiienko config->hca_attr.wqe_vlan_insert; 195938b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, "Tx VLAN insertion is supported"); 196038b4b397SViacheslav Ovsiienko goto exit; 196138b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: 196238b4b397SViacheslav Ovsiienko /* inline mode is defined by NIC vport context. */ 196338b4b397SViacheslav Ovsiienko if (!config->hca_attr.eth_virt) 196438b4b397SViacheslav Ovsiienko break; 196538b4b397SViacheslav Ovsiienko switch (config->hca_attr.vport_inline_mode) { 196638b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_NONE: 196738b4b397SViacheslav Ovsiienko config->txq_inline_min = 196838b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_NONE; 196938b4b397SViacheslav Ovsiienko goto exit; 197038b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_L2: 197138b4b397SViacheslav Ovsiienko config->txq_inline_min = 197238b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L2; 197338b4b397SViacheslav Ovsiienko goto exit; 197438b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_IP: 197538b4b397SViacheslav Ovsiienko config->txq_inline_min = 197638b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L3; 197738b4b397SViacheslav Ovsiienko goto exit; 197838b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_TCP_UDP: 197938b4b397SViacheslav Ovsiienko config->txq_inline_min = 198038b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L4; 198138b4b397SViacheslav Ovsiienko goto exit; 198238b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_L2: 198338b4b397SViacheslav Ovsiienko config->txq_inline_min = 198438b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L2; 198538b4b397SViacheslav Ovsiienko goto exit; 198638b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_IP: 198738b4b397SViacheslav Ovsiienko config->txq_inline_min = 198838b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L3; 198938b4b397SViacheslav Ovsiienko goto exit; 199038b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_TCP_UDP: 199138b4b397SViacheslav Ovsiienko config->txq_inline_min = 199238b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L4; 199338b4b397SViacheslav Ovsiienko goto exit; 199438b4b397SViacheslav Ovsiienko } 199538b4b397SViacheslav Ovsiienko } 199638b4b397SViacheslav Ovsiienko } 199738b4b397SViacheslav Ovsiienko /* 199838b4b397SViacheslav Ovsiienko * We get here if we are unable to deduce 199938b4b397SViacheslav Ovsiienko * inline data size with DevX. Try PCI ID 200038b4b397SViacheslav Ovsiienko * to determine old NICs. 200138b4b397SViacheslav Ovsiienko */ 200238b4b397SViacheslav Ovsiienko switch (spawn->pci_dev->id.device_id) { 200338b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 200438b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 200538b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: 200638b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 2007614de6c8SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 200838b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 0; 200938b4b397SViacheslav Ovsiienko break; 201038b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5: 201138b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 201238b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: 201338b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 201438b4b397SViacheslav Ovsiienko /* 201538b4b397SViacheslav Ovsiienko * These NICs support VLAN insertion from WQE and 201638b4b397SViacheslav Ovsiienko * report the wqe_vlan_insert flag. But there is the bug 201738b4b397SViacheslav Ovsiienko * and PFC control may be broken, so disable feature. 201838b4b397SViacheslav Ovsiienko */ 201938b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 0; 202020215627SDavid Christensen config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 202138b4b397SViacheslav Ovsiienko break; 202238b4b397SViacheslav Ovsiienko default: 202338b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 202438b4b397SViacheslav Ovsiienko break; 202538b4b397SViacheslav Ovsiienko } 202638b4b397SViacheslav Ovsiienko exit: 202738b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, "min tx inline configured: %d", config->txq_inline_min); 202838b4b397SViacheslav Ovsiienko } 202938b4b397SViacheslav Ovsiienko 203038b4b397SViacheslav Ovsiienko /** 203139139371SViacheslav Ovsiienko * Configures the metadata mask fields in the shared context. 203239139371SViacheslav Ovsiienko * 203339139371SViacheslav Ovsiienko * @param [in] dev 203439139371SViacheslav Ovsiienko * Pointer to Ethernet device. 203539139371SViacheslav Ovsiienko */ 203639139371SViacheslav Ovsiienko static void 203739139371SViacheslav Ovsiienko mlx5_set_metadata_mask(struct rte_eth_dev *dev) 203839139371SViacheslav Ovsiienko { 203939139371SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 204039139371SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 204139139371SViacheslav Ovsiienko uint32_t meta, mark, reg_c0; 204239139371SViacheslav Ovsiienko 204339139371SViacheslav Ovsiienko reg_c0 = ~priv->vport_meta_mask; 204439139371SViacheslav Ovsiienko switch (priv->config.dv_xmeta_en) { 204539139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_LEGACY: 204639139371SViacheslav Ovsiienko meta = UINT32_MAX; 204739139371SViacheslav Ovsiienko mark = MLX5_FLOW_MARK_MASK; 204839139371SViacheslav Ovsiienko break; 204939139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_META16: 205039139371SViacheslav Ovsiienko meta = reg_c0 >> rte_bsf32(reg_c0); 205139139371SViacheslav Ovsiienko mark = MLX5_FLOW_MARK_MASK; 205239139371SViacheslav Ovsiienko break; 205339139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_META32: 205439139371SViacheslav Ovsiienko meta = UINT32_MAX; 205539139371SViacheslav Ovsiienko mark = (reg_c0 >> rte_bsf32(reg_c0)) & MLX5_FLOW_MARK_MASK; 205639139371SViacheslav Ovsiienko break; 205739139371SViacheslav Ovsiienko default: 205839139371SViacheslav Ovsiienko meta = 0; 205939139371SViacheslav Ovsiienko mark = 0; 20608e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 206139139371SViacheslav Ovsiienko break; 206239139371SViacheslav Ovsiienko } 206339139371SViacheslav Ovsiienko if (sh->dv_mark_mask && sh->dv_mark_mask != mark) 206439139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata MARK mask mismatche %08X:%08X", 206539139371SViacheslav Ovsiienko sh->dv_mark_mask, mark); 206639139371SViacheslav Ovsiienko else 206739139371SViacheslav Ovsiienko sh->dv_mark_mask = mark; 206839139371SViacheslav Ovsiienko if (sh->dv_meta_mask && sh->dv_meta_mask != meta) 206939139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata META mask mismatche %08X:%08X", 207039139371SViacheslav Ovsiienko sh->dv_meta_mask, meta); 207139139371SViacheslav Ovsiienko else 207239139371SViacheslav Ovsiienko sh->dv_meta_mask = meta; 207339139371SViacheslav Ovsiienko if (sh->dv_regc0_mask && sh->dv_regc0_mask != reg_c0) 207439139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata reg_c0 mask mismatche %08X:%08X", 207539139371SViacheslav Ovsiienko sh->dv_meta_mask, reg_c0); 207639139371SViacheslav Ovsiienko else 207739139371SViacheslav Ovsiienko sh->dv_regc0_mask = reg_c0; 207839139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata mode %u", priv->config.dv_xmeta_en); 207939139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata MARK mask %08X", sh->dv_mark_mask); 208039139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata META mask %08X", sh->dv_meta_mask); 208139139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata reg_c0 mask %08X", sh->dv_regc0_mask); 208239139371SViacheslav Ovsiienko } 208339139371SViacheslav Ovsiienko 208439139371SViacheslav Ovsiienko /** 208521cae858SDekel Peled * Allocate page of door-bells and register it using DevX API. 208621cae858SDekel Peled * 208721cae858SDekel Peled * @param [in] dev 208821cae858SDekel Peled * Pointer to Ethernet device. 208921cae858SDekel Peled * 209021cae858SDekel Peled * @return 209121cae858SDekel Peled * Pointer to new page on success, NULL otherwise. 209221cae858SDekel Peled */ 209321cae858SDekel Peled static struct mlx5_devx_dbr_page * 209421cae858SDekel Peled mlx5_alloc_dbr_page(struct rte_eth_dev *dev) 209521cae858SDekel Peled { 209621cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 209721cae858SDekel Peled struct mlx5_devx_dbr_page *page; 209821cae858SDekel Peled 209921cae858SDekel Peled /* Allocate space for door-bell page and management data. */ 210021cae858SDekel Peled page = rte_calloc_socket(__func__, 1, sizeof(struct mlx5_devx_dbr_page), 210121cae858SDekel Peled RTE_CACHE_LINE_SIZE, dev->device->numa_node); 210221cae858SDekel Peled if (!page) { 210321cae858SDekel Peled DRV_LOG(ERR, "port %u cannot allocate dbr page", 210421cae858SDekel Peled dev->data->port_id); 210521cae858SDekel Peled return NULL; 210621cae858SDekel Peled } 210721cae858SDekel Peled /* Register allocated memory. */ 210821cae858SDekel Peled page->umem = mlx5_glue->devx_umem_reg(priv->sh->ctx, page->dbrs, 210921cae858SDekel Peled MLX5_DBR_PAGE_SIZE, 0); 211021cae858SDekel Peled if (!page->umem) { 211121cae858SDekel Peled DRV_LOG(ERR, "port %u cannot umem reg dbr page", 211221cae858SDekel Peled dev->data->port_id); 211321cae858SDekel Peled rte_free(page); 211421cae858SDekel Peled return NULL; 211521cae858SDekel Peled } 211621cae858SDekel Peled return page; 211721cae858SDekel Peled } 211821cae858SDekel Peled 211921cae858SDekel Peled /** 212021cae858SDekel Peled * Find the next available door-bell, allocate new page if needed. 212121cae858SDekel Peled * 212221cae858SDekel Peled * @param [in] dev 212321cae858SDekel Peled * Pointer to Ethernet device. 212421cae858SDekel Peled * @param [out] dbr_page 212521cae858SDekel Peled * Door-bell page containing the page data. 212621cae858SDekel Peled * 212721cae858SDekel Peled * @return 212821cae858SDekel Peled * Door-bell address offset on success, a negative error value otherwise. 212921cae858SDekel Peled */ 213021cae858SDekel Peled int64_t 213121cae858SDekel Peled mlx5_get_dbr(struct rte_eth_dev *dev, struct mlx5_devx_dbr_page **dbr_page) 213221cae858SDekel Peled { 213321cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 213421cae858SDekel Peled struct mlx5_devx_dbr_page *page = NULL; 213521cae858SDekel Peled uint32_t i, j; 213621cae858SDekel Peled 213721cae858SDekel Peled LIST_FOREACH(page, &priv->dbrpgs, next) 213821cae858SDekel Peled if (page->dbr_count < MLX5_DBR_PER_PAGE) 213921cae858SDekel Peled break; 214021cae858SDekel Peled if (!page) { /* No page with free door-bell exists. */ 214121cae858SDekel Peled page = mlx5_alloc_dbr_page(dev); 214221cae858SDekel Peled if (!page) /* Failed to allocate new page. */ 214321cae858SDekel Peled return (-1); 214421cae858SDekel Peled LIST_INSERT_HEAD(&priv->dbrpgs, page, next); 214521cae858SDekel Peled } 214621cae858SDekel Peled /* Loop to find bitmap part with clear bit. */ 214721cae858SDekel Peled for (i = 0; 214821cae858SDekel Peled i < MLX5_DBR_BITMAP_SIZE && page->dbr_bitmap[i] == UINT64_MAX; 214921cae858SDekel Peled i++) 215021cae858SDekel Peled ; /* Empty. */ 215121cae858SDekel Peled /* Find the first clear bit. */ 2152*9b080425SAsaf Penso MLX5_ASSERT(i < MLX5_DBR_BITMAP_SIZE); 215321cae858SDekel Peled j = rte_bsf64(~page->dbr_bitmap[i]); 215421cae858SDekel Peled page->dbr_bitmap[i] |= (1 << j); 215521cae858SDekel Peled page->dbr_count++; 215621cae858SDekel Peled *dbr_page = page; 215721cae858SDekel Peled return (((i * 64) + j) * sizeof(uint64_t)); 215821cae858SDekel Peled } 215921cae858SDekel Peled 216021cae858SDekel Peled /** 216121cae858SDekel Peled * Release a door-bell record. 216221cae858SDekel Peled * 216321cae858SDekel Peled * @param [in] dev 216421cae858SDekel Peled * Pointer to Ethernet device. 216521cae858SDekel Peled * @param [in] umem_id 216621cae858SDekel Peled * UMEM ID of page containing the door-bell record to release. 216721cae858SDekel Peled * @param [in] offset 216821cae858SDekel Peled * Offset of door-bell record in page. 216921cae858SDekel Peled * 217021cae858SDekel Peled * @return 217121cae858SDekel Peled * 0 on success, a negative error value otherwise. 217221cae858SDekel Peled */ 217321cae858SDekel Peled int32_t 217421cae858SDekel Peled mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id, uint64_t offset) 217521cae858SDekel Peled { 217621cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 217721cae858SDekel Peled struct mlx5_devx_dbr_page *page = NULL; 217821cae858SDekel Peled int ret = 0; 217921cae858SDekel Peled 218021cae858SDekel Peled LIST_FOREACH(page, &priv->dbrpgs, next) 218121cae858SDekel Peled /* Find the page this address belongs to. */ 218221cae858SDekel Peled if (page->umem->umem_id == umem_id) 218321cae858SDekel Peled break; 218421cae858SDekel Peled if (!page) 218521cae858SDekel Peled return -EINVAL; 218621cae858SDekel Peled page->dbr_count--; 218721cae858SDekel Peled if (!page->dbr_count) { 218821cae858SDekel Peled /* Page not used, free it and remove from list. */ 218921cae858SDekel Peled LIST_REMOVE(page, next); 219021cae858SDekel Peled if (page->umem) 219121cae858SDekel Peled ret = -mlx5_glue->devx_umem_dereg(page->umem); 219221cae858SDekel Peled rte_free(page); 219321cae858SDekel Peled } else { 219421cae858SDekel Peled /* Mark in bitmap that this door-bell is not in use. */ 2195a88209b0SDekel Peled offset /= MLX5_DBR_SIZE; 219621cae858SDekel Peled int i = offset / 64; 219721cae858SDekel Peled int j = offset % 64; 219821cae858SDekel Peled 219921cae858SDekel Peled page->dbr_bitmap[i] &= ~(1 << j); 220021cae858SDekel Peled } 220121cae858SDekel Peled return ret; 220221cae858SDekel Peled } 220321cae858SDekel Peled 2204efa79e68SOri Kam int 2205efa79e68SOri Kam rte_pmd_mlx5_get_dyn_flag_names(char *names[], unsigned int n) 2206efa79e68SOri Kam { 2207efa79e68SOri Kam static const char *const dynf_names[] = { 2208efa79e68SOri Kam RTE_PMD_MLX5_FINE_GRANULARITY_INLINE, 2209efa79e68SOri Kam RTE_MBUF_DYNFLAG_METADATA_NAME 2210efa79e68SOri Kam }; 2211efa79e68SOri Kam unsigned int i; 2212efa79e68SOri Kam 2213efa79e68SOri Kam if (n < RTE_DIM(dynf_names)) 2214efa79e68SOri Kam return -ENOMEM; 2215efa79e68SOri Kam for (i = 0; i < RTE_DIM(dynf_names); i++) { 2216efa79e68SOri Kam if (names[i] == NULL) 2217efa79e68SOri Kam return -EINVAL; 2218efa79e68SOri Kam strcpy(names[i], dynf_names[i]); 2219efa79e68SOri Kam } 2220efa79e68SOri Kam return RTE_DIM(dynf_names); 2221efa79e68SOri Kam } 2222efa79e68SOri Kam 222321cae858SDekel Peled /** 222492d5dd48SViacheslav Ovsiienko * Check sibling device configurations. 222592d5dd48SViacheslav Ovsiienko * 222692d5dd48SViacheslav Ovsiienko * Sibling devices sharing the Infiniband device context 222792d5dd48SViacheslav Ovsiienko * should have compatible configurations. This regards 222892d5dd48SViacheslav Ovsiienko * representors and bonding slaves. 222992d5dd48SViacheslav Ovsiienko * 223092d5dd48SViacheslav Ovsiienko * @param priv 223192d5dd48SViacheslav Ovsiienko * Private device descriptor. 223292d5dd48SViacheslav Ovsiienko * @param config 223392d5dd48SViacheslav Ovsiienko * Configuration of the device is going to be created. 223492d5dd48SViacheslav Ovsiienko * 223592d5dd48SViacheslav Ovsiienko * @return 223692d5dd48SViacheslav Ovsiienko * 0 on success, EINVAL otherwise 223792d5dd48SViacheslav Ovsiienko */ 223892d5dd48SViacheslav Ovsiienko static int 223992d5dd48SViacheslav Ovsiienko mlx5_dev_check_sibling_config(struct mlx5_priv *priv, 224092d5dd48SViacheslav Ovsiienko struct mlx5_dev_config *config) 224192d5dd48SViacheslav Ovsiienko { 224292d5dd48SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 224392d5dd48SViacheslav Ovsiienko struct mlx5_dev_config *sh_conf = NULL; 224492d5dd48SViacheslav Ovsiienko uint16_t port_id; 224592d5dd48SViacheslav Ovsiienko 22468e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 224792d5dd48SViacheslav Ovsiienko /* Nothing to compare for the single/first device. */ 224892d5dd48SViacheslav Ovsiienko if (sh->refcnt == 1) 224992d5dd48SViacheslav Ovsiienko return 0; 225092d5dd48SViacheslav Ovsiienko /* Find the device with shared context. */ 2251fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 225292d5dd48SViacheslav Ovsiienko struct mlx5_priv *opriv = 225392d5dd48SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 225492d5dd48SViacheslav Ovsiienko 225592d5dd48SViacheslav Ovsiienko if (opriv && opriv != priv && opriv->sh == sh) { 225692d5dd48SViacheslav Ovsiienko sh_conf = &opriv->config; 225792d5dd48SViacheslav Ovsiienko break; 225892d5dd48SViacheslav Ovsiienko } 225992d5dd48SViacheslav Ovsiienko } 226092d5dd48SViacheslav Ovsiienko if (!sh_conf) 226192d5dd48SViacheslav Ovsiienko return 0; 226292d5dd48SViacheslav Ovsiienko if (sh_conf->dv_flow_en ^ config->dv_flow_en) { 226392d5dd48SViacheslav Ovsiienko DRV_LOG(ERR, "\"dv_flow_en\" configuration mismatch" 226492d5dd48SViacheslav Ovsiienko " for shared %s context", sh->ibdev_name); 226592d5dd48SViacheslav Ovsiienko rte_errno = EINVAL; 226692d5dd48SViacheslav Ovsiienko return rte_errno; 226792d5dd48SViacheslav Ovsiienko } 22682d241515SViacheslav Ovsiienko if (sh_conf->dv_xmeta_en ^ config->dv_xmeta_en) { 22692d241515SViacheslav Ovsiienko DRV_LOG(ERR, "\"dv_xmeta_en\" configuration mismatch" 22702d241515SViacheslav Ovsiienko " for shared %s context", sh->ibdev_name); 22712d241515SViacheslav Ovsiienko rte_errno = EINVAL; 22722d241515SViacheslav Ovsiienko return rte_errno; 22732d241515SViacheslav Ovsiienko } 227492d5dd48SViacheslav Ovsiienko return 0; 227592d5dd48SViacheslav Ovsiienko } 227692d5dd48SViacheslav Ovsiienko /** 2277f38c5457SAdrien Mazarguil * Spawn an Ethernet device from Verbs information. 2278771fa900SAdrien Mazarguil * 2279f38c5457SAdrien Mazarguil * @param dpdk_dev 2280f38c5457SAdrien Mazarguil * Backing DPDK device. 2281ad74bc61SViacheslav Ovsiienko * @param spawn 2282ad74bc61SViacheslav Ovsiienko * Verbs device parameters (name, port, switch_info) to spawn. 2283f87bfa8eSYongseok Koh * @param config 2284f87bfa8eSYongseok Koh * Device configuration parameters. 2285771fa900SAdrien Mazarguil * 2286771fa900SAdrien Mazarguil * @return 2287f38c5457SAdrien Mazarguil * A valid Ethernet device object on success, NULL otherwise and rte_errno 2288206254b7SOphir Munk * is set. The following errors are defined: 22896de569f5SAdrien Mazarguil * 22906de569f5SAdrien Mazarguil * EBUSY: device is not supposed to be spawned. 2291206254b7SOphir Munk * EEXIST: device is already spawned 2292771fa900SAdrien Mazarguil */ 2293f38c5457SAdrien Mazarguil static struct rte_eth_dev * 2294f38c5457SAdrien Mazarguil mlx5_dev_spawn(struct rte_device *dpdk_dev, 2295ad74bc61SViacheslav Ovsiienko struct mlx5_dev_spawn_data *spawn, 2296ad74bc61SViacheslav Ovsiienko struct mlx5_dev_config config) 2297771fa900SAdrien Mazarguil { 2298ad74bc61SViacheslav Ovsiienko const struct mlx5_switch_info *switch_info = &spawn->info; 229917e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = NULL; 230068128934SAdrien Mazarguil struct ibv_port_attr port_attr; 23016057a10bSAdrien Mazarguil struct mlx5dv_context dv_attr = { .comp_mask = 0 }; 23029083982cSAdrien Mazarguil struct rte_eth_dev *eth_dev = NULL; 2303dbeba4cfSThomas Monjalon struct mlx5_priv *priv = NULL; 2304771fa900SAdrien Mazarguil int err = 0; 230578c7a16dSYongseok Koh unsigned int hw_padding = 0; 2306e192ef80SYaacov Hazan unsigned int mps; 2307523f5a74SYongseok Koh unsigned int cqe_comp; 2308bc91e8dbSYongseok Koh unsigned int cqe_pad = 0; 2309772d3435SXueming Li unsigned int tunnel_en = 0; 23101f106da2SMatan Azrad unsigned int mpls_en = 0; 23115f8ba81cSXueming Li unsigned int swp = 0; 23127d6bf6b8SYongseok Koh unsigned int mprq = 0; 23137d6bf6b8SYongseok Koh unsigned int mprq_min_stride_size_n = 0; 23147d6bf6b8SYongseok Koh unsigned int mprq_max_stride_size_n = 0; 23157d6bf6b8SYongseok Koh unsigned int mprq_min_stride_num_n = 0; 23167d6bf6b8SYongseok Koh unsigned int mprq_max_stride_num_n = 0; 23176d13ea8eSOlivier Matz struct rte_ether_addr mac; 231868128934SAdrien Mazarguil char name[RTE_ETH_NAME_MAX_LEN]; 23192b730263SAdrien Mazarguil int own_domain_id = 0; 2320206254b7SOphir Munk uint16_t port_id; 23212b730263SAdrien Mazarguil unsigned int i; 2322d5c06b1bSViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR_DEVX_PORT 232339139371SViacheslav Ovsiienko struct mlx5dv_devx_port devx_port = { .comp_mask = 0 }; 2324d5c06b1bSViacheslav Ovsiienko #endif 2325771fa900SAdrien Mazarguil 23266de569f5SAdrien Mazarguil /* Determine if this port representor is supposed to be spawned. */ 23276de569f5SAdrien Mazarguil if (switch_info->representor && dpdk_dev->devargs) { 23286de569f5SAdrien Mazarguil struct rte_eth_devargs eth_da; 23296de569f5SAdrien Mazarguil 23306de569f5SAdrien Mazarguil err = rte_eth_devargs_parse(dpdk_dev->devargs->args, ð_da); 23316de569f5SAdrien Mazarguil if (err) { 23326de569f5SAdrien Mazarguil rte_errno = -err; 23336de569f5SAdrien Mazarguil DRV_LOG(ERR, "failed to process device arguments: %s", 23346de569f5SAdrien Mazarguil strerror(rte_errno)); 23356de569f5SAdrien Mazarguil return NULL; 23366de569f5SAdrien Mazarguil } 23376de569f5SAdrien Mazarguil for (i = 0; i < eth_da.nb_representor_ports; ++i) 23386de569f5SAdrien Mazarguil if (eth_da.representor_ports[i] == 23396de569f5SAdrien Mazarguil (uint16_t)switch_info->port_name) 23406de569f5SAdrien Mazarguil break; 23416de569f5SAdrien Mazarguil if (i == eth_da.nb_representor_ports) { 23426de569f5SAdrien Mazarguil rte_errno = EBUSY; 23436de569f5SAdrien Mazarguil return NULL; 23446de569f5SAdrien Mazarguil } 23456de569f5SAdrien Mazarguil } 2346206254b7SOphir Munk /* Build device name. */ 234710dadfcbSViacheslav Ovsiienko if (spawn->pf_bond < 0) { 234810dadfcbSViacheslav Ovsiienko /* Single device. */ 2349206254b7SOphir Munk if (!switch_info->representor) 235009c9c4d2SThomas Monjalon strlcpy(name, dpdk_dev->name, sizeof(name)); 2351206254b7SOphir Munk else 2352206254b7SOphir Munk snprintf(name, sizeof(name), "%s_representor_%u", 2353206254b7SOphir Munk dpdk_dev->name, switch_info->port_name); 235410dadfcbSViacheslav Ovsiienko } else { 235510dadfcbSViacheslav Ovsiienko /* Bonding device. */ 235610dadfcbSViacheslav Ovsiienko if (!switch_info->representor) 235710dadfcbSViacheslav Ovsiienko snprintf(name, sizeof(name), "%s_%s", 235810dadfcbSViacheslav Ovsiienko dpdk_dev->name, spawn->ibv_dev->name); 235910dadfcbSViacheslav Ovsiienko else 236010dadfcbSViacheslav Ovsiienko snprintf(name, sizeof(name), "%s_%s_representor_%u", 236110dadfcbSViacheslav Ovsiienko dpdk_dev->name, spawn->ibv_dev->name, 236210dadfcbSViacheslav Ovsiienko switch_info->port_name); 236310dadfcbSViacheslav Ovsiienko } 2364206254b7SOphir Munk /* check if the device is already spawned */ 2365206254b7SOphir Munk if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) { 2366206254b7SOphir Munk rte_errno = EEXIST; 2367206254b7SOphir Munk return NULL; 2368206254b7SOphir Munk } 236917e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name); 237017e19bc4SViacheslav Ovsiienko if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 2371a4de9586SVu Pham struct mlx5_mp_id mp_id; 2372a4de9586SVu Pham 237317e19bc4SViacheslav Ovsiienko eth_dev = rte_eth_dev_attach_secondary(name); 237417e19bc4SViacheslav Ovsiienko if (eth_dev == NULL) { 237517e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "can not attach rte ethdev"); 237617e19bc4SViacheslav Ovsiienko rte_errno = ENOMEM; 2377f38c5457SAdrien Mazarguil return NULL; 2378771fa900SAdrien Mazarguil } 237917e19bc4SViacheslav Ovsiienko eth_dev->device = dpdk_dev; 238017e19bc4SViacheslav Ovsiienko eth_dev->dev_ops = &mlx5_dev_sec_ops; 2381120dc4a7SYongseok Koh err = mlx5_proc_priv_init(eth_dev); 2382120dc4a7SYongseok Koh if (err) 2383120dc4a7SYongseok Koh return NULL; 2384a4de9586SVu Pham mp_id.port_id = eth_dev->data->port_id; 2385a4de9586SVu Pham strlcpy(mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 238617e19bc4SViacheslav Ovsiienko /* Receive command fd from primary process */ 2387a4de9586SVu Pham err = mlx5_mp_req_verbs_cmd_fd(&mp_id); 238817e19bc4SViacheslav Ovsiienko if (err < 0) 238917e19bc4SViacheslav Ovsiienko return NULL; 239017e19bc4SViacheslav Ovsiienko /* Remap UAR for Tx queues. */ 2391120dc4a7SYongseok Koh err = mlx5_tx_uar_init_secondary(eth_dev, err); 239217e19bc4SViacheslav Ovsiienko if (err) 239317e19bc4SViacheslav Ovsiienko return NULL; 239417e19bc4SViacheslav Ovsiienko /* 239517e19bc4SViacheslav Ovsiienko * Ethdev pointer is still required as input since 239617e19bc4SViacheslav Ovsiienko * the primary device is not accessible from the 239717e19bc4SViacheslav Ovsiienko * secondary process. 239817e19bc4SViacheslav Ovsiienko */ 239917e19bc4SViacheslav Ovsiienko eth_dev->rx_pkt_burst = mlx5_select_rx_function(eth_dev); 240017e19bc4SViacheslav Ovsiienko eth_dev->tx_pkt_burst = mlx5_select_tx_function(eth_dev); 240117e19bc4SViacheslav Ovsiienko return eth_dev; 2402f5bf91deSMoti Haimovsky } 24038409a285SViacheslav Ovsiienko /* 24048409a285SViacheslav Ovsiienko * Some parameters ("tx_db_nc" in particularly) are needed in 24058409a285SViacheslav Ovsiienko * advance to create dv/verbs device context. We proceed the 24068409a285SViacheslav Ovsiienko * devargs here to get ones, and later proceed devargs again 24078409a285SViacheslav Ovsiienko * to override some hardware settings. 24088409a285SViacheslav Ovsiienko */ 24098409a285SViacheslav Ovsiienko err = mlx5_args(&config, dpdk_dev->devargs); 24108409a285SViacheslav Ovsiienko if (err) { 24118409a285SViacheslav Ovsiienko err = rte_errno; 24128409a285SViacheslav Ovsiienko DRV_LOG(ERR, "failed to process device arguments: %s", 24138409a285SViacheslav Ovsiienko strerror(rte_errno)); 24148409a285SViacheslav Ovsiienko goto error; 24158409a285SViacheslav Ovsiienko } 24168409a285SViacheslav Ovsiienko sh = mlx5_alloc_shared_ibctx(spawn, &config); 241717e19bc4SViacheslav Ovsiienko if (!sh) 241817e19bc4SViacheslav Ovsiienko return NULL; 241917e19bc4SViacheslav Ovsiienko config.devx = sh->devx; 24203075bd23SDekel Peled #ifdef HAVE_MLX5DV_DR_ACTION_DEST_DEVX_TIR 24213075bd23SDekel Peled config.dest_tir = 1; 24223075bd23SDekel Peled #endif 24235f8ba81cSXueming Li #ifdef HAVE_IBV_MLX5_MOD_SWP 24246057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP; 24255f8ba81cSXueming Li #endif 242643e9d979SShachar Beiser /* 242743e9d979SShachar Beiser * Multi-packet send is supported by ConnectX-4 Lx PF as well 242843e9d979SShachar Beiser * as all ConnectX-5 devices. 242943e9d979SShachar Beiser */ 2430038e7251SShahaf Shuler #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 24316057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_TUNNEL_OFFLOADS; 2432038e7251SShahaf Shuler #endif 24337d6bf6b8SYongseok Koh #ifdef HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT 24346057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_STRIDING_RQ; 24357d6bf6b8SYongseok Koh #endif 243617e19bc4SViacheslav Ovsiienko mlx5_glue->dv_query_device(sh->ctx, &dv_attr); 24376057a10bSAdrien Mazarguil if (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED) { 24386057a10bSAdrien Mazarguil if (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW) { 2439a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "enhanced MPW is supported"); 244043e9d979SShachar Beiser mps = MLX5_MPW_ENHANCED; 244143e9d979SShachar Beiser } else { 2442a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "MPW is supported"); 2443e589960cSYongseok Koh mps = MLX5_MPW; 2444e589960cSYongseok Koh } 2445e589960cSYongseok Koh } else { 2446a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "MPW isn't supported"); 244743e9d979SShachar Beiser mps = MLX5_MPW_DISABLED; 244843e9d979SShachar Beiser } 24495f8ba81cSXueming Li #ifdef HAVE_IBV_MLX5_MOD_SWP 24506057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_SWP) 24516057a10bSAdrien Mazarguil swp = dv_attr.sw_parsing_caps.sw_parsing_offloads; 24525f8ba81cSXueming Li DRV_LOG(DEBUG, "SWP support: %u", swp); 24535f8ba81cSXueming Li #endif 245468128934SAdrien Mazarguil config.swp = !!swp; 24557d6bf6b8SYongseok Koh #ifdef HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT 24566057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_STRIDING_RQ) { 24577d6bf6b8SYongseok Koh struct mlx5dv_striding_rq_caps mprq_caps = 24586057a10bSAdrien Mazarguil dv_attr.striding_rq_caps; 24597d6bf6b8SYongseok Koh 24607d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmin_single_stride_log_num_of_bytes: %d", 24617d6bf6b8SYongseok Koh mprq_caps.min_single_stride_log_num_of_bytes); 24627d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmax_single_stride_log_num_of_bytes: %d", 24637d6bf6b8SYongseok Koh mprq_caps.max_single_stride_log_num_of_bytes); 24647d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmin_single_wqe_log_num_of_strides: %d", 24657d6bf6b8SYongseok Koh mprq_caps.min_single_wqe_log_num_of_strides); 24667d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmax_single_wqe_log_num_of_strides: %d", 24677d6bf6b8SYongseok Koh mprq_caps.max_single_wqe_log_num_of_strides); 24687d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tsupported_qpts: %d", 24697d6bf6b8SYongseok Koh mprq_caps.supported_qpts); 24707d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "device supports Multi-Packet RQ"); 24717d6bf6b8SYongseok Koh mprq = 1; 24727d6bf6b8SYongseok Koh mprq_min_stride_size_n = 24737d6bf6b8SYongseok Koh mprq_caps.min_single_stride_log_num_of_bytes; 24747d6bf6b8SYongseok Koh mprq_max_stride_size_n = 24757d6bf6b8SYongseok Koh mprq_caps.max_single_stride_log_num_of_bytes; 24767d6bf6b8SYongseok Koh mprq_min_stride_num_n = 24777d6bf6b8SYongseok Koh mprq_caps.min_single_wqe_log_num_of_strides; 24787d6bf6b8SYongseok Koh mprq_max_stride_num_n = 24797d6bf6b8SYongseok Koh mprq_caps.max_single_wqe_log_num_of_strides; 24807d6bf6b8SYongseok Koh } 24817d6bf6b8SYongseok Koh #endif 2482523f5a74SYongseok Koh if (RTE_CACHE_LINE_SIZE == 128 && 24836057a10bSAdrien Mazarguil !(dv_attr.flags & MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP)) 2484523f5a74SYongseok Koh cqe_comp = 0; 2485523f5a74SYongseok Koh else 2486523f5a74SYongseok Koh cqe_comp = 1; 248768128934SAdrien Mazarguil config.cqe_comp = cqe_comp; 2488bc91e8dbSYongseok Koh #ifdef HAVE_IBV_MLX5_MOD_CQE_128B_PAD 2489bc91e8dbSYongseok Koh /* Whether device supports 128B Rx CQE padding. */ 2490bc91e8dbSYongseok Koh cqe_pad = RTE_CACHE_LINE_SIZE == 128 && 2491bc91e8dbSYongseok Koh (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD); 2492bc91e8dbSYongseok Koh #endif 2493038e7251SShahaf Shuler #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 24946057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_TUNNEL_OFFLOADS) { 24956057a10bSAdrien Mazarguil tunnel_en = ((dv_attr.tunnel_offloads_caps & 2496038e7251SShahaf Shuler MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_VXLAN) && 24976057a10bSAdrien Mazarguil (dv_attr.tunnel_offloads_caps & 24984acb96fdSSuanming Mou MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_GRE) && 24994acb96fdSSuanming Mou (dv_attr.tunnel_offloads_caps & 25004acb96fdSSuanming Mou MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_GENEVE)); 2501038e7251SShahaf Shuler } 2502a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "tunnel offloading is %ssupported", 2503a170a30dSNélio Laranjeiro tunnel_en ? "" : "not "); 2504038e7251SShahaf Shuler #else 2505a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 2506a170a30dSNélio Laranjeiro "tunnel offloading disabled due to old OFED/rdma-core version"); 2507038e7251SShahaf Shuler #endif 250868128934SAdrien Mazarguil config.tunnel_en = tunnel_en; 25091f106da2SMatan Azrad #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 25106057a10bSAdrien Mazarguil mpls_en = ((dv_attr.tunnel_offloads_caps & 25111f106da2SMatan Azrad MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_CW_MPLS_OVER_GRE) && 25126057a10bSAdrien Mazarguil (dv_attr.tunnel_offloads_caps & 25131f106da2SMatan Azrad MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_CW_MPLS_OVER_UDP)); 25141f106da2SMatan Azrad DRV_LOG(DEBUG, "MPLS over GRE/UDP tunnel offloading is %ssupported", 25151f106da2SMatan Azrad mpls_en ? "" : "not "); 25161f106da2SMatan Azrad #else 25171f106da2SMatan Azrad DRV_LOG(WARNING, "MPLS over GRE/UDP tunnel offloading disabled due to" 25181f106da2SMatan Azrad " old OFED/rdma-core version or firmware configuration"); 25191f106da2SMatan Azrad #endif 252068128934SAdrien Mazarguil config.mpls_en = mpls_en; 2521771fa900SAdrien Mazarguil /* Check port status. */ 252217e19bc4SViacheslav Ovsiienko err = mlx5_glue->query_port(sh->ctx, spawn->ibv_port, &port_attr); 2523771fa900SAdrien Mazarguil if (err) { 2524a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port query failed: %s", strerror(err)); 25259083982cSAdrien Mazarguil goto error; 2526771fa900SAdrien Mazarguil } 25271371f4dfSOr Ami if (port_attr.link_layer != IBV_LINK_LAYER_ETHERNET) { 25289083982cSAdrien Mazarguil DRV_LOG(ERR, "port is not configured in Ethernet mode"); 2529e1c3e305SMatan Azrad err = EINVAL; 25309083982cSAdrien Mazarguil goto error; 25311371f4dfSOr Ami } 2532771fa900SAdrien Mazarguil if (port_attr.state != IBV_PORT_ACTIVE) 25339083982cSAdrien Mazarguil DRV_LOG(DEBUG, "port is not active: \"%s\" (%d)", 2534a170a30dSNélio Laranjeiro mlx5_glue->port_state_str(port_attr.state), 2535771fa900SAdrien Mazarguil port_attr.state); 253617e19bc4SViacheslav Ovsiienko /* Allocate private eth device data. */ 2537771fa900SAdrien Mazarguil priv = rte_zmalloc("ethdev private structure", 2538771fa900SAdrien Mazarguil sizeof(*priv), 2539771fa900SAdrien Mazarguil RTE_CACHE_LINE_SIZE); 2540771fa900SAdrien Mazarguil if (priv == NULL) { 2541a170a30dSNélio Laranjeiro DRV_LOG(ERR, "priv allocation failure"); 2542771fa900SAdrien Mazarguil err = ENOMEM; 25439083982cSAdrien Mazarguil goto error; 2544771fa900SAdrien Mazarguil } 254517e19bc4SViacheslav Ovsiienko priv->sh = sh; 254617e19bc4SViacheslav Ovsiienko priv->ibv_port = spawn->ibv_port; 254746e10a4cSViacheslav Ovsiienko priv->pci_dev = spawn->pci_dev; 254835b2d13fSOlivier Matz priv->mtu = RTE_ETHER_MTU; 2549a4de9586SVu Pham priv->mp_id.port_id = port_id; 2550a4de9586SVu Pham strlcpy(priv->mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 25516bf10ab6SMoti Haimovsky #ifndef RTE_ARCH_64 25526bf10ab6SMoti Haimovsky /* Initialize UAR access locks for 32bit implementations. */ 25536bf10ab6SMoti Haimovsky rte_spinlock_init(&priv->uar_lock_cq); 25546bf10ab6SMoti Haimovsky for (i = 0; i < MLX5_UAR_PAGE_NUM_MAX; i++) 25556bf10ab6SMoti Haimovsky rte_spinlock_init(&priv->uar_lock[i]); 25566bf10ab6SMoti Haimovsky #endif 255726c08b97SAdrien Mazarguil /* Some internal functions rely on Netlink sockets, open them now. */ 25585366074bSNelio Laranjeiro priv->nl_socket_rdma = mlx5_nl_init(NETLINK_RDMA); 25595366074bSNelio Laranjeiro priv->nl_socket_route = mlx5_nl_init(NETLINK_ROUTE); 25602b730263SAdrien Mazarguil priv->representor = !!switch_info->representor; 2561299d7dc2SViacheslav Ovsiienko priv->master = !!switch_info->master; 25622b730263SAdrien Mazarguil priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 2563d5c06b1bSViacheslav Ovsiienko priv->vport_meta_tag = 0; 2564d5c06b1bSViacheslav Ovsiienko priv->vport_meta_mask = 0; 2565bee57a0aSViacheslav Ovsiienko priv->pf_bond = spawn->pf_bond; 2566d5c06b1bSViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR_DEVX_PORT 2567299d7dc2SViacheslav Ovsiienko /* 2568d5c06b1bSViacheslav Ovsiienko * The DevX port query API is implemented. E-Switch may use 2569d5c06b1bSViacheslav Ovsiienko * either vport or reg_c[0] metadata register to match on 2570d5c06b1bSViacheslav Ovsiienko * vport index. The engaged part of metadata register is 2571d5c06b1bSViacheslav Ovsiienko * defined by mask. 2572d5c06b1bSViacheslav Ovsiienko */ 257339139371SViacheslav Ovsiienko if (switch_info->representor || switch_info->master) { 2574d5c06b1bSViacheslav Ovsiienko devx_port.comp_mask = MLX5DV_DEVX_PORT_VPORT | 2575d5c06b1bSViacheslav Ovsiienko MLX5DV_DEVX_PORT_MATCH_REG_C_0; 257639139371SViacheslav Ovsiienko err = mlx5_glue->devx_port_query(sh->ctx, spawn->ibv_port, 257739139371SViacheslav Ovsiienko &devx_port); 2578d5c06b1bSViacheslav Ovsiienko if (err) { 257939139371SViacheslav Ovsiienko DRV_LOG(WARNING, 258039139371SViacheslav Ovsiienko "can't query devx port %d on device %s", 2581d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2582d5c06b1bSViacheslav Ovsiienko devx_port.comp_mask = 0; 2583d5c06b1bSViacheslav Ovsiienko } 258439139371SViacheslav Ovsiienko } 2585d5c06b1bSViacheslav Ovsiienko if (devx_port.comp_mask & MLX5DV_DEVX_PORT_MATCH_REG_C_0) { 2586d5c06b1bSViacheslav Ovsiienko priv->vport_meta_tag = devx_port.reg_c_0.value; 2587d5c06b1bSViacheslav Ovsiienko priv->vport_meta_mask = devx_port.reg_c_0.mask; 2588d5c06b1bSViacheslav Ovsiienko if (!priv->vport_meta_mask) { 2589d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "vport zero mask for port %d" 259006fa6988SDekel Peled " on bonding device %s", 2591d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2592d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2593d5c06b1bSViacheslav Ovsiienko goto error; 2594d5c06b1bSViacheslav Ovsiienko } 2595d5c06b1bSViacheslav Ovsiienko if (priv->vport_meta_tag & ~priv->vport_meta_mask) { 2596d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "invalid vport tag for port %d" 259706fa6988SDekel Peled " on bonding device %s", 2598d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2599d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2600d5c06b1bSViacheslav Ovsiienko goto error; 2601d5c06b1bSViacheslav Ovsiienko } 260285c4bcbcSViacheslav Ovsiienko } 260385c4bcbcSViacheslav Ovsiienko if (devx_port.comp_mask & MLX5DV_DEVX_PORT_VPORT) { 2604d5c06b1bSViacheslav Ovsiienko priv->vport_id = devx_port.vport_num; 2605d5c06b1bSViacheslav Ovsiienko } else if (spawn->pf_bond >= 0) { 2606d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "can't deduce vport index for port %d" 260706fa6988SDekel Peled " on bonding device %s", 2608d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2609d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2610d5c06b1bSViacheslav Ovsiienko goto error; 2611d5c06b1bSViacheslav Ovsiienko } else { 2612d5c06b1bSViacheslav Ovsiienko /* Suppose vport index in compatible way. */ 2613d5c06b1bSViacheslav Ovsiienko priv->vport_id = switch_info->representor ? 2614d5c06b1bSViacheslav Ovsiienko switch_info->port_name + 1 : -1; 2615d5c06b1bSViacheslav Ovsiienko } 2616d5c06b1bSViacheslav Ovsiienko #else 2617d5c06b1bSViacheslav Ovsiienko /* 2618d5c06b1bSViacheslav Ovsiienko * Kernel/rdma_core support single E-Switch per PF configurations 2619299d7dc2SViacheslav Ovsiienko * only and vport_id field contains the vport index for 2620299d7dc2SViacheslav Ovsiienko * associated VF, which is deduced from representor port name. 2621ae4eb7dcSViacheslav Ovsiienko * For example, let's have the IB device port 10, it has 2622299d7dc2SViacheslav Ovsiienko * attached network device eth0, which has port name attribute 2623299d7dc2SViacheslav Ovsiienko * pf0vf2, we can deduce the VF number as 2, and set vport index 2624299d7dc2SViacheslav Ovsiienko * as 3 (2+1). This assigning schema should be changed if the 2625299d7dc2SViacheslav Ovsiienko * multiple E-Switch instances per PF configurations or/and PCI 2626299d7dc2SViacheslav Ovsiienko * subfunctions are added. 2627299d7dc2SViacheslav Ovsiienko */ 2628299d7dc2SViacheslav Ovsiienko priv->vport_id = switch_info->representor ? 2629299d7dc2SViacheslav Ovsiienko switch_info->port_name + 1 : -1; 2630d5c06b1bSViacheslav Ovsiienko #endif 2631d5c06b1bSViacheslav Ovsiienko /* representor_id field keeps the unmodified VF index. */ 2632299d7dc2SViacheslav Ovsiienko priv->representor_id = switch_info->representor ? 2633299d7dc2SViacheslav Ovsiienko switch_info->port_name : -1; 26342b730263SAdrien Mazarguil /* 26352b730263SAdrien Mazarguil * Look for sibling devices in order to reuse their switch domain 26362b730263SAdrien Mazarguil * if any, otherwise allocate one. 26372b730263SAdrien Mazarguil */ 2638fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 2639dbeba4cfSThomas Monjalon const struct mlx5_priv *opriv = 2640d874a4eeSThomas Monjalon rte_eth_devices[port_id].data->dev_private; 26412b730263SAdrien Mazarguil 26422b730263SAdrien Mazarguil if (!opriv || 2643f7e95215SViacheslav Ovsiienko opriv->sh != priv->sh || 26442b730263SAdrien Mazarguil opriv->domain_id == 26452b730263SAdrien Mazarguil RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) 26462b730263SAdrien Mazarguil continue; 26472b730263SAdrien Mazarguil priv->domain_id = opriv->domain_id; 26482b730263SAdrien Mazarguil break; 26492b730263SAdrien Mazarguil } 26502b730263SAdrien Mazarguil if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 26512b730263SAdrien Mazarguil err = rte_eth_switch_domain_alloc(&priv->domain_id); 26522b730263SAdrien Mazarguil if (err) { 26532b730263SAdrien Mazarguil err = rte_errno; 26542b730263SAdrien Mazarguil DRV_LOG(ERR, "unable to allocate switch domain: %s", 26552b730263SAdrien Mazarguil strerror(rte_errno)); 26562b730263SAdrien Mazarguil goto error; 26572b730263SAdrien Mazarguil } 26582b730263SAdrien Mazarguil own_domain_id = 1; 26592b730263SAdrien Mazarguil } 26608409a285SViacheslav Ovsiienko /* Override some values set by hardware configuration. */ 26618409a285SViacheslav Ovsiienko mlx5_args(&config, dpdk_dev->devargs); 266292d5dd48SViacheslav Ovsiienko err = mlx5_dev_check_sibling_config(priv, &config); 266392d5dd48SViacheslav Ovsiienko if (err) 266492d5dd48SViacheslav Ovsiienko goto error; 266517e19bc4SViacheslav Ovsiienko config.hw_csum = !!(sh->device_attr.device_cap_flags_ex & 266617e19bc4SViacheslav Ovsiienko IBV_DEVICE_RAW_IP_CSUM); 2667a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "checksum offloading is %ssupported", 26687fe24446SShahaf Shuler (config.hw_csum ? "" : "not ")); 26692dd8b721SViacheslav Ovsiienko #if !defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) && \ 26702dd8b721SViacheslav Ovsiienko !defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 26712dd8b721SViacheslav Ovsiienko DRV_LOG(DEBUG, "counters are not supported"); 26729a761de8SOri Kam #endif 26730adf23adSDekel Peled #if !defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_MLX5DV_DR) 267458b1312eSYongseok Koh if (config.dv_flow_en) { 267558b1312eSYongseok Koh DRV_LOG(WARNING, "DV flow is not supported"); 267658b1312eSYongseok Koh config.dv_flow_en = 0; 267758b1312eSYongseok Koh } 267858b1312eSYongseok Koh #endif 26797fe24446SShahaf Shuler config.ind_table_max_size = 268017e19bc4SViacheslav Ovsiienko sh->device_attr.rss_caps.max_rwq_indirection_table_size; 268168128934SAdrien Mazarguil /* 268268128934SAdrien Mazarguil * Remove this check once DPDK supports larger/variable 268368128934SAdrien Mazarguil * indirection tables. 268468128934SAdrien Mazarguil */ 268568128934SAdrien Mazarguil if (config.ind_table_max_size > (unsigned int)ETH_RSS_RETA_SIZE_512) 26867fe24446SShahaf Shuler config.ind_table_max_size = ETH_RSS_RETA_SIZE_512; 2687a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "maximum Rx indirection table size is %u", 26887fe24446SShahaf Shuler config.ind_table_max_size); 268917e19bc4SViacheslav Ovsiienko config.hw_vlan_strip = !!(sh->device_attr.raw_packet_caps & 269043e9d979SShachar Beiser IBV_RAW_PACKET_CAP_CVLAN_STRIPPING); 2691a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "VLAN stripping is %ssupported", 26927fe24446SShahaf Shuler (config.hw_vlan_strip ? "" : "not ")); 269317e19bc4SViacheslav Ovsiienko config.hw_fcs_strip = !!(sh->device_attr.raw_packet_caps & 2694cd230a3eSShahaf Shuler IBV_RAW_PACKET_CAP_SCATTER_FCS); 2695a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "FCS stripping configuration is %ssupported", 26967fe24446SShahaf Shuler (config.hw_fcs_strip ? "" : "not ")); 26972014a7fbSYongseok Koh #if defined(HAVE_IBV_WQ_FLAG_RX_END_PADDING) 269817e19bc4SViacheslav Ovsiienko hw_padding = !!sh->device_attr.rx_pad_end_addr_align; 26992014a7fbSYongseok Koh #elif defined(HAVE_IBV_WQ_FLAGS_PCI_WRITE_END_PADDING) 270017e19bc4SViacheslav Ovsiienko hw_padding = !!(sh->device_attr.device_cap_flags_ex & 27012014a7fbSYongseok Koh IBV_DEVICE_PCI_WRITE_END_PADDING); 270243e9d979SShachar Beiser #endif 270378c7a16dSYongseok Koh if (config.hw_padding && !hw_padding) { 270478c7a16dSYongseok Koh DRV_LOG(DEBUG, "Rx end alignment padding isn't supported"); 270578c7a16dSYongseok Koh config.hw_padding = 0; 270678c7a16dSYongseok Koh } else if (config.hw_padding) { 270778c7a16dSYongseok Koh DRV_LOG(DEBUG, "Rx end alignment padding is enabled"); 270878c7a16dSYongseok Koh } 270917e19bc4SViacheslav Ovsiienko config.tso = (sh->device_attr.tso_caps.max_tso > 0 && 271017e19bc4SViacheslav Ovsiienko (sh->device_attr.tso_caps.supported_qpts & 271143e9d979SShachar Beiser (1 << IBV_QPT_RAW_PACKET))); 27127fe24446SShahaf Shuler if (config.tso) 271317e19bc4SViacheslav Ovsiienko config.tso_max_payload_sz = sh->device_attr.tso_caps.max_tso; 2714f9de8718SShahaf Shuler /* 2715f9de8718SShahaf Shuler * MPW is disabled by default, while the Enhanced MPW is enabled 2716f9de8718SShahaf Shuler * by default. 2717f9de8718SShahaf Shuler */ 2718f9de8718SShahaf Shuler if (config.mps == MLX5_ARG_UNSET) 2719f9de8718SShahaf Shuler config.mps = (mps == MLX5_MPW_ENHANCED) ? MLX5_MPW_ENHANCED : 2720f9de8718SShahaf Shuler MLX5_MPW_DISABLED; 2721f9de8718SShahaf Shuler else 2722f9de8718SShahaf Shuler config.mps = config.mps ? mps : MLX5_MPW_DISABLED; 2723a170a30dSNélio Laranjeiro DRV_LOG(INFO, "%sMPS is %s", 272482e75f83SViacheslav Ovsiienko config.mps == MLX5_MPW_ENHANCED ? "enhanced " : 272582e75f83SViacheslav Ovsiienko config.mps == MLX5_MPW ? "legacy " : "", 272668128934SAdrien Mazarguil config.mps != MLX5_MPW_DISABLED ? "enabled" : "disabled"); 27277fe24446SShahaf Shuler if (config.cqe_comp && !cqe_comp) { 2728a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "Rx CQE compression isn't supported"); 27297fe24446SShahaf Shuler config.cqe_comp = 0; 2730523f5a74SYongseok Koh } 2731bc91e8dbSYongseok Koh if (config.cqe_pad && !cqe_pad) { 2732bc91e8dbSYongseok Koh DRV_LOG(WARNING, "Rx CQE padding isn't supported"); 2733bc91e8dbSYongseok Koh config.cqe_pad = 0; 2734bc91e8dbSYongseok Koh } else if (config.cqe_pad) { 2735bc91e8dbSYongseok Koh DRV_LOG(INFO, "Rx CQE padding is enabled"); 2736bc91e8dbSYongseok Koh } 2737175f1c21SDekel Peled if (config.devx) { 2738175f1c21SDekel Peled priv->counter_fallback = 0; 2739175f1c21SDekel Peled err = mlx5_devx_cmd_query_hca_attr(sh->ctx, &config.hca_attr); 2740175f1c21SDekel Peled if (err) { 2741175f1c21SDekel Peled err = -err; 2742175f1c21SDekel Peled goto error; 2743175f1c21SDekel Peled } 2744175f1c21SDekel Peled if (!config.hca_attr.flow_counters_dump) 2745175f1c21SDekel Peled priv->counter_fallback = 1; 2746175f1c21SDekel Peled #ifndef HAVE_IBV_DEVX_ASYNC 2747175f1c21SDekel Peled priv->counter_fallback = 1; 2748175f1c21SDekel Peled #endif 2749175f1c21SDekel Peled if (priv->counter_fallback) 275006fa6988SDekel Peled DRV_LOG(INFO, "Use fall-back DV counter management"); 2751175f1c21SDekel Peled /* Check for LRO support. */ 27522eb5dce8SDekel Peled if (config.dest_tir && config.hca_attr.lro_cap && 27532eb5dce8SDekel Peled config.dv_flow_en) { 2754175f1c21SDekel Peled /* TBD check tunnel lro caps. */ 2755175f1c21SDekel Peled config.lro.supported = config.hca_attr.lro_cap; 2756175f1c21SDekel Peled DRV_LOG(DEBUG, "Device supports LRO"); 2757175f1c21SDekel Peled /* 2758175f1c21SDekel Peled * If LRO timeout is not configured by application, 2759175f1c21SDekel Peled * use the minimal supported value. 2760175f1c21SDekel Peled */ 2761175f1c21SDekel Peled if (!config.lro.timeout) 2762175f1c21SDekel Peled config.lro.timeout = 2763175f1c21SDekel Peled config.hca_attr.lro_timer_supported_periods[0]; 2764175f1c21SDekel Peled DRV_LOG(DEBUG, "LRO session timeout set to %d usec", 2765175f1c21SDekel Peled config.lro.timeout); 2766175f1c21SDekel Peled } 27676bc327b9SSuanming Mou #if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER) 27686bc327b9SSuanming Mou if (config.hca_attr.qos.sup && config.hca_attr.qos.srtcm_sup && 27696bc327b9SSuanming Mou config.dv_flow_en) { 277027efd5deSSuanming Mou uint8_t reg_c_mask = 277127efd5deSSuanming Mou config.hca_attr.qos.flow_meter_reg_c_ids; 277227efd5deSSuanming Mou /* 277327efd5deSSuanming Mou * Meter needs two REG_C's for color match and pre-sfx 277427efd5deSSuanming Mou * flow match. Here get the REG_C for color match. 277527efd5deSSuanming Mou * REG_C_0 and REG_C_1 is reserved for metadata feature. 277627efd5deSSuanming Mou */ 277727efd5deSSuanming Mou reg_c_mask &= 0xfc; 277827efd5deSSuanming Mou if (__builtin_popcount(reg_c_mask) < 1) { 277927efd5deSSuanming Mou priv->mtr_en = 0; 278027efd5deSSuanming Mou DRV_LOG(WARNING, "No available register for" 278127efd5deSSuanming Mou " meter."); 278227efd5deSSuanming Mou } else { 278327efd5deSSuanming Mou priv->mtr_color_reg = ffs(reg_c_mask) - 1 + 278427efd5deSSuanming Mou REG_C_0; 27856bc327b9SSuanming Mou priv->mtr_en = 1; 2786792e749eSSuanming Mou priv->mtr_reg_share = 2787792e749eSSuanming Mou config.hca_attr.qos.flow_meter_reg_share; 278827efd5deSSuanming Mou DRV_LOG(DEBUG, "The REG_C meter uses is %d", 278927efd5deSSuanming Mou priv->mtr_color_reg); 279027efd5deSSuanming Mou } 27916bc327b9SSuanming Mou } 27926bc327b9SSuanming Mou #endif 2793175f1c21SDekel Peled } 27945c0e2db6SYongseok Koh if (config.mprq.enabled && mprq) { 2795ecb16045SAlexander Kozyrev if (config.mprq.stride_num_n && 2796ecb16045SAlexander Kozyrev (config.mprq.stride_num_n > mprq_max_stride_num_n || 2797ecb16045SAlexander Kozyrev config.mprq.stride_num_n < mprq_min_stride_num_n)) { 27987d6bf6b8SYongseok Koh config.mprq.stride_num_n = 2799ecb16045SAlexander Kozyrev RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_NUM_N, 2800ecb16045SAlexander Kozyrev mprq_min_stride_num_n), 2801ecb16045SAlexander Kozyrev mprq_max_stride_num_n); 28027d6bf6b8SYongseok Koh DRV_LOG(WARNING, 28037d6bf6b8SYongseok Koh "the number of strides" 28047d6bf6b8SYongseok Koh " for Multi-Packet RQ is out of range," 28057d6bf6b8SYongseok Koh " setting default value (%u)", 28067d6bf6b8SYongseok Koh 1 << config.mprq.stride_num_n); 28077d6bf6b8SYongseok Koh } 2808ecb16045SAlexander Kozyrev if (config.mprq.stride_size_n && 2809ecb16045SAlexander Kozyrev (config.mprq.stride_size_n > mprq_max_stride_size_n || 2810ecb16045SAlexander Kozyrev config.mprq.stride_size_n < mprq_min_stride_size_n)) { 2811ecb16045SAlexander Kozyrev config.mprq.stride_size_n = 2812ecb16045SAlexander Kozyrev RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_SIZE_N, 2813ecb16045SAlexander Kozyrev mprq_min_stride_size_n), 2814ecb16045SAlexander Kozyrev mprq_max_stride_size_n); 2815ecb16045SAlexander Kozyrev DRV_LOG(WARNING, 2816ecb16045SAlexander Kozyrev "the size of a stride" 2817ecb16045SAlexander Kozyrev " for Multi-Packet RQ is out of range," 2818ecb16045SAlexander Kozyrev " setting default value (%u)", 2819ecb16045SAlexander Kozyrev 1 << config.mprq.stride_size_n); 2820ecb16045SAlexander Kozyrev } 28217d6bf6b8SYongseok Koh config.mprq.min_stride_size_n = mprq_min_stride_size_n; 28227d6bf6b8SYongseok Koh config.mprq.max_stride_size_n = mprq_max_stride_size_n; 28235c0e2db6SYongseok Koh } else if (config.mprq.enabled && !mprq) { 28245c0e2db6SYongseok Koh DRV_LOG(WARNING, "Multi-Packet RQ isn't supported"); 28255c0e2db6SYongseok Koh config.mprq.enabled = 0; 28267d6bf6b8SYongseok Koh } 2827066cfecdSMatan Azrad if (config.max_dump_files_num == 0) 2828066cfecdSMatan Azrad config.max_dump_files_num = 128; 2829af4f09f2SNélio Laranjeiro eth_dev = rte_eth_dev_allocate(name); 2830af4f09f2SNélio Laranjeiro if (eth_dev == NULL) { 2831a170a30dSNélio Laranjeiro DRV_LOG(ERR, "can not allocate rte ethdev"); 2832af4f09f2SNélio Laranjeiro err = ENOMEM; 28339083982cSAdrien Mazarguil goto error; 2834af4f09f2SNélio Laranjeiro } 283515febafdSThomas Monjalon /* Flag to call rte_eth_dev_release_port() in rte_eth_dev_close(). */ 283615febafdSThomas Monjalon eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; 2837a7d3c627SThomas Monjalon if (priv->representor) { 28382b730263SAdrien Mazarguil eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; 2839a7d3c627SThomas Monjalon eth_dev->data->representor_id = priv->representor_id; 2840a7d3c627SThomas Monjalon } 2841fa2e14d4SViacheslav Ovsiienko /* 2842fa2e14d4SViacheslav Ovsiienko * Store associated network device interface index. This index 2843fa2e14d4SViacheslav Ovsiienko * is permanent throughout the lifetime of device. So, we may store 2844fa2e14d4SViacheslav Ovsiienko * the ifindex here and use the cached value further. 2845fa2e14d4SViacheslav Ovsiienko */ 28468e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn->ifindex); 2847fa2e14d4SViacheslav Ovsiienko priv->if_index = spawn->ifindex; 2848af4f09f2SNélio Laranjeiro eth_dev->data->dev_private = priv; 2849df428ceeSYongseok Koh priv->dev_data = eth_dev->data; 2850af4f09f2SNélio Laranjeiro eth_dev->data->mac_addrs = priv->mac; 2851f38c5457SAdrien Mazarguil eth_dev->device = dpdk_dev; 2852771fa900SAdrien Mazarguil /* Configure the first MAC address by default. */ 2853af4f09f2SNélio Laranjeiro if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) { 2854a170a30dSNélio Laranjeiro DRV_LOG(ERR, 2855a170a30dSNélio Laranjeiro "port %u cannot get MAC address, is mlx5_en" 2856a170a30dSNélio Laranjeiro " loaded? (errno: %s)", 28578c3c2372SAdrien Mazarguil eth_dev->data->port_id, strerror(rte_errno)); 2858e1c3e305SMatan Azrad err = ENODEV; 28599083982cSAdrien Mazarguil goto error; 2860771fa900SAdrien Mazarguil } 2861a170a30dSNélio Laranjeiro DRV_LOG(INFO, 2862a170a30dSNélio Laranjeiro "port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 28630f99970bSNélio Laranjeiro eth_dev->data->port_id, 2864771fa900SAdrien Mazarguil mac.addr_bytes[0], mac.addr_bytes[1], 2865771fa900SAdrien Mazarguil mac.addr_bytes[2], mac.addr_bytes[3], 2866771fa900SAdrien Mazarguil mac.addr_bytes[4], mac.addr_bytes[5]); 28670afacb04SAlexander Kozyrev #ifdef RTE_LIBRTE_MLX5_DEBUG 2868771fa900SAdrien Mazarguil { 2869771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 2870771fa900SAdrien Mazarguil 2871af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(eth_dev, &ifname) == 0) 2872a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u ifname is \"%s\"", 28730f99970bSNélio Laranjeiro eth_dev->data->port_id, ifname); 2874771fa900SAdrien Mazarguil else 2875a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u ifname is unknown", 28760f99970bSNélio Laranjeiro eth_dev->data->port_id); 2877771fa900SAdrien Mazarguil } 2878771fa900SAdrien Mazarguil #endif 2879771fa900SAdrien Mazarguil /* Get actual MTU if possible. */ 2880a6d83b6aSNélio Laranjeiro err = mlx5_get_mtu(eth_dev, &priv->mtu); 2881012ad994SShahaf Shuler if (err) { 2882012ad994SShahaf Shuler err = rte_errno; 28839083982cSAdrien Mazarguil goto error; 2884012ad994SShahaf Shuler } 2885a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u MTU is %u", eth_dev->data->port_id, 2886a170a30dSNélio Laranjeiro priv->mtu); 288768128934SAdrien Mazarguil /* Initialize burst functions to prevent crashes before link-up. */ 2888e313ef4cSShahaf Shuler eth_dev->rx_pkt_burst = removed_rx_burst; 2889e313ef4cSShahaf Shuler eth_dev->tx_pkt_burst = removed_tx_burst; 2890771fa900SAdrien Mazarguil eth_dev->dev_ops = &mlx5_dev_ops; 2891272733b5SNélio Laranjeiro /* Register MAC address. */ 2892272733b5SNélio Laranjeiro claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); 2893f87bfa8eSYongseok Koh if (config.vf && config.vf_nl_en) 2894f22442cbSMatan Azrad mlx5_nl_mac_addr_sync(priv->nl_socket_route, 2895f22442cbSMatan Azrad mlx5_ifindex(eth_dev), 2896f22442cbSMatan Azrad eth_dev->data->mac_addrs, 2897f22442cbSMatan Azrad MLX5_MAX_MAC_ADDRESSES); 2898ab612adcSSuanming Mou priv->flows = 0; 2899ab612adcSSuanming Mou priv->ctrl_flows = 0; 29003f373f35SSuanming Mou TAILQ_INIT(&priv->flow_meters); 29013bd26b23SSuanming Mou TAILQ_INIT(&priv->flow_meter_profiles); 29021e3a39f7SXueming Li /* Hint libmlx5 to use PMD allocator for data plane resources */ 29031e3a39f7SXueming Li struct mlx5dv_ctx_allocators alctr = { 29041e3a39f7SXueming Li .alloc = &mlx5_alloc_verbs_buf, 29051e3a39f7SXueming Li .free = &mlx5_free_verbs_buf, 29061e3a39f7SXueming Li .data = priv, 29071e3a39f7SXueming Li }; 290817e19bc4SViacheslav Ovsiienko mlx5_glue->dv_set_context_attr(sh->ctx, 290917e19bc4SViacheslav Ovsiienko MLX5DV_CTX_ATTR_BUF_ALLOCATORS, 29101e3a39f7SXueming Li (void *)((uintptr_t)&alctr)); 2911771fa900SAdrien Mazarguil /* Bring Ethernet device up. */ 2912a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u forcing Ethernet interface up", 29130f99970bSNélio Laranjeiro eth_dev->data->port_id); 29147ba5320bSNélio Laranjeiro mlx5_set_link_up(eth_dev); 2915a85a606cSShahaf Shuler /* 2916a85a606cSShahaf Shuler * Even though the interrupt handler is not installed yet, 2917ae4eb7dcSViacheslav Ovsiienko * interrupts will still trigger on the async_fd from 2918a85a606cSShahaf Shuler * Verbs context returned by ibv_open_device(). 2919a85a606cSShahaf Shuler */ 2920a85a606cSShahaf Shuler mlx5_link_update(eth_dev, 0); 2921e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 2922e2b4925eSOri Kam if (!(config.hca_attr.eswitch_manager && config.dv_flow_en && 2923e2b4925eSOri Kam (switch_info->representor || switch_info->master))) 2924e2b4925eSOri Kam config.dv_esw_en = 0; 2925e2b4925eSOri Kam #else 2926e2b4925eSOri Kam config.dv_esw_en = 0; 2927e2b4925eSOri Kam #endif 292838b4b397SViacheslav Ovsiienko /* Detect minimal data bytes to inline. */ 292938b4b397SViacheslav Ovsiienko mlx5_set_min_inline(spawn, &config); 29307fe24446SShahaf Shuler /* Store device configuration on private structure. */ 29317fe24446SShahaf Shuler priv->config = config; 2932dfedf3e3SViacheslav Ovsiienko /* Create context for virtual machine VLAN workaround. */ 2933dfedf3e3SViacheslav Ovsiienko priv->vmwa_context = mlx5_vlan_vmwa_init(eth_dev, spawn->ifindex); 2934e2b4925eSOri Kam if (config.dv_flow_en) { 2935e2b4925eSOri Kam err = mlx5_alloc_shared_dr(priv); 2936e2b4925eSOri Kam if (err) 2937e2b4925eSOri Kam goto error; 2938792e749eSSuanming Mou /* 2939792e749eSSuanming Mou * RSS id is shared with meter flow id. Meter flow id can only 2940792e749eSSuanming Mou * use the 24 MSB of the register. 2941792e749eSSuanming Mou */ 2942792e749eSSuanming Mou priv->qrss_id_pool = mlx5_flow_id_pool_alloc(UINT32_MAX >> 2943792e749eSSuanming Mou MLX5_MTR_COLOR_BITS); 294471e254bcSViacheslav Ovsiienko if (!priv->qrss_id_pool) { 294571e254bcSViacheslav Ovsiienko DRV_LOG(ERR, "can't create flow id pool"); 294671e254bcSViacheslav Ovsiienko err = ENOMEM; 294771e254bcSViacheslav Ovsiienko goto error; 294871e254bcSViacheslav Ovsiienko } 2949e2b4925eSOri Kam } 295078be8852SNelio Laranjeiro /* Supported Verbs flow priority number detection. */ 29512815702bSNelio Laranjeiro err = mlx5_flow_discover_priorities(eth_dev); 29524fb27c1dSViacheslav Ovsiienko if (err < 0) { 29534fb27c1dSViacheslav Ovsiienko err = -err; 29549083982cSAdrien Mazarguil goto error; 29554fb27c1dSViacheslav Ovsiienko } 29562815702bSNelio Laranjeiro priv->config.flow_prio = err; 29572d241515SViacheslav Ovsiienko if (!priv->config.dv_esw_en && 29582d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 29592d241515SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata mode %u is not supported " 29602d241515SViacheslav Ovsiienko "(no E-Switch)", priv->config.dv_xmeta_en); 29612d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en = MLX5_XMETA_MODE_LEGACY; 29622d241515SViacheslav Ovsiienko } 296339139371SViacheslav Ovsiienko mlx5_set_metadata_mask(eth_dev); 296439139371SViacheslav Ovsiienko if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 296539139371SViacheslav Ovsiienko !priv->sh->dv_regc0_mask) { 296639139371SViacheslav Ovsiienko DRV_LOG(ERR, "metadata mode %u is not supported " 296739139371SViacheslav Ovsiienko "(no metadata reg_c[0] is available)", 296839139371SViacheslav Ovsiienko priv->config.dv_xmeta_en); 296939139371SViacheslav Ovsiienko err = ENOTSUP; 297039139371SViacheslav Ovsiienko goto error; 297139139371SViacheslav Ovsiienko } 2972e7bfa359SBing Zhao /* 2973e7bfa359SBing Zhao * Allocate the buffer for flow creating, just once. 2974e7bfa359SBing Zhao * The allocation must be done before any flow creating. 2975e7bfa359SBing Zhao */ 2976e7bfa359SBing Zhao mlx5_flow_alloc_intermediate(eth_dev); 297739139371SViacheslav Ovsiienko /* Query availibility of metadata reg_c's. */ 297839139371SViacheslav Ovsiienko err = mlx5_flow_discover_mreg_c(eth_dev); 297939139371SViacheslav Ovsiienko if (err < 0) { 298039139371SViacheslav Ovsiienko err = -err; 298139139371SViacheslav Ovsiienko goto error; 298239139371SViacheslav Ovsiienko } 29835e61bcddSViacheslav Ovsiienko if (!mlx5_flow_ext_mreg_supported(eth_dev)) { 29845e61bcddSViacheslav Ovsiienko DRV_LOG(DEBUG, 29855e61bcddSViacheslav Ovsiienko "port %u extensive metadata register is not supported", 29865e61bcddSViacheslav Ovsiienko eth_dev->data->port_id); 29872d241515SViacheslav Ovsiienko if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 29882d241515SViacheslav Ovsiienko DRV_LOG(ERR, "metadata mode %u is not supported " 29892d241515SViacheslav Ovsiienko "(no metadata registers available)", 29902d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en); 29912d241515SViacheslav Ovsiienko err = ENOTSUP; 29922d241515SViacheslav Ovsiienko goto error; 29932d241515SViacheslav Ovsiienko } 29945e61bcddSViacheslav Ovsiienko } 2995dd3c774fSViacheslav Ovsiienko if (priv->config.dv_flow_en && 2996dd3c774fSViacheslav Ovsiienko priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 2997dd3c774fSViacheslav Ovsiienko mlx5_flow_ext_mreg_supported(eth_dev) && 2998dd3c774fSViacheslav Ovsiienko priv->sh->dv_regc0_mask) { 2999dd3c774fSViacheslav Ovsiienko priv->mreg_cp_tbl = mlx5_hlist_create(MLX5_FLOW_MREG_HNAME, 3000dd3c774fSViacheslav Ovsiienko MLX5_FLOW_MREG_HTABLE_SZ); 3001dd3c774fSViacheslav Ovsiienko if (!priv->mreg_cp_tbl) { 3002dd3c774fSViacheslav Ovsiienko err = ENOMEM; 3003dd3c774fSViacheslav Ovsiienko goto error; 3004dd3c774fSViacheslav Ovsiienko } 3005dd3c774fSViacheslav Ovsiienko } 3006f38c5457SAdrien Mazarguil return eth_dev; 30079083982cSAdrien Mazarguil error: 300826c08b97SAdrien Mazarguil if (priv) { 3009dd3c774fSViacheslav Ovsiienko if (priv->mreg_cp_tbl) 3010dd3c774fSViacheslav Ovsiienko mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL); 3011b2177648SViacheslav Ovsiienko if (priv->sh) 3012b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(priv); 301326c08b97SAdrien Mazarguil if (priv->nl_socket_route >= 0) 301426c08b97SAdrien Mazarguil close(priv->nl_socket_route); 301526c08b97SAdrien Mazarguil if (priv->nl_socket_rdma >= 0) 301626c08b97SAdrien Mazarguil close(priv->nl_socket_rdma); 3017dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context) 3018dfedf3e3SViacheslav Ovsiienko mlx5_vlan_vmwa_exit(priv->vmwa_context); 301971e254bcSViacheslav Ovsiienko if (priv->qrss_id_pool) 302071e254bcSViacheslav Ovsiienko mlx5_flow_id_pool_release(priv->qrss_id_pool); 30212b730263SAdrien Mazarguil if (own_domain_id) 30222b730263SAdrien Mazarguil claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 3023771fa900SAdrien Mazarguil rte_free(priv); 3024e16adf08SThomas Monjalon if (eth_dev != NULL) 3025e16adf08SThomas Monjalon eth_dev->data->dev_private = NULL; 302626c08b97SAdrien Mazarguil } 3027e16adf08SThomas Monjalon if (eth_dev != NULL) { 3028e16adf08SThomas Monjalon /* mac_addrs must not be freed alone because part of dev_private */ 3029e16adf08SThomas Monjalon eth_dev->data->mac_addrs = NULL; 3030690de285SRaslan Darawsheh rte_eth_dev_release_port(eth_dev); 3031e16adf08SThomas Monjalon } 303217e19bc4SViacheslav Ovsiienko if (sh) 303317e19bc4SViacheslav Ovsiienko mlx5_free_shared_ibctx(sh); 30348e46d4e1SAlexander Kozyrev MLX5_ASSERT(err > 0); 3035a6d83b6aSNélio Laranjeiro rte_errno = err; 3036f38c5457SAdrien Mazarguil return NULL; 3037f38c5457SAdrien Mazarguil } 3038f38c5457SAdrien Mazarguil 3039116f90adSAdrien Mazarguil /** 3040116f90adSAdrien Mazarguil * Comparison callback to sort device data. 3041116f90adSAdrien Mazarguil * 3042116f90adSAdrien Mazarguil * This is meant to be used with qsort(). 3043116f90adSAdrien Mazarguil * 3044116f90adSAdrien Mazarguil * @param a[in] 3045116f90adSAdrien Mazarguil * Pointer to pointer to first data object. 3046116f90adSAdrien Mazarguil * @param b[in] 3047116f90adSAdrien Mazarguil * Pointer to pointer to second data object. 3048116f90adSAdrien Mazarguil * 3049116f90adSAdrien Mazarguil * @return 3050116f90adSAdrien Mazarguil * 0 if both objects are equal, less than 0 if the first argument is less 3051116f90adSAdrien Mazarguil * than the second, greater than 0 otherwise. 3052116f90adSAdrien Mazarguil */ 3053116f90adSAdrien Mazarguil static int 3054116f90adSAdrien Mazarguil mlx5_dev_spawn_data_cmp(const void *a, const void *b) 3055116f90adSAdrien Mazarguil { 3056116f90adSAdrien Mazarguil const struct mlx5_switch_info *si_a = 3057116f90adSAdrien Mazarguil &((const struct mlx5_dev_spawn_data *)a)->info; 3058116f90adSAdrien Mazarguil const struct mlx5_switch_info *si_b = 3059116f90adSAdrien Mazarguil &((const struct mlx5_dev_spawn_data *)b)->info; 3060116f90adSAdrien Mazarguil int ret; 3061116f90adSAdrien Mazarguil 3062116f90adSAdrien Mazarguil /* Master device first. */ 3063116f90adSAdrien Mazarguil ret = si_b->master - si_a->master; 3064116f90adSAdrien Mazarguil if (ret) 3065116f90adSAdrien Mazarguil return ret; 3066116f90adSAdrien Mazarguil /* Then representor devices. */ 3067116f90adSAdrien Mazarguil ret = si_b->representor - si_a->representor; 3068116f90adSAdrien Mazarguil if (ret) 3069116f90adSAdrien Mazarguil return ret; 3070116f90adSAdrien Mazarguil /* Unidentified devices come last in no specific order. */ 3071116f90adSAdrien Mazarguil if (!si_a->representor) 3072116f90adSAdrien Mazarguil return 0; 3073116f90adSAdrien Mazarguil /* Order representors by name. */ 3074116f90adSAdrien Mazarguil return si_a->port_name - si_b->port_name; 3075116f90adSAdrien Mazarguil } 3076116f90adSAdrien Mazarguil 3077f38c5457SAdrien Mazarguil /** 30782e569a37SViacheslav Ovsiienko * Match PCI information for possible slaves of bonding device. 30792e569a37SViacheslav Ovsiienko * 30802e569a37SViacheslav Ovsiienko * @param[in] ibv_dev 30812e569a37SViacheslav Ovsiienko * Pointer to Infiniband device structure. 30822e569a37SViacheslav Ovsiienko * @param[in] pci_dev 30832e569a37SViacheslav Ovsiienko * Pointer to PCI device structure to match PCI address. 30842e569a37SViacheslav Ovsiienko * @param[in] nl_rdma 30852e569a37SViacheslav Ovsiienko * Netlink RDMA group socket handle. 30862e569a37SViacheslav Ovsiienko * 30872e569a37SViacheslav Ovsiienko * @return 30882e569a37SViacheslav Ovsiienko * negative value if no bonding device found, otherwise 30892e569a37SViacheslav Ovsiienko * positive index of slave PF in bonding. 30902e569a37SViacheslav Ovsiienko */ 30912e569a37SViacheslav Ovsiienko static int 30922e569a37SViacheslav Ovsiienko mlx5_device_bond_pci_match(const struct ibv_device *ibv_dev, 30932e569a37SViacheslav Ovsiienko const struct rte_pci_device *pci_dev, 30942e569a37SViacheslav Ovsiienko int nl_rdma) 30952e569a37SViacheslav Ovsiienko { 30962e569a37SViacheslav Ovsiienko char ifname[IF_NAMESIZE + 1]; 30972e569a37SViacheslav Ovsiienko unsigned int ifindex; 30982e569a37SViacheslav Ovsiienko unsigned int np, i; 30992e569a37SViacheslav Ovsiienko FILE *file = NULL; 31002e569a37SViacheslav Ovsiienko int pf = -1; 31012e569a37SViacheslav Ovsiienko 31022e569a37SViacheslav Ovsiienko /* 31032e569a37SViacheslav Ovsiienko * Try to get master device name. If something goes 31042e569a37SViacheslav Ovsiienko * wrong suppose the lack of kernel support and no 31052e569a37SViacheslav Ovsiienko * bonding devices. 31062e569a37SViacheslav Ovsiienko */ 31072e569a37SViacheslav Ovsiienko if (nl_rdma < 0) 31082e569a37SViacheslav Ovsiienko return -1; 31092e569a37SViacheslav Ovsiienko if (!strstr(ibv_dev->name, "bond")) 31102e569a37SViacheslav Ovsiienko return -1; 31112e569a37SViacheslav Ovsiienko np = mlx5_nl_portnum(nl_rdma, ibv_dev->name); 31122e569a37SViacheslav Ovsiienko if (!np) 31132e569a37SViacheslav Ovsiienko return -1; 31142e569a37SViacheslav Ovsiienko /* 31152e569a37SViacheslav Ovsiienko * The Master device might not be on the predefined 31162e569a37SViacheslav Ovsiienko * port (not on port index 1, it is not garanted), 31172e569a37SViacheslav Ovsiienko * we have to scan all Infiniband device port and 31182e569a37SViacheslav Ovsiienko * find master. 31192e569a37SViacheslav Ovsiienko */ 31202e569a37SViacheslav Ovsiienko for (i = 1; i <= np; ++i) { 31212e569a37SViacheslav Ovsiienko /* Check whether Infiniband port is populated. */ 31222e569a37SViacheslav Ovsiienko ifindex = mlx5_nl_ifindex(nl_rdma, ibv_dev->name, i); 31232e569a37SViacheslav Ovsiienko if (!ifindex) 31242e569a37SViacheslav Ovsiienko continue; 31252e569a37SViacheslav Ovsiienko if (!if_indextoname(ifindex, ifname)) 31262e569a37SViacheslav Ovsiienko continue; 31272e569a37SViacheslav Ovsiienko /* Try to read bonding slave names from sysfs. */ 31282e569a37SViacheslav Ovsiienko MKSTR(slaves, 31292e569a37SViacheslav Ovsiienko "/sys/class/net/%s/master/bonding/slaves", ifname); 31302e569a37SViacheslav Ovsiienko file = fopen(slaves, "r"); 31312e569a37SViacheslav Ovsiienko if (file) 31322e569a37SViacheslav Ovsiienko break; 31332e569a37SViacheslav Ovsiienko } 31342e569a37SViacheslav Ovsiienko if (!file) 31352e569a37SViacheslav Ovsiienko return -1; 31362e569a37SViacheslav Ovsiienko /* Use safe format to check maximal buffer length. */ 31378e46d4e1SAlexander Kozyrev MLX5_ASSERT(atol(RTE_STR(IF_NAMESIZE)) == IF_NAMESIZE); 31382e569a37SViacheslav Ovsiienko while (fscanf(file, "%" RTE_STR(IF_NAMESIZE) "s", ifname) == 1) { 31392e569a37SViacheslav Ovsiienko char tmp_str[IF_NAMESIZE + 32]; 31402e569a37SViacheslav Ovsiienko struct rte_pci_addr pci_addr; 31412e569a37SViacheslav Ovsiienko struct mlx5_switch_info info; 31422e569a37SViacheslav Ovsiienko 31432e569a37SViacheslav Ovsiienko /* Process slave interface names in the loop. */ 31442e569a37SViacheslav Ovsiienko snprintf(tmp_str, sizeof(tmp_str), 31452e569a37SViacheslav Ovsiienko "/sys/class/net/%s", ifname); 31462e569a37SViacheslav Ovsiienko if (mlx5_dev_to_pci_addr(tmp_str, &pci_addr)) { 31472e569a37SViacheslav Ovsiienko DRV_LOG(WARNING, "can not get PCI address" 31482e569a37SViacheslav Ovsiienko " for netdev \"%s\"", ifname); 31492e569a37SViacheslav Ovsiienko continue; 31502e569a37SViacheslav Ovsiienko } 31512e569a37SViacheslav Ovsiienko if (pci_dev->addr.domain != pci_addr.domain || 31522e569a37SViacheslav Ovsiienko pci_dev->addr.bus != pci_addr.bus || 31532e569a37SViacheslav Ovsiienko pci_dev->addr.devid != pci_addr.devid || 31542e569a37SViacheslav Ovsiienko pci_dev->addr.function != pci_addr.function) 31552e569a37SViacheslav Ovsiienko continue; 31562e569a37SViacheslav Ovsiienko /* Slave interface PCI address match found. */ 31572e569a37SViacheslav Ovsiienko fclose(file); 31582e569a37SViacheslav Ovsiienko snprintf(tmp_str, sizeof(tmp_str), 31592e569a37SViacheslav Ovsiienko "/sys/class/net/%s/phys_port_name", ifname); 31602e569a37SViacheslav Ovsiienko file = fopen(tmp_str, "rb"); 31612e569a37SViacheslav Ovsiienko if (!file) 31622e569a37SViacheslav Ovsiienko break; 31632e569a37SViacheslav Ovsiienko info.name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET; 31642e569a37SViacheslav Ovsiienko if (fscanf(file, "%32s", tmp_str) == 1) 31652e569a37SViacheslav Ovsiienko mlx5_translate_port_name(tmp_str, &info); 31662e569a37SViacheslav Ovsiienko if (info.name_type == MLX5_PHYS_PORT_NAME_TYPE_LEGACY || 31672e569a37SViacheslav Ovsiienko info.name_type == MLX5_PHYS_PORT_NAME_TYPE_UPLINK) 31682e569a37SViacheslav Ovsiienko pf = info.port_name; 31692e569a37SViacheslav Ovsiienko break; 31702e569a37SViacheslav Ovsiienko } 31712e569a37SViacheslav Ovsiienko if (file) 31722e569a37SViacheslav Ovsiienko fclose(file); 31732e569a37SViacheslav Ovsiienko return pf; 31742e569a37SViacheslav Ovsiienko } 31752e569a37SViacheslav Ovsiienko 31762e569a37SViacheslav Ovsiienko /** 3177f38c5457SAdrien Mazarguil * DPDK callback to register a PCI device. 3178f38c5457SAdrien Mazarguil * 31792b730263SAdrien Mazarguil * This function spawns Ethernet devices out of a given PCI device. 3180f38c5457SAdrien Mazarguil * 3181f38c5457SAdrien Mazarguil * @param[in] pci_drv 3182f38c5457SAdrien Mazarguil * PCI driver structure (mlx5_driver). 3183f38c5457SAdrien Mazarguil * @param[in] pci_dev 3184f38c5457SAdrien Mazarguil * PCI device information. 3185f38c5457SAdrien Mazarguil * 3186f38c5457SAdrien Mazarguil * @return 3187f38c5457SAdrien Mazarguil * 0 on success, a negative errno value otherwise and rte_errno is set. 3188f38c5457SAdrien Mazarguil */ 3189f38c5457SAdrien Mazarguil static int 3190f38c5457SAdrien Mazarguil mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 3191f38c5457SAdrien Mazarguil struct rte_pci_device *pci_dev) 3192f38c5457SAdrien Mazarguil { 3193f38c5457SAdrien Mazarguil struct ibv_device **ibv_list; 3194ad74bc61SViacheslav Ovsiienko /* 3195ad74bc61SViacheslav Ovsiienko * Number of found IB Devices matching with requested PCI BDF. 3196ad74bc61SViacheslav Ovsiienko * nd != 1 means there are multiple IB devices over the same 3197ad74bc61SViacheslav Ovsiienko * PCI device and we have representors and master. 3198ad74bc61SViacheslav Ovsiienko */ 3199ad74bc61SViacheslav Ovsiienko unsigned int nd = 0; 3200ad74bc61SViacheslav Ovsiienko /* 3201ad74bc61SViacheslav Ovsiienko * Number of found IB device Ports. nd = 1 and np = 1..n means 3202ad74bc61SViacheslav Ovsiienko * we have the single multiport IB device, and there may be 3203ad74bc61SViacheslav Ovsiienko * representors attached to some of found ports. 3204ad74bc61SViacheslav Ovsiienko */ 3205ad74bc61SViacheslav Ovsiienko unsigned int np = 0; 3206ad74bc61SViacheslav Ovsiienko /* 3207ad74bc61SViacheslav Ovsiienko * Number of DPDK ethernet devices to Spawn - either over 3208ad74bc61SViacheslav Ovsiienko * multiple IB devices or multiple ports of single IB device. 3209ad74bc61SViacheslav Ovsiienko * Actually this is the number of iterations to spawn. 3210ad74bc61SViacheslav Ovsiienko */ 3211ad74bc61SViacheslav Ovsiienko unsigned int ns = 0; 32122e569a37SViacheslav Ovsiienko /* 32132e569a37SViacheslav Ovsiienko * Bonding device 32142e569a37SViacheslav Ovsiienko * < 0 - no bonding device (single one) 32152e569a37SViacheslav Ovsiienko * >= 0 - bonding device (value is slave PF index) 32162e569a37SViacheslav Ovsiienko */ 32172e569a37SViacheslav Ovsiienko int bd = -1; 3218a62ec991SViacheslav Ovsiienko struct mlx5_dev_spawn_data *list = NULL; 3219f87bfa8eSYongseok Koh struct mlx5_dev_config dev_config; 3220f38c5457SAdrien Mazarguil int ret; 3221f38c5457SAdrien Mazarguil 3222d768f324SMatan Azrad if (mlx5_class_get(pci_dev->device.devargs) != MLX5_CLASS_NET) { 3223d768f324SMatan Azrad DRV_LOG(DEBUG, "Skip probing - should be probed by other mlx5" 3224d768f324SMatan Azrad " driver."); 3225d768f324SMatan Azrad return 1; 3226d768f324SMatan Azrad } 3227e6cdc54cSXueming Li if (rte_eal_process_type() == RTE_PROC_PRIMARY) 3228e6cdc54cSXueming Li mlx5_pmd_socket_init(); 32297be600c8SYongseok Koh ret = mlx5_init_once(); 32307be600c8SYongseok Koh if (ret) { 32317be600c8SYongseok Koh DRV_LOG(ERR, "unable to init PMD global data: %s", 32327be600c8SYongseok Koh strerror(rte_errno)); 32337be600c8SYongseok Koh return -rte_errno; 32347be600c8SYongseok Koh } 32358e46d4e1SAlexander Kozyrev MLX5_ASSERT(pci_drv == &mlx5_driver); 3236f38c5457SAdrien Mazarguil errno = 0; 3237f38c5457SAdrien Mazarguil ibv_list = mlx5_glue->get_device_list(&ret); 3238f38c5457SAdrien Mazarguil if (!ibv_list) { 3239f38c5457SAdrien Mazarguil rte_errno = errno ? errno : ENOSYS; 3240f38c5457SAdrien Mazarguil DRV_LOG(ERR, "cannot list devices, is ib_uverbs loaded?"); 3241a6d83b6aSNélio Laranjeiro return -rte_errno; 3242a6d83b6aSNélio Laranjeiro } 3243ad74bc61SViacheslav Ovsiienko /* 3244ad74bc61SViacheslav Ovsiienko * First scan the list of all Infiniband devices to find 3245ad74bc61SViacheslav Ovsiienko * matching ones, gathering into the list. 3246ad74bc61SViacheslav Ovsiienko */ 324726c08b97SAdrien Mazarguil struct ibv_device *ibv_match[ret + 1]; 3248a62ec991SViacheslav Ovsiienko int nl_route = mlx5_nl_init(NETLINK_ROUTE); 3249a62ec991SViacheslav Ovsiienko int nl_rdma = mlx5_nl_init(NETLINK_RDMA); 3250ad74bc61SViacheslav Ovsiienko unsigned int i; 325126c08b97SAdrien Mazarguil 3252f38c5457SAdrien Mazarguil while (ret-- > 0) { 3253f38c5457SAdrien Mazarguil struct rte_pci_addr pci_addr; 3254f38c5457SAdrien Mazarguil 3255f38c5457SAdrien Mazarguil DRV_LOG(DEBUG, "checking device \"%s\"", ibv_list[ret]->name); 32562e569a37SViacheslav Ovsiienko bd = mlx5_device_bond_pci_match 32572e569a37SViacheslav Ovsiienko (ibv_list[ret], pci_dev, nl_rdma); 32582e569a37SViacheslav Ovsiienko if (bd >= 0) { 32592e569a37SViacheslav Ovsiienko /* 32602e569a37SViacheslav Ovsiienko * Bonding device detected. Only one match is allowed, 32612e569a37SViacheslav Ovsiienko * the bonding is supported over multi-port IB device, 32622e569a37SViacheslav Ovsiienko * there should be no matches on representor PCI 32632e569a37SViacheslav Ovsiienko * functions or non VF LAG bonding devices with 32642e569a37SViacheslav Ovsiienko * specified address. 32652e569a37SViacheslav Ovsiienko */ 32662e569a37SViacheslav Ovsiienko if (nd) { 32672e569a37SViacheslav Ovsiienko DRV_LOG(ERR, 32682e569a37SViacheslav Ovsiienko "multiple PCI match on bonding device" 32692e569a37SViacheslav Ovsiienko "\"%s\" found", ibv_list[ret]->name); 32702e569a37SViacheslav Ovsiienko rte_errno = ENOENT; 32712e569a37SViacheslav Ovsiienko ret = -rte_errno; 32722e569a37SViacheslav Ovsiienko goto exit; 32732e569a37SViacheslav Ovsiienko } 32742e569a37SViacheslav Ovsiienko DRV_LOG(INFO, "PCI information matches for" 32752e569a37SViacheslav Ovsiienko " slave %d bonding device \"%s\"", 32762e569a37SViacheslav Ovsiienko bd, ibv_list[ret]->name); 32772e569a37SViacheslav Ovsiienko ibv_match[nd++] = ibv_list[ret]; 32782e569a37SViacheslav Ovsiienko break; 32792e569a37SViacheslav Ovsiienko } 32805cf5f710SViacheslav Ovsiienko if (mlx5_dev_to_pci_addr 32815cf5f710SViacheslav Ovsiienko (ibv_list[ret]->ibdev_path, &pci_addr)) 3282f38c5457SAdrien Mazarguil continue; 3283f38c5457SAdrien Mazarguil if (pci_dev->addr.domain != pci_addr.domain || 3284f38c5457SAdrien Mazarguil pci_dev->addr.bus != pci_addr.bus || 3285f38c5457SAdrien Mazarguil pci_dev->addr.devid != pci_addr.devid || 3286f38c5457SAdrien Mazarguil pci_dev->addr.function != pci_addr.function) 3287f38c5457SAdrien Mazarguil continue; 328826c08b97SAdrien Mazarguil DRV_LOG(INFO, "PCI information matches for device \"%s\"", 3289f38c5457SAdrien Mazarguil ibv_list[ret]->name); 3290ad74bc61SViacheslav Ovsiienko ibv_match[nd++] = ibv_list[ret]; 329126c08b97SAdrien Mazarguil } 3292ad74bc61SViacheslav Ovsiienko ibv_match[nd] = NULL; 3293ad74bc61SViacheslav Ovsiienko if (!nd) { 3294ae4eb7dcSViacheslav Ovsiienko /* No device matches, just complain and bail out. */ 3295ad74bc61SViacheslav Ovsiienko DRV_LOG(WARNING, 3296ad74bc61SViacheslav Ovsiienko "no Verbs device matches PCI device " PCI_PRI_FMT "," 3297ad74bc61SViacheslav Ovsiienko " are kernel drivers loaded?", 3298ad74bc61SViacheslav Ovsiienko pci_dev->addr.domain, pci_dev->addr.bus, 3299ad74bc61SViacheslav Ovsiienko pci_dev->addr.devid, pci_dev->addr.function); 3300ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3301ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3302a62ec991SViacheslav Ovsiienko goto exit; 3303ad74bc61SViacheslav Ovsiienko } 3304ad74bc61SViacheslav Ovsiienko if (nd == 1) { 330526c08b97SAdrien Mazarguil /* 3306ad74bc61SViacheslav Ovsiienko * Found single matching device may have multiple ports. 3307ad74bc61SViacheslav Ovsiienko * Each port may be representor, we have to check the port 3308ad74bc61SViacheslav Ovsiienko * number and check the representors existence. 330926c08b97SAdrien Mazarguil */ 3310ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3311ad74bc61SViacheslav Ovsiienko np = mlx5_nl_portnum(nl_rdma, ibv_match[0]->name); 3312ad74bc61SViacheslav Ovsiienko if (!np) 3313ad74bc61SViacheslav Ovsiienko DRV_LOG(WARNING, "can not get IB device \"%s\"" 3314ad74bc61SViacheslav Ovsiienko " ports number", ibv_match[0]->name); 33152e569a37SViacheslav Ovsiienko if (bd >= 0 && !np) { 33162e569a37SViacheslav Ovsiienko DRV_LOG(ERR, "can not get ports" 33172e569a37SViacheslav Ovsiienko " for bonding device"); 33182e569a37SViacheslav Ovsiienko rte_errno = ENOENT; 33192e569a37SViacheslav Ovsiienko ret = -rte_errno; 33202e569a37SViacheslav Ovsiienko goto exit; 33212e569a37SViacheslav Ovsiienko } 3322ad74bc61SViacheslav Ovsiienko } 3323790164ceSViacheslav Ovsiienko #ifndef HAVE_MLX5DV_DR_DEVX_PORT 3324790164ceSViacheslav Ovsiienko if (bd >= 0) { 3325790164ceSViacheslav Ovsiienko /* 3326790164ceSViacheslav Ovsiienko * This may happen if there is VF LAG kernel support and 3327790164ceSViacheslav Ovsiienko * application is compiled with older rdma_core library. 3328790164ceSViacheslav Ovsiienko */ 3329790164ceSViacheslav Ovsiienko DRV_LOG(ERR, 3330790164ceSViacheslav Ovsiienko "No kernel/verbs support for VF LAG bonding found."); 3331790164ceSViacheslav Ovsiienko rte_errno = ENOTSUP; 3332790164ceSViacheslav Ovsiienko ret = -rte_errno; 3333790164ceSViacheslav Ovsiienko goto exit; 3334790164ceSViacheslav Ovsiienko } 3335790164ceSViacheslav Ovsiienko #endif 3336ad74bc61SViacheslav Ovsiienko /* 3337ad74bc61SViacheslav Ovsiienko * Now we can determine the maximal 3338ad74bc61SViacheslav Ovsiienko * amount of devices to be spawned. 3339ad74bc61SViacheslav Ovsiienko */ 3340a62ec991SViacheslav Ovsiienko list = rte_zmalloc("device spawn data", 3341a62ec991SViacheslav Ovsiienko sizeof(struct mlx5_dev_spawn_data) * 3342a62ec991SViacheslav Ovsiienko (np ? np : nd), 3343a62ec991SViacheslav Ovsiienko RTE_CACHE_LINE_SIZE); 3344a62ec991SViacheslav Ovsiienko if (!list) { 3345a62ec991SViacheslav Ovsiienko DRV_LOG(ERR, "spawn data array allocation failure"); 3346a62ec991SViacheslav Ovsiienko rte_errno = ENOMEM; 3347a62ec991SViacheslav Ovsiienko ret = -rte_errno; 3348a62ec991SViacheslav Ovsiienko goto exit; 3349a62ec991SViacheslav Ovsiienko } 33502e569a37SViacheslav Ovsiienko if (bd >= 0 || np > 1) { 3351ad74bc61SViacheslav Ovsiienko /* 3352ae4eb7dcSViacheslav Ovsiienko * Single IB device with multiple ports found, 3353ad74bc61SViacheslav Ovsiienko * it may be E-Switch master device and representors. 3354ad74bc61SViacheslav Ovsiienko * We have to perform identification trough the ports. 3355ad74bc61SViacheslav Ovsiienko */ 33568e46d4e1SAlexander Kozyrev MLX5_ASSERT(nl_rdma >= 0); 33578e46d4e1SAlexander Kozyrev MLX5_ASSERT(ns == 0); 33588e46d4e1SAlexander Kozyrev MLX5_ASSERT(nd == 1); 33598e46d4e1SAlexander Kozyrev MLX5_ASSERT(np); 3360ad74bc61SViacheslav Ovsiienko for (i = 1; i <= np; ++i) { 3361ad74bc61SViacheslav Ovsiienko list[ns].max_port = np; 3362ad74bc61SViacheslav Ovsiienko list[ns].ibv_port = i; 3363ad74bc61SViacheslav Ovsiienko list[ns].ibv_dev = ibv_match[0]; 3364ad74bc61SViacheslav Ovsiienko list[ns].eth_dev = NULL; 3365ab3cffcfSViacheslav Ovsiienko list[ns].pci_dev = pci_dev; 33662e569a37SViacheslav Ovsiienko list[ns].pf_bond = bd; 3367ad74bc61SViacheslav Ovsiienko list[ns].ifindex = mlx5_nl_ifindex 3368ad74bc61SViacheslav Ovsiienko (nl_rdma, list[ns].ibv_dev->name, i); 3369ad74bc61SViacheslav Ovsiienko if (!list[ns].ifindex) { 3370ad74bc61SViacheslav Ovsiienko /* 3371ad74bc61SViacheslav Ovsiienko * No network interface index found for the 3372ad74bc61SViacheslav Ovsiienko * specified port, it means there is no 3373ad74bc61SViacheslav Ovsiienko * representor on this port. It's OK, 3374ad74bc61SViacheslav Ovsiienko * there can be disabled ports, for example 3375ad74bc61SViacheslav Ovsiienko * if sriov_numvfs < sriov_totalvfs. 3376ad74bc61SViacheslav Ovsiienko */ 337726c08b97SAdrien Mazarguil continue; 337826c08b97SAdrien Mazarguil } 3379ad74bc61SViacheslav Ovsiienko ret = -1; 338026c08b97SAdrien Mazarguil if (nl_route >= 0) 3381ad74bc61SViacheslav Ovsiienko ret = mlx5_nl_switch_info 3382ad74bc61SViacheslav Ovsiienko (nl_route, 3383ad74bc61SViacheslav Ovsiienko list[ns].ifindex, 3384ad74bc61SViacheslav Ovsiienko &list[ns].info); 3385ad74bc61SViacheslav Ovsiienko if (ret || (!list[ns].info.representor && 3386ad74bc61SViacheslav Ovsiienko !list[ns].info.master)) { 3387ad74bc61SViacheslav Ovsiienko /* 3388ad74bc61SViacheslav Ovsiienko * We failed to recognize representors with 3389ad74bc61SViacheslav Ovsiienko * Netlink, let's try to perform the task 3390ad74bc61SViacheslav Ovsiienko * with sysfs. 3391ad74bc61SViacheslav Ovsiienko */ 3392ad74bc61SViacheslav Ovsiienko ret = mlx5_sysfs_switch_info 3393ad74bc61SViacheslav Ovsiienko (list[ns].ifindex, 3394ad74bc61SViacheslav Ovsiienko &list[ns].info); 3395ad74bc61SViacheslav Ovsiienko } 33962e569a37SViacheslav Ovsiienko if (!ret && bd >= 0) { 33972e569a37SViacheslav Ovsiienko switch (list[ns].info.name_type) { 33982e569a37SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 33992e569a37SViacheslav Ovsiienko if (list[ns].info.port_name == bd) 34002e569a37SViacheslav Ovsiienko ns++; 34012e569a37SViacheslav Ovsiienko break; 34022e569a37SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 34032e569a37SViacheslav Ovsiienko if (list[ns].info.pf_num == bd) 34042e569a37SViacheslav Ovsiienko ns++; 34052e569a37SViacheslav Ovsiienko break; 34062e569a37SViacheslav Ovsiienko default: 34072e569a37SViacheslav Ovsiienko break; 34082e569a37SViacheslav Ovsiienko } 34092e569a37SViacheslav Ovsiienko continue; 34102e569a37SViacheslav Ovsiienko } 3411ad74bc61SViacheslav Ovsiienko if (!ret && (list[ns].info.representor ^ 3412ad74bc61SViacheslav Ovsiienko list[ns].info.master)) 3413ad74bc61SViacheslav Ovsiienko ns++; 3414ad74bc61SViacheslav Ovsiienko } 3415ad74bc61SViacheslav Ovsiienko if (!ns) { 341626c08b97SAdrien Mazarguil DRV_LOG(ERR, 3417ad74bc61SViacheslav Ovsiienko "unable to recognize master/representors" 3418ad74bc61SViacheslav Ovsiienko " on the IB device with multiple ports"); 3419ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3420ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3421ad74bc61SViacheslav Ovsiienko goto exit; 3422ad74bc61SViacheslav Ovsiienko } 3423ad74bc61SViacheslav Ovsiienko } else { 3424ad74bc61SViacheslav Ovsiienko /* 3425ad74bc61SViacheslav Ovsiienko * The existence of several matching entries (nd > 1) means 3426ad74bc61SViacheslav Ovsiienko * port representors have been instantiated. No existing Verbs 3427ad74bc61SViacheslav Ovsiienko * call nor sysfs entries can tell them apart, this can only 3428ad74bc61SViacheslav Ovsiienko * be done through Netlink calls assuming kernel drivers are 3429ad74bc61SViacheslav Ovsiienko * recent enough to support them. 3430ad74bc61SViacheslav Ovsiienko * 3431ad74bc61SViacheslav Ovsiienko * In the event of identification failure through Netlink, 3432ad74bc61SViacheslav Ovsiienko * try again through sysfs, then: 3433ad74bc61SViacheslav Ovsiienko * 3434ad74bc61SViacheslav Ovsiienko * 1. A single IB device matches (nd == 1) with single 3435ad74bc61SViacheslav Ovsiienko * port (np=0/1) and is not a representor, assume 3436ad74bc61SViacheslav Ovsiienko * no switch support. 3437ad74bc61SViacheslav Ovsiienko * 3438ad74bc61SViacheslav Ovsiienko * 2. Otherwise no safe assumptions can be made; 3439ad74bc61SViacheslav Ovsiienko * complain louder and bail out. 3440ad74bc61SViacheslav Ovsiienko */ 3441ad74bc61SViacheslav Ovsiienko np = 1; 3442ad74bc61SViacheslav Ovsiienko for (i = 0; i != nd; ++i) { 3443ad74bc61SViacheslav Ovsiienko memset(&list[ns].info, 0, sizeof(list[ns].info)); 3444ad74bc61SViacheslav Ovsiienko list[ns].max_port = 1; 3445ad74bc61SViacheslav Ovsiienko list[ns].ibv_port = 1; 3446ad74bc61SViacheslav Ovsiienko list[ns].ibv_dev = ibv_match[i]; 3447ad74bc61SViacheslav Ovsiienko list[ns].eth_dev = NULL; 3448ab3cffcfSViacheslav Ovsiienko list[ns].pci_dev = pci_dev; 34492e569a37SViacheslav Ovsiienko list[ns].pf_bond = -1; 3450ad74bc61SViacheslav Ovsiienko list[ns].ifindex = 0; 3451ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3452ad74bc61SViacheslav Ovsiienko list[ns].ifindex = mlx5_nl_ifindex 3453ad74bc61SViacheslav Ovsiienko (nl_rdma, list[ns].ibv_dev->name, 1); 3454ad74bc61SViacheslav Ovsiienko if (!list[ns].ifindex) { 34559c2bbd04SViacheslav Ovsiienko char ifname[IF_NAMESIZE]; 34569c2bbd04SViacheslav Ovsiienko 3457ad74bc61SViacheslav Ovsiienko /* 34589c2bbd04SViacheslav Ovsiienko * Netlink failed, it may happen with old 34599c2bbd04SViacheslav Ovsiienko * ib_core kernel driver (before 4.16). 34609c2bbd04SViacheslav Ovsiienko * We can assume there is old driver because 34619c2bbd04SViacheslav Ovsiienko * here we are processing single ports IB 34629c2bbd04SViacheslav Ovsiienko * devices. Let's try sysfs to retrieve 34639c2bbd04SViacheslav Ovsiienko * the ifindex. The method works for 34649c2bbd04SViacheslav Ovsiienko * master device only. 34659c2bbd04SViacheslav Ovsiienko */ 34669c2bbd04SViacheslav Ovsiienko if (nd > 1) { 34679c2bbd04SViacheslav Ovsiienko /* 34689c2bbd04SViacheslav Ovsiienko * Multiple devices found, assume 34699c2bbd04SViacheslav Ovsiienko * representors, can not distinguish 34709c2bbd04SViacheslav Ovsiienko * master/representor and retrieve 34719c2bbd04SViacheslav Ovsiienko * ifindex via sysfs. 3472ad74bc61SViacheslav Ovsiienko */ 3473ad74bc61SViacheslav Ovsiienko continue; 3474ad74bc61SViacheslav Ovsiienko } 34759c2bbd04SViacheslav Ovsiienko ret = mlx5_get_master_ifname 34769c2bbd04SViacheslav Ovsiienko (ibv_match[i]->ibdev_path, &ifname); 34779c2bbd04SViacheslav Ovsiienko if (!ret) 34789c2bbd04SViacheslav Ovsiienko list[ns].ifindex = 34799c2bbd04SViacheslav Ovsiienko if_nametoindex(ifname); 34809c2bbd04SViacheslav Ovsiienko if (!list[ns].ifindex) { 34819c2bbd04SViacheslav Ovsiienko /* 34829c2bbd04SViacheslav Ovsiienko * No network interface index found 34839c2bbd04SViacheslav Ovsiienko * for the specified device, it means 34849c2bbd04SViacheslav Ovsiienko * there it is neither representor 34859c2bbd04SViacheslav Ovsiienko * nor master. 34869c2bbd04SViacheslav Ovsiienko */ 34879c2bbd04SViacheslav Ovsiienko continue; 34889c2bbd04SViacheslav Ovsiienko } 34899c2bbd04SViacheslav Ovsiienko } 3490ad74bc61SViacheslav Ovsiienko ret = -1; 3491ad74bc61SViacheslav Ovsiienko if (nl_route >= 0) 3492ad74bc61SViacheslav Ovsiienko ret = mlx5_nl_switch_info 3493ad74bc61SViacheslav Ovsiienko (nl_route, 3494ad74bc61SViacheslav Ovsiienko list[ns].ifindex, 3495ad74bc61SViacheslav Ovsiienko &list[ns].info); 3496ad74bc61SViacheslav Ovsiienko if (ret || (!list[ns].info.representor && 3497ad74bc61SViacheslav Ovsiienko !list[ns].info.master)) { 3498ad74bc61SViacheslav Ovsiienko /* 3499ad74bc61SViacheslav Ovsiienko * We failed to recognize representors with 3500ad74bc61SViacheslav Ovsiienko * Netlink, let's try to perform the task 3501ad74bc61SViacheslav Ovsiienko * with sysfs. 3502ad74bc61SViacheslav Ovsiienko */ 3503ad74bc61SViacheslav Ovsiienko ret = mlx5_sysfs_switch_info 3504ad74bc61SViacheslav Ovsiienko (list[ns].ifindex, 3505ad74bc61SViacheslav Ovsiienko &list[ns].info); 3506ad74bc61SViacheslav Ovsiienko } 3507ad74bc61SViacheslav Ovsiienko if (!ret && (list[ns].info.representor ^ 3508ad74bc61SViacheslav Ovsiienko list[ns].info.master)) { 3509ad74bc61SViacheslav Ovsiienko ns++; 3510ad74bc61SViacheslav Ovsiienko } else if ((nd == 1) && 3511ad74bc61SViacheslav Ovsiienko !list[ns].info.representor && 3512ad74bc61SViacheslav Ovsiienko !list[ns].info.master) { 3513ad74bc61SViacheslav Ovsiienko /* 3514ad74bc61SViacheslav Ovsiienko * Single IB device with 3515ad74bc61SViacheslav Ovsiienko * one physical port and 3516ad74bc61SViacheslav Ovsiienko * attached network device. 3517ad74bc61SViacheslav Ovsiienko * May be SRIOV is not enabled 3518ad74bc61SViacheslav Ovsiienko * or there is no representors. 3519ad74bc61SViacheslav Ovsiienko */ 3520ad74bc61SViacheslav Ovsiienko DRV_LOG(INFO, "no E-Switch support detected"); 3521ad74bc61SViacheslav Ovsiienko ns++; 3522ad74bc61SViacheslav Ovsiienko break; 352326c08b97SAdrien Mazarguil } 3524f38c5457SAdrien Mazarguil } 3525ad74bc61SViacheslav Ovsiienko if (!ns) { 3526ad74bc61SViacheslav Ovsiienko DRV_LOG(ERR, 3527ad74bc61SViacheslav Ovsiienko "unable to recognize master/representors" 3528ad74bc61SViacheslav Ovsiienko " on the multiple IB devices"); 3529ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3530ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3531ad74bc61SViacheslav Ovsiienko goto exit; 3532ad74bc61SViacheslav Ovsiienko } 3533ad74bc61SViacheslav Ovsiienko } 35348e46d4e1SAlexander Kozyrev MLX5_ASSERT(ns); 3535116f90adSAdrien Mazarguil /* 3536116f90adSAdrien Mazarguil * Sort list to probe devices in natural order for users convenience 3537116f90adSAdrien Mazarguil * (i.e. master first, then representors from lowest to highest ID). 3538116f90adSAdrien Mazarguil */ 3539ad74bc61SViacheslav Ovsiienko qsort(list, ns, sizeof(*list), mlx5_dev_spawn_data_cmp); 3540f87bfa8eSYongseok Koh /* Default configuration. */ 3541f87bfa8eSYongseok Koh dev_config = (struct mlx5_dev_config){ 354278c7a16dSYongseok Koh .hw_padding = 0, 3543f87bfa8eSYongseok Koh .mps = MLX5_ARG_UNSET, 35448409a285SViacheslav Ovsiienko .dbnc = MLX5_ARG_UNSET, 3545f87bfa8eSYongseok Koh .rx_vec_en = 1, 3546505f1fe4SViacheslav Ovsiienko .txq_inline_max = MLX5_ARG_UNSET, 3547505f1fe4SViacheslav Ovsiienko .txq_inline_min = MLX5_ARG_UNSET, 3548505f1fe4SViacheslav Ovsiienko .txq_inline_mpw = MLX5_ARG_UNSET, 3549f87bfa8eSYongseok Koh .txqs_inline = MLX5_ARG_UNSET, 3550f87bfa8eSYongseok Koh .vf_nl_en = 1, 3551dceb5029SYongseok Koh .mr_ext_memseg_en = 1, 3552f87bfa8eSYongseok Koh .mprq = { 3553f87bfa8eSYongseok Koh .enabled = 0, /* Disabled by default. */ 3554ecb16045SAlexander Kozyrev .stride_num_n = 0, 3555ecb16045SAlexander Kozyrev .stride_size_n = 0, 3556f87bfa8eSYongseok Koh .max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN, 3557f87bfa8eSYongseok Koh .min_rxqs_num = MLX5_MPRQ_MIN_RXQS, 3558f87bfa8eSYongseok Koh }, 3559e2b4925eSOri Kam .dv_esw_en = 1, 3560cd4569d2SDekel Peled .dv_flow_en = 1, 35611ad9a3d0SBing Zhao .log_hp_size = MLX5_ARG_UNSET, 3562f87bfa8eSYongseok Koh }; 3563ad74bc61SViacheslav Ovsiienko /* Device specific configuration. */ 3564f38c5457SAdrien Mazarguil switch (pci_dev->id.device_id) { 3565f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 3566f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 3567f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 3568f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 3569a40b734bSViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF: 3570c930f02cSViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX6VF: 35715fc66630SRaslan Darawsheh case PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF: 3572f87bfa8eSYongseok Koh dev_config.vf = 1; 3573f38c5457SAdrien Mazarguil break; 3574f38c5457SAdrien Mazarguil default: 3575f87bfa8eSYongseok Koh break; 3576f38c5457SAdrien Mazarguil } 3577ad74bc61SViacheslav Ovsiienko for (i = 0; i != ns; ++i) { 35782b730263SAdrien Mazarguil uint32_t restore; 35792b730263SAdrien Mazarguil 3580f87bfa8eSYongseok Koh list[i].eth_dev = mlx5_dev_spawn(&pci_dev->device, 3581ad74bc61SViacheslav Ovsiienko &list[i], 3582ad74bc61SViacheslav Ovsiienko dev_config); 35836de569f5SAdrien Mazarguil if (!list[i].eth_dev) { 3584206254b7SOphir Munk if (rte_errno != EBUSY && rte_errno != EEXIST) 35852b730263SAdrien Mazarguil break; 3586206254b7SOphir Munk /* Device is disabled or already spawned. Ignore it. */ 35876de569f5SAdrien Mazarguil continue; 35886de569f5SAdrien Mazarguil } 3589116f90adSAdrien Mazarguil restore = list[i].eth_dev->data->dev_flags; 3590116f90adSAdrien Mazarguil rte_eth_copy_pci_info(list[i].eth_dev, pci_dev); 35912b730263SAdrien Mazarguil /* Restore non-PCI flags cleared by the above call. */ 3592116f90adSAdrien Mazarguil list[i].eth_dev->data->dev_flags |= restore; 359323242063SMatan Azrad mlx5_dev_interrupt_handler_devx_install(list[i].eth_dev); 3594116f90adSAdrien Mazarguil rte_eth_dev_probing_finish(list[i].eth_dev); 35952b730263SAdrien Mazarguil } 3596ad74bc61SViacheslav Ovsiienko if (i != ns) { 3597f38c5457SAdrien Mazarguil DRV_LOG(ERR, 3598f38c5457SAdrien Mazarguil "probe of PCI device " PCI_PRI_FMT " aborted after" 3599f38c5457SAdrien Mazarguil " encountering an error: %s", 3600f38c5457SAdrien Mazarguil pci_dev->addr.domain, pci_dev->addr.bus, 3601f38c5457SAdrien Mazarguil pci_dev->addr.devid, pci_dev->addr.function, 3602f38c5457SAdrien Mazarguil strerror(rte_errno)); 3603f38c5457SAdrien Mazarguil ret = -rte_errno; 36042b730263SAdrien Mazarguil /* Roll back. */ 36052b730263SAdrien Mazarguil while (i--) { 36066de569f5SAdrien Mazarguil if (!list[i].eth_dev) 36076de569f5SAdrien Mazarguil continue; 3608116f90adSAdrien Mazarguil mlx5_dev_close(list[i].eth_dev); 3609e16adf08SThomas Monjalon /* mac_addrs must not be freed because in dev_private */ 3610e16adf08SThomas Monjalon list[i].eth_dev->data->mac_addrs = NULL; 3611116f90adSAdrien Mazarguil claim_zero(rte_eth_dev_release_port(list[i].eth_dev)); 36122b730263SAdrien Mazarguil } 36132b730263SAdrien Mazarguil /* Restore original error. */ 36142b730263SAdrien Mazarguil rte_errno = -ret; 3615f38c5457SAdrien Mazarguil } else { 3616f38c5457SAdrien Mazarguil ret = 0; 3617f38c5457SAdrien Mazarguil } 3618ad74bc61SViacheslav Ovsiienko exit: 3619ad74bc61SViacheslav Ovsiienko /* 3620ad74bc61SViacheslav Ovsiienko * Do the routine cleanup: 3621ad74bc61SViacheslav Ovsiienko * - close opened Netlink sockets 3622a62ec991SViacheslav Ovsiienko * - free allocated spawn data array 3623ad74bc61SViacheslav Ovsiienko * - free the Infiniband device list 3624ad74bc61SViacheslav Ovsiienko */ 3625ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3626ad74bc61SViacheslav Ovsiienko close(nl_rdma); 3627ad74bc61SViacheslav Ovsiienko if (nl_route >= 0) 3628ad74bc61SViacheslav Ovsiienko close(nl_route); 3629a62ec991SViacheslav Ovsiienko if (list) 3630a62ec991SViacheslav Ovsiienko rte_free(list); 36318e46d4e1SAlexander Kozyrev MLX5_ASSERT(ibv_list); 3632ad74bc61SViacheslav Ovsiienko mlx5_glue->free_device_list(ibv_list); 3633f38c5457SAdrien Mazarguil return ret; 3634771fa900SAdrien Mazarguil } 3635771fa900SAdrien Mazarguil 3636fbc83412SViacheslav Ovsiienko /** 3637fbc83412SViacheslav Ovsiienko * Look for the ethernet device belonging to mlx5 driver. 3638fbc83412SViacheslav Ovsiienko * 3639fbc83412SViacheslav Ovsiienko * @param[in] port_id 3640fbc83412SViacheslav Ovsiienko * port_id to start looking for device. 3641fbc83412SViacheslav Ovsiienko * @param[in] pci_dev 3642fbc83412SViacheslav Ovsiienko * Pointer to the hint PCI device. When device is being probed 3643fbc83412SViacheslav Ovsiienko * the its siblings (master and preceding representors might 3644fbc83412SViacheslav Ovsiienko * not have assigned driver yet (because the mlx5_pci_probe() 3645fbc83412SViacheslav Ovsiienko * is not completed yet, for this case match on hint PCI 3646fbc83412SViacheslav Ovsiienko * device may be used to detect sibling device. 3647fbc83412SViacheslav Ovsiienko * 3648fbc83412SViacheslav Ovsiienko * @return 3649fbc83412SViacheslav Ovsiienko * port_id of found device, RTE_MAX_ETHPORT if not found. 3650fbc83412SViacheslav Ovsiienko */ 3651f7e95215SViacheslav Ovsiienko uint16_t 3652fbc83412SViacheslav Ovsiienko mlx5_eth_find_next(uint16_t port_id, struct rte_pci_device *pci_dev) 3653f7e95215SViacheslav Ovsiienko { 3654f7e95215SViacheslav Ovsiienko while (port_id < RTE_MAX_ETHPORTS) { 3655f7e95215SViacheslav Ovsiienko struct rte_eth_dev *dev = &rte_eth_devices[port_id]; 3656f7e95215SViacheslav Ovsiienko 3657f7e95215SViacheslav Ovsiienko if (dev->state != RTE_ETH_DEV_UNUSED && 3658f7e95215SViacheslav Ovsiienko dev->device && 3659fbc83412SViacheslav Ovsiienko (dev->device == &pci_dev->device || 3660fbc83412SViacheslav Ovsiienko (dev->device->driver && 3661f7e95215SViacheslav Ovsiienko dev->device->driver->name && 3662fbc83412SViacheslav Ovsiienko !strcmp(dev->device->driver->name, MLX5_DRIVER_NAME)))) 3663f7e95215SViacheslav Ovsiienko break; 3664f7e95215SViacheslav Ovsiienko port_id++; 3665f7e95215SViacheslav Ovsiienko } 3666f7e95215SViacheslav Ovsiienko if (port_id >= RTE_MAX_ETHPORTS) 3667f7e95215SViacheslav Ovsiienko return RTE_MAX_ETHPORTS; 3668f7e95215SViacheslav Ovsiienko return port_id; 3669f7e95215SViacheslav Ovsiienko } 3670f7e95215SViacheslav Ovsiienko 36713a820742SOphir Munk /** 36723a820742SOphir Munk * DPDK callback to remove a PCI device. 36733a820742SOphir Munk * 36743a820742SOphir Munk * This function removes all Ethernet devices belong to a given PCI device. 36753a820742SOphir Munk * 36763a820742SOphir Munk * @param[in] pci_dev 36773a820742SOphir Munk * Pointer to the PCI device. 36783a820742SOphir Munk * 36793a820742SOphir Munk * @return 36803a820742SOphir Munk * 0 on success, the function cannot fail. 36813a820742SOphir Munk */ 36823a820742SOphir Munk static int 36833a820742SOphir Munk mlx5_pci_remove(struct rte_pci_device *pci_dev) 36843a820742SOphir Munk { 36853a820742SOphir Munk uint16_t port_id; 36863a820742SOphir Munk 36875294b800SThomas Monjalon RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) 36883a820742SOphir Munk rte_eth_dev_close(port_id); 36893a820742SOphir Munk return 0; 36903a820742SOphir Munk } 36913a820742SOphir Munk 3692771fa900SAdrien Mazarguil static const struct rte_pci_id mlx5_pci_id_map[] = { 3693771fa900SAdrien Mazarguil { 36941d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 36951d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4) 3696771fa900SAdrien Mazarguil }, 3697771fa900SAdrien Mazarguil { 36981d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 36991d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) 3700771fa900SAdrien Mazarguil }, 3701771fa900SAdrien Mazarguil { 37021d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37031d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LX) 3704771fa900SAdrien Mazarguil }, 3705771fa900SAdrien Mazarguil { 37061d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37071d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) 3708771fa900SAdrien Mazarguil }, 3709771fa900SAdrien Mazarguil { 3710528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3711528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5) 3712528a9fbeSYongseok Koh }, 3713528a9fbeSYongseok Koh { 3714528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3715528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) 3716528a9fbeSYongseok Koh }, 3717528a9fbeSYongseok Koh { 3718528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3719528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EX) 3720528a9fbeSYongseok Koh }, 3721528a9fbeSYongseok Koh { 3722528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3723528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF) 3724528a9fbeSYongseok Koh }, 3725528a9fbeSYongseok Koh { 3726dd3331c6SShahaf Shuler RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3727dd3331c6SShahaf Shuler PCI_DEVICE_ID_MELLANOX_CONNECTX5BF) 3728dd3331c6SShahaf Shuler }, 3729dd3331c6SShahaf Shuler { 3730c322c0e5SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3731c322c0e5SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF) 3732c322c0e5SOri Kam }, 3733c322c0e5SOri Kam { 3734f0354d84SWisam Jaddo RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3735f0354d84SWisam Jaddo PCI_DEVICE_ID_MELLANOX_CONNECTX6) 3736f0354d84SWisam Jaddo }, 3737f0354d84SWisam Jaddo { 3738f0354d84SWisam Jaddo RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3739f0354d84SWisam Jaddo PCI_DEVICE_ID_MELLANOX_CONNECTX6VF) 3740f0354d84SWisam Jaddo }, 3741f0354d84SWisam Jaddo { 37425fc66630SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37435fc66630SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DX) 37445fc66630SRaslan Darawsheh }, 37455fc66630SRaslan Darawsheh { 37465fc66630SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37475fc66630SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF) 37485fc66630SRaslan Darawsheh }, 37495fc66630SRaslan Darawsheh { 375058b4a2b1SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 375158b4a2b1SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 375258b4a2b1SRaslan Darawsheh }, 375358b4a2b1SRaslan Darawsheh { 3754771fa900SAdrien Mazarguil .vendor_id = 0 3755771fa900SAdrien Mazarguil } 3756771fa900SAdrien Mazarguil }; 3757771fa900SAdrien Mazarguil 3758fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver = { 37592f3193cfSJan Viktorin .driver = { 37602f3193cfSJan Viktorin .name = MLX5_DRIVER_NAME 37612f3193cfSJan Viktorin }, 3762771fa900SAdrien Mazarguil .id_table = mlx5_pci_id_map, 3763af424af8SShreyansh Jain .probe = mlx5_pci_probe, 37643a820742SOphir Munk .remove = mlx5_pci_remove, 3765989e999dSShahaf Shuler .dma_map = mlx5_dma_map, 3766989e999dSShahaf Shuler .dma_unmap = mlx5_dma_unmap, 376769c06d0eSYongseok Koh .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_INTR_RMV | 3768b76fafb1SDavid Marchand RTE_PCI_DRV_PROBE_AGAIN, 3769771fa900SAdrien Mazarguil }; 3770771fa900SAdrien Mazarguil 3771771fa900SAdrien Mazarguil /** 3772771fa900SAdrien Mazarguil * Driver initialization routine. 3773771fa900SAdrien Mazarguil */ 3774f8e99896SThomas Monjalon RTE_INIT(rte_mlx5_pmd_init) 3775771fa900SAdrien Mazarguil { 37763d96644aSStephen Hemminger /* Initialize driver log type. */ 37773d96644aSStephen Hemminger mlx5_logtype = rte_log_register("pmd.net.mlx5"); 37783d96644aSStephen Hemminger if (mlx5_logtype >= 0) 37793d96644aSStephen Hemminger rte_log_set_level(mlx5_logtype, RTE_LOG_NOTICE); 37803d96644aSStephen Hemminger 37815f8ba81cSXueming Li /* Build the static tables for Verbs conversion. */ 3782ea16068cSYongseok Koh mlx5_set_ptype_table(); 37835f8ba81cSXueming Li mlx5_set_cksum_table(); 37845f8ba81cSXueming Li mlx5_set_swp_types_table(); 37857b4f1e6bSMatan Azrad if (mlx5_glue) 37863dcfe039SThomas Monjalon rte_pci_register(&mlx5_driver); 3787771fa900SAdrien Mazarguil } 3788771fa900SAdrien Mazarguil 378901f19227SShreyansh Jain RTE_PMD_EXPORT_NAME(net_mlx5, __COUNTER__); 379001f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_mlx5, mlx5_pci_id_map); 37910880c401SOlivier Matz RTE_PMD_REGISTER_KMOD_DEP(net_mlx5, "* ib_uverbs & mlx5_core & mlx5_ib"); 3792