xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision b00f760354db0fd09f58bf6fb59972d50e772676)
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 
13771fa900SAdrien Mazarguil #include <rte_atomic.h>
14ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
15c752998bSGaetan Rivet #include <rte_bus_pci.h>
16771fa900SAdrien Mazarguil #include <rte_mbuf.h>
17771fa900SAdrien Mazarguil #include <rte_common.h>
18198a3c33SNelio Laranjeiro #include <rte_interrupts.h>
19a48deadaSOr Ami #include <rte_malloc.h>
20c022cb40SBruce Richardson #include <rte_string_fns.h>
21974f1e7eSYongseok Koh #include <rte_rwlock.h>
225897ac13SViacheslav Ovsiienko #include <rte_cycles.h>
23771fa900SAdrien Mazarguil 
2483c2047cSSuanming Mou #include <mlx5_malloc.h>
2583c2047cSSuanming Mou 
26e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h"
271256805dSOphir Munk #include "mlx5_autoconf.h"
282b730263SAdrien Mazarguil 
292b730263SAdrien Mazarguil /**
30ccdcba53SNélio Laranjeiro  * Get the interface index from device name.
31ccdcba53SNélio Laranjeiro  *
32ccdcba53SNélio Laranjeiro  * @param[in] dev
33ccdcba53SNélio Laranjeiro  *   Pointer to Ethernet device.
34ccdcba53SNélio Laranjeiro  *
35ccdcba53SNélio Laranjeiro  * @return
363f8cb05dSAdrien Mazarguil  *   Nonzero interface index on success, zero otherwise and rte_errno is set.
37ccdcba53SNélio Laranjeiro  */
383f8cb05dSAdrien Mazarguil unsigned int
39ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev)
40ccdcba53SNélio Laranjeiro {
41fa2e14d4SViacheslav Ovsiienko 	struct mlx5_priv *priv = dev->data->dev_private;
423f8cb05dSAdrien Mazarguil 	unsigned int ifindex;
43ccdcba53SNélio Laranjeiro 
448e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(priv);
458e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(priv->if_index);
46fa2e14d4SViacheslav Ovsiienko 	ifindex = priv->if_index;
473f8cb05dSAdrien Mazarguil 	if (!ifindex)
48fa2e14d4SViacheslav Ovsiienko 		rte_errno = ENXIO;
493f8cb05dSAdrien Mazarguil 	return ifindex;
50ccdcba53SNélio Laranjeiro }
51ccdcba53SNélio Laranjeiro 
52ccdcba53SNélio Laranjeiro /**
537b2423cdSNélio Laranjeiro  * DPDK callback for Ethernet device configuration.
54e60fbd5bSAdrien Mazarguil  *
55e60fbd5bSAdrien Mazarguil  * @param dev
56e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
57e60fbd5bSAdrien Mazarguil  *
58e60fbd5bSAdrien Mazarguil  * @return
59a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
60e60fbd5bSAdrien Mazarguil  */
617b2423cdSNélio Laranjeiro int
627b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev)
63e60fbd5bSAdrien Mazarguil {
64dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
65e60fbd5bSAdrien Mazarguil 	unsigned int rxqs_n = dev->data->nb_rx_queues;
66e60fbd5bSAdrien Mazarguil 	unsigned int txqs_n = dev->data->nb_tx_queues;
6729c1d8bbSNélio Laranjeiro 	const uint8_t use_app_rss_key =
6821e3a974SShahaf Shuler 		!!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
69a6d83b6aSNélio Laranjeiro 	int ret = 0;
70e60fbd5bSAdrien Mazarguil 
7129c1d8bbSNélio Laranjeiro 	if (use_app_rss_key &&
7229c1d8bbSNélio Laranjeiro 	    (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
73c388a2f6SNelio Laranjeiro 	     MLX5_RSS_HASH_KEY_LEN)) {
74c388a2f6SNelio Laranjeiro 		DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long",
75c388a2f6SNelio Laranjeiro 			dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN));
76a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
77a6d83b6aSNélio Laranjeiro 		return -rte_errno;
7829c1d8bbSNélio Laranjeiro 	}
7929c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key =
8083c2047cSSuanming Mou 		mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE,
8183c2047cSSuanming Mou 			    MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY);
8229c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
83a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
840f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
85a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
86a6d83b6aSNélio Laranjeiro 		return -rte_errno;
8729c1d8bbSNélio Laranjeiro 	}
888b945a7fSPavan Nikhilesh 
8973fb89ddSAndrew Rybchenko 	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
908b945a7fSPavan Nikhilesh 		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
918b945a7fSPavan Nikhilesh 
9229c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
9329c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
9429c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
9529c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
96c388a2f6SNelio Laranjeiro 	       MLX5_RSS_HASH_KEY_LEN);
97c388a2f6SNelio Laranjeiro 	priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN;
9829c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
99e60fbd5bSAdrien Mazarguil 	priv->rxqs = (void *)dev->data->rx_queues;
100e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
101e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
102a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
1030f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
104e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
105e60fbd5bSAdrien Mazarguil 	}
1067fe24446SShahaf Shuler 	if (rxqs_n > priv->config.ind_table_max_size) {
107a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
1080f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
109a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
110a6d83b6aSNélio Laranjeiro 		return -rte_errno;
111634efbc2SNelio Laranjeiro 	}
11209ba4c58SDekel Peled 	if (rxqs_n != priv->rxqs_n) {
113a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
1140f99970bSNélio Laranjeiro 			dev->data->port_id, priv->rxqs_n, rxqs_n);
115e60fbd5bSAdrien Mazarguil 		priv->rxqs_n = rxqs_n;
11663bd1629SOri Kam 	}
11763bd1629SOri Kam 	priv->skip_default_rss_reta = 0;
11863bd1629SOri Kam 	ret = mlx5_proc_priv_init(dev);
11963bd1629SOri Kam 	if (ret)
12063bd1629SOri Kam 		return ret;
12163bd1629SOri Kam 	return 0;
12263bd1629SOri Kam }
12363bd1629SOri Kam 
12463bd1629SOri Kam /**
12563bd1629SOri Kam  * Configure default RSS reta.
12663bd1629SOri Kam  *
12763bd1629SOri Kam  * @param dev
12863bd1629SOri Kam  *   Pointer to Ethernet device structure.
12963bd1629SOri Kam  *
13063bd1629SOri Kam  * @return
13163bd1629SOri Kam  *   0 on success, a negative errno value otherwise and rte_errno is set.
13263bd1629SOri Kam  */
13363bd1629SOri Kam int
13463bd1629SOri Kam mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
13563bd1629SOri Kam {
13663bd1629SOri Kam 	struct mlx5_priv *priv = dev->data->dev_private;
13763bd1629SOri Kam 	unsigned int rxqs_n = dev->data->nb_rx_queues;
13863bd1629SOri Kam 	unsigned int i;
13963bd1629SOri Kam 	unsigned int j;
14063bd1629SOri Kam 	unsigned int reta_idx_n;
14163bd1629SOri Kam 	int ret = 0;
14263bd1629SOri Kam 	unsigned int *rss_queue_arr = NULL;
14363bd1629SOri Kam 	unsigned int rss_queue_n = 0;
14463bd1629SOri Kam 
14563bd1629SOri Kam 	if (priv->skip_default_rss_reta)
14663bd1629SOri Kam 		return ret;
14783c2047cSSuanming Mou 	rss_queue_arr = mlx5_malloc(0, rxqs_n * sizeof(unsigned int), 0,
14883c2047cSSuanming Mou 				    SOCKET_ID_ANY);
14963bd1629SOri Kam 	if (!rss_queue_arr) {
15063bd1629SOri Kam 		DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)",
15163bd1629SOri Kam 			dev->data->port_id, rxqs_n);
15263bd1629SOri Kam 		rte_errno = ENOMEM;
15363bd1629SOri Kam 		return -rte_errno;
15463bd1629SOri Kam 	}
15563bd1629SOri Kam 	for (i = 0, j = 0; i < rxqs_n; i++) {
15663bd1629SOri Kam 		struct mlx5_rxq_data *rxq_data;
15763bd1629SOri Kam 		struct mlx5_rxq_ctrl *rxq_ctrl;
15863bd1629SOri Kam 
15963bd1629SOri Kam 		rxq_data = (*priv->rxqs)[i];
16063bd1629SOri Kam 		rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
161bf864e82STonghao Zhang 		if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
16263bd1629SOri Kam 			rss_queue_arr[j++] = i;
16363bd1629SOri Kam 	}
16463bd1629SOri Kam 	rss_queue_n = j;
16563bd1629SOri Kam 	if (rss_queue_n > priv->config.ind_table_max_size) {
16663bd1629SOri Kam 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
16763bd1629SOri Kam 			dev->data->port_id, rss_queue_n);
16863bd1629SOri Kam 		rte_errno = EINVAL;
16983c2047cSSuanming Mou 		mlx5_free(rss_queue_arr);
17063bd1629SOri Kam 		return -rte_errno;
17163bd1629SOri Kam 	}
17263bd1629SOri Kam 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
17363bd1629SOri Kam 		dev->data->port_id, priv->rxqs_n, rxqs_n);
17463bd1629SOri Kam 	priv->rxqs_n = rxqs_n;
17509ba4c58SDekel Peled 	/*
17609ba4c58SDekel Peled 	 * If the requested number of RX queues is not a power of two,
17709ba4c58SDekel Peled 	 * use the maximum indirection table size for better balancing.
17809ba4c58SDekel Peled 	 * The result is always rounded to the next power of two.
17909ba4c58SDekel Peled 	 */
18063bd1629SOri Kam 	reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ?
1817fe24446SShahaf Shuler 				priv->config.ind_table_max_size :
18263bd1629SOri Kam 				rss_queue_n));
183a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
18463bd1629SOri Kam 	if (ret) {
18583c2047cSSuanming Mou 		mlx5_free(rss_queue_arr);
186a6d83b6aSNélio Laranjeiro 		return ret;
18763bd1629SOri Kam 	}
18809ba4c58SDekel Peled 	/*
18909ba4c58SDekel Peled 	 * When the number of RX queues is not a power of two,
19009ba4c58SDekel Peled 	 * the remaining table entries are padded with reused WQs
19109ba4c58SDekel Peled 	 * and hashes are not spread uniformly.
19209ba4c58SDekel Peled 	 */
193634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
19463bd1629SOri Kam 		(*priv->reta_idx)[i] = rss_queue_arr[j];
19563bd1629SOri Kam 		if (++j == rss_queue_n)
196634efbc2SNelio Laranjeiro 			j = 0;
197634efbc2SNelio Laranjeiro 	}
19883c2047cSSuanming Mou 	mlx5_free(rss_queue_arr);
199120dc4a7SYongseok Koh 	return ret;
200e60fbd5bSAdrien Mazarguil }
201e60fbd5bSAdrien Mazarguil 
202e60fbd5bSAdrien Mazarguil /**
203d11d651fSShahaf Shuler  * Sets default tuning parameters.
204d11d651fSShahaf Shuler  *
205d11d651fSShahaf Shuler  * @param dev
206d11d651fSShahaf Shuler  *   Pointer to Ethernet device.
207d11d651fSShahaf Shuler  * @param[out] info
208d11d651fSShahaf Shuler  *   Info structure output buffer.
209d11d651fSShahaf Shuler  */
210d11d651fSShahaf Shuler static void
211d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
212d11d651fSShahaf Shuler {
213dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
214d11d651fSShahaf Shuler 
215d11d651fSShahaf Shuler 	/* Minimum CPU utilization. */
216d11d651fSShahaf Shuler 	info->default_rxportconf.ring_size = 256;
217d11d651fSShahaf Shuler 	info->default_txportconf.ring_size = 256;
218f078ceb6SViacheslav Ovsiienko 	info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST;
219f078ceb6SViacheslav Ovsiienko 	info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST;
2206e3a4595SAsaf Penso 	if ((priv->link_speed_capa & ETH_LINK_SPEED_200G) |
2216e3a4595SAsaf Penso 		(priv->link_speed_capa & ETH_LINK_SPEED_100G)) {
222d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 16;
223d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 16;
224d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
225d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
226d11d651fSShahaf Shuler 			/* Max Throughput. */
227d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 2048;
228d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 2048;
229d11d651fSShahaf Shuler 		}
230d11d651fSShahaf Shuler 	} else {
231d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 8;
232d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 8;
233d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
234d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
235d11d651fSShahaf Shuler 			/* Max Throughput. */
236d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 4096;
237d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 4096;
238d11d651fSShahaf Shuler 		}
239d11d651fSShahaf Shuler 	}
240d11d651fSShahaf Shuler }
241d11d651fSShahaf Shuler 
242d11d651fSShahaf Shuler /**
243cb9cb61eSViacheslav Ovsiienko  * Sets tx mbuf limiting parameters.
244cb9cb61eSViacheslav Ovsiienko  *
245cb9cb61eSViacheslav Ovsiienko  * @param dev
246cb9cb61eSViacheslav Ovsiienko  *   Pointer to Ethernet device.
247cb9cb61eSViacheslav Ovsiienko  * @param[out] info
248cb9cb61eSViacheslav Ovsiienko  *   Info structure output buffer.
249cb9cb61eSViacheslav Ovsiienko  */
250cb9cb61eSViacheslav Ovsiienko static void
251cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
252cb9cb61eSViacheslav Ovsiienko {
253cb9cb61eSViacheslav Ovsiienko 	struct mlx5_priv *priv = dev->data->dev_private;
254cb9cb61eSViacheslav Ovsiienko 	struct mlx5_dev_config *config = &priv->config;
255cb9cb61eSViacheslav Ovsiienko 	unsigned int inlen;
256cb9cb61eSViacheslav Ovsiienko 	uint16_t nb_max;
257cb9cb61eSViacheslav Ovsiienko 
258cb9cb61eSViacheslav Ovsiienko 	inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ?
259cb9cb61eSViacheslav Ovsiienko 		MLX5_SEND_DEF_INLINE_LEN :
260cb9cb61eSViacheslav Ovsiienko 		(unsigned int)config->txq_inline_max;
2618e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(config->txq_inline_min >= 0);
262cb9cb61eSViacheslav Ovsiienko 	inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min);
263cb9cb61eSViacheslav Ovsiienko 	inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX +
264cb9cb61eSViacheslav Ovsiienko 			       MLX5_ESEG_MIN_INLINE_SIZE -
265cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_CSEG_SIZE -
266cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_ESEG_SIZE -
267cb9cb61eSViacheslav Ovsiienko 			       MLX5_WQE_DSEG_SIZE * 2);
268cb9cb61eSViacheslav Ovsiienko 	nb_max = (MLX5_WQE_SIZE_MAX +
269cb9cb61eSViacheslav Ovsiienko 		  MLX5_ESEG_MIN_INLINE_SIZE -
270cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_CSEG_SIZE -
271cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_ESEG_SIZE -
272cb9cb61eSViacheslav Ovsiienko 		  MLX5_WQE_DSEG_SIZE -
273cb9cb61eSViacheslav Ovsiienko 		  inlen) / MLX5_WSEG_SIZE;
274cb9cb61eSViacheslav Ovsiienko 	info->tx_desc_lim.nb_seg_max = nb_max;
275cb9cb61eSViacheslav Ovsiienko 	info->tx_desc_lim.nb_mtu_seg_max = nb_max;
276cb9cb61eSViacheslav Ovsiienko }
277cb9cb61eSViacheslav Ovsiienko 
278cb9cb61eSViacheslav Ovsiienko /**
279e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
280e60fbd5bSAdrien Mazarguil  *
281e60fbd5bSAdrien Mazarguil  * @param dev
282e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
283e60fbd5bSAdrien Mazarguil  * @param[out] info
284e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
285e60fbd5bSAdrien Mazarguil  */
286bdad90d1SIvan Ilchenko int
287e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
288e60fbd5bSAdrien Mazarguil {
289dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
2907fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
291e60fbd5bSAdrien Mazarguil 	unsigned int max;
292e60fbd5bSAdrien Mazarguil 
293e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
294e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
295e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
2961c7e57f9SDekel Peled 	info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE;
297e60fbd5bSAdrien Mazarguil 	/*
298e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
299e60fbd5bSAdrien Mazarguil 	 * between the two values.
300e60fbd5bSAdrien Mazarguil 	 */
301e85f623eSOphir Munk 	max = RTE_MIN(priv->sh->device_attr.max_cq,
302e85f623eSOphir Munk 		      priv->sh->device_attr.max_qp);
303b689a781SThomas Monjalon 	/* max_rx_queues is uint16_t. */
304b689a781SThomas Monjalon 	max = RTE_MIN(max, (unsigned int)UINT16_MAX);
305e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
306e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
30718c01b98SNélio Laranjeiro 	info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES;
308af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
30917ed314cSMatan Azrad 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
31017b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
311af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
312fa2e14d4SViacheslav Ovsiienko 	info->if_index = mlx5_ifindex(dev);
313d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
3147fe24446SShahaf Shuler 		priv->reta_idx_n : config->ind_table_max_size;
315c388a2f6SNelio Laranjeiro 	info->hash_key_size = MLX5_RSS_HASH_KEY_LEN;
31675ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
317b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
318d11d651fSShahaf Shuler 	mlx5_set_default_params(dev, info);
319cb9cb61eSViacheslav Ovsiienko 	mlx5_set_txlimit_params(dev, info);
3202b730263SAdrien Mazarguil 	info->switch_info.name = dev->data->name;
3212b730263SAdrien Mazarguil 	info->switch_info.domain_id = priv->domain_id;
3222b730263SAdrien Mazarguil 	info->switch_info.port_id = priv->representor_id;
3232b730263SAdrien Mazarguil 	if (priv->representor) {
324f7e95215SViacheslav Ovsiienko 		uint16_t port_id;
3252b730263SAdrien Mazarguil 
326bee57a0aSViacheslav Ovsiienko 		if (priv->pf_bond >= 0) {
327bee57a0aSViacheslav Ovsiienko 			/*
328bee57a0aSViacheslav Ovsiienko 			 * Switch port ID is opaque value with driver defined
329bee57a0aSViacheslav Ovsiienko 			 * format. Push the PF index in bonding configurations
330bee57a0aSViacheslav Ovsiienko 			 * in upper four bits of port ID. If we get too many
331bee57a0aSViacheslav Ovsiienko 			 * representors (more than 4K) or PFs (more than 15)
332bee57a0aSViacheslav Ovsiienko 			 * this approach must be reconsidered.
333bee57a0aSViacheslav Ovsiienko 			 */
334bee57a0aSViacheslav Ovsiienko 			if ((info->switch_info.port_id >>
335bee57a0aSViacheslav Ovsiienko 				MLX5_PORT_ID_BONDING_PF_SHIFT) ||
336bee57a0aSViacheslav Ovsiienko 			    priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) {
337bee57a0aSViacheslav Ovsiienko 				DRV_LOG(ERR, "can't update switch port ID"
338bee57a0aSViacheslav Ovsiienko 					     " for bonding device");
3398e46d4e1SAlexander Kozyrev 				MLX5_ASSERT(false);
340bee57a0aSViacheslav Ovsiienko 				return -ENODEV;
341bee57a0aSViacheslav Ovsiienko 			}
342bee57a0aSViacheslav Ovsiienko 			info->switch_info.port_id |=
343bee57a0aSViacheslav Ovsiienko 				priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT;
344bee57a0aSViacheslav Ovsiienko 		}
345fbc83412SViacheslav Ovsiienko 		MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
346dbeba4cfSThomas Monjalon 			struct mlx5_priv *opriv =
347f7e95215SViacheslav Ovsiienko 				rte_eth_devices[port_id].data->dev_private;
3482b730263SAdrien Mazarguil 
3492b730263SAdrien Mazarguil 			if (!opriv ||
3502b730263SAdrien Mazarguil 			    opriv->representor ||
351f7e95215SViacheslav Ovsiienko 			    opriv->sh != priv->sh ||
3522b730263SAdrien Mazarguil 			    opriv->domain_id != priv->domain_id)
3532b730263SAdrien Mazarguil 				continue;
3542b730263SAdrien Mazarguil 			/*
3552b730263SAdrien Mazarguil 			 * Override switch name with that of the master
3562b730263SAdrien Mazarguil 			 * device.
3572b730263SAdrien Mazarguil 			 */
3582b730263SAdrien Mazarguil 			info->switch_info.name = opriv->dev_data->name;
3592b730263SAdrien Mazarguil 			break;
3602b730263SAdrien Mazarguil 		}
3612b730263SAdrien Mazarguil 	}
362bdad90d1SIvan Ilchenko 	return 0;
363e60fbd5bSAdrien Mazarguil }
364e60fbd5bSAdrien Mazarguil 
365fb732b0aSNélio Laranjeiro /**
366714bf46eSThomas Monjalon  * Get firmware version of a device.
367714bf46eSThomas Monjalon  *
368714bf46eSThomas Monjalon  * @param dev
369714bf46eSThomas Monjalon  *   Ethernet device port.
370714bf46eSThomas Monjalon  * @param fw_ver
371714bf46eSThomas Monjalon  *   String output allocated by caller.
372714bf46eSThomas Monjalon  * @param fw_size
373714bf46eSThomas Monjalon  *   Size of the output string, including terminating null byte.
374714bf46eSThomas Monjalon  *
375714bf46eSThomas Monjalon  * @return
376714bf46eSThomas Monjalon  *   0 on success, or the size of the non truncated string if too big.
377714bf46eSThomas Monjalon  */
3781256805dSOphir Munk int
3791256805dSOphir Munk mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
380714bf46eSThomas Monjalon {
381dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
382e85f623eSOphir Munk 	struct mlx5_dev_attr *attr = &priv->sh->device_attr;
383714bf46eSThomas Monjalon 	size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
384714bf46eSThomas Monjalon 
385714bf46eSThomas Monjalon 	if (fw_size < size)
386714bf46eSThomas Monjalon 		return size;
387714bf46eSThomas Monjalon 	if (fw_ver != NULL)
388714bf46eSThomas Monjalon 		strlcpy(fw_ver, attr->fw_ver, fw_size);
389714bf46eSThomas Monjalon 	return 0;
390714bf46eSThomas Monjalon }
391714bf46eSThomas Monjalon 
392714bf46eSThomas Monjalon /**
393fb732b0aSNélio Laranjeiro  * Get supported packet types.
394fb732b0aSNélio Laranjeiro  *
395fb732b0aSNélio Laranjeiro  * @param dev
396fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
397fb732b0aSNélio Laranjeiro  *
398fb732b0aSNélio Laranjeiro  * @return
399fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
400fb732b0aSNélio Laranjeiro  */
40178a38edfSJianfeng Tan const uint32_t *
40278a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
40378a38edfSJianfeng Tan {
40478a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
40578a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
406ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
407c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
408c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
409ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
410ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
411ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
412ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
413c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
414c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
415ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
416ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
417ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
418ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
41978a38edfSJianfeng Tan 		RTE_PTYPE_UNKNOWN
42078a38edfSJianfeng Tan 	};
42178a38edfSJianfeng Tan 
4226cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
4237d6bf6b8SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_mprq ||
4246cb559d6SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_vec)
42578a38edfSJianfeng Tan 		return ptypes;
42678a38edfSJianfeng Tan 	return NULL;
42778a38edfSJianfeng Tan }
42878a38edfSJianfeng Tan 
429e60fbd5bSAdrien Mazarguil /**
430cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
431cf37ca95SAdrien Mazarguil  *
432cf37ca95SAdrien Mazarguil  * @param dev
433cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
434cf37ca95SAdrien Mazarguil  * @param in_mtu
435cf37ca95SAdrien Mazarguil  *   New MTU.
436cf37ca95SAdrien Mazarguil  *
437cf37ca95SAdrien Mazarguil  * @return
438a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
439cf37ca95SAdrien Mazarguil  */
440cf37ca95SAdrien Mazarguil int
441cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
442cf37ca95SAdrien Mazarguil {
443dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
444a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
445a6d83b6aSNélio Laranjeiro 	int ret;
446cf37ca95SAdrien Mazarguil 
447af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
448a0edafe4SNelio Laranjeiro 	if (ret)
449a6d83b6aSNélio Laranjeiro 		return ret;
450cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
451af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
452a0edafe4SNelio Laranjeiro 	if (ret)
453a6d83b6aSNélio Laranjeiro 		return ret;
454af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
455a0edafe4SNelio Laranjeiro 	if (ret)
456a6d83b6aSNélio Laranjeiro 		return ret;
457a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
458a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
459a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
460a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
461a0edafe4SNelio Laranjeiro 		return 0;
462a6d83b6aSNélio Laranjeiro 	}
463a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
464a6d83b6aSNélio Laranjeiro 	return -rte_errno;
465cf37ca95SAdrien Mazarguil }
466cf37ca95SAdrien Mazarguil 
467cf37ca95SAdrien Mazarguil /**
468cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
469cdab90cbSNélio Laranjeiro  *
470aee1b165SXueming Li  * @param dev
471af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
4721cfa649bSShahaf Shuler  *
4731cfa649bSShahaf Shuler  * @return
4741cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
475cdab90cbSNélio Laranjeiro  */
4761cfa649bSShahaf Shuler eth_rx_burst_t
477af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
478cdab90cbSNélio Laranjeiro {
4791cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
4801cfa649bSShahaf Shuler 
4818e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(dev != NULL);
482af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
4831cfa649bSShahaf Shuler 		rx_pkt_burst = mlx5_rx_burst_vec;
484a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected Rx vectorized function",
4850f99970bSNélio Laranjeiro 			dev->data->port_id);
4867d6bf6b8SYongseok Koh 	} else if (mlx5_mprq_enabled(dev)) {
4877d6bf6b8SYongseok Koh 		rx_pkt_burst = mlx5_rx_burst_mprq;
488cdab90cbSNélio Laranjeiro 	}
4891cfa649bSShahaf Shuler 	return rx_pkt_burst;
4906cb559d6SYongseok Koh }
491d3e0f392SMatan Azrad 
492d3e0f392SMatan Azrad /**
49309a16bcaSViacheslav Ovsiienko  * Get the E-Switch parameters by port id.
4942e4c987aSOri Kam  *
4952e4c987aSOri Kam  * @param[in] port
4962e4c987aSOri Kam  *   Device port id.
4975e61bcddSViacheslav Ovsiienko  * @param[in] valid
4985e61bcddSViacheslav Ovsiienko  *   Device port id is valid, skip check. This flag is useful
4995e61bcddSViacheslav Ovsiienko  *   when trials are performed from probing and device is not
5005e61bcddSViacheslav Ovsiienko  *   flagged as valid yet (in attaching process).
5012e4c987aSOri Kam  * @param[out] es_domain_id
5022e4c987aSOri Kam  *   E-Switch domain id.
5032e4c987aSOri Kam  * @param[out] es_port_id
5042e4c987aSOri Kam  *   The port id of the port in the E-Switch.
5052e4c987aSOri Kam  *
5062e4c987aSOri Kam  * @return
50709a16bcaSViacheslav Ovsiienko  *   pointer to device private data structure containing data needed
50809a16bcaSViacheslav Ovsiienko  *   on success, NULL otherwise and rte_errno is set.
5092e4c987aSOri Kam  */
51009a16bcaSViacheslav Ovsiienko struct mlx5_priv *
5115e61bcddSViacheslav Ovsiienko mlx5_port_to_eswitch_info(uint16_t port, bool valid)
5122e4c987aSOri Kam {
5132e4c987aSOri Kam 	struct rte_eth_dev *dev;
5142e4c987aSOri Kam 	struct mlx5_priv *priv;
5152e4c987aSOri Kam 
5162e4c987aSOri Kam 	if (port >= RTE_MAX_ETHPORTS) {
5172e4c987aSOri Kam 		rte_errno = EINVAL;
51809a16bcaSViacheslav Ovsiienko 		return NULL;
5192e4c987aSOri Kam 	}
5205e61bcddSViacheslav Ovsiienko 	if (!valid && !rte_eth_dev_is_valid_port(port)) {
5212e4c987aSOri Kam 		rte_errno = ENODEV;
52209a16bcaSViacheslav Ovsiienko 		return NULL;
5232e4c987aSOri Kam 	}
5242e4c987aSOri Kam 	dev = &rte_eth_devices[port];
5252e4c987aSOri Kam 	priv = dev->data->dev_private;
5262e4c987aSOri Kam 	if (!(priv->representor || priv->master)) {
5272e4c987aSOri Kam 		rte_errno = EINVAL;
52809a16bcaSViacheslav Ovsiienko 		return NULL;
5292e4c987aSOri Kam 	}
53009a16bcaSViacheslav Ovsiienko 	return priv;
53109a16bcaSViacheslav Ovsiienko }
53209a16bcaSViacheslav Ovsiienko 
53309a16bcaSViacheslav Ovsiienko /**
53409a16bcaSViacheslav Ovsiienko  * Get the E-Switch parameters by device instance.
53509a16bcaSViacheslav Ovsiienko  *
53609a16bcaSViacheslav Ovsiienko  * @param[in] port
53709a16bcaSViacheslav Ovsiienko  *   Device port id.
53809a16bcaSViacheslav Ovsiienko  * @param[out] es_domain_id
53909a16bcaSViacheslav Ovsiienko  *   E-Switch domain id.
54009a16bcaSViacheslav Ovsiienko  * @param[out] es_port_id
54109a16bcaSViacheslav Ovsiienko  *   The port id of the port in the E-Switch.
54209a16bcaSViacheslav Ovsiienko  *
54309a16bcaSViacheslav Ovsiienko  * @return
54409a16bcaSViacheslav Ovsiienko  *   pointer to device private data structure containing data needed
54509a16bcaSViacheslav Ovsiienko  *   on success, NULL otherwise and rte_errno is set.
54609a16bcaSViacheslav Ovsiienko  */
54709a16bcaSViacheslav Ovsiienko struct mlx5_priv *
54809a16bcaSViacheslav Ovsiienko mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev)
54909a16bcaSViacheslav Ovsiienko {
55009a16bcaSViacheslav Ovsiienko 	struct mlx5_priv *priv;
55109a16bcaSViacheslav Ovsiienko 
55209a16bcaSViacheslav Ovsiienko 	priv = dev->data->dev_private;
55309a16bcaSViacheslav Ovsiienko 	if (!(priv->representor || priv->master)) {
55409a16bcaSViacheslav Ovsiienko 		rte_errno = EINVAL;
55509a16bcaSViacheslav Ovsiienko 		return NULL;
55609a16bcaSViacheslav Ovsiienko 	}
55709a16bcaSViacheslav Ovsiienko 	return priv;
5582e4c987aSOri Kam }
5592e4c987aSOri Kam 
5602e4c987aSOri Kam /**
561b6b3bf86SOri Kam  * DPDK callback to retrieve hairpin capabilities.
562b6b3bf86SOri Kam  *
563b6b3bf86SOri Kam  * @param dev
564b6b3bf86SOri Kam  *   Pointer to Ethernet device structure.
565b6b3bf86SOri Kam  * @param[out] cap
566b6b3bf86SOri Kam  *   Storage for hairpin capability data.
567b6b3bf86SOri Kam  *
568b6b3bf86SOri Kam  * @return
569b6b3bf86SOri Kam  *   0 on success, a negative errno value otherwise and rte_errno is set.
570b6b3bf86SOri Kam  */
5711256805dSOphir Munk int
572*b00f7603SMichael Baum mlx5_hairpin_cap_get(struct rte_eth_dev *dev, struct rte_eth_hairpin_cap *cap)
573b6b3bf86SOri Kam {
574b6b3bf86SOri Kam 	struct mlx5_priv *priv = dev->data->dev_private;
575*b00f7603SMichael Baum 	struct mlx5_dev_config *config = &priv->config;
576b6b3bf86SOri Kam 
577*b00f7603SMichael Baum 	if (!priv->sh->devx || !config->dest_tir || !config->dv_flow_en) {
578b6b3bf86SOri Kam 		rte_errno = ENOTSUP;
579b6b3bf86SOri Kam 		return -rte_errno;
580b6b3bf86SOri Kam 	}
581b6b3bf86SOri Kam 	cap->max_nb_queues = UINT16_MAX;
582b6b3bf86SOri Kam 	cap->max_rx_2_tx = 1;
583b6b3bf86SOri Kam 	cap->max_tx_2_rx = 1;
584b6b3bf86SOri Kam 	cap->max_nb_desc = 8192;
585b6b3bf86SOri Kam 	return 0;
586b6b3bf86SOri Kam }
587