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> 91256805dSOphir Munk #include <stdint.h> 10771fa900SAdrien Mazarguil #include <stdlib.h> 11771fa900SAdrien Mazarguil #include <errno.h> 12771fa900SAdrien Mazarguil 13ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 14c752998bSGaetan Rivet #include <rte_bus_pci.h> 15771fa900SAdrien Mazarguil #include <rte_mbuf.h> 16771fa900SAdrien Mazarguil #include <rte_common.h> 17198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 18a48deadaSOr Ami #include <rte_malloc.h> 19c022cb40SBruce Richardson #include <rte_string_fns.h> 20974f1e7eSYongseok Koh #include <rte_rwlock.h> 215897ac13SViacheslav Ovsiienko #include <rte_cycles.h> 22771fa900SAdrien Mazarguil 2383c2047cSSuanming Mou #include <mlx5_malloc.h> 2483c2047cSSuanming Mou 25e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 261256805dSOphir Munk #include "mlx5_autoconf.h" 272b730263SAdrien Mazarguil 282b730263SAdrien Mazarguil /** 29ccdcba53SNélio Laranjeiro * Get the interface index from device name. 30ccdcba53SNélio Laranjeiro * 31ccdcba53SNélio Laranjeiro * @param[in] dev 32ccdcba53SNélio Laranjeiro * Pointer to Ethernet device. 33ccdcba53SNélio Laranjeiro * 34ccdcba53SNélio Laranjeiro * @return 353f8cb05dSAdrien Mazarguil * Nonzero interface index on success, zero otherwise and rte_errno is set. 36ccdcba53SNélio Laranjeiro */ 373f8cb05dSAdrien Mazarguil unsigned int 38ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev) 39ccdcba53SNélio Laranjeiro { 40fa2e14d4SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 413f8cb05dSAdrien Mazarguil unsigned int ifindex; 42ccdcba53SNélio Laranjeiro 438e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv); 448e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv->if_index); 45c21e5facSXueming Li ifindex = priv->bond_ifindex > 0 ? priv->bond_ifindex : priv->if_index; 463f8cb05dSAdrien Mazarguil if (!ifindex) 47fa2e14d4SViacheslav Ovsiienko rte_errno = ENXIO; 483f8cb05dSAdrien Mazarguil return ifindex; 49ccdcba53SNélio Laranjeiro } 50ccdcba53SNélio Laranjeiro 51ccdcba53SNélio Laranjeiro /** 527b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 53e60fbd5bSAdrien Mazarguil * 54e60fbd5bSAdrien Mazarguil * @param dev 55e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 56e60fbd5bSAdrien Mazarguil * 57e60fbd5bSAdrien Mazarguil * @return 58a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 59e60fbd5bSAdrien Mazarguil */ 607b2423cdSNélio Laranjeiro int 617b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 62e60fbd5bSAdrien Mazarguil { 63dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 64e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 65e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 6629c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 6721e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 68a6d83b6aSNélio Laranjeiro int ret = 0; 69e60fbd5bSAdrien Mazarguil 7029c1d8bbSNélio Laranjeiro if (use_app_rss_key && 7129c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 72c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN)) { 73c388a2f6SNelio Laranjeiro DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long", 74c388a2f6SNelio Laranjeiro dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 75a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 76a6d83b6aSNélio Laranjeiro return -rte_errno; 7729c1d8bbSNélio Laranjeiro } 7829c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 7983c2047cSSuanming Mou mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE, 8083c2047cSSuanming Mou MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY); 8129c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 82a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)", 830f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 84a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 85a6d83b6aSNélio Laranjeiro return -rte_errno; 8629c1d8bbSNélio Laranjeiro } 878b945a7fSPavan Nikhilesh 88af270529SThomas Monjalon if ((dev->data->dev_conf.txmode.offloads & 89af270529SThomas Monjalon DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) && 90af270529SThomas Monjalon rte_mbuf_dyn_tx_timestamp_register(NULL, NULL) != 0) { 91af270529SThomas Monjalon DRV_LOG(ERR, "port %u cannot register Tx timestamp field/flag", 92af270529SThomas Monjalon dev->data->port_id); 93af270529SThomas Monjalon return -rte_errno; 94af270529SThomas Monjalon } 9529c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 9629c1d8bbSNélio Laranjeiro use_app_rss_key ? 9729c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 9829c1d8bbSNélio Laranjeiro rss_hash_default_key, 99c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN); 100c388a2f6SNelio Laranjeiro priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN; 10129c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 102e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 103e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 104e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 105a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u", 1060f99970bSNélio Laranjeiro dev->data->port_id, priv->txqs_n, txqs_n); 107e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 108e60fbd5bSAdrien Mazarguil } 1097fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 110a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 1110f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 112a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 113a6d83b6aSNélio Laranjeiro return -rte_errno; 114634efbc2SNelio Laranjeiro } 11509ba4c58SDekel Peled if (rxqs_n != priv->rxqs_n) { 116a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 1170f99970bSNélio Laranjeiro dev->data->port_id, priv->rxqs_n, rxqs_n); 118e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 11963bd1629SOri Kam } 12063bd1629SOri Kam priv->skip_default_rss_reta = 0; 12163bd1629SOri Kam ret = mlx5_proc_priv_init(dev); 12263bd1629SOri Kam if (ret) 12363bd1629SOri Kam return ret; 12463bd1629SOri Kam return 0; 12563bd1629SOri Kam } 12663bd1629SOri Kam 12763bd1629SOri Kam /** 12863bd1629SOri Kam * Configure default RSS reta. 12963bd1629SOri Kam * 13063bd1629SOri Kam * @param dev 13163bd1629SOri Kam * Pointer to Ethernet device structure. 13263bd1629SOri Kam * 13363bd1629SOri Kam * @return 13463bd1629SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 13563bd1629SOri Kam */ 13663bd1629SOri Kam int 13763bd1629SOri Kam mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev) 13863bd1629SOri Kam { 13963bd1629SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 14063bd1629SOri Kam unsigned int rxqs_n = dev->data->nb_rx_queues; 14163bd1629SOri Kam unsigned int i; 14263bd1629SOri Kam unsigned int j; 14363bd1629SOri Kam unsigned int reta_idx_n; 14463bd1629SOri Kam int ret = 0; 14563bd1629SOri Kam unsigned int *rss_queue_arr = NULL; 14663bd1629SOri Kam unsigned int rss_queue_n = 0; 14763bd1629SOri Kam 14863bd1629SOri Kam if (priv->skip_default_rss_reta) 14963bd1629SOri Kam return ret; 15083c2047cSSuanming Mou rss_queue_arr = mlx5_malloc(0, rxqs_n * sizeof(unsigned int), 0, 15183c2047cSSuanming Mou SOCKET_ID_ANY); 15263bd1629SOri Kam if (!rss_queue_arr) { 15363bd1629SOri Kam DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)", 15463bd1629SOri Kam dev->data->port_id, rxqs_n); 15563bd1629SOri Kam rte_errno = ENOMEM; 15663bd1629SOri Kam return -rte_errno; 15763bd1629SOri Kam } 15863bd1629SOri Kam for (i = 0, j = 0; i < rxqs_n; i++) { 15963bd1629SOri Kam struct mlx5_rxq_data *rxq_data; 16063bd1629SOri Kam struct mlx5_rxq_ctrl *rxq_ctrl; 16163bd1629SOri Kam 16263bd1629SOri Kam rxq_data = (*priv->rxqs)[i]; 16363bd1629SOri Kam rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); 164bf864e82STonghao Zhang if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) 16563bd1629SOri Kam rss_queue_arr[j++] = i; 16663bd1629SOri Kam } 16763bd1629SOri Kam rss_queue_n = j; 16863bd1629SOri Kam if (rss_queue_n > priv->config.ind_table_max_size) { 16963bd1629SOri Kam DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 17063bd1629SOri Kam dev->data->port_id, rss_queue_n); 17163bd1629SOri Kam rte_errno = EINVAL; 17283c2047cSSuanming Mou mlx5_free(rss_queue_arr); 17363bd1629SOri Kam return -rte_errno; 17463bd1629SOri Kam } 17563bd1629SOri Kam DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 17663bd1629SOri Kam dev->data->port_id, priv->rxqs_n, rxqs_n); 17763bd1629SOri Kam priv->rxqs_n = rxqs_n; 17809ba4c58SDekel Peled /* 17909ba4c58SDekel Peled * If the requested number of RX queues is not a power of two, 18009ba4c58SDekel Peled * use the maximum indirection table size for better balancing. 18109ba4c58SDekel Peled * The result is always rounded to the next power of two. 18209ba4c58SDekel Peled */ 18363bd1629SOri Kam reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ? 1847fe24446SShahaf Shuler priv->config.ind_table_max_size : 18563bd1629SOri Kam rss_queue_n)); 186a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 18763bd1629SOri Kam if (ret) { 18883c2047cSSuanming Mou mlx5_free(rss_queue_arr); 189a6d83b6aSNélio Laranjeiro return ret; 19063bd1629SOri Kam } 19109ba4c58SDekel Peled /* 19209ba4c58SDekel Peled * When the number of RX queues is not a power of two, 19309ba4c58SDekel Peled * the remaining table entries are padded with reused WQs 19409ba4c58SDekel Peled * and hashes are not spread uniformly. 19509ba4c58SDekel Peled */ 196634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 19763bd1629SOri Kam (*priv->reta_idx)[i] = rss_queue_arr[j]; 19863bd1629SOri Kam if (++j == rss_queue_n) 199634efbc2SNelio Laranjeiro j = 0; 200634efbc2SNelio Laranjeiro } 20183c2047cSSuanming Mou mlx5_free(rss_queue_arr); 202120dc4a7SYongseok Koh return ret; 203e60fbd5bSAdrien Mazarguil } 204e60fbd5bSAdrien Mazarguil 205e60fbd5bSAdrien Mazarguil /** 206d11d651fSShahaf Shuler * Sets default tuning parameters. 207d11d651fSShahaf Shuler * 208d11d651fSShahaf Shuler * @param dev 209d11d651fSShahaf Shuler * Pointer to Ethernet device. 210d11d651fSShahaf Shuler * @param[out] info 211d11d651fSShahaf Shuler * Info structure output buffer. 212d11d651fSShahaf Shuler */ 213d11d651fSShahaf Shuler static void 214d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 215d11d651fSShahaf Shuler { 216dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 217d11d651fSShahaf Shuler 218d11d651fSShahaf Shuler /* Minimum CPU utilization. */ 219d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 256; 220d11d651fSShahaf Shuler info->default_txportconf.ring_size = 256; 221f078ceb6SViacheslav Ovsiienko info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST; 222f078ceb6SViacheslav Ovsiienko info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST; 2236e3a4595SAsaf Penso if ((priv->link_speed_capa & ETH_LINK_SPEED_200G) | 2246e3a4595SAsaf Penso (priv->link_speed_capa & ETH_LINK_SPEED_100G)) { 225d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 16; 226d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 16; 227d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 228d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 229d11d651fSShahaf Shuler /* Max Throughput. */ 230d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 2048; 231d11d651fSShahaf Shuler info->default_txportconf.ring_size = 2048; 232d11d651fSShahaf Shuler } 233d11d651fSShahaf Shuler } else { 234d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 8; 235d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 8; 236d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 237d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 238d11d651fSShahaf Shuler /* Max Throughput. */ 239d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 4096; 240d11d651fSShahaf Shuler info->default_txportconf.ring_size = 4096; 241d11d651fSShahaf Shuler } 242d11d651fSShahaf Shuler } 243d11d651fSShahaf Shuler } 244d11d651fSShahaf Shuler 245d11d651fSShahaf Shuler /** 246cb9cb61eSViacheslav Ovsiienko * Sets tx mbuf limiting parameters. 247cb9cb61eSViacheslav Ovsiienko * 248cb9cb61eSViacheslav Ovsiienko * @param dev 249cb9cb61eSViacheslav Ovsiienko * Pointer to Ethernet device. 250cb9cb61eSViacheslav Ovsiienko * @param[out] info 251cb9cb61eSViacheslav Ovsiienko * Info structure output buffer. 252cb9cb61eSViacheslav Ovsiienko */ 253cb9cb61eSViacheslav Ovsiienko static void 254cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 255cb9cb61eSViacheslav Ovsiienko { 256cb9cb61eSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 257cb9cb61eSViacheslav Ovsiienko struct mlx5_dev_config *config = &priv->config; 258cb9cb61eSViacheslav Ovsiienko unsigned int inlen; 259cb9cb61eSViacheslav Ovsiienko uint16_t nb_max; 260cb9cb61eSViacheslav Ovsiienko 261cb9cb61eSViacheslav Ovsiienko inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ? 262cb9cb61eSViacheslav Ovsiienko MLX5_SEND_DEF_INLINE_LEN : 263cb9cb61eSViacheslav Ovsiienko (unsigned int)config->txq_inline_max; 2648e46d4e1SAlexander Kozyrev MLX5_ASSERT(config->txq_inline_min >= 0); 265cb9cb61eSViacheslav Ovsiienko inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min); 266cb9cb61eSViacheslav Ovsiienko inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX + 267cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 268cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 269cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 270cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE * 2); 271cb9cb61eSViacheslav Ovsiienko nb_max = (MLX5_WQE_SIZE_MAX + 272cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 273cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 274cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 275cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE - 276cb9cb61eSViacheslav Ovsiienko inlen) / MLX5_WSEG_SIZE; 277cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_seg_max = nb_max; 278cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_mtu_seg_max = nb_max; 279cb9cb61eSViacheslav Ovsiienko } 280cb9cb61eSViacheslav Ovsiienko 281cb9cb61eSViacheslav Ovsiienko /** 282e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 283e60fbd5bSAdrien Mazarguil * 284e60fbd5bSAdrien Mazarguil * @param dev 285e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 286e60fbd5bSAdrien Mazarguil * @param[out] info 287e60fbd5bSAdrien Mazarguil * Info structure output buffer. 288e60fbd5bSAdrien Mazarguil */ 289bdad90d1SIvan Ilchenko int 290e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 291e60fbd5bSAdrien Mazarguil { 292dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 2937fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 294e60fbd5bSAdrien Mazarguil unsigned int max; 295e60fbd5bSAdrien Mazarguil 296e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 297e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 298e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 2991c7e57f9SDekel Peled info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE; 300e60fbd5bSAdrien Mazarguil /* 301e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 302e60fbd5bSAdrien Mazarguil * between the two values. 303e60fbd5bSAdrien Mazarguil */ 304e85f623eSOphir Munk max = RTE_MIN(priv->sh->device_attr.max_cq, 305e85f623eSOphir Munk priv->sh->device_attr.max_qp); 306b689a781SThomas Monjalon /* max_rx_queues is uint16_t. */ 307b689a781SThomas Monjalon max = RTE_MIN(max, (unsigned int)UINT16_MAX); 308e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 309e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 31018c01b98SNélio Laranjeiro info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; 311af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 3126c8f7f1cSViacheslav Ovsiienko info->rx_seg_capa.max_nseg = MLX5_MAX_RXQ_NSEG; 313*ddb03843SViacheslav Ovsiienko info->rx_seg_capa.multi_pools = !config->mprq.enabled; 314*ddb03843SViacheslav Ovsiienko info->rx_seg_capa.offset_allowed = !config->mprq.enabled; 3156c8f7f1cSViacheslav Ovsiienko info->rx_seg_capa.offset_align_log2 = 0; 31617ed314cSMatan Azrad info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 31717b843ebSShahaf Shuler info->rx_queue_offload_capa); 318af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 319fa2e14d4SViacheslav Ovsiienko info->if_index = mlx5_ifindex(dev); 320d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 3217fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 322c388a2f6SNelio Laranjeiro info->hash_key_size = MLX5_RSS_HASH_KEY_LEN; 32375ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 324b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 325d11d651fSShahaf Shuler mlx5_set_default_params(dev, info); 326cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(dev, info); 3272b730263SAdrien Mazarguil info->switch_info.name = dev->data->name; 3282b730263SAdrien Mazarguil info->switch_info.domain_id = priv->domain_id; 3292b730263SAdrien Mazarguil info->switch_info.port_id = priv->representor_id; 3302b730263SAdrien Mazarguil if (priv->representor) { 331f7e95215SViacheslav Ovsiienko uint16_t port_id; 3322b730263SAdrien Mazarguil 333bee57a0aSViacheslav Ovsiienko if (priv->pf_bond >= 0) { 334bee57a0aSViacheslav Ovsiienko /* 335bee57a0aSViacheslav Ovsiienko * Switch port ID is opaque value with driver defined 336bee57a0aSViacheslav Ovsiienko * format. Push the PF index in bonding configurations 337bee57a0aSViacheslav Ovsiienko * in upper four bits of port ID. If we get too many 338bee57a0aSViacheslav Ovsiienko * representors (more than 4K) or PFs (more than 15) 339bee57a0aSViacheslav Ovsiienko * this approach must be reconsidered. 340bee57a0aSViacheslav Ovsiienko */ 341cdbdcd46SDong Zhou /* Switch port ID for VF representors: 0 - 0xFFE */ 342cdbdcd46SDong Zhou if ((info->switch_info.port_id != 0xffff && 343cdbdcd46SDong Zhou info->switch_info.port_id >= 344cdbdcd46SDong Zhou ((1 << MLX5_PORT_ID_BONDING_PF_SHIFT) - 1)) || 345bee57a0aSViacheslav Ovsiienko priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) { 346bee57a0aSViacheslav Ovsiienko DRV_LOG(ERR, "can't update switch port ID" 347bee57a0aSViacheslav Ovsiienko " for bonding device"); 3488e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 349bee57a0aSViacheslav Ovsiienko return -ENODEV; 350bee57a0aSViacheslav Ovsiienko } 351cdbdcd46SDong Zhou /* 352cdbdcd46SDong Zhou * Switch port ID for Host PF representor 353cdbdcd46SDong Zhou * (representor_id is -1) , set to 0xFFF 354cdbdcd46SDong Zhou */ 355cdbdcd46SDong Zhou if (info->switch_info.port_id == 0xffff) 356cdbdcd46SDong Zhou info->switch_info.port_id = 0xfff; 357bee57a0aSViacheslav Ovsiienko info->switch_info.port_id |= 358bee57a0aSViacheslav Ovsiienko priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT; 359bee57a0aSViacheslav Ovsiienko } 360fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 361dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 362f7e95215SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 3632b730263SAdrien Mazarguil 3642b730263SAdrien Mazarguil if (!opriv || 3652b730263SAdrien Mazarguil opriv->representor || 366f7e95215SViacheslav Ovsiienko opriv->sh != priv->sh || 3672b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id) 3682b730263SAdrien Mazarguil continue; 3692b730263SAdrien Mazarguil /* 3702b730263SAdrien Mazarguil * Override switch name with that of the master 3712b730263SAdrien Mazarguil * device. 3722b730263SAdrien Mazarguil */ 3732b730263SAdrien Mazarguil info->switch_info.name = opriv->dev_data->name; 3742b730263SAdrien Mazarguil break; 3752b730263SAdrien Mazarguil } 3762b730263SAdrien Mazarguil } 377bdad90d1SIvan Ilchenko return 0; 378e60fbd5bSAdrien Mazarguil } 379e60fbd5bSAdrien Mazarguil 380fb732b0aSNélio Laranjeiro /** 381714bf46eSThomas Monjalon * Get firmware version of a device. 382714bf46eSThomas Monjalon * 383714bf46eSThomas Monjalon * @param dev 384714bf46eSThomas Monjalon * Ethernet device port. 385714bf46eSThomas Monjalon * @param fw_ver 386714bf46eSThomas Monjalon * String output allocated by caller. 387714bf46eSThomas Monjalon * @param fw_size 388714bf46eSThomas Monjalon * Size of the output string, including terminating null byte. 389714bf46eSThomas Monjalon * 390714bf46eSThomas Monjalon * @return 391714bf46eSThomas Monjalon * 0 on success, or the size of the non truncated string if too big. 392714bf46eSThomas Monjalon */ 3931256805dSOphir Munk int 3941256805dSOphir Munk mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 395714bf46eSThomas Monjalon { 396dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 397e85f623eSOphir Munk struct mlx5_dev_attr *attr = &priv->sh->device_attr; 398714bf46eSThomas Monjalon size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 399714bf46eSThomas Monjalon 400714bf46eSThomas Monjalon if (fw_size < size) 401714bf46eSThomas Monjalon return size; 402714bf46eSThomas Monjalon if (fw_ver != NULL) 403714bf46eSThomas Monjalon strlcpy(fw_ver, attr->fw_ver, fw_size); 404714bf46eSThomas Monjalon return 0; 405714bf46eSThomas Monjalon } 406714bf46eSThomas Monjalon 407714bf46eSThomas Monjalon /** 408fb732b0aSNélio Laranjeiro * Get supported packet types. 409fb732b0aSNélio Laranjeiro * 410fb732b0aSNélio Laranjeiro * @param dev 411fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 412fb732b0aSNélio Laranjeiro * 413fb732b0aSNélio Laranjeiro * @return 414fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 415fb732b0aSNélio Laranjeiro */ 41678a38edfSJianfeng Tan const uint32_t * 41778a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 41878a38edfSJianfeng Tan { 41978a38edfSJianfeng Tan static const uint32_t ptypes[] = { 42078a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 421ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 422c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 423c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 424ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 425ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 426ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 427ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 428c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 429c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 430ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 431ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 432ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 433ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 43478a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 43578a38edfSJianfeng Tan }; 43678a38edfSJianfeng Tan 4376cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 4387d6bf6b8SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_mprq || 4390f20acbfSAlexander Kozyrev dev->rx_pkt_burst == mlx5_rx_burst_vec || 4400f20acbfSAlexander Kozyrev dev->rx_pkt_burst == mlx5_rx_burst_mprq_vec) 44178a38edfSJianfeng Tan return ptypes; 44278a38edfSJianfeng Tan return NULL; 44378a38edfSJianfeng Tan } 44478a38edfSJianfeng Tan 445e60fbd5bSAdrien Mazarguil /** 446cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 447cf37ca95SAdrien Mazarguil * 448cf37ca95SAdrien Mazarguil * @param dev 449cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 450cf37ca95SAdrien Mazarguil * @param in_mtu 451cf37ca95SAdrien Mazarguil * New MTU. 452cf37ca95SAdrien Mazarguil * 453cf37ca95SAdrien Mazarguil * @return 454a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 455cf37ca95SAdrien Mazarguil */ 456cf37ca95SAdrien Mazarguil int 457cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 458cf37ca95SAdrien Mazarguil { 459dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 460a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 461a6d83b6aSNélio Laranjeiro int ret; 462cf37ca95SAdrien Mazarguil 463af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 464a0edafe4SNelio Laranjeiro if (ret) 465a6d83b6aSNélio Laranjeiro return ret; 466cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 467af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 468a0edafe4SNelio Laranjeiro if (ret) 469a6d83b6aSNélio Laranjeiro return ret; 470af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 471a0edafe4SNelio Laranjeiro if (ret) 472a6d83b6aSNélio Laranjeiro return ret; 473a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 474a0edafe4SNelio Laranjeiro priv->mtu = mtu; 475a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u adapter MTU set to %u", 476a170a30dSNélio Laranjeiro dev->data->port_id, mtu); 477a0edafe4SNelio Laranjeiro return 0; 478a6d83b6aSNélio Laranjeiro } 479a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 480a6d83b6aSNélio Laranjeiro return -rte_errno; 481cf37ca95SAdrien Mazarguil } 482cf37ca95SAdrien Mazarguil 483cf37ca95SAdrien Mazarguil /** 484cdab90cbSNélio Laranjeiro * Configure the RX function to use. 485cdab90cbSNélio Laranjeiro * 486aee1b165SXueming Li * @param dev 487af4f09f2SNélio Laranjeiro * Pointer to private data structure. 4881cfa649bSShahaf Shuler * 4891cfa649bSShahaf Shuler * @return 4901cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 491cdab90cbSNélio Laranjeiro */ 4921cfa649bSShahaf Shuler eth_rx_burst_t 493af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 494cdab90cbSNélio Laranjeiro { 4951cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 4961cfa649bSShahaf Shuler 4978e46d4e1SAlexander Kozyrev MLX5_ASSERT(dev != NULL); 498af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 4990f20acbfSAlexander Kozyrev if (mlx5_mprq_enabled(dev)) { 5000f20acbfSAlexander Kozyrev rx_pkt_burst = mlx5_rx_burst_mprq_vec; 5010f20acbfSAlexander Kozyrev DRV_LOG(DEBUG, "port %u selected vectorized" 5020f20acbfSAlexander Kozyrev " MPRQ Rx function", dev->data->port_id); 5030f20acbfSAlexander Kozyrev } else { 5041cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 5050f20acbfSAlexander Kozyrev DRV_LOG(DEBUG, "port %u selected vectorized" 5060f20acbfSAlexander Kozyrev " SPRQ Rx function", dev->data->port_id); 5070f20acbfSAlexander Kozyrev } 5087d6bf6b8SYongseok Koh } else if (mlx5_mprq_enabled(dev)) { 5097d6bf6b8SYongseok Koh rx_pkt_burst = mlx5_rx_burst_mprq; 5100f20acbfSAlexander Kozyrev DRV_LOG(DEBUG, "port %u selected MPRQ Rx function", 5110f20acbfSAlexander Kozyrev dev->data->port_id); 5120f20acbfSAlexander Kozyrev } else { 5130f20acbfSAlexander Kozyrev DRV_LOG(DEBUG, "port %u selected SPRQ Rx function", 5140f20acbfSAlexander Kozyrev dev->data->port_id); 515cdab90cbSNélio Laranjeiro } 5161cfa649bSShahaf Shuler return rx_pkt_burst; 5176cb559d6SYongseok Koh } 518d3e0f392SMatan Azrad 519d3e0f392SMatan Azrad /** 52009a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by port id. 5212e4c987aSOri Kam * 5222e4c987aSOri Kam * @param[in] port 5232e4c987aSOri Kam * Device port id. 5245e61bcddSViacheslav Ovsiienko * @param[in] valid 5255e61bcddSViacheslav Ovsiienko * Device port id is valid, skip check. This flag is useful 5265e61bcddSViacheslav Ovsiienko * when trials are performed from probing and device is not 5275e61bcddSViacheslav Ovsiienko * flagged as valid yet (in attaching process). 5282e4c987aSOri Kam * @param[out] es_domain_id 5292e4c987aSOri Kam * E-Switch domain id. 5302e4c987aSOri Kam * @param[out] es_port_id 5312e4c987aSOri Kam * The port id of the port in the E-Switch. 5322e4c987aSOri Kam * 5332e4c987aSOri Kam * @return 53409a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 53509a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 5362e4c987aSOri Kam */ 53709a16bcaSViacheslav Ovsiienko struct mlx5_priv * 5385e61bcddSViacheslav Ovsiienko mlx5_port_to_eswitch_info(uint16_t port, bool valid) 5392e4c987aSOri Kam { 5402e4c987aSOri Kam struct rte_eth_dev *dev; 5412e4c987aSOri Kam struct mlx5_priv *priv; 5422e4c987aSOri Kam 5432e4c987aSOri Kam if (port >= RTE_MAX_ETHPORTS) { 5442e4c987aSOri Kam rte_errno = EINVAL; 54509a16bcaSViacheslav Ovsiienko return NULL; 5462e4c987aSOri Kam } 5475e61bcddSViacheslav Ovsiienko if (!valid && !rte_eth_dev_is_valid_port(port)) { 5482e4c987aSOri Kam rte_errno = ENODEV; 54909a16bcaSViacheslav Ovsiienko return NULL; 5502e4c987aSOri Kam } 5512e4c987aSOri Kam dev = &rte_eth_devices[port]; 5522e4c987aSOri Kam priv = dev->data->dev_private; 5532e4c987aSOri Kam if (!(priv->representor || priv->master)) { 5542e4c987aSOri Kam rte_errno = EINVAL; 55509a16bcaSViacheslav Ovsiienko return NULL; 5562e4c987aSOri Kam } 55709a16bcaSViacheslav Ovsiienko return priv; 55809a16bcaSViacheslav Ovsiienko } 55909a16bcaSViacheslav Ovsiienko 56009a16bcaSViacheslav Ovsiienko /** 56109a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by device instance. 56209a16bcaSViacheslav Ovsiienko * 56309a16bcaSViacheslav Ovsiienko * @param[in] port 56409a16bcaSViacheslav Ovsiienko * Device port id. 56509a16bcaSViacheslav Ovsiienko * @param[out] es_domain_id 56609a16bcaSViacheslav Ovsiienko * E-Switch domain id. 56709a16bcaSViacheslav Ovsiienko * @param[out] es_port_id 56809a16bcaSViacheslav Ovsiienko * The port id of the port in the E-Switch. 56909a16bcaSViacheslav Ovsiienko * 57009a16bcaSViacheslav Ovsiienko * @return 57109a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 57209a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 57309a16bcaSViacheslav Ovsiienko */ 57409a16bcaSViacheslav Ovsiienko struct mlx5_priv * 57509a16bcaSViacheslav Ovsiienko mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev) 57609a16bcaSViacheslav Ovsiienko { 57709a16bcaSViacheslav Ovsiienko struct mlx5_priv *priv; 57809a16bcaSViacheslav Ovsiienko 57909a16bcaSViacheslav Ovsiienko priv = dev->data->dev_private; 58009a16bcaSViacheslav Ovsiienko if (!(priv->representor || priv->master)) { 58109a16bcaSViacheslav Ovsiienko rte_errno = EINVAL; 58209a16bcaSViacheslav Ovsiienko return NULL; 58309a16bcaSViacheslav Ovsiienko } 58409a16bcaSViacheslav Ovsiienko return priv; 5852e4c987aSOri Kam } 5862e4c987aSOri Kam 5872e4c987aSOri Kam /** 588b6b3bf86SOri Kam * DPDK callback to retrieve hairpin capabilities. 589b6b3bf86SOri Kam * 590b6b3bf86SOri Kam * @param dev 591b6b3bf86SOri Kam * Pointer to Ethernet device structure. 592b6b3bf86SOri Kam * @param[out] cap 593b6b3bf86SOri Kam * Storage for hairpin capability data. 594b6b3bf86SOri Kam * 595b6b3bf86SOri Kam * @return 596b6b3bf86SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 597b6b3bf86SOri Kam */ 5981256805dSOphir Munk int 599b00f7603SMichael Baum mlx5_hairpin_cap_get(struct rte_eth_dev *dev, struct rte_eth_hairpin_cap *cap) 600b6b3bf86SOri Kam { 601b6b3bf86SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 602b00f7603SMichael Baum struct mlx5_dev_config *config = &priv->config; 603b6b3bf86SOri Kam 604b00f7603SMichael Baum if (!priv->sh->devx || !config->dest_tir || !config->dv_flow_en) { 605b6b3bf86SOri Kam rte_errno = ENOTSUP; 606b6b3bf86SOri Kam return -rte_errno; 607b6b3bf86SOri Kam } 608b6b3bf86SOri Kam cap->max_nb_queues = UINT16_MAX; 609b6b3bf86SOri Kam cap->max_rx_2_tx = 1; 610b6b3bf86SOri Kam cap->max_tx_2_rx = 1; 611b6b3bf86SOri Kam cap->max_nb_desc = 8192; 612b6b3bf86SOri Kam return 0; 613b6b3bf86SOri Kam } 614