xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision 7dd7be29b4cac1f8a1e7f5456585ab64ee0ccd68)
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 
6f8b9a3baSXueming Li #define _GNU_SOURCE
7f8b9a3baSXueming Li 
8771fa900SAdrien Mazarguil #include <stddef.h>
9e60fbd5bSAdrien Mazarguil #include <assert.h>
10fc40db99SAdrien Mazarguil #include <inttypes.h>
11771fa900SAdrien Mazarguil #include <unistd.h>
12771fa900SAdrien Mazarguil #include <stdint.h>
13771fa900SAdrien Mazarguil #include <stdio.h>
14771fa900SAdrien Mazarguil #include <string.h>
15771fa900SAdrien Mazarguil #include <stdlib.h>
16771fa900SAdrien Mazarguil #include <errno.h>
17771fa900SAdrien Mazarguil #include <dirent.h>
18771fa900SAdrien Mazarguil #include <net/if.h>
19771fa900SAdrien Mazarguil #include <sys/ioctl.h>
20771fa900SAdrien Mazarguil #include <sys/socket.h>
21771fa900SAdrien Mazarguil #include <netinet/in.h>
22cb8faed7SAdrien Mazarguil #include <linux/ethtool.h>
23cb8faed7SAdrien Mazarguil #include <linux/sockios.h>
24198a3c33SNelio Laranjeiro #include <fcntl.h>
2590260d57SNélio Laranjeiro #include <stdalign.h>
26f8b9a3baSXueming Li #include <sys/un.h>
27cfee9475SNélio Laranjeiro #include <time.h>
28771fa900SAdrien Mazarguil 
29771fa900SAdrien Mazarguil #include <rte_atomic.h>
30ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
31c752998bSGaetan Rivet #include <rte_bus_pci.h>
32771fa900SAdrien Mazarguil #include <rte_mbuf.h>
33771fa900SAdrien Mazarguil #include <rte_common.h>
34198a3c33SNelio Laranjeiro #include <rte_interrupts.h>
35a48deadaSOr Ami #include <rte_malloc.h>
36c022cb40SBruce Richardson #include <rte_string_fns.h>
37974f1e7eSYongseok Koh #include <rte_rwlock.h>
38771fa900SAdrien Mazarguil 
39771fa900SAdrien Mazarguil #include "mlx5.h"
400e83b8e5SNelio Laranjeiro #include "mlx5_glue.h"
41e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h"
42771fa900SAdrien Mazarguil #include "mlx5_utils.h"
43771fa900SAdrien Mazarguil 
4479d09892SMoti Haimovsky /* Supported speed values found in /usr/include/linux/ethtool.h */
4579d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseKR4_Full
4679d09892SMoti Haimovsky #define SUPPORTED_40000baseKR4_Full (1 << 23)
4779d09892SMoti Haimovsky #endif
4879d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseCR4_Full
4979d09892SMoti Haimovsky #define SUPPORTED_40000baseCR4_Full (1 << 24)
5079d09892SMoti Haimovsky #endif
5179d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseSR4_Full
5279d09892SMoti Haimovsky #define SUPPORTED_40000baseSR4_Full (1 << 25)
5379d09892SMoti Haimovsky #endif
5479d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseLR4_Full
5579d09892SMoti Haimovsky #define SUPPORTED_40000baseLR4_Full (1 << 26)
5679d09892SMoti Haimovsky #endif
5779d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseKR4_Full
5879d09892SMoti Haimovsky #define SUPPORTED_56000baseKR4_Full (1 << 27)
5979d09892SMoti Haimovsky #endif
6079d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseCR4_Full
6179d09892SMoti Haimovsky #define SUPPORTED_56000baseCR4_Full (1 << 28)
6279d09892SMoti Haimovsky #endif
6379d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseSR4_Full
6479d09892SMoti Haimovsky #define SUPPORTED_56000baseSR4_Full (1 << 29)
6579d09892SMoti Haimovsky #endif
6679d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseLR4_Full
6779d09892SMoti Haimovsky #define SUPPORTED_56000baseLR4_Full (1 << 30)
6879d09892SMoti Haimovsky #endif
6979d09892SMoti Haimovsky 
703a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */
713a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS
723a49ffe3SShahaf Shuler struct ethtool_link_settings {
733a49ffe3SShahaf Shuler 	uint32_t cmd;
743a49ffe3SShahaf Shuler 	uint32_t speed;
753a49ffe3SShahaf Shuler 	uint8_t duplex;
763a49ffe3SShahaf Shuler 	uint8_t port;
773a49ffe3SShahaf Shuler 	uint8_t phy_address;
783a49ffe3SShahaf Shuler 	uint8_t autoneg;
793a49ffe3SShahaf Shuler 	uint8_t mdio_support;
803a49ffe3SShahaf Shuler 	uint8_t eth_to_mdix;
813a49ffe3SShahaf Shuler 	uint8_t eth_tp_mdix_ctrl;
823a49ffe3SShahaf Shuler 	int8_t link_mode_masks_nwords;
833a49ffe3SShahaf Shuler 	uint32_t reserved[8];
843a49ffe3SShahaf Shuler 	uint32_t link_mode_masks[];
853a49ffe3SShahaf Shuler };
863a49ffe3SShahaf Shuler 
873a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c
883a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5
893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6
903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17
913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18
923a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19
933a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20
943a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21
953a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22
963a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23
973a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24
983a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25
993a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26
1003a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27
1013a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28
1023a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29
1033a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30
1043a49ffe3SShahaf Shuler #endif
1053a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G
1063a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31
1073a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32
1083a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33
1093a49ffe3SShahaf Shuler #endif
1103a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G
1113a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34
1123a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35
1133a49ffe3SShahaf Shuler #endif
1143a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G
1153a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36
1163a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37
1173a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38
1183a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39
1193a49ffe3SShahaf Shuler #endif
1203a49ffe3SShahaf Shuler 
121771fa900SAdrien Mazarguil /**
1222b730263SAdrien Mazarguil  * Get master interface name from private structure.
123771fa900SAdrien Mazarguil  *
124af4f09f2SNélio Laranjeiro  * @param[in] dev
125af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
126771fa900SAdrien Mazarguil  * @param[out] ifname
127771fa900SAdrien Mazarguil  *   Interface name output buffer.
128771fa900SAdrien Mazarguil  *
129771fa900SAdrien Mazarguil  * @return
130a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
131771fa900SAdrien Mazarguil  */
132*7dd7be29SShahaf Shuler static int
1332b730263SAdrien Mazarguil mlx5_get_master_ifname(const struct rte_eth_dev *dev,
1342b730263SAdrien Mazarguil 		       char (*ifname)[IF_NAMESIZE])
135771fa900SAdrien Mazarguil {
136af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
137771fa900SAdrien Mazarguil 	DIR *dir;
138771fa900SAdrien Mazarguil 	struct dirent *dent;
139771fa900SAdrien Mazarguil 	unsigned int dev_type = 0;
140771fa900SAdrien Mazarguil 	unsigned int dev_port_prev = ~0u;
141771fa900SAdrien Mazarguil 	char match[IF_NAMESIZE] = "";
142771fa900SAdrien Mazarguil 
143771fa900SAdrien Mazarguil 	{
14487ec44ceSXueming Li 		MKSTR(path, "%s/device/net", priv->ibdev_path);
145771fa900SAdrien Mazarguil 
146771fa900SAdrien Mazarguil 		dir = opendir(path);
147a6d83b6aSNélio Laranjeiro 		if (dir == NULL) {
148a6d83b6aSNélio Laranjeiro 			rte_errno = errno;
149a6d83b6aSNélio Laranjeiro 			return -rte_errno;
150a6d83b6aSNélio Laranjeiro 		}
151771fa900SAdrien Mazarguil 	}
152771fa900SAdrien Mazarguil 	while ((dent = readdir(dir)) != NULL) {
153771fa900SAdrien Mazarguil 		char *name = dent->d_name;
154771fa900SAdrien Mazarguil 		FILE *file;
155771fa900SAdrien Mazarguil 		unsigned int dev_port;
156771fa900SAdrien Mazarguil 		int r;
157771fa900SAdrien Mazarguil 
158771fa900SAdrien Mazarguil 		if ((name[0] == '.') &&
159771fa900SAdrien Mazarguil 		    ((name[1] == '\0') ||
160771fa900SAdrien Mazarguil 		     ((name[1] == '.') && (name[2] == '\0'))))
161771fa900SAdrien Mazarguil 			continue;
162771fa900SAdrien Mazarguil 
163771fa900SAdrien Mazarguil 		MKSTR(path, "%s/device/net/%s/%s",
16487ec44ceSXueming Li 		      priv->ibdev_path, name,
165771fa900SAdrien Mazarguil 		      (dev_type ? "dev_id" : "dev_port"));
166771fa900SAdrien Mazarguil 
167771fa900SAdrien Mazarguil 		file = fopen(path, "rb");
168771fa900SAdrien Mazarguil 		if (file == NULL) {
169771fa900SAdrien Mazarguil 			if (errno != ENOENT)
170771fa900SAdrien Mazarguil 				continue;
171771fa900SAdrien Mazarguil 			/*
172771fa900SAdrien Mazarguil 			 * Switch to dev_id when dev_port does not exist as
173771fa900SAdrien Mazarguil 			 * is the case with Linux kernel versions < 3.15.
174771fa900SAdrien Mazarguil 			 */
175771fa900SAdrien Mazarguil try_dev_id:
176771fa900SAdrien Mazarguil 			match[0] = '\0';
177771fa900SAdrien Mazarguil 			if (dev_type)
178771fa900SAdrien Mazarguil 				break;
179771fa900SAdrien Mazarguil 			dev_type = 1;
180771fa900SAdrien Mazarguil 			dev_port_prev = ~0u;
181771fa900SAdrien Mazarguil 			rewinddir(dir);
182771fa900SAdrien Mazarguil 			continue;
183771fa900SAdrien Mazarguil 		}
184771fa900SAdrien Mazarguil 		r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
185771fa900SAdrien Mazarguil 		fclose(file);
186771fa900SAdrien Mazarguil 		if (r != 1)
187771fa900SAdrien Mazarguil 			continue;
188771fa900SAdrien Mazarguil 		/*
189771fa900SAdrien Mazarguil 		 * Switch to dev_id when dev_port returns the same value for
190771fa900SAdrien Mazarguil 		 * all ports. May happen when using a MOFED release older than
191771fa900SAdrien Mazarguil 		 * 3.0 with a Linux kernel >= 3.15.
192771fa900SAdrien Mazarguil 		 */
193771fa900SAdrien Mazarguil 		if (dev_port == dev_port_prev)
194771fa900SAdrien Mazarguil 			goto try_dev_id;
195771fa900SAdrien Mazarguil 		dev_port_prev = dev_port;
1969083982cSAdrien Mazarguil 		if (dev_port == 0)
197c022cb40SBruce Richardson 			strlcpy(match, name, sizeof(match));
198771fa900SAdrien Mazarguil 	}
199771fa900SAdrien Mazarguil 	closedir(dir);
200a6d83b6aSNélio Laranjeiro 	if (match[0] == '\0') {
201a6d83b6aSNélio Laranjeiro 		rte_errno = ENOENT;
202a6d83b6aSNélio Laranjeiro 		return -rte_errno;
203a6d83b6aSNélio Laranjeiro 	}
204771fa900SAdrien Mazarguil 	strncpy(*ifname, match, sizeof(*ifname));
205771fa900SAdrien Mazarguil 	return 0;
206771fa900SAdrien Mazarguil }
207771fa900SAdrien Mazarguil 
208771fa900SAdrien Mazarguil /**
2092b730263SAdrien Mazarguil  * Get interface name from private structure.
2102b730263SAdrien Mazarguil  *
2112b730263SAdrien Mazarguil  * This is a port representor-aware version of mlx5_get_master_ifname().
2122b730263SAdrien Mazarguil  *
2132b730263SAdrien Mazarguil  * @param[in] dev
2142b730263SAdrien Mazarguil  *   Pointer to Ethernet device.
2152b730263SAdrien Mazarguil  * @param[out] ifname
2162b730263SAdrien Mazarguil  *   Interface name output buffer.
2172b730263SAdrien Mazarguil  *
2182b730263SAdrien Mazarguil  * @return
2192b730263SAdrien Mazarguil  *   0 on success, a negative errno value otherwise and rte_errno is set.
2202b730263SAdrien Mazarguil  */
2212b730263SAdrien Mazarguil int
2222b730263SAdrien Mazarguil mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
2232b730263SAdrien Mazarguil {
2242b730263SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
2252b730263SAdrien Mazarguil 	unsigned int ifindex =
2262b730263SAdrien Mazarguil 		priv->nl_socket_rdma >= 0 ?
2272b730263SAdrien Mazarguil 		mlx5_nl_ifindex(priv->nl_socket_rdma, priv->ibdev_name) : 0;
2282b730263SAdrien Mazarguil 
2292b730263SAdrien Mazarguil 	if (!ifindex) {
2302b730263SAdrien Mazarguil 		if (!priv->representor)
2312b730263SAdrien Mazarguil 			return mlx5_get_master_ifname(dev, ifname);
2322b730263SAdrien Mazarguil 		rte_errno = ENXIO;
2332b730263SAdrien Mazarguil 		return -rte_errno;
2342b730263SAdrien Mazarguil 	}
2352b730263SAdrien Mazarguil 	if (if_indextoname(ifindex, &(*ifname)[0]))
2362b730263SAdrien Mazarguil 		return 0;
2372b730263SAdrien Mazarguil 	rte_errno = errno;
2382b730263SAdrien Mazarguil 	return -rte_errno;
2392b730263SAdrien Mazarguil }
2402b730263SAdrien Mazarguil 
2412b730263SAdrien Mazarguil /**
242ccdcba53SNélio Laranjeiro  * Get the interface index from device name.
243ccdcba53SNélio Laranjeiro  *
244ccdcba53SNélio Laranjeiro  * @param[in] dev
245ccdcba53SNélio Laranjeiro  *   Pointer to Ethernet device.
246ccdcba53SNélio Laranjeiro  *
247ccdcba53SNélio Laranjeiro  * @return
2483f8cb05dSAdrien Mazarguil  *   Nonzero interface index on success, zero otherwise and rte_errno is set.
249ccdcba53SNélio Laranjeiro  */
2503f8cb05dSAdrien Mazarguil unsigned int
251ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev)
252ccdcba53SNélio Laranjeiro {
253ccdcba53SNélio Laranjeiro 	char ifname[IF_NAMESIZE];
2543f8cb05dSAdrien Mazarguil 	unsigned int ifindex;
255ccdcba53SNélio Laranjeiro 
2563f8cb05dSAdrien Mazarguil 	if (mlx5_get_ifname(dev, &ifname))
2573f8cb05dSAdrien Mazarguil 		return 0;
2583f8cb05dSAdrien Mazarguil 	ifindex = if_nametoindex(ifname);
2593f8cb05dSAdrien Mazarguil 	if (!ifindex)
260ccdcba53SNélio Laranjeiro 		rte_errno = errno;
2613f8cb05dSAdrien Mazarguil 	return ifindex;
262ccdcba53SNélio Laranjeiro }
263ccdcba53SNélio Laranjeiro 
264ccdcba53SNélio Laranjeiro /**
265771fa900SAdrien Mazarguil  * Perform ifreq ioctl() on associated Ethernet device.
266771fa900SAdrien Mazarguil  *
267af4f09f2SNélio Laranjeiro  * @param[in] dev
268af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
269771fa900SAdrien Mazarguil  * @param req
270771fa900SAdrien Mazarguil  *   Request number to pass to ioctl().
271771fa900SAdrien Mazarguil  * @param[out] ifr
272771fa900SAdrien Mazarguil  *   Interface request structure output buffer.
273771fa900SAdrien Mazarguil  *
274771fa900SAdrien Mazarguil  * @return
275a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
276771fa900SAdrien Mazarguil  */
277771fa900SAdrien Mazarguil int
278*7dd7be29SShahaf Shuler mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
279771fa900SAdrien Mazarguil {
280771fa900SAdrien Mazarguil 	int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
281a6d83b6aSNélio Laranjeiro 	int ret = 0;
282771fa900SAdrien Mazarguil 
283a6d83b6aSNélio Laranjeiro 	if (sock == -1) {
284a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
285a6d83b6aSNélio Laranjeiro 		return -rte_errno;
286a6d83b6aSNélio Laranjeiro 	}
287a6d83b6aSNélio Laranjeiro 	ret = mlx5_get_ifname(dev, &ifr->ifr_name);
288a6d83b6aSNélio Laranjeiro 	if (ret)
289a6d83b6aSNélio Laranjeiro 		goto error;
290771fa900SAdrien Mazarguil 	ret = ioctl(sock, req, ifr);
291a6d83b6aSNélio Laranjeiro 	if (ret == -1) {
292a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
293a6d83b6aSNélio Laranjeiro 		goto error;
294a6d83b6aSNélio Laranjeiro 	}
295771fa900SAdrien Mazarguil 	close(sock);
296a6d83b6aSNélio Laranjeiro 	return 0;
297a6d83b6aSNélio Laranjeiro error:
298a6d83b6aSNélio Laranjeiro 	close(sock);
299a6d83b6aSNélio Laranjeiro 	return -rte_errno;
300771fa900SAdrien Mazarguil }
301771fa900SAdrien Mazarguil 
302771fa900SAdrien Mazarguil /**
303771fa900SAdrien Mazarguil  * Get device MTU.
304771fa900SAdrien Mazarguil  *
305af4f09f2SNélio Laranjeiro  * @param dev
306af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
307771fa900SAdrien Mazarguil  * @param[out] mtu
308771fa900SAdrien Mazarguil  *   MTU value output buffer.
309771fa900SAdrien Mazarguil  *
310771fa900SAdrien Mazarguil  * @return
311a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
312771fa900SAdrien Mazarguil  */
313771fa900SAdrien Mazarguil int
314af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
315771fa900SAdrien Mazarguil {
316fc40db99SAdrien Mazarguil 	struct ifreq request;
317*7dd7be29SShahaf Shuler 	int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
318771fa900SAdrien Mazarguil 
319fc40db99SAdrien Mazarguil 	if (ret)
320fc40db99SAdrien Mazarguil 		return ret;
321fc40db99SAdrien Mazarguil 	*mtu = request.ifr_mtu;
322859081d3SShahaf Shuler 	return 0;
323859081d3SShahaf Shuler }
324859081d3SShahaf Shuler 
325859081d3SShahaf Shuler /**
326cf37ca95SAdrien Mazarguil  * Set device MTU.
327cf37ca95SAdrien Mazarguil  *
328af4f09f2SNélio Laranjeiro  * @param dev
329af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
330cf37ca95SAdrien Mazarguil  * @param mtu
331cf37ca95SAdrien Mazarguil  *   MTU value to set.
332cf37ca95SAdrien Mazarguil  *
333cf37ca95SAdrien Mazarguil  * @return
334a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
335cf37ca95SAdrien Mazarguil  */
336cf37ca95SAdrien Mazarguil static int
337af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
338cf37ca95SAdrien Mazarguil {
339fc40db99SAdrien Mazarguil 	struct ifreq request = { .ifr_mtu = mtu, };
340f3b492d7SAdrien Mazarguil 
341*7dd7be29SShahaf Shuler 	return mlx5_ifreq(dev, SIOCSIFMTU, &request);
342cf37ca95SAdrien Mazarguil }
343cf37ca95SAdrien Mazarguil 
344cf37ca95SAdrien Mazarguil /**
345771fa900SAdrien Mazarguil  * Set device flags.
346771fa900SAdrien Mazarguil  *
347af4f09f2SNélio Laranjeiro  * @param dev
348af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
349771fa900SAdrien Mazarguil  * @param keep
350771fa900SAdrien Mazarguil  *   Bitmask for flags that must remain untouched.
351771fa900SAdrien Mazarguil  * @param flags
352771fa900SAdrien Mazarguil  *   Bitmask for flags to modify.
353771fa900SAdrien Mazarguil  *
354771fa900SAdrien Mazarguil  * @return
355a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
356771fa900SAdrien Mazarguil  */
357771fa900SAdrien Mazarguil int
358af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
359771fa900SAdrien Mazarguil {
360fc40db99SAdrien Mazarguil 	struct ifreq request;
361*7dd7be29SShahaf Shuler 	int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
362771fa900SAdrien Mazarguil 
363fc40db99SAdrien Mazarguil 	if (ret)
364fc40db99SAdrien Mazarguil 		return ret;
365fc40db99SAdrien Mazarguil 	request.ifr_flags &= keep;
366fc40db99SAdrien Mazarguil 	request.ifr_flags |= flags & ~keep;
367*7dd7be29SShahaf Shuler 	return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
368771fa900SAdrien Mazarguil }
369771fa900SAdrien Mazarguil 
370771fa900SAdrien Mazarguil /**
3717b2423cdSNélio Laranjeiro  * DPDK callback for Ethernet device configuration.
372e60fbd5bSAdrien Mazarguil  *
373e60fbd5bSAdrien Mazarguil  * @param dev
374e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
375e60fbd5bSAdrien Mazarguil  *
376e60fbd5bSAdrien Mazarguil  * @return
377a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
378e60fbd5bSAdrien Mazarguil  */
3797b2423cdSNélio Laranjeiro int
3807b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev)
381e60fbd5bSAdrien Mazarguil {
382e60fbd5bSAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
383e60fbd5bSAdrien Mazarguil 	unsigned int rxqs_n = dev->data->nb_rx_queues;
384e60fbd5bSAdrien Mazarguil 	unsigned int txqs_n = dev->data->nb_tx_queues;
385634efbc2SNelio Laranjeiro 	unsigned int i;
386634efbc2SNelio Laranjeiro 	unsigned int j;
387634efbc2SNelio Laranjeiro 	unsigned int reta_idx_n;
38829c1d8bbSNélio Laranjeiro 	const uint8_t use_app_rss_key =
38921e3a974SShahaf Shuler 		!!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
390a6d83b6aSNélio Laranjeiro 	int ret = 0;
391e60fbd5bSAdrien Mazarguil 
39229c1d8bbSNélio Laranjeiro 	if (use_app_rss_key &&
39329c1d8bbSNélio Laranjeiro 	    (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
394c388a2f6SNelio Laranjeiro 	     MLX5_RSS_HASH_KEY_LEN)) {
395c388a2f6SNelio Laranjeiro 		DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long",
396c388a2f6SNelio Laranjeiro 			dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN));
397a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
398a6d83b6aSNélio Laranjeiro 		return -rte_errno;
39929c1d8bbSNélio Laranjeiro 	}
40029c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key =
40129c1d8bbSNélio Laranjeiro 		rte_realloc(priv->rss_conf.rss_key,
402c388a2f6SNelio Laranjeiro 			    MLX5_RSS_HASH_KEY_LEN, 0);
40329c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
404a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
4050f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
406a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
407a6d83b6aSNélio Laranjeiro 		return -rte_errno;
40829c1d8bbSNélio Laranjeiro 	}
40929c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
41029c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
41129c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
41229c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
413c388a2f6SNelio Laranjeiro 	       MLX5_RSS_HASH_KEY_LEN);
414c388a2f6SNelio Laranjeiro 	priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN;
41529c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
416e60fbd5bSAdrien Mazarguil 	priv->rxqs = (void *)dev->data->rx_queues;
417e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
418e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
419a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
4200f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
421e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
422e60fbd5bSAdrien Mazarguil 	}
4237fe24446SShahaf Shuler 	if (rxqs_n > priv->config.ind_table_max_size) {
424a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
4250f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
426a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
427a6d83b6aSNélio Laranjeiro 		return -rte_errno;
428634efbc2SNelio Laranjeiro 	}
429e60fbd5bSAdrien Mazarguil 	if (rxqs_n == priv->rxqs_n)
430e60fbd5bSAdrien Mazarguil 		return 0;
431a170a30dSNélio Laranjeiro 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
4320f99970bSNélio Laranjeiro 		dev->data->port_id, priv->rxqs_n, rxqs_n);
433e60fbd5bSAdrien Mazarguil 	priv->rxqs_n = rxqs_n;
434634efbc2SNelio Laranjeiro 	/* If the requested number of RX queues is not a power of two, use the
435634efbc2SNelio Laranjeiro 	 * maximum indirection table size for better balancing.
436634efbc2SNelio Laranjeiro 	 * The result is always rounded to the next power of two. */
437634efbc2SNelio Laranjeiro 	reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ?
4387fe24446SShahaf Shuler 				     priv->config.ind_table_max_size :
439634efbc2SNelio Laranjeiro 				     rxqs_n));
440a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
441a6d83b6aSNélio Laranjeiro 	if (ret)
442a6d83b6aSNélio Laranjeiro 		return ret;
443634efbc2SNelio Laranjeiro 	/* When the number of RX queues is not a power of two, the remaining
444634efbc2SNelio Laranjeiro 	 * table entries are padded with reused WQs and hashes are not spread
445634efbc2SNelio Laranjeiro 	 * uniformly. */
446634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
447634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = j;
448634efbc2SNelio Laranjeiro 		if (++j == rxqs_n)
449634efbc2SNelio Laranjeiro 			j = 0;
450634efbc2SNelio Laranjeiro 	}
451e60fbd5bSAdrien Mazarguil 	return 0;
452e60fbd5bSAdrien Mazarguil }
453e60fbd5bSAdrien Mazarguil 
454e60fbd5bSAdrien Mazarguil /**
455d11d651fSShahaf Shuler  * Sets default tuning parameters.
456d11d651fSShahaf Shuler  *
457d11d651fSShahaf Shuler  * @param dev
458d11d651fSShahaf Shuler  *   Pointer to Ethernet device.
459d11d651fSShahaf Shuler  * @param[out] info
460d11d651fSShahaf Shuler  *   Info structure output buffer.
461d11d651fSShahaf Shuler  */
462d11d651fSShahaf Shuler static void
463d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
464d11d651fSShahaf Shuler {
465d11d651fSShahaf Shuler 	struct priv *priv = dev->data->dev_private;
466d11d651fSShahaf Shuler 
467d11d651fSShahaf Shuler 	/* Minimum CPU utilization. */
468d11d651fSShahaf Shuler 	info->default_rxportconf.ring_size = 256;
469d11d651fSShahaf Shuler 	info->default_txportconf.ring_size = 256;
470d11d651fSShahaf Shuler 	info->default_rxportconf.burst_size = 64;
471d11d651fSShahaf Shuler 	info->default_txportconf.burst_size = 64;
472d11d651fSShahaf Shuler 	if (priv->link_speed_capa & ETH_LINK_SPEED_100G) {
473d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 16;
474d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 16;
475d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
476d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
477d11d651fSShahaf Shuler 			/* Max Throughput. */
478d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 2048;
479d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 2048;
480d11d651fSShahaf Shuler 		}
481d11d651fSShahaf Shuler 	} else {
482d11d651fSShahaf Shuler 		info->default_rxportconf.nb_queues = 8;
483d11d651fSShahaf Shuler 		info->default_txportconf.nb_queues = 8;
484d11d651fSShahaf Shuler 		if (dev->data->nb_rx_queues > 2 ||
485d11d651fSShahaf Shuler 		    dev->data->nb_tx_queues > 2) {
486d11d651fSShahaf Shuler 			/* Max Throughput. */
487d11d651fSShahaf Shuler 			info->default_rxportconf.ring_size = 4096;
488d11d651fSShahaf Shuler 			info->default_txportconf.ring_size = 4096;
489d11d651fSShahaf Shuler 		}
490d11d651fSShahaf Shuler 	}
491d11d651fSShahaf Shuler }
492d11d651fSShahaf Shuler 
493d11d651fSShahaf Shuler /**
494e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
495e60fbd5bSAdrien Mazarguil  *
496e60fbd5bSAdrien Mazarguil  * @param dev
497e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
498e60fbd5bSAdrien Mazarguil  * @param[out] info
499e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
500e60fbd5bSAdrien Mazarguil  */
501e60fbd5bSAdrien Mazarguil void
502e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
503e60fbd5bSAdrien Mazarguil {
50401d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
5057fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
506e60fbd5bSAdrien Mazarguil 	unsigned int max;
507e60fbd5bSAdrien Mazarguil 	char ifname[IF_NAMESIZE];
508e60fbd5bSAdrien Mazarguil 
509e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
510e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
511e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
512e60fbd5bSAdrien Mazarguil 	/*
513e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
514e60fbd5bSAdrien Mazarguil 	 * between the two values.
515e60fbd5bSAdrien Mazarguil 	 */
51643e9d979SShachar Beiser 	max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
51743e9d979SShachar Beiser 		      priv->device_attr.orig_attr.max_qp);
518e60fbd5bSAdrien Mazarguil 	/* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
519e60fbd5bSAdrien Mazarguil 	if (max >= 65535)
520e60fbd5bSAdrien Mazarguil 		max = 65535;
521e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
522e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
52318c01b98SNélio Laranjeiro 	info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES;
524af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
525af4f09f2SNélio Laranjeiro 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
52617b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
527af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
528af4f09f2SNélio Laranjeiro 	if (mlx5_get_ifname(dev, &ifname) == 0)
529e60fbd5bSAdrien Mazarguil 		info->if_index = if_nametoindex(ifname);
530d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
5317fe24446SShahaf Shuler 		priv->reta_idx_n : config->ind_table_max_size;
532c388a2f6SNelio Laranjeiro 	info->hash_key_size = MLX5_RSS_HASH_KEY_LEN;
53375ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
534b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
535d11d651fSShahaf Shuler 	mlx5_set_default_params(dev, info);
5362b730263SAdrien Mazarguil 	info->switch_info.name = dev->data->name;
5372b730263SAdrien Mazarguil 	info->switch_info.domain_id = priv->domain_id;
5382b730263SAdrien Mazarguil 	info->switch_info.port_id = priv->representor_id;
5392b730263SAdrien Mazarguil 	if (priv->representor) {
5402b730263SAdrien Mazarguil 		unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);
5412b730263SAdrien Mazarguil 		uint16_t port_id[i];
5422b730263SAdrien Mazarguil 
5432b730263SAdrien Mazarguil 		i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
5442b730263SAdrien Mazarguil 		while (i--) {
5452b730263SAdrien Mazarguil 			struct priv *opriv =
5462b730263SAdrien Mazarguil 				rte_eth_devices[port_id[i]].data->dev_private;
5472b730263SAdrien Mazarguil 
5482b730263SAdrien Mazarguil 			if (!opriv ||
5492b730263SAdrien Mazarguil 			    opriv->representor ||
5502b730263SAdrien Mazarguil 			    opriv->domain_id != priv->domain_id)
5512b730263SAdrien Mazarguil 				continue;
5522b730263SAdrien Mazarguil 			/*
5532b730263SAdrien Mazarguil 			 * Override switch name with that of the master
5542b730263SAdrien Mazarguil 			 * device.
5552b730263SAdrien Mazarguil 			 */
5562b730263SAdrien Mazarguil 			info->switch_info.name = opriv->dev_data->name;
5572b730263SAdrien Mazarguil 			break;
5582b730263SAdrien Mazarguil 		}
5592b730263SAdrien Mazarguil 	}
560e60fbd5bSAdrien Mazarguil }
561e60fbd5bSAdrien Mazarguil 
562fb732b0aSNélio Laranjeiro /**
563fb732b0aSNélio Laranjeiro  * Get supported packet types.
564fb732b0aSNélio Laranjeiro  *
565fb732b0aSNélio Laranjeiro  * @param dev
566fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
567fb732b0aSNélio Laranjeiro  *
568fb732b0aSNélio Laranjeiro  * @return
569fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
570fb732b0aSNélio Laranjeiro  */
57178a38edfSJianfeng Tan const uint32_t *
57278a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
57378a38edfSJianfeng Tan {
57478a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
57578a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
576ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
577c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
578c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
579ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
580ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
581ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
582ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
583c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
584c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
585ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
586ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
587ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
588ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
58978a38edfSJianfeng Tan 		RTE_PTYPE_UNKNOWN
59078a38edfSJianfeng Tan 	};
59178a38edfSJianfeng Tan 
5926cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
5937d6bf6b8SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_mprq ||
5946cb559d6SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_vec)
59578a38edfSJianfeng Tan 		return ptypes;
59678a38edfSJianfeng Tan 	return NULL;
59778a38edfSJianfeng Tan }
59878a38edfSJianfeng Tan 
599e60fbd5bSAdrien Mazarguil /**
6002c960a51SMatthieu Ternisien d'Ouville  * DPDK callback to retrieve physical link information.
601cb8faed7SAdrien Mazarguil  *
602cb8faed7SAdrien Mazarguil  * @param dev
603cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
604cfee9475SNélio Laranjeiro  * @param[out] link
605cfee9475SNélio Laranjeiro  *   Storage for current link status.
606fb732b0aSNélio Laranjeiro  *
607fb732b0aSNélio Laranjeiro  * @return
608a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
609cb8faed7SAdrien Mazarguil  */
61018840871SNélio Laranjeiro static int
611cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
612cfee9475SNélio Laranjeiro 			       struct rte_eth_link *link)
613cb8faed7SAdrien Mazarguil {
61401d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
615cb8faed7SAdrien Mazarguil 	struct ethtool_cmd edata = {
61675ef62a9SNélio Laranjeiro 		.cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
617cb8faed7SAdrien Mazarguil 	};
618cb8faed7SAdrien Mazarguil 	struct ifreq ifr;
619cb8faed7SAdrien Mazarguil 	struct rte_eth_link dev_link;
620cb8faed7SAdrien Mazarguil 	int link_speed = 0;
621a6d83b6aSNélio Laranjeiro 	int ret;
622cb8faed7SAdrien Mazarguil 
623*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
624a6d83b6aSNélio Laranjeiro 	if (ret) {
625a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
6260f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
627a6d83b6aSNélio Laranjeiro 		return ret;
628cb8faed7SAdrien Mazarguil 	}
6297bc47fb8SXueming Li 	dev_link = (struct rte_eth_link) {
6307bc47fb8SXueming Li 		.link_status = ((ifr.ifr_flags & IFF_UP) &&
6317bc47fb8SXueming Li 				(ifr.ifr_flags & IFF_RUNNING)),
6327bc47fb8SXueming Li 	};
6337bc47fb8SXueming Li 	ifr = (struct ifreq) {
6347bc47fb8SXueming Li 		.ifr_data = (void *)&edata,
6357bc47fb8SXueming Li 	};
636*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
637a6d83b6aSNélio Laranjeiro 	if (ret) {
638a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
639a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
6400f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
641a6d83b6aSNélio Laranjeiro 		return ret;
642cb8faed7SAdrien Mazarguil 	}
643cb8faed7SAdrien Mazarguil 	link_speed = ethtool_cmd_speed(&edata);
644cb8faed7SAdrien Mazarguil 	if (link_speed == -1)
6453fef0822SFerruh Yigit 		dev_link.link_speed = ETH_SPEED_NUM_NONE;
646cb8faed7SAdrien Mazarguil 	else
647cb8faed7SAdrien Mazarguil 		dev_link.link_speed = link_speed;
64875ef62a9SNélio Laranjeiro 	priv->link_speed_capa = 0;
64975ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_Autoneg)
65075ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
65175ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_1000baseT_Full |
65275ef62a9SNélio Laranjeiro 			       SUPPORTED_1000baseKX_Full))
65375ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
65475ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_10000baseKR_Full)
65575ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
65675ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_40000baseKR4_Full |
65775ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseCR4_Full |
65875ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseSR4_Full |
65975ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseLR4_Full))
66075ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
661cb8faed7SAdrien Mazarguil 	dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
662cb8faed7SAdrien Mazarguil 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
66382113036SMarc Sune 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
66482113036SMarc Sune 			ETH_LINK_SPEED_FIXED);
665*7dd7be29SShahaf Shuler 	if (((dev_link.link_speed && !dev_link.link_status) ||
6667bc47fb8SXueming Li 	     (!dev_link.link_speed && dev_link.link_status))) {
667a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
668a6d83b6aSNélio Laranjeiro 		return -rte_errno;
669cb8faed7SAdrien Mazarguil 	}
670cfee9475SNélio Laranjeiro 	*link = dev_link;
671cfee9475SNélio Laranjeiro 	return 0;
672cfee9475SNélio Laranjeiro }
673cb8faed7SAdrien Mazarguil 
674cb8faed7SAdrien Mazarguil /**
6753a49ffe3SShahaf Shuler  * Retrieve physical link information (unlocked version using new ioctl).
67618840871SNélio Laranjeiro  *
67718840871SNélio Laranjeiro  * @param dev
67818840871SNélio Laranjeiro  *   Pointer to Ethernet device structure.
679cfee9475SNélio Laranjeiro  * @param[out] link
680cfee9475SNélio Laranjeiro  *   Storage for current link status.
681fb732b0aSNélio Laranjeiro  *
682fb732b0aSNélio Laranjeiro  * @return
683a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
68418840871SNélio Laranjeiro  */
68518840871SNélio Laranjeiro static int
686cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
687cfee9475SNélio Laranjeiro 			     struct rte_eth_link *link)
688cfee9475SNélio Laranjeiro 
68918840871SNélio Laranjeiro {
69001d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
69137a4406cSNélio Laranjeiro 	struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
69218840871SNélio Laranjeiro 	struct ifreq ifr;
69318840871SNélio Laranjeiro 	struct rte_eth_link dev_link;
69418840871SNélio Laranjeiro 	uint64_t sc;
695a6d83b6aSNélio Laranjeiro 	int ret;
69618840871SNélio Laranjeiro 
697*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
698a6d83b6aSNélio Laranjeiro 	if (ret) {
699a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
7000f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
701a6d83b6aSNélio Laranjeiro 		return ret;
70218840871SNélio Laranjeiro 	}
7037bc47fb8SXueming Li 	dev_link = (struct rte_eth_link) {
7047bc47fb8SXueming Li 		.link_status = ((ifr.ifr_flags & IFF_UP) &&
7057bc47fb8SXueming Li 				(ifr.ifr_flags & IFF_RUNNING)),
7067bc47fb8SXueming Li 	};
7077bc47fb8SXueming Li 	ifr = (struct ifreq) {
7087bc47fb8SXueming Li 		.ifr_data = (void *)&gcmd,
7097bc47fb8SXueming Li 	};
710*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
711a6d83b6aSNélio Laranjeiro 	if (ret) {
712a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
713a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
714a170a30dSNélio Laranjeiro 			" failed: %s",
715a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
716a6d83b6aSNélio Laranjeiro 		return ret;
71718840871SNélio Laranjeiro 	}
71837a4406cSNélio Laranjeiro 	gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
71937a4406cSNélio Laranjeiro 
72037a4406cSNélio Laranjeiro 	alignas(struct ethtool_link_settings)
72137a4406cSNélio Laranjeiro 	uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
72237a4406cSNélio Laranjeiro 		     sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
72337a4406cSNélio Laranjeiro 	struct ethtool_link_settings *ecmd = (void *)data;
72437a4406cSNélio Laranjeiro 
72537a4406cSNélio Laranjeiro 	*ecmd = gcmd;
72637a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)ecmd;
727*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
728a6d83b6aSNélio Laranjeiro 	if (ret) {
729a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
730a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
731a170a30dSNélio Laranjeiro 			" failed: %s",
732a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
733a6d83b6aSNélio Laranjeiro 		return ret;
734ef09a7fcSGowrishankar Muthukrishnan 	}
73590260d57SNélio Laranjeiro 	dev_link.link_speed = ecmd->speed;
73690260d57SNélio Laranjeiro 	sc = ecmd->link_mode_masks[0] |
73790260d57SNélio Laranjeiro 		((uint64_t)ecmd->link_mode_masks[1] << 32);
73818840871SNélio Laranjeiro 	priv->link_speed_capa = 0;
739b113cb5eSEdward Makarov 	if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
74018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
741b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
742b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
74318840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
744b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
745b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
746b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
74718840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
748b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
749b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
75018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_20G;
751b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
752b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
753b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
754b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
75518840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
756b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
757b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
758b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
759b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
76018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_56G;
761b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
762b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
763b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
76418840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_25G;
765b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
766b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
76718840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_50G;
768b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
769b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
770b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
771b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
77218840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_100G;
77390260d57SNélio Laranjeiro 	dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
77418840871SNélio Laranjeiro 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
77518840871SNélio Laranjeiro 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
77618840871SNélio Laranjeiro 				  ETH_LINK_SPEED_FIXED);
777*7dd7be29SShahaf Shuler 	if (((dev_link.link_speed && !dev_link.link_status) ||
7787bc47fb8SXueming Li 	     (!dev_link.link_speed && dev_link.link_status))) {
779a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
780a6d83b6aSNélio Laranjeiro 		return -rte_errno;
78118840871SNélio Laranjeiro 	}
782cfee9475SNélio Laranjeiro 	*link = dev_link;
783cfee9475SNélio Laranjeiro 	return 0;
784cfee9475SNélio Laranjeiro }
78518840871SNélio Laranjeiro 
78618840871SNélio Laranjeiro /**
787cb8faed7SAdrien Mazarguil  * DPDK callback to retrieve physical link information.
788cb8faed7SAdrien Mazarguil  *
789cb8faed7SAdrien Mazarguil  * @param dev
790cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
791cb8faed7SAdrien Mazarguil  * @param wait_to_complete
792cfee9475SNélio Laranjeiro  *   Wait for request completion.
793fb732b0aSNélio Laranjeiro  *
794fb732b0aSNélio Laranjeiro  * @return
795cfee9475SNélio Laranjeiro  *   0 if link status was not updated, positive if it was, a negative errno
796cfee9475SNélio Laranjeiro  *   value otherwise and rte_errno is set.
797cb8faed7SAdrien Mazarguil  */
798cb8faed7SAdrien Mazarguil int
799cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
800cb8faed7SAdrien Mazarguil {
801c7bf6225SYongseok Koh 	int ret;
802cfee9475SNélio Laranjeiro 	struct rte_eth_link dev_link;
803cfee9475SNélio Laranjeiro 	time_t start_time = time(NULL);
804cb8faed7SAdrien Mazarguil 
805cfee9475SNélio Laranjeiro 	do {
806cfee9475SNélio Laranjeiro 		ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
8077d2e32f7SShahaf Shuler 		if (ret)
8087d2e32f7SShahaf Shuler 			ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
809cfee9475SNélio Laranjeiro 		if (ret == 0)
810cfee9475SNélio Laranjeiro 			break;
811cfee9475SNélio Laranjeiro 		/* Handle wait to complete situation. */
812cfee9475SNélio Laranjeiro 		if (wait_to_complete && ret == -EAGAIN) {
813cfee9475SNélio Laranjeiro 			if (abs((int)difftime(time(NULL), start_time)) <
814cfee9475SNélio Laranjeiro 			    MLX5_LINK_STATUS_TIMEOUT) {
815cfee9475SNélio Laranjeiro 				usleep(0);
816cfee9475SNélio Laranjeiro 				continue;
817cfee9475SNélio Laranjeiro 			} else {
818cfee9475SNélio Laranjeiro 				rte_errno = EBUSY;
819cfee9475SNélio Laranjeiro 				return -rte_errno;
820cfee9475SNélio Laranjeiro 			}
821cfee9475SNélio Laranjeiro 		} else if (ret < 0) {
822cfee9475SNélio Laranjeiro 			return ret;
823cfee9475SNélio Laranjeiro 		}
824cfee9475SNélio Laranjeiro 	} while (wait_to_complete);
825cfee9475SNélio Laranjeiro 	ret = !!memcmp(&dev->data->dev_link, &dev_link,
826cfee9475SNélio Laranjeiro 		       sizeof(struct rte_eth_link));
827cfee9475SNélio Laranjeiro 	dev->data->dev_link = dev_link;
828cfee9475SNélio Laranjeiro 	return ret;
829cb8faed7SAdrien Mazarguil }
830cb8faed7SAdrien Mazarguil 
831cb8faed7SAdrien Mazarguil /**
832cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
833cf37ca95SAdrien Mazarguil  *
834cf37ca95SAdrien Mazarguil  * @param dev
835cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
836cf37ca95SAdrien Mazarguil  * @param in_mtu
837cf37ca95SAdrien Mazarguil  *   New MTU.
838cf37ca95SAdrien Mazarguil  *
839cf37ca95SAdrien Mazarguil  * @return
840a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
841cf37ca95SAdrien Mazarguil  */
842cf37ca95SAdrien Mazarguil int
843cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
844cf37ca95SAdrien Mazarguil {
845cf37ca95SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
846a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
847a6d83b6aSNélio Laranjeiro 	int ret;
848cf37ca95SAdrien Mazarguil 
849af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
850a0edafe4SNelio Laranjeiro 	if (ret)
851a6d83b6aSNélio Laranjeiro 		return ret;
852cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
853af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
854a0edafe4SNelio Laranjeiro 	if (ret)
855a6d83b6aSNélio Laranjeiro 		return ret;
856af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
857a0edafe4SNelio Laranjeiro 	if (ret)
858a6d83b6aSNélio Laranjeiro 		return ret;
859a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
860a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
861a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
862a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
863a0edafe4SNelio Laranjeiro 		return 0;
864a6d83b6aSNélio Laranjeiro 	}
865a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
866a6d83b6aSNélio Laranjeiro 	return -rte_errno;
867cf37ca95SAdrien Mazarguil }
868cf37ca95SAdrien Mazarguil 
869cf37ca95SAdrien Mazarguil /**
87002d75430SAdrien Mazarguil  * DPDK callback to get flow control status.
87102d75430SAdrien Mazarguil  *
87202d75430SAdrien Mazarguil  * @param dev
87302d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
87402d75430SAdrien Mazarguil  * @param[out] fc_conf
87502d75430SAdrien Mazarguil  *   Flow control output buffer.
87602d75430SAdrien Mazarguil  *
87702d75430SAdrien Mazarguil  * @return
878a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
87902d75430SAdrien Mazarguil  */
88002d75430SAdrien Mazarguil int
88102d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
88202d75430SAdrien Mazarguil {
88302d75430SAdrien Mazarguil 	struct ifreq ifr;
88402d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
88502d75430SAdrien Mazarguil 		.cmd = ETHTOOL_GPAUSEPARAM
88602d75430SAdrien Mazarguil 	};
88702d75430SAdrien Mazarguil 	int ret;
88802d75430SAdrien Mazarguil 
889d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
890*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
891a6d83b6aSNélio Laranjeiro 	if (ret) {
892a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
893a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
894a170a30dSNélio Laranjeiro 			" %s",
895a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
896a6d83b6aSNélio Laranjeiro 		return ret;
89702d75430SAdrien Mazarguil 	}
89802d75430SAdrien Mazarguil 	fc_conf->autoneg = ethpause.autoneg;
89902d75430SAdrien Mazarguil 	if (ethpause.rx_pause && ethpause.tx_pause)
90002d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_FULL;
90102d75430SAdrien Mazarguil 	else if (ethpause.rx_pause)
90202d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_RX_PAUSE;
90302d75430SAdrien Mazarguil 	else if (ethpause.tx_pause)
90402d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_TX_PAUSE;
90502d75430SAdrien Mazarguil 	else
90602d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_NONE;
907a6d83b6aSNélio Laranjeiro 	return 0;
90802d75430SAdrien Mazarguil }
90902d75430SAdrien Mazarguil 
91002d75430SAdrien Mazarguil /**
91102d75430SAdrien Mazarguil  * DPDK callback to modify flow control parameters.
91202d75430SAdrien Mazarguil  *
91302d75430SAdrien Mazarguil  * @param dev
91402d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
91502d75430SAdrien Mazarguil  * @param[in] fc_conf
91602d75430SAdrien Mazarguil  *   Flow control parameters.
91702d75430SAdrien Mazarguil  *
91802d75430SAdrien Mazarguil  * @return
919a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
92002d75430SAdrien Mazarguil  */
92102d75430SAdrien Mazarguil int
92202d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
92302d75430SAdrien Mazarguil {
92402d75430SAdrien Mazarguil 	struct ifreq ifr;
92502d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
92602d75430SAdrien Mazarguil 		.cmd = ETHTOOL_SPAUSEPARAM
92702d75430SAdrien Mazarguil 	};
92802d75430SAdrien Mazarguil 	int ret;
92902d75430SAdrien Mazarguil 
930d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
93102d75430SAdrien Mazarguil 	ethpause.autoneg = fc_conf->autoneg;
93202d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
93302d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_RX_PAUSE))
93402d75430SAdrien Mazarguil 		ethpause.rx_pause = 1;
93502d75430SAdrien Mazarguil 	else
93602d75430SAdrien Mazarguil 		ethpause.rx_pause = 0;
93702d75430SAdrien Mazarguil 
93802d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
93902d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_TX_PAUSE))
94002d75430SAdrien Mazarguil 		ethpause.tx_pause = 1;
94102d75430SAdrien Mazarguil 	else
94202d75430SAdrien Mazarguil 		ethpause.tx_pause = 0;
943*7dd7be29SShahaf Shuler 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
944a6d83b6aSNélio Laranjeiro 	if (ret) {
945a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
946a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
947a170a30dSNélio Laranjeiro 			" failed: %s",
948a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
949a6d83b6aSNélio Laranjeiro 		return ret;
95002d75430SAdrien Mazarguil 	}
951a6d83b6aSNélio Laranjeiro 	return 0;
95202d75430SAdrien Mazarguil }
95302d75430SAdrien Mazarguil 
95402d75430SAdrien Mazarguil /**
955771fa900SAdrien Mazarguil  * Get PCI information from struct ibv_device.
956771fa900SAdrien Mazarguil  *
957771fa900SAdrien Mazarguil  * @param device
958771fa900SAdrien Mazarguil  *   Pointer to Ethernet device structure.
959771fa900SAdrien Mazarguil  * @param[out] pci_addr
960771fa900SAdrien Mazarguil  *   PCI bus address output buffer.
961771fa900SAdrien Mazarguil  *
962771fa900SAdrien Mazarguil  * @return
963a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
964771fa900SAdrien Mazarguil  */
965771fa900SAdrien Mazarguil int
966771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
967771fa900SAdrien Mazarguil 			    struct rte_pci_addr *pci_addr)
968771fa900SAdrien Mazarguil {
969771fa900SAdrien Mazarguil 	FILE *file;
970771fa900SAdrien Mazarguil 	char line[32];
971771fa900SAdrien Mazarguil 	MKSTR(path, "%s/device/uevent", device->ibdev_path);
972771fa900SAdrien Mazarguil 
973771fa900SAdrien Mazarguil 	file = fopen(path, "rb");
974a6d83b6aSNélio Laranjeiro 	if (file == NULL) {
975a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
976a6d83b6aSNélio Laranjeiro 		return -rte_errno;
977a6d83b6aSNélio Laranjeiro 	}
978771fa900SAdrien Mazarguil 	while (fgets(line, sizeof(line), file) == line) {
979771fa900SAdrien Mazarguil 		size_t len = strlen(line);
980771fa900SAdrien Mazarguil 		int ret;
981771fa900SAdrien Mazarguil 
982771fa900SAdrien Mazarguil 		/* Truncate long lines. */
983771fa900SAdrien Mazarguil 		if (len == (sizeof(line) - 1))
984771fa900SAdrien Mazarguil 			while (line[(len - 1)] != '\n') {
985771fa900SAdrien Mazarguil 				ret = fgetc(file);
986771fa900SAdrien Mazarguil 				if (ret == EOF)
987771fa900SAdrien Mazarguil 					break;
988771fa900SAdrien Mazarguil 				line[(len - 1)] = ret;
989771fa900SAdrien Mazarguil 			}
990771fa900SAdrien Mazarguil 		/* Extract information. */
991771fa900SAdrien Mazarguil 		if (sscanf(line,
992771fa900SAdrien Mazarguil 			   "PCI_SLOT_NAME="
993463ced95SStephen Hemminger 			   "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
994771fa900SAdrien Mazarguil 			   &pci_addr->domain,
995771fa900SAdrien Mazarguil 			   &pci_addr->bus,
996771fa900SAdrien Mazarguil 			   &pci_addr->devid,
997771fa900SAdrien Mazarguil 			   &pci_addr->function) == 4) {
998771fa900SAdrien Mazarguil 			ret = 0;
999771fa900SAdrien Mazarguil 			break;
1000771fa900SAdrien Mazarguil 		}
1001771fa900SAdrien Mazarguil 	}
1002771fa900SAdrien Mazarguil 	fclose(file);
1003771fa900SAdrien Mazarguil 	return 0;
1004771fa900SAdrien Mazarguil }
1005198a3c33SNelio Laranjeiro 
1006198a3c33SNelio Laranjeiro /**
1007c26ae069SMatan Azrad  * Device status handler.
1008c26ae069SMatan Azrad  *
1009af4f09f2SNélio Laranjeiro  * @param dev
1010af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
1011c26ae069SMatan Azrad  * @param events
1012c26ae069SMatan Azrad  *   Pointer to event flags holder.
1013c26ae069SMatan Azrad  *
1014c26ae069SMatan Azrad  * @return
1015c26ae069SMatan Azrad  *   Events bitmap of callback process which can be called immediately.
1016c26ae069SMatan Azrad  */
1017c26ae069SMatan Azrad static uint32_t
1018af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev)
1019198a3c33SNelio Laranjeiro {
1020af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
1021198a3c33SNelio Laranjeiro 	struct ibv_async_event event;
1022c26ae069SMatan Azrad 	uint32_t ret = 0;
1023198a3c33SNelio Laranjeiro 
1024cfee9475SNélio Laranjeiro 	if (mlx5_link_update(dev, 0) == -EAGAIN) {
1025cfee9475SNélio Laranjeiro 		usleep(0);
1026cfee9475SNélio Laranjeiro 		return 0;
1027cfee9475SNélio Laranjeiro 	}
1028198a3c33SNelio Laranjeiro 	/* Read all message and acknowledge them. */
1029198a3c33SNelio Laranjeiro 	for (;;) {
10300e83b8e5SNelio Laranjeiro 		if (mlx5_glue->get_async_event(priv->ctx, &event))
1031198a3c33SNelio Laranjeiro 			break;
1032c26ae069SMatan Azrad 		if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
1033c26ae069SMatan Azrad 			event.event_type == IBV_EVENT_PORT_ERR) &&
1034af4f09f2SNélio Laranjeiro 			(dev->data->dev_conf.intr_conf.lsc == 1))
1035c26ae069SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
10367d7d7ad1SMatan Azrad 		else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
1037af4f09f2SNélio Laranjeiro 			dev->data->dev_conf.intr_conf.rmv == 1)
10387d7d7ad1SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
1039c26ae069SMatan Azrad 		else
1040a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1041a170a30dSNélio Laranjeiro 				"port %u event type %d on not handled",
10420f99970bSNélio Laranjeiro 				dev->data->port_id, event.event_type);
10430e83b8e5SNelio Laranjeiro 		mlx5_glue->ack_async_event(&event);
1044198a3c33SNelio Laranjeiro 	}
1045198a3c33SNelio Laranjeiro 	return ret;
1046198a3c33SNelio Laranjeiro }
1047198a3c33SNelio Laranjeiro 
1048198a3c33SNelio Laranjeiro /**
1049198a3c33SNelio Laranjeiro  * Handle interrupts from the NIC.
1050198a3c33SNelio Laranjeiro  *
1051198a3c33SNelio Laranjeiro  * @param[in] intr_handle
1052198a3c33SNelio Laranjeiro  *   Interrupt handler.
1053198a3c33SNelio Laranjeiro  * @param cb_arg
1054198a3c33SNelio Laranjeiro  *   Callback argument.
1055198a3c33SNelio Laranjeiro  */
1056198a3c33SNelio Laranjeiro void
1057c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg)
1058198a3c33SNelio Laranjeiro {
1059198a3c33SNelio Laranjeiro 	struct rte_eth_dev *dev = cb_arg;
1060c26ae069SMatan Azrad 	uint32_t events;
1061198a3c33SNelio Laranjeiro 
1062af4f09f2SNélio Laranjeiro 	events = mlx5_dev_status_handler(dev);
1063c26ae069SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
1064cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
10657d7d7ad1SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
1066cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
1067198a3c33SNelio Laranjeiro }
1068198a3c33SNelio Laranjeiro 
1069198a3c33SNelio Laranjeiro /**
1070f8b9a3baSXueming Li  * Handle interrupts from the socket.
1071f8b9a3baSXueming Li  *
1072f8b9a3baSXueming Li  * @param cb_arg
1073f8b9a3baSXueming Li  *   Callback argument.
1074f8b9a3baSXueming Li  */
1075f8b9a3baSXueming Li static void
1076f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg)
1077f8b9a3baSXueming Li {
1078f8b9a3baSXueming Li 	struct rte_eth_dev *dev = cb_arg;
1079f8b9a3baSXueming Li 
1080af4f09f2SNélio Laranjeiro 	mlx5_socket_handle(dev);
1081f8b9a3baSXueming Li }
1082f8b9a3baSXueming Li 
1083f8b9a3baSXueming Li /**
1084198a3c33SNelio Laranjeiro  * Uninstall interrupt handler.
1085198a3c33SNelio Laranjeiro  *
1086198a3c33SNelio Laranjeiro  * @param dev
1087af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
1088198a3c33SNelio Laranjeiro  */
1089198a3c33SNelio Laranjeiro void
1090af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
1091198a3c33SNelio Laranjeiro {
1092af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
1093af4f09f2SNélio Laranjeiro 
1094f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
1095f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv)
1096198a3c33SNelio Laranjeiro 		rte_intr_callback_unregister(&priv->intr_handle,
1097f8b9a3baSXueming Li 					     mlx5_dev_interrupt_handler, dev);
1098f8b9a3baSXueming Li 	if (priv->primary_socket)
1099f8b9a3baSXueming Li 		rte_intr_callback_unregister(&priv->intr_handle_socket,
1100f8b9a3baSXueming Li 					     mlx5_dev_handler_socket, dev);
1101198a3c33SNelio Laranjeiro 	priv->intr_handle.fd = 0;
110236351ea3SFerruh Yigit 	priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
1103f8b9a3baSXueming Li 	priv->intr_handle_socket.fd = 0;
1104f8b9a3baSXueming Li 	priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
1105198a3c33SNelio Laranjeiro }
1106198a3c33SNelio Laranjeiro 
1107198a3c33SNelio Laranjeiro /**
1108198a3c33SNelio Laranjeiro  * Install interrupt handler.
1109198a3c33SNelio Laranjeiro  *
1110198a3c33SNelio Laranjeiro  * @param dev
1111af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
1112198a3c33SNelio Laranjeiro  */
1113198a3c33SNelio Laranjeiro void
1114af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
1115198a3c33SNelio Laranjeiro {
1116af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
1117a6d83b6aSNélio Laranjeiro 	int ret;
1118a6d83b6aSNélio Laranjeiro 	int flags;
1119198a3c33SNelio Laranjeiro 
1120198a3c33SNelio Laranjeiro 	assert(priv->ctx->async_fd > 0);
1121198a3c33SNelio Laranjeiro 	flags = fcntl(priv->ctx->async_fd, F_GETFL);
1122a6d83b6aSNélio Laranjeiro 	ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
1123a6d83b6aSNélio Laranjeiro 	if (ret) {
1124a170a30dSNélio Laranjeiro 		DRV_LOG(INFO,
1125a170a30dSNélio Laranjeiro 			"port %u failed to change file descriptor async event"
1126a170a30dSNélio Laranjeiro 			" queue",
1127a170a30dSNélio Laranjeiro 			dev->data->port_id);
1128198a3c33SNelio Laranjeiro 		dev->data->dev_conf.intr_conf.lsc = 0;
11297d7d7ad1SMatan Azrad 		dev->data->dev_conf.intr_conf.rmv = 0;
1130f8b9a3baSXueming Li 	}
1131f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
1132f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv) {
1133198a3c33SNelio Laranjeiro 		priv->intr_handle.fd = priv->ctx->async_fd;
1134198a3c33SNelio Laranjeiro 		priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
1135198a3c33SNelio Laranjeiro 		rte_intr_callback_register(&priv->intr_handle,
1136f8b9a3baSXueming Li 					   mlx5_dev_interrupt_handler, dev);
1137f8b9a3baSXueming Li 	}
1138a6d83b6aSNélio Laranjeiro 	ret = mlx5_socket_init(dev);
1139a6d83b6aSNélio Laranjeiro 	if (ret)
1140a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot initialise socket: %s",
11410f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
1142a6d83b6aSNélio Laranjeiro 	else if (priv->primary_socket) {
1143f8b9a3baSXueming Li 		priv->intr_handle_socket.fd = priv->primary_socket;
1144f8b9a3baSXueming Li 		priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
1145f8b9a3baSXueming Li 		rte_intr_callback_register(&priv->intr_handle_socket,
1146f8b9a3baSXueming Li 					   mlx5_dev_handler_socket, dev);
1147198a3c33SNelio Laranjeiro 	}
1148198a3c33SNelio Laranjeiro }
114962072098SOr Ami 
115062072098SOr Ami /**
115162072098SOr Ami  * DPDK callback to bring the link DOWN.
115262072098SOr Ami  *
115362072098SOr Ami  * @param dev
115462072098SOr Ami  *   Pointer to Ethernet device structure.
115562072098SOr Ami  *
115662072098SOr Ami  * @return
1157a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
115862072098SOr Ami  */
115962072098SOr Ami int
116062072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev)
116162072098SOr Ami {
1162af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
116362072098SOr Ami }
116462072098SOr Ami 
116562072098SOr Ami /**
116662072098SOr Ami  * DPDK callback to bring the link UP.
116762072098SOr Ami  *
116862072098SOr Ami  * @param dev
116962072098SOr Ami  *   Pointer to Ethernet device structure.
117062072098SOr Ami  *
117162072098SOr Ami  * @return
1172a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
117362072098SOr Ami  */
117462072098SOr Ami int
117562072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev)
117662072098SOr Ami {
1177af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
117862072098SOr Ami }
1179a48deadaSOr Ami 
1180a48deadaSOr Ami /**
1181cdab90cbSNélio Laranjeiro  * Configure the TX function to use.
1182cdab90cbSNélio Laranjeiro  *
1183aee1b165SXueming Li  * @param dev
1184af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
11851cfa649bSShahaf Shuler  *
11861cfa649bSShahaf Shuler  * @return
11871cfa649bSShahaf Shuler  *   Pointer to selected Tx burst function.
1188cdab90cbSNélio Laranjeiro  */
11891cfa649bSShahaf Shuler eth_tx_burst_t
1190af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev)
1191cdab90cbSNélio Laranjeiro {
1192af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
11931cfa649bSShahaf Shuler 	eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst;
11947fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
1195dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
1196dbccb4cdSShahaf Shuler 	int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO |
1197dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
119832d4246cSXueming Li 				    DEV_TX_OFFLOAD_GRE_TNL_TSO |
119932d4246cSXueming Li 				    DEV_TX_OFFLOAD_IP_TNL_TSO |
120032d4246cSXueming Li 				    DEV_TX_OFFLOAD_UDP_TNL_TSO));
12015f8ba81cSXueming Li 	int swp = !!(tx_offloads & (DEV_TX_OFFLOAD_IP_TNL_TSO |
12025f8ba81cSXueming Li 				    DEV_TX_OFFLOAD_UDP_TNL_TSO |
12035f8ba81cSXueming Li 				    DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM));
1204dbccb4cdSShahaf Shuler 	int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT);
12051cfa649bSShahaf Shuler 
1206aee1b165SXueming Li 	assert(priv != NULL);
1207230189d9SNélio Laranjeiro 	/* Select appropriate TX function. */
12085f8ba81cSXueming Li 	if (vlan_insert || tso || swp)
1209dbccb4cdSShahaf Shuler 		return tx_pkt_burst;
12107fe24446SShahaf Shuler 	if (config->mps == MLX5_MPW_ENHANCED) {
1211af4f09f2SNélio Laranjeiro 		if (mlx5_check_vec_tx_support(dev) > 0) {
1212af4f09f2SNélio Laranjeiro 			if (mlx5_check_raw_vec_tx_support(dev) > 0)
12131cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_raw_vec;
12146cb559d6SYongseok Koh 			else
12151cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_vec;
1216a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1217a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx vectorized"
1218a170a30dSNélio Laranjeiro 				" function",
1219a170a30dSNélio Laranjeiro 				dev->data->port_id);
12206cb559d6SYongseok Koh 		} else {
12211cfa649bSShahaf Shuler 			tx_pkt_burst = mlx5_tx_burst_empw;
1222a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1223a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx function",
12240f99970bSNélio Laranjeiro 				dev->data->port_id);
12256cb559d6SYongseok Koh 		}
12267fe24446SShahaf Shuler 	} else if (config->mps && (config->txq_inline > 0)) {
12271cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw_inline;
1228a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW inline Tx function",
12290f99970bSNélio Laranjeiro 			dev->data->port_id);
12307fe24446SShahaf Shuler 	} else if (config->mps) {
12311cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw;
1232a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW Tx function",
1233a170a30dSNélio Laranjeiro 			dev->data->port_id);
12342a66cf37SYaacov Hazan 	}
12351cfa649bSShahaf Shuler 	return tx_pkt_burst;
1236cdab90cbSNélio Laranjeiro }
1237cdab90cbSNélio Laranjeiro 
1238cdab90cbSNélio Laranjeiro /**
1239cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
1240cdab90cbSNélio Laranjeiro  *
1241aee1b165SXueming Li  * @param dev
1242af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
12431cfa649bSShahaf Shuler  *
12441cfa649bSShahaf Shuler  * @return
12451cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
1246cdab90cbSNélio Laranjeiro  */
12471cfa649bSShahaf Shuler eth_rx_burst_t
1248af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
1249cdab90cbSNélio Laranjeiro {
12501cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
12511cfa649bSShahaf Shuler 
1252af4f09f2SNélio Laranjeiro 	assert(dev != NULL);
1253af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
12541cfa649bSShahaf Shuler 		rx_pkt_burst = mlx5_rx_burst_vec;
1255a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected Rx vectorized function",
12560f99970bSNélio Laranjeiro 			dev->data->port_id);
12577d6bf6b8SYongseok Koh 	} else if (mlx5_mprq_enabled(dev)) {
12587d6bf6b8SYongseok Koh 		rx_pkt_burst = mlx5_rx_burst_mprq;
1259cdab90cbSNélio Laranjeiro 	}
12601cfa649bSShahaf Shuler 	return rx_pkt_burst;
12616cb559d6SYongseok Koh }
1262d3e0f392SMatan Azrad 
1263d3e0f392SMatan Azrad /**
1264d3e0f392SMatan Azrad  * Check if mlx5 device was removed.
1265d3e0f392SMatan Azrad  *
1266d3e0f392SMatan Azrad  * @param dev
1267d3e0f392SMatan Azrad  *   Pointer to Ethernet device structure.
1268d3e0f392SMatan Azrad  *
1269d3e0f392SMatan Azrad  * @return
1270d3e0f392SMatan Azrad  *   1 when device is removed, otherwise 0.
1271d3e0f392SMatan Azrad  */
1272d3e0f392SMatan Azrad int
1273d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev)
1274d3e0f392SMatan Azrad {
1275d3e0f392SMatan Azrad 	struct ibv_device_attr device_attr;
1276d3e0f392SMatan Azrad 	struct priv *priv = dev->data->dev_private;
1277d3e0f392SMatan Azrad 
12780e83b8e5SNelio Laranjeiro 	if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO)
1279d3e0f392SMatan Azrad 		return 1;
1280d3e0f392SMatan Azrad 	return 0;
1281d3e0f392SMatan Azrad }
12822b730263SAdrien Mazarguil 
12832b730263SAdrien Mazarguil /**
12842b730263SAdrien Mazarguil  * Get port ID list of mlx5 instances sharing a common device.
12852b730263SAdrien Mazarguil  *
12862b730263SAdrien Mazarguil  * @param[in] dev
12872b730263SAdrien Mazarguil  *   Device to look for.
12882b730263SAdrien Mazarguil  * @param[out] port_list
12892b730263SAdrien Mazarguil  *   Result buffer for collected port IDs.
12902b730263SAdrien Mazarguil  * @param port_list_n
12912b730263SAdrien Mazarguil  *   Maximum number of entries in result buffer. If 0, @p port_list can be
12922b730263SAdrien Mazarguil  *   NULL.
12932b730263SAdrien Mazarguil  *
12942b730263SAdrien Mazarguil  * @return
12952b730263SAdrien Mazarguil  *   Number of matching instances regardless of the @p port_list_n
12962b730263SAdrien Mazarguil  *   parameter, 0 if none were found.
12972b730263SAdrien Mazarguil  */
12982b730263SAdrien Mazarguil unsigned int
12992b730263SAdrien Mazarguil mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
13002b730263SAdrien Mazarguil 		    unsigned int port_list_n)
13012b730263SAdrien Mazarguil {
13022b730263SAdrien Mazarguil 	uint16_t id;
13032b730263SAdrien Mazarguil 	unsigned int n = 0;
13042b730263SAdrien Mazarguil 
13052b730263SAdrien Mazarguil 	RTE_ETH_FOREACH_DEV(id) {
13062b730263SAdrien Mazarguil 		struct rte_eth_dev *ldev = &rte_eth_devices[id];
13072b730263SAdrien Mazarguil 
13082b730263SAdrien Mazarguil 		if (!ldev->device ||
13092b730263SAdrien Mazarguil 		    !ldev->device->driver ||
13102b730263SAdrien Mazarguil 		    strcmp(ldev->device->driver->name, MLX5_DRIVER_NAME) ||
13112b730263SAdrien Mazarguil 		    ldev->device != dev)
13122b730263SAdrien Mazarguil 			continue;
13132b730263SAdrien Mazarguil 		if (n < port_list_n)
13142b730263SAdrien Mazarguil 			port_list[n] = id;
13152b730263SAdrien Mazarguil 		n++;
13162b730263SAdrien Mazarguil 	}
13172b730263SAdrien Mazarguil 	return n;
13182b730263SAdrien Mazarguil }
1319f872b4b9SNelio Laranjeiro 
1320f872b4b9SNelio Laranjeiro /**
1321f872b4b9SNelio Laranjeiro  * Get switch information associated with network interface.
1322f872b4b9SNelio Laranjeiro  *
1323f872b4b9SNelio Laranjeiro  * @param ifindex
1324f872b4b9SNelio Laranjeiro  *   Network interface index.
1325f872b4b9SNelio Laranjeiro  * @param[out] info
1326f872b4b9SNelio Laranjeiro  *   Switch information object, populated in case of success.
1327f872b4b9SNelio Laranjeiro  *
1328f872b4b9SNelio Laranjeiro  * @return
1329f872b4b9SNelio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
1330f872b4b9SNelio Laranjeiro  */
1331f872b4b9SNelio Laranjeiro int
1332f872b4b9SNelio Laranjeiro mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
1333f872b4b9SNelio Laranjeiro {
1334f872b4b9SNelio Laranjeiro 	char ifname[IF_NAMESIZE];
1335f872b4b9SNelio Laranjeiro 	FILE *file;
1336f872b4b9SNelio Laranjeiro 	struct mlx5_switch_info data = { .master = 0, };
1337f872b4b9SNelio Laranjeiro 	bool port_name_set = false;
1338f872b4b9SNelio Laranjeiro 	bool port_switch_id_set = false;
1339f872b4b9SNelio Laranjeiro 	char c;
1340f872b4b9SNelio Laranjeiro 
1341f872b4b9SNelio Laranjeiro 	if (!if_indextoname(ifindex, ifname)) {
1342f872b4b9SNelio Laranjeiro 		rte_errno = errno;
1343f872b4b9SNelio Laranjeiro 		return -rte_errno;
1344f872b4b9SNelio Laranjeiro 	}
1345f872b4b9SNelio Laranjeiro 
1346f872b4b9SNelio Laranjeiro 	MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name",
1347f872b4b9SNelio Laranjeiro 	      ifname);
1348f872b4b9SNelio Laranjeiro 	MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id",
1349f872b4b9SNelio Laranjeiro 	      ifname);
1350f872b4b9SNelio Laranjeiro 
1351f872b4b9SNelio Laranjeiro 	file = fopen(phys_port_name, "rb");
1352f872b4b9SNelio Laranjeiro 	if (file != NULL) {
1353f872b4b9SNelio Laranjeiro 		port_name_set =
1354f872b4b9SNelio Laranjeiro 			fscanf(file, "%d%c", &data.port_name, &c) == 2 &&
1355f872b4b9SNelio Laranjeiro 			c == '\n';
1356f872b4b9SNelio Laranjeiro 		fclose(file);
1357f872b4b9SNelio Laranjeiro 	}
1358f872b4b9SNelio Laranjeiro 	file = fopen(phys_switch_id, "rb");
1359f872b4b9SNelio Laranjeiro 	if (file == NULL) {
1360f872b4b9SNelio Laranjeiro 		rte_errno = errno;
1361f872b4b9SNelio Laranjeiro 		return -rte_errno;
1362f872b4b9SNelio Laranjeiro 	}
1363f872b4b9SNelio Laranjeiro 	port_switch_id_set =
1364f872b4b9SNelio Laranjeiro 		fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 &&
1365f872b4b9SNelio Laranjeiro 		c == '\n';
1366f872b4b9SNelio Laranjeiro 	fclose(file);
1367f872b4b9SNelio Laranjeiro 	data.master = port_switch_id_set && !port_name_set;
1368f872b4b9SNelio Laranjeiro 	data.representor = port_switch_id_set && port_name_set;
1369f872b4b9SNelio Laranjeiro 	*info = data;
1370f872b4b9SNelio Laranjeiro 	return 0;
1371f872b4b9SNelio Laranjeiro }
1372