1771fa900SAdrien Mazarguil /*- 2771fa900SAdrien Mazarguil * BSD LICENSE 3771fa900SAdrien Mazarguil * 4771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 5771fa900SAdrien Mazarguil * Copyright 2015 Mellanox. 6771fa900SAdrien Mazarguil * 7771fa900SAdrien Mazarguil * Redistribution and use in source and binary forms, with or without 8771fa900SAdrien Mazarguil * modification, are permitted provided that the following conditions 9771fa900SAdrien Mazarguil * are met: 10771fa900SAdrien Mazarguil * 11771fa900SAdrien Mazarguil * * Redistributions of source code must retain the above copyright 12771fa900SAdrien Mazarguil * notice, this list of conditions and the following disclaimer. 13771fa900SAdrien Mazarguil * * Redistributions in binary form must reproduce the above copyright 14771fa900SAdrien Mazarguil * notice, this list of conditions and the following disclaimer in 15771fa900SAdrien Mazarguil * the documentation and/or other materials provided with the 16771fa900SAdrien Mazarguil * distribution. 17771fa900SAdrien Mazarguil * * Neither the name of 6WIND S.A. nor the names of its 18771fa900SAdrien Mazarguil * contributors may be used to endorse or promote products derived 19771fa900SAdrien Mazarguil * from this software without specific prior written permission. 20771fa900SAdrien Mazarguil * 21771fa900SAdrien Mazarguil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22771fa900SAdrien Mazarguil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23771fa900SAdrien Mazarguil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24771fa900SAdrien Mazarguil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25771fa900SAdrien Mazarguil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26771fa900SAdrien Mazarguil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27771fa900SAdrien Mazarguil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28771fa900SAdrien Mazarguil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29771fa900SAdrien Mazarguil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30771fa900SAdrien Mazarguil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31771fa900SAdrien Mazarguil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32771fa900SAdrien Mazarguil */ 33771fa900SAdrien Mazarguil 34771fa900SAdrien Mazarguil #include <stddef.h> 35771fa900SAdrien Mazarguil #include <unistd.h> 36771fa900SAdrien Mazarguil #include <string.h> 37771fa900SAdrien Mazarguil #include <assert.h> 38771fa900SAdrien Mazarguil #include <stdint.h> 39771fa900SAdrien Mazarguil #include <stdlib.h> 40e72dd09bSNélio Laranjeiro #include <errno.h> 41771fa900SAdrien Mazarguil #include <net/if.h> 42771fa900SAdrien Mazarguil 43771fa900SAdrien Mazarguil /* Verbs header. */ 44771fa900SAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 45771fa900SAdrien Mazarguil #ifdef PEDANTIC 46fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 47771fa900SAdrien Mazarguil #endif 48771fa900SAdrien Mazarguil #include <infiniband/verbs.h> 49771fa900SAdrien Mazarguil #ifdef PEDANTIC 50fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 51771fa900SAdrien Mazarguil #endif 52771fa900SAdrien Mazarguil 53771fa900SAdrien Mazarguil #include <rte_malloc.h> 54ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 55fdf91e0fSJan Blunck #include <rte_ethdev_pci.h> 56771fa900SAdrien Mazarguil #include <rte_pci.h> 57c752998bSGaetan Rivet #include <rte_bus_pci.h> 58771fa900SAdrien Mazarguil #include <rte_common.h> 59e72dd09bSNélio Laranjeiro #include <rte_kvargs.h> 60771fa900SAdrien Mazarguil 61771fa900SAdrien Mazarguil #include "mlx5.h" 62771fa900SAdrien Mazarguil #include "mlx5_utils.h" 632e22920bSAdrien Mazarguil #include "mlx5_rxtx.h" 64771fa900SAdrien Mazarguil #include "mlx5_autoconf.h" 6513d57bd5SAdrien Mazarguil #include "mlx5_defs.h" 66771fa900SAdrien Mazarguil 6799c12dccSNélio Laranjeiro /* Device parameter to enable RX completion queue compression. */ 6899c12dccSNélio Laranjeiro #define MLX5_RXQ_CQE_COMP_EN "rxq_cqe_comp_en" 6999c12dccSNélio Laranjeiro 702a66cf37SYaacov Hazan /* Device parameter to configure inline send. */ 712a66cf37SYaacov Hazan #define MLX5_TXQ_INLINE "txq_inline" 722a66cf37SYaacov Hazan 732a66cf37SYaacov Hazan /* 742a66cf37SYaacov Hazan * Device parameter to configure the number of TX queues threshold for 752a66cf37SYaacov Hazan * enabling inline send. 762a66cf37SYaacov Hazan */ 772a66cf37SYaacov Hazan #define MLX5_TXQS_MIN_INLINE "txqs_min_inline" 782a66cf37SYaacov Hazan 79230189d9SNélio Laranjeiro /* Device parameter to enable multi-packet send WQEs. */ 80230189d9SNélio Laranjeiro #define MLX5_TXQ_MPW_EN "txq_mpw_en" 81230189d9SNélio Laranjeiro 826ce84bd8SYongseok Koh /* Device parameter to include 2 dsegs in the title WQEBB. */ 836ce84bd8SYongseok Koh #define MLX5_TXQ_MPW_HDR_DSEG_EN "txq_mpw_hdr_dseg_en" 846ce84bd8SYongseok Koh 856ce84bd8SYongseok Koh /* Device parameter to limit the size of inlining packet. */ 866ce84bd8SYongseok Koh #define MLX5_TXQ_MAX_INLINE_LEN "txq_max_inline_len" 876ce84bd8SYongseok Koh 885644d5b9SNelio Laranjeiro /* Device parameter to enable hardware Tx vector. */ 895644d5b9SNelio Laranjeiro #define MLX5_TX_VEC_EN "tx_vec_en" 905644d5b9SNelio Laranjeiro 915644d5b9SNelio Laranjeiro /* Device parameter to enable hardware Rx vector. */ 925644d5b9SNelio Laranjeiro #define MLX5_RX_VEC_EN "rx_vec_en" 935644d5b9SNelio Laranjeiro 9443e9d979SShachar Beiser #ifndef HAVE_IBV_MLX5_MOD_MPW 9543e9d979SShachar Beiser #define MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED (1 << 2) 9643e9d979SShachar Beiser #define MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW (1 << 3) 9743e9d979SShachar Beiser #endif 9843e9d979SShachar Beiser 99523f5a74SYongseok Koh #ifndef HAVE_IBV_MLX5_MOD_CQE_128B_COMP 100523f5a74SYongseok Koh #define MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP (1 << 4) 101523f5a74SYongseok Koh #endif 102523f5a74SYongseok Koh 103771fa900SAdrien Mazarguil /** 1044d803a72SOlga Shern * Retrieve integer value from environment variable. 1054d803a72SOlga Shern * 1064d803a72SOlga Shern * @param[in] name 1074d803a72SOlga Shern * Environment variable name. 1084d803a72SOlga Shern * 1094d803a72SOlga Shern * @return 1104d803a72SOlga Shern * Integer value, 0 if the variable is not set. 1114d803a72SOlga Shern */ 1124d803a72SOlga Shern int 1134d803a72SOlga Shern mlx5_getenv_int(const char *name) 1144d803a72SOlga Shern { 1154d803a72SOlga Shern const char *val = getenv(name); 1164d803a72SOlga Shern 1174d803a72SOlga Shern if (val == NULL) 1184d803a72SOlga Shern return 0; 1194d803a72SOlga Shern return atoi(val); 1204d803a72SOlga Shern } 1214d803a72SOlga Shern 1224d803a72SOlga Shern /** 1231e3a39f7SXueming Li * Verbs callback to allocate a memory. This function should allocate the space 1241e3a39f7SXueming Li * according to the size provided residing inside a huge page. 1251e3a39f7SXueming Li * Please note that all allocation must respect the alignment from libmlx5 1261e3a39f7SXueming Li * (i.e. currently sysconf(_SC_PAGESIZE)). 1271e3a39f7SXueming Li * 1281e3a39f7SXueming Li * @param[in] size 1291e3a39f7SXueming Li * The size in bytes of the memory to allocate. 1301e3a39f7SXueming Li * @param[in] data 1311e3a39f7SXueming Li * A pointer to the callback data. 1321e3a39f7SXueming Li * 1331e3a39f7SXueming Li * @return 1341e3a39f7SXueming Li * a pointer to the allocate space. 1351e3a39f7SXueming Li */ 1361e3a39f7SXueming Li static void * 1371e3a39f7SXueming Li mlx5_alloc_verbs_buf(size_t size, void *data) 1381e3a39f7SXueming Li { 1391e3a39f7SXueming Li struct priv *priv = data; 1401e3a39f7SXueming Li void *ret; 1411e3a39f7SXueming Li size_t alignment = sysconf(_SC_PAGESIZE); 142*d10b09dbSOlivier Matz unsigned int socket = SOCKET_ID_ANY; 1431e3a39f7SXueming Li 144*d10b09dbSOlivier Matz if (priv->verbs_alloc_ctx.type == MLX5_VERBS_ALLOC_TYPE_TX_QUEUE) { 145*d10b09dbSOlivier Matz const struct mlx5_txq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 146*d10b09dbSOlivier Matz 147*d10b09dbSOlivier Matz socket = ctrl->socket; 148*d10b09dbSOlivier Matz } else if (priv->verbs_alloc_ctx.type == 149*d10b09dbSOlivier Matz MLX5_VERBS_ALLOC_TYPE_RX_QUEUE) { 150*d10b09dbSOlivier Matz const struct mlx5_rxq_ctrl *ctrl = priv->verbs_alloc_ctx.obj; 151*d10b09dbSOlivier Matz 152*d10b09dbSOlivier Matz socket = ctrl->socket; 153*d10b09dbSOlivier Matz } 1541e3a39f7SXueming Li assert(data != NULL); 155*d10b09dbSOlivier Matz ret = rte_malloc_socket(__func__, size, alignment, socket); 1561e3a39f7SXueming Li DEBUG("Extern alloc size: %lu, align: %lu: %p", size, alignment, ret); 1571e3a39f7SXueming Li return ret; 1581e3a39f7SXueming Li } 1591e3a39f7SXueming Li 1601e3a39f7SXueming Li /** 1611e3a39f7SXueming Li * Verbs callback to free a memory. 1621e3a39f7SXueming Li * 1631e3a39f7SXueming Li * @param[in] ptr 1641e3a39f7SXueming Li * A pointer to the memory to free. 1651e3a39f7SXueming Li * @param[in] data 1661e3a39f7SXueming Li * A pointer to the callback data. 1671e3a39f7SXueming Li */ 1681e3a39f7SXueming Li static void 1691e3a39f7SXueming Li mlx5_free_verbs_buf(void *ptr, void *data __rte_unused) 1701e3a39f7SXueming Li { 1711e3a39f7SXueming Li assert(data != NULL); 1721e3a39f7SXueming Li DEBUG("Extern free request: %p", ptr); 1731e3a39f7SXueming Li rte_free(ptr); 1741e3a39f7SXueming Li } 1751e3a39f7SXueming Li 1761e3a39f7SXueming Li /** 177771fa900SAdrien Mazarguil * DPDK callback to close the device. 178771fa900SAdrien Mazarguil * 179771fa900SAdrien Mazarguil * Destroy all queues and objects, free memory. 180771fa900SAdrien Mazarguil * 181771fa900SAdrien Mazarguil * @param dev 182771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 183771fa900SAdrien Mazarguil */ 184771fa900SAdrien Mazarguil static void 185771fa900SAdrien Mazarguil mlx5_dev_close(struct rte_eth_dev *dev) 186771fa900SAdrien Mazarguil { 18701d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 1882e22920bSAdrien Mazarguil unsigned int i; 1896af6b973SNélio Laranjeiro int ret; 190771fa900SAdrien Mazarguil 191771fa900SAdrien Mazarguil priv_lock(priv); 192771fa900SAdrien Mazarguil DEBUG("%p: closing device \"%s\"", 193771fa900SAdrien Mazarguil (void *)dev, 194771fa900SAdrien Mazarguil ((priv->ctx != NULL) ? priv->ctx->device->name : "")); 195ecc1c29dSAdrien Mazarguil /* In case mlx5_dev_stop() has not been called. */ 196198a3c33SNelio Laranjeiro priv_dev_interrupt_handler_uninstall(priv, dev); 197272733b5SNélio Laranjeiro priv_dev_traffic_disable(priv, dev); 1982e22920bSAdrien Mazarguil /* Prevent crashes when queues are still in use. */ 1992e22920bSAdrien Mazarguil dev->rx_pkt_burst = removed_rx_burst; 2002e22920bSAdrien Mazarguil dev->tx_pkt_burst = removed_tx_burst; 2012e22920bSAdrien Mazarguil if (priv->rxqs != NULL) { 2022e22920bSAdrien Mazarguil /* XXX race condition if mlx5_rx_burst() is still running. */ 2032e22920bSAdrien Mazarguil usleep(1000); 204a1366b1aSNélio Laranjeiro for (i = 0; (i != priv->rxqs_n); ++i) 205a1366b1aSNélio Laranjeiro mlx5_priv_rxq_release(priv, i); 2062e22920bSAdrien Mazarguil priv->rxqs_n = 0; 2072e22920bSAdrien Mazarguil priv->rxqs = NULL; 2082e22920bSAdrien Mazarguil } 2092e22920bSAdrien Mazarguil if (priv->txqs != NULL) { 2102e22920bSAdrien Mazarguil /* XXX race condition if mlx5_tx_burst() is still running. */ 2112e22920bSAdrien Mazarguil usleep(1000); 2126e78005aSNélio Laranjeiro for (i = 0; (i != priv->txqs_n); ++i) 2136e78005aSNélio Laranjeiro mlx5_priv_txq_release(priv, i); 2142e22920bSAdrien Mazarguil priv->txqs_n = 0; 2152e22920bSAdrien Mazarguil priv->txqs = NULL; 2162e22920bSAdrien Mazarguil } 217771fa900SAdrien Mazarguil if (priv->pd != NULL) { 218771fa900SAdrien Mazarguil assert(priv->ctx != NULL); 219771fa900SAdrien Mazarguil claim_zero(ibv_dealloc_pd(priv->pd)); 220771fa900SAdrien Mazarguil claim_zero(ibv_close_device(priv->ctx)); 221771fa900SAdrien Mazarguil } else 222771fa900SAdrien Mazarguil assert(priv->ctx == NULL); 22329c1d8bbSNélio Laranjeiro if (priv->rss_conf.rss_key != NULL) 22429c1d8bbSNélio Laranjeiro rte_free(priv->rss_conf.rss_key); 225634efbc2SNelio Laranjeiro if (priv->reta_idx != NULL) 226634efbc2SNelio Laranjeiro rte_free(priv->reta_idx); 227f8b9a3baSXueming Li priv_socket_uninit(priv); 228f5479b68SNélio Laranjeiro ret = mlx5_priv_hrxq_ibv_verify(priv); 229f5479b68SNélio Laranjeiro if (ret) 230f5479b68SNélio Laranjeiro WARN("%p: some Hash Rx queue still remain", (void *)priv); 2314c7a0f5fSNélio Laranjeiro ret = mlx5_priv_ind_table_ibv_verify(priv); 2324c7a0f5fSNélio Laranjeiro if (ret) 2334c7a0f5fSNélio Laranjeiro WARN("%p: some Indirection table still remain", (void *)priv); 23409cb5b58SNélio Laranjeiro ret = mlx5_priv_rxq_ibv_verify(priv); 23509cb5b58SNélio Laranjeiro if (ret) 23609cb5b58SNélio Laranjeiro WARN("%p: some Verbs Rx queue still remain", (void *)priv); 237a1366b1aSNélio Laranjeiro ret = mlx5_priv_rxq_verify(priv); 238a1366b1aSNélio Laranjeiro if (ret) 239a1366b1aSNélio Laranjeiro WARN("%p: some Rx Queues still remain", (void *)priv); 240faf2667fSNélio Laranjeiro ret = mlx5_priv_txq_ibv_verify(priv); 241faf2667fSNélio Laranjeiro if (ret) 242faf2667fSNélio Laranjeiro WARN("%p: some Verbs Tx queue still remain", (void *)priv); 2436e78005aSNélio Laranjeiro ret = mlx5_priv_txq_verify(priv); 2446e78005aSNélio Laranjeiro if (ret) 2456e78005aSNélio Laranjeiro WARN("%p: some Tx Queues still remain", (void *)priv); 2466af6b973SNélio Laranjeiro ret = priv_flow_verify(priv); 2476af6b973SNélio Laranjeiro if (ret) 2486af6b973SNélio Laranjeiro WARN("%p: some flows still remain", (void *)priv); 249f8fb87d5SNélio Laranjeiro ret = priv_mr_verify(priv); 250f8fb87d5SNélio Laranjeiro if (ret) 251f8fb87d5SNélio Laranjeiro WARN("%p: some Memory Region still remain", (void *)priv); 252771fa900SAdrien Mazarguil priv_unlock(priv); 253771fa900SAdrien Mazarguil memset(priv, 0, sizeof(*priv)); 254771fa900SAdrien Mazarguil } 255771fa900SAdrien Mazarguil 2560887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops = { 257e60fbd5bSAdrien Mazarguil .dev_configure = mlx5_dev_configure, 258e60fbd5bSAdrien Mazarguil .dev_start = mlx5_dev_start, 259e60fbd5bSAdrien Mazarguil .dev_stop = mlx5_dev_stop, 26062072098SOr Ami .dev_set_link_down = mlx5_set_link_down, 26162072098SOr Ami .dev_set_link_up = mlx5_set_link_up, 262771fa900SAdrien Mazarguil .dev_close = mlx5_dev_close, 2631bdbe1afSAdrien Mazarguil .promiscuous_enable = mlx5_promiscuous_enable, 2641bdbe1afSAdrien Mazarguil .promiscuous_disable = mlx5_promiscuous_disable, 2651bdbe1afSAdrien Mazarguil .allmulticast_enable = mlx5_allmulticast_enable, 2661bdbe1afSAdrien Mazarguil .allmulticast_disable = mlx5_allmulticast_disable, 267cb8faed7SAdrien Mazarguil .link_update = mlx5_link_update, 26887011737SAdrien Mazarguil .stats_get = mlx5_stats_get, 26987011737SAdrien Mazarguil .stats_reset = mlx5_stats_reset, 270a4193ae3SShahaf Shuler .xstats_get = mlx5_xstats_get, 271a4193ae3SShahaf Shuler .xstats_reset = mlx5_xstats_reset, 272a4193ae3SShahaf Shuler .xstats_get_names = mlx5_xstats_get_names, 273e60fbd5bSAdrien Mazarguil .dev_infos_get = mlx5_dev_infos_get, 27478a38edfSJianfeng Tan .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 275e9086978SAdrien Mazarguil .vlan_filter_set = mlx5_vlan_filter_set, 2762e22920bSAdrien Mazarguil .rx_queue_setup = mlx5_rx_queue_setup, 2772e22920bSAdrien Mazarguil .tx_queue_setup = mlx5_tx_queue_setup, 2782e22920bSAdrien Mazarguil .rx_queue_release = mlx5_rx_queue_release, 2792e22920bSAdrien Mazarguil .tx_queue_release = mlx5_tx_queue_release, 28002d75430SAdrien Mazarguil .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 28102d75430SAdrien Mazarguil .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 2823318aef7SAdrien Mazarguil .mac_addr_remove = mlx5_mac_addr_remove, 2833318aef7SAdrien Mazarguil .mac_addr_add = mlx5_mac_addr_add, 28486977fccSDavid Marchand .mac_addr_set = mlx5_mac_addr_set, 285cf37ca95SAdrien Mazarguil .mtu_set = mlx5_dev_set_mtu, 286f3db9489SYaacov Hazan .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 287f3db9489SYaacov Hazan .vlan_offload_set = mlx5_vlan_offload_set, 288634efbc2SNelio Laranjeiro .reta_update = mlx5_dev_rss_reta_update, 289634efbc2SNelio Laranjeiro .reta_query = mlx5_dev_rss_reta_query, 2902f97422eSNelio Laranjeiro .rss_hash_update = mlx5_rss_hash_update, 2912f97422eSNelio Laranjeiro .rss_hash_conf_get = mlx5_rss_hash_conf_get, 29276f5c99eSYaacov Hazan .filter_ctrl = mlx5_dev_filter_ctrl, 2938788fec1SOlivier Matz .rx_descriptor_status = mlx5_rx_descriptor_status, 2948788fec1SOlivier Matz .tx_descriptor_status = mlx5_tx_descriptor_status, 2953c7d44afSShahaf Shuler .rx_queue_intr_enable = mlx5_rx_intr_enable, 2963c7d44afSShahaf Shuler .rx_queue_intr_disable = mlx5_rx_intr_disable, 297d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 298771fa900SAdrien Mazarguil }; 299771fa900SAdrien Mazarguil 30087ec44ceSXueming Li static const struct eth_dev_ops mlx5_dev_sec_ops = { 30187ec44ceSXueming Li .stats_get = mlx5_stats_get, 30287ec44ceSXueming Li .stats_reset = mlx5_stats_reset, 30387ec44ceSXueming Li .xstats_get = mlx5_xstats_get, 30487ec44ceSXueming Li .xstats_reset = mlx5_xstats_reset, 30587ec44ceSXueming Li .xstats_get_names = mlx5_xstats_get_names, 30687ec44ceSXueming Li .dev_infos_get = mlx5_dev_infos_get, 30787ec44ceSXueming Li .rx_descriptor_status = mlx5_rx_descriptor_status, 30887ec44ceSXueming Li .tx_descriptor_status = mlx5_tx_descriptor_status, 30987ec44ceSXueming Li }; 31087ec44ceSXueming Li 3110887aa7fSNélio Laranjeiro /* Available operators in flow isolated mode. */ 3120887aa7fSNélio Laranjeiro const struct eth_dev_ops mlx5_dev_ops_isolate = { 3130887aa7fSNélio Laranjeiro .dev_configure = mlx5_dev_configure, 3140887aa7fSNélio Laranjeiro .dev_start = mlx5_dev_start, 3150887aa7fSNélio Laranjeiro .dev_stop = mlx5_dev_stop, 3160887aa7fSNélio Laranjeiro .dev_set_link_down = mlx5_set_link_down, 3170887aa7fSNélio Laranjeiro .dev_set_link_up = mlx5_set_link_up, 3180887aa7fSNélio Laranjeiro .dev_close = mlx5_dev_close, 3190887aa7fSNélio Laranjeiro .link_update = mlx5_link_update, 3200887aa7fSNélio Laranjeiro .stats_get = mlx5_stats_get, 3210887aa7fSNélio Laranjeiro .stats_reset = mlx5_stats_reset, 3220887aa7fSNélio Laranjeiro .xstats_get = mlx5_xstats_get, 3230887aa7fSNélio Laranjeiro .xstats_reset = mlx5_xstats_reset, 3240887aa7fSNélio Laranjeiro .xstats_get_names = mlx5_xstats_get_names, 3250887aa7fSNélio Laranjeiro .dev_infos_get = mlx5_dev_infos_get, 3260887aa7fSNélio Laranjeiro .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 3270887aa7fSNélio Laranjeiro .vlan_filter_set = mlx5_vlan_filter_set, 3280887aa7fSNélio Laranjeiro .rx_queue_setup = mlx5_rx_queue_setup, 3290887aa7fSNélio Laranjeiro .tx_queue_setup = mlx5_tx_queue_setup, 3300887aa7fSNélio Laranjeiro .rx_queue_release = mlx5_rx_queue_release, 3310887aa7fSNélio Laranjeiro .tx_queue_release = mlx5_tx_queue_release, 3320887aa7fSNélio Laranjeiro .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 3330887aa7fSNélio Laranjeiro .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 3340887aa7fSNélio Laranjeiro .mac_addr_remove = mlx5_mac_addr_remove, 3350887aa7fSNélio Laranjeiro .mac_addr_add = mlx5_mac_addr_add, 3360887aa7fSNélio Laranjeiro .mac_addr_set = mlx5_mac_addr_set, 3370887aa7fSNélio Laranjeiro .mtu_set = mlx5_dev_set_mtu, 3380887aa7fSNélio Laranjeiro .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 3390887aa7fSNélio Laranjeiro .vlan_offload_set = mlx5_vlan_offload_set, 3400887aa7fSNélio Laranjeiro .filter_ctrl = mlx5_dev_filter_ctrl, 3410887aa7fSNélio Laranjeiro .rx_descriptor_status = mlx5_rx_descriptor_status, 3420887aa7fSNélio Laranjeiro .tx_descriptor_status = mlx5_tx_descriptor_status, 3430887aa7fSNélio Laranjeiro .rx_queue_intr_enable = mlx5_rx_intr_enable, 3440887aa7fSNélio Laranjeiro .rx_queue_intr_disable = mlx5_rx_intr_disable, 345d3e0f392SMatan Azrad .is_removed = mlx5_is_removed, 3460887aa7fSNélio Laranjeiro }; 3470887aa7fSNélio Laranjeiro 348771fa900SAdrien Mazarguil static struct { 349771fa900SAdrien Mazarguil struct rte_pci_addr pci_addr; /* associated PCI address */ 350771fa900SAdrien Mazarguil uint32_t ports; /* physical ports bitfield. */ 351771fa900SAdrien Mazarguil } mlx5_dev[32]; 352771fa900SAdrien Mazarguil 353771fa900SAdrien Mazarguil /** 354771fa900SAdrien Mazarguil * Get device index in mlx5_dev[] from PCI bus address. 355771fa900SAdrien Mazarguil * 356771fa900SAdrien Mazarguil * @param[in] pci_addr 357771fa900SAdrien Mazarguil * PCI bus address to look for. 358771fa900SAdrien Mazarguil * 359771fa900SAdrien Mazarguil * @return 360771fa900SAdrien Mazarguil * mlx5_dev[] index on success, -1 on failure. 361771fa900SAdrien Mazarguil */ 362771fa900SAdrien Mazarguil static int 363771fa900SAdrien Mazarguil mlx5_dev_idx(struct rte_pci_addr *pci_addr) 364771fa900SAdrien Mazarguil { 365771fa900SAdrien Mazarguil unsigned int i; 366771fa900SAdrien Mazarguil int ret = -1; 367771fa900SAdrien Mazarguil 368771fa900SAdrien Mazarguil assert(pci_addr != NULL); 369771fa900SAdrien Mazarguil for (i = 0; (i != RTE_DIM(mlx5_dev)); ++i) { 370771fa900SAdrien Mazarguil if ((mlx5_dev[i].pci_addr.domain == pci_addr->domain) && 371771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.bus == pci_addr->bus) && 372771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.devid == pci_addr->devid) && 373771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.function == pci_addr->function)) 374771fa900SAdrien Mazarguil return i; 375771fa900SAdrien Mazarguil if ((mlx5_dev[i].ports == 0) && (ret == -1)) 376771fa900SAdrien Mazarguil ret = i; 377771fa900SAdrien Mazarguil } 378771fa900SAdrien Mazarguil return ret; 379771fa900SAdrien Mazarguil } 380771fa900SAdrien Mazarguil 381e72dd09bSNélio Laranjeiro /** 382e72dd09bSNélio Laranjeiro * Verify and store value for device argument. 383e72dd09bSNélio Laranjeiro * 384e72dd09bSNélio Laranjeiro * @param[in] key 385e72dd09bSNélio Laranjeiro * Key argument to verify. 386e72dd09bSNélio Laranjeiro * @param[in] val 387e72dd09bSNélio Laranjeiro * Value associated with key. 388e72dd09bSNélio Laranjeiro * @param opaque 389e72dd09bSNélio Laranjeiro * User data. 390e72dd09bSNélio Laranjeiro * 391e72dd09bSNélio Laranjeiro * @return 392e72dd09bSNélio Laranjeiro * 0 on success, negative errno value on failure. 393e72dd09bSNélio Laranjeiro */ 394e72dd09bSNélio Laranjeiro static int 395e72dd09bSNélio Laranjeiro mlx5_args_check(const char *key, const char *val, void *opaque) 396e72dd09bSNélio Laranjeiro { 3977fe24446SShahaf Shuler struct mlx5_dev_config *config = opaque; 39899c12dccSNélio Laranjeiro unsigned long tmp; 399e72dd09bSNélio Laranjeiro 40099c12dccSNélio Laranjeiro errno = 0; 40199c12dccSNélio Laranjeiro tmp = strtoul(val, NULL, 0); 40299c12dccSNélio Laranjeiro if (errno) { 40399c12dccSNélio Laranjeiro WARN("%s: \"%s\" is not a valid integer", key, val); 40499c12dccSNélio Laranjeiro return errno; 40599c12dccSNélio Laranjeiro } 40699c12dccSNélio Laranjeiro if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) { 4077fe24446SShahaf Shuler config->cqe_comp = !!tmp; 4082a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { 4097fe24446SShahaf Shuler config->txq_inline = tmp; 4102a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { 4117fe24446SShahaf Shuler config->txqs_inline = tmp; 412230189d9SNélio Laranjeiro } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { 4137fe24446SShahaf Shuler config->mps = !!tmp ? config->mps : 0; 4146ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) { 4157fe24446SShahaf Shuler config->mpw_hdr_dseg = !!tmp; 4166ce84bd8SYongseok Koh } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) { 4177fe24446SShahaf Shuler config->inline_max_packet_sz = tmp; 4185644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { 4197fe24446SShahaf Shuler config->tx_vec_en = !!tmp; 4205644d5b9SNelio Laranjeiro } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { 4217fe24446SShahaf Shuler config->rx_vec_en = !!tmp; 42299c12dccSNélio Laranjeiro } else { 423e72dd09bSNélio Laranjeiro WARN("%s: unknown parameter", key); 424e72dd09bSNélio Laranjeiro return -EINVAL; 425e72dd09bSNélio Laranjeiro } 42699c12dccSNélio Laranjeiro return 0; 42799c12dccSNélio Laranjeiro } 428e72dd09bSNélio Laranjeiro 429e72dd09bSNélio Laranjeiro /** 430e72dd09bSNélio Laranjeiro * Parse device parameters. 431e72dd09bSNélio Laranjeiro * 4327fe24446SShahaf Shuler * @param config 4337fe24446SShahaf Shuler * Pointer to device configuration structure. 434e72dd09bSNélio Laranjeiro * @param devargs 435e72dd09bSNélio Laranjeiro * Device arguments structure. 436e72dd09bSNélio Laranjeiro * 437e72dd09bSNélio Laranjeiro * @return 438e72dd09bSNélio Laranjeiro * 0 on success, errno value on failure. 439e72dd09bSNélio Laranjeiro */ 440e72dd09bSNélio Laranjeiro static int 4417fe24446SShahaf Shuler mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) 442e72dd09bSNélio Laranjeiro { 443e72dd09bSNélio Laranjeiro const char **params = (const char *[]){ 44499c12dccSNélio Laranjeiro MLX5_RXQ_CQE_COMP_EN, 4452a66cf37SYaacov Hazan MLX5_TXQ_INLINE, 4462a66cf37SYaacov Hazan MLX5_TXQS_MIN_INLINE, 447230189d9SNélio Laranjeiro MLX5_TXQ_MPW_EN, 4486ce84bd8SYongseok Koh MLX5_TXQ_MPW_HDR_DSEG_EN, 4496ce84bd8SYongseok Koh MLX5_TXQ_MAX_INLINE_LEN, 4505644d5b9SNelio Laranjeiro MLX5_TX_VEC_EN, 4515644d5b9SNelio Laranjeiro MLX5_RX_VEC_EN, 452e72dd09bSNélio Laranjeiro NULL, 453e72dd09bSNélio Laranjeiro }; 454e72dd09bSNélio Laranjeiro struct rte_kvargs *kvlist; 455e72dd09bSNélio Laranjeiro int ret = 0; 456e72dd09bSNélio Laranjeiro int i; 457e72dd09bSNélio Laranjeiro 458e72dd09bSNélio Laranjeiro if (devargs == NULL) 459e72dd09bSNélio Laranjeiro return 0; 460e72dd09bSNélio Laranjeiro /* Following UGLY cast is done to pass checkpatch. */ 461e72dd09bSNélio Laranjeiro kvlist = rte_kvargs_parse(devargs->args, params); 462e72dd09bSNélio Laranjeiro if (kvlist == NULL) 463e72dd09bSNélio Laranjeiro return 0; 464e72dd09bSNélio Laranjeiro /* Process parameters. */ 465e72dd09bSNélio Laranjeiro for (i = 0; (params[i] != NULL); ++i) { 466e72dd09bSNélio Laranjeiro if (rte_kvargs_count(kvlist, params[i])) { 467e72dd09bSNélio Laranjeiro ret = rte_kvargs_process(kvlist, params[i], 4687fe24446SShahaf Shuler mlx5_args_check, config); 469a67323e4SShahaf Shuler if (ret != 0) { 470a67323e4SShahaf Shuler rte_kvargs_free(kvlist); 471e72dd09bSNélio Laranjeiro return ret; 472e72dd09bSNélio Laranjeiro } 473e72dd09bSNélio Laranjeiro } 474a67323e4SShahaf Shuler } 475e72dd09bSNélio Laranjeiro rte_kvargs_free(kvlist); 476e72dd09bSNélio Laranjeiro return 0; 477e72dd09bSNélio Laranjeiro } 478e72dd09bSNélio Laranjeiro 479fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver; 480771fa900SAdrien Mazarguil 481771fa900SAdrien Mazarguil /** 482771fa900SAdrien Mazarguil * DPDK callback to register a PCI device. 483771fa900SAdrien Mazarguil * 484771fa900SAdrien Mazarguil * This function creates an Ethernet device for each port of a given 485771fa900SAdrien Mazarguil * PCI device. 486771fa900SAdrien Mazarguil * 487771fa900SAdrien Mazarguil * @param[in] pci_drv 488771fa900SAdrien Mazarguil * PCI driver structure (mlx5_driver). 489771fa900SAdrien Mazarguil * @param[in] pci_dev 490771fa900SAdrien Mazarguil * PCI device information. 491771fa900SAdrien Mazarguil * 492771fa900SAdrien Mazarguil * @return 493771fa900SAdrien Mazarguil * 0 on success, negative errno value on failure. 494771fa900SAdrien Mazarguil */ 495771fa900SAdrien Mazarguil static int 496af424af8SShreyansh Jain mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 497771fa900SAdrien Mazarguil { 498771fa900SAdrien Mazarguil struct ibv_device **list; 499771fa900SAdrien Mazarguil struct ibv_device *ibv_dev; 500771fa900SAdrien Mazarguil int err = 0; 501771fa900SAdrien Mazarguil struct ibv_context *attr_ctx = NULL; 50243e9d979SShachar Beiser struct ibv_device_attr_ex device_attr; 50385e347dbSNélio Laranjeiro unsigned int sriov; 504e192ef80SYaacov Hazan unsigned int mps; 505523f5a74SYongseok Koh unsigned int cqe_comp; 506772d3435SXueming Li unsigned int tunnel_en = 0; 507771fa900SAdrien Mazarguil int idx; 508771fa900SAdrien Mazarguil int i; 50943e9d979SShachar Beiser struct mlx5dv_context attrs_out; 5109a761de8SOri Kam #ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT 5119a761de8SOri Kam struct ibv_counter_set_description cs_desc; 5129a761de8SOri Kam #endif 513771fa900SAdrien Mazarguil 514771fa900SAdrien Mazarguil (void)pci_drv; 515fdf91e0fSJan Blunck assert(pci_drv == &mlx5_driver); 516771fa900SAdrien Mazarguil /* Get mlx5_dev[] index. */ 517771fa900SAdrien Mazarguil idx = mlx5_dev_idx(&pci_dev->addr); 518771fa900SAdrien Mazarguil if (idx == -1) { 519771fa900SAdrien Mazarguil ERROR("this driver cannot support any more adapters"); 520771fa900SAdrien Mazarguil return -ENOMEM; 521771fa900SAdrien Mazarguil } 522771fa900SAdrien Mazarguil DEBUG("using driver device index %d", idx); 523771fa900SAdrien Mazarguil 524771fa900SAdrien Mazarguil /* Save PCI address. */ 525771fa900SAdrien Mazarguil mlx5_dev[idx].pci_addr = pci_dev->addr; 526771fa900SAdrien Mazarguil list = ibv_get_device_list(&i); 527771fa900SAdrien Mazarguil if (list == NULL) { 528771fa900SAdrien Mazarguil assert(errno); 5295525aa8fSGaetan Rivet if (errno == ENOSYS) 5305525aa8fSGaetan Rivet ERROR("cannot list devices, is ib_uverbs loaded?"); 531771fa900SAdrien Mazarguil return -errno; 532771fa900SAdrien Mazarguil } 533771fa900SAdrien Mazarguil assert(i >= 0); 534771fa900SAdrien Mazarguil /* 535771fa900SAdrien Mazarguil * For each listed device, check related sysfs entry against 536771fa900SAdrien Mazarguil * the provided PCI ID. 537771fa900SAdrien Mazarguil */ 538771fa900SAdrien Mazarguil while (i != 0) { 539771fa900SAdrien Mazarguil struct rte_pci_addr pci_addr; 540771fa900SAdrien Mazarguil 541771fa900SAdrien Mazarguil --i; 542771fa900SAdrien Mazarguil DEBUG("checking device \"%s\"", list[i]->name); 543771fa900SAdrien Mazarguil if (mlx5_ibv_device_to_pci_addr(list[i], &pci_addr)) 544771fa900SAdrien Mazarguil continue; 545771fa900SAdrien Mazarguil if ((pci_dev->addr.domain != pci_addr.domain) || 546771fa900SAdrien Mazarguil (pci_dev->addr.bus != pci_addr.bus) || 547771fa900SAdrien Mazarguil (pci_dev->addr.devid != pci_addr.devid) || 548771fa900SAdrien Mazarguil (pci_dev->addr.function != pci_addr.function)) 549771fa900SAdrien Mazarguil continue; 55085e347dbSNélio Laranjeiro sriov = ((pci_dev->id.device_id == 551771fa900SAdrien Mazarguil PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) || 552771fa900SAdrien Mazarguil (pci_dev->id.device_id == 553528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) || 554528a9fbeSYongseok Koh (pci_dev->id.device_id == 555528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) || 556528a9fbeSYongseok Koh (pci_dev->id.device_id == 557528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF)); 558528a9fbeSYongseok Koh switch (pci_dev->id.device_id) { 559f5fde520SShahaf Shuler case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 560f5fde520SShahaf Shuler tunnel_en = 1; 561f5fde520SShahaf Shuler break; 562528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: 563528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5: 564528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 565528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: 566528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 567f5fde520SShahaf Shuler tunnel_en = 1; 568528a9fbeSYongseok Koh break; 569528a9fbeSYongseok Koh default: 57043e9d979SShachar Beiser break; 571528a9fbeSYongseok Koh } 57285e347dbSNélio Laranjeiro INFO("PCI information matches, using device \"%s\"" 57343e9d979SShachar Beiser " (SR-IOV: %s)", 574e192ef80SYaacov Hazan list[i]->name, 57543e9d979SShachar Beiser sriov ? "true" : "false"); 576771fa900SAdrien Mazarguil attr_ctx = ibv_open_device(list[i]); 577771fa900SAdrien Mazarguil err = errno; 578771fa900SAdrien Mazarguil break; 579771fa900SAdrien Mazarguil } 580771fa900SAdrien Mazarguil if (attr_ctx == NULL) { 581771fa900SAdrien Mazarguil ibv_free_device_list(list); 582771fa900SAdrien Mazarguil switch (err) { 583771fa900SAdrien Mazarguil case 0: 5845525aa8fSGaetan Rivet ERROR("cannot access device, is mlx5_ib loaded?"); 5855525aa8fSGaetan Rivet return -ENODEV; 586771fa900SAdrien Mazarguil case EINVAL: 5875525aa8fSGaetan Rivet ERROR("cannot use device, are drivers up to date?"); 5885525aa8fSGaetan Rivet return -EINVAL; 589771fa900SAdrien Mazarguil } 590771fa900SAdrien Mazarguil assert(err > 0); 591771fa900SAdrien Mazarguil return -err; 592771fa900SAdrien Mazarguil } 593771fa900SAdrien Mazarguil ibv_dev = list[i]; 594771fa900SAdrien Mazarguil 595771fa900SAdrien Mazarguil DEBUG("device opened"); 59643e9d979SShachar Beiser /* 59743e9d979SShachar Beiser * Multi-packet send is supported by ConnectX-4 Lx PF as well 59843e9d979SShachar Beiser * as all ConnectX-5 devices. 59943e9d979SShachar Beiser */ 60043e9d979SShachar Beiser mlx5dv_query_device(attr_ctx, &attrs_out); 601e589960cSYongseok Koh if (attrs_out.flags & MLX5DV_CONTEXT_FLAGS_MPW_ALLOWED) { 602e589960cSYongseok Koh if (attrs_out.flags & MLX5DV_CONTEXT_FLAGS_ENHANCED_MPW) { 603e589960cSYongseok Koh DEBUG("Enhanced MPW is supported"); 60443e9d979SShachar Beiser mps = MLX5_MPW_ENHANCED; 60543e9d979SShachar Beiser } else { 606e589960cSYongseok Koh DEBUG("MPW is supported"); 607e589960cSYongseok Koh mps = MLX5_MPW; 608e589960cSYongseok Koh } 609e589960cSYongseok Koh } else { 610e589960cSYongseok Koh DEBUG("MPW isn't supported"); 61143e9d979SShachar Beiser mps = MLX5_MPW_DISABLED; 61243e9d979SShachar Beiser } 613523f5a74SYongseok Koh if (RTE_CACHE_LINE_SIZE == 128 && 614523f5a74SYongseok Koh !(attrs_out.flags & MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP)) 615523f5a74SYongseok Koh cqe_comp = 0; 616523f5a74SYongseok Koh else 617523f5a74SYongseok Koh cqe_comp = 1; 61843e9d979SShachar Beiser if (ibv_query_device_ex(attr_ctx, NULL, &device_attr)) 619771fa900SAdrien Mazarguil goto error; 62043e9d979SShachar Beiser INFO("%u port(s) detected", device_attr.orig_attr.phys_port_cnt); 621771fa900SAdrien Mazarguil 62243e9d979SShachar Beiser for (i = 0; i < device_attr.orig_attr.phys_port_cnt; i++) { 623771fa900SAdrien Mazarguil uint32_t port = i + 1; /* ports are indexed from one */ 624771fa900SAdrien Mazarguil uint32_t test = (1 << i); 625771fa900SAdrien Mazarguil struct ibv_context *ctx = NULL; 626771fa900SAdrien Mazarguil struct ibv_port_attr port_attr; 627771fa900SAdrien Mazarguil struct ibv_pd *pd = NULL; 628771fa900SAdrien Mazarguil struct priv *priv = NULL; 629771fa900SAdrien Mazarguil struct rte_eth_dev *eth_dev; 63043e9d979SShachar Beiser struct ibv_device_attr_ex device_attr_ex; 631771fa900SAdrien Mazarguil struct ether_addr mac; 63285e347dbSNélio Laranjeiro uint16_t num_vfs = 0; 6339a761de8SOri Kam struct ibv_device_attr_ex device_attr; 6347fe24446SShahaf Shuler struct mlx5_dev_config config = { 6357fe24446SShahaf Shuler .cqe_comp = cqe_comp, 6367fe24446SShahaf Shuler .mps = mps, 6377fe24446SShahaf Shuler .tunnel_en = tunnel_en, 6387fe24446SShahaf Shuler .tx_vec_en = 1, 6397fe24446SShahaf Shuler .rx_vec_en = 1, 6407fe24446SShahaf Shuler .mpw_hdr_dseg = 0, 64150b244a1SShahaf Shuler .txq_inline = MLX5_ARG_UNSET, 64250b244a1SShahaf Shuler .txqs_inline = MLX5_ARG_UNSET, 64350b244a1SShahaf Shuler .inline_max_packet_sz = MLX5_ARG_UNSET, 64450b244a1SShahaf Shuler }; 645771fa900SAdrien Mazarguil 646f8b9a3baSXueming Li mlx5_dev[idx].ports |= test; 647f8b9a3baSXueming Li 64851e7fa8dSNélio Laranjeiro if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 649f8b9a3baSXueming Li /* from rte_ethdev.c */ 650f8b9a3baSXueming Li char name[RTE_ETH_NAME_MAX_LEN]; 651f8b9a3baSXueming Li 652f8b9a3baSXueming Li snprintf(name, sizeof(name), "%s port %u", 653f8b9a3baSXueming Li ibv_get_device_name(ibv_dev), port); 654f8b9a3baSXueming Li eth_dev = rte_eth_dev_attach_secondary(name); 655f8b9a3baSXueming Li if (eth_dev == NULL) { 656f8b9a3baSXueming Li ERROR("can not attach rte ethdev"); 657f8b9a3baSXueming Li err = ENOMEM; 658f8b9a3baSXueming Li goto error; 659f8b9a3baSXueming Li } 660f8b9a3baSXueming Li eth_dev->device = &pci_dev->device; 66187ec44ceSXueming Li eth_dev->dev_ops = &mlx5_dev_sec_ops; 662f8b9a3baSXueming Li priv = eth_dev->data->dev_private; 663f8b9a3baSXueming Li /* Receive command fd from primary process */ 664f8b9a3baSXueming Li err = priv_socket_connect(priv); 665f8b9a3baSXueming Li if (err < 0) { 666f8b9a3baSXueming Li err = -err; 667f8b9a3baSXueming Li goto error; 668f8b9a3baSXueming Li } 669f8b9a3baSXueming Li /* Remap UAR for Tx queues. */ 670f8b9a3baSXueming Li err = priv_tx_uar_remap(priv, err); 671f8b9a3baSXueming Li if (err < 0) { 672f8b9a3baSXueming Li err = -err; 673f8b9a3baSXueming Li goto error; 674f8b9a3baSXueming Li } 6751cfa649bSShahaf Shuler /* 6761cfa649bSShahaf Shuler * Ethdev pointer is still required as input since 6771cfa649bSShahaf Shuler * the primary device is not accessible from the 6781cfa649bSShahaf Shuler * secondary process. 6791cfa649bSShahaf Shuler */ 6801cfa649bSShahaf Shuler eth_dev->rx_pkt_burst = 6811cfa649bSShahaf Shuler priv_select_rx_function(priv, eth_dev); 6821cfa649bSShahaf Shuler eth_dev->tx_pkt_burst = 6831cfa649bSShahaf Shuler priv_select_tx_function(priv, eth_dev); 684f8b9a3baSXueming Li continue; 685f8b9a3baSXueming Li } 686f8b9a3baSXueming Li 687771fa900SAdrien Mazarguil DEBUG("using port %u (%08" PRIx32 ")", port, test); 688771fa900SAdrien Mazarguil 689771fa900SAdrien Mazarguil ctx = ibv_open_device(ibv_dev); 690e1c3e305SMatan Azrad if (ctx == NULL) { 691e1c3e305SMatan Azrad err = ENODEV; 692771fa900SAdrien Mazarguil goto port_error; 693e1c3e305SMatan Azrad } 694771fa900SAdrien Mazarguil 6959a761de8SOri Kam ibv_query_device_ex(ctx, NULL, &device_attr); 696771fa900SAdrien Mazarguil /* Check port status. */ 697771fa900SAdrien Mazarguil err = ibv_query_port(ctx, port, &port_attr); 698771fa900SAdrien Mazarguil if (err) { 699771fa900SAdrien Mazarguil ERROR("port query failed: %s", strerror(err)); 700771fa900SAdrien Mazarguil goto port_error; 701771fa900SAdrien Mazarguil } 7021371f4dfSOr Ami 7031371f4dfSOr Ami if (port_attr.link_layer != IBV_LINK_LAYER_ETHERNET) { 7041371f4dfSOr Ami ERROR("port %d is not configured in Ethernet mode", 7051371f4dfSOr Ami port); 706e1c3e305SMatan Azrad err = EINVAL; 7071371f4dfSOr Ami goto port_error; 7081371f4dfSOr Ami } 7091371f4dfSOr Ami 710771fa900SAdrien Mazarguil if (port_attr.state != IBV_PORT_ACTIVE) 711771fa900SAdrien Mazarguil DEBUG("port %d is not active: \"%s\" (%d)", 712771fa900SAdrien Mazarguil port, ibv_port_state_str(port_attr.state), 713771fa900SAdrien Mazarguil port_attr.state); 714771fa900SAdrien Mazarguil 715771fa900SAdrien Mazarguil /* Allocate protection domain. */ 716771fa900SAdrien Mazarguil pd = ibv_alloc_pd(ctx); 717771fa900SAdrien Mazarguil if (pd == NULL) { 718771fa900SAdrien Mazarguil ERROR("PD allocation failure"); 719771fa900SAdrien Mazarguil err = ENOMEM; 720771fa900SAdrien Mazarguil goto port_error; 721771fa900SAdrien Mazarguil } 722771fa900SAdrien Mazarguil 723771fa900SAdrien Mazarguil mlx5_dev[idx].ports |= test; 724771fa900SAdrien Mazarguil 725771fa900SAdrien Mazarguil /* from rte_ethdev.c */ 726771fa900SAdrien Mazarguil priv = rte_zmalloc("ethdev private structure", 727771fa900SAdrien Mazarguil sizeof(*priv), 728771fa900SAdrien Mazarguil RTE_CACHE_LINE_SIZE); 729771fa900SAdrien Mazarguil if (priv == NULL) { 730771fa900SAdrien Mazarguil ERROR("priv allocation failure"); 731771fa900SAdrien Mazarguil err = ENOMEM; 732771fa900SAdrien Mazarguil goto port_error; 733771fa900SAdrien Mazarguil } 734771fa900SAdrien Mazarguil 735771fa900SAdrien Mazarguil priv->ctx = ctx; 73687ec44ceSXueming Li strncpy(priv->ibdev_path, priv->ctx->device->ibdev_path, 73787ec44ceSXueming Li sizeof(priv->ibdev_path)); 738771fa900SAdrien Mazarguil priv->device_attr = device_attr; 739771fa900SAdrien Mazarguil priv->port = port; 740771fa900SAdrien Mazarguil priv->pd = pd; 741771fa900SAdrien Mazarguil priv->mtu = ETHER_MTU; 7427fe24446SShahaf Shuler err = mlx5_args(&config, pci_dev->device.devargs); 743e72dd09bSNélio Laranjeiro if (err) { 744e72dd09bSNélio Laranjeiro ERROR("failed to process device arguments: %s", 745e72dd09bSNélio Laranjeiro strerror(err)); 746e72dd09bSNélio Laranjeiro goto port_error; 747e72dd09bSNélio Laranjeiro } 74843e9d979SShachar Beiser if (ibv_query_device_ex(ctx, NULL, &device_attr_ex)) { 74943e9d979SShachar Beiser ERROR("ibv_query_device_ex() failed"); 750771fa900SAdrien Mazarguil goto port_error; 751771fa900SAdrien Mazarguil } 752771fa900SAdrien Mazarguil 7537fe24446SShahaf Shuler config.hw_csum = !!(device_attr_ex.device_cap_flags_ex & 75443e9d979SShachar Beiser IBV_DEVICE_RAW_IP_CSUM); 755771fa900SAdrien Mazarguil DEBUG("checksum offloading is %ssupported", 7567fe24446SShahaf Shuler (config.hw_csum ? "" : "not ")); 757771fa900SAdrien Mazarguil 75843e9d979SShachar Beiser #ifdef HAVE_IBV_DEVICE_VXLAN_SUPPORT 7597fe24446SShahaf Shuler config.hw_csum_l2tun = 7607fe24446SShahaf Shuler !!(exp_device_attr.exp_device_cap_flags & 76143e9d979SShachar Beiser IBV_DEVICE_VXLAN_SUPPORT); 76243e9d979SShachar Beiser #endif 7634aa15eb1SNélio Laranjeiro DEBUG("Rx L2 tunnel checksum offloads are %ssupported", 7647fe24446SShahaf Shuler (config.hw_csum_l2tun ? "" : "not ")); 765771fa900SAdrien Mazarguil 7669a761de8SOri Kam #ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT 76773b620f2SNelio Laranjeiro config.flow_counter_en = !!(device_attr.max_counter_sets); 7689a761de8SOri Kam ibv_describe_counter_set(ctx, 0, &cs_desc); 7699a761de8SOri Kam DEBUG("counter type = %d, num of cs = %ld, attributes = %d", 7709a761de8SOri Kam cs_desc.counter_type, cs_desc.num_of_cs, 7719a761de8SOri Kam cs_desc.attributes); 7729a761de8SOri Kam #endif 7737fe24446SShahaf Shuler config.ind_table_max_size = 77443e9d979SShachar Beiser device_attr_ex.rss_caps.max_rwq_indirection_table_size; 77513d57bd5SAdrien Mazarguil /* Remove this check once DPDK supports larger/variable 77613d57bd5SAdrien Mazarguil * indirection tables. */ 7777fe24446SShahaf Shuler if (config.ind_table_max_size > 778ec1fed22SYongseok Koh (unsigned int)ETH_RSS_RETA_SIZE_512) 7797fe24446SShahaf Shuler config.ind_table_max_size = ETH_RSS_RETA_SIZE_512; 78095e16ef3SNelio Laranjeiro DEBUG("maximum RX indirection table size is %u", 7817fe24446SShahaf Shuler config.ind_table_max_size); 7827fe24446SShahaf Shuler config.hw_vlan_strip = !!(device_attr_ex.raw_packet_caps & 78343e9d979SShachar Beiser IBV_RAW_PACKET_CAP_CVLAN_STRIPPING); 784f3db9489SYaacov Hazan DEBUG("VLAN stripping is %ssupported", 7857fe24446SShahaf Shuler (config.hw_vlan_strip ? "" : "not ")); 78695e16ef3SNelio Laranjeiro 7877fe24446SShahaf Shuler config.hw_fcs_strip = 78843e9d979SShachar Beiser !!(device_attr_ex.orig_attr.device_cap_flags & 78943e9d979SShachar Beiser IBV_WQ_FLAGS_SCATTER_FCS); 7904d326709SOlga Shern DEBUG("FCS stripping configuration is %ssupported", 7917fe24446SShahaf Shuler (config.hw_fcs_strip ? "" : "not ")); 7924d326709SOlga Shern 79343e9d979SShachar Beiser #ifdef HAVE_IBV_WQ_FLAG_RX_END_PADDING 7947fe24446SShahaf Shuler config.hw_padding = !!device_attr_ex.rx_pad_end_addr_align; 79543e9d979SShachar Beiser #endif 7964d803a72SOlga Shern DEBUG("hardware RX end alignment padding is %ssupported", 7977fe24446SShahaf Shuler (config.hw_padding ? "" : "not ")); 7984d803a72SOlga Shern 79985e347dbSNélio Laranjeiro priv_get_num_vfs(priv, &num_vfs); 8007fe24446SShahaf Shuler config.sriov = (num_vfs || sriov); 8017fe24446SShahaf Shuler config.tso = ((device_attr_ex.tso_caps.max_tso > 0) && 80243e9d979SShachar Beiser (device_attr_ex.tso_caps.supported_qpts & 80343e9d979SShachar Beiser (1 << IBV_QPT_RAW_PACKET))); 8047fe24446SShahaf Shuler if (config.tso) 8057fe24446SShahaf Shuler config.tso_max_payload_sz = 80643e9d979SShachar Beiser device_attr_ex.tso_caps.max_tso; 8077fe24446SShahaf Shuler if (config.mps && !mps) { 808230189d9SNélio Laranjeiro ERROR("multi-packet send not supported on this device" 809230189d9SNélio Laranjeiro " (" MLX5_TXQ_MPW_EN ")"); 810230189d9SNélio Laranjeiro err = ENOTSUP; 811230189d9SNélio Laranjeiro goto port_error; 812230189d9SNélio Laranjeiro } 8136ce84bd8SYongseok Koh INFO("%sMPS is %s", 8147fe24446SShahaf Shuler config.mps == MLX5_MPW_ENHANCED ? "Enhanced " : "", 8157fe24446SShahaf Shuler config.mps != MLX5_MPW_DISABLED ? "enabled" : "disabled"); 8167fe24446SShahaf Shuler if (config.cqe_comp && !cqe_comp) { 817523f5a74SYongseok Koh WARN("Rx CQE compression isn't supported"); 8187fe24446SShahaf Shuler config.cqe_comp = 0; 819523f5a74SYongseok Koh } 820771fa900SAdrien Mazarguil /* Configure the first MAC address by default. */ 821771fa900SAdrien Mazarguil if (priv_get_mac(priv, &mac.addr_bytes)) { 822771fa900SAdrien Mazarguil ERROR("cannot get MAC address, is mlx5_en loaded?" 823771fa900SAdrien Mazarguil " (errno: %s)", strerror(errno)); 824e1c3e305SMatan Azrad err = ENODEV; 825771fa900SAdrien Mazarguil goto port_error; 826771fa900SAdrien Mazarguil } 827771fa900SAdrien Mazarguil INFO("port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 828771fa900SAdrien Mazarguil priv->port, 829771fa900SAdrien Mazarguil mac.addr_bytes[0], mac.addr_bytes[1], 830771fa900SAdrien Mazarguil mac.addr_bytes[2], mac.addr_bytes[3], 831771fa900SAdrien Mazarguil mac.addr_bytes[4], mac.addr_bytes[5]); 832771fa900SAdrien Mazarguil #ifndef NDEBUG 833771fa900SAdrien Mazarguil { 834771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 835771fa900SAdrien Mazarguil 836771fa900SAdrien Mazarguil if (priv_get_ifname(priv, &ifname) == 0) 837771fa900SAdrien Mazarguil DEBUG("port %u ifname is \"%s\"", 838771fa900SAdrien Mazarguil priv->port, ifname); 839771fa900SAdrien Mazarguil else 840771fa900SAdrien Mazarguil DEBUG("port %u ifname is unknown", priv->port); 841771fa900SAdrien Mazarguil } 842771fa900SAdrien Mazarguil #endif 843771fa900SAdrien Mazarguil /* Get actual MTU if possible. */ 844771fa900SAdrien Mazarguil priv_get_mtu(priv, &priv->mtu); 845771fa900SAdrien Mazarguil DEBUG("port %u MTU is %u", priv->port, priv->mtu); 846771fa900SAdrien Mazarguil 847771fa900SAdrien Mazarguil /* from rte_ethdev.c */ 848771fa900SAdrien Mazarguil { 849771fa900SAdrien Mazarguil char name[RTE_ETH_NAME_MAX_LEN]; 850771fa900SAdrien Mazarguil 851771fa900SAdrien Mazarguil snprintf(name, sizeof(name), "%s port %u", 852771fa900SAdrien Mazarguil ibv_get_device_name(ibv_dev), port); 8536751f6deSDavid Marchand eth_dev = rte_eth_dev_allocate(name); 854771fa900SAdrien Mazarguil } 855771fa900SAdrien Mazarguil if (eth_dev == NULL) { 856771fa900SAdrien Mazarguil ERROR("can not allocate rte ethdev"); 857771fa900SAdrien Mazarguil err = ENOMEM; 858771fa900SAdrien Mazarguil goto port_error; 859771fa900SAdrien Mazarguil } 860771fa900SAdrien Mazarguil eth_dev->data->dev_private = priv; 861a48deadaSOr Ami eth_dev->data->mac_addrs = priv->mac; 862eac901ceSJan Blunck eth_dev->device = &pci_dev->device; 863a48deadaSOr Ami rte_eth_copy_pci_info(eth_dev, pci_dev); 864fdf91e0fSJan Blunck eth_dev->device->driver = &mlx5_driver.driver; 865771fa900SAdrien Mazarguil priv->dev = eth_dev; 866771fa900SAdrien Mazarguil eth_dev->dev_ops = &mlx5_dev_ops; 867272733b5SNélio Laranjeiro /* Register MAC address. */ 868272733b5SNélio Laranjeiro claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); 869c8ffb8a9SNélio Laranjeiro TAILQ_INIT(&priv->flows); 8701b37f5d8SNélio Laranjeiro TAILQ_INIT(&priv->ctrl_flows); 871a48deadaSOr Ami 8721e3a39f7SXueming Li /* Hint libmlx5 to use PMD allocator for data plane resources */ 8731e3a39f7SXueming Li struct mlx5dv_ctx_allocators alctr = { 8741e3a39f7SXueming Li .alloc = &mlx5_alloc_verbs_buf, 8751e3a39f7SXueming Li .free = &mlx5_free_verbs_buf, 8761e3a39f7SXueming Li .data = priv, 8771e3a39f7SXueming Li }; 8781e3a39f7SXueming Li mlx5dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS, 8791e3a39f7SXueming Li (void *)((uintptr_t)&alctr)); 8801e3a39f7SXueming Li 881771fa900SAdrien Mazarguil /* Bring Ethernet device up. */ 882771fa900SAdrien Mazarguil DEBUG("forcing Ethernet interface up"); 883771fa900SAdrien Mazarguil priv_set_flags(priv, ~IFF_UP, IFF_UP); 8847fe24446SShahaf Shuler /* Store device configuration on private structure. */ 8857fe24446SShahaf Shuler priv->config = config; 886771fa900SAdrien Mazarguil continue; 887771fa900SAdrien Mazarguil 888771fa900SAdrien Mazarguil port_error: 88929c1d8bbSNélio Laranjeiro if (priv) 890771fa900SAdrien Mazarguil rte_free(priv); 891771fa900SAdrien Mazarguil if (pd) 892771fa900SAdrien Mazarguil claim_zero(ibv_dealloc_pd(pd)); 893771fa900SAdrien Mazarguil if (ctx) 894771fa900SAdrien Mazarguil claim_zero(ibv_close_device(ctx)); 895771fa900SAdrien Mazarguil break; 896771fa900SAdrien Mazarguil } 897771fa900SAdrien Mazarguil 898771fa900SAdrien Mazarguil /* 899771fa900SAdrien Mazarguil * XXX if something went wrong in the loop above, there is a resource 900771fa900SAdrien Mazarguil * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as 901771fa900SAdrien Mazarguil * long as the dpdk does not provide a way to deallocate a ethdev and a 902771fa900SAdrien Mazarguil * way to enumerate the registered ethdevs to free the previous ones. 903771fa900SAdrien Mazarguil */ 904771fa900SAdrien Mazarguil 905771fa900SAdrien Mazarguil /* no port found, complain */ 906771fa900SAdrien Mazarguil if (!mlx5_dev[idx].ports) { 907771fa900SAdrien Mazarguil err = ENODEV; 908771fa900SAdrien Mazarguil goto error; 909771fa900SAdrien Mazarguil } 910771fa900SAdrien Mazarguil 911771fa900SAdrien Mazarguil error: 912771fa900SAdrien Mazarguil if (attr_ctx) 913771fa900SAdrien Mazarguil claim_zero(ibv_close_device(attr_ctx)); 914771fa900SAdrien Mazarguil if (list) 915771fa900SAdrien Mazarguil ibv_free_device_list(list); 916771fa900SAdrien Mazarguil assert(err >= 0); 917771fa900SAdrien Mazarguil return -err; 918771fa900SAdrien Mazarguil } 919771fa900SAdrien Mazarguil 920771fa900SAdrien Mazarguil static const struct rte_pci_id mlx5_pci_id_map[] = { 921771fa900SAdrien Mazarguil { 9221d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9231d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4) 924771fa900SAdrien Mazarguil }, 925771fa900SAdrien Mazarguil { 9261d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9271d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) 928771fa900SAdrien Mazarguil }, 929771fa900SAdrien Mazarguil { 9301d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9311d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LX) 932771fa900SAdrien Mazarguil }, 933771fa900SAdrien Mazarguil { 9341d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9351d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) 936771fa900SAdrien Mazarguil }, 937771fa900SAdrien Mazarguil { 938528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 939528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5) 940528a9fbeSYongseok Koh }, 941528a9fbeSYongseok Koh { 942528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 943528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) 944528a9fbeSYongseok Koh }, 945528a9fbeSYongseok Koh { 946528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 947528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EX) 948528a9fbeSYongseok Koh }, 949528a9fbeSYongseok Koh { 950528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 951528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF) 952528a9fbeSYongseok Koh }, 953528a9fbeSYongseok Koh { 954771fa900SAdrien Mazarguil .vendor_id = 0 955771fa900SAdrien Mazarguil } 956771fa900SAdrien Mazarguil }; 957771fa900SAdrien Mazarguil 958fdf91e0fSJan Blunck static struct rte_pci_driver mlx5_driver = { 9592f3193cfSJan Viktorin .driver = { 9602f3193cfSJan Viktorin .name = MLX5_DRIVER_NAME 9612f3193cfSJan Viktorin }, 962771fa900SAdrien Mazarguil .id_table = mlx5_pci_id_map, 963af424af8SShreyansh Jain .probe = mlx5_pci_probe, 9647d7d7ad1SMatan Azrad .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_INTR_RMV, 965771fa900SAdrien Mazarguil }; 966771fa900SAdrien Mazarguil 967771fa900SAdrien Mazarguil /** 968771fa900SAdrien Mazarguil * Driver initialization routine. 969771fa900SAdrien Mazarguil */ 970c830cb29SDavid Marchand RTE_INIT(rte_mlx5_pmd_init); 971c830cb29SDavid Marchand static void 972c830cb29SDavid Marchand rte_mlx5_pmd_init(void) 973771fa900SAdrien Mazarguil { 974ea16068cSYongseok Koh /* Build the static table for ptype conversion. */ 975ea16068cSYongseok Koh mlx5_set_ptype_table(); 976771fa900SAdrien Mazarguil /* 977771fa900SAdrien Mazarguil * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use 978771fa900SAdrien Mazarguil * huge pages. Calling ibv_fork_init() during init allows 979771fa900SAdrien Mazarguil * applications to use fork() safely for purposes other than 980771fa900SAdrien Mazarguil * using this PMD, which is not supported in forked processes. 981771fa900SAdrien Mazarguil */ 982771fa900SAdrien Mazarguil setenv("RDMAV_HUGEPAGES_SAFE", "1", 1); 983161b93e5SYongseok Koh /* Match the size of Rx completion entry to the size of a cacheline. */ 984161b93e5SYongseok Koh if (RTE_CACHE_LINE_SIZE == 128) 985161b93e5SYongseok Koh setenv("MLX5_CQE_SIZE", "128", 0); 986771fa900SAdrien Mazarguil ibv_fork_init(); 9873dcfe039SThomas Monjalon rte_pci_register(&mlx5_driver); 988771fa900SAdrien Mazarguil } 989771fa900SAdrien Mazarguil 99001f19227SShreyansh Jain RTE_PMD_EXPORT_NAME(net_mlx5, __COUNTER__); 99101f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_mlx5, mlx5_pci_id_map); 9920880c401SOlivier Matz RTE_PMD_REGISTER_KMOD_DEP(net_mlx5, "* ib_uverbs & mlx5_core & mlx5_ib"); 993