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 /* DPDK headers don't like -pedantic. */ 54771fa900SAdrien Mazarguil #ifdef PEDANTIC 55fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic" 56771fa900SAdrien Mazarguil #endif 57771fa900SAdrien Mazarguil #include <rte_malloc.h> 58771fa900SAdrien Mazarguil #include <rte_ethdev.h> 59771fa900SAdrien Mazarguil #include <rte_pci.h> 60771fa900SAdrien Mazarguil #include <rte_common.h> 61e72dd09bSNélio Laranjeiro #include <rte_kvargs.h> 62771fa900SAdrien Mazarguil #ifdef PEDANTIC 63fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic" 64771fa900SAdrien Mazarguil #endif 65771fa900SAdrien Mazarguil 66771fa900SAdrien Mazarguil #include "mlx5.h" 67771fa900SAdrien Mazarguil #include "mlx5_utils.h" 682e22920bSAdrien Mazarguil #include "mlx5_rxtx.h" 69771fa900SAdrien Mazarguil #include "mlx5_autoconf.h" 7013d57bd5SAdrien Mazarguil #include "mlx5_defs.h" 71771fa900SAdrien Mazarguil 7299c12dccSNélio Laranjeiro /* Device parameter to enable RX completion queue compression. */ 7399c12dccSNélio Laranjeiro #define MLX5_RXQ_CQE_COMP_EN "rxq_cqe_comp_en" 7499c12dccSNélio Laranjeiro 752a66cf37SYaacov Hazan /* Device parameter to configure inline send. */ 762a66cf37SYaacov Hazan #define MLX5_TXQ_INLINE "txq_inline" 772a66cf37SYaacov Hazan 782a66cf37SYaacov Hazan /* 792a66cf37SYaacov Hazan * Device parameter to configure the number of TX queues threshold for 802a66cf37SYaacov Hazan * enabling inline send. 812a66cf37SYaacov Hazan */ 822a66cf37SYaacov Hazan #define MLX5_TXQS_MIN_INLINE "txqs_min_inline" 832a66cf37SYaacov Hazan 84230189d9SNélio Laranjeiro /* Device parameter to enable multi-packet send WQEs. */ 85230189d9SNélio Laranjeiro #define MLX5_TXQ_MPW_EN "txq_mpw_en" 86230189d9SNélio Laranjeiro 87*3f13f8c2SShahaf Shuler /* Device parameter to enable hardware TSO offload. */ 88*3f13f8c2SShahaf Shuler #define MLX5_TSO "tso" 89*3f13f8c2SShahaf Shuler 90771fa900SAdrien Mazarguil /** 914d803a72SOlga Shern * Retrieve integer value from environment variable. 924d803a72SOlga Shern * 934d803a72SOlga Shern * @param[in] name 944d803a72SOlga Shern * Environment variable name. 954d803a72SOlga Shern * 964d803a72SOlga Shern * @return 974d803a72SOlga Shern * Integer value, 0 if the variable is not set. 984d803a72SOlga Shern */ 994d803a72SOlga Shern int 1004d803a72SOlga Shern mlx5_getenv_int(const char *name) 1014d803a72SOlga Shern { 1024d803a72SOlga Shern const char *val = getenv(name); 1034d803a72SOlga Shern 1044d803a72SOlga Shern if (val == NULL) 1054d803a72SOlga Shern return 0; 1064d803a72SOlga Shern return atoi(val); 1074d803a72SOlga Shern } 1084d803a72SOlga Shern 1094d803a72SOlga Shern /** 110771fa900SAdrien Mazarguil * DPDK callback to close the device. 111771fa900SAdrien Mazarguil * 112771fa900SAdrien Mazarguil * Destroy all queues and objects, free memory. 113771fa900SAdrien Mazarguil * 114771fa900SAdrien Mazarguil * @param dev 115771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 116771fa900SAdrien Mazarguil */ 117771fa900SAdrien Mazarguil static void 118771fa900SAdrien Mazarguil mlx5_dev_close(struct rte_eth_dev *dev) 119771fa900SAdrien Mazarguil { 120a48deadaSOr Ami struct priv *priv = mlx5_get_priv(dev); 1212e22920bSAdrien Mazarguil unsigned int i; 122771fa900SAdrien Mazarguil 123771fa900SAdrien Mazarguil priv_lock(priv); 124771fa900SAdrien Mazarguil DEBUG("%p: closing device \"%s\"", 125771fa900SAdrien Mazarguil (void *)dev, 126771fa900SAdrien Mazarguil ((priv->ctx != NULL) ? priv->ctx->device->name : "")); 127ecc1c29dSAdrien Mazarguil /* In case mlx5_dev_stop() has not been called. */ 128198a3c33SNelio Laranjeiro priv_dev_interrupt_handler_uninstall(priv, dev); 1290d218674SAdrien Mazarguil priv_special_flow_disable_all(priv); 130ecc1c29dSAdrien Mazarguil priv_mac_addrs_disable(priv); 131ecc1c29dSAdrien Mazarguil priv_destroy_hash_rxqs(priv); 13276f5c99eSYaacov Hazan 13376f5c99eSYaacov Hazan /* Remove flow director elements. */ 13476f5c99eSYaacov Hazan priv_fdir_disable(priv); 13576f5c99eSYaacov Hazan priv_fdir_delete_filters_list(priv); 13676f5c99eSYaacov Hazan 1372e22920bSAdrien Mazarguil /* Prevent crashes when queues are still in use. */ 1382e22920bSAdrien Mazarguil dev->rx_pkt_burst = removed_rx_burst; 1392e22920bSAdrien Mazarguil dev->tx_pkt_burst = removed_tx_burst; 1402e22920bSAdrien Mazarguil if (priv->rxqs != NULL) { 1412e22920bSAdrien Mazarguil /* XXX race condition if mlx5_rx_burst() is still running. */ 1422e22920bSAdrien Mazarguil usleep(1000); 1432e22920bSAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) { 14421c8bb49SNélio Laranjeiro struct rxq *rxq = (*priv->rxqs)[i]; 1450cdddf4dSNélio Laranjeiro struct rxq_ctrl *rxq_ctrl; 14621c8bb49SNélio Laranjeiro 14721c8bb49SNélio Laranjeiro if (rxq == NULL) 1482e22920bSAdrien Mazarguil continue; 1490cdddf4dSNélio Laranjeiro rxq_ctrl = container_of(rxq, struct rxq_ctrl, rxq); 1502e22920bSAdrien Mazarguil (*priv->rxqs)[i] = NULL; 1510cdddf4dSNélio Laranjeiro rxq_cleanup(rxq_ctrl); 1520cdddf4dSNélio Laranjeiro rte_free(rxq_ctrl); 1532e22920bSAdrien Mazarguil } 1542e22920bSAdrien Mazarguil priv->rxqs_n = 0; 1552e22920bSAdrien Mazarguil priv->rxqs = NULL; 1562e22920bSAdrien Mazarguil } 1572e22920bSAdrien Mazarguil if (priv->txqs != NULL) { 1582e22920bSAdrien Mazarguil /* XXX race condition if mlx5_tx_burst() is still running. */ 1592e22920bSAdrien Mazarguil usleep(1000); 1602e22920bSAdrien Mazarguil for (i = 0; (i != priv->txqs_n); ++i) { 16121c8bb49SNélio Laranjeiro struct txq *txq = (*priv->txqs)[i]; 16221c8bb49SNélio Laranjeiro struct txq_ctrl *txq_ctrl; 16321c8bb49SNélio Laranjeiro 16421c8bb49SNélio Laranjeiro if (txq == NULL) 1652e22920bSAdrien Mazarguil continue; 16621c8bb49SNélio Laranjeiro txq_ctrl = container_of(txq, struct txq_ctrl, txq); 1672e22920bSAdrien Mazarguil (*priv->txqs)[i] = NULL; 16821c8bb49SNélio Laranjeiro txq_cleanup(txq_ctrl); 16921c8bb49SNélio Laranjeiro rte_free(txq_ctrl); 1702e22920bSAdrien Mazarguil } 1712e22920bSAdrien Mazarguil priv->txqs_n = 0; 1722e22920bSAdrien Mazarguil priv->txqs = NULL; 1732e22920bSAdrien Mazarguil } 174771fa900SAdrien Mazarguil if (priv->pd != NULL) { 175771fa900SAdrien Mazarguil assert(priv->ctx != NULL); 176771fa900SAdrien Mazarguil claim_zero(ibv_dealloc_pd(priv->pd)); 177771fa900SAdrien Mazarguil claim_zero(ibv_close_device(priv->ctx)); 178771fa900SAdrien Mazarguil } else 179771fa900SAdrien Mazarguil assert(priv->ctx == NULL); 1800573873dSNelio Laranjeiro if (priv->rss_conf != NULL) { 1810573873dSNelio Laranjeiro for (i = 0; (i != hash_rxq_init_n); ++i) 1820573873dSNelio Laranjeiro rte_free((*priv->rss_conf)[i]); 1832f97422eSNelio Laranjeiro rte_free(priv->rss_conf); 1840573873dSNelio Laranjeiro } 185634efbc2SNelio Laranjeiro if (priv->reta_idx != NULL) 186634efbc2SNelio Laranjeiro rte_free(priv->reta_idx); 187771fa900SAdrien Mazarguil priv_unlock(priv); 188771fa900SAdrien Mazarguil memset(priv, 0, sizeof(*priv)); 189771fa900SAdrien Mazarguil } 190771fa900SAdrien Mazarguil 191771fa900SAdrien Mazarguil static const struct eth_dev_ops mlx5_dev_ops = { 192e60fbd5bSAdrien Mazarguil .dev_configure = mlx5_dev_configure, 193e60fbd5bSAdrien Mazarguil .dev_start = mlx5_dev_start, 194e60fbd5bSAdrien Mazarguil .dev_stop = mlx5_dev_stop, 19562072098SOr Ami .dev_set_link_down = mlx5_set_link_down, 19662072098SOr Ami .dev_set_link_up = mlx5_set_link_up, 197771fa900SAdrien Mazarguil .dev_close = mlx5_dev_close, 1981bdbe1afSAdrien Mazarguil .promiscuous_enable = mlx5_promiscuous_enable, 1991bdbe1afSAdrien Mazarguil .promiscuous_disable = mlx5_promiscuous_disable, 2001bdbe1afSAdrien Mazarguil .allmulticast_enable = mlx5_allmulticast_enable, 2011bdbe1afSAdrien Mazarguil .allmulticast_disable = mlx5_allmulticast_disable, 202cb8faed7SAdrien Mazarguil .link_update = mlx5_link_update, 20387011737SAdrien Mazarguil .stats_get = mlx5_stats_get, 20487011737SAdrien Mazarguil .stats_reset = mlx5_stats_reset, 205a4193ae3SShahaf Shuler .xstats_get = mlx5_xstats_get, 206a4193ae3SShahaf Shuler .xstats_reset = mlx5_xstats_reset, 207a4193ae3SShahaf Shuler .xstats_get_names = mlx5_xstats_get_names, 208e60fbd5bSAdrien Mazarguil .dev_infos_get = mlx5_dev_infos_get, 20978a38edfSJianfeng Tan .dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get, 210e9086978SAdrien Mazarguil .vlan_filter_set = mlx5_vlan_filter_set, 2112e22920bSAdrien Mazarguil .rx_queue_setup = mlx5_rx_queue_setup, 2122e22920bSAdrien Mazarguil .tx_queue_setup = mlx5_tx_queue_setup, 2132e22920bSAdrien Mazarguil .rx_queue_release = mlx5_rx_queue_release, 2142e22920bSAdrien Mazarguil .tx_queue_release = mlx5_tx_queue_release, 21502d75430SAdrien Mazarguil .flow_ctrl_get = mlx5_dev_get_flow_ctrl, 21602d75430SAdrien Mazarguil .flow_ctrl_set = mlx5_dev_set_flow_ctrl, 2173318aef7SAdrien Mazarguil .mac_addr_remove = mlx5_mac_addr_remove, 2183318aef7SAdrien Mazarguil .mac_addr_add = mlx5_mac_addr_add, 21986977fccSDavid Marchand .mac_addr_set = mlx5_mac_addr_set, 220cf37ca95SAdrien Mazarguil .mtu_set = mlx5_dev_set_mtu, 221f3db9489SYaacov Hazan .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, 222f3db9489SYaacov Hazan .vlan_offload_set = mlx5_vlan_offload_set, 223634efbc2SNelio Laranjeiro .reta_update = mlx5_dev_rss_reta_update, 224634efbc2SNelio Laranjeiro .reta_query = mlx5_dev_rss_reta_query, 2252f97422eSNelio Laranjeiro .rss_hash_update = mlx5_rss_hash_update, 2262f97422eSNelio Laranjeiro .rss_hash_conf_get = mlx5_rss_hash_conf_get, 22776f5c99eSYaacov Hazan .filter_ctrl = mlx5_dev_filter_ctrl, 2288788fec1SOlivier Matz .rx_descriptor_status = mlx5_rx_descriptor_status, 2298788fec1SOlivier Matz .tx_descriptor_status = mlx5_tx_descriptor_status, 230771fa900SAdrien Mazarguil }; 231771fa900SAdrien Mazarguil 232771fa900SAdrien Mazarguil static struct { 233771fa900SAdrien Mazarguil struct rte_pci_addr pci_addr; /* associated PCI address */ 234771fa900SAdrien Mazarguil uint32_t ports; /* physical ports bitfield. */ 235771fa900SAdrien Mazarguil } mlx5_dev[32]; 236771fa900SAdrien Mazarguil 237771fa900SAdrien Mazarguil /** 238771fa900SAdrien Mazarguil * Get device index in mlx5_dev[] from PCI bus address. 239771fa900SAdrien Mazarguil * 240771fa900SAdrien Mazarguil * @param[in] pci_addr 241771fa900SAdrien Mazarguil * PCI bus address to look for. 242771fa900SAdrien Mazarguil * 243771fa900SAdrien Mazarguil * @return 244771fa900SAdrien Mazarguil * mlx5_dev[] index on success, -1 on failure. 245771fa900SAdrien Mazarguil */ 246771fa900SAdrien Mazarguil static int 247771fa900SAdrien Mazarguil mlx5_dev_idx(struct rte_pci_addr *pci_addr) 248771fa900SAdrien Mazarguil { 249771fa900SAdrien Mazarguil unsigned int i; 250771fa900SAdrien Mazarguil int ret = -1; 251771fa900SAdrien Mazarguil 252771fa900SAdrien Mazarguil assert(pci_addr != NULL); 253771fa900SAdrien Mazarguil for (i = 0; (i != RTE_DIM(mlx5_dev)); ++i) { 254771fa900SAdrien Mazarguil if ((mlx5_dev[i].pci_addr.domain == pci_addr->domain) && 255771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.bus == pci_addr->bus) && 256771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.devid == pci_addr->devid) && 257771fa900SAdrien Mazarguil (mlx5_dev[i].pci_addr.function == pci_addr->function)) 258771fa900SAdrien Mazarguil return i; 259771fa900SAdrien Mazarguil if ((mlx5_dev[i].ports == 0) && (ret == -1)) 260771fa900SAdrien Mazarguil ret = i; 261771fa900SAdrien Mazarguil } 262771fa900SAdrien Mazarguil return ret; 263771fa900SAdrien Mazarguil } 264771fa900SAdrien Mazarguil 265e72dd09bSNélio Laranjeiro /** 266e72dd09bSNélio Laranjeiro * Verify and store value for device argument. 267e72dd09bSNélio Laranjeiro * 268e72dd09bSNélio Laranjeiro * @param[in] key 269e72dd09bSNélio Laranjeiro * Key argument to verify. 270e72dd09bSNélio Laranjeiro * @param[in] val 271e72dd09bSNélio Laranjeiro * Value associated with key. 272e72dd09bSNélio Laranjeiro * @param opaque 273e72dd09bSNélio Laranjeiro * User data. 274e72dd09bSNélio Laranjeiro * 275e72dd09bSNélio Laranjeiro * @return 276e72dd09bSNélio Laranjeiro * 0 on success, negative errno value on failure. 277e72dd09bSNélio Laranjeiro */ 278e72dd09bSNélio Laranjeiro static int 279e72dd09bSNélio Laranjeiro mlx5_args_check(const char *key, const char *val, void *opaque) 280e72dd09bSNélio Laranjeiro { 281e72dd09bSNélio Laranjeiro struct priv *priv = opaque; 28299c12dccSNélio Laranjeiro unsigned long tmp; 283e72dd09bSNélio Laranjeiro 28499c12dccSNélio Laranjeiro errno = 0; 28599c12dccSNélio Laranjeiro tmp = strtoul(val, NULL, 0); 28699c12dccSNélio Laranjeiro if (errno) { 28799c12dccSNélio Laranjeiro WARN("%s: \"%s\" is not a valid integer", key, val); 28899c12dccSNélio Laranjeiro return errno; 28999c12dccSNélio Laranjeiro } 29099c12dccSNélio Laranjeiro if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) { 29199c12dccSNélio Laranjeiro priv->cqe_comp = !!tmp; 2922a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { 2932a66cf37SYaacov Hazan priv->txq_inline = tmp; 2942a66cf37SYaacov Hazan } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { 2952a66cf37SYaacov Hazan priv->txqs_inline = tmp; 296230189d9SNélio Laranjeiro } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { 297528a9fbeSYongseok Koh priv->mps &= !!tmp; /* Enable MPW only if HW supports */ 298*3f13f8c2SShahaf Shuler } else if (strcmp(MLX5_TSO, key) == 0) { 299*3f13f8c2SShahaf Shuler priv->tso = !!tmp; 30099c12dccSNélio Laranjeiro } else { 301e72dd09bSNélio Laranjeiro WARN("%s: unknown parameter", key); 302e72dd09bSNélio Laranjeiro return -EINVAL; 303e72dd09bSNélio Laranjeiro } 30499c12dccSNélio Laranjeiro return 0; 30599c12dccSNélio Laranjeiro } 306e72dd09bSNélio Laranjeiro 307e72dd09bSNélio Laranjeiro /** 308e72dd09bSNélio Laranjeiro * Parse device parameters. 309e72dd09bSNélio Laranjeiro * 310e72dd09bSNélio Laranjeiro * @param priv 311e72dd09bSNélio Laranjeiro * Pointer to private structure. 312e72dd09bSNélio Laranjeiro * @param devargs 313e72dd09bSNélio Laranjeiro * Device arguments structure. 314e72dd09bSNélio Laranjeiro * 315e72dd09bSNélio Laranjeiro * @return 316e72dd09bSNélio Laranjeiro * 0 on success, errno value on failure. 317e72dd09bSNélio Laranjeiro */ 318e72dd09bSNélio Laranjeiro static int 319e72dd09bSNélio Laranjeiro mlx5_args(struct priv *priv, struct rte_devargs *devargs) 320e72dd09bSNélio Laranjeiro { 321e72dd09bSNélio Laranjeiro const char **params = (const char *[]){ 32299c12dccSNélio Laranjeiro MLX5_RXQ_CQE_COMP_EN, 3232a66cf37SYaacov Hazan MLX5_TXQ_INLINE, 3242a66cf37SYaacov Hazan MLX5_TXQS_MIN_INLINE, 325230189d9SNélio Laranjeiro MLX5_TXQ_MPW_EN, 326*3f13f8c2SShahaf Shuler MLX5_TSO, 327e72dd09bSNélio Laranjeiro NULL, 328e72dd09bSNélio Laranjeiro }; 329e72dd09bSNélio Laranjeiro struct rte_kvargs *kvlist; 330e72dd09bSNélio Laranjeiro int ret = 0; 331e72dd09bSNélio Laranjeiro int i; 332e72dd09bSNélio Laranjeiro 333e72dd09bSNélio Laranjeiro if (devargs == NULL) 334e72dd09bSNélio Laranjeiro return 0; 335e72dd09bSNélio Laranjeiro /* Following UGLY cast is done to pass checkpatch. */ 336e72dd09bSNélio Laranjeiro kvlist = rte_kvargs_parse(devargs->args, params); 337e72dd09bSNélio Laranjeiro if (kvlist == NULL) 338e72dd09bSNélio Laranjeiro return 0; 339e72dd09bSNélio Laranjeiro /* Process parameters. */ 340e72dd09bSNélio Laranjeiro for (i = 0; (params[i] != NULL); ++i) { 341e72dd09bSNélio Laranjeiro if (rte_kvargs_count(kvlist, params[i])) { 342e72dd09bSNélio Laranjeiro ret = rte_kvargs_process(kvlist, params[i], 343e72dd09bSNélio Laranjeiro mlx5_args_check, priv); 344a67323e4SShahaf Shuler if (ret != 0) { 345a67323e4SShahaf Shuler rte_kvargs_free(kvlist); 346e72dd09bSNélio Laranjeiro return ret; 347e72dd09bSNélio Laranjeiro } 348e72dd09bSNélio Laranjeiro } 349a67323e4SShahaf Shuler } 350e72dd09bSNélio Laranjeiro rte_kvargs_free(kvlist); 351e72dd09bSNélio Laranjeiro return 0; 352e72dd09bSNélio Laranjeiro } 353e72dd09bSNélio Laranjeiro 354771fa900SAdrien Mazarguil static struct eth_driver mlx5_driver; 355771fa900SAdrien Mazarguil 356771fa900SAdrien Mazarguil /** 357771fa900SAdrien Mazarguil * DPDK callback to register a PCI device. 358771fa900SAdrien Mazarguil * 359771fa900SAdrien Mazarguil * This function creates an Ethernet device for each port of a given 360771fa900SAdrien Mazarguil * PCI device. 361771fa900SAdrien Mazarguil * 362771fa900SAdrien Mazarguil * @param[in] pci_drv 363771fa900SAdrien Mazarguil * PCI driver structure (mlx5_driver). 364771fa900SAdrien Mazarguil * @param[in] pci_dev 365771fa900SAdrien Mazarguil * PCI device information. 366771fa900SAdrien Mazarguil * 367771fa900SAdrien Mazarguil * @return 368771fa900SAdrien Mazarguil * 0 on success, negative errno value on failure. 369771fa900SAdrien Mazarguil */ 370771fa900SAdrien Mazarguil static int 371af424af8SShreyansh Jain mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 372771fa900SAdrien Mazarguil { 373771fa900SAdrien Mazarguil struct ibv_device **list; 374771fa900SAdrien Mazarguil struct ibv_device *ibv_dev; 375771fa900SAdrien Mazarguil int err = 0; 376771fa900SAdrien Mazarguil struct ibv_context *attr_ctx = NULL; 377771fa900SAdrien Mazarguil struct ibv_device_attr device_attr; 37885e347dbSNélio Laranjeiro unsigned int sriov; 379e192ef80SYaacov Hazan unsigned int mps; 380771fa900SAdrien Mazarguil int idx; 381771fa900SAdrien Mazarguil int i; 382771fa900SAdrien Mazarguil 383771fa900SAdrien Mazarguil (void)pci_drv; 384771fa900SAdrien Mazarguil assert(pci_drv == &mlx5_driver.pci_drv); 385771fa900SAdrien Mazarguil /* Get mlx5_dev[] index. */ 386771fa900SAdrien Mazarguil idx = mlx5_dev_idx(&pci_dev->addr); 387771fa900SAdrien Mazarguil if (idx == -1) { 388771fa900SAdrien Mazarguil ERROR("this driver cannot support any more adapters"); 389771fa900SAdrien Mazarguil return -ENOMEM; 390771fa900SAdrien Mazarguil } 391771fa900SAdrien Mazarguil DEBUG("using driver device index %d", idx); 392771fa900SAdrien Mazarguil 393771fa900SAdrien Mazarguil /* Save PCI address. */ 394771fa900SAdrien Mazarguil mlx5_dev[idx].pci_addr = pci_dev->addr; 395771fa900SAdrien Mazarguil list = ibv_get_device_list(&i); 396771fa900SAdrien Mazarguil if (list == NULL) { 397771fa900SAdrien Mazarguil assert(errno); 398771fa900SAdrien Mazarguil if (errno == ENOSYS) { 399771fa900SAdrien Mazarguil WARN("cannot list devices, is ib_uverbs loaded?"); 400771fa900SAdrien Mazarguil return 0; 401771fa900SAdrien Mazarguil } 402771fa900SAdrien Mazarguil return -errno; 403771fa900SAdrien Mazarguil } 404771fa900SAdrien Mazarguil assert(i >= 0); 405771fa900SAdrien Mazarguil /* 406771fa900SAdrien Mazarguil * For each listed device, check related sysfs entry against 407771fa900SAdrien Mazarguil * the provided PCI ID. 408771fa900SAdrien Mazarguil */ 409771fa900SAdrien Mazarguil while (i != 0) { 410771fa900SAdrien Mazarguil struct rte_pci_addr pci_addr; 411771fa900SAdrien Mazarguil 412771fa900SAdrien Mazarguil --i; 413771fa900SAdrien Mazarguil DEBUG("checking device \"%s\"", list[i]->name); 414771fa900SAdrien Mazarguil if (mlx5_ibv_device_to_pci_addr(list[i], &pci_addr)) 415771fa900SAdrien Mazarguil continue; 416771fa900SAdrien Mazarguil if ((pci_dev->addr.domain != pci_addr.domain) || 417771fa900SAdrien Mazarguil (pci_dev->addr.bus != pci_addr.bus) || 418771fa900SAdrien Mazarguil (pci_dev->addr.devid != pci_addr.devid) || 419771fa900SAdrien Mazarguil (pci_dev->addr.function != pci_addr.function)) 420771fa900SAdrien Mazarguil continue; 42185e347dbSNélio Laranjeiro sriov = ((pci_dev->id.device_id == 422771fa900SAdrien Mazarguil PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) || 423771fa900SAdrien Mazarguil (pci_dev->id.device_id == 424528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) || 425528a9fbeSYongseok Koh (pci_dev->id.device_id == 426528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) || 427528a9fbeSYongseok Koh (pci_dev->id.device_id == 428528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF)); 429528a9fbeSYongseok Koh /* 430528a9fbeSYongseok Koh * Multi-packet send is supported by ConnectX-4 Lx PF as well 431528a9fbeSYongseok Koh * as all ConnectX-5 devices. 432528a9fbeSYongseok Koh */ 433528a9fbeSYongseok Koh switch (pci_dev->id.device_id) { 434528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: 435528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5: 436528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 437528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: 438528a9fbeSYongseok Koh case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 439528a9fbeSYongseok Koh mps = 1; 440528a9fbeSYongseok Koh break; 441528a9fbeSYongseok Koh default: 442528a9fbeSYongseok Koh mps = 0; 443528a9fbeSYongseok Koh } 44485e347dbSNélio Laranjeiro INFO("PCI information matches, using device \"%s\"" 44585e347dbSNélio Laranjeiro " (SR-IOV: %s, MPS: %s)", 446e192ef80SYaacov Hazan list[i]->name, 44785e347dbSNélio Laranjeiro sriov ? "true" : "false", 448e192ef80SYaacov Hazan mps ? "true" : "false"); 449771fa900SAdrien Mazarguil attr_ctx = ibv_open_device(list[i]); 450771fa900SAdrien Mazarguil err = errno; 451771fa900SAdrien Mazarguil break; 452771fa900SAdrien Mazarguil } 453771fa900SAdrien Mazarguil if (attr_ctx == NULL) { 454771fa900SAdrien Mazarguil ibv_free_device_list(list); 455771fa900SAdrien Mazarguil switch (err) { 456771fa900SAdrien Mazarguil case 0: 457771fa900SAdrien Mazarguil WARN("cannot access device, is mlx5_ib loaded?"); 458771fa900SAdrien Mazarguil return 0; 459771fa900SAdrien Mazarguil case EINVAL: 460771fa900SAdrien Mazarguil WARN("cannot use device, are drivers up to date?"); 461771fa900SAdrien Mazarguil return 0; 462771fa900SAdrien Mazarguil } 463771fa900SAdrien Mazarguil assert(err > 0); 464771fa900SAdrien Mazarguil return -err; 465771fa900SAdrien Mazarguil } 466771fa900SAdrien Mazarguil ibv_dev = list[i]; 467771fa900SAdrien Mazarguil 468771fa900SAdrien Mazarguil DEBUG("device opened"); 469771fa900SAdrien Mazarguil if (ibv_query_device(attr_ctx, &device_attr)) 470771fa900SAdrien Mazarguil goto error; 471771fa900SAdrien Mazarguil INFO("%u port(s) detected", device_attr.phys_port_cnt); 472771fa900SAdrien Mazarguil 473771fa900SAdrien Mazarguil for (i = 0; i < device_attr.phys_port_cnt; i++) { 474771fa900SAdrien Mazarguil uint32_t port = i + 1; /* ports are indexed from one */ 475771fa900SAdrien Mazarguil uint32_t test = (1 << i); 476771fa900SAdrien Mazarguil struct ibv_context *ctx = NULL; 477771fa900SAdrien Mazarguil struct ibv_port_attr port_attr; 478771fa900SAdrien Mazarguil struct ibv_pd *pd = NULL; 479771fa900SAdrien Mazarguil struct priv *priv = NULL; 480771fa900SAdrien Mazarguil struct rte_eth_dev *eth_dev; 481771fa900SAdrien Mazarguil struct ibv_exp_device_attr exp_device_attr; 482771fa900SAdrien Mazarguil struct ether_addr mac; 48385e347dbSNélio Laranjeiro uint16_t num_vfs = 0; 484771fa900SAdrien Mazarguil 48595e16ef3SNelio Laranjeiro exp_device_attr.comp_mask = 48695e16ef3SNelio Laranjeiro IBV_EXP_DEVICE_ATTR_EXP_CAP_FLAGS | 487f3db9489SYaacov Hazan IBV_EXP_DEVICE_ATTR_RX_HASH | 488f3db9489SYaacov Hazan IBV_EXP_DEVICE_ATTR_VLAN_OFFLOADS | 4894d803a72SOlga Shern IBV_EXP_DEVICE_ATTR_RX_PAD_END_ALIGN | 490*3f13f8c2SShahaf Shuler IBV_EXP_DEVICE_ATTR_TSO_CAPS | 491f3db9489SYaacov Hazan 0; 492771fa900SAdrien Mazarguil 493771fa900SAdrien Mazarguil DEBUG("using port %u (%08" PRIx32 ")", port, test); 494771fa900SAdrien Mazarguil 495771fa900SAdrien Mazarguil ctx = ibv_open_device(ibv_dev); 496771fa900SAdrien Mazarguil if (ctx == NULL) 497771fa900SAdrien Mazarguil goto port_error; 498771fa900SAdrien Mazarguil 499771fa900SAdrien Mazarguil /* Check port status. */ 500771fa900SAdrien Mazarguil err = ibv_query_port(ctx, port, &port_attr); 501771fa900SAdrien Mazarguil if (err) { 502771fa900SAdrien Mazarguil ERROR("port query failed: %s", strerror(err)); 503771fa900SAdrien Mazarguil goto port_error; 504771fa900SAdrien Mazarguil } 5051371f4dfSOr Ami 5061371f4dfSOr Ami if (port_attr.link_layer != IBV_LINK_LAYER_ETHERNET) { 5071371f4dfSOr Ami ERROR("port %d is not configured in Ethernet mode", 5081371f4dfSOr Ami port); 5091371f4dfSOr Ami goto port_error; 5101371f4dfSOr Ami } 5111371f4dfSOr Ami 512771fa900SAdrien Mazarguil if (port_attr.state != IBV_PORT_ACTIVE) 513771fa900SAdrien Mazarguil DEBUG("port %d is not active: \"%s\" (%d)", 514771fa900SAdrien Mazarguil port, ibv_port_state_str(port_attr.state), 515771fa900SAdrien Mazarguil port_attr.state); 516771fa900SAdrien Mazarguil 517771fa900SAdrien Mazarguil /* Allocate protection domain. */ 518771fa900SAdrien Mazarguil pd = ibv_alloc_pd(ctx); 519771fa900SAdrien Mazarguil if (pd == NULL) { 520771fa900SAdrien Mazarguil ERROR("PD allocation failure"); 521771fa900SAdrien Mazarguil err = ENOMEM; 522771fa900SAdrien Mazarguil goto port_error; 523771fa900SAdrien Mazarguil } 524771fa900SAdrien Mazarguil 525771fa900SAdrien Mazarguil mlx5_dev[idx].ports |= test; 526771fa900SAdrien Mazarguil 527771fa900SAdrien Mazarguil /* from rte_ethdev.c */ 528771fa900SAdrien Mazarguil priv = rte_zmalloc("ethdev private structure", 529771fa900SAdrien Mazarguil sizeof(*priv), 530771fa900SAdrien Mazarguil RTE_CACHE_LINE_SIZE); 531771fa900SAdrien Mazarguil if (priv == NULL) { 532771fa900SAdrien Mazarguil ERROR("priv allocation failure"); 533771fa900SAdrien Mazarguil err = ENOMEM; 534771fa900SAdrien Mazarguil goto port_error; 535771fa900SAdrien Mazarguil } 536771fa900SAdrien Mazarguil 537771fa900SAdrien Mazarguil priv->ctx = ctx; 538771fa900SAdrien Mazarguil priv->device_attr = device_attr; 539771fa900SAdrien Mazarguil priv->port = port; 540771fa900SAdrien Mazarguil priv->pd = pd; 541771fa900SAdrien Mazarguil priv->mtu = ETHER_MTU; 542230189d9SNélio Laranjeiro priv->mps = mps; /* Enable MPW by default if supported. */ 54399c12dccSNélio Laranjeiro priv->cqe_comp = 1; /* Enable compression by default. */ 54413a1317dSJan Viktorin err = mlx5_args(priv, pci_dev->device.devargs); 545e72dd09bSNélio Laranjeiro if (err) { 546e72dd09bSNélio Laranjeiro ERROR("failed to process device arguments: %s", 547e72dd09bSNélio Laranjeiro strerror(err)); 548e72dd09bSNélio Laranjeiro goto port_error; 549e72dd09bSNélio Laranjeiro } 550771fa900SAdrien Mazarguil if (ibv_exp_query_device(ctx, &exp_device_attr)) { 551771fa900SAdrien Mazarguil ERROR("ibv_exp_query_device() failed"); 552771fa900SAdrien Mazarguil goto port_error; 553771fa900SAdrien Mazarguil } 554771fa900SAdrien Mazarguil 555771fa900SAdrien Mazarguil priv->hw_csum = 556771fa900SAdrien Mazarguil ((exp_device_attr.exp_device_cap_flags & 557771fa900SAdrien Mazarguil IBV_EXP_DEVICE_RX_CSUM_TCP_UDP_PKT) && 558771fa900SAdrien Mazarguil (exp_device_attr.exp_device_cap_flags & 559771fa900SAdrien Mazarguil IBV_EXP_DEVICE_RX_CSUM_IP_PKT)); 560771fa900SAdrien Mazarguil DEBUG("checksum offloading is %ssupported", 561771fa900SAdrien Mazarguil (priv->hw_csum ? "" : "not ")); 562771fa900SAdrien Mazarguil 563771fa900SAdrien Mazarguil priv->hw_csum_l2tun = !!(exp_device_attr.exp_device_cap_flags & 564771fa900SAdrien Mazarguil IBV_EXP_DEVICE_VXLAN_SUPPORT); 565771fa900SAdrien Mazarguil DEBUG("L2 tunnel checksum offloads are %ssupported", 566771fa900SAdrien Mazarguil (priv->hw_csum_l2tun ? "" : "not ")); 567771fa900SAdrien Mazarguil 56813d57bd5SAdrien Mazarguil priv->ind_table_max_size = exp_device_attr.rx_hash_caps.max_rwq_indirection_table_size; 56913d57bd5SAdrien Mazarguil /* Remove this check once DPDK supports larger/variable 57013d57bd5SAdrien Mazarguil * indirection tables. */ 571ec1fed22SYongseok Koh if (priv->ind_table_max_size > 572ec1fed22SYongseok Koh (unsigned int)ETH_RSS_RETA_SIZE_512) 573ec1fed22SYongseok Koh priv->ind_table_max_size = ETH_RSS_RETA_SIZE_512; 57495e16ef3SNelio Laranjeiro DEBUG("maximum RX indirection table size is %u", 57595e16ef3SNelio Laranjeiro priv->ind_table_max_size); 576f3db9489SYaacov Hazan priv->hw_vlan_strip = !!(exp_device_attr.wq_vlan_offloads_cap & 577f3db9489SYaacov Hazan IBV_EXP_RECEIVE_WQ_CVLAN_STRIP); 578f3db9489SYaacov Hazan DEBUG("VLAN stripping is %ssupported", 579f3db9489SYaacov Hazan (priv->hw_vlan_strip ? "" : "not ")); 58095e16ef3SNelio Laranjeiro 5814d326709SOlga Shern priv->hw_fcs_strip = !!(exp_device_attr.exp_device_cap_flags & 5824d326709SOlga Shern IBV_EXP_DEVICE_SCATTER_FCS); 5834d326709SOlga Shern DEBUG("FCS stripping configuration is %ssupported", 5844d326709SOlga Shern (priv->hw_fcs_strip ? "" : "not ")); 5854d326709SOlga Shern 5864d803a72SOlga Shern priv->hw_padding = !!exp_device_attr.rx_pad_end_addr_align; 5874d803a72SOlga Shern DEBUG("hardware RX end alignment padding is %ssupported", 5884d803a72SOlga Shern (priv->hw_padding ? "" : "not ")); 5894d803a72SOlga Shern 59085e347dbSNélio Laranjeiro priv_get_num_vfs(priv, &num_vfs); 59185e347dbSNélio Laranjeiro priv->sriov = (num_vfs || sriov); 592*3f13f8c2SShahaf Shuler priv->tso = ((priv->tso) && 593*3f13f8c2SShahaf Shuler (exp_device_attr.tso_caps.max_tso > 0) && 594*3f13f8c2SShahaf Shuler (exp_device_attr.tso_caps.supported_qpts & 595*3f13f8c2SShahaf Shuler (1 << IBV_QPT_RAW_ETH))); 596*3f13f8c2SShahaf Shuler if (priv->tso) 597*3f13f8c2SShahaf Shuler priv->max_tso_payload_sz = 598*3f13f8c2SShahaf Shuler exp_device_attr.tso_caps.max_tso; 599230189d9SNélio Laranjeiro if (priv->mps && !mps) { 600230189d9SNélio Laranjeiro ERROR("multi-packet send not supported on this device" 601230189d9SNélio Laranjeiro " (" MLX5_TXQ_MPW_EN ")"); 602230189d9SNélio Laranjeiro err = ENOTSUP; 603230189d9SNélio Laranjeiro goto port_error; 604*3f13f8c2SShahaf Shuler } else if (priv->mps && priv->tso) { 605*3f13f8c2SShahaf Shuler WARN("multi-packet send not supported in conjunction " 606*3f13f8c2SShahaf Shuler "with TSO. MPS disabled"); 607*3f13f8c2SShahaf Shuler priv->mps = 0; 608230189d9SNélio Laranjeiro } 6090573873dSNelio Laranjeiro /* Allocate and register default RSS hash keys. */ 6100573873dSNelio Laranjeiro priv->rss_conf = rte_calloc(__func__, hash_rxq_init_n, 6110573873dSNelio Laranjeiro sizeof((*priv->rss_conf)[0]), 0); 6120573873dSNelio Laranjeiro if (priv->rss_conf == NULL) { 6130573873dSNelio Laranjeiro err = ENOMEM; 6140573873dSNelio Laranjeiro goto port_error; 6150573873dSNelio Laranjeiro } 6162f97422eSNelio Laranjeiro err = rss_hash_rss_conf_new_key(priv, 6172f97422eSNelio Laranjeiro rss_hash_default_key, 6180573873dSNelio Laranjeiro rss_hash_default_key_len, 6190573873dSNelio Laranjeiro ETH_RSS_PROTO_MASK); 6202f97422eSNelio Laranjeiro if (err) 6212f97422eSNelio Laranjeiro goto port_error; 622771fa900SAdrien Mazarguil /* Configure the first MAC address by default. */ 623771fa900SAdrien Mazarguil if (priv_get_mac(priv, &mac.addr_bytes)) { 624771fa900SAdrien Mazarguil ERROR("cannot get MAC address, is mlx5_en loaded?" 625771fa900SAdrien Mazarguil " (errno: %s)", strerror(errno)); 626771fa900SAdrien Mazarguil goto port_error; 627771fa900SAdrien Mazarguil } 628771fa900SAdrien Mazarguil INFO("port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x", 629771fa900SAdrien Mazarguil priv->port, 630771fa900SAdrien Mazarguil mac.addr_bytes[0], mac.addr_bytes[1], 631771fa900SAdrien Mazarguil mac.addr_bytes[2], mac.addr_bytes[3], 632771fa900SAdrien Mazarguil mac.addr_bytes[4], mac.addr_bytes[5]); 6330497ddaaSYaacov Hazan /* Register MAC address. */ 634771fa900SAdrien Mazarguil claim_zero(priv_mac_addr_add(priv, 0, 635771fa900SAdrien Mazarguil (const uint8_t (*)[ETHER_ADDR_LEN]) 636771fa900SAdrien Mazarguil mac.addr_bytes)); 63776f5c99eSYaacov Hazan /* Initialize FD filters list. */ 63876f5c99eSYaacov Hazan err = fdir_init_filters_list(priv); 63976f5c99eSYaacov Hazan if (err) 64076f5c99eSYaacov Hazan goto port_error; 641771fa900SAdrien Mazarguil #ifndef NDEBUG 642771fa900SAdrien Mazarguil { 643771fa900SAdrien Mazarguil char ifname[IF_NAMESIZE]; 644771fa900SAdrien Mazarguil 645771fa900SAdrien Mazarguil if (priv_get_ifname(priv, &ifname) == 0) 646771fa900SAdrien Mazarguil DEBUG("port %u ifname is \"%s\"", 647771fa900SAdrien Mazarguil priv->port, ifname); 648771fa900SAdrien Mazarguil else 649771fa900SAdrien Mazarguil DEBUG("port %u ifname is unknown", priv->port); 650771fa900SAdrien Mazarguil } 651771fa900SAdrien Mazarguil #endif 652771fa900SAdrien Mazarguil /* Get actual MTU if possible. */ 653771fa900SAdrien Mazarguil priv_get_mtu(priv, &priv->mtu); 654771fa900SAdrien Mazarguil DEBUG("port %u MTU is %u", priv->port, priv->mtu); 655771fa900SAdrien Mazarguil 656771fa900SAdrien Mazarguil /* from rte_ethdev.c */ 657771fa900SAdrien Mazarguil { 658771fa900SAdrien Mazarguil char name[RTE_ETH_NAME_MAX_LEN]; 659771fa900SAdrien Mazarguil 660771fa900SAdrien Mazarguil snprintf(name, sizeof(name), "%s port %u", 661771fa900SAdrien Mazarguil ibv_get_device_name(ibv_dev), port); 6626751f6deSDavid Marchand eth_dev = rte_eth_dev_allocate(name); 663771fa900SAdrien Mazarguil } 664771fa900SAdrien Mazarguil if (eth_dev == NULL) { 665771fa900SAdrien Mazarguil ERROR("can not allocate rte ethdev"); 666771fa900SAdrien Mazarguil err = ENOMEM; 667771fa900SAdrien Mazarguil goto port_error; 668771fa900SAdrien Mazarguil } 669771fa900SAdrien Mazarguil 670a48deadaSOr Ami /* Secondary processes have to use local storage for their 671a48deadaSOr Ami * private data as well as a copy of eth_dev->data, but this 672a48deadaSOr Ami * pointer must not be modified before burst functions are 673a48deadaSOr Ami * actually called. */ 674a48deadaSOr Ami if (mlx5_is_secondary()) { 675a48deadaSOr Ami struct mlx5_secondary_data *sd = 676a48deadaSOr Ami &mlx5_secondary_data[eth_dev->data->port_id]; 677a48deadaSOr Ami sd->primary_priv = eth_dev->data->dev_private; 678a48deadaSOr Ami if (sd->primary_priv == NULL) { 679a48deadaSOr Ami ERROR("no private data for port %u", 680a48deadaSOr Ami eth_dev->data->port_id); 681a48deadaSOr Ami err = EINVAL; 682a48deadaSOr Ami goto port_error; 683a48deadaSOr Ami } 684a48deadaSOr Ami sd->shared_dev_data = eth_dev->data; 685a48deadaSOr Ami rte_spinlock_init(&sd->lock); 686a48deadaSOr Ami memcpy(sd->data.name, sd->shared_dev_data->name, 687a48deadaSOr Ami sizeof(sd->data.name)); 688a48deadaSOr Ami sd->data.dev_private = priv; 689a48deadaSOr Ami sd->data.rx_mbuf_alloc_failed = 0; 690a48deadaSOr Ami sd->data.mtu = ETHER_MTU; 691a48deadaSOr Ami sd->data.port_id = sd->shared_dev_data->port_id; 692a48deadaSOr Ami sd->data.mac_addrs = priv->mac; 693a48deadaSOr Ami eth_dev->tx_pkt_burst = mlx5_tx_burst_secondary_setup; 694a48deadaSOr Ami eth_dev->rx_pkt_burst = mlx5_rx_burst_secondary_setup; 695a48deadaSOr Ami } else { 696771fa900SAdrien Mazarguil eth_dev->data->dev_private = priv; 697a48deadaSOr Ami eth_dev->data->mac_addrs = priv->mac; 698a48deadaSOr Ami } 699771fa900SAdrien Mazarguil 700eac901ceSJan Blunck eth_dev->device = &pci_dev->device; 701a48deadaSOr Ami rte_eth_copy_pci_info(eth_dev, pci_dev); 702a48deadaSOr Ami eth_dev->driver = &mlx5_driver; 703771fa900SAdrien Mazarguil priv->dev = eth_dev; 704771fa900SAdrien Mazarguil eth_dev->dev_ops = &mlx5_dev_ops; 705a48deadaSOr Ami 706771fa900SAdrien Mazarguil /* Bring Ethernet device up. */ 707771fa900SAdrien Mazarguil DEBUG("forcing Ethernet interface up"); 708771fa900SAdrien Mazarguil priv_set_flags(priv, ~IFF_UP, IFF_UP); 7092c960a51SMatthieu Ternisien d'Ouville mlx5_link_update(priv->dev, 1); 710771fa900SAdrien Mazarguil continue; 711771fa900SAdrien Mazarguil 712771fa900SAdrien Mazarguil port_error: 7132f636ae5SOr Ami if (priv) { 7142f97422eSNelio Laranjeiro rte_free(priv->rss_conf); 715771fa900SAdrien Mazarguil rte_free(priv); 7162f636ae5SOr Ami } 717771fa900SAdrien Mazarguil if (pd) 718771fa900SAdrien Mazarguil claim_zero(ibv_dealloc_pd(pd)); 719771fa900SAdrien Mazarguil if (ctx) 720771fa900SAdrien Mazarguil claim_zero(ibv_close_device(ctx)); 721771fa900SAdrien Mazarguil break; 722771fa900SAdrien Mazarguil } 723771fa900SAdrien Mazarguil 724771fa900SAdrien Mazarguil /* 725771fa900SAdrien Mazarguil * XXX if something went wrong in the loop above, there is a resource 726771fa900SAdrien Mazarguil * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as 727771fa900SAdrien Mazarguil * long as the dpdk does not provide a way to deallocate a ethdev and a 728771fa900SAdrien Mazarguil * way to enumerate the registered ethdevs to free the previous ones. 729771fa900SAdrien Mazarguil */ 730771fa900SAdrien Mazarguil 731771fa900SAdrien Mazarguil /* no port found, complain */ 732771fa900SAdrien Mazarguil if (!mlx5_dev[idx].ports) { 733771fa900SAdrien Mazarguil err = ENODEV; 734771fa900SAdrien Mazarguil goto error; 735771fa900SAdrien Mazarguil } 736771fa900SAdrien Mazarguil 737771fa900SAdrien Mazarguil error: 738771fa900SAdrien Mazarguil if (attr_ctx) 739771fa900SAdrien Mazarguil claim_zero(ibv_close_device(attr_ctx)); 740771fa900SAdrien Mazarguil if (list) 741771fa900SAdrien Mazarguil ibv_free_device_list(list); 742771fa900SAdrien Mazarguil assert(err >= 0); 743771fa900SAdrien Mazarguil return -err; 744771fa900SAdrien Mazarguil } 745771fa900SAdrien Mazarguil 746771fa900SAdrien Mazarguil static const struct rte_pci_id mlx5_pci_id_map[] = { 747771fa900SAdrien Mazarguil { 7481d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 7491d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4) 750771fa900SAdrien Mazarguil }, 751771fa900SAdrien Mazarguil { 7521d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 7531d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) 754771fa900SAdrien Mazarguil }, 755771fa900SAdrien Mazarguil { 7561d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 7571d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LX) 758771fa900SAdrien Mazarguil }, 759771fa900SAdrien Mazarguil { 7601d1bc870SNélio Laranjeiro RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 7611d1bc870SNélio Laranjeiro PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) 762771fa900SAdrien Mazarguil }, 763771fa900SAdrien Mazarguil { 764528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 765528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5) 766528a9fbeSYongseok Koh }, 767528a9fbeSYongseok Koh { 768528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 769528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) 770528a9fbeSYongseok Koh }, 771528a9fbeSYongseok Koh { 772528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 773528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EX) 774528a9fbeSYongseok Koh }, 775528a9fbeSYongseok Koh { 776528a9fbeSYongseok Koh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 777528a9fbeSYongseok Koh PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF) 778528a9fbeSYongseok Koh }, 779528a9fbeSYongseok Koh { 780771fa900SAdrien Mazarguil .vendor_id = 0 781771fa900SAdrien Mazarguil } 782771fa900SAdrien Mazarguil }; 783771fa900SAdrien Mazarguil 784771fa900SAdrien Mazarguil static struct eth_driver mlx5_driver = { 785771fa900SAdrien Mazarguil .pci_drv = { 7862f3193cfSJan Viktorin .driver = { 7872f3193cfSJan Viktorin .name = MLX5_DRIVER_NAME 7882f3193cfSJan Viktorin }, 789771fa900SAdrien Mazarguil .id_table = mlx5_pci_id_map, 790af424af8SShreyansh Jain .probe = mlx5_pci_probe, 791198a3c33SNelio Laranjeiro .drv_flags = RTE_PCI_DRV_INTR_LSC, 792771fa900SAdrien Mazarguil }, 793771fa900SAdrien Mazarguil .dev_private_size = sizeof(struct priv) 794771fa900SAdrien Mazarguil }; 795771fa900SAdrien Mazarguil 796771fa900SAdrien Mazarguil /** 797771fa900SAdrien Mazarguil * Driver initialization routine. 798771fa900SAdrien Mazarguil */ 799c830cb29SDavid Marchand RTE_INIT(rte_mlx5_pmd_init); 800c830cb29SDavid Marchand static void 801c830cb29SDavid Marchand rte_mlx5_pmd_init(void) 802771fa900SAdrien Mazarguil { 803771fa900SAdrien Mazarguil /* 804771fa900SAdrien Mazarguil * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use 805771fa900SAdrien Mazarguil * huge pages. Calling ibv_fork_init() during init allows 806771fa900SAdrien Mazarguil * applications to use fork() safely for purposes other than 807771fa900SAdrien Mazarguil * using this PMD, which is not supported in forked processes. 808771fa900SAdrien Mazarguil */ 809771fa900SAdrien Mazarguil setenv("RDMAV_HUGEPAGES_SAFE", "1", 1); 810771fa900SAdrien Mazarguil ibv_fork_init(); 811771fa900SAdrien Mazarguil rte_eal_pci_register(&mlx5_driver.pci_drv); 812771fa900SAdrien Mazarguil } 813771fa900SAdrien Mazarguil 81401f19227SShreyansh Jain RTE_PMD_EXPORT_NAME(net_mlx5, __COUNTER__); 81501f19227SShreyansh Jain RTE_PMD_REGISTER_PCI_TABLE(net_mlx5, mlx5_pci_id_map); 8160880c401SOlivier Matz RTE_PMD_REGISTER_KMOD_DEP(net_mlx5, "* ib_uverbs & mlx5_core & mlx5_ib"); 817