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