xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision 1944fbc3c2c8dd0cbaf04ad04cab39c0bb0cd7fc)
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 
13df96fd0dSBruce Richardson #include <ethdev_driver.h>
141f37cb2bSDavid Marchand #include <bus_pci_driver.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"
26151cbe3aSMichael Baum #include "mlx5_rx.h"
27377b69fbSMichael Baum #include "mlx5_tx.h"
281256805dSOphir Munk #include "mlx5_autoconf.h"
2909c25553SXueming Li #include "mlx5_devx.h"
3080f872eeSMichael Baum #include "rte_pmd_mlx5.h"
312b730263SAdrien Mazarguil 
322b730263SAdrien Mazarguil /**
33ccdcba53SNélio Laranjeiro  * Get the interface index from device name.
34ccdcba53SNélio Laranjeiro  *
35ccdcba53SNélio Laranjeiro  * @param[in] dev
36ccdcba53SNélio Laranjeiro  *   Pointer to Ethernet device.
37ccdcba53SNélio Laranjeiro  *
38ccdcba53SNélio Laranjeiro  * @return
393f8cb05dSAdrien Mazarguil  *   Nonzero interface index on success, zero otherwise and rte_errno is set.
40ccdcba53SNélio Laranjeiro  */
413f8cb05dSAdrien Mazarguil unsigned int
42ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev)
43ccdcba53SNélio Laranjeiro {
44fa2e14d4SViacheslav Ovsiienko 	struct mlx5_priv *priv = dev->data->dev_private;
453f8cb05dSAdrien Mazarguil 	unsigned int ifindex;
46ccdcba53SNélio Laranjeiro 
478e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(priv);
488e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(priv->if_index);
49f5f4c482SXueming Li 	if (priv->master && priv->sh->bond.ifindex > 0)
50f5f4c482SXueming Li 		ifindex = priv->sh->bond.ifindex;
51f5f4c482SXueming Li 	else
52f5f4c482SXueming Li 		ifindex = priv->if_index;
533f8cb05dSAdrien Mazarguil 	if (!ifindex)
54fa2e14d4SViacheslav Ovsiienko 		rte_errno = ENXIO;
553f8cb05dSAdrien Mazarguil 	return ifindex;
56ccdcba53SNélio Laranjeiro }
57ccdcba53SNélio Laranjeiro 
58ccdcba53SNélio Laranjeiro /**
597b2423cdSNélio Laranjeiro  * DPDK callback for Ethernet device configuration.
60e60fbd5bSAdrien Mazarguil  *
61e60fbd5bSAdrien Mazarguil  * @param dev
62e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
63e60fbd5bSAdrien Mazarguil  *
64e60fbd5bSAdrien Mazarguil  * @return
65a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
66e60fbd5bSAdrien Mazarguil  */
677b2423cdSNélio Laranjeiro int
687b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev)
69e60fbd5bSAdrien Mazarguil {
70dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
71e60fbd5bSAdrien Mazarguil 	unsigned int rxqs_n = dev->data->nb_rx_queues;
72e60fbd5bSAdrien Mazarguil 	unsigned int txqs_n = dev->data->nb_tx_queues;
7329c1d8bbSNélio Laranjeiro 	const uint8_t use_app_rss_key =
7421e3a974SShahaf Shuler 		!!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
75a6d83b6aSNélio Laranjeiro 	int ret = 0;
76e60fbd5bSAdrien Mazarguil 
7729c1d8bbSNélio Laranjeiro 	if (use_app_rss_key &&
7829c1d8bbSNélio Laranjeiro 	    (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
79c388a2f6SNelio Laranjeiro 	     MLX5_RSS_HASH_KEY_LEN)) {
80c388a2f6SNelio Laranjeiro 		DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long",
81c388a2f6SNelio Laranjeiro 			dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN));
82a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
83a6d83b6aSNélio Laranjeiro 		return -rte_errno;
8429c1d8bbSNélio Laranjeiro 	}
8580f872eeSMichael Baum 	priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
8680f872eeSMichael Baum 					      MLX5_MEM_RTE,
8780f872eeSMichael Baum 					      MLX5_RSS_HASH_KEY_LEN, 0,
8880f872eeSMichael Baum 					      SOCKET_ID_ANY);
8929c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
90a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
910f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
92a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
93a6d83b6aSNélio Laranjeiro 		return -rte_errno;
9429c1d8bbSNélio Laranjeiro 	}
958b945a7fSPavan Nikhilesh 
96af270529SThomas Monjalon 	if ((dev->data->dev_conf.txmode.offloads &
97295968d1SFerruh Yigit 			RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP) &&
98af270529SThomas Monjalon 			rte_mbuf_dyn_tx_timestamp_register(NULL, NULL) != 0) {
99af270529SThomas Monjalon 		DRV_LOG(ERR, "port %u cannot register Tx timestamp field/flag",
100af270529SThomas Monjalon 			dev->data->port_id);
101af270529SThomas Monjalon 		return -rte_errno;
102af270529SThomas Monjalon 	}
10329c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
10429c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
10529c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
10629c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
107c388a2f6SNelio Laranjeiro 	       MLX5_RSS_HASH_KEY_LEN);
108c388a2f6SNelio Laranjeiro 	priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN;
10929c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
1104cda06c3SXueming Li 	priv->rxq_privs = mlx5_realloc(priv->rxq_privs,
1114cda06c3SXueming Li 				       MLX5_MEM_RTE | MLX5_MEM_ZERO,
1124cda06c3SXueming Li 				       sizeof(void *) * rxqs_n, 0,
1134cda06c3SXueming Li 				       SOCKET_ID_ANY);
1143ef18940SBing Zhao 	if (rxqs_n && priv->rxq_privs == NULL) {
1154cda06c3SXueming Li 		DRV_LOG(ERR, "port %u cannot allocate rxq private data",
1164cda06c3SXueming Li 			dev->data->port_id);
1174cda06c3SXueming Li 		rte_errno = ENOMEM;
1184cda06c3SXueming Li 		return -rte_errno;
1194cda06c3SXueming Li 	}
120e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
121e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
122a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
1230f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
124e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
125e60fbd5bSAdrien Mazarguil 	}
126*1944fbc3SSuanming Mou 	if (priv->ext_txqs && txqs_n >= MLX5_EXTERNAL_TX_QUEUE_ID_MIN) {
127*1944fbc3SSuanming Mou 		DRV_LOG(ERR, "port %u cannot handle this many Tx queues (%u), "
128*1944fbc3SSuanming Mou 			"the maximal number of internal Tx queues is %u",
129*1944fbc3SSuanming Mou 			dev->data->port_id, txqs_n,
130*1944fbc3SSuanming Mou 			MLX5_EXTERNAL_TX_QUEUE_ID_MIN - 1);
131*1944fbc3SSuanming Mou 		rte_errno = EINVAL;
132*1944fbc3SSuanming Mou 		return -rte_errno;
133*1944fbc3SSuanming Mou 	}
13487af0d1eSMichael Baum 	if (rxqs_n > priv->sh->dev_cap.ind_table_max_size) {
135a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
1360f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
137a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
138a6d83b6aSNélio Laranjeiro 		return -rte_errno;
139634efbc2SNelio Laranjeiro 	}
14086647d46SThomas Monjalon 	if (priv->ext_rxqs && rxqs_n >= RTE_PMD_MLX5_EXTERNAL_RX_QUEUE_ID_MIN) {
14180f872eeSMichael Baum 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u), "
14280f872eeSMichael Baum 			"the maximal number of internal Rx queues is %u",
14380f872eeSMichael Baum 			dev->data->port_id, rxqs_n,
14486647d46SThomas Monjalon 			RTE_PMD_MLX5_EXTERNAL_RX_QUEUE_ID_MIN - 1);
14580f872eeSMichael Baum 		rte_errno = EINVAL;
14680f872eeSMichael Baum 		return -rte_errno;
14780f872eeSMichael Baum 	}
14809ba4c58SDekel Peled 	if (rxqs_n != priv->rxqs_n) {
149a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
1500f99970bSNélio Laranjeiro 			dev->data->port_id, priv->rxqs_n, rxqs_n);
151e60fbd5bSAdrien Mazarguil 		priv->rxqs_n = rxqs_n;
15263bd1629SOri Kam 	}
15363bd1629SOri Kam 	priv->skip_default_rss_reta = 0;
15463bd1629SOri Kam 	ret = mlx5_proc_priv_init(dev);
15563bd1629SOri Kam 	if (ret)
15663bd1629SOri Kam 		return ret;
15763bd1629SOri Kam 	return 0;
15863bd1629SOri Kam }
15963bd1629SOri Kam 
16063bd1629SOri Kam /**
16163bd1629SOri Kam  * Configure default RSS reta.
16263bd1629SOri Kam  *
16363bd1629SOri Kam  * @param dev
16463bd1629SOri Kam  *   Pointer to Ethernet device structure.
16563bd1629SOri Kam  *
16663bd1629SOri Kam  * @return
16763bd1629SOri Kam  *   0 on success, a negative errno value otherwise and rte_errno is set.
16863bd1629SOri Kam  */
16963bd1629SOri Kam int
17063bd1629SOri Kam mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
17163bd1629SOri Kam {
17263bd1629SOri Kam 	struct mlx5_priv *priv = dev->data->dev_private;
17363bd1629SOri Kam 	unsigned int rxqs_n = dev->data->nb_rx_queues;
17463bd1629SOri Kam 	unsigned int i;
17563bd1629SOri Kam 	unsigned int j;
17663bd1629SOri Kam 	unsigned int reta_idx_n;
17763bd1629SOri Kam 	int ret = 0;
17863bd1629SOri Kam 	unsigned int *rss_queue_arr = NULL;
17963bd1629SOri Kam 	unsigned int rss_queue_n = 0;
18063bd1629SOri Kam 
18163bd1629SOri Kam 	if (priv->skip_default_rss_reta)
18263bd1629SOri Kam 		return ret;
18383c2047cSSuanming Mou 	rss_queue_arr = mlx5_malloc(0, rxqs_n * sizeof(unsigned int), 0,
18483c2047cSSuanming Mou 				    SOCKET_ID_ANY);
18563bd1629SOri Kam 	if (!rss_queue_arr) {
18663bd1629SOri Kam 		DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)",
18763bd1629SOri Kam 			dev->data->port_id, rxqs_n);
18863bd1629SOri Kam 		rte_errno = ENOMEM;
18963bd1629SOri Kam 		return -rte_errno;
19063bd1629SOri Kam 	}
19163bd1629SOri Kam 	for (i = 0, j = 0; i < rxqs_n; i++) {
1925cf0707fSXueming Li 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
19363bd1629SOri Kam 
194c06f77aeSMichael Baum 		if (rxq_ctrl && !rxq_ctrl->is_hairpin)
19563bd1629SOri Kam 			rss_queue_arr[j++] = i;
19663bd1629SOri Kam 	}
19763bd1629SOri Kam 	rss_queue_n = j;
19887af0d1eSMichael Baum 	if (rss_queue_n > priv->sh->dev_cap.ind_table_max_size) {
19963bd1629SOri Kam 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
20063bd1629SOri Kam 			dev->data->port_id, rss_queue_n);
20163bd1629SOri Kam 		rte_errno = EINVAL;
20283c2047cSSuanming Mou 		mlx5_free(rss_queue_arr);
20363bd1629SOri Kam 		return -rte_errno;
20463bd1629SOri Kam 	}
20563bd1629SOri Kam 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
20663bd1629SOri Kam 		dev->data->port_id, priv->rxqs_n, rxqs_n);
20763bd1629SOri Kam 	priv->rxqs_n = rxqs_n;
20809ba4c58SDekel Peled 	/*
20909ba4c58SDekel Peled 	 * If the requested number of RX queues is not a power of two,
21009ba4c58SDekel Peled 	 * use the maximum indirection table size for better balancing.
21109ba4c58SDekel Peled 	 * The result is always rounded to the next power of two.
21209ba4c58SDekel Peled 	 */
21363bd1629SOri Kam 	reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ?
21487af0d1eSMichael Baum 				     priv->sh->dev_cap.ind_table_max_size :
21563bd1629SOri Kam 				     rss_queue_n));
216a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
21763bd1629SOri Kam 	if (ret) {
21883c2047cSSuanming Mou 		mlx5_free(rss_queue_arr);
219a6d83b6aSNélio Laranjeiro 		return ret;
22063bd1629SOri Kam 	}
22109ba4c58SDekel Peled 	/*
22209ba4c58SDekel Peled 	 * When the number of RX queues is not a power of two,
22309ba4c58SDekel Peled 	 * the remaining table entries are padded with reused WQs
22409ba4c58SDekel Peled 	 * and hashes are not spread uniformly.
22509ba4c58SDekel Peled 	 */
226634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
22763bd1629SOri Kam 		(*priv->reta_idx)[i] = rss_queue_arr[j];
22863bd1629SOri Kam 		if (++j == rss_queue_n)
229634efbc2SNelio Laranjeiro 			j = 0;
230634efbc2SNelio Laranjeiro 	}
23183c2047cSSuanming Mou 	mlx5_free(rss_queue_arr);
232120dc4a7SYongseok Koh 	return ret;
233e60fbd5bSAdrien Mazarguil }
234e60fbd5bSAdrien Mazarguil 
235e60fbd5bSAdrien Mazarguil /**
236d11d651fSShahaf Shuler  * Sets default tuning parameters.
237d11d651fSShahaf Shuler  *
238d11d651fSShahaf Shuler  * @param dev
239d11d651fSShahaf Shuler  *   Pointer to Ethernet device.
240d11d651fSShahaf Shuler  * @param[out] info
241d11d651fSShahaf Shuler  *   Info structure output buffer.
242d11d651fSShahaf Shuler  */
243d11d651fSShahaf Shuler static void
244d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
245d11d651fSShahaf Shuler {
246dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
247d11d651fSShahaf Shuler 
248d11d651fSShahaf Shuler 	/* Minimum CPU utilization. */
249d11d651fSShahaf Shuler 	info->default_rxportconf.ring_size = 256;
250d11d651fSShahaf Shuler 	info->default_txportconf.ring_size = 256;
251f078ceb6SViacheslav Ovsiienko 	info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST;
252f078ceb6SViacheslav Ovsiienko 	info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST;
2533d57ec9fSThomas Monjalon 	if (priv->link_speed_capa >> rte_bsf32(RTE_ETH_LINK_SPEED_100G)) {
2543d57ec9fSThomas Monjalon 		/* if supports at least 100G */
255d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 16;
256d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 16;
257d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
258d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
259d11d651fSShahaf Shuler 			/* Max Throughput. */
260d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 2048;
261d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 2048;
262d11d651fSShahaf Shuler 		}
263d11d651fSShahaf Shuler 	} else {
264d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 8;
265d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 8;
266d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
267d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
268d11d651fSShahaf Shuler 			/* Max Throughput. */
269d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 4096;
270d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 4096;
271d11d651fSShahaf Shuler 		}
272d11d651fSShahaf Shuler 	}
273d11d651fSShahaf Shuler }
274d11d651fSShahaf Shuler 
275d11d651fSShahaf Shuler /**
276cb9cb61eSViacheslav Ovsiienko  * Sets tx mbuf limiting parameters.
277cb9cb61eSViacheslav Ovsiienko  *
278cb9cb61eSViacheslav Ovsiienko  * @param dev
279cb9cb61eSViacheslav Ovsiienko  *   Pointer to Ethernet device.
280cb9cb61eSViacheslav Ovsiienko  * @param[out] info
281cb9cb61eSViacheslav Ovsiienko  *   Info structure output buffer.
282cb9cb61eSViacheslav Ovsiienko  */
283cb9cb61eSViacheslav Ovsiienko static void
284cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
285cb9cb61eSViacheslav Ovsiienko {
286cb9cb61eSViacheslav Ovsiienko 	struct mlx5_priv *priv = dev->data->dev_private;
28745a6df80SMichael Baum 	struct mlx5_port_config *config = &priv->config;
288cb9cb61eSViacheslav Ovsiienko 	unsigned int inlen;
289cb9cb61eSViacheslav Ovsiienko 	uint16_t nb_max;
290cb9cb61eSViacheslav Ovsiienko 
291cb9cb61eSViacheslav Ovsiienko 	inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ?
292cb9cb61eSViacheslav Ovsiienko 		MLX5_SEND_DEF_INLINE_LEN :
293cb9cb61eSViacheslav Ovsiienko 		(unsigned int)config->txq_inline_max;
2948e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(config->txq_inline_min >= 0);
295cb9cb61eSViacheslav Ovsiienko 	inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min);
296cb9cb61eSViacheslav Ovsiienko 	inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX +
297cb9cb61eSViacheslav Ovsiienko 			       MLX5_ESEG_MIN_INLINE_SIZE -
298cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_CSEG_SIZE -
299cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_ESEG_SIZE -
300cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_DSEG_SIZE * 2);
301cb9cb61eSViacheslav Ovsiienko 	nb_max = (MLX5_WQE_SIZE_MAX +
302cb9cb61eSViacheslav Ovsiienko 		  MLX5_ESEG_MIN_INLINE_SIZE -
303cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_CSEG_SIZE -
304cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_ESEG_SIZE -
305cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_DSEG_SIZE -
306cb9cb61eSViacheslav Ovsiienko 		  inlen) / MLX5_WSEG_SIZE;
307cb9cb61eSViacheslav Ovsiienko 	info->tx_desc_lim.nb_seg_max = nb_max;
308cb9cb61eSViacheslav Ovsiienko 	info->tx_desc_lim.nb_mtu_seg_max = nb_max;
309cb9cb61eSViacheslav Ovsiienko }
310cb9cb61eSViacheslav Ovsiienko 
311cb9cb61eSViacheslav Ovsiienko /**
312e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
313e60fbd5bSAdrien Mazarguil  *
314e60fbd5bSAdrien Mazarguil  * @param dev
315e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
316e60fbd5bSAdrien Mazarguil  * @param[out] info
317e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
318e60fbd5bSAdrien Mazarguil  */
319bdad90d1SIvan Ilchenko int
320e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
321e60fbd5bSAdrien Mazarguil {
322dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
323e60fbd5bSAdrien Mazarguil 	unsigned int max;
324e60fbd5bSAdrien Mazarguil 
325e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
326e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
327e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
3281c7e57f9SDekel Peled 	info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE;
329e60fbd5bSAdrien Mazarguil 	/*
330e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
331e60fbd5bSAdrien Mazarguil 	 * between the two values.
332e60fbd5bSAdrien Mazarguil 	 */
33391d1cfafSMichael Baum 	max = RTE_MIN(priv->sh->dev_cap.max_cq, priv->sh->dev_cap.max_qp);
334b689a781SThomas Monjalon 	/* max_rx_queues is uint16_t. */
335b689a781SThomas Monjalon 	max = RTE_MIN(max, (unsigned int)UINT16_MAX);
336e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
337e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
33818c01b98SNélio Laranjeiro 	info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES;
339af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
3406c8f7f1cSViacheslav Ovsiienko 	info->rx_seg_capa.max_nseg = MLX5_MAX_RXQ_NSEG;
34145a6df80SMichael Baum 	info->rx_seg_capa.multi_pools = !priv->config.mprq.enabled;
34245a6df80SMichael Baum 	info->rx_seg_capa.offset_allowed = !priv->config.mprq.enabled;
3436c8f7f1cSViacheslav Ovsiienko 	info->rx_seg_capa.offset_align_log2 = 0;
34417ed314cSMatan Azrad 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
34517b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
346af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
347ec4e11d4SDmitry Kozlyuk 	info->dev_capa = RTE_ETH_DEV_CAPA_FLOW_SHARED_OBJECT_KEEP;
348fa2e14d4SViacheslav Ovsiienko 	info->if_index = mlx5_ifindex(dev);
349d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
35087af0d1eSMichael Baum 		priv->reta_idx_n : priv->sh->dev_cap.ind_table_max_size;
351c388a2f6SNelio Laranjeiro 	info->hash_key_size = MLX5_RSS_HASH_KEY_LEN;
35275ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
353b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
354d11d651fSShahaf Shuler 	mlx5_set_default_params(dev, info);
355cb9cb61eSViacheslav Ovsiienko 	mlx5_set_txlimit_params(dev, info);
35653820561SMichael Baum 	if (priv->sh->cdev->config.hca_attr.mem_rq_rmp &&
35709c25553SXueming Li 	    priv->obj_ops.rxq_obj_new == devx_obj_ops.rxq_obj_new)
35809c25553SXueming Li 		info->dev_capa |= RTE_ETH_DEV_CAPA_RXQ_SHARE;
3592b730263SAdrien Mazarguil 	info->switch_info.name = dev->data->name;
3602b730263SAdrien Mazarguil 	info->switch_info.domain_id = priv->domain_id;
3612b730263SAdrien Mazarguil 	info->switch_info.port_id = priv->representor_id;
36209c25553SXueming Li 	info->switch_info.rx_domain = 0; /* No sub Rx domains. */
3632b730263SAdrien Mazarguil 	if (priv->representor) {
364f7e95215SViacheslav Ovsiienko 		uint16_t port_id;
3652b730263SAdrien Mazarguil 
36656bb3c84SXueming Li 		MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
367dbeba4cfSThomas Monjalon 			struct mlx5_priv *opriv =
368f7e95215SViacheslav Ovsiienko 				rte_eth_devices[port_id].data->dev_private;
3692b730263SAdrien Mazarguil 
3702b730263SAdrien Mazarguil 			if (!opriv ||
3712b730263SAdrien Mazarguil 			    opriv->representor ||
372f7e95215SViacheslav Ovsiienko 			    opriv->sh != priv->sh ||
3732b730263SAdrien Mazarguil 			    opriv->domain_id != priv->domain_id)
3742b730263SAdrien Mazarguil 				continue;
3752b730263SAdrien Mazarguil 			/*
3762b730263SAdrien Mazarguil 			 * Override switch name with that of the master
3772b730263SAdrien Mazarguil 			 * device.
3782b730263SAdrien Mazarguil 			 */
3792b730263SAdrien Mazarguil 			info->switch_info.name = opriv->dev_data->name;
3802b730263SAdrien Mazarguil 			break;
3812b730263SAdrien Mazarguil 		}
3822b730263SAdrien Mazarguil 	}
383bdad90d1SIvan Ilchenko 	return 0;
384e60fbd5bSAdrien Mazarguil }
385e60fbd5bSAdrien Mazarguil 
386fb732b0aSNélio Laranjeiro /**
387cb95feefSXueming Li  * Calculate representor ID from port switch info.
388cb95feefSXueming Li  *
389cb95feefSXueming Li  * Uint16 representor ID bits definition:
390cb95feefSXueming Li  *   pf: 2
391cb95feefSXueming Li  *   type: 2
392cb95feefSXueming Li  *   vf/sf: 12
393cb95feefSXueming Li  *
394cb95feefSXueming Li  * @param info
395cb95feefSXueming Li  *   Port switch info.
39691766faeSXueming Li  * @param hpf_type
39791766faeSXueming Li  *   Use this type if port is HPF.
398cb95feefSXueming Li  *
399cb95feefSXueming Li  * @return
400cb95feefSXueming Li  *   Encoded representor ID.
401cb95feefSXueming Li  */
402cb95feefSXueming Li uint16_t
40391766faeSXueming Li mlx5_representor_id_encode(const struct mlx5_switch_info *info,
40491766faeSXueming Li 			   enum rte_eth_representor_type hpf_type)
405cb95feefSXueming Li {
40611c73de9SDariusz Sosnowski 	enum rte_eth_representor_type type;
407cb95feefSXueming Li 	uint16_t repr = info->port_name;
40811c73de9SDariusz Sosnowski 	int32_t pf = info->pf_num;
409cb95feefSXueming Li 
41011c73de9SDariusz Sosnowski 	switch (info->name_type) {
41111c73de9SDariusz Sosnowski 	case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
41211c73de9SDariusz Sosnowski 		if (!info->representor)
413cb95feefSXueming Li 			return UINT16_MAX;
41411c73de9SDariusz Sosnowski 		type = RTE_ETH_REPRESENTOR_PF;
41511c73de9SDariusz Sosnowski 		pf = info->mpesw_owner;
41611c73de9SDariusz Sosnowski 		break;
41711c73de9SDariusz Sosnowski 	case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
418cb95feefSXueming Li 		type = RTE_ETH_REPRESENTOR_SF;
41911c73de9SDariusz Sosnowski 		break;
42011c73de9SDariusz Sosnowski 	case MLX5_PHYS_PORT_NAME_TYPE_PFHPF:
42191766faeSXueming Li 		type = hpf_type;
422cb95feefSXueming Li 		repr = UINT16_MAX;
42311c73de9SDariusz Sosnowski 		break;
42411c73de9SDariusz Sosnowski 	case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
42511c73de9SDariusz Sosnowski 	default:
42611c73de9SDariusz Sosnowski 		type = RTE_ETH_REPRESENTOR_VF;
42711c73de9SDariusz Sosnowski 		break;
42891766faeSXueming Li 	}
42911c73de9SDariusz Sosnowski 	return MLX5_REPRESENTOR_ID(pf, type, repr);
430cb95feefSXueming Li }
431cb95feefSXueming Li 
432cb95feefSXueming Li /**
433cb95feefSXueming Li  * DPDK callback to get information about representor.
434cb95feefSXueming Li  *
435cb95feefSXueming Li  * Representor ID bits definition:
436cb95feefSXueming Li  *   vf/sf: 12
437cb95feefSXueming Li  *   type: 2
438cb95feefSXueming Li  *   pf: 2
439cb95feefSXueming Li  *
440cb95feefSXueming Li  * @param dev
441cb95feefSXueming Li  *   Pointer to Ethernet device structure.
442cb95feefSXueming Li  * @param[out] info
443cb95feefSXueming Li  *   Nullable info structure output buffer.
444cb95feefSXueming Li  *
445cb95feefSXueming Li  * @return
446cb95feefSXueming Li  *   negative on error, or the number of representor ranges.
447cb95feefSXueming Li  */
448cb95feefSXueming Li int
449cb95feefSXueming Li mlx5_representor_info_get(struct rte_eth_dev *dev,
450cb95feefSXueming Li 			  struct rte_eth_representor_info *info)
451cb95feefSXueming Li {
452cb95feefSXueming Li 	struct mlx5_priv *priv = dev->data->dev_private;
45311c73de9SDariusz Sosnowski 	int n_type = 5; /* Representor types: PF, VF, HPF@VF, SF and HPF@SF. */
454cb95feefSXueming Li 	int n_pf = 2; /* Number of PFs. */
455cb95feefSXueming Li 	int i = 0, pf;
45610eaf41dSViacheslav Galaktionov 	int n_entries;
457cb95feefSXueming Li 
458cb95feefSXueming Li 	if (info == NULL)
459cb95feefSXueming Li 		goto out;
46010eaf41dSViacheslav Galaktionov 
46110eaf41dSViacheslav Galaktionov 	n_entries = n_type * n_pf;
46210eaf41dSViacheslav Galaktionov 	if ((uint32_t)n_entries > info->nb_ranges_alloc)
46310eaf41dSViacheslav Galaktionov 		n_entries = info->nb_ranges_alloc;
46410eaf41dSViacheslav Galaktionov 
465cb95feefSXueming Li 	info->controller = 0;
46611c73de9SDariusz Sosnowski 	info->pf = 0;
46711c73de9SDariusz Sosnowski 	if (mlx5_is_port_on_mpesw_device(priv)) {
46811c73de9SDariusz Sosnowski 		info->pf = priv->mpesw_port;
46911c73de9SDariusz Sosnowski 		/* PF range, both ports will show the same information. */
47011c73de9SDariusz Sosnowski 		info->ranges[i].type = RTE_ETH_REPRESENTOR_PF;
47111c73de9SDariusz Sosnowski 		info->ranges[i].controller = 0;
47211c73de9SDariusz Sosnowski 		info->ranges[i].pf = priv->mpesw_owner + 1;
47311c73de9SDariusz Sosnowski 		info->ranges[i].vf = 0;
47411c73de9SDariusz Sosnowski 		/*
47511c73de9SDariusz Sosnowski 		 * The representor indexes should be the values set of "priv->mpesw_port".
47611c73de9SDariusz Sosnowski 		 * In the real case now, only 1 PF/UPLINK representor is supported.
47711c73de9SDariusz Sosnowski 		 * The port index will always be the value of "owner + 1".
47811c73de9SDariusz Sosnowski 		 */
47911c73de9SDariusz Sosnowski 		info->ranges[i].id_base =
48011c73de9SDariusz Sosnowski 			MLX5_REPRESENTOR_ID(priv->mpesw_owner, info->ranges[i].type,
48111c73de9SDariusz Sosnowski 					    info->ranges[i].pf);
48211c73de9SDariusz Sosnowski 		info->ranges[i].id_end =
48311c73de9SDariusz Sosnowski 			MLX5_REPRESENTOR_ID(priv->mpesw_owner, info->ranges[i].type,
48411c73de9SDariusz Sosnowski 					    info->ranges[i].pf);
48511c73de9SDariusz Sosnowski 		snprintf(info->ranges[i].name, sizeof(info->ranges[i].name),
48611c73de9SDariusz Sosnowski 			 "pf%d", info->ranges[i].pf);
48711c73de9SDariusz Sosnowski 		i++;
48811c73de9SDariusz Sosnowski 	} else if (priv->pf_bond >= 0)
48911c73de9SDariusz Sosnowski 		info->pf = priv->pf_bond;
490cb95feefSXueming Li 	for (pf = 0; pf < n_pf; ++pf) {
491cb95feefSXueming Li 		/* VF range. */
492cb95feefSXueming Li 		info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
493cb95feefSXueming Li 		info->ranges[i].controller = 0;
494cb95feefSXueming Li 		info->ranges[i].pf = pf;
495cb95feefSXueming Li 		info->ranges[i].vf = 0;
496cb95feefSXueming Li 		info->ranges[i].id_base =
497cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, 0);
498cb95feefSXueming Li 		info->ranges[i].id_end =
499cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
500cb95feefSXueming Li 		snprintf(info->ranges[i].name,
501cb95feefSXueming Li 			 sizeof(info->ranges[i].name), "pf%dvf", pf);
502cb95feefSXueming Li 		i++;
50310eaf41dSViacheslav Galaktionov 		if (i == n_entries)
50410eaf41dSViacheslav Galaktionov 			break;
50591766faeSXueming Li 		/* HPF range of VF type. */
506cb95feefSXueming Li 		info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
507cb95feefSXueming Li 		info->ranges[i].controller = 0;
508cb95feefSXueming Li 		info->ranges[i].pf = pf;
509cb95feefSXueming Li 		info->ranges[i].vf = UINT16_MAX;
510cb95feefSXueming Li 		info->ranges[i].id_base =
511cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
512cb95feefSXueming Li 		info->ranges[i].id_end =
513cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
514cb95feefSXueming Li 		snprintf(info->ranges[i].name,
515cb95feefSXueming Li 			 sizeof(info->ranges[i].name), "pf%dvf", pf);
516cb95feefSXueming Li 		i++;
51710eaf41dSViacheslav Galaktionov 		if (i == n_entries)
51810eaf41dSViacheslav Galaktionov 			break;
519cb95feefSXueming Li 		/* SF range. */
520cb95feefSXueming Li 		info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
521cb95feefSXueming Li 		info->ranges[i].controller = 0;
522cb95feefSXueming Li 		info->ranges[i].pf = pf;
523cb95feefSXueming Li 		info->ranges[i].vf = 0;
524cb95feefSXueming Li 		info->ranges[i].id_base =
525cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, 0);
526cb95feefSXueming Li 		info->ranges[i].id_end =
527cb95feefSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
528cb95feefSXueming Li 		snprintf(info->ranges[i].name,
529cb95feefSXueming Li 			 sizeof(info->ranges[i].name), "pf%dsf", pf);
530cb95feefSXueming Li 		i++;
53110eaf41dSViacheslav Galaktionov 		if (i == n_entries)
53210eaf41dSViacheslav Galaktionov 			break;
53391766faeSXueming Li 		/* HPF range of SF type. */
53491766faeSXueming Li 		info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
53591766faeSXueming Li 		info->ranges[i].controller = 0;
53691766faeSXueming Li 		info->ranges[i].pf = pf;
53791766faeSXueming Li 		info->ranges[i].vf = UINT16_MAX;
53891766faeSXueming Li 		info->ranges[i].id_base =
53991766faeSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
54091766faeSXueming Li 		info->ranges[i].id_end =
54191766faeSXueming Li 			MLX5_REPRESENTOR_ID(pf, info->ranges[i].type, -1);
54291766faeSXueming Li 		snprintf(info->ranges[i].name,
54391766faeSXueming Li 			 sizeof(info->ranges[i].name), "pf%dsf", pf);
54491766faeSXueming Li 		i++;
54510eaf41dSViacheslav Galaktionov 		if (i == n_entries)
54610eaf41dSViacheslav Galaktionov 			break;
547cb95feefSXueming Li 	}
54810eaf41dSViacheslav Galaktionov 	info->nb_ranges = i;
549cb95feefSXueming Li out:
550cb95feefSXueming Li 	return n_type * n_pf;
551cb95feefSXueming Li }
552cb95feefSXueming Li 
553cb95feefSXueming Li /**
554714bf46eSThomas Monjalon  * Get firmware version of a device.
555714bf46eSThomas Monjalon  *
556714bf46eSThomas Monjalon  * @param dev
557714bf46eSThomas Monjalon  *   Ethernet device port.
558714bf46eSThomas Monjalon  * @param fw_ver
559714bf46eSThomas Monjalon  *   String output allocated by caller.
560714bf46eSThomas Monjalon  * @param fw_size
561714bf46eSThomas Monjalon  *   Size of the output string, including terminating null byte.
562714bf46eSThomas Monjalon  *
563714bf46eSThomas Monjalon  * @return
564714bf46eSThomas Monjalon  *   0 on success, or the size of the non truncated string if too big.
565714bf46eSThomas Monjalon  */
5661256805dSOphir Munk int
5671256805dSOphir Munk mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
568714bf46eSThomas Monjalon {
569dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
57091d1cfafSMichael Baum 	struct mlx5_dev_cap *attr = &priv->sh->dev_cap;
571714bf46eSThomas Monjalon 	size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
572714bf46eSThomas Monjalon 
573714bf46eSThomas Monjalon 	if (fw_size < size)
574714bf46eSThomas Monjalon 		return size;
575714bf46eSThomas Monjalon 	if (fw_ver != NULL)
576714bf46eSThomas Monjalon 		strlcpy(fw_ver, attr->fw_ver, fw_size);
577714bf46eSThomas Monjalon 	return 0;
578714bf46eSThomas Monjalon }
579714bf46eSThomas Monjalon 
580714bf46eSThomas Monjalon /**
581fb732b0aSNélio Laranjeiro  * Get supported packet types.
582fb732b0aSNélio Laranjeiro  *
583fb732b0aSNélio Laranjeiro  * @param dev
584fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
585fb732b0aSNélio Laranjeiro  *
586fb732b0aSNélio Laranjeiro  * @return
587fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
588fb732b0aSNélio Laranjeiro  */
58978a38edfSJianfeng Tan const uint32_t *
590ba6a168aSSivaramakrishnan Venkat mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
59178a38edfSJianfeng Tan {
59278a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
59378a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
594ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
595c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
596c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
597ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
598ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
599ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
600ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
601c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
602c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
603ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
604ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
605ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
606ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
60778a38edfSJianfeng Tan 	};
60878a38edfSJianfeng Tan 
6096cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
6107d6bf6b8SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_mprq ||
6110f20acbfSAlexander Kozyrev 	    dev->rx_pkt_burst == mlx5_rx_burst_vec ||
612ba6a168aSSivaramakrishnan Venkat 	    dev->rx_pkt_burst == mlx5_rx_burst_mprq_vec) {
613ba6a168aSSivaramakrishnan Venkat 		*no_of_elements = RTE_DIM(ptypes);
61478a38edfSJianfeng Tan 		return ptypes;
615ba6a168aSSivaramakrishnan Venkat 	}
61678a38edfSJianfeng Tan 	return NULL;
61778a38edfSJianfeng Tan }
61878a38edfSJianfeng Tan 
619e60fbd5bSAdrien Mazarguil /**
620cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
621cf37ca95SAdrien Mazarguil  *
622cf37ca95SAdrien Mazarguil  * @param dev
623cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
624cf37ca95SAdrien Mazarguil  * @param in_mtu
625cf37ca95SAdrien Mazarguil  *   New MTU.
626cf37ca95SAdrien Mazarguil  *
627cf37ca95SAdrien Mazarguil  * @return
628a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
629cf37ca95SAdrien Mazarguil  */
630cf37ca95SAdrien Mazarguil int
631cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
632cf37ca95SAdrien Mazarguil {
633dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
634a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
635a6d83b6aSNélio Laranjeiro 	int ret;
636cf37ca95SAdrien Mazarguil 
637af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
638a0edafe4SNelio Laranjeiro 	if (ret)
639a6d83b6aSNélio Laranjeiro 		return ret;
640cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
641af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
642a0edafe4SNelio Laranjeiro 	if (ret)
643a6d83b6aSNélio Laranjeiro 		return ret;
644af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
645a0edafe4SNelio Laranjeiro 	if (ret)
646a6d83b6aSNélio Laranjeiro 		return ret;
647a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
648a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
649a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
650a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
651a0edafe4SNelio Laranjeiro 		return 0;
652a6d83b6aSNélio Laranjeiro 	}
653a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
654a6d83b6aSNélio Laranjeiro 	return -rte_errno;
655cf37ca95SAdrien Mazarguil }
656cf37ca95SAdrien Mazarguil 
657cf37ca95SAdrien Mazarguil /**
658cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
659cdab90cbSNélio Laranjeiro  *
660aee1b165SXueming Li  * @param dev
661af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
6621cfa649bSShahaf Shuler  *
6631cfa649bSShahaf Shuler  * @return
6641cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
665cdab90cbSNélio Laranjeiro  */
6661cfa649bSShahaf Shuler eth_rx_burst_t
667af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
668cdab90cbSNélio Laranjeiro {
6691cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
6701cfa649bSShahaf Shuler 
6718e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(dev != NULL);
672af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
6730f20acbfSAlexander Kozyrev 		if (mlx5_mprq_enabled(dev)) {
6740f20acbfSAlexander Kozyrev 			rx_pkt_burst = mlx5_rx_burst_mprq_vec;
6750f20acbfSAlexander Kozyrev 			DRV_LOG(DEBUG, "port %u selected vectorized"
6760f20acbfSAlexander Kozyrev 				" MPRQ Rx function", dev->data->port_id);
6770f20acbfSAlexander Kozyrev 		} else {
6781cfa649bSShahaf Shuler 			rx_pkt_burst = mlx5_rx_burst_vec;
6790f20acbfSAlexander Kozyrev 			DRV_LOG(DEBUG, "port %u selected vectorized"
6800f20acbfSAlexander Kozyrev 				" SPRQ Rx function", dev->data->port_id);
6810f20acbfSAlexander Kozyrev 		}
6827d6bf6b8SYongseok Koh 	} else if (mlx5_mprq_enabled(dev)) {
6837d6bf6b8SYongseok Koh 		rx_pkt_burst = mlx5_rx_burst_mprq;
6840f20acbfSAlexander Kozyrev 		DRV_LOG(DEBUG, "port %u selected MPRQ Rx function",
6850f20acbfSAlexander Kozyrev 			dev->data->port_id);
6860f20acbfSAlexander Kozyrev 	} else {
6870f20acbfSAlexander Kozyrev 		DRV_LOG(DEBUG, "port %u selected SPRQ Rx function",
6880f20acbfSAlexander Kozyrev 			dev->data->port_id);
689cdab90cbSNélio Laranjeiro 	}
6901cfa649bSShahaf Shuler 	return rx_pkt_burst;
6916cb559d6SYongseok Koh }
692d3e0f392SMatan Azrad 
693d3e0f392SMatan Azrad /**
69409a16bcaSViacheslav Ovsiienko  * Get the E-Switch parameters by port id.
6952e4c987aSOri Kam  *
6962e4c987aSOri Kam  * @param[in] port
6972e4c987aSOri Kam  *   Device port id.
6985e61bcddSViacheslav Ovsiienko  * @param[in] valid
6995e61bcddSViacheslav Ovsiienko  *   Device port id is valid, skip check. This flag is useful
7005e61bcddSViacheslav Ovsiienko  *   when trials are performed from probing and device is not
7015e61bcddSViacheslav Ovsiienko  *   flagged as valid yet (in attaching process).
7022e4c987aSOri Kam  * @param[out] es_domain_id
7032e4c987aSOri Kam  *   E-Switch domain id.
7042e4c987aSOri Kam  * @param[out] es_port_id
7052e4c987aSOri Kam  *   The port id of the port in the E-Switch.
7062e4c987aSOri Kam  *
7072e4c987aSOri Kam  * @return
70809a16bcaSViacheslav Ovsiienko  *   pointer to device private data structure containing data needed
70909a16bcaSViacheslav Ovsiienko  *   on success, NULL otherwise and rte_errno is set.
7102e4c987aSOri Kam  */
71109a16bcaSViacheslav Ovsiienko struct mlx5_priv *
7125e61bcddSViacheslav Ovsiienko mlx5_port_to_eswitch_info(uint16_t port, bool valid)
7132e4c987aSOri Kam {
7142e4c987aSOri Kam 	struct rte_eth_dev *dev;
7152e4c987aSOri Kam 	struct mlx5_priv *priv;
7162e4c987aSOri Kam 
7172e4c987aSOri Kam 	if (port >= RTE_MAX_ETHPORTS) {
7182e4c987aSOri Kam 		rte_errno = EINVAL;
71909a16bcaSViacheslav Ovsiienko 		return NULL;
7202e4c987aSOri Kam 	}
7215e61bcddSViacheslav Ovsiienko 	if (!valid && !rte_eth_dev_is_valid_port(port)) {
7222e4c987aSOri Kam 		rte_errno = ENODEV;
72309a16bcaSViacheslav Ovsiienko 		return NULL;
7242e4c987aSOri Kam 	}
7252e4c987aSOri Kam 	dev = &rte_eth_devices[port];
7262e4c987aSOri Kam 	priv = dev->data->dev_private;
727cf004fd3SMichael Baum 	if (!priv->sh->esw_mode) {
7282e4c987aSOri Kam 		rte_errno = EINVAL;
72909a16bcaSViacheslav Ovsiienko 		return NULL;
7302e4c987aSOri Kam 	}
73109a16bcaSViacheslav Ovsiienko 	return priv;
73209a16bcaSViacheslav Ovsiienko }
73309a16bcaSViacheslav Ovsiienko 
73409a16bcaSViacheslav Ovsiienko /**
73509a16bcaSViacheslav Ovsiienko  * Get the E-Switch parameters by device instance.
73609a16bcaSViacheslav Ovsiienko  *
73709a16bcaSViacheslav Ovsiienko  * @param[in] port
73809a16bcaSViacheslav Ovsiienko  *   Device port id.
73909a16bcaSViacheslav Ovsiienko  * @param[out] es_domain_id
74009a16bcaSViacheslav Ovsiienko  *   E-Switch domain id.
74109a16bcaSViacheslav Ovsiienko  * @param[out] es_port_id
74209a16bcaSViacheslav Ovsiienko  *   The port id of the port in the E-Switch.
74309a16bcaSViacheslav Ovsiienko  *
74409a16bcaSViacheslav Ovsiienko  * @return
74509a16bcaSViacheslav Ovsiienko  *   pointer to device private data structure containing data needed
74609a16bcaSViacheslav Ovsiienko  *   on success, NULL otherwise and rte_errno is set.
74709a16bcaSViacheslav Ovsiienko  */
74809a16bcaSViacheslav Ovsiienko struct mlx5_priv *
74909a16bcaSViacheslav Ovsiienko mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev)
75009a16bcaSViacheslav Ovsiienko {
75109a16bcaSViacheslav Ovsiienko 	struct mlx5_priv *priv;
75209a16bcaSViacheslav Ovsiienko 
75309a16bcaSViacheslav Ovsiienko 	priv = dev->data->dev_private;
754cf004fd3SMichael Baum 	if (!priv->sh->esw_mode) {
75509a16bcaSViacheslav Ovsiienko 		rte_errno = EINVAL;
75609a16bcaSViacheslav Ovsiienko 		return NULL;
75709a16bcaSViacheslav Ovsiienko 	}
75809a16bcaSViacheslav Ovsiienko 	return priv;
7592e4c987aSOri Kam }
7602e4c987aSOri Kam 
7612e4c987aSOri Kam /**
762b6b3bf86SOri Kam  * DPDK callback to retrieve hairpin capabilities.
763b6b3bf86SOri Kam  *
764b6b3bf86SOri Kam  * @param dev
765b6b3bf86SOri Kam  *   Pointer to Ethernet device structure.
766b6b3bf86SOri Kam  * @param[out] cap
767b6b3bf86SOri Kam  *   Storage for hairpin capability data.
768b6b3bf86SOri Kam  *
769b6b3bf86SOri Kam  * @return
770b6b3bf86SOri Kam  *   0 on success, a negative errno value otherwise and rte_errno is set.
771b6b3bf86SOri Kam  */
7721256805dSOphir Munk int
773b00f7603SMichael Baum mlx5_hairpin_cap_get(struct rte_eth_dev *dev, struct rte_eth_hairpin_cap *cap)
774b6b3bf86SOri Kam {
775b6b3bf86SOri Kam 	struct mlx5_priv *priv = dev->data->dev_private;
7767274b417SDariusz Sosnowski 	struct mlx5_hca_attr *hca_attr;
777b6b3bf86SOri Kam 
778c4b86201SMichael Baum 	if (!mlx5_devx_obj_ops_en(priv->sh)) {
779b6b3bf86SOri Kam 		rte_errno = ENOTSUP;
780b6b3bf86SOri Kam 		return -rte_errno;
781b6b3bf86SOri Kam 	}
782b6b3bf86SOri Kam 	cap->max_nb_queues = UINT16_MAX;
783b6b3bf86SOri Kam 	cap->max_rx_2_tx = 1;
784b6b3bf86SOri Kam 	cap->max_tx_2_rx = 1;
785b6b3bf86SOri Kam 	cap->max_nb_desc = 8192;
7867274b417SDariusz Sosnowski 	hca_attr = &priv->sh->cdev->config.hca_attr;
787f2d43ff5SDariusz Sosnowski 	cap->rx_cap.locked_device_memory = hca_attr->hairpin_data_buffer_locked;
788f2d43ff5SDariusz Sosnowski 	cap->rx_cap.rte_memory = 0;
7897274b417SDariusz Sosnowski 	cap->tx_cap.locked_device_memory = 0;
7907274b417SDariusz Sosnowski 	cap->tx_cap.rte_memory = hca_attr->hairpin_sq_wq_in_host_mem;
791b6b3bf86SOri Kam 	return 0;
792b6b3bf86SOri Kam }
793