xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision ddb0384346be3e1a0f0f478831b3c5f4adc20be9)
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