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 /** 441fa2d01c8SDong Zhou * Initialize the shared aging list information per port. 442fa2d01c8SDong Zhou * 443fa2d01c8SDong Zhou * @param[in] sh 444fa2d01c8SDong Zhou * Pointer to mlx5_ibv_shared object. 445fa2d01c8SDong Zhou */ 446fa2d01c8SDong Zhou static void 447fa2d01c8SDong Zhou mlx5_flow_aging_init(struct mlx5_ibv_shared *sh) 448fa2d01c8SDong Zhou { 449fa2d01c8SDong Zhou uint32_t i; 450fa2d01c8SDong Zhou struct mlx5_age_info *age_info; 451fa2d01c8SDong Zhou 452fa2d01c8SDong Zhou for (i = 0; i < sh->max_port; i++) { 453fa2d01c8SDong Zhou age_info = &sh->port[i].age_info; 454fa2d01c8SDong Zhou age_info->flags = 0; 455fa2d01c8SDong Zhou TAILQ_INIT(&age_info->aged_counters); 456fa2d01c8SDong Zhou rte_spinlock_init(&age_info->aged_sl); 457fa2d01c8SDong Zhou MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER); 458fa2d01c8SDong Zhou } 459fa2d01c8SDong Zhou } 460fa2d01c8SDong Zhou 461fa2d01c8SDong Zhou /** 4625382d28cSMatan Azrad * Initialize the counters management structure. 4635382d28cSMatan Azrad * 4645382d28cSMatan Azrad * @param[in] sh 4655382d28cSMatan Azrad * Pointer to mlx5_ibv_shared object to free 4665382d28cSMatan Azrad */ 4675382d28cSMatan Azrad static void 4685382d28cSMatan Azrad mlx5_flow_counters_mng_init(struct mlx5_ibv_shared *sh) 4695382d28cSMatan Azrad { 470*5af61440SMatan Azrad int i; 4715382d28cSMatan Azrad 472*5af61440SMatan Azrad memset(&sh->cmng, 0, sizeof(sh->cmng)); 4735382d28cSMatan Azrad TAILQ_INIT(&sh->cmng.flow_counters); 474*5af61440SMatan Azrad for (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) { 475*5af61440SMatan Azrad TAILQ_INIT(&sh->cmng.ccont[i].pool_list); 476*5af61440SMatan Azrad rte_spinlock_init(&sh->cmng.ccont[i].resize_sl); 477fa2d01c8SDong Zhou } 4785382d28cSMatan Azrad } 4795382d28cSMatan Azrad 4805382d28cSMatan Azrad /** 4815382d28cSMatan Azrad * Destroy all the resources allocated for a counter memory management. 4825382d28cSMatan Azrad * 4835382d28cSMatan Azrad * @param[in] mng 4845382d28cSMatan Azrad * Pointer to the memory management structure. 4855382d28cSMatan Azrad */ 4865382d28cSMatan Azrad static void 4875382d28cSMatan Azrad mlx5_flow_destroy_counter_stat_mem_mng(struct mlx5_counter_stats_mem_mng *mng) 4885382d28cSMatan Azrad { 4895382d28cSMatan Azrad uint8_t *mem = (uint8_t *)(uintptr_t)mng->raws[0].data; 4905382d28cSMatan Azrad 4915382d28cSMatan Azrad LIST_REMOVE(mng, next); 4925382d28cSMatan Azrad claim_zero(mlx5_devx_cmd_destroy(mng->dm)); 4935382d28cSMatan Azrad claim_zero(mlx5_glue->devx_umem_dereg(mng->umem)); 4945382d28cSMatan Azrad rte_free(mem); 4955382d28cSMatan Azrad } 4965382d28cSMatan Azrad 4975382d28cSMatan Azrad /** 4985382d28cSMatan Azrad * Close and release all the resources of the counters management. 4995382d28cSMatan Azrad * 5005382d28cSMatan Azrad * @param[in] sh 5015382d28cSMatan Azrad * Pointer to mlx5_ibv_shared object to free. 5025382d28cSMatan Azrad */ 5035382d28cSMatan Azrad static void 5045382d28cSMatan Azrad mlx5_flow_counters_mng_close(struct mlx5_ibv_shared *sh) 5055382d28cSMatan Azrad { 5065382d28cSMatan Azrad struct mlx5_counter_stats_mem_mng *mng; 507*5af61440SMatan Azrad int i; 5085382d28cSMatan Azrad int j; 509f15db67dSMatan Azrad int retries = 1024; 5105382d28cSMatan Azrad 511f15db67dSMatan Azrad rte_errno = 0; 512f15db67dSMatan Azrad while (--retries) { 513f15db67dSMatan Azrad rte_eal_alarm_cancel(mlx5_flow_query_alarm, sh); 514f15db67dSMatan Azrad if (rte_errno != EINPROGRESS) 515f15db67dSMatan Azrad break; 516f15db67dSMatan Azrad rte_pause(); 517f15db67dSMatan Azrad } 518*5af61440SMatan Azrad for (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) { 5195382d28cSMatan Azrad struct mlx5_flow_counter_pool *pool; 520*5af61440SMatan Azrad uint32_t batch = !!(i > 1); 5215382d28cSMatan Azrad 522*5af61440SMatan Azrad if (!sh->cmng.ccont[i].pools) 5235382d28cSMatan Azrad continue; 524*5af61440SMatan Azrad pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 5255382d28cSMatan Azrad while (pool) { 526*5af61440SMatan Azrad if (batch && pool->min_dcs) 527*5af61440SMatan Azrad claim_zero(mlx5_devx_cmd_destroy 528fa2d01c8SDong Zhou (pool->min_dcs)); 5295382d28cSMatan Azrad for (j = 0; j < MLX5_COUNTERS_PER_POOL; ++j) { 5308d93c830SDong Zhou if (MLX5_POOL_GET_CNT(pool, j)->action) 5315382d28cSMatan Azrad claim_zero 5325382d28cSMatan Azrad (mlx5_glue->destroy_flow_action 533fa2d01c8SDong Zhou (MLX5_POOL_GET_CNT 534fa2d01c8SDong Zhou (pool, j)->action)); 535826b8a87SSuanming Mou if (!batch && MLX5_GET_POOL_CNT_EXT 536826b8a87SSuanming Mou (pool, j)->dcs) 5375382d28cSMatan Azrad claim_zero(mlx5_devx_cmd_destroy 538826b8a87SSuanming Mou (MLX5_GET_POOL_CNT_EXT 539826b8a87SSuanming Mou (pool, j)->dcs)); 5405382d28cSMatan Azrad } 541*5af61440SMatan Azrad TAILQ_REMOVE(&sh->cmng.ccont[i].pool_list, pool, next); 5425382d28cSMatan Azrad rte_free(pool); 543*5af61440SMatan Azrad pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 5445382d28cSMatan Azrad } 545*5af61440SMatan Azrad rte_free(sh->cmng.ccont[i].pools); 5465382d28cSMatan Azrad } 5475382d28cSMatan Azrad mng = LIST_FIRST(&sh->cmng.mem_mngs); 5485382d28cSMatan Azrad while (mng) { 5495382d28cSMatan Azrad mlx5_flow_destroy_counter_stat_mem_mng(mng); 5505382d28cSMatan Azrad mng = LIST_FIRST(&sh->cmng.mem_mngs); 5515382d28cSMatan Azrad } 5525382d28cSMatan Azrad memset(&sh->cmng, 0, sizeof(sh->cmng)); 5535382d28cSMatan Azrad } 5545382d28cSMatan Azrad 5555382d28cSMatan Azrad /** 556014d1cbeSSuanming Mou * Initialize the flow resources' indexed mempool. 557014d1cbeSSuanming Mou * 558014d1cbeSSuanming Mou * @param[in] sh 559014d1cbeSSuanming Mou * Pointer to mlx5_ibv_shared object. 560b88341caSSuanming Mou * @param[in] sh 561b88341caSSuanming Mou * Pointer to user dev config. 562014d1cbeSSuanming Mou */ 563014d1cbeSSuanming Mou static void 564b88341caSSuanming Mou mlx5_flow_ipool_create(struct mlx5_ibv_shared *sh, 565b88341caSSuanming Mou const struct mlx5_dev_config *config __rte_unused) 566014d1cbeSSuanming Mou { 567014d1cbeSSuanming Mou uint8_t i; 568014d1cbeSSuanming Mou 569b88341caSSuanming Mou #ifdef HAVE_IBV_FLOW_DV_SUPPORT 570b88341caSSuanming Mou /* 571b88341caSSuanming Mou * While DV is supported, user chooses the verbs mode, 572b88341caSSuanming Mou * the mlx5 flow handle size is different with the 573b88341caSSuanming Mou * MLX5_FLOW_HANDLE_VERBS_SIZE. 574b88341caSSuanming Mou */ 575b88341caSSuanming Mou if (!config->dv_flow_en) 576b88341caSSuanming Mou mlx5_ipool_cfg[MLX5_IPOOL_MLX5_FLOW].size = 577b88341caSSuanming Mou MLX5_FLOW_HANDLE_VERBS_SIZE; 578b88341caSSuanming Mou #endif 579014d1cbeSSuanming Mou for (i = 0; i < MLX5_IPOOL_MAX; ++i) 580014d1cbeSSuanming Mou sh->ipool[i] = mlx5_ipool_create(&mlx5_ipool_cfg[i]); 581014d1cbeSSuanming Mou } 582014d1cbeSSuanming Mou 583014d1cbeSSuanming Mou /** 584014d1cbeSSuanming Mou * Release the flow resources' indexed mempool. 585014d1cbeSSuanming Mou * 586014d1cbeSSuanming Mou * @param[in] sh 587014d1cbeSSuanming Mou * Pointer to mlx5_ibv_shared object. 588014d1cbeSSuanming Mou */ 589014d1cbeSSuanming Mou static void 590014d1cbeSSuanming Mou mlx5_flow_ipool_destroy(struct mlx5_ibv_shared *sh) 591014d1cbeSSuanming Mou { 592014d1cbeSSuanming Mou uint8_t i; 593014d1cbeSSuanming Mou 594014d1cbeSSuanming Mou for (i = 0; i < MLX5_IPOOL_MAX; ++i) 595014d1cbeSSuanming Mou mlx5_ipool_destroy(sh->ipool[i]); 596014d1cbeSSuanming Mou } 597014d1cbeSSuanming Mou 598014d1cbeSSuanming Mou /** 599b9d86122SDekel Peled * Extract pdn of PD object using DV API. 600b9d86122SDekel Peled * 601b9d86122SDekel Peled * @param[in] pd 602b9d86122SDekel Peled * Pointer to the verbs PD object. 603b9d86122SDekel Peled * @param[out] pdn 604b9d86122SDekel Peled * Pointer to the PD object number variable. 605b9d86122SDekel Peled * 606b9d86122SDekel Peled * @return 607b9d86122SDekel Peled * 0 on success, error value otherwise. 608b9d86122SDekel Peled */ 609b9d86122SDekel Peled #ifdef HAVE_IBV_FLOW_DV_SUPPORT 610b9d86122SDekel Peled static int 611b9d86122SDekel Peled mlx5_get_pdn(struct ibv_pd *pd __rte_unused, uint32_t *pdn __rte_unused) 612b9d86122SDekel Peled { 613b9d86122SDekel Peled struct mlx5dv_obj obj; 614b9d86122SDekel Peled struct mlx5dv_pd pd_info; 615b9d86122SDekel Peled int ret = 0; 616b9d86122SDekel Peled 617b9d86122SDekel Peled obj.pd.in = pd; 618b9d86122SDekel Peled obj.pd.out = &pd_info; 619b9d86122SDekel Peled ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD); 620b9d86122SDekel Peled if (ret) { 621b9d86122SDekel Peled DRV_LOG(DEBUG, "Fail to get PD object info"); 622b9d86122SDekel Peled return ret; 623b9d86122SDekel Peled } 624b9d86122SDekel Peled *pdn = pd_info.pdn; 625b9d86122SDekel Peled return 0; 626b9d86122SDekel Peled } 627b9d86122SDekel Peled #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 628b9d86122SDekel Peled 6298409a285SViacheslav Ovsiienko static int 6308409a285SViacheslav Ovsiienko mlx5_config_doorbell_mapping_env(const struct mlx5_dev_config *config) 6318409a285SViacheslav Ovsiienko { 6328409a285SViacheslav Ovsiienko char *env; 6338409a285SViacheslav Ovsiienko int value; 6348409a285SViacheslav Ovsiienko 6358e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 6368409a285SViacheslav Ovsiienko /* Get environment variable to store. */ 6378409a285SViacheslav Ovsiienko env = getenv(MLX5_SHUT_UP_BF); 6388409a285SViacheslav Ovsiienko value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET; 6398409a285SViacheslav Ovsiienko if (config->dbnc == MLX5_ARG_UNSET) 6408409a285SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1); 6418409a285SViacheslav Ovsiienko else 642f078ceb6SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, 643f078ceb6SViacheslav Ovsiienko config->dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1); 6448409a285SViacheslav Ovsiienko return value; 6458409a285SViacheslav Ovsiienko } 6468409a285SViacheslav Ovsiienko 6478409a285SViacheslav Ovsiienko static void 64806f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(int value) 6498409a285SViacheslav Ovsiienko { 6508e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 6518409a285SViacheslav Ovsiienko /* Restore the original environment variable state. */ 6528409a285SViacheslav Ovsiienko if (value == MLX5_ARG_UNSET) 6538409a285SViacheslav Ovsiienko unsetenv(MLX5_SHUT_UP_BF); 6548409a285SViacheslav Ovsiienko else 6558409a285SViacheslav Ovsiienko setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1); 6568409a285SViacheslav Ovsiienko } 6578409a285SViacheslav Ovsiienko 658b9d86122SDekel Peled /** 65917e19bc4SViacheslav Ovsiienko * Allocate shared IB device context. If there is multiport device the 66017e19bc4SViacheslav Ovsiienko * master and representors will share this context, if there is single 66117e19bc4SViacheslav Ovsiienko * port dedicated IB device, the context will be used by only given 66217e19bc4SViacheslav Ovsiienko * port due to unification. 66317e19bc4SViacheslav Ovsiienko * 664ae4eb7dcSViacheslav Ovsiienko * Routine first searches the context for the specified IB device name, 66517e19bc4SViacheslav Ovsiienko * if found the shared context assumed and reference counter is incremented. 66617e19bc4SViacheslav Ovsiienko * If no context found the new one is created and initialized with specified 66717e19bc4SViacheslav Ovsiienko * IB device context and parameters. 66817e19bc4SViacheslav Ovsiienko * 66917e19bc4SViacheslav Ovsiienko * @param[in] spawn 67017e19bc4SViacheslav Ovsiienko * Pointer to the IB device attributes (name, port, etc). 6718409a285SViacheslav Ovsiienko * @param[in] config 6728409a285SViacheslav Ovsiienko * Pointer to device configuration structure. 67317e19bc4SViacheslav Ovsiienko * 67417e19bc4SViacheslav Ovsiienko * @return 67517e19bc4SViacheslav Ovsiienko * Pointer to mlx5_ibv_shared object on success, 67617e19bc4SViacheslav Ovsiienko * otherwise NULL and rte_errno is set. 67717e19bc4SViacheslav Ovsiienko */ 67817e19bc4SViacheslav Ovsiienko static struct mlx5_ibv_shared * 6798409a285SViacheslav Ovsiienko mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn, 6808409a285SViacheslav Ovsiienko const struct mlx5_dev_config *config) 68117e19bc4SViacheslav Ovsiienko { 68217e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *sh; 6838409a285SViacheslav Ovsiienko int dbmap_env; 68417e19bc4SViacheslav Ovsiienko int err = 0; 68553e5a82fSViacheslav Ovsiienko uint32_t i; 686ae18a1aeSOri Kam #ifdef HAVE_IBV_FLOW_DV_SUPPORT 687ae18a1aeSOri Kam struct mlx5_devx_tis_attr tis_attr = { 0 }; 688ae18a1aeSOri Kam #endif 68917e19bc4SViacheslav Ovsiienko 6908e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn); 69117e19bc4SViacheslav Ovsiienko /* Secondary process should not create the shared context. */ 6928e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 69317e19bc4SViacheslav Ovsiienko pthread_mutex_lock(&mlx5_ibv_list_mutex); 69417e19bc4SViacheslav Ovsiienko /* Search for IB context by device name. */ 69517e19bc4SViacheslav Ovsiienko LIST_FOREACH(sh, &mlx5_ibv_list, next) { 69617e19bc4SViacheslav Ovsiienko if (!strcmp(sh->ibdev_name, spawn->ibv_dev->name)) { 69717e19bc4SViacheslav Ovsiienko sh->refcnt++; 69817e19bc4SViacheslav Ovsiienko goto exit; 69917e19bc4SViacheslav Ovsiienko } 70017e19bc4SViacheslav Ovsiienko } 701ae4eb7dcSViacheslav Ovsiienko /* No device found, we have to create new shared context. */ 7028e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn->max_port); 70317e19bc4SViacheslav Ovsiienko sh = rte_zmalloc("ethdev shared ib context", 70417e19bc4SViacheslav Ovsiienko sizeof(struct mlx5_ibv_shared) + 70517e19bc4SViacheslav Ovsiienko spawn->max_port * 70617e19bc4SViacheslav Ovsiienko sizeof(struct mlx5_ibv_shared_port), 70717e19bc4SViacheslav Ovsiienko RTE_CACHE_LINE_SIZE); 70817e19bc4SViacheslav Ovsiienko if (!sh) { 70917e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "shared context allocation failure"); 71017e19bc4SViacheslav Ovsiienko rte_errno = ENOMEM; 71117e19bc4SViacheslav Ovsiienko goto exit; 71217e19bc4SViacheslav Ovsiienko } 7138409a285SViacheslav Ovsiienko /* 7148409a285SViacheslav Ovsiienko * Configure environment variable "MLX5_BF_SHUT_UP" 7158409a285SViacheslav Ovsiienko * before the device creation. The rdma_core library 7168409a285SViacheslav Ovsiienko * checks the variable at device creation and 7178409a285SViacheslav Ovsiienko * stores the result internally. 7188409a285SViacheslav Ovsiienko */ 7198409a285SViacheslav Ovsiienko dbmap_env = mlx5_config_doorbell_mapping_env(config); 72017e19bc4SViacheslav Ovsiienko /* Try to open IB device with DV first, then usual Verbs. */ 72117e19bc4SViacheslav Ovsiienko errno = 0; 72217e19bc4SViacheslav Ovsiienko sh->ctx = mlx5_glue->dv_open_device(spawn->ibv_dev); 72317e19bc4SViacheslav Ovsiienko if (sh->ctx) { 72417e19bc4SViacheslav Ovsiienko sh->devx = 1; 72517e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "DevX is supported"); 7268409a285SViacheslav Ovsiienko /* The device is created, no need for environment. */ 72706f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(dbmap_env); 72817e19bc4SViacheslav Ovsiienko } else { 7298409a285SViacheslav Ovsiienko /* The environment variable is still configured. */ 73017e19bc4SViacheslav Ovsiienko sh->ctx = mlx5_glue->open_device(spawn->ibv_dev); 73117e19bc4SViacheslav Ovsiienko err = errno ? errno : ENODEV; 7328409a285SViacheslav Ovsiienko /* 7338409a285SViacheslav Ovsiienko * The environment variable is not needed anymore, 7348409a285SViacheslav Ovsiienko * all device creation attempts are completed. 7358409a285SViacheslav Ovsiienko */ 73606f78b5eSViacheslav Ovsiienko mlx5_restore_doorbell_mapping_env(dbmap_env); 73706f78b5eSViacheslav Ovsiienko if (!sh->ctx) 73817e19bc4SViacheslav Ovsiienko goto error; 73917e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "DevX is NOT supported"); 74017e19bc4SViacheslav Ovsiienko } 74117e19bc4SViacheslav Ovsiienko err = mlx5_glue->query_device_ex(sh->ctx, NULL, &sh->device_attr); 74217e19bc4SViacheslav Ovsiienko if (err) { 74317e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "ibv_query_device_ex() failed"); 74417e19bc4SViacheslav Ovsiienko goto error; 74517e19bc4SViacheslav Ovsiienko } 74617e19bc4SViacheslav Ovsiienko sh->refcnt = 1; 74717e19bc4SViacheslav Ovsiienko sh->max_port = spawn->max_port; 74817e19bc4SViacheslav Ovsiienko strncpy(sh->ibdev_name, sh->ctx->device->name, 74917e19bc4SViacheslav Ovsiienko sizeof(sh->ibdev_name)); 75017e19bc4SViacheslav Ovsiienko strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path, 75117e19bc4SViacheslav Ovsiienko sizeof(sh->ibdev_path)); 75253e5a82fSViacheslav Ovsiienko pthread_mutex_init(&sh->intr_mutex, NULL); 75353e5a82fSViacheslav Ovsiienko /* 75453e5a82fSViacheslav Ovsiienko * Setting port_id to max unallowed value means 75553e5a82fSViacheslav Ovsiienko * there is no interrupt subhandler installed for 75653e5a82fSViacheslav Ovsiienko * the given port index i. 75753e5a82fSViacheslav Ovsiienko */ 75823242063SMatan Azrad for (i = 0; i < sh->max_port; i++) { 75953e5a82fSViacheslav Ovsiienko sh->port[i].ih_port_id = RTE_MAX_ETHPORTS; 76023242063SMatan Azrad sh->port[i].devx_ih_port_id = RTE_MAX_ETHPORTS; 76123242063SMatan Azrad } 76217e19bc4SViacheslav Ovsiienko sh->pd = mlx5_glue->alloc_pd(sh->ctx); 76317e19bc4SViacheslav Ovsiienko if (sh->pd == NULL) { 76417e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "PD allocation failure"); 76517e19bc4SViacheslav Ovsiienko err = ENOMEM; 76617e19bc4SViacheslav Ovsiienko goto error; 76717e19bc4SViacheslav Ovsiienko } 768b9d86122SDekel Peled #ifdef HAVE_IBV_FLOW_DV_SUPPORT 769ae18a1aeSOri Kam if (sh->devx) { 770b9d86122SDekel Peled err = mlx5_get_pdn(sh->pd, &sh->pdn); 771b9d86122SDekel Peled if (err) { 772b9d86122SDekel Peled DRV_LOG(ERR, "Fail to extract pdn from PD"); 773b9d86122SDekel Peled goto error; 774b9d86122SDekel Peled } 775ae18a1aeSOri Kam sh->td = mlx5_devx_cmd_create_td(sh->ctx); 776ae18a1aeSOri Kam if (!sh->td) { 777ae18a1aeSOri Kam DRV_LOG(ERR, "TD allocation failure"); 778ae18a1aeSOri Kam err = ENOMEM; 779ae18a1aeSOri Kam goto error; 780ae18a1aeSOri Kam } 781ae18a1aeSOri Kam tis_attr.transport_domain = sh->td->id; 782ae18a1aeSOri Kam sh->tis = mlx5_devx_cmd_create_tis(sh->ctx, &tis_attr); 783ae18a1aeSOri Kam if (!sh->tis) { 784ae18a1aeSOri Kam DRV_LOG(ERR, "TIS allocation failure"); 785ae18a1aeSOri Kam err = ENOMEM; 786ae18a1aeSOri Kam goto error; 787ae18a1aeSOri Kam } 788ae18a1aeSOri Kam } 7890136df99SSuanming Mou sh->flow_id_pool = mlx5_flow_id_pool_alloc 7900136df99SSuanming Mou ((1 << HAIRPIN_FLOW_ID_BITS) - 1); 791d85c7b5eSOri Kam if (!sh->flow_id_pool) { 792d85c7b5eSOri Kam DRV_LOG(ERR, "can't create flow id pool"); 793d85c7b5eSOri Kam err = ENOMEM; 794d85c7b5eSOri Kam goto error; 795d85c7b5eSOri Kam } 796b9d86122SDekel Peled #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 797ab3cffcfSViacheslav Ovsiienko /* 798ab3cffcfSViacheslav Ovsiienko * Once the device is added to the list of memory event 799ab3cffcfSViacheslav Ovsiienko * callback, its global MR cache table cannot be expanded 800ab3cffcfSViacheslav Ovsiienko * on the fly because of deadlock. If it overflows, lookup 801ab3cffcfSViacheslav Ovsiienko * should be done by searching MR list linearly, which is slow. 802ab3cffcfSViacheslav Ovsiienko * 803ab3cffcfSViacheslav Ovsiienko * At this point the device is not added to the memory 804ab3cffcfSViacheslav Ovsiienko * event list yet, context is just being created. 805ab3cffcfSViacheslav Ovsiienko */ 806b8dc6b0eSVu Pham err = mlx5_mr_btree_init(&sh->share_cache.cache, 807ab3cffcfSViacheslav Ovsiienko MLX5_MR_BTREE_CACHE_N * 2, 80846e10a4cSViacheslav Ovsiienko spawn->pci_dev->device.numa_node); 809ab3cffcfSViacheslav Ovsiienko if (err) { 810ab3cffcfSViacheslav Ovsiienko err = rte_errno; 811ab3cffcfSViacheslav Ovsiienko goto error; 812ab3cffcfSViacheslav Ovsiienko } 813fa2d01c8SDong Zhou mlx5_flow_aging_init(sh); 8145382d28cSMatan Azrad mlx5_flow_counters_mng_init(sh); 815b88341caSSuanming Mou mlx5_flow_ipool_create(sh, config); 8160e3d0525SViacheslav Ovsiienko /* Add device to memory callback list. */ 8170e3d0525SViacheslav Ovsiienko rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 8180e3d0525SViacheslav Ovsiienko LIST_INSERT_HEAD(&mlx5_shared_data->mem_event_cb_list, 8190e3d0525SViacheslav Ovsiienko sh, mem_event_cb); 8200e3d0525SViacheslav Ovsiienko rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 8210e3d0525SViacheslav Ovsiienko /* Add context to the global device list. */ 82217e19bc4SViacheslav Ovsiienko LIST_INSERT_HEAD(&mlx5_ibv_list, sh, next); 82317e19bc4SViacheslav Ovsiienko exit: 82417e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 82517e19bc4SViacheslav Ovsiienko return sh; 82617e19bc4SViacheslav Ovsiienko error: 82717e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 8288e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 829ae18a1aeSOri Kam if (sh->tis) 830ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 831ae18a1aeSOri Kam if (sh->td) 832ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->td)); 83317e19bc4SViacheslav Ovsiienko if (sh->pd) 83417e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 83517e19bc4SViacheslav Ovsiienko if (sh->ctx) 83617e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->close_device(sh->ctx)); 837d85c7b5eSOri Kam if (sh->flow_id_pool) 838d85c7b5eSOri Kam mlx5_flow_id_pool_release(sh->flow_id_pool); 83917e19bc4SViacheslav Ovsiienko rte_free(sh); 8408e46d4e1SAlexander Kozyrev MLX5_ASSERT(err > 0); 84117e19bc4SViacheslav Ovsiienko rte_errno = err; 84217e19bc4SViacheslav Ovsiienko return NULL; 84317e19bc4SViacheslav Ovsiienko } 84417e19bc4SViacheslav Ovsiienko 84517e19bc4SViacheslav Ovsiienko /** 84617e19bc4SViacheslav Ovsiienko * Free shared IB device context. Decrement counter and if zero free 84717e19bc4SViacheslav Ovsiienko * all allocated resources and close handles. 84817e19bc4SViacheslav Ovsiienko * 84917e19bc4SViacheslav Ovsiienko * @param[in] sh 85017e19bc4SViacheslav Ovsiienko * Pointer to mlx5_ibv_shared object to free 85117e19bc4SViacheslav Ovsiienko */ 85217e19bc4SViacheslav Ovsiienko static void 85317e19bc4SViacheslav Ovsiienko mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh) 85417e19bc4SViacheslav Ovsiienko { 85517e19bc4SViacheslav Ovsiienko pthread_mutex_lock(&mlx5_ibv_list_mutex); 8560afacb04SAlexander Kozyrev #ifdef RTE_LIBRTE_MLX5_DEBUG 85717e19bc4SViacheslav Ovsiienko /* Check the object presence in the list. */ 85817e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *lctx; 85917e19bc4SViacheslav Ovsiienko 86017e19bc4SViacheslav Ovsiienko LIST_FOREACH(lctx, &mlx5_ibv_list, next) 86117e19bc4SViacheslav Ovsiienko if (lctx == sh) 86217e19bc4SViacheslav Ovsiienko break; 8638e46d4e1SAlexander Kozyrev MLX5_ASSERT(lctx); 86417e19bc4SViacheslav Ovsiienko if (lctx != sh) { 86517e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "Freeing non-existing shared IB context"); 86617e19bc4SViacheslav Ovsiienko goto exit; 86717e19bc4SViacheslav Ovsiienko } 86817e19bc4SViacheslav Ovsiienko #endif 8698e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 8708e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh->refcnt); 87117e19bc4SViacheslav Ovsiienko /* Secondary process should not free the shared context. */ 8728e46d4e1SAlexander Kozyrev MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 87317e19bc4SViacheslav Ovsiienko if (--sh->refcnt) 87417e19bc4SViacheslav Ovsiienko goto exit; 8750e3d0525SViacheslav Ovsiienko /* Remove from memory callback device list. */ 8760e3d0525SViacheslav Ovsiienko rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 8770e3d0525SViacheslav Ovsiienko LIST_REMOVE(sh, mem_event_cb); 8780e3d0525SViacheslav Ovsiienko rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 8794f8e6befSMichael Baum /* Release created Memory Regions. */ 880b8dc6b0eSVu Pham mlx5_mr_release_cache(&sh->share_cache); 8810e3d0525SViacheslav Ovsiienko /* Remove context from the global device list. */ 88217e19bc4SViacheslav Ovsiienko LIST_REMOVE(sh, next); 88353e5a82fSViacheslav Ovsiienko /* 88453e5a82fSViacheslav Ovsiienko * Ensure there is no async event handler installed. 88553e5a82fSViacheslav Ovsiienko * Only primary process handles async device events. 88653e5a82fSViacheslav Ovsiienko **/ 8875382d28cSMatan Azrad mlx5_flow_counters_mng_close(sh); 888014d1cbeSSuanming Mou mlx5_flow_ipool_destroy(sh); 8898e46d4e1SAlexander Kozyrev MLX5_ASSERT(!sh->intr_cnt); 89053e5a82fSViacheslav Ovsiienko if (sh->intr_cnt) 8915897ac13SViacheslav Ovsiienko mlx5_intr_callback_unregister 89253e5a82fSViacheslav Ovsiienko (&sh->intr_handle, mlx5_dev_interrupt_handler, sh); 89323242063SMatan Azrad #ifdef HAVE_MLX5_DEVX_ASYNC_SUPPORT 89423242063SMatan Azrad if (sh->devx_intr_cnt) { 89523242063SMatan Azrad if (sh->intr_handle_devx.fd) 89623242063SMatan Azrad rte_intr_callback_unregister(&sh->intr_handle_devx, 89723242063SMatan Azrad mlx5_dev_interrupt_handler_devx, sh); 89823242063SMatan Azrad if (sh->devx_comp) 89923242063SMatan Azrad mlx5dv_devx_destroy_cmd_comp(sh->devx_comp); 90023242063SMatan Azrad } 90123242063SMatan Azrad #endif 90253e5a82fSViacheslav Ovsiienko pthread_mutex_destroy(&sh->intr_mutex); 90317e19bc4SViacheslav Ovsiienko if (sh->pd) 90417e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 905ae18a1aeSOri Kam if (sh->tis) 906ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 907ae18a1aeSOri Kam if (sh->td) 908ae18a1aeSOri Kam claim_zero(mlx5_devx_cmd_destroy(sh->td)); 90917e19bc4SViacheslav Ovsiienko if (sh->ctx) 91017e19bc4SViacheslav Ovsiienko claim_zero(mlx5_glue->close_device(sh->ctx)); 911d85c7b5eSOri Kam if (sh->flow_id_pool) 912d85c7b5eSOri Kam mlx5_flow_id_pool_release(sh->flow_id_pool); 91317e19bc4SViacheslav Ovsiienko rte_free(sh); 91417e19bc4SViacheslav Ovsiienko exit: 91517e19bc4SViacheslav Ovsiienko pthread_mutex_unlock(&mlx5_ibv_list_mutex); 91617e19bc4SViacheslav Ovsiienko } 91717e19bc4SViacheslav Ovsiienko 918771fa900SAdrien Mazarguil /** 91954534725SMatan Azrad * Destroy table hash list and all the root entries per domain. 92054534725SMatan Azrad * 92154534725SMatan Azrad * @param[in] priv 92254534725SMatan Azrad * Pointer to the private device data structure. 92354534725SMatan Azrad */ 92454534725SMatan Azrad static void 92554534725SMatan Azrad mlx5_free_table_hash_list(struct mlx5_priv *priv) 92654534725SMatan Azrad { 92754534725SMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 92854534725SMatan Azrad struct mlx5_flow_tbl_data_entry *tbl_data; 92954534725SMatan Azrad union mlx5_flow_tbl_key table_key = { 93054534725SMatan Azrad { 93154534725SMatan Azrad .table_id = 0, 93254534725SMatan Azrad .reserved = 0, 93354534725SMatan Azrad .domain = 0, 93454534725SMatan Azrad .direction = 0, 93554534725SMatan Azrad } 93654534725SMatan Azrad }; 93754534725SMatan Azrad struct mlx5_hlist_entry *pos; 93854534725SMatan Azrad 93954534725SMatan Azrad if (!sh->flow_tbls) 94054534725SMatan Azrad return; 94154534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 94254534725SMatan Azrad if (pos) { 94354534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 94454534725SMatan Azrad entry); 9458e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 94654534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 94754534725SMatan Azrad rte_free(tbl_data); 94854534725SMatan Azrad } 94954534725SMatan Azrad table_key.direction = 1; 95054534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 95154534725SMatan Azrad if (pos) { 95254534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 95354534725SMatan Azrad entry); 9548e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 95554534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 95654534725SMatan Azrad rte_free(tbl_data); 95754534725SMatan Azrad } 95854534725SMatan Azrad table_key.direction = 0; 95954534725SMatan Azrad table_key.domain = 1; 96054534725SMatan Azrad pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 96154534725SMatan Azrad if (pos) { 96254534725SMatan Azrad tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 96354534725SMatan Azrad entry); 9648e46d4e1SAlexander Kozyrev MLX5_ASSERT(tbl_data); 96554534725SMatan Azrad mlx5_hlist_remove(sh->flow_tbls, pos); 96654534725SMatan Azrad rte_free(tbl_data); 96754534725SMatan Azrad } 96854534725SMatan Azrad mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL); 96954534725SMatan Azrad } 97054534725SMatan Azrad 97154534725SMatan Azrad /** 97254534725SMatan Azrad * Initialize flow table hash list and create the root tables entry 97354534725SMatan Azrad * for each domain. 97454534725SMatan Azrad * 97554534725SMatan Azrad * @param[in] priv 97654534725SMatan Azrad * Pointer to the private device data structure. 97754534725SMatan Azrad * 97854534725SMatan Azrad * @return 97954534725SMatan Azrad * Zero on success, positive error code otherwise. 98054534725SMatan Azrad */ 98154534725SMatan Azrad static int 98254534725SMatan Azrad mlx5_alloc_table_hash_list(struct mlx5_priv *priv) 98354534725SMatan Azrad { 98454534725SMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 98554534725SMatan Azrad char s[MLX5_HLIST_NAMESIZE]; 98654534725SMatan Azrad int err = 0; 98754534725SMatan Azrad 9888e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 98954534725SMatan Azrad snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name); 99054534725SMatan Azrad sh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE); 99154534725SMatan Azrad if (!sh->flow_tbls) { 99254534725SMatan Azrad DRV_LOG(ERR, "flow tables with hash creation failed.\n"); 99354534725SMatan Azrad err = ENOMEM; 99454534725SMatan Azrad return err; 99554534725SMatan Azrad } 99654534725SMatan Azrad #ifndef HAVE_MLX5DV_DR 99754534725SMatan Azrad /* 99854534725SMatan Azrad * In case we have not DR support, the zero tables should be created 99954534725SMatan Azrad * because DV expect to see them even if they cannot be created by 100054534725SMatan Azrad * RDMA-CORE. 100154534725SMatan Azrad */ 100254534725SMatan Azrad union mlx5_flow_tbl_key table_key = { 100354534725SMatan Azrad { 100454534725SMatan Azrad .table_id = 0, 100554534725SMatan Azrad .reserved = 0, 100654534725SMatan Azrad .domain = 0, 100754534725SMatan Azrad .direction = 0, 100854534725SMatan Azrad } 100954534725SMatan Azrad }; 101054534725SMatan Azrad struct mlx5_flow_tbl_data_entry *tbl_data = rte_zmalloc(NULL, 101154534725SMatan Azrad sizeof(*tbl_data), 0); 101254534725SMatan Azrad 101354534725SMatan Azrad if (!tbl_data) { 101454534725SMatan Azrad err = ENOMEM; 101554534725SMatan Azrad goto error; 101654534725SMatan Azrad } 101754534725SMatan Azrad tbl_data->entry.key = table_key.v64; 101854534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 101954534725SMatan Azrad if (err) 102054534725SMatan Azrad goto error; 102154534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 102254534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 102354534725SMatan Azrad table_key.direction = 1; 102454534725SMatan Azrad tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0); 102554534725SMatan Azrad if (!tbl_data) { 102654534725SMatan Azrad err = ENOMEM; 102754534725SMatan Azrad goto error; 102854534725SMatan Azrad } 102954534725SMatan Azrad tbl_data->entry.key = table_key.v64; 103054534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 103154534725SMatan Azrad if (err) 103254534725SMatan Azrad goto error; 103354534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 103454534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 103554534725SMatan Azrad table_key.direction = 0; 103654534725SMatan Azrad table_key.domain = 1; 103754534725SMatan Azrad tbl_data = rte_zmalloc(NULL, sizeof(*tbl_data), 0); 103854534725SMatan Azrad if (!tbl_data) { 103954534725SMatan Azrad err = ENOMEM; 104054534725SMatan Azrad goto error; 104154534725SMatan Azrad } 104254534725SMatan Azrad tbl_data->entry.key = table_key.v64; 104354534725SMatan Azrad err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 104454534725SMatan Azrad if (err) 104554534725SMatan Azrad goto error; 104654534725SMatan Azrad rte_atomic32_init(&tbl_data->tbl.refcnt); 104754534725SMatan Azrad rte_atomic32_inc(&tbl_data->tbl.refcnt); 104854534725SMatan Azrad return err; 104954534725SMatan Azrad error: 105054534725SMatan Azrad mlx5_free_table_hash_list(priv); 105154534725SMatan Azrad #endif /* HAVE_MLX5DV_DR */ 105254534725SMatan Azrad return err; 105354534725SMatan Azrad } 105454534725SMatan Azrad 105554534725SMatan Azrad /** 1056b2177648SViacheslav Ovsiienko * Initialize DR related data within private structure. 1057b2177648SViacheslav Ovsiienko * Routine checks the reference counter and does actual 1058ae4eb7dcSViacheslav Ovsiienko * resources creation/initialization only if counter is zero. 1059b2177648SViacheslav Ovsiienko * 1060b2177648SViacheslav Ovsiienko * @param[in] priv 1061b2177648SViacheslav Ovsiienko * Pointer to the private device data structure. 1062b2177648SViacheslav Ovsiienko * 1063b2177648SViacheslav Ovsiienko * @return 1064b2177648SViacheslav Ovsiienko * Zero on success, positive error code otherwise. 1065b2177648SViacheslav Ovsiienko */ 1066b2177648SViacheslav Ovsiienko static int 1067b2177648SViacheslav Ovsiienko mlx5_alloc_shared_dr(struct mlx5_priv *priv) 1068b2177648SViacheslav Ovsiienko { 10691ef4cdefSMatan Azrad struct mlx5_ibv_shared *sh = priv->sh; 10701ef4cdefSMatan Azrad char s[MLX5_HLIST_NAMESIZE]; 107168011166SXiaoyu Min int err = 0; 107254534725SMatan Azrad 107368011166SXiaoyu Min if (!sh->flow_tbls) 107468011166SXiaoyu Min err = mlx5_alloc_table_hash_list(priv); 107568011166SXiaoyu Min else 107668011166SXiaoyu Min DRV_LOG(DEBUG, "sh->flow_tbls[%p] already created, reuse\n", 107768011166SXiaoyu Min (void *)sh->flow_tbls); 107854534725SMatan Azrad if (err) 107954534725SMatan Azrad return err; 10801ef4cdefSMatan Azrad /* Create tags hash list table. */ 10811ef4cdefSMatan Azrad snprintf(s, sizeof(s), "%s_tags", sh->ibdev_name); 10821ef4cdefSMatan Azrad sh->tag_table = mlx5_hlist_create(s, MLX5_TAGS_HLIST_ARRAY_SIZE); 10831ef4cdefSMatan Azrad if (!sh->tag_table) { 10841ef4cdefSMatan Azrad DRV_LOG(ERR, "tags with hash creation failed.\n"); 10851ef4cdefSMatan Azrad err = ENOMEM; 10861ef4cdefSMatan Azrad goto error; 10871ef4cdefSMatan Azrad } 1088b2177648SViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR 108954534725SMatan Azrad void *domain; 1090b2177648SViacheslav Ovsiienko 1091b2177648SViacheslav Ovsiienko if (sh->dv_refcnt) { 1092b2177648SViacheslav Ovsiienko /* Shared DV/DR structures is already initialized. */ 1093b2177648SViacheslav Ovsiienko sh->dv_refcnt++; 1094b2177648SViacheslav Ovsiienko priv->dr_shared = 1; 1095b2177648SViacheslav Ovsiienko return 0; 1096b2177648SViacheslav Ovsiienko } 1097b2177648SViacheslav Ovsiienko /* Reference counter is zero, we should initialize structures. */ 1098d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain(sh->ctx, 1099d1e64fbfSOri Kam MLX5DV_DR_DOMAIN_TYPE_NIC_RX); 1100d1e64fbfSOri Kam if (!domain) { 1101d1e64fbfSOri Kam DRV_LOG(ERR, "ingress mlx5dv_dr_create_domain failed"); 1102b2177648SViacheslav Ovsiienko err = errno; 1103b2177648SViacheslav Ovsiienko goto error; 1104b2177648SViacheslav Ovsiienko } 1105d1e64fbfSOri Kam sh->rx_domain = domain; 1106d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain(sh->ctx, 1107d1e64fbfSOri Kam MLX5DV_DR_DOMAIN_TYPE_NIC_TX); 1108d1e64fbfSOri Kam if (!domain) { 1109d1e64fbfSOri Kam DRV_LOG(ERR, "egress mlx5dv_dr_create_domain failed"); 1110b2177648SViacheslav Ovsiienko err = errno; 1111b2177648SViacheslav Ovsiienko goto error; 1112b2177648SViacheslav Ovsiienko } 111379e35d0dSViacheslav Ovsiienko pthread_mutex_init(&sh->dv_mutex, NULL); 1114d1e64fbfSOri Kam sh->tx_domain = domain; 1115e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 1116e2b4925eSOri Kam if (priv->config.dv_esw_en) { 1117d1e64fbfSOri Kam domain = mlx5_glue->dr_create_domain 1118d1e64fbfSOri Kam (sh->ctx, MLX5DV_DR_DOMAIN_TYPE_FDB); 1119d1e64fbfSOri Kam if (!domain) { 1120d1e64fbfSOri Kam DRV_LOG(ERR, "FDB mlx5dv_dr_create_domain failed"); 1121e2b4925eSOri Kam err = errno; 1122e2b4925eSOri Kam goto error; 1123e2b4925eSOri Kam } 1124d1e64fbfSOri Kam sh->fdb_domain = domain; 112534fa7c02SOri Kam sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop(); 1126e2b4925eSOri Kam } 1127e2b4925eSOri Kam #endif 1128b41e47daSMoti Haimovsky sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan(); 11291ef4cdefSMatan Azrad #endif /* HAVE_MLX5DV_DR */ 1130b2177648SViacheslav Ovsiienko sh->dv_refcnt++; 1131b2177648SViacheslav Ovsiienko priv->dr_shared = 1; 1132b2177648SViacheslav Ovsiienko return 0; 1133b2177648SViacheslav Ovsiienko error: 1134b2177648SViacheslav Ovsiienko /* Rollback the created objects. */ 1135d1e64fbfSOri Kam if (sh->rx_domain) { 1136d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->rx_domain); 1137d1e64fbfSOri Kam sh->rx_domain = NULL; 1138b2177648SViacheslav Ovsiienko } 1139d1e64fbfSOri Kam if (sh->tx_domain) { 1140d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->tx_domain); 1141d1e64fbfSOri Kam sh->tx_domain = NULL; 1142b2177648SViacheslav Ovsiienko } 1143d1e64fbfSOri Kam if (sh->fdb_domain) { 1144d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->fdb_domain); 1145d1e64fbfSOri Kam sh->fdb_domain = NULL; 1146e2b4925eSOri Kam } 114734fa7c02SOri Kam if (sh->esw_drop_action) { 114834fa7c02SOri Kam mlx5_glue->destroy_flow_action(sh->esw_drop_action); 114934fa7c02SOri Kam sh->esw_drop_action = NULL; 115034fa7c02SOri Kam } 1151b41e47daSMoti Haimovsky if (sh->pop_vlan_action) { 1152b41e47daSMoti Haimovsky mlx5_glue->destroy_flow_action(sh->pop_vlan_action); 1153b41e47daSMoti Haimovsky sh->pop_vlan_action = NULL; 1154b41e47daSMoti Haimovsky } 11551ef4cdefSMatan Azrad if (sh->tag_table) { 11561ef4cdefSMatan Azrad /* tags should be destroyed with flow before. */ 11571ef4cdefSMatan Azrad mlx5_hlist_destroy(sh->tag_table, NULL, NULL); 11581ef4cdefSMatan Azrad sh->tag_table = NULL; 11591ef4cdefSMatan Azrad } 116054534725SMatan Azrad mlx5_free_table_hash_list(priv); 116154534725SMatan Azrad return err; 1162b2177648SViacheslav Ovsiienko } 1163b2177648SViacheslav Ovsiienko 1164b2177648SViacheslav Ovsiienko /** 1165b2177648SViacheslav Ovsiienko * Destroy DR related data within private structure. 1166b2177648SViacheslav Ovsiienko * 1167b2177648SViacheslav Ovsiienko * @param[in] priv 1168b2177648SViacheslav Ovsiienko * Pointer to the private device data structure. 1169b2177648SViacheslav Ovsiienko */ 1170b2177648SViacheslav Ovsiienko static void 1171b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(struct mlx5_priv *priv) 1172b2177648SViacheslav Ovsiienko { 1173b2177648SViacheslav Ovsiienko struct mlx5_ibv_shared *sh; 1174b2177648SViacheslav Ovsiienko 1175b2177648SViacheslav Ovsiienko if (!priv->dr_shared) 1176b2177648SViacheslav Ovsiienko return; 1177b2177648SViacheslav Ovsiienko priv->dr_shared = 0; 1178b2177648SViacheslav Ovsiienko sh = priv->sh; 11798e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 11801ef4cdefSMatan Azrad #ifdef HAVE_MLX5DV_DR 11818e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh->dv_refcnt); 1182b2177648SViacheslav Ovsiienko if (sh->dv_refcnt && --sh->dv_refcnt) 1183b2177648SViacheslav Ovsiienko return; 1184d1e64fbfSOri Kam if (sh->rx_domain) { 1185d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->rx_domain); 1186d1e64fbfSOri Kam sh->rx_domain = NULL; 1187b2177648SViacheslav Ovsiienko } 1188d1e64fbfSOri Kam if (sh->tx_domain) { 1189d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->tx_domain); 1190d1e64fbfSOri Kam sh->tx_domain = NULL; 1191b2177648SViacheslav Ovsiienko } 1192e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 1193d1e64fbfSOri Kam if (sh->fdb_domain) { 1194d1e64fbfSOri Kam mlx5_glue->dr_destroy_domain(sh->fdb_domain); 1195d1e64fbfSOri Kam sh->fdb_domain = NULL; 1196e2b4925eSOri Kam } 119734fa7c02SOri Kam if (sh->esw_drop_action) { 119834fa7c02SOri Kam mlx5_glue->destroy_flow_action(sh->esw_drop_action); 119934fa7c02SOri Kam sh->esw_drop_action = NULL; 120034fa7c02SOri Kam } 1201e2b4925eSOri Kam #endif 1202b41e47daSMoti Haimovsky if (sh->pop_vlan_action) { 1203b41e47daSMoti Haimovsky mlx5_glue->destroy_flow_action(sh->pop_vlan_action); 1204b41e47daSMoti Haimovsky sh->pop_vlan_action = NULL; 1205b41e47daSMoti Haimovsky } 120679e35d0dSViacheslav Ovsiienko pthread_mutex_destroy(&sh->dv_mutex); 120754534725SMatan Azrad #endif /* HAVE_MLX5DV_DR */ 12081ef4cdefSMatan Azrad if (sh->tag_table) { 12091ef4cdefSMatan Azrad /* tags should be destroyed with flow before. */ 12101ef4cdefSMatan Azrad mlx5_hlist_destroy(sh->tag_table, NULL, NULL); 12111ef4cdefSMatan Azrad sh->tag_table = NULL; 12121ef4cdefSMatan Azrad } 121354534725SMatan Azrad mlx5_free_table_hash_list(priv); 1214b2177648SViacheslav Ovsiienko } 1215b2177648SViacheslav Ovsiienko 1216b2177648SViacheslav Ovsiienko /** 12177be600c8SYongseok Koh * Initialize shared data between primary and secondary process. 12187be600c8SYongseok Koh * 12197be600c8SYongseok Koh * A memzone is reserved by primary process and secondary processes attach to 12207be600c8SYongseok Koh * the memzone. 12217be600c8SYongseok Koh * 12227be600c8SYongseok Koh * @return 12237be600c8SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 1224974f1e7eSYongseok Koh */ 12257be600c8SYongseok Koh static int 12267be600c8SYongseok Koh mlx5_init_shared_data(void) 1227974f1e7eSYongseok Koh { 1228974f1e7eSYongseok Koh const struct rte_memzone *mz; 12297be600c8SYongseok Koh int ret = 0; 1230974f1e7eSYongseok Koh 1231974f1e7eSYongseok Koh rte_spinlock_lock(&mlx5_shared_data_lock); 1232974f1e7eSYongseok Koh if (mlx5_shared_data == NULL) { 1233974f1e7eSYongseok Koh if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 1234974f1e7eSYongseok Koh /* Allocate shared memory. */ 1235974f1e7eSYongseok Koh mz = rte_memzone_reserve(MZ_MLX5_PMD_SHARED_DATA, 1236974f1e7eSYongseok Koh sizeof(*mlx5_shared_data), 1237974f1e7eSYongseok Koh SOCKET_ID_ANY, 0); 12387be600c8SYongseok Koh if (mz == NULL) { 12397be600c8SYongseok Koh DRV_LOG(ERR, 124006fa6988SDekel Peled "Cannot allocate mlx5 shared data"); 12417be600c8SYongseok Koh ret = -rte_errno; 12427be600c8SYongseok Koh goto error; 12437be600c8SYongseok Koh } 12447be600c8SYongseok Koh mlx5_shared_data = mz->addr; 12457be600c8SYongseok Koh memset(mlx5_shared_data, 0, sizeof(*mlx5_shared_data)); 12467be600c8SYongseok Koh rte_spinlock_init(&mlx5_shared_data->lock); 1247974f1e7eSYongseok Koh } else { 1248974f1e7eSYongseok Koh /* Lookup allocated shared memory. */ 1249974f1e7eSYongseok Koh mz = rte_memzone_lookup(MZ_MLX5_PMD_SHARED_DATA); 12507be600c8SYongseok Koh if (mz == NULL) { 12517be600c8SYongseok Koh DRV_LOG(ERR, 125206fa6988SDekel Peled "Cannot attach mlx5 shared data"); 12537be600c8SYongseok Koh ret = -rte_errno; 12547be600c8SYongseok Koh goto error; 1255974f1e7eSYongseok Koh } 1256974f1e7eSYongseok Koh mlx5_shared_data = mz->addr; 12577be600c8SYongseok Koh memset(&mlx5_local_data, 0, sizeof(mlx5_local_data)); 12583ebe6580SYongseok Koh } 1259974f1e7eSYongseok Koh } 12607be600c8SYongseok Koh error: 12617be600c8SYongseok Koh rte_spinlock_unlock(&mlx5_shared_data_lock); 12627be600c8SYongseok Koh return ret; 12637be600c8SYongseok Koh } 12647be600c8SYongseok Koh 12657be600c8SYongseok Koh /** 12664d803a72SOlga Shern * Retrieve integer value from environment variable. 12674d803a72SOlga Shern * 12684d803a72SOlga Shern * @param[in] name 12694d803a72SOlga Shern * Environment variable name. 12704d803a72SOlga Shern * 12714d803a72SOlga Shern * @return 12724d803a72SOlga Shern * Integer value, 0 if the variable is not set. 12734d803a72SOlga Shern */ 12744d803a72SOlga Shern int 12754d803a72SOlga Shern mlx5_getenv_int(const char *name) 12764d803a72SOlga Shern { 12774d803a72SOlga Shern const char *val = getenv(name); 12784d803a72SOlga Shern 12794d803a72SOlga Shern if (val == NULL) 12804d803a72SOlga Shern return 0; 12814d803a72SOlga Shern return atoi(val); 12824d803a72SOlga Shern } 12834d803a72SOlga Shern 12844d803a72SOlga Shern /** 12851e3a39f7SXueming Li * Verbs callback to allocate a memory. This function should allocate the space 12861e3a39f7SXueming Li * according to the size provided residing inside a huge page. 12871e3a39f7SXueming Li * Please note that all allocation must respect the alignment from libmlx5 12881e3a39f7SXueming Li * (i.e. currently sysconf(_SC_PAGESIZE)). 12891e3a39f7SXueming Li * 12901e3a39f7SXueming Li * @param[in] size 12911e3a39f7SXueming Li * The size in bytes of the memory to allocate. 12921e3a39f7SXueming Li * @param[in] data 12931e3a39f7SXueming Li * A pointer to the callback data. 12941e3a39f7SXueming Li * 12951e3a39f7SXueming Li * @return 1296a6d83b6aSNélio Laranjeiro * Allocated buffer, NULL otherwise and rte_errno is set. 12971e3a39f7SXueming Li */ 12981e3a39f7SXueming Li static void * 12991e3a39f7SXueming Li mlx5_alloc_verbs_buf(size_t size, void *data) 13001e3a39f7SXueming Li { 1301dbeba4cfSThomas Monjalon struct mlx5_priv *priv = data; 13021e3a39f7SXueming Li void *ret; 13031e3a39f7SXueming Li size_t alignment = sysconf(_SC_PAGESIZE); 1304d10b09dbSOlivier Matz unsigned int socket = SOCKET_ID_ANY; 13051e3a39f7SXueming Li 1306d10b09dbSOlivier Matz if (priv->verbs_alloc_ctx.type == MLX5_VERBS_ALLOC_TYPE_TX_QUEUE) { 1307d10b09dbSOlivier Matz const struct mlx5_txq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 1308d10b09dbSOlivier Matz 1309d10b09dbSOlivier Matz socket = ctrl->socket; 1310d10b09dbSOlivier Matz } else if (priv->verbs_alloc_ctx.type == 1311d10b09dbSOlivier Matz MLX5_VERBS_ALLOC_TYPE_RX_QUEUE) { 1312d10b09dbSOlivier Matz const struct mlx5_rxq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 1313d10b09dbSOlivier Matz 1314d10b09dbSOlivier Matz socket = ctrl->socket; 1315d10b09dbSOlivier Matz } 13168e46d4e1SAlexander Kozyrev MLX5_ASSERT(data != NULL); 1317d10b09dbSOlivier Matz ret = rte_malloc_socket(__func__, size, alignment, socket); 1318a6d83b6aSNélio Laranjeiro if (!ret && size) 1319a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 13201e3a39f7SXueming Li return ret; 13211e3a39f7SXueming Li } 13221e3a39f7SXueming Li 13231e3a39f7SXueming Li /** 13241e3a39f7SXueming Li * Verbs callback to free a memory. 13251e3a39f7SXueming Li * 13261e3a39f7SXueming Li * @param[in] ptr 13271e3a39f7SXueming Li * A pointer to the memory to free. 13281e3a39f7SXueming Li * @param[in] data 13291e3a39f7SXueming Li * A pointer to the callback data. 13301e3a39f7SXueming Li */ 13311e3a39f7SXueming Li static void 13321e3a39f7SXueming Li mlx5_free_verbs_buf(void *ptr, void *data __rte_unused) 13331e3a39f7SXueming Li { 13348e46d4e1SAlexander Kozyrev MLX5_ASSERT(data != NULL); 13351e3a39f7SXueming Li rte_free(ptr); 13361e3a39f7SXueming Li } 13371e3a39f7SXueming Li 13381e3a39f7SXueming Li /** 1339c9ba7523SRaslan Darawsheh * DPDK callback to add udp tunnel port 1340c9ba7523SRaslan Darawsheh * 1341c9ba7523SRaslan Darawsheh * @param[in] dev 1342c9ba7523SRaslan Darawsheh * A pointer to eth_dev 1343c9ba7523SRaslan Darawsheh * @param[in] udp_tunnel 1344c9ba7523SRaslan Darawsheh * A pointer to udp tunnel 1345c9ba7523SRaslan Darawsheh * 1346c9ba7523SRaslan Darawsheh * @return 1347c9ba7523SRaslan Darawsheh * 0 on valid udp ports and tunnels, -ENOTSUP otherwise. 1348c9ba7523SRaslan Darawsheh */ 1349c9ba7523SRaslan Darawsheh int 1350c9ba7523SRaslan Darawsheh mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev __rte_unused, 1351c9ba7523SRaslan Darawsheh struct rte_eth_udp_tunnel *udp_tunnel) 1352c9ba7523SRaslan Darawsheh { 13538e46d4e1SAlexander Kozyrev MLX5_ASSERT(udp_tunnel != NULL); 1354c9ba7523SRaslan Darawsheh if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN && 1355c9ba7523SRaslan Darawsheh udp_tunnel->udp_port == 4789) 1356c9ba7523SRaslan Darawsheh return 0; 1357c9ba7523SRaslan Darawsheh if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN_GPE && 1358c9ba7523SRaslan Darawsheh udp_tunnel->udp_port == 4790) 1359c9ba7523SRaslan Darawsheh return 0; 1360c9ba7523SRaslan Darawsheh return -ENOTSUP; 1361c9ba7523SRaslan Darawsheh } 1362c9ba7523SRaslan Darawsheh 1363c9ba7523SRaslan Darawsheh /** 1364120dc4a7SYongseok Koh * Initialize process private data structure. 1365120dc4a7SYongseok Koh * 1366120dc4a7SYongseok Koh * @param dev 1367120dc4a7SYongseok Koh * Pointer to Ethernet device structure. 1368120dc4a7SYongseok Koh * 1369120dc4a7SYongseok Koh * @return 1370120dc4a7SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 1371120dc4a7SYongseok Koh */ 1372120dc4a7SYongseok Koh int 1373120dc4a7SYongseok Koh mlx5_proc_priv_init(struct rte_eth_dev *dev) 1374120dc4a7SYongseok Koh { 1375120dc4a7SYongseok Koh struct mlx5_priv *priv = dev->data->dev_private; 1376120dc4a7SYongseok Koh struct mlx5_proc_priv *ppriv; 1377120dc4a7SYongseok Koh size_t ppriv_size; 1378120dc4a7SYongseok Koh 1379120dc4a7SYongseok Koh /* 1380120dc4a7SYongseok Koh * UAR register table follows the process private structure. BlueFlame 1381120dc4a7SYongseok Koh * registers for Tx queues are stored in the table. 1382120dc4a7SYongseok Koh */ 1383120dc4a7SYongseok Koh ppriv_size = 1384120dc4a7SYongseok Koh sizeof(struct mlx5_proc_priv) + priv->txqs_n * sizeof(void *); 1385120dc4a7SYongseok Koh ppriv = rte_malloc_socket("mlx5_proc_priv", ppriv_size, 1386120dc4a7SYongseok Koh RTE_CACHE_LINE_SIZE, dev->device->numa_node); 1387120dc4a7SYongseok Koh if (!ppriv) { 1388120dc4a7SYongseok Koh rte_errno = ENOMEM; 1389120dc4a7SYongseok Koh return -rte_errno; 1390120dc4a7SYongseok Koh } 1391120dc4a7SYongseok Koh ppriv->uar_table_sz = ppriv_size; 1392120dc4a7SYongseok Koh dev->process_private = ppriv; 1393120dc4a7SYongseok Koh return 0; 1394120dc4a7SYongseok Koh } 1395120dc4a7SYongseok Koh 1396120dc4a7SYongseok Koh /** 1397120dc4a7SYongseok Koh * Un-initialize process private data structure. 1398120dc4a7SYongseok Koh * 1399120dc4a7SYongseok Koh * @param dev 1400120dc4a7SYongseok Koh * Pointer to Ethernet device structure. 1401120dc4a7SYongseok Koh */ 1402120dc4a7SYongseok Koh static void 1403120dc4a7SYongseok Koh mlx5_proc_priv_uninit(struct rte_eth_dev *dev) 1404120dc4a7SYongseok Koh { 1405120dc4a7SYongseok Koh if (!dev->process_private) 1406120dc4a7SYongseok Koh return; 1407120dc4a7SYongseok Koh rte_free(dev->process_private); 1408120dc4a7SYongseok Koh dev->process_private = NULL; 1409120dc4a7SYongseok Koh } 1410120dc4a7SYongseok Koh 1411120dc4a7SYongseok Koh /** 1412771fa900SAdrien Mazarguil * DPDK callback to close the device. 1413771fa900SAdrien Mazarguil * 1414771fa900SAdrien Mazarguil * Destroy all queues and objects, free memory. 1415771fa900SAdrien Mazarguil * 1416771fa900SAdrien Mazarguil * @param dev 1417771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 1418771fa900SAdrien Mazarguil */ 1419771fa900SAdrien Mazarguil static void 1420771fa900SAdrien Mazarguil mlx5_dev_close(struct rte_eth_dev *dev) 1421771fa900SAdrien Mazarguil { 1422dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 14232e22920bSAdrien Mazarguil unsigned int i; 14246af6b973SNélio Laranjeiro int ret; 1425771fa900SAdrien Mazarguil 1426a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u closing device \"%s\"", 14270f99970bSNélio Laranjeiro dev->data->port_id, 1428f048f3d4SViacheslav Ovsiienko ((priv->sh->ctx != NULL) ? priv->sh->ctx->device->name : "")); 1429ecc1c29dSAdrien Mazarguil /* In case mlx5_dev_stop() has not been called. */ 1430af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(dev); 143123242063SMatan Azrad mlx5_dev_interrupt_handler_devx_uninstall(dev); 14328db7e3b6SBing Zhao /* 14338db7e3b6SBing Zhao * If default mreg copy action is removed at the stop stage, 14348db7e3b6SBing Zhao * the search will return none and nothing will be done anymore. 14358db7e3b6SBing Zhao */ 14368db7e3b6SBing Zhao mlx5_flow_stop_default(dev); 1437af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 14388db7e3b6SBing Zhao /* 14398db7e3b6SBing Zhao * If all the flows are already flushed in the device stop stage, 14408db7e3b6SBing Zhao * then this will return directly without any action. 14418db7e3b6SBing Zhao */ 14428db7e3b6SBing Zhao mlx5_flow_list_flush(dev, &priv->flows, true); 144302e76468SSuanming Mou mlx5_flow_meter_flush(dev, NULL); 1444e7bfa359SBing Zhao /* Free the intermediate buffers for flow creation. */ 1445e7bfa359SBing Zhao mlx5_flow_free_intermediate(dev); 14462e22920bSAdrien Mazarguil /* Prevent crashes when queues are still in use. */ 14472e22920bSAdrien Mazarguil dev->rx_pkt_burst = removed_rx_burst; 14482e22920bSAdrien Mazarguil dev->tx_pkt_burst = removed_tx_burst; 14492aac5b5dSYongseok Koh rte_wmb(); 14502aac5b5dSYongseok Koh /* Disable datapath on secondary process. */ 14512aac5b5dSYongseok Koh mlx5_mp_req_stop_rxtx(dev); 14522e22920bSAdrien Mazarguil if (priv->rxqs != NULL) { 14532e22920bSAdrien Mazarguil /* XXX race condition if mlx5_rx_burst() is still running. */ 14542e22920bSAdrien Mazarguil usleep(1000); 1455a1366b1aSNélio Laranjeiro for (i = 0; (i != priv->rxqs_n); ++i) 1456af4f09f2SNélio Laranjeiro mlx5_rxq_release(dev, i); 14572e22920bSAdrien Mazarguil priv->rxqs_n = 0; 14582e22920bSAdrien Mazarguil priv->rxqs = NULL; 14592e22920bSAdrien Mazarguil } 14602e22920bSAdrien Mazarguil if (priv->txqs != NULL) { 14612e22920bSAdrien Mazarguil /* XXX race condition if mlx5_tx_burst() is still running. */ 14622e22920bSAdrien Mazarguil usleep(1000); 14636e78005aSNélio Laranjeiro for (i = 0; (i != priv->txqs_n); ++i) 1464af4f09f2SNélio Laranjeiro mlx5_txq_release(dev, i); 14652e22920bSAdrien Mazarguil priv->txqs_n = 0; 14662e22920bSAdrien Mazarguil priv->txqs = NULL; 14672e22920bSAdrien Mazarguil } 1468120dc4a7SYongseok Koh mlx5_proc_priv_uninit(dev); 1469dd3c774fSViacheslav Ovsiienko if (priv->mreg_cp_tbl) 1470dd3c774fSViacheslav Ovsiienko mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL); 14717d6bf6b8SYongseok Koh mlx5_mprq_free_mp(dev); 1472b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(priv); 147329c1d8bbSNélio Laranjeiro if (priv->rss_conf.rss_key != NULL) 147429c1d8bbSNélio Laranjeiro rte_free(priv->rss_conf.rss_key); 1475634efbc2SNelio Laranjeiro if (priv->reta_idx != NULL) 1476634efbc2SNelio Laranjeiro rte_free(priv->reta_idx); 1477ccdcba53SNélio Laranjeiro if (priv->config.vf) 1478f22442cbSMatan Azrad mlx5_nl_mac_addr_flush(priv->nl_socket_route, mlx5_ifindex(dev), 1479f22442cbSMatan Azrad dev->data->mac_addrs, 1480f22442cbSMatan Azrad MLX5_MAX_MAC_ADDRESSES, priv->mac_own); 148126c08b97SAdrien Mazarguil if (priv->nl_socket_route >= 0) 148226c08b97SAdrien Mazarguil close(priv->nl_socket_route); 148326c08b97SAdrien Mazarguil if (priv->nl_socket_rdma >= 0) 148426c08b97SAdrien Mazarguil close(priv->nl_socket_rdma); 1485dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context) 1486dfedf3e3SViacheslav Ovsiienko mlx5_vlan_vmwa_exit(priv->vmwa_context); 148723820a79SDekel Peled ret = mlx5_hrxq_verify(dev); 1488f5479b68SNélio Laranjeiro if (ret) 1489a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some hash Rx queue still remain", 14900f99970bSNélio Laranjeiro dev->data->port_id); 149115c80a12SDekel Peled ret = mlx5_ind_table_obj_verify(dev); 14924c7a0f5fSNélio Laranjeiro if (ret) 1493a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some indirection table still remain", 14940f99970bSNélio Laranjeiro dev->data->port_id); 149593403560SDekel Peled ret = mlx5_rxq_obj_verify(dev); 149609cb5b58SNélio Laranjeiro if (ret) 149793403560SDekel Peled DRV_LOG(WARNING, "port %u some Rx queue objects still remain", 14980f99970bSNélio Laranjeiro dev->data->port_id); 1499af4f09f2SNélio Laranjeiro ret = mlx5_rxq_verify(dev); 1500a1366b1aSNélio Laranjeiro if (ret) 1501a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Rx queues still remain", 15020f99970bSNélio Laranjeiro dev->data->port_id); 1503894c4a8eSOri Kam ret = mlx5_txq_obj_verify(dev); 1504faf2667fSNélio Laranjeiro if (ret) 1505a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Verbs Tx queue still remain", 15060f99970bSNélio Laranjeiro dev->data->port_id); 1507af4f09f2SNélio Laranjeiro ret = mlx5_txq_verify(dev); 15086e78005aSNélio Laranjeiro if (ret) 1509a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some Tx queues still remain", 15100f99970bSNélio Laranjeiro dev->data->port_id); 1511af4f09f2SNélio Laranjeiro ret = mlx5_flow_verify(dev); 15126af6b973SNélio Laranjeiro if (ret) 1513a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u some flows still remain", 1514a170a30dSNélio Laranjeiro dev->data->port_id); 1515772dc0ebSSuanming Mou if (priv->sh) { 1516772dc0ebSSuanming Mou /* 1517772dc0ebSSuanming Mou * Free the shared context in last turn, because the cleanup 1518772dc0ebSSuanming Mou * routines above may use some shared fields, like 1519772dc0ebSSuanming Mou * mlx5_nl_mac_addr_flush() uses ibdev_path for retrieveing 1520772dc0ebSSuanming Mou * ifindex if Netlink fails. 1521772dc0ebSSuanming Mou */ 1522772dc0ebSSuanming Mou mlx5_free_shared_ibctx(priv->sh); 1523772dc0ebSSuanming Mou priv->sh = NULL; 1524772dc0ebSSuanming Mou } 15252b730263SAdrien Mazarguil if (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 15262b730263SAdrien Mazarguil unsigned int c = 0; 1527d874a4eeSThomas Monjalon uint16_t port_id; 15282b730263SAdrien Mazarguil 1529fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 1530dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 1531d874a4eeSThomas Monjalon rte_eth_devices[port_id].data->dev_private; 15322b730263SAdrien Mazarguil 15332b730263SAdrien Mazarguil if (!opriv || 15342b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id || 1535d874a4eeSThomas Monjalon &rte_eth_devices[port_id] == dev) 15362b730263SAdrien Mazarguil continue; 15372b730263SAdrien Mazarguil ++c; 1538f7e95215SViacheslav Ovsiienko break; 15392b730263SAdrien Mazarguil } 15402b730263SAdrien Mazarguil if (!c) 15412b730263SAdrien Mazarguil claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 15422b730263SAdrien Mazarguil } 1543771fa900SAdrien Mazarguil memset(priv, 0, sizeof(*priv)); 15442b730263SAdrien Mazarguil priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 154542603bbdSOphir Munk /* 154642603bbdSOphir Munk * Reset mac_addrs to NULL such that it is not freed as part of 154742603bbdSOphir Munk * rte_eth_dev_release_port(). mac_addrs is part of dev_private so 154842603bbdSOphir Munk * it is freed when dev_private is freed. 154942603bbdSOphir Munk */ 155042603bbdSOphir Munk dev->data->mac_addrs = NULL; 1551771fa900SAdrien Mazarguil } 1552771fa900SAdrien Mazarguil 15530887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops = { 1554e60fbd5bSAdrien Mazarguil .dev_configure = mlx5_dev_configure, 1555e60fbd5bSAdrien Mazarguil .dev_start = mlx5_dev_start, 1556e60fbd5bSAdrien Mazarguil .dev_stop = mlx5_dev_stop, 155762072098SOr Ami .dev_set_link_down = mlx5_set_link_down, 155862072098SOr Ami .dev_set_link_up = mlx5_set_link_up, 1559771fa900SAdrien Mazarguil .dev_close = mlx5_dev_close, 15601bdbe1afSAdrien Mazarguil .promiscuous_enable = mlx5_promiscuous_enable, 15611bdbe1afSAdrien Mazarguil .promiscuous_disable = mlx5_promiscuous_disable, 15621bdbe1afSAdrien Mazarguil .allmulticast_enable = mlx5_allmulticast_enable, 15631bdbe1afSAdrien Mazarguil .allmulticast_disable = mlx5_allmulticast_disable, 1564cb8faed7SAdrien Mazarguil .link_update = mlx5_link_update, 156587011737SAdrien Mazarguil .stats_get = mlx5_stats_get, 156687011737SAdrien Mazarguil .stats_reset = mlx5_stats_reset, 1567a4193ae3SShahaf Shuler .xstats_get = mlx5_xstats_get, 1568a4193ae3SShahaf Shuler .xstats_reset = mlx5_xstats_reset, 1569a4193ae3SShahaf Shuler .xstats_get_names = mlx5_xstats_get_names, 1570714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 1571e60fbd5bSAdrien Mazarguil .dev_infos_get = mlx5_dev_infos_get, 1572e571ad55STom Barbette .read_clock = mlx5_read_clock, 157378a38edfSJianfeng Tan .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 1574e9086978SAdrien Mazarguil .vlan_filter_set = mlx5_vlan_filter_set, 15752e22920bSAdrien Mazarguil .rx_queue_setup = mlx5_rx_queue_setup, 1576e79c9be9SOri Kam .rx_hairpin_queue_setup = mlx5_rx_hairpin_queue_setup, 15772e22920bSAdrien Mazarguil .tx_queue_setup = mlx5_tx_queue_setup, 1578ae18a1aeSOri Kam .tx_hairpin_queue_setup = mlx5_tx_hairpin_queue_setup, 15792e22920bSAdrien Mazarguil .rx_queue_release = mlx5_rx_queue_release, 15802e22920bSAdrien Mazarguil .tx_queue_release = mlx5_tx_queue_release, 158102d75430SAdrien Mazarguil .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 158202d75430SAdrien Mazarguil .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 15833318aef7SAdrien Mazarguil .mac_addr_remove = mlx5_mac_addr_remove, 15843318aef7SAdrien Mazarguil .mac_addr_add = mlx5_mac_addr_add, 158586977fccSDavid Marchand .mac_addr_set = mlx5_mac_addr_set, 1586e0586a8dSNélio Laranjeiro .set_mc_addr_list = mlx5_set_mc_addr_list, 1587cf37ca95SAdrien Mazarguil .mtu_set = mlx5_dev_set_mtu, 1588f3db9489SYaacov Hazan .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 1589f3db9489SYaacov Hazan .vlan_offload_set = mlx5_vlan_offload_set, 1590634efbc2SNelio Laranjeiro .reta_update = mlx5_dev_rss_reta_update, 1591634efbc2SNelio Laranjeiro .reta_query = mlx5_dev_rss_reta_query, 15922f97422eSNelio Laranjeiro .rss_hash_update = mlx5_rss_hash_update, 15932f97422eSNelio Laranjeiro .rss_hash_conf_get = mlx5_rss_hash_conf_get, 159476f5c99eSYaacov Hazan .filter_ctrl = mlx5_dev_filter_ctrl, 15958788fec1SOlivier Matz .rx_descriptor_status = mlx5_rx_descriptor_status, 15968788fec1SOlivier Matz .tx_descriptor_status = mlx5_tx_descriptor_status, 159726f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 159826f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 159926f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 160026f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 160126f04883STom Barbette .rx_queue_count = mlx5_rx_queue_count, 16023c7d44afSShahaf Shuler .rx_queue_intr_enable = mlx5_rx_intr_enable, 16033c7d44afSShahaf Shuler .rx_queue_intr_disable = mlx5_rx_intr_disable, 1604d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 1605c9ba7523SRaslan Darawsheh .udp_tunnel_port_add = mlx5_udp_tunnel_port_add, 16068a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 16078a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 1608b6b3bf86SOri Kam .hairpin_cap_get = mlx5_hairpin_cap_get, 1609d740eb50SSuanming Mou .mtr_ops_get = mlx5_flow_meter_ops_get, 1610771fa900SAdrien Mazarguil }; 1611771fa900SAdrien Mazarguil 1612714bf46eSThomas Monjalon /* Available operations from secondary process. */ 161387ec44ceSXueming Li static const struct eth_dev_ops mlx5_dev_sec_ops = { 161487ec44ceSXueming Li .stats_get = mlx5_stats_get, 161587ec44ceSXueming Li .stats_reset = mlx5_stats_reset, 161687ec44ceSXueming Li .xstats_get = mlx5_xstats_get, 161787ec44ceSXueming Li .xstats_reset = mlx5_xstats_reset, 161887ec44ceSXueming Li .xstats_get_names = mlx5_xstats_get_names, 1619714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 162087ec44ceSXueming Li .dev_infos_get = mlx5_dev_infos_get, 162187ec44ceSXueming Li .rx_descriptor_status = mlx5_rx_descriptor_status, 162287ec44ceSXueming Li .tx_descriptor_status = mlx5_tx_descriptor_status, 162326f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 162426f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 162526f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 162626f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 16278a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 16288a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 162987ec44ceSXueming Li }; 163087ec44ceSXueming Li 1631714bf46eSThomas Monjalon /* Available operations in flow isolated mode. */ 16320887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops_isolate = { 16330887aa7fSNélio Laranjeiro .dev_configure = mlx5_dev_configure, 16340887aa7fSNélio Laranjeiro .dev_start = mlx5_dev_start, 16350887aa7fSNélio Laranjeiro .dev_stop = mlx5_dev_stop, 16360887aa7fSNélio Laranjeiro .dev_set_link_down = mlx5_set_link_down, 16370887aa7fSNélio Laranjeiro .dev_set_link_up = mlx5_set_link_up, 16380887aa7fSNélio Laranjeiro .dev_close = mlx5_dev_close, 163924b068adSYongseok Koh .promiscuous_enable = mlx5_promiscuous_enable, 164024b068adSYongseok Koh .promiscuous_disable = mlx5_promiscuous_disable, 16412547ee74SYongseok Koh .allmulticast_enable = mlx5_allmulticast_enable, 16422547ee74SYongseok Koh .allmulticast_disable = mlx5_allmulticast_disable, 16430887aa7fSNélio Laranjeiro .link_update = mlx5_link_update, 16440887aa7fSNélio Laranjeiro .stats_get = mlx5_stats_get, 16450887aa7fSNélio Laranjeiro .stats_reset = mlx5_stats_reset, 16460887aa7fSNélio Laranjeiro .xstats_get = mlx5_xstats_get, 16470887aa7fSNélio Laranjeiro .xstats_reset = mlx5_xstats_reset, 16480887aa7fSNélio Laranjeiro .xstats_get_names = mlx5_xstats_get_names, 1649714bf46eSThomas Monjalon .fw_version_get = mlx5_fw_version_get, 16500887aa7fSNélio Laranjeiro .dev_infos_get = mlx5_dev_infos_get, 16510887aa7fSNélio Laranjeiro .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 16520887aa7fSNélio Laranjeiro .vlan_filter_set = mlx5_vlan_filter_set, 16530887aa7fSNélio Laranjeiro .rx_queue_setup = mlx5_rx_queue_setup, 1654e79c9be9SOri Kam .rx_hairpin_queue_setup = mlx5_rx_hairpin_queue_setup, 16550887aa7fSNélio Laranjeiro .tx_queue_setup = mlx5_tx_queue_setup, 1656ae18a1aeSOri Kam .tx_hairpin_queue_setup = mlx5_tx_hairpin_queue_setup, 16570887aa7fSNélio Laranjeiro .rx_queue_release = mlx5_rx_queue_release, 16580887aa7fSNélio Laranjeiro .tx_queue_release = mlx5_tx_queue_release, 16590887aa7fSNélio Laranjeiro .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 16600887aa7fSNélio Laranjeiro .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 16610887aa7fSNélio Laranjeiro .mac_addr_remove = mlx5_mac_addr_remove, 16620887aa7fSNélio Laranjeiro .mac_addr_add = mlx5_mac_addr_add, 16630887aa7fSNélio Laranjeiro .mac_addr_set = mlx5_mac_addr_set, 1664e0586a8dSNélio Laranjeiro .set_mc_addr_list = mlx5_set_mc_addr_list, 16650887aa7fSNélio Laranjeiro .mtu_set = mlx5_dev_set_mtu, 16660887aa7fSNélio Laranjeiro .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 16670887aa7fSNélio Laranjeiro .vlan_offload_set = mlx5_vlan_offload_set, 16680887aa7fSNélio Laranjeiro .filter_ctrl = mlx5_dev_filter_ctrl, 16690887aa7fSNélio Laranjeiro .rx_descriptor_status = mlx5_rx_descriptor_status, 16700887aa7fSNélio Laranjeiro .tx_descriptor_status = mlx5_tx_descriptor_status, 167126f1bae8SAlexander Kozyrev .rxq_info_get = mlx5_rxq_info_get, 167226f1bae8SAlexander Kozyrev .txq_info_get = mlx5_txq_info_get, 167326f1bae8SAlexander Kozyrev .rx_burst_mode_get = mlx5_rx_burst_mode_get, 167426f1bae8SAlexander Kozyrev .tx_burst_mode_get = mlx5_tx_burst_mode_get, 16750887aa7fSNélio Laranjeiro .rx_queue_intr_enable = mlx5_rx_intr_enable, 16760887aa7fSNélio Laranjeiro .rx_queue_intr_disable = mlx5_rx_intr_disable, 1677d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 16788a6a09f8SDekel Peled .get_module_info = mlx5_get_module_info, 16798a6a09f8SDekel Peled .get_module_eeprom = mlx5_get_module_eeprom, 1680b6b3bf86SOri Kam .hairpin_cap_get = mlx5_hairpin_cap_get, 1681d740eb50SSuanming Mou .mtr_ops_get = mlx5_flow_meter_ops_get, 16820887aa7fSNélio Laranjeiro }; 16830887aa7fSNélio Laranjeiro 1684e72dd09bSNélio Laranjeiro /** 1685e72dd09bSNélio Laranjeiro * Verify and store value for device argument. 1686e72dd09bSNélio Laranjeiro * 1687e72dd09bSNélio Laranjeiro * @param[in] key 1688e72dd09bSNélio Laranjeiro * Key argument to verify. 1689e72dd09bSNélio Laranjeiro * @param[in] val 1690e72dd09bSNélio Laranjeiro * Value associated with key. 1691e72dd09bSNélio Laranjeiro * @param opaque 1692e72dd09bSNélio Laranjeiro * User data. 1693e72dd09bSNélio Laranjeiro * 1694e72dd09bSNélio Laranjeiro * @return 1695a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1696e72dd09bSNélio Laranjeiro */ 1697e72dd09bSNélio Laranjeiro static int 1698e72dd09bSNélio Laranjeiro mlx5_args_check(const char *key, const char *val, void *opaque) 1699e72dd09bSNélio Laranjeiro { 17007fe24446SShahaf Shuler struct mlx5_dev_config *config = opaque; 170199c12dccSNélio Laranjeiro unsigned long tmp; 1702e72dd09bSNélio Laranjeiro 17036de569f5SAdrien Mazarguil /* No-op, port representors are processed in mlx5_dev_spawn(). */ 17046de569f5SAdrien Mazarguil if (!strcmp(MLX5_REPRESENTOR, key)) 17056de569f5SAdrien Mazarguil return 0; 170699c12dccSNélio Laranjeiro errno = 0; 170799c12dccSNélio Laranjeiro tmp = strtoul(val, NULL, 0); 170899c12dccSNélio Laranjeiro if (errno) { 1709a6d83b6aSNélio Laranjeiro rte_errno = errno; 1710a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "%s: \"%s\" is not a valid integer", key, val); 1711a6d83b6aSNélio Laranjeiro return -rte_errno; 171299c12dccSNélio Laranjeiro } 171399c12dccSNélio Laranjeiro if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) { 17147fe24446SShahaf Shuler config->cqe_comp = !!tmp; 1715bc91e8dbSYongseok Koh } else if (strcmp(MLX5_RXQ_CQE_PAD_EN, key) == 0) { 1716bc91e8dbSYongseok Koh config->cqe_pad = !!tmp; 171778c7a16dSYongseok Koh } else if (strcmp(MLX5_RXQ_PKT_PAD_EN, key) == 0) { 171878c7a16dSYongseok Koh config->hw_padding = !!tmp; 17197d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_EN, key) == 0) { 17207d6bf6b8SYongseok Koh config->mprq.enabled = !!tmp; 17217d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_NUM, key) == 0) { 17227d6bf6b8SYongseok Koh config->mprq.stride_num_n = tmp; 1723ecb16045SAlexander Kozyrev } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_SIZE, key) == 0) { 1724ecb16045SAlexander Kozyrev config->mprq.stride_size_n = tmp; 17257d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RX_MPRQ_MAX_MEMCPY_LEN, key) == 0) { 17267d6bf6b8SYongseok Koh config->mprq.max_memcpy_len = tmp; 17277d6bf6b8SYongseok Koh } else if (strcmp(MLX5_RXQS_MIN_MPRQ, key) == 0) { 17287d6bf6b8SYongseok Koh config->mprq.min_rxqs_num = tmp; 17292a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { 1730505f1fe4SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter," 1731505f1fe4SViacheslav Ovsiienko " converted to txq_inline_max", key); 1732505f1fe4SViacheslav Ovsiienko config->txq_inline_max = tmp; 1733505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MAX, key) == 0) { 1734505f1fe4SViacheslav Ovsiienko config->txq_inline_max = tmp; 1735505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MIN, key) == 0) { 1736505f1fe4SViacheslav Ovsiienko config->txq_inline_min = tmp; 1737505f1fe4SViacheslav Ovsiienko } else if (strcmp(MLX5_TXQ_INLINE_MPW, key) == 0) { 1738505f1fe4SViacheslav Ovsiienko config->txq_inline_mpw = tmp; 17392a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { 17407fe24446SShahaf Shuler config->txqs_inline = tmp; 174109d8b416SYongseok Koh } else if (strcmp(MLX5_TXQS_MAX_VEC, key) == 0) { 1742a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 1743230189d9SNélio Laranjeiro } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { 1744f9de8718SShahaf Shuler config->mps = !!tmp; 17458409a285SViacheslav Ovsiienko } else if (strcmp(MLX5_TX_DB_NC, key) == 0) { 1746f078ceb6SViacheslav Ovsiienko if (tmp != MLX5_TXDB_CACHED && 1747f078ceb6SViacheslav Ovsiienko tmp != MLX5_TXDB_NCACHED && 1748f078ceb6SViacheslav Ovsiienko tmp != MLX5_TXDB_HEURISTIC) { 1749f078ceb6SViacheslav Ovsiienko DRV_LOG(ERR, "invalid Tx doorbell " 1750f078ceb6SViacheslav Ovsiienko "mapping parameter"); 1751f078ceb6SViacheslav Ovsiienko rte_errno = EINVAL; 1752f078ceb6SViacheslav Ovsiienko return -rte_errno; 1753f078ceb6SViacheslav Ovsiienko } 1754f078ceb6SViacheslav Ovsiienko config->dbnc = tmp; 17556ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) { 1756a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 17576ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) { 1758505f1fe4SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter," 1759505f1fe4SViacheslav Ovsiienko " converted to txq_inline_mpw", key); 1760505f1fe4SViacheslav Ovsiienko config->txq_inline_mpw = tmp; 17615644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { 1762a6bd4911SViacheslav Ovsiienko DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 17635644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { 17647fe24446SShahaf Shuler config->rx_vec_en = !!tmp; 176578a54648SXueming Li } else if (strcmp(MLX5_L3_VXLAN_EN, key) == 0) { 176678a54648SXueming Li config->l3_vxlan_en = !!tmp; 1767db209cc3SNélio Laranjeiro } else if (strcmp(MLX5_VF_NL_EN, key) == 0) { 1768db209cc3SNélio Laranjeiro config->vf_nl_en = !!tmp; 1769e2b4925eSOri Kam } else if (strcmp(MLX5_DV_ESW_EN, key) == 0) { 1770e2b4925eSOri Kam config->dv_esw_en = !!tmp; 177151e72d38SOri Kam } else if (strcmp(MLX5_DV_FLOW_EN, key) == 0) { 177251e72d38SOri Kam config->dv_flow_en = !!tmp; 17732d241515SViacheslav Ovsiienko } else if (strcmp(MLX5_DV_XMETA_EN, key) == 0) { 17742d241515SViacheslav Ovsiienko if (tmp != MLX5_XMETA_MODE_LEGACY && 17752d241515SViacheslav Ovsiienko tmp != MLX5_XMETA_MODE_META16 && 17762d241515SViacheslav Ovsiienko tmp != MLX5_XMETA_MODE_META32) { 1777f078ceb6SViacheslav Ovsiienko DRV_LOG(ERR, "invalid extensive " 17782d241515SViacheslav Ovsiienko "metadata parameter"); 17792d241515SViacheslav Ovsiienko rte_errno = EINVAL; 17802d241515SViacheslav Ovsiienko return -rte_errno; 17812d241515SViacheslav Ovsiienko } 17822d241515SViacheslav Ovsiienko config->dv_xmeta_en = tmp; 1783dceb5029SYongseok Koh } else if (strcmp(MLX5_MR_EXT_MEMSEG_EN, key) == 0) { 1784dceb5029SYongseok Koh config->mr_ext_memseg_en = !!tmp; 1785066cfecdSMatan Azrad } else if (strcmp(MLX5_MAX_DUMP_FILES_NUM, key) == 0) { 1786066cfecdSMatan Azrad config->max_dump_files_num = tmp; 178721bb6c7eSDekel Peled } else if (strcmp(MLX5_LRO_TIMEOUT_USEC, key) == 0) { 178821bb6c7eSDekel Peled config->lro.timeout = tmp; 1789d768f324SMatan Azrad } else if (strcmp(MLX5_CLASS_ARG_NAME, key) == 0) { 1790d768f324SMatan Azrad DRV_LOG(DEBUG, "class argument is %s.", val); 17911ad9a3d0SBing Zhao } else if (strcmp(MLX5_HP_BUF_SIZE, key) == 0) { 17921ad9a3d0SBing Zhao config->log_hp_size = tmp; 179399c12dccSNélio Laranjeiro } else { 1794a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "%s: unknown parameter", key); 1795a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 1796a6d83b6aSNélio Laranjeiro return -rte_errno; 1797e72dd09bSNélio Laranjeiro } 179899c12dccSNélio Laranjeiro return 0; 179999c12dccSNélio Laranjeiro } 1800e72dd09bSNélio Laranjeiro 1801e72dd09bSNélio Laranjeiro /** 1802e72dd09bSNélio Laranjeiro * Parse device parameters. 1803e72dd09bSNélio Laranjeiro * 18047fe24446SShahaf Shuler * @param config 18057fe24446SShahaf Shuler * Pointer to device configuration structure. 1806e72dd09bSNélio Laranjeiro * @param devargs 1807e72dd09bSNélio Laranjeiro * Device arguments structure. 1808e72dd09bSNélio Laranjeiro * 1809e72dd09bSNélio Laranjeiro * @return 1810a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1811e72dd09bSNélio Laranjeiro */ 1812e72dd09bSNélio Laranjeiro static int 18137fe24446SShahaf Shuler mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) 1814e72dd09bSNélio Laranjeiro { 1815e72dd09bSNélio Laranjeiro const char **params = (const char *[]){ 181699c12dccSNélio Laranjeiro MLX5_RXQ_CQE_COMP_EN, 1817bc91e8dbSYongseok Koh MLX5_RXQ_CQE_PAD_EN, 181878c7a16dSYongseok Koh MLX5_RXQ_PKT_PAD_EN, 18197d6bf6b8SYongseok Koh MLX5_RX_MPRQ_EN, 18207d6bf6b8SYongseok Koh MLX5_RX_MPRQ_LOG_STRIDE_NUM, 1821ecb16045SAlexander Kozyrev MLX5_RX_MPRQ_LOG_STRIDE_SIZE, 18227d6bf6b8SYongseok Koh MLX5_RX_MPRQ_MAX_MEMCPY_LEN, 18237d6bf6b8SYongseok Koh MLX5_RXQS_MIN_MPRQ, 18242a66cf37SYaacov Hazan MLX5_TXQ_INLINE, 1825505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MIN, 1826505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MAX, 1827505f1fe4SViacheslav Ovsiienko MLX5_TXQ_INLINE_MPW, 18282a66cf37SYaacov Hazan MLX5_TXQS_MIN_INLINE, 182909d8b416SYongseok Koh MLX5_TXQS_MAX_VEC, 1830230189d9SNélio Laranjeiro MLX5_TXQ_MPW_EN, 18316ce84bd8SYongseok Koh MLX5_TXQ_MPW_HDR_DSEG_EN, 18326ce84bd8SYongseok Koh MLX5_TXQ_MAX_INLINE_LEN, 18338409a285SViacheslav Ovsiienko MLX5_TX_DB_NC, 18345644d5b9SNelio Laranjeiro MLX5_TX_VEC_EN, 18355644d5b9SNelio Laranjeiro MLX5_RX_VEC_EN, 183678a54648SXueming Li MLX5_L3_VXLAN_EN, 1837db209cc3SNélio Laranjeiro MLX5_VF_NL_EN, 1838e2b4925eSOri Kam MLX5_DV_ESW_EN, 183951e72d38SOri Kam MLX5_DV_FLOW_EN, 18402d241515SViacheslav Ovsiienko MLX5_DV_XMETA_EN, 1841dceb5029SYongseok Koh MLX5_MR_EXT_MEMSEG_EN, 18426de569f5SAdrien Mazarguil MLX5_REPRESENTOR, 1843066cfecdSMatan Azrad MLX5_MAX_DUMP_FILES_NUM, 184421bb6c7eSDekel Peled MLX5_LRO_TIMEOUT_USEC, 1845d768f324SMatan Azrad MLX5_CLASS_ARG_NAME, 18461ad9a3d0SBing Zhao MLX5_HP_BUF_SIZE, 1847e72dd09bSNélio Laranjeiro NULL, 1848e72dd09bSNélio Laranjeiro }; 1849e72dd09bSNélio Laranjeiro struct rte_kvargs *kvlist; 1850e72dd09bSNélio Laranjeiro int ret = 0; 1851e72dd09bSNélio Laranjeiro int i; 1852e72dd09bSNélio Laranjeiro 1853e72dd09bSNélio Laranjeiro if (devargs == NULL) 1854e72dd09bSNélio Laranjeiro return 0; 1855e72dd09bSNélio Laranjeiro /* Following UGLY cast is done to pass checkpatch. */ 1856e72dd09bSNélio Laranjeiro kvlist = rte_kvargs_parse(devargs->args, params); 185715b0ea00SMatan Azrad if (kvlist == NULL) { 185815b0ea00SMatan Azrad rte_errno = EINVAL; 185915b0ea00SMatan Azrad return -rte_errno; 186015b0ea00SMatan Azrad } 1861e72dd09bSNélio Laranjeiro /* Process parameters. */ 1862e72dd09bSNélio Laranjeiro for (i = 0; (params[i] != NULL); ++i) { 1863e72dd09bSNélio Laranjeiro if (rte_kvargs_count(kvlist, params[i])) { 1864e72dd09bSNélio Laranjeiro ret = rte_kvargs_process(kvlist, params[i], 18657fe24446SShahaf Shuler mlx5_args_check, config); 1866a6d83b6aSNélio Laranjeiro if (ret) { 1867a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 1868a67323e4SShahaf Shuler rte_kvargs_free(kvlist); 1869a6d83b6aSNélio Laranjeiro return -rte_errno; 1870e72dd09bSNélio Laranjeiro } 1871e72dd09bSNélio Laranjeiro } 1872a67323e4SShahaf Shuler } 1873e72dd09bSNélio Laranjeiro rte_kvargs_free(kvlist); 1874e72dd09bSNélio Laranjeiro return 0; 1875e72dd09bSNélio Laranjeiro } 1876e72dd09bSNélio Laranjeiro 1877fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver; 1878771fa900SAdrien Mazarguil 18797be600c8SYongseok Koh /** 18807be600c8SYongseok Koh * PMD global initialization. 18817be600c8SYongseok Koh * 18827be600c8SYongseok Koh * Independent from individual device, this function initializes global 18837be600c8SYongseok Koh * per-PMD data structures distinguishing primary and secondary processes. 18847be600c8SYongseok Koh * Hence, each initialization is called once per a process. 18857be600c8SYongseok Koh * 18867be600c8SYongseok Koh * @return 18877be600c8SYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set. 18887be600c8SYongseok Koh */ 18897be600c8SYongseok Koh static int 18907be600c8SYongseok Koh mlx5_init_once(void) 18917be600c8SYongseok Koh { 18927be600c8SYongseok Koh struct mlx5_shared_data *sd; 18937be600c8SYongseok Koh struct mlx5_local_data *ld = &mlx5_local_data; 1894edf73dd3SAnatoly Burakov int ret = 0; 18957be600c8SYongseok Koh 18967be600c8SYongseok Koh if (mlx5_init_shared_data()) 18977be600c8SYongseok Koh return -rte_errno; 18987be600c8SYongseok Koh sd = mlx5_shared_data; 18998e46d4e1SAlexander Kozyrev MLX5_ASSERT(sd); 19007be600c8SYongseok Koh rte_spinlock_lock(&sd->lock); 19017be600c8SYongseok Koh switch (rte_eal_process_type()) { 19027be600c8SYongseok Koh case RTE_PROC_PRIMARY: 19037be600c8SYongseok Koh if (sd->init_done) 19047be600c8SYongseok Koh break; 19057be600c8SYongseok Koh LIST_INIT(&sd->mem_event_cb_list); 19067be600c8SYongseok Koh rte_rwlock_init(&sd->mem_event_rwlock); 19077be600c8SYongseok Koh rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 19087be600c8SYongseok Koh mlx5_mr_mem_event_cb, NULL); 1909a4de9586SVu Pham ret = mlx5_mp_init_primary(MLX5_MP_NAME, 1910a4de9586SVu Pham mlx5_mp_primary_handle); 1911edf73dd3SAnatoly Burakov if (ret) 1912edf73dd3SAnatoly Burakov goto out; 19137be600c8SYongseok Koh sd->init_done = true; 19147be600c8SYongseok Koh break; 19157be600c8SYongseok Koh case RTE_PROC_SECONDARY: 19167be600c8SYongseok Koh if (ld->init_done) 19177be600c8SYongseok Koh break; 1918a4de9586SVu Pham ret = mlx5_mp_init_secondary(MLX5_MP_NAME, 1919a4de9586SVu Pham mlx5_mp_secondary_handle); 1920edf73dd3SAnatoly Burakov if (ret) 1921edf73dd3SAnatoly Burakov goto out; 19227be600c8SYongseok Koh ++sd->secondary_cnt; 19237be600c8SYongseok Koh ld->init_done = true; 19247be600c8SYongseok Koh break; 19257be600c8SYongseok Koh default: 19267be600c8SYongseok Koh break; 19277be600c8SYongseok Koh } 1928edf73dd3SAnatoly Burakov out: 19297be600c8SYongseok Koh rte_spinlock_unlock(&sd->lock); 1930edf73dd3SAnatoly Burakov return ret; 19317be600c8SYongseok Koh } 19327be600c8SYongseok Koh 19337be600c8SYongseok Koh /** 193438b4b397SViacheslav Ovsiienko * Configures the minimal amount of data to inline into WQE 193538b4b397SViacheslav Ovsiienko * while sending packets. 193638b4b397SViacheslav Ovsiienko * 193738b4b397SViacheslav Ovsiienko * - the txq_inline_min has the maximal priority, if this 193838b4b397SViacheslav Ovsiienko * key is specified in devargs 193938b4b397SViacheslav Ovsiienko * - if DevX is enabled the inline mode is queried from the 194038b4b397SViacheslav Ovsiienko * device (HCA attributes and NIC vport context if needed). 1941ee76bddcSThomas Monjalon * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4 Lx 194238b4b397SViacheslav Ovsiienko * and none (0 bytes) for other NICs 194338b4b397SViacheslav Ovsiienko * 194438b4b397SViacheslav Ovsiienko * @param spawn 194538b4b397SViacheslav Ovsiienko * Verbs device parameters (name, port, switch_info) to spawn. 194638b4b397SViacheslav Ovsiienko * @param config 194738b4b397SViacheslav Ovsiienko * Device configuration parameters. 194838b4b397SViacheslav Ovsiienko */ 194938b4b397SViacheslav Ovsiienko static void 195038b4b397SViacheslav Ovsiienko mlx5_set_min_inline(struct mlx5_dev_spawn_data *spawn, 195138b4b397SViacheslav Ovsiienko struct mlx5_dev_config *config) 195238b4b397SViacheslav Ovsiienko { 195338b4b397SViacheslav Ovsiienko if (config->txq_inline_min != MLX5_ARG_UNSET) { 195438b4b397SViacheslav Ovsiienko /* Application defines size of inlined data explicitly. */ 195538b4b397SViacheslav Ovsiienko switch (spawn->pci_dev->id.device_id) { 195638b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 195738b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 195838b4b397SViacheslav Ovsiienko if (config->txq_inline_min < 195938b4b397SViacheslav Ovsiienko (int)MLX5_INLINE_HSIZE_L2) { 196038b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, 196138b4b397SViacheslav Ovsiienko "txq_inline_mix aligned to minimal" 196238b4b397SViacheslav Ovsiienko " ConnectX-4 required value %d", 196338b4b397SViacheslav Ovsiienko (int)MLX5_INLINE_HSIZE_L2); 196438b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 196538b4b397SViacheslav Ovsiienko } 196638b4b397SViacheslav Ovsiienko break; 196738b4b397SViacheslav Ovsiienko } 196838b4b397SViacheslav Ovsiienko goto exit; 196938b4b397SViacheslav Ovsiienko } 197038b4b397SViacheslav Ovsiienko if (config->hca_attr.eth_net_offloads) { 197138b4b397SViacheslav Ovsiienko /* We have DevX enabled, inline mode queried successfully. */ 197238b4b397SViacheslav Ovsiienko switch (config->hca_attr.wqe_inline_mode) { 197338b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_L2: 197438b4b397SViacheslav Ovsiienko /* outer L2 header must be inlined. */ 197538b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 197638b4b397SViacheslav Ovsiienko goto exit; 197738b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: 197838b4b397SViacheslav Ovsiienko /* No inline data are required by NIC. */ 197938b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 198038b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 198138b4b397SViacheslav Ovsiienko config->hca_attr.wqe_vlan_insert; 198238b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, "Tx VLAN insertion is supported"); 198338b4b397SViacheslav Ovsiienko goto exit; 198438b4b397SViacheslav Ovsiienko case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: 198538b4b397SViacheslav Ovsiienko /* inline mode is defined by NIC vport context. */ 198638b4b397SViacheslav Ovsiienko if (!config->hca_attr.eth_virt) 198738b4b397SViacheslav Ovsiienko break; 198838b4b397SViacheslav Ovsiienko switch (config->hca_attr.vport_inline_mode) { 198938b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_NONE: 199038b4b397SViacheslav Ovsiienko config->txq_inline_min = 199138b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_NONE; 199238b4b397SViacheslav Ovsiienko goto exit; 199338b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_L2: 199438b4b397SViacheslav Ovsiienko config->txq_inline_min = 199538b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L2; 199638b4b397SViacheslav Ovsiienko goto exit; 199738b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_IP: 199838b4b397SViacheslav Ovsiienko config->txq_inline_min = 199938b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L3; 200038b4b397SViacheslav Ovsiienko goto exit; 200138b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_TCP_UDP: 200238b4b397SViacheslav Ovsiienko config->txq_inline_min = 200338b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_L4; 200438b4b397SViacheslav Ovsiienko goto exit; 200538b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_L2: 200638b4b397SViacheslav Ovsiienko config->txq_inline_min = 200738b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L2; 200838b4b397SViacheslav Ovsiienko goto exit; 200938b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_IP: 201038b4b397SViacheslav Ovsiienko config->txq_inline_min = 201138b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L3; 201238b4b397SViacheslav Ovsiienko goto exit; 201338b4b397SViacheslav Ovsiienko case MLX5_INLINE_MODE_INNER_TCP_UDP: 201438b4b397SViacheslav Ovsiienko config->txq_inline_min = 201538b4b397SViacheslav Ovsiienko MLX5_INLINE_HSIZE_INNER_L4; 201638b4b397SViacheslav Ovsiienko goto exit; 201738b4b397SViacheslav Ovsiienko } 201838b4b397SViacheslav Ovsiienko } 201938b4b397SViacheslav Ovsiienko } 202038b4b397SViacheslav Ovsiienko /* 202138b4b397SViacheslav Ovsiienko * We get here if we are unable to deduce 202238b4b397SViacheslav Ovsiienko * inline data size with DevX. Try PCI ID 202338b4b397SViacheslav Ovsiienko * to determine old NICs. 202438b4b397SViacheslav Ovsiienko */ 202538b4b397SViacheslav Ovsiienko switch (spawn->pci_dev->id.device_id) { 202638b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 202738b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 202838b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: 202938b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 2030614de6c8SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 203138b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 0; 203238b4b397SViacheslav Ovsiienko break; 203338b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5: 203438b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 203538b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: 203638b4b397SViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 203738b4b397SViacheslav Ovsiienko /* 203838b4b397SViacheslav Ovsiienko * These NICs support VLAN insertion from WQE and 203938b4b397SViacheslav Ovsiienko * report the wqe_vlan_insert flag. But there is the bug 204038b4b397SViacheslav Ovsiienko * and PFC control may be broken, so disable feature. 204138b4b397SViacheslav Ovsiienko */ 204238b4b397SViacheslav Ovsiienko config->hw_vlan_insert = 0; 204320215627SDavid Christensen config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 204438b4b397SViacheslav Ovsiienko break; 204538b4b397SViacheslav Ovsiienko default: 204638b4b397SViacheslav Ovsiienko config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 204738b4b397SViacheslav Ovsiienko break; 204838b4b397SViacheslav Ovsiienko } 204938b4b397SViacheslav Ovsiienko exit: 205038b4b397SViacheslav Ovsiienko DRV_LOG(DEBUG, "min tx inline configured: %d", config->txq_inline_min); 205138b4b397SViacheslav Ovsiienko } 205238b4b397SViacheslav Ovsiienko 205338b4b397SViacheslav Ovsiienko /** 205439139371SViacheslav Ovsiienko * Configures the metadata mask fields in the shared context. 205539139371SViacheslav Ovsiienko * 205639139371SViacheslav Ovsiienko * @param [in] dev 205739139371SViacheslav Ovsiienko * Pointer to Ethernet device. 205839139371SViacheslav Ovsiienko */ 205939139371SViacheslav Ovsiienko static void 206039139371SViacheslav Ovsiienko mlx5_set_metadata_mask(struct rte_eth_dev *dev) 206139139371SViacheslav Ovsiienko { 206239139371SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 206339139371SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 206439139371SViacheslav Ovsiienko uint32_t meta, mark, reg_c0; 206539139371SViacheslav Ovsiienko 206639139371SViacheslav Ovsiienko reg_c0 = ~priv->vport_meta_mask; 206739139371SViacheslav Ovsiienko switch (priv->config.dv_xmeta_en) { 206839139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_LEGACY: 206939139371SViacheslav Ovsiienko meta = UINT32_MAX; 207039139371SViacheslav Ovsiienko mark = MLX5_FLOW_MARK_MASK; 207139139371SViacheslav Ovsiienko break; 207239139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_META16: 207339139371SViacheslav Ovsiienko meta = reg_c0 >> rte_bsf32(reg_c0); 207439139371SViacheslav Ovsiienko mark = MLX5_FLOW_MARK_MASK; 207539139371SViacheslav Ovsiienko break; 207639139371SViacheslav Ovsiienko case MLX5_XMETA_MODE_META32: 207739139371SViacheslav Ovsiienko meta = UINT32_MAX; 207839139371SViacheslav Ovsiienko mark = (reg_c0 >> rte_bsf32(reg_c0)) & MLX5_FLOW_MARK_MASK; 207939139371SViacheslav Ovsiienko break; 208039139371SViacheslav Ovsiienko default: 208139139371SViacheslav Ovsiienko meta = 0; 208239139371SViacheslav Ovsiienko mark = 0; 20838e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 208439139371SViacheslav Ovsiienko break; 208539139371SViacheslav Ovsiienko } 208639139371SViacheslav Ovsiienko if (sh->dv_mark_mask && sh->dv_mark_mask != mark) 208739139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata MARK mask mismatche %08X:%08X", 208839139371SViacheslav Ovsiienko sh->dv_mark_mask, mark); 208939139371SViacheslav Ovsiienko else 209039139371SViacheslav Ovsiienko sh->dv_mark_mask = mark; 209139139371SViacheslav Ovsiienko if (sh->dv_meta_mask && sh->dv_meta_mask != meta) 209239139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata META mask mismatche %08X:%08X", 209339139371SViacheslav Ovsiienko sh->dv_meta_mask, meta); 209439139371SViacheslav Ovsiienko else 209539139371SViacheslav Ovsiienko sh->dv_meta_mask = meta; 209639139371SViacheslav Ovsiienko if (sh->dv_regc0_mask && sh->dv_regc0_mask != reg_c0) 209739139371SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata reg_c0 mask mismatche %08X:%08X", 209839139371SViacheslav Ovsiienko sh->dv_meta_mask, reg_c0); 209939139371SViacheslav Ovsiienko else 210039139371SViacheslav Ovsiienko sh->dv_regc0_mask = reg_c0; 210139139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata mode %u", priv->config.dv_xmeta_en); 210239139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata MARK mask %08X", sh->dv_mark_mask); 210339139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata META mask %08X", sh->dv_meta_mask); 210439139371SViacheslav Ovsiienko DRV_LOG(DEBUG, "metadata reg_c0 mask %08X", sh->dv_regc0_mask); 210539139371SViacheslav Ovsiienko } 210639139371SViacheslav Ovsiienko 210739139371SViacheslav Ovsiienko /** 210821cae858SDekel Peled * Allocate page of door-bells and register it using DevX API. 210921cae858SDekel Peled * 211021cae858SDekel Peled * @param [in] dev 211121cae858SDekel Peled * Pointer to Ethernet device. 211221cae858SDekel Peled * 211321cae858SDekel Peled * @return 211421cae858SDekel Peled * Pointer to new page on success, NULL otherwise. 211521cae858SDekel Peled */ 211621cae858SDekel Peled static struct mlx5_devx_dbr_page * 211721cae858SDekel Peled mlx5_alloc_dbr_page(struct rte_eth_dev *dev) 211821cae858SDekel Peled { 211921cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 212021cae858SDekel Peled struct mlx5_devx_dbr_page *page; 212121cae858SDekel Peled 212221cae858SDekel Peled /* Allocate space for door-bell page and management data. */ 212321cae858SDekel Peled page = rte_calloc_socket(__func__, 1, sizeof(struct mlx5_devx_dbr_page), 212421cae858SDekel Peled RTE_CACHE_LINE_SIZE, dev->device->numa_node); 212521cae858SDekel Peled if (!page) { 212621cae858SDekel Peled DRV_LOG(ERR, "port %u cannot allocate dbr page", 212721cae858SDekel Peled dev->data->port_id); 212821cae858SDekel Peled return NULL; 212921cae858SDekel Peled } 213021cae858SDekel Peled /* Register allocated memory. */ 213121cae858SDekel Peled page->umem = mlx5_glue->devx_umem_reg(priv->sh->ctx, page->dbrs, 213221cae858SDekel Peled MLX5_DBR_PAGE_SIZE, 0); 213321cae858SDekel Peled if (!page->umem) { 213421cae858SDekel Peled DRV_LOG(ERR, "port %u cannot umem reg dbr page", 213521cae858SDekel Peled dev->data->port_id); 213621cae858SDekel Peled rte_free(page); 213721cae858SDekel Peled return NULL; 213821cae858SDekel Peled } 213921cae858SDekel Peled return page; 214021cae858SDekel Peled } 214121cae858SDekel Peled 214221cae858SDekel Peled /** 214321cae858SDekel Peled * Find the next available door-bell, allocate new page if needed. 214421cae858SDekel Peled * 214521cae858SDekel Peled * @param [in] dev 214621cae858SDekel Peled * Pointer to Ethernet device. 214721cae858SDekel Peled * @param [out] dbr_page 214821cae858SDekel Peled * Door-bell page containing the page data. 214921cae858SDekel Peled * 215021cae858SDekel Peled * @return 215121cae858SDekel Peled * Door-bell address offset on success, a negative error value otherwise. 215221cae858SDekel Peled */ 215321cae858SDekel Peled int64_t 215421cae858SDekel Peled mlx5_get_dbr(struct rte_eth_dev *dev, struct mlx5_devx_dbr_page **dbr_page) 215521cae858SDekel Peled { 215621cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 215721cae858SDekel Peled struct mlx5_devx_dbr_page *page = NULL; 215821cae858SDekel Peled uint32_t i, j; 215921cae858SDekel Peled 216021cae858SDekel Peled LIST_FOREACH(page, &priv->dbrpgs, next) 216121cae858SDekel Peled if (page->dbr_count < MLX5_DBR_PER_PAGE) 216221cae858SDekel Peled break; 216321cae858SDekel Peled if (!page) { /* No page with free door-bell exists. */ 216421cae858SDekel Peled page = mlx5_alloc_dbr_page(dev); 216521cae858SDekel Peled if (!page) /* Failed to allocate new page. */ 216621cae858SDekel Peled return (-1); 216721cae858SDekel Peled LIST_INSERT_HEAD(&priv->dbrpgs, page, next); 216821cae858SDekel Peled } 216921cae858SDekel Peled /* Loop to find bitmap part with clear bit. */ 217021cae858SDekel Peled for (i = 0; 217121cae858SDekel Peled i < MLX5_DBR_BITMAP_SIZE && page->dbr_bitmap[i] == UINT64_MAX; 217221cae858SDekel Peled i++) 217321cae858SDekel Peled ; /* Empty. */ 217421cae858SDekel Peled /* Find the first clear bit. */ 21759b080425SAsaf Penso MLX5_ASSERT(i < MLX5_DBR_BITMAP_SIZE); 217621cae858SDekel Peled j = rte_bsf64(~page->dbr_bitmap[i]); 217721cae858SDekel Peled page->dbr_bitmap[i] |= (1 << j); 217821cae858SDekel Peled page->dbr_count++; 217921cae858SDekel Peled *dbr_page = page; 218021cae858SDekel Peled return (((i * 64) + j) * sizeof(uint64_t)); 218121cae858SDekel Peled } 218221cae858SDekel Peled 218321cae858SDekel Peled /** 218421cae858SDekel Peled * Release a door-bell record. 218521cae858SDekel Peled * 218621cae858SDekel Peled * @param [in] dev 218721cae858SDekel Peled * Pointer to Ethernet device. 218821cae858SDekel Peled * @param [in] umem_id 218921cae858SDekel Peled * UMEM ID of page containing the door-bell record to release. 219021cae858SDekel Peled * @param [in] offset 219121cae858SDekel Peled * Offset of door-bell record in page. 219221cae858SDekel Peled * 219321cae858SDekel Peled * @return 219421cae858SDekel Peled * 0 on success, a negative error value otherwise. 219521cae858SDekel Peled */ 219621cae858SDekel Peled int32_t 219721cae858SDekel Peled mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id, uint64_t offset) 219821cae858SDekel Peled { 219921cae858SDekel Peled struct mlx5_priv *priv = dev->data->dev_private; 220021cae858SDekel Peled struct mlx5_devx_dbr_page *page = NULL; 220121cae858SDekel Peled int ret = 0; 220221cae858SDekel Peled 220321cae858SDekel Peled LIST_FOREACH(page, &priv->dbrpgs, next) 220421cae858SDekel Peled /* Find the page this address belongs to. */ 220521cae858SDekel Peled if (page->umem->umem_id == umem_id) 220621cae858SDekel Peled break; 220721cae858SDekel Peled if (!page) 220821cae858SDekel Peled return -EINVAL; 220921cae858SDekel Peled page->dbr_count--; 221021cae858SDekel Peled if (!page->dbr_count) { 221121cae858SDekel Peled /* Page not used, free it and remove from list. */ 221221cae858SDekel Peled LIST_REMOVE(page, next); 221321cae858SDekel Peled if (page->umem) 221421cae858SDekel Peled ret = -mlx5_glue->devx_umem_dereg(page->umem); 221521cae858SDekel Peled rte_free(page); 221621cae858SDekel Peled } else { 221721cae858SDekel Peled /* Mark in bitmap that this door-bell is not in use. */ 2218a88209b0SDekel Peled offset /= MLX5_DBR_SIZE; 221921cae858SDekel Peled int i = offset / 64; 222021cae858SDekel Peled int j = offset % 64; 222121cae858SDekel Peled 222221cae858SDekel Peled page->dbr_bitmap[i] &= ~(1 << j); 222321cae858SDekel Peled } 222421cae858SDekel Peled return ret; 222521cae858SDekel Peled } 222621cae858SDekel Peled 2227efa79e68SOri Kam int 2228efa79e68SOri Kam rte_pmd_mlx5_get_dyn_flag_names(char *names[], unsigned int n) 2229efa79e68SOri Kam { 2230efa79e68SOri Kam static const char *const dynf_names[] = { 2231efa79e68SOri Kam RTE_PMD_MLX5_FINE_GRANULARITY_INLINE, 2232efa79e68SOri Kam RTE_MBUF_DYNFLAG_METADATA_NAME 2233efa79e68SOri Kam }; 2234efa79e68SOri Kam unsigned int i; 2235efa79e68SOri Kam 2236efa79e68SOri Kam if (n < RTE_DIM(dynf_names)) 2237efa79e68SOri Kam return -ENOMEM; 2238efa79e68SOri Kam for (i = 0; i < RTE_DIM(dynf_names); i++) { 2239efa79e68SOri Kam if (names[i] == NULL) 2240efa79e68SOri Kam return -EINVAL; 2241efa79e68SOri Kam strcpy(names[i], dynf_names[i]); 2242efa79e68SOri Kam } 2243efa79e68SOri Kam return RTE_DIM(dynf_names); 2244efa79e68SOri Kam } 2245efa79e68SOri Kam 224621cae858SDekel Peled /** 224792d5dd48SViacheslav Ovsiienko * Check sibling device configurations. 224892d5dd48SViacheslav Ovsiienko * 224992d5dd48SViacheslav Ovsiienko * Sibling devices sharing the Infiniband device context 225092d5dd48SViacheslav Ovsiienko * should have compatible configurations. This regards 225192d5dd48SViacheslav Ovsiienko * representors and bonding slaves. 225292d5dd48SViacheslav Ovsiienko * 225392d5dd48SViacheslav Ovsiienko * @param priv 225492d5dd48SViacheslav Ovsiienko * Private device descriptor. 225592d5dd48SViacheslav Ovsiienko * @param config 225692d5dd48SViacheslav Ovsiienko * Configuration of the device is going to be created. 225792d5dd48SViacheslav Ovsiienko * 225892d5dd48SViacheslav Ovsiienko * @return 225992d5dd48SViacheslav Ovsiienko * 0 on success, EINVAL otherwise 226092d5dd48SViacheslav Ovsiienko */ 226192d5dd48SViacheslav Ovsiienko static int 226292d5dd48SViacheslav Ovsiienko mlx5_dev_check_sibling_config(struct mlx5_priv *priv, 226392d5dd48SViacheslav Ovsiienko struct mlx5_dev_config *config) 226492d5dd48SViacheslav Ovsiienko { 226592d5dd48SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 226692d5dd48SViacheslav Ovsiienko struct mlx5_dev_config *sh_conf = NULL; 226792d5dd48SViacheslav Ovsiienko uint16_t port_id; 226892d5dd48SViacheslav Ovsiienko 22698e46d4e1SAlexander Kozyrev MLX5_ASSERT(sh); 227092d5dd48SViacheslav Ovsiienko /* Nothing to compare for the single/first device. */ 227192d5dd48SViacheslav Ovsiienko if (sh->refcnt == 1) 227292d5dd48SViacheslav Ovsiienko return 0; 227392d5dd48SViacheslav Ovsiienko /* Find the device with shared context. */ 2274fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 227592d5dd48SViacheslav Ovsiienko struct mlx5_priv *opriv = 227692d5dd48SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 227792d5dd48SViacheslav Ovsiienko 227892d5dd48SViacheslav Ovsiienko if (opriv && opriv != priv && opriv->sh == sh) { 227992d5dd48SViacheslav Ovsiienko sh_conf = &opriv->config; 228092d5dd48SViacheslav Ovsiienko break; 228192d5dd48SViacheslav Ovsiienko } 228292d5dd48SViacheslav Ovsiienko } 228392d5dd48SViacheslav Ovsiienko if (!sh_conf) 228492d5dd48SViacheslav Ovsiienko return 0; 228592d5dd48SViacheslav Ovsiienko if (sh_conf->dv_flow_en ^ config->dv_flow_en) { 228692d5dd48SViacheslav Ovsiienko DRV_LOG(ERR, "\"dv_flow_en\" configuration mismatch" 228792d5dd48SViacheslav Ovsiienko " for shared %s context", sh->ibdev_name); 228892d5dd48SViacheslav Ovsiienko rte_errno = EINVAL; 228992d5dd48SViacheslav Ovsiienko return rte_errno; 229092d5dd48SViacheslav Ovsiienko } 22912d241515SViacheslav Ovsiienko if (sh_conf->dv_xmeta_en ^ config->dv_xmeta_en) { 22922d241515SViacheslav Ovsiienko DRV_LOG(ERR, "\"dv_xmeta_en\" configuration mismatch" 22932d241515SViacheslav Ovsiienko " for shared %s context", sh->ibdev_name); 22942d241515SViacheslav Ovsiienko rte_errno = EINVAL; 22952d241515SViacheslav Ovsiienko return rte_errno; 22962d241515SViacheslav Ovsiienko } 229792d5dd48SViacheslav Ovsiienko return 0; 229892d5dd48SViacheslav Ovsiienko } 229992d5dd48SViacheslav Ovsiienko /** 2300f38c5457SAdrien Mazarguil * Spawn an Ethernet device from Verbs information. 2301771fa900SAdrien Mazarguil * 2302f38c5457SAdrien Mazarguil * @param dpdk_dev 2303f38c5457SAdrien Mazarguil * Backing DPDK device. 2304ad74bc61SViacheslav Ovsiienko * @param spawn 2305ad74bc61SViacheslav Ovsiienko * Verbs device parameters (name, port, switch_info) to spawn. 2306f87bfa8eSYongseok Koh * @param config 2307f87bfa8eSYongseok Koh * Device configuration parameters. 2308771fa900SAdrien Mazarguil * 2309771fa900SAdrien Mazarguil * @return 2310f38c5457SAdrien Mazarguil * A valid Ethernet device object on success, NULL otherwise and rte_errno 2311206254b7SOphir Munk * is set. The following errors are defined: 23126de569f5SAdrien Mazarguil * 23136de569f5SAdrien Mazarguil * EBUSY: device is not supposed to be spawned. 2314206254b7SOphir Munk * EEXIST: device is already spawned 2315771fa900SAdrien Mazarguil */ 2316f38c5457SAdrien Mazarguil static struct rte_eth_dev * 2317f38c5457SAdrien Mazarguil mlx5_dev_spawn(struct rte_device *dpdk_dev, 2318ad74bc61SViacheslav Ovsiienko struct mlx5_dev_spawn_data *spawn, 2319ad74bc61SViacheslav Ovsiienko struct mlx5_dev_config config) 2320771fa900SAdrien Mazarguil { 2321ad74bc61SViacheslav Ovsiienko const struct mlx5_switch_info *switch_info = &spawn->info; 232217e19bc4SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = NULL; 232368128934SAdrien Mazarguil struct ibv_port_attr port_attr; 23246057a10bSAdrien Mazarguil struct mlx5dv_context dv_attr = { .comp_mask = 0 }; 23259083982cSAdrien Mazarguil struct rte_eth_dev *eth_dev = NULL; 2326dbeba4cfSThomas Monjalon struct mlx5_priv *priv = NULL; 2327771fa900SAdrien Mazarguil int err = 0; 232878c7a16dSYongseok Koh unsigned int hw_padding = 0; 2329e192ef80SYaacov Hazan unsigned int mps; 2330523f5a74SYongseok Koh unsigned int cqe_comp; 2331bc91e8dbSYongseok Koh unsigned int cqe_pad = 0; 2332772d3435SXueming Li unsigned int tunnel_en = 0; 23331f106da2SMatan Azrad unsigned int mpls_en = 0; 23345f8ba81cSXueming Li unsigned int swp = 0; 23357d6bf6b8SYongseok Koh unsigned int mprq = 0; 23367d6bf6b8SYongseok Koh unsigned int mprq_min_stride_size_n = 0; 23377d6bf6b8SYongseok Koh unsigned int mprq_max_stride_size_n = 0; 23387d6bf6b8SYongseok Koh unsigned int mprq_min_stride_num_n = 0; 23397d6bf6b8SYongseok Koh unsigned int mprq_max_stride_num_n = 0; 23406d13ea8eSOlivier Matz struct rte_ether_addr mac; 234168128934SAdrien Mazarguil char name[RTE_ETH_NAME_MAX_LEN]; 23422b730263SAdrien Mazarguil int own_domain_id = 0; 2343206254b7SOphir Munk uint16_t port_id; 23442b730263SAdrien Mazarguil unsigned int i; 2345d5c06b1bSViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR_DEVX_PORT 234639139371SViacheslav Ovsiienko struct mlx5dv_devx_port devx_port = { .comp_mask = 0 }; 2347d5c06b1bSViacheslav Ovsiienko #endif 2348771fa900SAdrien Mazarguil 23496de569f5SAdrien Mazarguil /* Determine if this port representor is supposed to be spawned. */ 23506de569f5SAdrien Mazarguil if (switch_info->representor && dpdk_dev->devargs) { 23516de569f5SAdrien Mazarguil struct rte_eth_devargs eth_da; 23526de569f5SAdrien Mazarguil 23536de569f5SAdrien Mazarguil err = rte_eth_devargs_parse(dpdk_dev->devargs->args, ð_da); 23546de569f5SAdrien Mazarguil if (err) { 23556de569f5SAdrien Mazarguil rte_errno = -err; 23566de569f5SAdrien Mazarguil DRV_LOG(ERR, "failed to process device arguments: %s", 23576de569f5SAdrien Mazarguil strerror(rte_errno)); 23586de569f5SAdrien Mazarguil return NULL; 23596de569f5SAdrien Mazarguil } 23606de569f5SAdrien Mazarguil for (i = 0; i < eth_da.nb_representor_ports; ++i) 23616de569f5SAdrien Mazarguil if (eth_da.representor_ports[i] == 23626de569f5SAdrien Mazarguil (uint16_t)switch_info->port_name) 23636de569f5SAdrien Mazarguil break; 23646de569f5SAdrien Mazarguil if (i == eth_da.nb_representor_ports) { 23656de569f5SAdrien Mazarguil rte_errno = EBUSY; 23666de569f5SAdrien Mazarguil return NULL; 23676de569f5SAdrien Mazarguil } 23686de569f5SAdrien Mazarguil } 2369206254b7SOphir Munk /* Build device name. */ 237010dadfcbSViacheslav Ovsiienko if (spawn->pf_bond < 0) { 237110dadfcbSViacheslav Ovsiienko /* Single device. */ 2372206254b7SOphir Munk if (!switch_info->representor) 237309c9c4d2SThomas Monjalon strlcpy(name, dpdk_dev->name, sizeof(name)); 2374206254b7SOphir Munk else 2375206254b7SOphir Munk snprintf(name, sizeof(name), "%s_representor_%u", 2376206254b7SOphir Munk dpdk_dev->name, switch_info->port_name); 237710dadfcbSViacheslav Ovsiienko } else { 237810dadfcbSViacheslav Ovsiienko /* Bonding device. */ 237910dadfcbSViacheslav Ovsiienko if (!switch_info->representor) 238010dadfcbSViacheslav Ovsiienko snprintf(name, sizeof(name), "%s_%s", 238110dadfcbSViacheslav Ovsiienko dpdk_dev->name, spawn->ibv_dev->name); 238210dadfcbSViacheslav Ovsiienko else 238310dadfcbSViacheslav Ovsiienko snprintf(name, sizeof(name), "%s_%s_representor_%u", 238410dadfcbSViacheslav Ovsiienko dpdk_dev->name, spawn->ibv_dev->name, 238510dadfcbSViacheslav Ovsiienko switch_info->port_name); 238610dadfcbSViacheslav Ovsiienko } 2387206254b7SOphir Munk /* check if the device is already spawned */ 2388206254b7SOphir Munk if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) { 2389206254b7SOphir Munk rte_errno = EEXIST; 2390206254b7SOphir Munk return NULL; 2391206254b7SOphir Munk } 239217e19bc4SViacheslav Ovsiienko DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name); 239317e19bc4SViacheslav Ovsiienko if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 2394a4de9586SVu Pham struct mlx5_mp_id mp_id; 2395a4de9586SVu Pham 239617e19bc4SViacheslav Ovsiienko eth_dev = rte_eth_dev_attach_secondary(name); 239717e19bc4SViacheslav Ovsiienko if (eth_dev == NULL) { 239817e19bc4SViacheslav Ovsiienko DRV_LOG(ERR, "can not attach rte ethdev"); 239917e19bc4SViacheslav Ovsiienko rte_errno = ENOMEM; 2400f38c5457SAdrien Mazarguil return NULL; 2401771fa900SAdrien Mazarguil } 240217e19bc4SViacheslav Ovsiienko eth_dev->device = dpdk_dev; 240317e19bc4SViacheslav Ovsiienko eth_dev->dev_ops = &mlx5_dev_sec_ops; 2404120dc4a7SYongseok Koh err = mlx5_proc_priv_init(eth_dev); 2405120dc4a7SYongseok Koh if (err) 2406120dc4a7SYongseok Koh return NULL; 2407a4de9586SVu Pham mp_id.port_id = eth_dev->data->port_id; 2408a4de9586SVu Pham strlcpy(mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 240917e19bc4SViacheslav Ovsiienko /* Receive command fd from primary process */ 2410a4de9586SVu Pham err = mlx5_mp_req_verbs_cmd_fd(&mp_id); 241117e19bc4SViacheslav Ovsiienko if (err < 0) 241217e19bc4SViacheslav Ovsiienko return NULL; 241317e19bc4SViacheslav Ovsiienko /* Remap UAR for Tx queues. */ 2414120dc4a7SYongseok Koh err = mlx5_tx_uar_init_secondary(eth_dev, err); 241517e19bc4SViacheslav Ovsiienko if (err) 241617e19bc4SViacheslav Ovsiienko return NULL; 241717e19bc4SViacheslav Ovsiienko /* 241817e19bc4SViacheslav Ovsiienko * Ethdev pointer is still required as input since 241917e19bc4SViacheslav Ovsiienko * the primary device is not accessible from the 242017e19bc4SViacheslav Ovsiienko * secondary process. 242117e19bc4SViacheslav Ovsiienko */ 242217e19bc4SViacheslav Ovsiienko eth_dev->rx_pkt_burst = mlx5_select_rx_function(eth_dev); 242317e19bc4SViacheslav Ovsiienko eth_dev->tx_pkt_burst = mlx5_select_tx_function(eth_dev); 242417e19bc4SViacheslav Ovsiienko return eth_dev; 2425f5bf91deSMoti Haimovsky } 24268409a285SViacheslav Ovsiienko /* 24278409a285SViacheslav Ovsiienko * Some parameters ("tx_db_nc" in particularly) are needed in 24288409a285SViacheslav Ovsiienko * advance to create dv/verbs device context. We proceed the 24298409a285SViacheslav Ovsiienko * devargs here to get ones, and later proceed devargs again 24308409a285SViacheslav Ovsiienko * to override some hardware settings. 24318409a285SViacheslav Ovsiienko */ 24328409a285SViacheslav Ovsiienko err = mlx5_args(&config, dpdk_dev->devargs); 24338409a285SViacheslav Ovsiienko if (err) { 24348409a285SViacheslav Ovsiienko err = rte_errno; 24358409a285SViacheslav Ovsiienko DRV_LOG(ERR, "failed to process device arguments: %s", 24368409a285SViacheslav Ovsiienko strerror(rte_errno)); 24378409a285SViacheslav Ovsiienko goto error; 24388409a285SViacheslav Ovsiienko } 24398409a285SViacheslav Ovsiienko sh = mlx5_alloc_shared_ibctx(spawn, &config); 244017e19bc4SViacheslav Ovsiienko if (!sh) 244117e19bc4SViacheslav Ovsiienko return NULL; 244217e19bc4SViacheslav Ovsiienko config.devx = sh->devx; 24433075bd23SDekel Peled #ifdef HAVE_MLX5DV_DR_ACTION_DEST_DEVX_TIR 24443075bd23SDekel Peled config.dest_tir = 1; 24453075bd23SDekel Peled #endif 24465f8ba81cSXueming Li #ifdef HAVE_IBV_MLX5_MOD_SWP 24476057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP; 24485f8ba81cSXueming Li #endif 244943e9d979SShachar Beiser /* 245043e9d979SShachar Beiser * Multi-packet send is supported by ConnectX-4 Lx PF as well 245143e9d979SShachar Beiser * as all ConnectX-5 devices. 245243e9d979SShachar Beiser */ 2453038e7251SShahaf Shuler #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 24546057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_TUNNEL_OFFLOADS; 2455038e7251SShahaf Shuler #endif 24567d6bf6b8SYongseok Koh #ifdef HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT 24576057a10bSAdrien Mazarguil dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_STRIDING_RQ; 24587d6bf6b8SYongseok Koh #endif 245917e19bc4SViacheslav Ovsiienko mlx5_glue->dv_query_device(sh->ctx, &dv_attr); 24606057a10bSAdrien Mazarguil if (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED) { 24616057a10bSAdrien Mazarguil if (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW) { 2462a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "enhanced MPW is supported"); 246343e9d979SShachar Beiser mps = MLX5_MPW_ENHANCED; 246443e9d979SShachar Beiser } else { 2465a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "MPW is supported"); 2466e589960cSYongseok Koh mps = MLX5_MPW; 2467e589960cSYongseok Koh } 2468e589960cSYongseok Koh } else { 2469a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "MPW isn't supported"); 247043e9d979SShachar Beiser mps = MLX5_MPW_DISABLED; 247143e9d979SShachar Beiser } 24725f8ba81cSXueming Li #ifdef HAVE_IBV_MLX5_MOD_SWP 24736057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_SWP) 24746057a10bSAdrien Mazarguil swp = dv_attr.sw_parsing_caps.sw_parsing_offloads; 24755f8ba81cSXueming Li DRV_LOG(DEBUG, "SWP support: %u", swp); 24765f8ba81cSXueming Li #endif 247768128934SAdrien Mazarguil config.swp = !!swp; 24787d6bf6b8SYongseok Koh #ifdef HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT 24796057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_STRIDING_RQ) { 24807d6bf6b8SYongseok Koh struct mlx5dv_striding_rq_caps mprq_caps = 24816057a10bSAdrien Mazarguil dv_attr.striding_rq_caps; 24827d6bf6b8SYongseok Koh 24837d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmin_single_stride_log_num_of_bytes: %d", 24847d6bf6b8SYongseok Koh mprq_caps.min_single_stride_log_num_of_bytes); 24857d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmax_single_stride_log_num_of_bytes: %d", 24867d6bf6b8SYongseok Koh mprq_caps.max_single_stride_log_num_of_bytes); 24877d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmin_single_wqe_log_num_of_strides: %d", 24887d6bf6b8SYongseok Koh mprq_caps.min_single_wqe_log_num_of_strides); 24897d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tmax_single_wqe_log_num_of_strides: %d", 24907d6bf6b8SYongseok Koh mprq_caps.max_single_wqe_log_num_of_strides); 24917d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "\tsupported_qpts: %d", 24927d6bf6b8SYongseok Koh mprq_caps.supported_qpts); 24937d6bf6b8SYongseok Koh DRV_LOG(DEBUG, "device supports Multi-Packet RQ"); 24947d6bf6b8SYongseok Koh mprq = 1; 24957d6bf6b8SYongseok Koh mprq_min_stride_size_n = 24967d6bf6b8SYongseok Koh mprq_caps.min_single_stride_log_num_of_bytes; 24977d6bf6b8SYongseok Koh mprq_max_stride_size_n = 24987d6bf6b8SYongseok Koh mprq_caps.max_single_stride_log_num_of_bytes; 24997d6bf6b8SYongseok Koh mprq_min_stride_num_n = 25007d6bf6b8SYongseok Koh mprq_caps.min_single_wqe_log_num_of_strides; 25017d6bf6b8SYongseok Koh mprq_max_stride_num_n = 25027d6bf6b8SYongseok Koh mprq_caps.max_single_wqe_log_num_of_strides; 25037d6bf6b8SYongseok Koh } 25047d6bf6b8SYongseok Koh #endif 2505523f5a74SYongseok Koh if (RTE_CACHE_LINE_SIZE == 128 && 25066057a10bSAdrien Mazarguil !(dv_attr.flags & MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP)) 2507523f5a74SYongseok Koh cqe_comp = 0; 2508523f5a74SYongseok Koh else 2509523f5a74SYongseok Koh cqe_comp = 1; 251068128934SAdrien Mazarguil config.cqe_comp = cqe_comp; 2511bc91e8dbSYongseok Koh #ifdef HAVE_IBV_MLX5_MOD_CQE_128B_PAD 2512bc91e8dbSYongseok Koh /* Whether device supports 128B Rx CQE padding. */ 2513bc91e8dbSYongseok Koh cqe_pad = RTE_CACHE_LINE_SIZE == 128 && 2514bc91e8dbSYongseok Koh (dv_attr.flags & MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD); 2515bc91e8dbSYongseok Koh #endif 2516038e7251SShahaf Shuler #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 25176057a10bSAdrien Mazarguil if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_TUNNEL_OFFLOADS) { 25186057a10bSAdrien Mazarguil tunnel_en = ((dv_attr.tunnel_offloads_caps & 2519038e7251SShahaf Shuler MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_VXLAN) && 25206057a10bSAdrien Mazarguil (dv_attr.tunnel_offloads_caps & 25214acb96fdSSuanming Mou MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_GRE) && 25224acb96fdSSuanming Mou (dv_attr.tunnel_offloads_caps & 25234acb96fdSSuanming Mou MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_GENEVE)); 2524038e7251SShahaf Shuler } 2525a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "tunnel offloading is %ssupported", 2526a170a30dSNélio Laranjeiro tunnel_en ? "" : "not "); 2527038e7251SShahaf Shuler #else 2528a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 2529a170a30dSNélio Laranjeiro "tunnel offloading disabled due to old OFED/rdma-core version"); 2530038e7251SShahaf Shuler #endif 253168128934SAdrien Mazarguil config.tunnel_en = tunnel_en; 25321f106da2SMatan Azrad #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 25336057a10bSAdrien Mazarguil mpls_en = ((dv_attr.tunnel_offloads_caps & 25341f106da2SMatan Azrad MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_CW_MPLS_OVER_GRE) && 25356057a10bSAdrien Mazarguil (dv_attr.tunnel_offloads_caps & 25361f106da2SMatan Azrad MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_CW_MPLS_OVER_UDP)); 25371f106da2SMatan Azrad DRV_LOG(DEBUG, "MPLS over GRE/UDP tunnel offloading is %ssupported", 25381f106da2SMatan Azrad mpls_en ? "" : "not "); 25391f106da2SMatan Azrad #else 25401f106da2SMatan Azrad DRV_LOG(WARNING, "MPLS over GRE/UDP tunnel offloading disabled due to" 25411f106da2SMatan Azrad " old OFED/rdma-core version or firmware configuration"); 25421f106da2SMatan Azrad #endif 254368128934SAdrien Mazarguil config.mpls_en = mpls_en; 2544771fa900SAdrien Mazarguil /* Check port status. */ 254517e19bc4SViacheslav Ovsiienko err = mlx5_glue->query_port(sh->ctx, spawn->ibv_port, &port_attr); 2546771fa900SAdrien Mazarguil if (err) { 2547a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port query failed: %s", strerror(err)); 25489083982cSAdrien Mazarguil goto error; 2549771fa900SAdrien Mazarguil } 25501371f4dfSOr Ami if (port_attr.link_layer != IBV_LINK_LAYER_ETHERNET) { 25519083982cSAdrien Mazarguil DRV_LOG(ERR, "port is not configured in Ethernet mode"); 2552e1c3e305SMatan Azrad err = EINVAL; 25539083982cSAdrien Mazarguil goto error; 25541371f4dfSOr Ami } 2555771fa900SAdrien Mazarguil if (port_attr.state != IBV_PORT_ACTIVE) 25569083982cSAdrien Mazarguil DRV_LOG(DEBUG, "port is not active: \"%s\" (%d)", 2557a170a30dSNélio Laranjeiro mlx5_glue->port_state_str(port_attr.state), 2558771fa900SAdrien Mazarguil port_attr.state); 255917e19bc4SViacheslav Ovsiienko /* Allocate private eth device data. */ 2560771fa900SAdrien Mazarguil priv = rte_zmalloc("ethdev private structure", 2561771fa900SAdrien Mazarguil sizeof(*priv), 2562771fa900SAdrien Mazarguil RTE_CACHE_LINE_SIZE); 2563771fa900SAdrien Mazarguil if (priv == NULL) { 2564a170a30dSNélio Laranjeiro DRV_LOG(ERR, "priv allocation failure"); 2565771fa900SAdrien Mazarguil err = ENOMEM; 25669083982cSAdrien Mazarguil goto error; 2567771fa900SAdrien Mazarguil } 256817e19bc4SViacheslav Ovsiienko priv->sh = sh; 256917e19bc4SViacheslav Ovsiienko priv->ibv_port = spawn->ibv_port; 257046e10a4cSViacheslav Ovsiienko priv->pci_dev = spawn->pci_dev; 257135b2d13fSOlivier Matz priv->mtu = RTE_ETHER_MTU; 2572a4de9586SVu Pham priv->mp_id.port_id = port_id; 2573a4de9586SVu Pham strlcpy(priv->mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 25746bf10ab6SMoti Haimovsky #ifndef RTE_ARCH_64 25756bf10ab6SMoti Haimovsky /* Initialize UAR access locks for 32bit implementations. */ 25766bf10ab6SMoti Haimovsky rte_spinlock_init(&priv->uar_lock_cq); 25776bf10ab6SMoti Haimovsky for (i = 0; i < MLX5_UAR_PAGE_NUM_MAX; i++) 25786bf10ab6SMoti Haimovsky rte_spinlock_init(&priv->uar_lock[i]); 25796bf10ab6SMoti Haimovsky #endif 258026c08b97SAdrien Mazarguil /* Some internal functions rely on Netlink sockets, open them now. */ 25815366074bSNelio Laranjeiro priv->nl_socket_rdma = mlx5_nl_init(NETLINK_RDMA); 25825366074bSNelio Laranjeiro priv->nl_socket_route = mlx5_nl_init(NETLINK_ROUTE); 25832b730263SAdrien Mazarguil priv->representor = !!switch_info->representor; 2584299d7dc2SViacheslav Ovsiienko priv->master = !!switch_info->master; 25852b730263SAdrien Mazarguil priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 2586d5c06b1bSViacheslav Ovsiienko priv->vport_meta_tag = 0; 2587d5c06b1bSViacheslav Ovsiienko priv->vport_meta_mask = 0; 2588bee57a0aSViacheslav Ovsiienko priv->pf_bond = spawn->pf_bond; 2589d5c06b1bSViacheslav Ovsiienko #ifdef HAVE_MLX5DV_DR_DEVX_PORT 2590299d7dc2SViacheslav Ovsiienko /* 2591d5c06b1bSViacheslav Ovsiienko * The DevX port query API is implemented. E-Switch may use 2592d5c06b1bSViacheslav Ovsiienko * either vport or reg_c[0] metadata register to match on 2593d5c06b1bSViacheslav Ovsiienko * vport index. The engaged part of metadata register is 2594d5c06b1bSViacheslav Ovsiienko * defined by mask. 2595d5c06b1bSViacheslav Ovsiienko */ 259639139371SViacheslav Ovsiienko if (switch_info->representor || switch_info->master) { 2597d5c06b1bSViacheslav Ovsiienko devx_port.comp_mask = MLX5DV_DEVX_PORT_VPORT | 2598d5c06b1bSViacheslav Ovsiienko MLX5DV_DEVX_PORT_MATCH_REG_C_0; 259939139371SViacheslav Ovsiienko err = mlx5_glue->devx_port_query(sh->ctx, spawn->ibv_port, 260039139371SViacheslav Ovsiienko &devx_port); 2601d5c06b1bSViacheslav Ovsiienko if (err) { 260239139371SViacheslav Ovsiienko DRV_LOG(WARNING, 260339139371SViacheslav Ovsiienko "can't query devx port %d on device %s", 2604d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2605d5c06b1bSViacheslav Ovsiienko devx_port.comp_mask = 0; 2606d5c06b1bSViacheslav Ovsiienko } 260739139371SViacheslav Ovsiienko } 2608d5c06b1bSViacheslav Ovsiienko if (devx_port.comp_mask & MLX5DV_DEVX_PORT_MATCH_REG_C_0) { 2609d5c06b1bSViacheslav Ovsiienko priv->vport_meta_tag = devx_port.reg_c_0.value; 2610d5c06b1bSViacheslav Ovsiienko priv->vport_meta_mask = devx_port.reg_c_0.mask; 2611d5c06b1bSViacheslav Ovsiienko if (!priv->vport_meta_mask) { 2612d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "vport zero mask for port %d" 261306fa6988SDekel Peled " on bonding device %s", 2614d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2615d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2616d5c06b1bSViacheslav Ovsiienko goto error; 2617d5c06b1bSViacheslav Ovsiienko } 2618d5c06b1bSViacheslav Ovsiienko if (priv->vport_meta_tag & ~priv->vport_meta_mask) { 2619d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "invalid vport tag for port %d" 262006fa6988SDekel Peled " on bonding device %s", 2621d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2622d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2623d5c06b1bSViacheslav Ovsiienko goto error; 2624d5c06b1bSViacheslav Ovsiienko } 262585c4bcbcSViacheslav Ovsiienko } 262685c4bcbcSViacheslav Ovsiienko if (devx_port.comp_mask & MLX5DV_DEVX_PORT_VPORT) { 2627d5c06b1bSViacheslav Ovsiienko priv->vport_id = devx_port.vport_num; 2628d5c06b1bSViacheslav Ovsiienko } else if (spawn->pf_bond >= 0) { 2629d5c06b1bSViacheslav Ovsiienko DRV_LOG(ERR, "can't deduce vport index for port %d" 263006fa6988SDekel Peled " on bonding device %s", 2631d5c06b1bSViacheslav Ovsiienko spawn->ibv_port, spawn->ibv_dev->name); 2632d5c06b1bSViacheslav Ovsiienko err = ENOTSUP; 2633d5c06b1bSViacheslav Ovsiienko goto error; 2634d5c06b1bSViacheslav Ovsiienko } else { 2635d5c06b1bSViacheslav Ovsiienko /* Suppose vport index in compatible way. */ 2636d5c06b1bSViacheslav Ovsiienko priv->vport_id = switch_info->representor ? 2637d5c06b1bSViacheslav Ovsiienko switch_info->port_name + 1 : -1; 2638d5c06b1bSViacheslav Ovsiienko } 2639d5c06b1bSViacheslav Ovsiienko #else 2640d5c06b1bSViacheslav Ovsiienko /* 2641d5c06b1bSViacheslav Ovsiienko * Kernel/rdma_core support single E-Switch per PF configurations 2642299d7dc2SViacheslav Ovsiienko * only and vport_id field contains the vport index for 2643299d7dc2SViacheslav Ovsiienko * associated VF, which is deduced from representor port name. 2644ae4eb7dcSViacheslav Ovsiienko * For example, let's have the IB device port 10, it has 2645299d7dc2SViacheslav Ovsiienko * attached network device eth0, which has port name attribute 2646299d7dc2SViacheslav Ovsiienko * pf0vf2, we can deduce the VF number as 2, and set vport index 2647299d7dc2SViacheslav Ovsiienko * as 3 (2+1). This assigning schema should be changed if the 2648299d7dc2SViacheslav Ovsiienko * multiple E-Switch instances per PF configurations or/and PCI 2649299d7dc2SViacheslav Ovsiienko * subfunctions are added. 2650299d7dc2SViacheslav Ovsiienko */ 2651299d7dc2SViacheslav Ovsiienko priv->vport_id = switch_info->representor ? 2652299d7dc2SViacheslav Ovsiienko switch_info->port_name + 1 : -1; 2653d5c06b1bSViacheslav Ovsiienko #endif 2654d5c06b1bSViacheslav Ovsiienko /* representor_id field keeps the unmodified VF index. */ 2655299d7dc2SViacheslav Ovsiienko priv->representor_id = switch_info->representor ? 2656299d7dc2SViacheslav Ovsiienko switch_info->port_name : -1; 26572b730263SAdrien Mazarguil /* 26582b730263SAdrien Mazarguil * Look for sibling devices in order to reuse their switch domain 26592b730263SAdrien Mazarguil * if any, otherwise allocate one. 26602b730263SAdrien Mazarguil */ 2661fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 2662dbeba4cfSThomas Monjalon const struct mlx5_priv *opriv = 2663d874a4eeSThomas Monjalon rte_eth_devices[port_id].data->dev_private; 26642b730263SAdrien Mazarguil 26652b730263SAdrien Mazarguil if (!opriv || 2666f7e95215SViacheslav Ovsiienko opriv->sh != priv->sh || 26672b730263SAdrien Mazarguil opriv->domain_id == 26682b730263SAdrien Mazarguil RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) 26692b730263SAdrien Mazarguil continue; 26702b730263SAdrien Mazarguil priv->domain_id = opriv->domain_id; 26712b730263SAdrien Mazarguil break; 26722b730263SAdrien Mazarguil } 26732b730263SAdrien Mazarguil if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 26742b730263SAdrien Mazarguil err = rte_eth_switch_domain_alloc(&priv->domain_id); 26752b730263SAdrien Mazarguil if (err) { 26762b730263SAdrien Mazarguil err = rte_errno; 26772b730263SAdrien Mazarguil DRV_LOG(ERR, "unable to allocate switch domain: %s", 26782b730263SAdrien Mazarguil strerror(rte_errno)); 26792b730263SAdrien Mazarguil goto error; 26802b730263SAdrien Mazarguil } 26812b730263SAdrien Mazarguil own_domain_id = 1; 26822b730263SAdrien Mazarguil } 26838409a285SViacheslav Ovsiienko /* Override some values set by hardware configuration. */ 26848409a285SViacheslav Ovsiienko mlx5_args(&config, dpdk_dev->devargs); 268592d5dd48SViacheslav Ovsiienko err = mlx5_dev_check_sibling_config(priv, &config); 268692d5dd48SViacheslav Ovsiienko if (err) 268792d5dd48SViacheslav Ovsiienko goto error; 268817e19bc4SViacheslav Ovsiienko config.hw_csum = !!(sh->device_attr.device_cap_flags_ex & 268917e19bc4SViacheslav Ovsiienko IBV_DEVICE_RAW_IP_CSUM); 2690a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "checksum offloading is %ssupported", 26917fe24446SShahaf Shuler (config.hw_csum ? "" : "not ")); 26922dd8b721SViacheslav Ovsiienko #if !defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) && \ 26932dd8b721SViacheslav Ovsiienko !defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 26942dd8b721SViacheslav Ovsiienko DRV_LOG(DEBUG, "counters are not supported"); 26959a761de8SOri Kam #endif 26960adf23adSDekel Peled #if !defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_MLX5DV_DR) 269758b1312eSYongseok Koh if (config.dv_flow_en) { 269858b1312eSYongseok Koh DRV_LOG(WARNING, "DV flow is not supported"); 269958b1312eSYongseok Koh config.dv_flow_en = 0; 270058b1312eSYongseok Koh } 270158b1312eSYongseok Koh #endif 27027fe24446SShahaf Shuler config.ind_table_max_size = 270317e19bc4SViacheslav Ovsiienko sh->device_attr.rss_caps.max_rwq_indirection_table_size; 270468128934SAdrien Mazarguil /* 270568128934SAdrien Mazarguil * Remove this check once DPDK supports larger/variable 270668128934SAdrien Mazarguil * indirection tables. 270768128934SAdrien Mazarguil */ 270868128934SAdrien Mazarguil if (config.ind_table_max_size > (unsigned int)ETH_RSS_RETA_SIZE_512) 27097fe24446SShahaf Shuler config.ind_table_max_size = ETH_RSS_RETA_SIZE_512; 2710a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "maximum Rx indirection table size is %u", 27117fe24446SShahaf Shuler config.ind_table_max_size); 271217e19bc4SViacheslav Ovsiienko config.hw_vlan_strip = !!(sh->device_attr.raw_packet_caps & 271343e9d979SShachar Beiser IBV_RAW_PACKET_CAP_CVLAN_STRIPPING); 2714a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "VLAN stripping is %ssupported", 27157fe24446SShahaf Shuler (config.hw_vlan_strip ? "" : "not ")); 271617e19bc4SViacheslav Ovsiienko config.hw_fcs_strip = !!(sh->device_attr.raw_packet_caps & 2717cd230a3eSShahaf Shuler IBV_RAW_PACKET_CAP_SCATTER_FCS); 2718a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "FCS stripping configuration is %ssupported", 27197fe24446SShahaf Shuler (config.hw_fcs_strip ? "" : "not ")); 27202014a7fbSYongseok Koh #if defined(HAVE_IBV_WQ_FLAG_RX_END_PADDING) 272117e19bc4SViacheslav Ovsiienko hw_padding = !!sh->device_attr.rx_pad_end_addr_align; 27222014a7fbSYongseok Koh #elif defined(HAVE_IBV_WQ_FLAGS_PCI_WRITE_END_PADDING) 272317e19bc4SViacheslav Ovsiienko hw_padding = !!(sh->device_attr.device_cap_flags_ex & 27242014a7fbSYongseok Koh IBV_DEVICE_PCI_WRITE_END_PADDING); 272543e9d979SShachar Beiser #endif 272678c7a16dSYongseok Koh if (config.hw_padding && !hw_padding) { 272778c7a16dSYongseok Koh DRV_LOG(DEBUG, "Rx end alignment padding isn't supported"); 272878c7a16dSYongseok Koh config.hw_padding = 0; 272978c7a16dSYongseok Koh } else if (config.hw_padding) { 273078c7a16dSYongseok Koh DRV_LOG(DEBUG, "Rx end alignment padding is enabled"); 273178c7a16dSYongseok Koh } 273217e19bc4SViacheslav Ovsiienko config.tso = (sh->device_attr.tso_caps.max_tso > 0 && 273317e19bc4SViacheslav Ovsiienko (sh->device_attr.tso_caps.supported_qpts & 273443e9d979SShachar Beiser (1 << IBV_QPT_RAW_PACKET))); 27357fe24446SShahaf Shuler if (config.tso) 273617e19bc4SViacheslav Ovsiienko config.tso_max_payload_sz = sh->device_attr.tso_caps.max_tso; 2737f9de8718SShahaf Shuler /* 2738f9de8718SShahaf Shuler * MPW is disabled by default, while the Enhanced MPW is enabled 2739f9de8718SShahaf Shuler * by default. 2740f9de8718SShahaf Shuler */ 2741f9de8718SShahaf Shuler if (config.mps == MLX5_ARG_UNSET) 2742f9de8718SShahaf Shuler config.mps = (mps == MLX5_MPW_ENHANCED) ? MLX5_MPW_ENHANCED : 2743f9de8718SShahaf Shuler MLX5_MPW_DISABLED; 2744f9de8718SShahaf Shuler else 2745f9de8718SShahaf Shuler config.mps = config.mps ? mps : MLX5_MPW_DISABLED; 2746a170a30dSNélio Laranjeiro DRV_LOG(INFO, "%sMPS is %s", 274782e75f83SViacheslav Ovsiienko config.mps == MLX5_MPW_ENHANCED ? "enhanced " : 274882e75f83SViacheslav Ovsiienko config.mps == MLX5_MPW ? "legacy " : "", 274968128934SAdrien Mazarguil config.mps != MLX5_MPW_DISABLED ? "enabled" : "disabled"); 27507fe24446SShahaf Shuler if (config.cqe_comp && !cqe_comp) { 2751a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "Rx CQE compression isn't supported"); 27527fe24446SShahaf Shuler config.cqe_comp = 0; 2753523f5a74SYongseok Koh } 2754bc91e8dbSYongseok Koh if (config.cqe_pad && !cqe_pad) { 2755bc91e8dbSYongseok Koh DRV_LOG(WARNING, "Rx CQE padding isn't supported"); 2756bc91e8dbSYongseok Koh config.cqe_pad = 0; 2757bc91e8dbSYongseok Koh } else if (config.cqe_pad) { 2758bc91e8dbSYongseok Koh DRV_LOG(INFO, "Rx CQE padding is enabled"); 2759bc91e8dbSYongseok Koh } 2760175f1c21SDekel Peled if (config.devx) { 2761175f1c21SDekel Peled priv->counter_fallback = 0; 2762175f1c21SDekel Peled err = mlx5_devx_cmd_query_hca_attr(sh->ctx, &config.hca_attr); 2763175f1c21SDekel Peled if (err) { 2764175f1c21SDekel Peled err = -err; 2765175f1c21SDekel Peled goto error; 2766175f1c21SDekel Peled } 2767175f1c21SDekel Peled if (!config.hca_attr.flow_counters_dump) 2768175f1c21SDekel Peled priv->counter_fallback = 1; 2769175f1c21SDekel Peled #ifndef HAVE_IBV_DEVX_ASYNC 2770175f1c21SDekel Peled priv->counter_fallback = 1; 2771175f1c21SDekel Peled #endif 2772175f1c21SDekel Peled if (priv->counter_fallback) 277306fa6988SDekel Peled DRV_LOG(INFO, "Use fall-back DV counter management"); 2774175f1c21SDekel Peled /* Check for LRO support. */ 27752eb5dce8SDekel Peled if (config.dest_tir && config.hca_attr.lro_cap && 27762eb5dce8SDekel Peled config.dv_flow_en) { 2777175f1c21SDekel Peled /* TBD check tunnel lro caps. */ 2778175f1c21SDekel Peled config.lro.supported = config.hca_attr.lro_cap; 2779175f1c21SDekel Peled DRV_LOG(DEBUG, "Device supports LRO"); 2780175f1c21SDekel Peled /* 2781175f1c21SDekel Peled * If LRO timeout is not configured by application, 2782175f1c21SDekel Peled * use the minimal supported value. 2783175f1c21SDekel Peled */ 2784175f1c21SDekel Peled if (!config.lro.timeout) 2785175f1c21SDekel Peled config.lro.timeout = 2786175f1c21SDekel Peled config.hca_attr.lro_timer_supported_periods[0]; 2787175f1c21SDekel Peled DRV_LOG(DEBUG, "LRO session timeout set to %d usec", 2788175f1c21SDekel Peled config.lro.timeout); 2789175f1c21SDekel Peled } 27906bc327b9SSuanming Mou #if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER) 27916bc327b9SSuanming Mou if (config.hca_attr.qos.sup && config.hca_attr.qos.srtcm_sup && 27926bc327b9SSuanming Mou config.dv_flow_en) { 279327efd5deSSuanming Mou uint8_t reg_c_mask = 279427efd5deSSuanming Mou config.hca_attr.qos.flow_meter_reg_c_ids; 279527efd5deSSuanming Mou /* 279627efd5deSSuanming Mou * Meter needs two REG_C's for color match and pre-sfx 279727efd5deSSuanming Mou * flow match. Here get the REG_C for color match. 279827efd5deSSuanming Mou * REG_C_0 and REG_C_1 is reserved for metadata feature. 279927efd5deSSuanming Mou */ 280027efd5deSSuanming Mou reg_c_mask &= 0xfc; 280127efd5deSSuanming Mou if (__builtin_popcount(reg_c_mask) < 1) { 280227efd5deSSuanming Mou priv->mtr_en = 0; 280327efd5deSSuanming Mou DRV_LOG(WARNING, "No available register for" 280427efd5deSSuanming Mou " meter."); 280527efd5deSSuanming Mou } else { 280627efd5deSSuanming Mou priv->mtr_color_reg = ffs(reg_c_mask) - 1 + 280727efd5deSSuanming Mou REG_C_0; 28086bc327b9SSuanming Mou priv->mtr_en = 1; 2809792e749eSSuanming Mou priv->mtr_reg_share = 2810792e749eSSuanming Mou config.hca_attr.qos.flow_meter_reg_share; 281127efd5deSSuanming Mou DRV_LOG(DEBUG, "The REG_C meter uses is %d", 281227efd5deSSuanming Mou priv->mtr_color_reg); 281327efd5deSSuanming Mou } 28146bc327b9SSuanming Mou } 28156bc327b9SSuanming Mou #endif 2816175f1c21SDekel Peled } 28175c0e2db6SYongseok Koh if (config.mprq.enabled && mprq) { 2818ecb16045SAlexander Kozyrev if (config.mprq.stride_num_n && 2819ecb16045SAlexander Kozyrev (config.mprq.stride_num_n > mprq_max_stride_num_n || 2820ecb16045SAlexander Kozyrev config.mprq.stride_num_n < mprq_min_stride_num_n)) { 28217d6bf6b8SYongseok Koh config.mprq.stride_num_n = 2822ecb16045SAlexander Kozyrev RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_NUM_N, 2823ecb16045SAlexander Kozyrev mprq_min_stride_num_n), 2824ecb16045SAlexander Kozyrev mprq_max_stride_num_n); 28257d6bf6b8SYongseok Koh DRV_LOG(WARNING, 28267d6bf6b8SYongseok Koh "the number of strides" 28277d6bf6b8SYongseok Koh " for Multi-Packet RQ is out of range," 28287d6bf6b8SYongseok Koh " setting default value (%u)", 28297d6bf6b8SYongseok Koh 1 << config.mprq.stride_num_n); 28307d6bf6b8SYongseok Koh } 2831ecb16045SAlexander Kozyrev if (config.mprq.stride_size_n && 2832ecb16045SAlexander Kozyrev (config.mprq.stride_size_n > mprq_max_stride_size_n || 2833ecb16045SAlexander Kozyrev config.mprq.stride_size_n < mprq_min_stride_size_n)) { 2834ecb16045SAlexander Kozyrev config.mprq.stride_size_n = 2835ecb16045SAlexander Kozyrev RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_SIZE_N, 2836ecb16045SAlexander Kozyrev mprq_min_stride_size_n), 2837ecb16045SAlexander Kozyrev mprq_max_stride_size_n); 2838ecb16045SAlexander Kozyrev DRV_LOG(WARNING, 2839ecb16045SAlexander Kozyrev "the size of a stride" 2840ecb16045SAlexander Kozyrev " for Multi-Packet RQ is out of range," 2841ecb16045SAlexander Kozyrev " setting default value (%u)", 2842ecb16045SAlexander Kozyrev 1 << config.mprq.stride_size_n); 2843ecb16045SAlexander Kozyrev } 28447d6bf6b8SYongseok Koh config.mprq.min_stride_size_n = mprq_min_stride_size_n; 28457d6bf6b8SYongseok Koh config.mprq.max_stride_size_n = mprq_max_stride_size_n; 28465c0e2db6SYongseok Koh } else if (config.mprq.enabled && !mprq) { 28475c0e2db6SYongseok Koh DRV_LOG(WARNING, "Multi-Packet RQ isn't supported"); 28485c0e2db6SYongseok Koh config.mprq.enabled = 0; 28497d6bf6b8SYongseok Koh } 2850066cfecdSMatan Azrad if (config.max_dump_files_num == 0) 2851066cfecdSMatan Azrad config.max_dump_files_num = 128; 2852af4f09f2SNélio Laranjeiro eth_dev = rte_eth_dev_allocate(name); 2853af4f09f2SNélio Laranjeiro if (eth_dev == NULL) { 2854a170a30dSNélio Laranjeiro DRV_LOG(ERR, "can not allocate rte ethdev"); 2855af4f09f2SNélio Laranjeiro err = ENOMEM; 28569083982cSAdrien Mazarguil goto error; 2857af4f09f2SNélio Laranjeiro } 285815febafdSThomas Monjalon /* Flag to call rte_eth_dev_release_port() in rte_eth_dev_close(). */ 285915febafdSThomas Monjalon eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; 2860a7d3c627SThomas Monjalon if (priv->representor) { 28612b730263SAdrien Mazarguil eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; 2862a7d3c627SThomas Monjalon eth_dev->data->representor_id = priv->representor_id; 2863a7d3c627SThomas Monjalon } 2864fa2e14d4SViacheslav Ovsiienko /* 2865fa2e14d4SViacheslav Ovsiienko * Store associated network device interface index. This index 2866fa2e14d4SViacheslav Ovsiienko * is permanent throughout the lifetime of device. So, we may store 2867fa2e14d4SViacheslav Ovsiienko * the ifindex here and use the cached value further. 2868fa2e14d4SViacheslav Ovsiienko */ 28698e46d4e1SAlexander Kozyrev MLX5_ASSERT(spawn->ifindex); 2870fa2e14d4SViacheslav Ovsiienko priv->if_index = spawn->ifindex; 2871af4f09f2SNélio Laranjeiro eth_dev->data->dev_private = priv; 2872df428ceeSYongseok Koh priv->dev_data = eth_dev->data; 2873af4f09f2SNélio Laranjeiro eth_dev->data->mac_addrs = priv->mac; 2874f38c5457SAdrien Mazarguil eth_dev->device = dpdk_dev; 2875771fa900SAdrien Mazarguil /* Configure the first MAC address by default. */ 2876af4f09f2SNélio Laranjeiro if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) { 2877a170a30dSNélio Laranjeiro DRV_LOG(ERR, 2878a170a30dSNélio Laranjeiro "port %u cannot get MAC address, is mlx5_en" 2879a170a30dSNélio Laranjeiro " loaded? (errno: %s)", 28808c3c2372SAdrien Mazarguil eth_dev->data->port_id, strerror(rte_errno)); 2881e1c3e305SMatan Azrad err = ENODEV; 28829083982cSAdrien Mazarguil goto error; 2883771fa900SAdrien Mazarguil } 2884a170a30dSNélio Laranjeiro DRV_LOG(INFO, 2885a170a30dSNélio Laranjeiro "port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 28860f99970bSNélio Laranjeiro eth_dev->data->port_id, 2887771fa900SAdrien Mazarguil mac.addr_bytes[0], mac.addr_bytes[1], 2888771fa900SAdrien Mazarguil mac.addr_bytes[2], mac.addr_bytes[3], 2889771fa900SAdrien Mazarguil mac.addr_bytes[4], mac.addr_bytes[5]); 28900afacb04SAlexander Kozyrev #ifdef RTE_LIBRTE_MLX5_DEBUG 2891771fa900SAdrien Mazarguil { 2892771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 2893771fa900SAdrien Mazarguil 2894af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(eth_dev, &ifname) == 0) 2895a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u ifname is \"%s\"", 28960f99970bSNélio Laranjeiro eth_dev->data->port_id, ifname); 2897771fa900SAdrien Mazarguil else 2898a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u ifname is unknown", 28990f99970bSNélio Laranjeiro eth_dev->data->port_id); 2900771fa900SAdrien Mazarguil } 2901771fa900SAdrien Mazarguil #endif 2902771fa900SAdrien Mazarguil /* Get actual MTU if possible. */ 2903a6d83b6aSNélio Laranjeiro err = mlx5_get_mtu(eth_dev, &priv->mtu); 2904012ad994SShahaf Shuler if (err) { 2905012ad994SShahaf Shuler err = rte_errno; 29069083982cSAdrien Mazarguil goto error; 2907012ad994SShahaf Shuler } 2908a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u MTU is %u", eth_dev->data->port_id, 2909a170a30dSNélio Laranjeiro priv->mtu); 291068128934SAdrien Mazarguil /* Initialize burst functions to prevent crashes before link-up. */ 2911e313ef4cSShahaf Shuler eth_dev->rx_pkt_burst = removed_rx_burst; 2912e313ef4cSShahaf Shuler eth_dev->tx_pkt_burst = removed_tx_burst; 2913771fa900SAdrien Mazarguil eth_dev->dev_ops = &mlx5_dev_ops; 2914272733b5SNélio Laranjeiro /* Register MAC address. */ 2915272733b5SNélio Laranjeiro claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); 2916f87bfa8eSYongseok Koh if (config.vf && config.vf_nl_en) 2917f22442cbSMatan Azrad mlx5_nl_mac_addr_sync(priv->nl_socket_route, 2918f22442cbSMatan Azrad mlx5_ifindex(eth_dev), 2919f22442cbSMatan Azrad eth_dev->data->mac_addrs, 2920f22442cbSMatan Azrad MLX5_MAX_MAC_ADDRESSES); 2921ab612adcSSuanming Mou priv->flows = 0; 2922ab612adcSSuanming Mou priv->ctrl_flows = 0; 29233f373f35SSuanming Mou TAILQ_INIT(&priv->flow_meters); 29243bd26b23SSuanming Mou TAILQ_INIT(&priv->flow_meter_profiles); 29251e3a39f7SXueming Li /* Hint libmlx5 to use PMD allocator for data plane resources */ 29261e3a39f7SXueming Li struct mlx5dv_ctx_allocators alctr = { 29271e3a39f7SXueming Li .alloc = &mlx5_alloc_verbs_buf, 29281e3a39f7SXueming Li .free = &mlx5_free_verbs_buf, 29291e3a39f7SXueming Li .data = priv, 29301e3a39f7SXueming Li }; 293117e19bc4SViacheslav Ovsiienko mlx5_glue->dv_set_context_attr(sh->ctx, 293217e19bc4SViacheslav Ovsiienko MLX5DV_CTX_ATTR_BUF_ALLOCATORS, 29331e3a39f7SXueming Li (void *)((uintptr_t)&alctr)); 2934771fa900SAdrien Mazarguil /* Bring Ethernet device up. */ 2935a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u forcing Ethernet interface up", 29360f99970bSNélio Laranjeiro eth_dev->data->port_id); 29377ba5320bSNélio Laranjeiro mlx5_set_link_up(eth_dev); 2938a85a606cSShahaf Shuler /* 2939a85a606cSShahaf Shuler * Even though the interrupt handler is not installed yet, 2940ae4eb7dcSViacheslav Ovsiienko * interrupts will still trigger on the async_fd from 2941a85a606cSShahaf Shuler * Verbs context returned by ibv_open_device(). 2942a85a606cSShahaf Shuler */ 2943a85a606cSShahaf Shuler mlx5_link_update(eth_dev, 0); 2944e2b4925eSOri Kam #ifdef HAVE_MLX5DV_DR_ESWITCH 2945e2b4925eSOri Kam if (!(config.hca_attr.eswitch_manager && config.dv_flow_en && 2946e2b4925eSOri Kam (switch_info->representor || switch_info->master))) 2947e2b4925eSOri Kam config.dv_esw_en = 0; 2948e2b4925eSOri Kam #else 2949e2b4925eSOri Kam config.dv_esw_en = 0; 2950e2b4925eSOri Kam #endif 295138b4b397SViacheslav Ovsiienko /* Detect minimal data bytes to inline. */ 295238b4b397SViacheslav Ovsiienko mlx5_set_min_inline(spawn, &config); 29537fe24446SShahaf Shuler /* Store device configuration on private structure. */ 29547fe24446SShahaf Shuler priv->config = config; 2955dfedf3e3SViacheslav Ovsiienko /* Create context for virtual machine VLAN workaround. */ 2956dfedf3e3SViacheslav Ovsiienko priv->vmwa_context = mlx5_vlan_vmwa_init(eth_dev, spawn->ifindex); 2957e2b4925eSOri Kam if (config.dv_flow_en) { 2958e2b4925eSOri Kam err = mlx5_alloc_shared_dr(priv); 2959e2b4925eSOri Kam if (err) 2960e2b4925eSOri Kam goto error; 2961792e749eSSuanming Mou /* 2962792e749eSSuanming Mou * RSS id is shared with meter flow id. Meter flow id can only 2963792e749eSSuanming Mou * use the 24 MSB of the register. 2964792e749eSSuanming Mou */ 2965792e749eSSuanming Mou priv->qrss_id_pool = mlx5_flow_id_pool_alloc(UINT32_MAX >> 2966792e749eSSuanming Mou MLX5_MTR_COLOR_BITS); 296771e254bcSViacheslav Ovsiienko if (!priv->qrss_id_pool) { 296871e254bcSViacheslav Ovsiienko DRV_LOG(ERR, "can't create flow id pool"); 296971e254bcSViacheslav Ovsiienko err = ENOMEM; 297071e254bcSViacheslav Ovsiienko goto error; 297171e254bcSViacheslav Ovsiienko } 2972e2b4925eSOri Kam } 297378be8852SNelio Laranjeiro /* Supported Verbs flow priority number detection. */ 29742815702bSNelio Laranjeiro err = mlx5_flow_discover_priorities(eth_dev); 29754fb27c1dSViacheslav Ovsiienko if (err < 0) { 29764fb27c1dSViacheslav Ovsiienko err = -err; 29779083982cSAdrien Mazarguil goto error; 29784fb27c1dSViacheslav Ovsiienko } 29792815702bSNelio Laranjeiro priv->config.flow_prio = err; 29802d241515SViacheslav Ovsiienko if (!priv->config.dv_esw_en && 29812d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 29822d241515SViacheslav Ovsiienko DRV_LOG(WARNING, "metadata mode %u is not supported " 29832d241515SViacheslav Ovsiienko "(no E-Switch)", priv->config.dv_xmeta_en); 29842d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en = MLX5_XMETA_MODE_LEGACY; 29852d241515SViacheslav Ovsiienko } 298639139371SViacheslav Ovsiienko mlx5_set_metadata_mask(eth_dev); 298739139371SViacheslav Ovsiienko if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 298839139371SViacheslav Ovsiienko !priv->sh->dv_regc0_mask) { 298939139371SViacheslav Ovsiienko DRV_LOG(ERR, "metadata mode %u is not supported " 299039139371SViacheslav Ovsiienko "(no metadata reg_c[0] is available)", 299139139371SViacheslav Ovsiienko priv->config.dv_xmeta_en); 299239139371SViacheslav Ovsiienko err = ENOTSUP; 299339139371SViacheslav Ovsiienko goto error; 299439139371SViacheslav Ovsiienko } 2995e7bfa359SBing Zhao /* 2996e7bfa359SBing Zhao * Allocate the buffer for flow creating, just once. 2997e7bfa359SBing Zhao * The allocation must be done before any flow creating. 2998e7bfa359SBing Zhao */ 2999e7bfa359SBing Zhao mlx5_flow_alloc_intermediate(eth_dev); 300039139371SViacheslav Ovsiienko /* Query availibility of metadata reg_c's. */ 300139139371SViacheslav Ovsiienko err = mlx5_flow_discover_mreg_c(eth_dev); 300239139371SViacheslav Ovsiienko if (err < 0) { 300339139371SViacheslav Ovsiienko err = -err; 300439139371SViacheslav Ovsiienko goto error; 300539139371SViacheslav Ovsiienko } 30065e61bcddSViacheslav Ovsiienko if (!mlx5_flow_ext_mreg_supported(eth_dev)) { 30075e61bcddSViacheslav Ovsiienko DRV_LOG(DEBUG, 30085e61bcddSViacheslav Ovsiienko "port %u extensive metadata register is not supported", 30095e61bcddSViacheslav Ovsiienko eth_dev->data->port_id); 30102d241515SViacheslav Ovsiienko if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 30112d241515SViacheslav Ovsiienko DRV_LOG(ERR, "metadata mode %u is not supported " 30122d241515SViacheslav Ovsiienko "(no metadata registers available)", 30132d241515SViacheslav Ovsiienko priv->config.dv_xmeta_en); 30142d241515SViacheslav Ovsiienko err = ENOTSUP; 30152d241515SViacheslav Ovsiienko goto error; 30162d241515SViacheslav Ovsiienko } 30175e61bcddSViacheslav Ovsiienko } 3018dd3c774fSViacheslav Ovsiienko if (priv->config.dv_flow_en && 3019dd3c774fSViacheslav Ovsiienko priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 3020dd3c774fSViacheslav Ovsiienko mlx5_flow_ext_mreg_supported(eth_dev) && 3021dd3c774fSViacheslav Ovsiienko priv->sh->dv_regc0_mask) { 3022dd3c774fSViacheslav Ovsiienko priv->mreg_cp_tbl = mlx5_hlist_create(MLX5_FLOW_MREG_HNAME, 3023dd3c774fSViacheslav Ovsiienko MLX5_FLOW_MREG_HTABLE_SZ); 3024dd3c774fSViacheslav Ovsiienko if (!priv->mreg_cp_tbl) { 3025dd3c774fSViacheslav Ovsiienko err = ENOMEM; 3026dd3c774fSViacheslav Ovsiienko goto error; 3027dd3c774fSViacheslav Ovsiienko } 3028dd3c774fSViacheslav Ovsiienko } 3029f38c5457SAdrien Mazarguil return eth_dev; 30309083982cSAdrien Mazarguil error: 303126c08b97SAdrien Mazarguil if (priv) { 3032dd3c774fSViacheslav Ovsiienko if (priv->mreg_cp_tbl) 3033dd3c774fSViacheslav Ovsiienko mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL); 3034b2177648SViacheslav Ovsiienko if (priv->sh) 3035b2177648SViacheslav Ovsiienko mlx5_free_shared_dr(priv); 303626c08b97SAdrien Mazarguil if (priv->nl_socket_route >= 0) 303726c08b97SAdrien Mazarguil close(priv->nl_socket_route); 303826c08b97SAdrien Mazarguil if (priv->nl_socket_rdma >= 0) 303926c08b97SAdrien Mazarguil close(priv->nl_socket_rdma); 3040dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context) 3041dfedf3e3SViacheslav Ovsiienko mlx5_vlan_vmwa_exit(priv->vmwa_context); 304271e254bcSViacheslav Ovsiienko if (priv->qrss_id_pool) 304371e254bcSViacheslav Ovsiienko mlx5_flow_id_pool_release(priv->qrss_id_pool); 30442b730263SAdrien Mazarguil if (own_domain_id) 30452b730263SAdrien Mazarguil claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 3046771fa900SAdrien Mazarguil rte_free(priv); 3047e16adf08SThomas Monjalon if (eth_dev != NULL) 3048e16adf08SThomas Monjalon eth_dev->data->dev_private = NULL; 304926c08b97SAdrien Mazarguil } 3050e16adf08SThomas Monjalon if (eth_dev != NULL) { 3051e16adf08SThomas Monjalon /* mac_addrs must not be freed alone because part of dev_private */ 3052e16adf08SThomas Monjalon eth_dev->data->mac_addrs = NULL; 3053690de285SRaslan Darawsheh rte_eth_dev_release_port(eth_dev); 3054e16adf08SThomas Monjalon } 305517e19bc4SViacheslav Ovsiienko if (sh) 305617e19bc4SViacheslav Ovsiienko mlx5_free_shared_ibctx(sh); 30578e46d4e1SAlexander Kozyrev MLX5_ASSERT(err > 0); 3058a6d83b6aSNélio Laranjeiro rte_errno = err; 3059f38c5457SAdrien Mazarguil return NULL; 3060f38c5457SAdrien Mazarguil } 3061f38c5457SAdrien Mazarguil 3062116f90adSAdrien Mazarguil /** 3063116f90adSAdrien Mazarguil * Comparison callback to sort device data. 3064116f90adSAdrien Mazarguil * 3065116f90adSAdrien Mazarguil * This is meant to be used with qsort(). 3066116f90adSAdrien Mazarguil * 3067116f90adSAdrien Mazarguil * @param a[in] 3068116f90adSAdrien Mazarguil * Pointer to pointer to first data object. 3069116f90adSAdrien Mazarguil * @param b[in] 3070116f90adSAdrien Mazarguil * Pointer to pointer to second data object. 3071116f90adSAdrien Mazarguil * 3072116f90adSAdrien Mazarguil * @return 3073116f90adSAdrien Mazarguil * 0 if both objects are equal, less than 0 if the first argument is less 3074116f90adSAdrien Mazarguil * than the second, greater than 0 otherwise. 3075116f90adSAdrien Mazarguil */ 3076116f90adSAdrien Mazarguil static int 3077116f90adSAdrien Mazarguil mlx5_dev_spawn_data_cmp(const void *a, const void *b) 3078116f90adSAdrien Mazarguil { 3079116f90adSAdrien Mazarguil const struct mlx5_switch_info *si_a = 3080116f90adSAdrien Mazarguil &((const struct mlx5_dev_spawn_data *)a)->info; 3081116f90adSAdrien Mazarguil const struct mlx5_switch_info *si_b = 3082116f90adSAdrien Mazarguil &((const struct mlx5_dev_spawn_data *)b)->info; 3083116f90adSAdrien Mazarguil int ret; 3084116f90adSAdrien Mazarguil 3085116f90adSAdrien Mazarguil /* Master device first. */ 3086116f90adSAdrien Mazarguil ret = si_b->master - si_a->master; 3087116f90adSAdrien Mazarguil if (ret) 3088116f90adSAdrien Mazarguil return ret; 3089116f90adSAdrien Mazarguil /* Then representor devices. */ 3090116f90adSAdrien Mazarguil ret = si_b->representor - si_a->representor; 3091116f90adSAdrien Mazarguil if (ret) 3092116f90adSAdrien Mazarguil return ret; 3093116f90adSAdrien Mazarguil /* Unidentified devices come last in no specific order. */ 3094116f90adSAdrien Mazarguil if (!si_a->representor) 3095116f90adSAdrien Mazarguil return 0; 3096116f90adSAdrien Mazarguil /* Order representors by name. */ 3097116f90adSAdrien Mazarguil return si_a->port_name - si_b->port_name; 3098116f90adSAdrien Mazarguil } 3099116f90adSAdrien Mazarguil 3100f38c5457SAdrien Mazarguil /** 31012e569a37SViacheslav Ovsiienko * Match PCI information for possible slaves of bonding device. 31022e569a37SViacheslav Ovsiienko * 31032e569a37SViacheslav Ovsiienko * @param[in] ibv_dev 31042e569a37SViacheslav Ovsiienko * Pointer to Infiniband device structure. 31052e569a37SViacheslav Ovsiienko * @param[in] pci_dev 31062e569a37SViacheslav Ovsiienko * Pointer to PCI device structure to match PCI address. 31072e569a37SViacheslav Ovsiienko * @param[in] nl_rdma 31082e569a37SViacheslav Ovsiienko * Netlink RDMA group socket handle. 31092e569a37SViacheslav Ovsiienko * 31102e569a37SViacheslav Ovsiienko * @return 31112e569a37SViacheslav Ovsiienko * negative value if no bonding device found, otherwise 31122e569a37SViacheslav Ovsiienko * positive index of slave PF in bonding. 31132e569a37SViacheslav Ovsiienko */ 31142e569a37SViacheslav Ovsiienko static int 31152e569a37SViacheslav Ovsiienko mlx5_device_bond_pci_match(const struct ibv_device *ibv_dev, 31162e569a37SViacheslav Ovsiienko const struct rte_pci_device *pci_dev, 31172e569a37SViacheslav Ovsiienko int nl_rdma) 31182e569a37SViacheslav Ovsiienko { 31192e569a37SViacheslav Ovsiienko char ifname[IF_NAMESIZE + 1]; 31202e569a37SViacheslav Ovsiienko unsigned int ifindex; 31212e569a37SViacheslav Ovsiienko unsigned int np, i; 31222e569a37SViacheslav Ovsiienko FILE *file = NULL; 31232e569a37SViacheslav Ovsiienko int pf = -1; 31242e569a37SViacheslav Ovsiienko 31252e569a37SViacheslav Ovsiienko /* 31262e569a37SViacheslav Ovsiienko * Try to get master device name. If something goes 31272e569a37SViacheslav Ovsiienko * wrong suppose the lack of kernel support and no 31282e569a37SViacheslav Ovsiienko * bonding devices. 31292e569a37SViacheslav Ovsiienko */ 31302e569a37SViacheslav Ovsiienko if (nl_rdma < 0) 31312e569a37SViacheslav Ovsiienko return -1; 31322e569a37SViacheslav Ovsiienko if (!strstr(ibv_dev->name, "bond")) 31332e569a37SViacheslav Ovsiienko return -1; 31342e569a37SViacheslav Ovsiienko np = mlx5_nl_portnum(nl_rdma, ibv_dev->name); 31352e569a37SViacheslav Ovsiienko if (!np) 31362e569a37SViacheslav Ovsiienko return -1; 31372e569a37SViacheslav Ovsiienko /* 31382e569a37SViacheslav Ovsiienko * The Master device might not be on the predefined 31392e569a37SViacheslav Ovsiienko * port (not on port index 1, it is not garanted), 31402e569a37SViacheslav Ovsiienko * we have to scan all Infiniband device port and 31412e569a37SViacheslav Ovsiienko * find master. 31422e569a37SViacheslav Ovsiienko */ 31432e569a37SViacheslav Ovsiienko for (i = 1; i <= np; ++i) { 31442e569a37SViacheslav Ovsiienko /* Check whether Infiniband port is populated. */ 31452e569a37SViacheslav Ovsiienko ifindex = mlx5_nl_ifindex(nl_rdma, ibv_dev->name, i); 31462e569a37SViacheslav Ovsiienko if (!ifindex) 31472e569a37SViacheslav Ovsiienko continue; 31482e569a37SViacheslav Ovsiienko if (!if_indextoname(ifindex, ifname)) 31492e569a37SViacheslav Ovsiienko continue; 31502e569a37SViacheslav Ovsiienko /* Try to read bonding slave names from sysfs. */ 31512e569a37SViacheslav Ovsiienko MKSTR(slaves, 31522e569a37SViacheslav Ovsiienko "/sys/class/net/%s/master/bonding/slaves", ifname); 31532e569a37SViacheslav Ovsiienko file = fopen(slaves, "r"); 31542e569a37SViacheslav Ovsiienko if (file) 31552e569a37SViacheslav Ovsiienko break; 31562e569a37SViacheslav Ovsiienko } 31572e569a37SViacheslav Ovsiienko if (!file) 31582e569a37SViacheslav Ovsiienko return -1; 31592e569a37SViacheslav Ovsiienko /* Use safe format to check maximal buffer length. */ 31608e46d4e1SAlexander Kozyrev MLX5_ASSERT(atol(RTE_STR(IF_NAMESIZE)) == IF_NAMESIZE); 31612e569a37SViacheslav Ovsiienko while (fscanf(file, "%" RTE_STR(IF_NAMESIZE) "s", ifname) == 1) { 31622e569a37SViacheslav Ovsiienko char tmp_str[IF_NAMESIZE + 32]; 31632e569a37SViacheslav Ovsiienko struct rte_pci_addr pci_addr; 31642e569a37SViacheslav Ovsiienko struct mlx5_switch_info info; 31652e569a37SViacheslav Ovsiienko 31662e569a37SViacheslav Ovsiienko /* Process slave interface names in the loop. */ 31672e569a37SViacheslav Ovsiienko snprintf(tmp_str, sizeof(tmp_str), 31682e569a37SViacheslav Ovsiienko "/sys/class/net/%s", ifname); 31692e569a37SViacheslav Ovsiienko if (mlx5_dev_to_pci_addr(tmp_str, &pci_addr)) { 31702e569a37SViacheslav Ovsiienko DRV_LOG(WARNING, "can not get PCI address" 31712e569a37SViacheslav Ovsiienko " for netdev \"%s\"", ifname); 31722e569a37SViacheslav Ovsiienko continue; 31732e569a37SViacheslav Ovsiienko } 31742e569a37SViacheslav Ovsiienko if (pci_dev->addr.domain != pci_addr.domain || 31752e569a37SViacheslav Ovsiienko pci_dev->addr.bus != pci_addr.bus || 31762e569a37SViacheslav Ovsiienko pci_dev->addr.devid != pci_addr.devid || 31772e569a37SViacheslav Ovsiienko pci_dev->addr.function != pci_addr.function) 31782e569a37SViacheslav Ovsiienko continue; 31792e569a37SViacheslav Ovsiienko /* Slave interface PCI address match found. */ 31802e569a37SViacheslav Ovsiienko fclose(file); 31812e569a37SViacheslav Ovsiienko snprintf(tmp_str, sizeof(tmp_str), 31822e569a37SViacheslav Ovsiienko "/sys/class/net/%s/phys_port_name", ifname); 31832e569a37SViacheslav Ovsiienko file = fopen(tmp_str, "rb"); 31842e569a37SViacheslav Ovsiienko if (!file) 31852e569a37SViacheslav Ovsiienko break; 31862e569a37SViacheslav Ovsiienko info.name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET; 31872e569a37SViacheslav Ovsiienko if (fscanf(file, "%32s", tmp_str) == 1) 31882e569a37SViacheslav Ovsiienko mlx5_translate_port_name(tmp_str, &info); 31892e569a37SViacheslav Ovsiienko if (info.name_type == MLX5_PHYS_PORT_NAME_TYPE_LEGACY || 31902e569a37SViacheslav Ovsiienko info.name_type == MLX5_PHYS_PORT_NAME_TYPE_UPLINK) 31912e569a37SViacheslav Ovsiienko pf = info.port_name; 31922e569a37SViacheslav Ovsiienko break; 31932e569a37SViacheslav Ovsiienko } 31942e569a37SViacheslav Ovsiienko if (file) 31952e569a37SViacheslav Ovsiienko fclose(file); 31962e569a37SViacheslav Ovsiienko return pf; 31972e569a37SViacheslav Ovsiienko } 31982e569a37SViacheslav Ovsiienko 31992e569a37SViacheslav Ovsiienko /** 3200f38c5457SAdrien Mazarguil * DPDK callback to register a PCI device. 3201f38c5457SAdrien Mazarguil * 32022b730263SAdrien Mazarguil * This function spawns Ethernet devices out of a given PCI device. 3203f38c5457SAdrien Mazarguil * 3204f38c5457SAdrien Mazarguil * @param[in] pci_drv 3205f38c5457SAdrien Mazarguil * PCI driver structure (mlx5_driver). 3206f38c5457SAdrien Mazarguil * @param[in] pci_dev 3207f38c5457SAdrien Mazarguil * PCI device information. 3208f38c5457SAdrien Mazarguil * 3209f38c5457SAdrien Mazarguil * @return 3210f38c5457SAdrien Mazarguil * 0 on success, a negative errno value otherwise and rte_errno is set. 3211f38c5457SAdrien Mazarguil */ 3212f38c5457SAdrien Mazarguil static int 3213f38c5457SAdrien Mazarguil mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 3214f38c5457SAdrien Mazarguil struct rte_pci_device *pci_dev) 3215f38c5457SAdrien Mazarguil { 3216f38c5457SAdrien Mazarguil struct ibv_device **ibv_list; 3217ad74bc61SViacheslav Ovsiienko /* 3218ad74bc61SViacheslav Ovsiienko * Number of found IB Devices matching with requested PCI BDF. 3219ad74bc61SViacheslav Ovsiienko * nd != 1 means there are multiple IB devices over the same 3220ad74bc61SViacheslav Ovsiienko * PCI device and we have representors and master. 3221ad74bc61SViacheslav Ovsiienko */ 3222ad74bc61SViacheslav Ovsiienko unsigned int nd = 0; 3223ad74bc61SViacheslav Ovsiienko /* 3224ad74bc61SViacheslav Ovsiienko * Number of found IB device Ports. nd = 1 and np = 1..n means 3225ad74bc61SViacheslav Ovsiienko * we have the single multiport IB device, and there may be 3226ad74bc61SViacheslav Ovsiienko * representors attached to some of found ports. 3227ad74bc61SViacheslav Ovsiienko */ 3228ad74bc61SViacheslav Ovsiienko unsigned int np = 0; 3229ad74bc61SViacheslav Ovsiienko /* 3230ad74bc61SViacheslav Ovsiienko * Number of DPDK ethernet devices to Spawn - either over 3231ad74bc61SViacheslav Ovsiienko * multiple IB devices or multiple ports of single IB device. 3232ad74bc61SViacheslav Ovsiienko * Actually this is the number of iterations to spawn. 3233ad74bc61SViacheslav Ovsiienko */ 3234ad74bc61SViacheslav Ovsiienko unsigned int ns = 0; 32352e569a37SViacheslav Ovsiienko /* 32362e569a37SViacheslav Ovsiienko * Bonding device 32372e569a37SViacheslav Ovsiienko * < 0 - no bonding device (single one) 32382e569a37SViacheslav Ovsiienko * >= 0 - bonding device (value is slave PF index) 32392e569a37SViacheslav Ovsiienko */ 32402e569a37SViacheslav Ovsiienko int bd = -1; 3241a62ec991SViacheslav Ovsiienko struct mlx5_dev_spawn_data *list = NULL; 3242f87bfa8eSYongseok Koh struct mlx5_dev_config dev_config; 3243f38c5457SAdrien Mazarguil int ret; 3244f38c5457SAdrien Mazarguil 3245d768f324SMatan Azrad if (mlx5_class_get(pci_dev->device.devargs) != MLX5_CLASS_NET) { 3246d768f324SMatan Azrad DRV_LOG(DEBUG, "Skip probing - should be probed by other mlx5" 3247d768f324SMatan Azrad " driver."); 3248d768f324SMatan Azrad return 1; 3249d768f324SMatan Azrad } 3250e6cdc54cSXueming Li if (rte_eal_process_type() == RTE_PROC_PRIMARY) 3251e6cdc54cSXueming Li mlx5_pmd_socket_init(); 32527be600c8SYongseok Koh ret = mlx5_init_once(); 32537be600c8SYongseok Koh if (ret) { 32547be600c8SYongseok Koh DRV_LOG(ERR, "unable to init PMD global data: %s", 32557be600c8SYongseok Koh strerror(rte_errno)); 32567be600c8SYongseok Koh return -rte_errno; 32577be600c8SYongseok Koh } 32588e46d4e1SAlexander Kozyrev MLX5_ASSERT(pci_drv == &mlx5_driver); 3259f38c5457SAdrien Mazarguil errno = 0; 3260f38c5457SAdrien Mazarguil ibv_list = mlx5_glue->get_device_list(&ret); 3261f38c5457SAdrien Mazarguil if (!ibv_list) { 3262f38c5457SAdrien Mazarguil rte_errno = errno ? errno : ENOSYS; 3263f38c5457SAdrien Mazarguil DRV_LOG(ERR, "cannot list devices, is ib_uverbs loaded?"); 3264a6d83b6aSNélio Laranjeiro return -rte_errno; 3265a6d83b6aSNélio Laranjeiro } 3266ad74bc61SViacheslav Ovsiienko /* 3267ad74bc61SViacheslav Ovsiienko * First scan the list of all Infiniband devices to find 3268ad74bc61SViacheslav Ovsiienko * matching ones, gathering into the list. 3269ad74bc61SViacheslav Ovsiienko */ 327026c08b97SAdrien Mazarguil struct ibv_device *ibv_match[ret + 1]; 3271a62ec991SViacheslav Ovsiienko int nl_route = mlx5_nl_init(NETLINK_ROUTE); 3272a62ec991SViacheslav Ovsiienko int nl_rdma = mlx5_nl_init(NETLINK_RDMA); 3273ad74bc61SViacheslav Ovsiienko unsigned int i; 327426c08b97SAdrien Mazarguil 3275f38c5457SAdrien Mazarguil while (ret-- > 0) { 3276f38c5457SAdrien Mazarguil struct rte_pci_addr pci_addr; 3277f38c5457SAdrien Mazarguil 3278f38c5457SAdrien Mazarguil DRV_LOG(DEBUG, "checking device \"%s\"", ibv_list[ret]->name); 32792e569a37SViacheslav Ovsiienko bd = mlx5_device_bond_pci_match 32802e569a37SViacheslav Ovsiienko (ibv_list[ret], pci_dev, nl_rdma); 32812e569a37SViacheslav Ovsiienko if (bd >= 0) { 32822e569a37SViacheslav Ovsiienko /* 32832e569a37SViacheslav Ovsiienko * Bonding device detected. Only one match is allowed, 32842e569a37SViacheslav Ovsiienko * the bonding is supported over multi-port IB device, 32852e569a37SViacheslav Ovsiienko * there should be no matches on representor PCI 32862e569a37SViacheslav Ovsiienko * functions or non VF LAG bonding devices with 32872e569a37SViacheslav Ovsiienko * specified address. 32882e569a37SViacheslav Ovsiienko */ 32892e569a37SViacheslav Ovsiienko if (nd) { 32902e569a37SViacheslav Ovsiienko DRV_LOG(ERR, 32912e569a37SViacheslav Ovsiienko "multiple PCI match on bonding device" 32922e569a37SViacheslav Ovsiienko "\"%s\" found", ibv_list[ret]->name); 32932e569a37SViacheslav Ovsiienko rte_errno = ENOENT; 32942e569a37SViacheslav Ovsiienko ret = -rte_errno; 32952e569a37SViacheslav Ovsiienko goto exit; 32962e569a37SViacheslav Ovsiienko } 32972e569a37SViacheslav Ovsiienko DRV_LOG(INFO, "PCI information matches for" 32982e569a37SViacheslav Ovsiienko " slave %d bonding device \"%s\"", 32992e569a37SViacheslav Ovsiienko bd, ibv_list[ret]->name); 33002e569a37SViacheslav Ovsiienko ibv_match[nd++] = ibv_list[ret]; 33012e569a37SViacheslav Ovsiienko break; 33022e569a37SViacheslav Ovsiienko } 33035cf5f710SViacheslav Ovsiienko if (mlx5_dev_to_pci_addr 33045cf5f710SViacheslav Ovsiienko (ibv_list[ret]->ibdev_path, &pci_addr)) 3305f38c5457SAdrien Mazarguil continue; 3306f38c5457SAdrien Mazarguil if (pci_dev->addr.domain != pci_addr.domain || 3307f38c5457SAdrien Mazarguil pci_dev->addr.bus != pci_addr.bus || 3308f38c5457SAdrien Mazarguil pci_dev->addr.devid != pci_addr.devid || 3309f38c5457SAdrien Mazarguil pci_dev->addr.function != pci_addr.function) 3310f38c5457SAdrien Mazarguil continue; 331126c08b97SAdrien Mazarguil DRV_LOG(INFO, "PCI information matches for device \"%s\"", 3312f38c5457SAdrien Mazarguil ibv_list[ret]->name); 3313ad74bc61SViacheslav Ovsiienko ibv_match[nd++] = ibv_list[ret]; 331426c08b97SAdrien Mazarguil } 3315ad74bc61SViacheslav Ovsiienko ibv_match[nd] = NULL; 3316ad74bc61SViacheslav Ovsiienko if (!nd) { 3317ae4eb7dcSViacheslav Ovsiienko /* No device matches, just complain and bail out. */ 3318ad74bc61SViacheslav Ovsiienko DRV_LOG(WARNING, 3319ad74bc61SViacheslav Ovsiienko "no Verbs device matches PCI device " PCI_PRI_FMT "," 3320ad74bc61SViacheslav Ovsiienko " are kernel drivers loaded?", 3321ad74bc61SViacheslav Ovsiienko pci_dev->addr.domain, pci_dev->addr.bus, 3322ad74bc61SViacheslav Ovsiienko pci_dev->addr.devid, pci_dev->addr.function); 3323ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3324ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3325a62ec991SViacheslav Ovsiienko goto exit; 3326ad74bc61SViacheslav Ovsiienko } 3327ad74bc61SViacheslav Ovsiienko if (nd == 1) { 332826c08b97SAdrien Mazarguil /* 3329ad74bc61SViacheslav Ovsiienko * Found single matching device may have multiple ports. 3330ad74bc61SViacheslav Ovsiienko * Each port may be representor, we have to check the port 3331ad74bc61SViacheslav Ovsiienko * number and check the representors existence. 333226c08b97SAdrien Mazarguil */ 3333ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3334ad74bc61SViacheslav Ovsiienko np = mlx5_nl_portnum(nl_rdma, ibv_match[0]->name); 3335ad74bc61SViacheslav Ovsiienko if (!np) 3336ad74bc61SViacheslav Ovsiienko DRV_LOG(WARNING, "can not get IB device \"%s\"" 3337ad74bc61SViacheslav Ovsiienko " ports number", ibv_match[0]->name); 33382e569a37SViacheslav Ovsiienko if (bd >= 0 && !np) { 33392e569a37SViacheslav Ovsiienko DRV_LOG(ERR, "can not get ports" 33402e569a37SViacheslav Ovsiienko " for bonding device"); 33412e569a37SViacheslav Ovsiienko rte_errno = ENOENT; 33422e569a37SViacheslav Ovsiienko ret = -rte_errno; 33432e569a37SViacheslav Ovsiienko goto exit; 33442e569a37SViacheslav Ovsiienko } 3345ad74bc61SViacheslav Ovsiienko } 3346790164ceSViacheslav Ovsiienko #ifndef HAVE_MLX5DV_DR_DEVX_PORT 3347790164ceSViacheslav Ovsiienko if (bd >= 0) { 3348790164ceSViacheslav Ovsiienko /* 3349790164ceSViacheslav Ovsiienko * This may happen if there is VF LAG kernel support and 3350790164ceSViacheslav Ovsiienko * application is compiled with older rdma_core library. 3351790164ceSViacheslav Ovsiienko */ 3352790164ceSViacheslav Ovsiienko DRV_LOG(ERR, 3353790164ceSViacheslav Ovsiienko "No kernel/verbs support for VF LAG bonding found."); 3354790164ceSViacheslav Ovsiienko rte_errno = ENOTSUP; 3355790164ceSViacheslav Ovsiienko ret = -rte_errno; 3356790164ceSViacheslav Ovsiienko goto exit; 3357790164ceSViacheslav Ovsiienko } 3358790164ceSViacheslav Ovsiienko #endif 3359ad74bc61SViacheslav Ovsiienko /* 3360ad74bc61SViacheslav Ovsiienko * Now we can determine the maximal 3361ad74bc61SViacheslav Ovsiienko * amount of devices to be spawned. 3362ad74bc61SViacheslav Ovsiienko */ 3363a62ec991SViacheslav Ovsiienko list = rte_zmalloc("device spawn data", 3364a62ec991SViacheslav Ovsiienko sizeof(struct mlx5_dev_spawn_data) * 3365a62ec991SViacheslav Ovsiienko (np ? np : nd), 3366a62ec991SViacheslav Ovsiienko RTE_CACHE_LINE_SIZE); 3367a62ec991SViacheslav Ovsiienko if (!list) { 3368a62ec991SViacheslav Ovsiienko DRV_LOG(ERR, "spawn data array allocation failure"); 3369a62ec991SViacheslav Ovsiienko rte_errno = ENOMEM; 3370a62ec991SViacheslav Ovsiienko ret = -rte_errno; 3371a62ec991SViacheslav Ovsiienko goto exit; 3372a62ec991SViacheslav Ovsiienko } 33732e569a37SViacheslav Ovsiienko if (bd >= 0 || np > 1) { 3374ad74bc61SViacheslav Ovsiienko /* 3375ae4eb7dcSViacheslav Ovsiienko * Single IB device with multiple ports found, 3376ad74bc61SViacheslav Ovsiienko * it may be E-Switch master device and representors. 3377ad74bc61SViacheslav Ovsiienko * We have to perform identification trough the ports. 3378ad74bc61SViacheslav Ovsiienko */ 33798e46d4e1SAlexander Kozyrev MLX5_ASSERT(nl_rdma >= 0); 33808e46d4e1SAlexander Kozyrev MLX5_ASSERT(ns == 0); 33818e46d4e1SAlexander Kozyrev MLX5_ASSERT(nd == 1); 33828e46d4e1SAlexander Kozyrev MLX5_ASSERT(np); 3383ad74bc61SViacheslav Ovsiienko for (i = 1; i <= np; ++i) { 3384ad74bc61SViacheslav Ovsiienko list[ns].max_port = np; 3385ad74bc61SViacheslav Ovsiienko list[ns].ibv_port = i; 3386ad74bc61SViacheslav Ovsiienko list[ns].ibv_dev = ibv_match[0]; 3387ad74bc61SViacheslav Ovsiienko list[ns].eth_dev = NULL; 3388ab3cffcfSViacheslav Ovsiienko list[ns].pci_dev = pci_dev; 33892e569a37SViacheslav Ovsiienko list[ns].pf_bond = bd; 3390ad74bc61SViacheslav Ovsiienko list[ns].ifindex = mlx5_nl_ifindex 3391ad74bc61SViacheslav Ovsiienko (nl_rdma, list[ns].ibv_dev->name, i); 3392ad74bc61SViacheslav Ovsiienko if (!list[ns].ifindex) { 3393ad74bc61SViacheslav Ovsiienko /* 3394ad74bc61SViacheslav Ovsiienko * No network interface index found for the 3395ad74bc61SViacheslav Ovsiienko * specified port, it means there is no 3396ad74bc61SViacheslav Ovsiienko * representor on this port. It's OK, 3397ad74bc61SViacheslav Ovsiienko * there can be disabled ports, for example 3398ad74bc61SViacheslav Ovsiienko * if sriov_numvfs < sriov_totalvfs. 3399ad74bc61SViacheslav Ovsiienko */ 340026c08b97SAdrien Mazarguil continue; 340126c08b97SAdrien Mazarguil } 3402ad74bc61SViacheslav Ovsiienko ret = -1; 340326c08b97SAdrien Mazarguil if (nl_route >= 0) 3404ad74bc61SViacheslav Ovsiienko ret = mlx5_nl_switch_info 3405ad74bc61SViacheslav Ovsiienko (nl_route, 3406ad74bc61SViacheslav Ovsiienko list[ns].ifindex, 3407ad74bc61SViacheslav Ovsiienko &list[ns].info); 3408ad74bc61SViacheslav Ovsiienko if (ret || (!list[ns].info.representor && 3409ad74bc61SViacheslav Ovsiienko !list[ns].info.master)) { 3410ad74bc61SViacheslav Ovsiienko /* 3411ad74bc61SViacheslav Ovsiienko * We failed to recognize representors with 3412ad74bc61SViacheslav Ovsiienko * Netlink, let's try to perform the task 3413ad74bc61SViacheslav Ovsiienko * with sysfs. 3414ad74bc61SViacheslav Ovsiienko */ 3415ad74bc61SViacheslav Ovsiienko ret = mlx5_sysfs_switch_info 3416ad74bc61SViacheslav Ovsiienko (list[ns].ifindex, 3417ad74bc61SViacheslav Ovsiienko &list[ns].info); 3418ad74bc61SViacheslav Ovsiienko } 34192e569a37SViacheslav Ovsiienko if (!ret && bd >= 0) { 34202e569a37SViacheslav Ovsiienko switch (list[ns].info.name_type) { 34212e569a37SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 34222e569a37SViacheslav Ovsiienko if (list[ns].info.port_name == bd) 34232e569a37SViacheslav Ovsiienko ns++; 34242e569a37SViacheslav Ovsiienko break; 34252e569a37SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 34262e569a37SViacheslav Ovsiienko if (list[ns].info.pf_num == bd) 34272e569a37SViacheslav Ovsiienko ns++; 34282e569a37SViacheslav Ovsiienko break; 34292e569a37SViacheslav Ovsiienko default: 34302e569a37SViacheslav Ovsiienko break; 34312e569a37SViacheslav Ovsiienko } 34322e569a37SViacheslav Ovsiienko continue; 34332e569a37SViacheslav Ovsiienko } 3434ad74bc61SViacheslav Ovsiienko if (!ret && (list[ns].info.representor ^ 3435ad74bc61SViacheslav Ovsiienko list[ns].info.master)) 3436ad74bc61SViacheslav Ovsiienko ns++; 3437ad74bc61SViacheslav Ovsiienko } 3438ad74bc61SViacheslav Ovsiienko if (!ns) { 343926c08b97SAdrien Mazarguil DRV_LOG(ERR, 3440ad74bc61SViacheslav Ovsiienko "unable to recognize master/representors" 3441ad74bc61SViacheslav Ovsiienko " on the IB device with multiple ports"); 3442ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3443ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3444ad74bc61SViacheslav Ovsiienko goto exit; 3445ad74bc61SViacheslav Ovsiienko } 3446ad74bc61SViacheslav Ovsiienko } else { 3447ad74bc61SViacheslav Ovsiienko /* 3448ad74bc61SViacheslav Ovsiienko * The existence of several matching entries (nd > 1) means 3449ad74bc61SViacheslav Ovsiienko * port representors have been instantiated. No existing Verbs 3450ad74bc61SViacheslav Ovsiienko * call nor sysfs entries can tell them apart, this can only 3451ad74bc61SViacheslav Ovsiienko * be done through Netlink calls assuming kernel drivers are 3452ad74bc61SViacheslav Ovsiienko * recent enough to support them. 3453ad74bc61SViacheslav Ovsiienko * 3454ad74bc61SViacheslav Ovsiienko * In the event of identification failure through Netlink, 3455ad74bc61SViacheslav Ovsiienko * try again through sysfs, then: 3456ad74bc61SViacheslav Ovsiienko * 3457ad74bc61SViacheslav Ovsiienko * 1. A single IB device matches (nd == 1) with single 3458ad74bc61SViacheslav Ovsiienko * port (np=0/1) and is not a representor, assume 3459ad74bc61SViacheslav Ovsiienko * no switch support. 3460ad74bc61SViacheslav Ovsiienko * 3461ad74bc61SViacheslav Ovsiienko * 2. Otherwise no safe assumptions can be made; 3462ad74bc61SViacheslav Ovsiienko * complain louder and bail out. 3463ad74bc61SViacheslav Ovsiienko */ 3464ad74bc61SViacheslav Ovsiienko np = 1; 3465ad74bc61SViacheslav Ovsiienko for (i = 0; i != nd; ++i) { 3466ad74bc61SViacheslav Ovsiienko memset(&list[ns].info, 0, sizeof(list[ns].info)); 3467ad74bc61SViacheslav Ovsiienko list[ns].max_port = 1; 3468ad74bc61SViacheslav Ovsiienko list[ns].ibv_port = 1; 3469ad74bc61SViacheslav Ovsiienko list[ns].ibv_dev = ibv_match[i]; 3470ad74bc61SViacheslav Ovsiienko list[ns].eth_dev = NULL; 3471ab3cffcfSViacheslav Ovsiienko list[ns].pci_dev = pci_dev; 34722e569a37SViacheslav Ovsiienko list[ns].pf_bond = -1; 3473ad74bc61SViacheslav Ovsiienko list[ns].ifindex = 0; 3474ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3475ad74bc61SViacheslav Ovsiienko list[ns].ifindex = mlx5_nl_ifindex 3476ad74bc61SViacheslav Ovsiienko (nl_rdma, list[ns].ibv_dev->name, 1); 3477ad74bc61SViacheslav Ovsiienko if (!list[ns].ifindex) { 34789c2bbd04SViacheslav Ovsiienko char ifname[IF_NAMESIZE]; 34799c2bbd04SViacheslav Ovsiienko 3480ad74bc61SViacheslav Ovsiienko /* 34819c2bbd04SViacheslav Ovsiienko * Netlink failed, it may happen with old 34829c2bbd04SViacheslav Ovsiienko * ib_core kernel driver (before 4.16). 34839c2bbd04SViacheslav Ovsiienko * We can assume there is old driver because 34849c2bbd04SViacheslav Ovsiienko * here we are processing single ports IB 34859c2bbd04SViacheslav Ovsiienko * devices. Let's try sysfs to retrieve 34869c2bbd04SViacheslav Ovsiienko * the ifindex. The method works for 34879c2bbd04SViacheslav Ovsiienko * master device only. 34889c2bbd04SViacheslav Ovsiienko */ 34899c2bbd04SViacheslav Ovsiienko if (nd > 1) { 34909c2bbd04SViacheslav Ovsiienko /* 34919c2bbd04SViacheslav Ovsiienko * Multiple devices found, assume 34929c2bbd04SViacheslav Ovsiienko * representors, can not distinguish 34939c2bbd04SViacheslav Ovsiienko * master/representor and retrieve 34949c2bbd04SViacheslav Ovsiienko * ifindex via sysfs. 3495ad74bc61SViacheslav Ovsiienko */ 3496ad74bc61SViacheslav Ovsiienko continue; 3497ad74bc61SViacheslav Ovsiienko } 34989c2bbd04SViacheslav Ovsiienko ret = mlx5_get_master_ifname 34999c2bbd04SViacheslav Ovsiienko (ibv_match[i]->ibdev_path, &ifname); 35009c2bbd04SViacheslav Ovsiienko if (!ret) 35019c2bbd04SViacheslav Ovsiienko list[ns].ifindex = 35029c2bbd04SViacheslav Ovsiienko if_nametoindex(ifname); 35039c2bbd04SViacheslav Ovsiienko if (!list[ns].ifindex) { 35049c2bbd04SViacheslav Ovsiienko /* 35059c2bbd04SViacheslav Ovsiienko * No network interface index found 35069c2bbd04SViacheslav Ovsiienko * for the specified device, it means 35079c2bbd04SViacheslav Ovsiienko * there it is neither representor 35089c2bbd04SViacheslav Ovsiienko * nor master. 35099c2bbd04SViacheslav Ovsiienko */ 35109c2bbd04SViacheslav Ovsiienko continue; 35119c2bbd04SViacheslav Ovsiienko } 35129c2bbd04SViacheslav Ovsiienko } 3513ad74bc61SViacheslav Ovsiienko ret = -1; 3514ad74bc61SViacheslav Ovsiienko if (nl_route >= 0) 3515ad74bc61SViacheslav Ovsiienko ret = mlx5_nl_switch_info 3516ad74bc61SViacheslav Ovsiienko (nl_route, 3517ad74bc61SViacheslav Ovsiienko list[ns].ifindex, 3518ad74bc61SViacheslav Ovsiienko &list[ns].info); 3519ad74bc61SViacheslav Ovsiienko if (ret || (!list[ns].info.representor && 3520ad74bc61SViacheslav Ovsiienko !list[ns].info.master)) { 3521ad74bc61SViacheslav Ovsiienko /* 3522ad74bc61SViacheslav Ovsiienko * We failed to recognize representors with 3523ad74bc61SViacheslav Ovsiienko * Netlink, let's try to perform the task 3524ad74bc61SViacheslav Ovsiienko * with sysfs. 3525ad74bc61SViacheslav Ovsiienko */ 3526ad74bc61SViacheslav Ovsiienko ret = mlx5_sysfs_switch_info 3527ad74bc61SViacheslav Ovsiienko (list[ns].ifindex, 3528ad74bc61SViacheslav Ovsiienko &list[ns].info); 3529ad74bc61SViacheslav Ovsiienko } 3530ad74bc61SViacheslav Ovsiienko if (!ret && (list[ns].info.representor ^ 3531ad74bc61SViacheslav Ovsiienko list[ns].info.master)) { 3532ad74bc61SViacheslav Ovsiienko ns++; 3533ad74bc61SViacheslav Ovsiienko } else if ((nd == 1) && 3534ad74bc61SViacheslav Ovsiienko !list[ns].info.representor && 3535ad74bc61SViacheslav Ovsiienko !list[ns].info.master) { 3536ad74bc61SViacheslav Ovsiienko /* 3537ad74bc61SViacheslav Ovsiienko * Single IB device with 3538ad74bc61SViacheslav Ovsiienko * one physical port and 3539ad74bc61SViacheslav Ovsiienko * attached network device. 3540ad74bc61SViacheslav Ovsiienko * May be SRIOV is not enabled 3541ad74bc61SViacheslav Ovsiienko * or there is no representors. 3542ad74bc61SViacheslav Ovsiienko */ 3543ad74bc61SViacheslav Ovsiienko DRV_LOG(INFO, "no E-Switch support detected"); 3544ad74bc61SViacheslav Ovsiienko ns++; 3545ad74bc61SViacheslav Ovsiienko break; 354626c08b97SAdrien Mazarguil } 3547f38c5457SAdrien Mazarguil } 3548ad74bc61SViacheslav Ovsiienko if (!ns) { 3549ad74bc61SViacheslav Ovsiienko DRV_LOG(ERR, 3550ad74bc61SViacheslav Ovsiienko "unable to recognize master/representors" 3551ad74bc61SViacheslav Ovsiienko " on the multiple IB devices"); 3552ad74bc61SViacheslav Ovsiienko rte_errno = ENOENT; 3553ad74bc61SViacheslav Ovsiienko ret = -rte_errno; 3554ad74bc61SViacheslav Ovsiienko goto exit; 3555ad74bc61SViacheslav Ovsiienko } 3556ad74bc61SViacheslav Ovsiienko } 35578e46d4e1SAlexander Kozyrev MLX5_ASSERT(ns); 3558116f90adSAdrien Mazarguil /* 3559116f90adSAdrien Mazarguil * Sort list to probe devices in natural order for users convenience 3560116f90adSAdrien Mazarguil * (i.e. master first, then representors from lowest to highest ID). 3561116f90adSAdrien Mazarguil */ 3562ad74bc61SViacheslav Ovsiienko qsort(list, ns, sizeof(*list), mlx5_dev_spawn_data_cmp); 3563f87bfa8eSYongseok Koh /* Default configuration. */ 3564f87bfa8eSYongseok Koh dev_config = (struct mlx5_dev_config){ 356578c7a16dSYongseok Koh .hw_padding = 0, 3566f87bfa8eSYongseok Koh .mps = MLX5_ARG_UNSET, 35678409a285SViacheslav Ovsiienko .dbnc = MLX5_ARG_UNSET, 3568f87bfa8eSYongseok Koh .rx_vec_en = 1, 3569505f1fe4SViacheslav Ovsiienko .txq_inline_max = MLX5_ARG_UNSET, 3570505f1fe4SViacheslav Ovsiienko .txq_inline_min = MLX5_ARG_UNSET, 3571505f1fe4SViacheslav Ovsiienko .txq_inline_mpw = MLX5_ARG_UNSET, 3572f87bfa8eSYongseok Koh .txqs_inline = MLX5_ARG_UNSET, 3573f87bfa8eSYongseok Koh .vf_nl_en = 1, 3574dceb5029SYongseok Koh .mr_ext_memseg_en = 1, 3575f87bfa8eSYongseok Koh .mprq = { 3576f87bfa8eSYongseok Koh .enabled = 0, /* Disabled by default. */ 3577ecb16045SAlexander Kozyrev .stride_num_n = 0, 3578ecb16045SAlexander Kozyrev .stride_size_n = 0, 3579f87bfa8eSYongseok Koh .max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN, 3580f87bfa8eSYongseok Koh .min_rxqs_num = MLX5_MPRQ_MIN_RXQS, 3581f87bfa8eSYongseok Koh }, 3582e2b4925eSOri Kam .dv_esw_en = 1, 3583cd4569d2SDekel Peled .dv_flow_en = 1, 35841ad9a3d0SBing Zhao .log_hp_size = MLX5_ARG_UNSET, 3585f87bfa8eSYongseok Koh }; 3586ad74bc61SViacheslav Ovsiienko /* Device specific configuration. */ 3587f38c5457SAdrien Mazarguil switch (pci_dev->id.device_id) { 3588f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 3589f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 3590f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 3591f38c5457SAdrien Mazarguil case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 3592a40b734bSViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF: 3593c930f02cSViacheslav Ovsiienko case PCI_DEVICE_ID_MELLANOX_CONNECTX6VF: 35945fc66630SRaslan Darawsheh case PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF: 3595f87bfa8eSYongseok Koh dev_config.vf = 1; 3596f38c5457SAdrien Mazarguil break; 3597f38c5457SAdrien Mazarguil default: 3598f87bfa8eSYongseok Koh break; 3599f38c5457SAdrien Mazarguil } 3600ad74bc61SViacheslav Ovsiienko for (i = 0; i != ns; ++i) { 36012b730263SAdrien Mazarguil uint32_t restore; 36022b730263SAdrien Mazarguil 3603f87bfa8eSYongseok Koh list[i].eth_dev = mlx5_dev_spawn(&pci_dev->device, 3604ad74bc61SViacheslav Ovsiienko &list[i], 3605ad74bc61SViacheslav Ovsiienko dev_config); 36066de569f5SAdrien Mazarguil if (!list[i].eth_dev) { 3607206254b7SOphir Munk if (rte_errno != EBUSY && rte_errno != EEXIST) 36082b730263SAdrien Mazarguil break; 3609206254b7SOphir Munk /* Device is disabled or already spawned. Ignore it. */ 36106de569f5SAdrien Mazarguil continue; 36116de569f5SAdrien Mazarguil } 3612116f90adSAdrien Mazarguil restore = list[i].eth_dev->data->dev_flags; 3613116f90adSAdrien Mazarguil rte_eth_copy_pci_info(list[i].eth_dev, pci_dev); 36142b730263SAdrien Mazarguil /* Restore non-PCI flags cleared by the above call. */ 3615116f90adSAdrien Mazarguil list[i].eth_dev->data->dev_flags |= restore; 361623242063SMatan Azrad mlx5_dev_interrupt_handler_devx_install(list[i].eth_dev); 3617116f90adSAdrien Mazarguil rte_eth_dev_probing_finish(list[i].eth_dev); 36182b730263SAdrien Mazarguil } 3619ad74bc61SViacheslav Ovsiienko if (i != ns) { 3620f38c5457SAdrien Mazarguil DRV_LOG(ERR, 3621f38c5457SAdrien Mazarguil "probe of PCI device " PCI_PRI_FMT " aborted after" 3622f38c5457SAdrien Mazarguil " encountering an error: %s", 3623f38c5457SAdrien Mazarguil pci_dev->addr.domain, pci_dev->addr.bus, 3624f38c5457SAdrien Mazarguil pci_dev->addr.devid, pci_dev->addr.function, 3625f38c5457SAdrien Mazarguil strerror(rte_errno)); 3626f38c5457SAdrien Mazarguil ret = -rte_errno; 36272b730263SAdrien Mazarguil /* Roll back. */ 36282b730263SAdrien Mazarguil while (i--) { 36296de569f5SAdrien Mazarguil if (!list[i].eth_dev) 36306de569f5SAdrien Mazarguil continue; 3631116f90adSAdrien Mazarguil mlx5_dev_close(list[i].eth_dev); 3632e16adf08SThomas Monjalon /* mac_addrs must not be freed because in dev_private */ 3633e16adf08SThomas Monjalon list[i].eth_dev->data->mac_addrs = NULL; 3634116f90adSAdrien Mazarguil claim_zero(rte_eth_dev_release_port(list[i].eth_dev)); 36352b730263SAdrien Mazarguil } 36362b730263SAdrien Mazarguil /* Restore original error. */ 36372b730263SAdrien Mazarguil rte_errno = -ret; 3638f38c5457SAdrien Mazarguil } else { 3639f38c5457SAdrien Mazarguil ret = 0; 3640f38c5457SAdrien Mazarguil } 3641ad74bc61SViacheslav Ovsiienko exit: 3642ad74bc61SViacheslav Ovsiienko /* 3643ad74bc61SViacheslav Ovsiienko * Do the routine cleanup: 3644ad74bc61SViacheslav Ovsiienko * - close opened Netlink sockets 3645a62ec991SViacheslav Ovsiienko * - free allocated spawn data array 3646ad74bc61SViacheslav Ovsiienko * - free the Infiniband device list 3647ad74bc61SViacheslav Ovsiienko */ 3648ad74bc61SViacheslav Ovsiienko if (nl_rdma >= 0) 3649ad74bc61SViacheslav Ovsiienko close(nl_rdma); 3650ad74bc61SViacheslav Ovsiienko if (nl_route >= 0) 3651ad74bc61SViacheslav Ovsiienko close(nl_route); 3652a62ec991SViacheslav Ovsiienko if (list) 3653a62ec991SViacheslav Ovsiienko rte_free(list); 36548e46d4e1SAlexander Kozyrev MLX5_ASSERT(ibv_list); 3655ad74bc61SViacheslav Ovsiienko mlx5_glue->free_device_list(ibv_list); 3656f38c5457SAdrien Mazarguil return ret; 3657771fa900SAdrien Mazarguil } 3658771fa900SAdrien Mazarguil 3659fbc83412SViacheslav Ovsiienko /** 3660fbc83412SViacheslav Ovsiienko * Look for the ethernet device belonging to mlx5 driver. 3661fbc83412SViacheslav Ovsiienko * 3662fbc83412SViacheslav Ovsiienko * @param[in] port_id 3663fbc83412SViacheslav Ovsiienko * port_id to start looking for device. 3664fbc83412SViacheslav Ovsiienko * @param[in] pci_dev 3665fbc83412SViacheslav Ovsiienko * Pointer to the hint PCI device. When device is being probed 3666fbc83412SViacheslav Ovsiienko * the its siblings (master and preceding representors might 3667fbc83412SViacheslav Ovsiienko * not have assigned driver yet (because the mlx5_pci_probe() 3668fbc83412SViacheslav Ovsiienko * is not completed yet, for this case match on hint PCI 3669fbc83412SViacheslav Ovsiienko * device may be used to detect sibling device. 3670fbc83412SViacheslav Ovsiienko * 3671fbc83412SViacheslav Ovsiienko * @return 3672fbc83412SViacheslav Ovsiienko * port_id of found device, RTE_MAX_ETHPORT if not found. 3673fbc83412SViacheslav Ovsiienko */ 3674f7e95215SViacheslav Ovsiienko uint16_t 3675fbc83412SViacheslav Ovsiienko mlx5_eth_find_next(uint16_t port_id, struct rte_pci_device *pci_dev) 3676f7e95215SViacheslav Ovsiienko { 3677f7e95215SViacheslav Ovsiienko while (port_id < RTE_MAX_ETHPORTS) { 3678f7e95215SViacheslav Ovsiienko struct rte_eth_dev *dev = &rte_eth_devices[port_id]; 3679f7e95215SViacheslav Ovsiienko 3680f7e95215SViacheslav Ovsiienko if (dev->state != RTE_ETH_DEV_UNUSED && 3681f7e95215SViacheslav Ovsiienko dev->device && 3682fbc83412SViacheslav Ovsiienko (dev->device == &pci_dev->device || 3683fbc83412SViacheslav Ovsiienko (dev->device->driver && 3684f7e95215SViacheslav Ovsiienko dev->device->driver->name && 3685fbc83412SViacheslav Ovsiienko !strcmp(dev->device->driver->name, MLX5_DRIVER_NAME)))) 3686f7e95215SViacheslav Ovsiienko break; 3687f7e95215SViacheslav Ovsiienko port_id++; 3688f7e95215SViacheslav Ovsiienko } 3689f7e95215SViacheslav Ovsiienko if (port_id >= RTE_MAX_ETHPORTS) 3690f7e95215SViacheslav Ovsiienko return RTE_MAX_ETHPORTS; 3691f7e95215SViacheslav Ovsiienko return port_id; 3692f7e95215SViacheslav Ovsiienko } 3693f7e95215SViacheslav Ovsiienko 36943a820742SOphir Munk /** 36953a820742SOphir Munk * DPDK callback to remove a PCI device. 36963a820742SOphir Munk * 36973a820742SOphir Munk * This function removes all Ethernet devices belong to a given PCI device. 36983a820742SOphir Munk * 36993a820742SOphir Munk * @param[in] pci_dev 37003a820742SOphir Munk * Pointer to the PCI device. 37013a820742SOphir Munk * 37023a820742SOphir Munk * @return 37033a820742SOphir Munk * 0 on success, the function cannot fail. 37043a820742SOphir Munk */ 37053a820742SOphir Munk static int 37063a820742SOphir Munk mlx5_pci_remove(struct rte_pci_device *pci_dev) 37073a820742SOphir Munk { 37083a820742SOphir Munk uint16_t port_id; 37093a820742SOphir Munk 37105294b800SThomas Monjalon RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) 37113a820742SOphir Munk rte_eth_dev_close(port_id); 37123a820742SOphir Munk return 0; 37133a820742SOphir Munk } 37143a820742SOphir Munk 3715771fa900SAdrien Mazarguil static const struct rte_pci_id mlx5_pci_id_map[] = { 3716771fa900SAdrien Mazarguil { 37171d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37181d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4) 3719771fa900SAdrien Mazarguil }, 3720771fa900SAdrien Mazarguil { 37211d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37221d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) 3723771fa900SAdrien Mazarguil }, 3724771fa900SAdrien Mazarguil { 37251d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37261d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LX) 3727771fa900SAdrien Mazarguil }, 3728771fa900SAdrien Mazarguil { 37291d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37301d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) 3731771fa900SAdrien Mazarguil }, 3732771fa900SAdrien Mazarguil { 3733528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3734528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5) 3735528a9fbeSYongseok Koh }, 3736528a9fbeSYongseok Koh { 3737528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3738528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) 3739528a9fbeSYongseok Koh }, 3740528a9fbeSYongseok Koh { 3741528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3742528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EX) 3743528a9fbeSYongseok Koh }, 3744528a9fbeSYongseok Koh { 3745528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3746528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF) 3747528a9fbeSYongseok Koh }, 3748528a9fbeSYongseok Koh { 3749dd3331c6SShahaf Shuler RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3750dd3331c6SShahaf Shuler PCI_DEVICE_ID_MELLANOX_CONNECTX5BF) 3751dd3331c6SShahaf Shuler }, 3752dd3331c6SShahaf Shuler { 3753c322c0e5SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3754c322c0e5SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF) 3755c322c0e5SOri Kam }, 3756c322c0e5SOri Kam { 3757f0354d84SWisam Jaddo RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3758f0354d84SWisam Jaddo PCI_DEVICE_ID_MELLANOX_CONNECTX6) 3759f0354d84SWisam Jaddo }, 3760f0354d84SWisam Jaddo { 3761f0354d84SWisam Jaddo RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3762f0354d84SWisam Jaddo PCI_DEVICE_ID_MELLANOX_CONNECTX6VF) 3763f0354d84SWisam Jaddo }, 3764f0354d84SWisam Jaddo { 37655fc66630SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37665fc66630SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DX) 37675fc66630SRaslan Darawsheh }, 37685fc66630SRaslan Darawsheh { 37695fc66630SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 37705fc66630SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF) 37715fc66630SRaslan Darawsheh }, 37725fc66630SRaslan Darawsheh { 377358b4a2b1SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 377458b4a2b1SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 377558b4a2b1SRaslan Darawsheh }, 377658b4a2b1SRaslan Darawsheh { 3777771fa900SAdrien Mazarguil .vendor_id = 0 3778771fa900SAdrien Mazarguil } 3779771fa900SAdrien Mazarguil }; 3780771fa900SAdrien Mazarguil 3781fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver = { 37822f3193cfSJan Viktorin .driver = { 37832f3193cfSJan Viktorin .name = MLX5_DRIVER_NAME 37842f3193cfSJan Viktorin }, 3785771fa900SAdrien Mazarguil .id_table = mlx5_pci_id_map, 3786af424af8SShreyansh Jain .probe = mlx5_pci_probe, 37873a820742SOphir Munk .remove = mlx5_pci_remove, 3788989e999dSShahaf Shuler .dma_map = mlx5_dma_map, 3789989e999dSShahaf Shuler .dma_unmap = mlx5_dma_unmap, 379069c06d0eSYongseok Koh .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_INTR_RMV | 3791b76fafb1SDavid Marchand RTE_PCI_DRV_PROBE_AGAIN, 3792771fa900SAdrien Mazarguil }; 3793771fa900SAdrien Mazarguil 3794771fa900SAdrien Mazarguil /** 3795771fa900SAdrien Mazarguil * Driver initialization routine. 3796771fa900SAdrien Mazarguil */ 3797f8e99896SThomas Monjalon RTE_INIT(rte_mlx5_pmd_init) 3798771fa900SAdrien Mazarguil { 37993d96644aSStephen Hemminger /* Initialize driver log type. */ 38003d96644aSStephen Hemminger mlx5_logtype = rte_log_register("pmd.net.mlx5"); 38013d96644aSStephen Hemminger if (mlx5_logtype >= 0) 38023d96644aSStephen Hemminger rte_log_set_level(mlx5_logtype, RTE_LOG_NOTICE); 38033d96644aSStephen Hemminger 38045f8ba81cSXueming Li /* Build the static tables for Verbs conversion. */ 3805ea16068cSYongseok Koh mlx5_set_ptype_table(); 38065f8ba81cSXueming Li mlx5_set_cksum_table(); 38075f8ba81cSXueming Li mlx5_set_swp_types_table(); 38087b4f1e6bSMatan Azrad if (mlx5_glue) 38093dcfe039SThomas Monjalon rte_pci_register(&mlx5_driver); 3810771fa900SAdrien Mazarguil } 3811771fa900SAdrien Mazarguil 381201f19227SShreyansh Jain RTE_PMD_EXPORT_NAME(net_mlx5, __COUNTER__); 381301f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_mlx5, mlx5_pci_id_map); 38140880c401SOlivier Matz RTE_PMD_REGISTER_KMOD_DEP(net_mlx5, "* ib_uverbs & mlx5_core & mlx5_ib"); 3815