18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6771fa900SAdrien Mazarguil #include <stddef.h> 7771fa900SAdrien Mazarguil #include <unistd.h> 8771fa900SAdrien Mazarguil #include <string.h> 9*1256805dSOphir Munk #include <stdint.h> 10771fa900SAdrien Mazarguil #include <stdlib.h> 11771fa900SAdrien Mazarguil #include <errno.h> 12771fa900SAdrien Mazarguil 13771fa900SAdrien Mazarguil #include <rte_atomic.h> 14ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 15c752998bSGaetan Rivet #include <rte_bus_pci.h> 16771fa900SAdrien Mazarguil #include <rte_mbuf.h> 17771fa900SAdrien Mazarguil #include <rte_common.h> 18198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 19a48deadaSOr Ami #include <rte_malloc.h> 20c022cb40SBruce Richardson #include <rte_string_fns.h> 21974f1e7eSYongseok Koh #include <rte_rwlock.h> 225897ac13SViacheslav Ovsiienko #include <rte_cycles.h> 23771fa900SAdrien Mazarguil 24e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 25*1256805dSOphir Munk #include "mlx5_autoconf.h" 262b730263SAdrien Mazarguil 272b730263SAdrien Mazarguil /** 28ccdcba53SNélio Laranjeiro * Get the interface index from device name. 29ccdcba53SNélio Laranjeiro * 30ccdcba53SNélio Laranjeiro * @param[in] dev 31ccdcba53SNélio Laranjeiro * Pointer to Ethernet device. 32ccdcba53SNélio Laranjeiro * 33ccdcba53SNélio Laranjeiro * @return 343f8cb05dSAdrien Mazarguil * Nonzero interface index on success, zero otherwise and rte_errno is set. 35ccdcba53SNélio Laranjeiro */ 363f8cb05dSAdrien Mazarguil unsigned int 37ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev) 38ccdcba53SNélio Laranjeiro { 39fa2e14d4SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 403f8cb05dSAdrien Mazarguil unsigned int ifindex; 41ccdcba53SNélio Laranjeiro 428e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv); 438e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv->if_index); 44fa2e14d4SViacheslav Ovsiienko ifindex = priv->if_index; 453f8cb05dSAdrien Mazarguil if (!ifindex) 46fa2e14d4SViacheslav Ovsiienko rte_errno = ENXIO; 473f8cb05dSAdrien Mazarguil return ifindex; 48ccdcba53SNélio Laranjeiro } 49ccdcba53SNélio Laranjeiro 50ccdcba53SNélio Laranjeiro /** 517b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 52e60fbd5bSAdrien Mazarguil * 53e60fbd5bSAdrien Mazarguil * @param dev 54e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 55e60fbd5bSAdrien Mazarguil * 56e60fbd5bSAdrien Mazarguil * @return 57a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 58e60fbd5bSAdrien Mazarguil */ 597b2423cdSNélio Laranjeiro int 607b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 61e60fbd5bSAdrien Mazarguil { 62dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 63e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 64e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 6529c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 6621e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 67a6d83b6aSNélio Laranjeiro int ret = 0; 68e60fbd5bSAdrien Mazarguil 6929c1d8bbSNélio Laranjeiro if (use_app_rss_key && 7029c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 71c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN)) { 72c388a2f6SNelio Laranjeiro DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long", 73c388a2f6SNelio Laranjeiro dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 74a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 75a6d83b6aSNélio Laranjeiro return -rte_errno; 7629c1d8bbSNélio Laranjeiro } 7729c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 7829c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 79c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN, 0); 8029c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 81a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)", 820f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 83a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 84a6d83b6aSNélio Laranjeiro return -rte_errno; 8529c1d8bbSNélio Laranjeiro } 868b945a7fSPavan Nikhilesh 8773fb89ddSAndrew Rybchenko if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) 888b945a7fSPavan Nikhilesh dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH; 898b945a7fSPavan Nikhilesh 9029c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 9129c1d8bbSNélio Laranjeiro use_app_rss_key ? 9229c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 9329c1d8bbSNélio Laranjeiro rss_hash_default_key, 94c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN); 95c388a2f6SNelio Laranjeiro priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN; 9629c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 97e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 98e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 99e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 100a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u", 1010f99970bSNélio Laranjeiro dev->data->port_id, priv->txqs_n, txqs_n); 102e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 103e60fbd5bSAdrien Mazarguil } 1047fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 105a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 1060f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 107a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 108a6d83b6aSNélio Laranjeiro return -rte_errno; 109634efbc2SNelio Laranjeiro } 11009ba4c58SDekel Peled if (rxqs_n != priv->rxqs_n) { 111a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 1120f99970bSNélio Laranjeiro dev->data->port_id, priv->rxqs_n, rxqs_n); 113e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 11463bd1629SOri Kam } 11563bd1629SOri Kam priv->skip_default_rss_reta = 0; 11663bd1629SOri Kam ret = mlx5_proc_priv_init(dev); 11763bd1629SOri Kam if (ret) 11863bd1629SOri Kam return ret; 11963bd1629SOri Kam return 0; 12063bd1629SOri Kam } 12163bd1629SOri Kam 12263bd1629SOri Kam /** 12363bd1629SOri Kam * Configure default RSS reta. 12463bd1629SOri Kam * 12563bd1629SOri Kam * @param dev 12663bd1629SOri Kam * Pointer to Ethernet device structure. 12763bd1629SOri Kam * 12863bd1629SOri Kam * @return 12963bd1629SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 13063bd1629SOri Kam */ 13163bd1629SOri Kam int 13263bd1629SOri Kam mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev) 13363bd1629SOri Kam { 13463bd1629SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 13563bd1629SOri Kam unsigned int rxqs_n = dev->data->nb_rx_queues; 13663bd1629SOri Kam unsigned int i; 13763bd1629SOri Kam unsigned int j; 13863bd1629SOri Kam unsigned int reta_idx_n; 13963bd1629SOri Kam int ret = 0; 14063bd1629SOri Kam unsigned int *rss_queue_arr = NULL; 14163bd1629SOri Kam unsigned int rss_queue_n = 0; 14263bd1629SOri Kam 14363bd1629SOri Kam if (priv->skip_default_rss_reta) 14463bd1629SOri Kam return ret; 14563bd1629SOri Kam rss_queue_arr = rte_malloc("", rxqs_n * sizeof(unsigned int), 0); 14663bd1629SOri Kam if (!rss_queue_arr) { 14763bd1629SOri Kam DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)", 14863bd1629SOri Kam dev->data->port_id, rxqs_n); 14963bd1629SOri Kam rte_errno = ENOMEM; 15063bd1629SOri Kam return -rte_errno; 15163bd1629SOri Kam } 15263bd1629SOri Kam for (i = 0, j = 0; i < rxqs_n; i++) { 15363bd1629SOri Kam struct mlx5_rxq_data *rxq_data; 15463bd1629SOri Kam struct mlx5_rxq_ctrl *rxq_ctrl; 15563bd1629SOri Kam 15663bd1629SOri Kam rxq_data = (*priv->rxqs)[i]; 15763bd1629SOri Kam rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); 158bf864e82STonghao Zhang if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) 15963bd1629SOri Kam rss_queue_arr[j++] = i; 16063bd1629SOri Kam } 16163bd1629SOri Kam rss_queue_n = j; 16263bd1629SOri Kam if (rss_queue_n > priv->config.ind_table_max_size) { 16363bd1629SOri Kam DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 16463bd1629SOri Kam dev->data->port_id, rss_queue_n); 16563bd1629SOri Kam rte_errno = EINVAL; 16663bd1629SOri Kam rte_free(rss_queue_arr); 16763bd1629SOri Kam return -rte_errno; 16863bd1629SOri Kam } 16963bd1629SOri Kam DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 17063bd1629SOri Kam dev->data->port_id, priv->rxqs_n, rxqs_n); 17163bd1629SOri Kam priv->rxqs_n = rxqs_n; 17209ba4c58SDekel Peled /* 17309ba4c58SDekel Peled * If the requested number of RX queues is not a power of two, 17409ba4c58SDekel Peled * use the maximum indirection table size for better balancing. 17509ba4c58SDekel Peled * The result is always rounded to the next power of two. 17609ba4c58SDekel Peled */ 17763bd1629SOri Kam reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ? 1787fe24446SShahaf Shuler priv->config.ind_table_max_size : 17963bd1629SOri Kam rss_queue_n)); 180a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 18163bd1629SOri Kam if (ret) { 18263bd1629SOri Kam rte_free(rss_queue_arr); 183a6d83b6aSNélio Laranjeiro return ret; 18463bd1629SOri Kam } 18509ba4c58SDekel Peled /* 18609ba4c58SDekel Peled * When the number of RX queues is not a power of two, 18709ba4c58SDekel Peled * the remaining table entries are padded with reused WQs 18809ba4c58SDekel Peled * and hashes are not spread uniformly. 18909ba4c58SDekel Peled */ 190634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 19163bd1629SOri Kam (*priv->reta_idx)[i] = rss_queue_arr[j]; 19263bd1629SOri Kam if (++j == rss_queue_n) 193634efbc2SNelio Laranjeiro j = 0; 194634efbc2SNelio Laranjeiro } 19563bd1629SOri Kam rte_free(rss_queue_arr); 196120dc4a7SYongseok Koh return ret; 197e60fbd5bSAdrien Mazarguil } 198e60fbd5bSAdrien Mazarguil 199e60fbd5bSAdrien Mazarguil /** 200d11d651fSShahaf Shuler * Sets default tuning parameters. 201d11d651fSShahaf Shuler * 202d11d651fSShahaf Shuler * @param dev 203d11d651fSShahaf Shuler * Pointer to Ethernet device. 204d11d651fSShahaf Shuler * @param[out] info 205d11d651fSShahaf Shuler * Info structure output buffer. 206d11d651fSShahaf Shuler */ 207d11d651fSShahaf Shuler static void 208d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 209d11d651fSShahaf Shuler { 210dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 211d11d651fSShahaf Shuler 212d11d651fSShahaf Shuler /* Minimum CPU utilization. */ 213d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 256; 214d11d651fSShahaf Shuler info->default_txportconf.ring_size = 256; 215f078ceb6SViacheslav Ovsiienko info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST; 216f078ceb6SViacheslav Ovsiienko info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST; 2176e3a4595SAsaf Penso if ((priv->link_speed_capa & ETH_LINK_SPEED_200G) | 2186e3a4595SAsaf Penso (priv->link_speed_capa & ETH_LINK_SPEED_100G)) { 219d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 16; 220d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 16; 221d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 222d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 223d11d651fSShahaf Shuler /* Max Throughput. */ 224d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 2048; 225d11d651fSShahaf Shuler info->default_txportconf.ring_size = 2048; 226d11d651fSShahaf Shuler } 227d11d651fSShahaf Shuler } else { 228d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 8; 229d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 8; 230d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 231d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 232d11d651fSShahaf Shuler /* Max Throughput. */ 233d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 4096; 234d11d651fSShahaf Shuler info->default_txportconf.ring_size = 4096; 235d11d651fSShahaf Shuler } 236d11d651fSShahaf Shuler } 237d11d651fSShahaf Shuler } 238d11d651fSShahaf Shuler 239d11d651fSShahaf Shuler /** 240cb9cb61eSViacheslav Ovsiienko * Sets tx mbuf limiting parameters. 241cb9cb61eSViacheslav Ovsiienko * 242cb9cb61eSViacheslav Ovsiienko * @param dev 243cb9cb61eSViacheslav Ovsiienko * Pointer to Ethernet device. 244cb9cb61eSViacheslav Ovsiienko * @param[out] info 245cb9cb61eSViacheslav Ovsiienko * Info structure output buffer. 246cb9cb61eSViacheslav Ovsiienko */ 247cb9cb61eSViacheslav Ovsiienko static void 248cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 249cb9cb61eSViacheslav Ovsiienko { 250cb9cb61eSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 251cb9cb61eSViacheslav Ovsiienko struct mlx5_dev_config *config = &priv->config; 252cb9cb61eSViacheslav Ovsiienko unsigned int inlen; 253cb9cb61eSViacheslav Ovsiienko uint16_t nb_max; 254cb9cb61eSViacheslav Ovsiienko 255cb9cb61eSViacheslav Ovsiienko inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ? 256cb9cb61eSViacheslav Ovsiienko MLX5_SEND_DEF_INLINE_LEN : 257cb9cb61eSViacheslav Ovsiienko (unsigned int)config->txq_inline_max; 2588e46d4e1SAlexander Kozyrev MLX5_ASSERT(config->txq_inline_min >= 0); 259cb9cb61eSViacheslav Ovsiienko inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min); 260cb9cb61eSViacheslav Ovsiienko inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX + 261cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 262cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 263cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 264cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE * 2); 265cb9cb61eSViacheslav Ovsiienko nb_max = (MLX5_WQE_SIZE_MAX + 266cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 267cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 268cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 269cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE - 270cb9cb61eSViacheslav Ovsiienko inlen) / MLX5_WSEG_SIZE; 271cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_seg_max = nb_max; 272cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_mtu_seg_max = nb_max; 273cb9cb61eSViacheslav Ovsiienko } 274cb9cb61eSViacheslav Ovsiienko 275cb9cb61eSViacheslav Ovsiienko /** 276e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 277e60fbd5bSAdrien Mazarguil * 278e60fbd5bSAdrien Mazarguil * @param dev 279e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 280e60fbd5bSAdrien Mazarguil * @param[out] info 281e60fbd5bSAdrien Mazarguil * Info structure output buffer. 282e60fbd5bSAdrien Mazarguil */ 283bdad90d1SIvan Ilchenko int 284e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 285e60fbd5bSAdrien Mazarguil { 286dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 2877fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 288e60fbd5bSAdrien Mazarguil unsigned int max; 289e60fbd5bSAdrien Mazarguil 290e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 291e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 292e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 2931c7e57f9SDekel Peled info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE; 294e60fbd5bSAdrien Mazarguil /* 295e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 296e60fbd5bSAdrien Mazarguil * between the two values. 297e60fbd5bSAdrien Mazarguil */ 298e85f623eSOphir Munk max = RTE_MIN(priv->sh->device_attr.max_cq, 299e85f623eSOphir Munk priv->sh->device_attr.max_qp); 300b689a781SThomas Monjalon /* max_rx_queues is uint16_t. */ 301b689a781SThomas Monjalon max = RTE_MIN(max, (unsigned int)UINT16_MAX); 302e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 303e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 30418c01b98SNélio Laranjeiro info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; 305af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 30617ed314cSMatan Azrad info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 30717b843ebSShahaf Shuler info->rx_queue_offload_capa); 308af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 309fa2e14d4SViacheslav Ovsiienko info->if_index = mlx5_ifindex(dev); 310d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 3117fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 312c388a2f6SNelio Laranjeiro info->hash_key_size = MLX5_RSS_HASH_KEY_LEN; 31375ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 314b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 315d11d651fSShahaf Shuler mlx5_set_default_params(dev, info); 316cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(dev, info); 3172b730263SAdrien Mazarguil info->switch_info.name = dev->data->name; 3182b730263SAdrien Mazarguil info->switch_info.domain_id = priv->domain_id; 3192b730263SAdrien Mazarguil info->switch_info.port_id = priv->representor_id; 3202b730263SAdrien Mazarguil if (priv->representor) { 321f7e95215SViacheslav Ovsiienko uint16_t port_id; 3222b730263SAdrien Mazarguil 323bee57a0aSViacheslav Ovsiienko if (priv->pf_bond >= 0) { 324bee57a0aSViacheslav Ovsiienko /* 325bee57a0aSViacheslav Ovsiienko * Switch port ID is opaque value with driver defined 326bee57a0aSViacheslav Ovsiienko * format. Push the PF index in bonding configurations 327bee57a0aSViacheslav Ovsiienko * in upper four bits of port ID. If we get too many 328bee57a0aSViacheslav Ovsiienko * representors (more than 4K) or PFs (more than 15) 329bee57a0aSViacheslav Ovsiienko * this approach must be reconsidered. 330bee57a0aSViacheslav Ovsiienko */ 331bee57a0aSViacheslav Ovsiienko if ((info->switch_info.port_id >> 332bee57a0aSViacheslav Ovsiienko MLX5_PORT_ID_BONDING_PF_SHIFT) || 333bee57a0aSViacheslav Ovsiienko priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) { 334bee57a0aSViacheslav Ovsiienko DRV_LOG(ERR, "can't update switch port ID" 335bee57a0aSViacheslav Ovsiienko " for bonding device"); 3368e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 337bee57a0aSViacheslav Ovsiienko return -ENODEV; 338bee57a0aSViacheslav Ovsiienko } 339bee57a0aSViacheslav Ovsiienko info->switch_info.port_id |= 340bee57a0aSViacheslav Ovsiienko priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT; 341bee57a0aSViacheslav Ovsiienko } 342fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 343dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 344f7e95215SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 3452b730263SAdrien Mazarguil 3462b730263SAdrien Mazarguil if (!opriv || 3472b730263SAdrien Mazarguil opriv->representor || 348f7e95215SViacheslav Ovsiienko opriv->sh != priv->sh || 3492b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id) 3502b730263SAdrien Mazarguil continue; 3512b730263SAdrien Mazarguil /* 3522b730263SAdrien Mazarguil * Override switch name with that of the master 3532b730263SAdrien Mazarguil * device. 3542b730263SAdrien Mazarguil */ 3552b730263SAdrien Mazarguil info->switch_info.name = opriv->dev_data->name; 3562b730263SAdrien Mazarguil break; 3572b730263SAdrien Mazarguil } 3582b730263SAdrien Mazarguil } 359bdad90d1SIvan Ilchenko return 0; 360e60fbd5bSAdrien Mazarguil } 361e60fbd5bSAdrien Mazarguil 362fb732b0aSNélio Laranjeiro /** 363714bf46eSThomas Monjalon * Get firmware version of a device. 364714bf46eSThomas Monjalon * 365714bf46eSThomas Monjalon * @param dev 366714bf46eSThomas Monjalon * Ethernet device port. 367714bf46eSThomas Monjalon * @param fw_ver 368714bf46eSThomas Monjalon * String output allocated by caller. 369714bf46eSThomas Monjalon * @param fw_size 370714bf46eSThomas Monjalon * Size of the output string, including terminating null byte. 371714bf46eSThomas Monjalon * 372714bf46eSThomas Monjalon * @return 373714bf46eSThomas Monjalon * 0 on success, or the size of the non truncated string if too big. 374714bf46eSThomas Monjalon */ 375*1256805dSOphir Munk int 376*1256805dSOphir Munk mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 377714bf46eSThomas Monjalon { 378dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 379e85f623eSOphir Munk struct mlx5_dev_attr *attr = &priv->sh->device_attr; 380714bf46eSThomas Monjalon size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 381714bf46eSThomas Monjalon 382714bf46eSThomas Monjalon if (fw_size < size) 383714bf46eSThomas Monjalon return size; 384714bf46eSThomas Monjalon if (fw_ver != NULL) 385714bf46eSThomas Monjalon strlcpy(fw_ver, attr->fw_ver, fw_size); 386714bf46eSThomas Monjalon return 0; 387714bf46eSThomas Monjalon } 388714bf46eSThomas Monjalon 389714bf46eSThomas Monjalon /** 390fb732b0aSNélio Laranjeiro * Get supported packet types. 391fb732b0aSNélio Laranjeiro * 392fb732b0aSNélio Laranjeiro * @param dev 393fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 394fb732b0aSNélio Laranjeiro * 395fb732b0aSNélio Laranjeiro * @return 396fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 397fb732b0aSNélio Laranjeiro */ 39878a38edfSJianfeng Tan const uint32_t * 39978a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 40078a38edfSJianfeng Tan { 40178a38edfSJianfeng Tan static const uint32_t ptypes[] = { 40278a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 403ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 404c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 405c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 406ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 407ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 408ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 409ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 410c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 411c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 412ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 413ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 414ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 415ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 41678a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 41778a38edfSJianfeng Tan }; 41878a38edfSJianfeng Tan 4196cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 4207d6bf6b8SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_mprq || 4216cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 42278a38edfSJianfeng Tan return ptypes; 42378a38edfSJianfeng Tan return NULL; 42478a38edfSJianfeng Tan } 42578a38edfSJianfeng Tan 426e60fbd5bSAdrien Mazarguil /** 427cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 428cf37ca95SAdrien Mazarguil * 429cf37ca95SAdrien Mazarguil * @param dev 430cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 431cf37ca95SAdrien Mazarguil * @param in_mtu 432cf37ca95SAdrien Mazarguil * New MTU. 433cf37ca95SAdrien Mazarguil * 434cf37ca95SAdrien Mazarguil * @return 435a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 436cf37ca95SAdrien Mazarguil */ 437cf37ca95SAdrien Mazarguil int 438cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 439cf37ca95SAdrien Mazarguil { 440dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 441a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 442a6d83b6aSNélio Laranjeiro int ret; 443cf37ca95SAdrien Mazarguil 444af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 445a0edafe4SNelio Laranjeiro if (ret) 446a6d83b6aSNélio Laranjeiro return ret; 447cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 448af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 449a0edafe4SNelio Laranjeiro if (ret) 450a6d83b6aSNélio Laranjeiro return ret; 451af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 452a0edafe4SNelio Laranjeiro if (ret) 453a6d83b6aSNélio Laranjeiro return ret; 454a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 455a0edafe4SNelio Laranjeiro priv->mtu = mtu; 456a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u adapter MTU set to %u", 457a170a30dSNélio Laranjeiro dev->data->port_id, mtu); 458a0edafe4SNelio Laranjeiro return 0; 459a6d83b6aSNélio Laranjeiro } 460a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 461a6d83b6aSNélio Laranjeiro return -rte_errno; 462cf37ca95SAdrien Mazarguil } 463cf37ca95SAdrien Mazarguil 464cf37ca95SAdrien Mazarguil /** 465cdab90cbSNélio Laranjeiro * Configure the RX function to use. 466cdab90cbSNélio Laranjeiro * 467aee1b165SXueming Li * @param dev 468af4f09f2SNélio Laranjeiro * Pointer to private data structure. 4691cfa649bSShahaf Shuler * 4701cfa649bSShahaf Shuler * @return 4711cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 472cdab90cbSNélio Laranjeiro */ 4731cfa649bSShahaf Shuler eth_rx_burst_t 474af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 475cdab90cbSNélio Laranjeiro { 4761cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 4771cfa649bSShahaf Shuler 4788e46d4e1SAlexander Kozyrev MLX5_ASSERT(dev != NULL); 479af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 4801cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 481a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected Rx vectorized function", 4820f99970bSNélio Laranjeiro dev->data->port_id); 4837d6bf6b8SYongseok Koh } else if (mlx5_mprq_enabled(dev)) { 4847d6bf6b8SYongseok Koh rx_pkt_burst = mlx5_rx_burst_mprq; 485cdab90cbSNélio Laranjeiro } 4861cfa649bSShahaf Shuler return rx_pkt_burst; 4876cb559d6SYongseok Koh } 488d3e0f392SMatan Azrad 489d3e0f392SMatan Azrad /** 49009a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by port id. 4912e4c987aSOri Kam * 4922e4c987aSOri Kam * @param[in] port 4932e4c987aSOri Kam * Device port id. 4945e61bcddSViacheslav Ovsiienko * @param[in] valid 4955e61bcddSViacheslav Ovsiienko * Device port id is valid, skip check. This flag is useful 4965e61bcddSViacheslav Ovsiienko * when trials are performed from probing and device is not 4975e61bcddSViacheslav Ovsiienko * flagged as valid yet (in attaching process). 4982e4c987aSOri Kam * @param[out] es_domain_id 4992e4c987aSOri Kam * E-Switch domain id. 5002e4c987aSOri Kam * @param[out] es_port_id 5012e4c987aSOri Kam * The port id of the port in the E-Switch. 5022e4c987aSOri Kam * 5032e4c987aSOri Kam * @return 50409a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 50509a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 5062e4c987aSOri Kam */ 50709a16bcaSViacheslav Ovsiienko struct mlx5_priv * 5085e61bcddSViacheslav Ovsiienko mlx5_port_to_eswitch_info(uint16_t port, bool valid) 5092e4c987aSOri Kam { 5102e4c987aSOri Kam struct rte_eth_dev *dev; 5112e4c987aSOri Kam struct mlx5_priv *priv; 5122e4c987aSOri Kam 5132e4c987aSOri Kam if (port >= RTE_MAX_ETHPORTS) { 5142e4c987aSOri Kam rte_errno = EINVAL; 51509a16bcaSViacheslav Ovsiienko return NULL; 5162e4c987aSOri Kam } 5175e61bcddSViacheslav Ovsiienko if (!valid && !rte_eth_dev_is_valid_port(port)) { 5182e4c987aSOri Kam rte_errno = ENODEV; 51909a16bcaSViacheslav Ovsiienko return NULL; 5202e4c987aSOri Kam } 5212e4c987aSOri Kam dev = &rte_eth_devices[port]; 5222e4c987aSOri Kam priv = dev->data->dev_private; 5232e4c987aSOri Kam if (!(priv->representor || priv->master)) { 5242e4c987aSOri Kam rte_errno = EINVAL; 52509a16bcaSViacheslav Ovsiienko return NULL; 5262e4c987aSOri Kam } 52709a16bcaSViacheslav Ovsiienko return priv; 52809a16bcaSViacheslav Ovsiienko } 52909a16bcaSViacheslav Ovsiienko 53009a16bcaSViacheslav Ovsiienko /** 53109a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by device instance. 53209a16bcaSViacheslav Ovsiienko * 53309a16bcaSViacheslav Ovsiienko * @param[in] port 53409a16bcaSViacheslav Ovsiienko * Device port id. 53509a16bcaSViacheslav Ovsiienko * @param[out] es_domain_id 53609a16bcaSViacheslav Ovsiienko * E-Switch domain id. 53709a16bcaSViacheslav Ovsiienko * @param[out] es_port_id 53809a16bcaSViacheslav Ovsiienko * The port id of the port in the E-Switch. 53909a16bcaSViacheslav Ovsiienko * 54009a16bcaSViacheslav Ovsiienko * @return 54109a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 54209a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 54309a16bcaSViacheslav Ovsiienko */ 54409a16bcaSViacheslav Ovsiienko struct mlx5_priv * 54509a16bcaSViacheslav Ovsiienko mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev) 54609a16bcaSViacheslav Ovsiienko { 54709a16bcaSViacheslav Ovsiienko struct mlx5_priv *priv; 54809a16bcaSViacheslav Ovsiienko 54909a16bcaSViacheslav Ovsiienko priv = dev->data->dev_private; 55009a16bcaSViacheslav Ovsiienko if (!(priv->representor || priv->master)) { 55109a16bcaSViacheslav Ovsiienko rte_errno = EINVAL; 55209a16bcaSViacheslav Ovsiienko return NULL; 55309a16bcaSViacheslav Ovsiienko } 55409a16bcaSViacheslav Ovsiienko return priv; 5552e4c987aSOri Kam } 5562e4c987aSOri Kam 5572e4c987aSOri Kam /** 558b6b3bf86SOri Kam * DPDK callback to retrieve hairpin capabilities. 559b6b3bf86SOri Kam * 560b6b3bf86SOri Kam * @param dev 561b6b3bf86SOri Kam * Pointer to Ethernet device structure. 562b6b3bf86SOri Kam * @param[out] cap 563b6b3bf86SOri Kam * Storage for hairpin capability data. 564b6b3bf86SOri Kam * 565b6b3bf86SOri Kam * @return 566b6b3bf86SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 567b6b3bf86SOri Kam */ 568*1256805dSOphir Munk int 569*1256805dSOphir Munk mlx5_hairpin_cap_get(struct rte_eth_dev *dev, 570b6b3bf86SOri Kam struct rte_eth_hairpin_cap *cap) 571b6b3bf86SOri Kam { 572b6b3bf86SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 573b6b3bf86SOri Kam 574b6b3bf86SOri Kam if (priv->sh->devx == 0) { 575b6b3bf86SOri Kam rte_errno = ENOTSUP; 576b6b3bf86SOri Kam return -rte_errno; 577b6b3bf86SOri Kam } 578b6b3bf86SOri Kam cap->max_nb_queues = UINT16_MAX; 579b6b3bf86SOri Kam cap->max_rx_2_tx = 1; 580b6b3bf86SOri Kam cap->max_tx_2_rx = 1; 581b6b3bf86SOri Kam cap->max_nb_desc = 8192; 582b6b3bf86SOri Kam return 0; 583b6b3bf86SOri Kam } 584