xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision cfee94752b8f8f09b984335ae77b29af15b967fd)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2771fa900SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
3771fa900SAdrien Mazarguil  * Copyright 2015 Mellanox.
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>
27*cfee9475SNé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>
36771fa900SAdrien Mazarguil 
37771fa900SAdrien Mazarguil #include "mlx5.h"
380e83b8e5SNelio Laranjeiro #include "mlx5_glue.h"
39e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h"
40771fa900SAdrien Mazarguil #include "mlx5_utils.h"
41771fa900SAdrien Mazarguil 
423a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */
433a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS
443a49ffe3SShahaf Shuler struct ethtool_link_settings {
453a49ffe3SShahaf Shuler 	uint32_t cmd;
463a49ffe3SShahaf Shuler 	uint32_t speed;
473a49ffe3SShahaf Shuler 	uint8_t duplex;
483a49ffe3SShahaf Shuler 	uint8_t port;
493a49ffe3SShahaf Shuler 	uint8_t phy_address;
503a49ffe3SShahaf Shuler 	uint8_t autoneg;
513a49ffe3SShahaf Shuler 	uint8_t mdio_support;
523a49ffe3SShahaf Shuler 	uint8_t eth_to_mdix;
533a49ffe3SShahaf Shuler 	uint8_t eth_tp_mdix_ctrl;
543a49ffe3SShahaf Shuler 	int8_t link_mode_masks_nwords;
553a49ffe3SShahaf Shuler 	uint32_t reserved[8];
563a49ffe3SShahaf Shuler 	uint32_t link_mode_masks[];
573a49ffe3SShahaf Shuler };
583a49ffe3SShahaf Shuler 
593a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c
603a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5
613a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6
623a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17
633a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18
643a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19
653a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20
663a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21
673a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22
683a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23
693a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24
703a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25
713a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26
723a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27
733a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28
743a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29
753a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30
763a49ffe3SShahaf Shuler #endif
773a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G
783a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31
793a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32
803a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33
813a49ffe3SShahaf Shuler #endif
823a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G
833a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34
843a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35
853a49ffe3SShahaf Shuler #endif
863a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G
873a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36
883a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37
893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38
903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39
913a49ffe3SShahaf Shuler #endif
923a49ffe3SShahaf Shuler 
93771fa900SAdrien Mazarguil /**
94771fa900SAdrien Mazarguil  * Get interface name from private structure.
95771fa900SAdrien Mazarguil  *
96af4f09f2SNélio Laranjeiro  * @param[in] dev
97af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
98771fa900SAdrien Mazarguil  * @param[out] ifname
99771fa900SAdrien Mazarguil  *   Interface name output buffer.
100771fa900SAdrien Mazarguil  *
101771fa900SAdrien Mazarguil  * @return
102a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
103771fa900SAdrien Mazarguil  */
104771fa900SAdrien Mazarguil int
105af4f09f2SNélio Laranjeiro mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
106771fa900SAdrien Mazarguil {
107af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
108771fa900SAdrien Mazarguil 	DIR *dir;
109771fa900SAdrien Mazarguil 	struct dirent *dent;
110771fa900SAdrien Mazarguil 	unsigned int dev_type = 0;
111771fa900SAdrien Mazarguil 	unsigned int dev_port_prev = ~0u;
112771fa900SAdrien Mazarguil 	char match[IF_NAMESIZE] = "";
113771fa900SAdrien Mazarguil 
114771fa900SAdrien Mazarguil 	{
11587ec44ceSXueming Li 		MKSTR(path, "%s/device/net", priv->ibdev_path);
116771fa900SAdrien Mazarguil 
117771fa900SAdrien Mazarguil 		dir = opendir(path);
118a6d83b6aSNélio Laranjeiro 		if (dir == NULL) {
119a6d83b6aSNélio Laranjeiro 			rte_errno = errno;
120a6d83b6aSNélio Laranjeiro 			return -rte_errno;
121a6d83b6aSNélio Laranjeiro 		}
122771fa900SAdrien Mazarguil 	}
123771fa900SAdrien Mazarguil 	while ((dent = readdir(dir)) != NULL) {
124771fa900SAdrien Mazarguil 		char *name = dent->d_name;
125771fa900SAdrien Mazarguil 		FILE *file;
126771fa900SAdrien Mazarguil 		unsigned int dev_port;
127771fa900SAdrien Mazarguil 		int r;
128771fa900SAdrien Mazarguil 
129771fa900SAdrien Mazarguil 		if ((name[0] == '.') &&
130771fa900SAdrien Mazarguil 		    ((name[1] == '\0') ||
131771fa900SAdrien Mazarguil 		     ((name[1] == '.') && (name[2] == '\0'))))
132771fa900SAdrien Mazarguil 			continue;
133771fa900SAdrien Mazarguil 
134771fa900SAdrien Mazarguil 		MKSTR(path, "%s/device/net/%s/%s",
13587ec44ceSXueming Li 		      priv->ibdev_path, name,
136771fa900SAdrien Mazarguil 		      (dev_type ? "dev_id" : "dev_port"));
137771fa900SAdrien Mazarguil 
138771fa900SAdrien Mazarguil 		file = fopen(path, "rb");
139771fa900SAdrien Mazarguil 		if (file == NULL) {
140771fa900SAdrien Mazarguil 			if (errno != ENOENT)
141771fa900SAdrien Mazarguil 				continue;
142771fa900SAdrien Mazarguil 			/*
143771fa900SAdrien Mazarguil 			 * Switch to dev_id when dev_port does not exist as
144771fa900SAdrien Mazarguil 			 * is the case with Linux kernel versions < 3.15.
145771fa900SAdrien Mazarguil 			 */
146771fa900SAdrien Mazarguil try_dev_id:
147771fa900SAdrien Mazarguil 			match[0] = '\0';
148771fa900SAdrien Mazarguil 			if (dev_type)
149771fa900SAdrien Mazarguil 				break;
150771fa900SAdrien Mazarguil 			dev_type = 1;
151771fa900SAdrien Mazarguil 			dev_port_prev = ~0u;
152771fa900SAdrien Mazarguil 			rewinddir(dir);
153771fa900SAdrien Mazarguil 			continue;
154771fa900SAdrien Mazarguil 		}
155771fa900SAdrien Mazarguil 		r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
156771fa900SAdrien Mazarguil 		fclose(file);
157771fa900SAdrien Mazarguil 		if (r != 1)
158771fa900SAdrien Mazarguil 			continue;
159771fa900SAdrien Mazarguil 		/*
160771fa900SAdrien Mazarguil 		 * Switch to dev_id when dev_port returns the same value for
161771fa900SAdrien Mazarguil 		 * all ports. May happen when using a MOFED release older than
162771fa900SAdrien Mazarguil 		 * 3.0 with a Linux kernel >= 3.15.
163771fa900SAdrien Mazarguil 		 */
164771fa900SAdrien Mazarguil 		if (dev_port == dev_port_prev)
165771fa900SAdrien Mazarguil 			goto try_dev_id;
166771fa900SAdrien Mazarguil 		dev_port_prev = dev_port;
167771fa900SAdrien Mazarguil 		if (dev_port == (priv->port - 1u))
168771fa900SAdrien Mazarguil 			snprintf(match, sizeof(match), "%s", name);
169771fa900SAdrien Mazarguil 	}
170771fa900SAdrien Mazarguil 	closedir(dir);
171a6d83b6aSNélio Laranjeiro 	if (match[0] == '\0') {
172a6d83b6aSNélio Laranjeiro 		rte_errno = ENOENT;
173a6d83b6aSNélio Laranjeiro 		return -rte_errno;
174a6d83b6aSNélio Laranjeiro 	}
175771fa900SAdrien Mazarguil 	strncpy(*ifname, match, sizeof(*ifname));
176771fa900SAdrien Mazarguil 	return 0;
177771fa900SAdrien Mazarguil }
178771fa900SAdrien Mazarguil 
179771fa900SAdrien Mazarguil /**
180771fa900SAdrien Mazarguil  * Perform ifreq ioctl() on associated Ethernet device.
181771fa900SAdrien Mazarguil  *
182af4f09f2SNélio Laranjeiro  * @param[in] dev
183af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
184771fa900SAdrien Mazarguil  * @param req
185771fa900SAdrien Mazarguil  *   Request number to pass to ioctl().
186771fa900SAdrien Mazarguil  * @param[out] ifr
187771fa900SAdrien Mazarguil  *   Interface request structure output buffer.
188771fa900SAdrien Mazarguil  *
189771fa900SAdrien Mazarguil  * @return
190a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
191771fa900SAdrien Mazarguil  */
192771fa900SAdrien Mazarguil int
193af4f09f2SNélio Laranjeiro mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
194771fa900SAdrien Mazarguil {
195771fa900SAdrien Mazarguil 	int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
196a6d83b6aSNélio Laranjeiro 	int ret = 0;
197771fa900SAdrien Mazarguil 
198a6d83b6aSNélio Laranjeiro 	if (sock == -1) {
199a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
200a6d83b6aSNélio Laranjeiro 		return -rte_errno;
201a6d83b6aSNélio Laranjeiro 	}
202a6d83b6aSNélio Laranjeiro 	ret = mlx5_get_ifname(dev, &ifr->ifr_name);
203a6d83b6aSNélio Laranjeiro 	if (ret)
204a6d83b6aSNélio Laranjeiro 		goto error;
205771fa900SAdrien Mazarguil 	ret = ioctl(sock, req, ifr);
206a6d83b6aSNélio Laranjeiro 	if (ret == -1) {
207a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
208a6d83b6aSNélio Laranjeiro 		goto error;
209a6d83b6aSNélio Laranjeiro 	}
210771fa900SAdrien Mazarguil 	close(sock);
211a6d83b6aSNélio Laranjeiro 	return 0;
212a6d83b6aSNélio Laranjeiro error:
213a6d83b6aSNélio Laranjeiro 	close(sock);
214a6d83b6aSNélio Laranjeiro 	return -rte_errno;
215771fa900SAdrien Mazarguil }
216771fa900SAdrien Mazarguil 
217771fa900SAdrien Mazarguil /**
218771fa900SAdrien Mazarguil  * Get device MTU.
219771fa900SAdrien Mazarguil  *
220af4f09f2SNélio Laranjeiro  * @param dev
221af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
222771fa900SAdrien Mazarguil  * @param[out] mtu
223771fa900SAdrien Mazarguil  *   MTU value output buffer.
224771fa900SAdrien Mazarguil  *
225771fa900SAdrien Mazarguil  * @return
226a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
227771fa900SAdrien Mazarguil  */
228771fa900SAdrien Mazarguil int
229af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
230771fa900SAdrien Mazarguil {
231fc40db99SAdrien Mazarguil 	struct ifreq request;
232af4f09f2SNélio Laranjeiro 	int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
233771fa900SAdrien Mazarguil 
234fc40db99SAdrien Mazarguil 	if (ret)
235fc40db99SAdrien Mazarguil 		return ret;
236fc40db99SAdrien Mazarguil 	*mtu = request.ifr_mtu;
237859081d3SShahaf Shuler 	return 0;
238859081d3SShahaf Shuler }
239859081d3SShahaf Shuler 
240859081d3SShahaf Shuler /**
241cf37ca95SAdrien Mazarguil  * Set device MTU.
242cf37ca95SAdrien Mazarguil  *
243af4f09f2SNélio Laranjeiro  * @param dev
244af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
245cf37ca95SAdrien Mazarguil  * @param mtu
246cf37ca95SAdrien Mazarguil  *   MTU value to set.
247cf37ca95SAdrien Mazarguil  *
248cf37ca95SAdrien Mazarguil  * @return
249a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
250cf37ca95SAdrien Mazarguil  */
251cf37ca95SAdrien Mazarguil static int
252af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
253cf37ca95SAdrien Mazarguil {
254fc40db99SAdrien Mazarguil 	struct ifreq request = { .ifr_mtu = mtu, };
255f3b492d7SAdrien Mazarguil 
256af4f09f2SNélio Laranjeiro 	return mlx5_ifreq(dev, SIOCSIFMTU, &request);
257cf37ca95SAdrien Mazarguil }
258cf37ca95SAdrien Mazarguil 
259cf37ca95SAdrien Mazarguil /**
260771fa900SAdrien Mazarguil  * Set device flags.
261771fa900SAdrien Mazarguil  *
262af4f09f2SNélio Laranjeiro  * @param dev
263af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
264771fa900SAdrien Mazarguil  * @param keep
265771fa900SAdrien Mazarguil  *   Bitmask for flags that must remain untouched.
266771fa900SAdrien Mazarguil  * @param flags
267771fa900SAdrien Mazarguil  *   Bitmask for flags to modify.
268771fa900SAdrien Mazarguil  *
269771fa900SAdrien Mazarguil  * @return
270a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
271771fa900SAdrien Mazarguil  */
272771fa900SAdrien Mazarguil int
273af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
274771fa900SAdrien Mazarguil {
275fc40db99SAdrien Mazarguil 	struct ifreq request;
276af4f09f2SNélio Laranjeiro 	int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
277771fa900SAdrien Mazarguil 
278fc40db99SAdrien Mazarguil 	if (ret)
279fc40db99SAdrien Mazarguil 		return ret;
280fc40db99SAdrien Mazarguil 	request.ifr_flags &= keep;
281fc40db99SAdrien Mazarguil 	request.ifr_flags |= flags & ~keep;
282af4f09f2SNélio Laranjeiro 	return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
283771fa900SAdrien Mazarguil }
284771fa900SAdrien Mazarguil 
285771fa900SAdrien Mazarguil /**
2867b2423cdSNélio Laranjeiro  * DPDK callback for Ethernet device configuration.
287e60fbd5bSAdrien Mazarguil  *
288e60fbd5bSAdrien Mazarguil  * @param dev
289e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
290e60fbd5bSAdrien Mazarguil  *
291e60fbd5bSAdrien Mazarguil  * @return
292a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
293e60fbd5bSAdrien Mazarguil  */
2947b2423cdSNélio Laranjeiro int
2957b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev)
296e60fbd5bSAdrien Mazarguil {
297e60fbd5bSAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
298e60fbd5bSAdrien Mazarguil 	unsigned int rxqs_n = dev->data->nb_rx_queues;
299e60fbd5bSAdrien Mazarguil 	unsigned int txqs_n = dev->data->nb_tx_queues;
300634efbc2SNelio Laranjeiro 	unsigned int i;
301634efbc2SNelio Laranjeiro 	unsigned int j;
302634efbc2SNelio Laranjeiro 	unsigned int reta_idx_n;
30329c1d8bbSNélio Laranjeiro 	const uint8_t use_app_rss_key =
30421e3a974SShahaf Shuler 		!!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
305af4f09f2SNélio Laranjeiro 	uint64_t supp_tx_offloads = mlx5_get_tx_port_offloads(dev);
306dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
30717b843ebSShahaf Shuler 	uint64_t supp_rx_offloads =
308af4f09f2SNélio Laranjeiro 		(mlx5_get_rx_port_offloads() |
309af4f09f2SNélio Laranjeiro 		 mlx5_get_rx_queue_offloads(dev));
31017b843ebSShahaf Shuler 	uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
311a6d83b6aSNélio Laranjeiro 	int ret = 0;
312e60fbd5bSAdrien Mazarguil 
313dbccb4cdSShahaf Shuler 	if ((tx_offloads & supp_tx_offloads) != tx_offloads) {
314a170a30dSNélio Laranjeiro 		DRV_LOG(ERR,
315a170a30dSNélio Laranjeiro 			"port %u some Tx offloads are not supported requested"
316a170a30dSNélio Laranjeiro 			" 0x%" PRIx64 " supported 0x%" PRIx64,
3170f99970bSNélio Laranjeiro 			dev->data->port_id, tx_offloads, supp_tx_offloads);
318a6d83b6aSNélio Laranjeiro 		rte_errno = ENOTSUP;
319a6d83b6aSNélio Laranjeiro 		return -rte_errno;
320dbccb4cdSShahaf Shuler 	}
32117b843ebSShahaf Shuler 	if ((rx_offloads & supp_rx_offloads) != rx_offloads) {
322a170a30dSNélio Laranjeiro 		DRV_LOG(ERR,
323a170a30dSNélio Laranjeiro 			"port %u some Rx offloads are not supported requested"
324a170a30dSNélio Laranjeiro 			" 0x%" PRIx64 " supported 0x%" PRIx64,
3250f99970bSNélio Laranjeiro 			dev->data->port_id, rx_offloads, supp_rx_offloads);
326a6d83b6aSNélio Laranjeiro 		rte_errno = ENOTSUP;
327a6d83b6aSNélio Laranjeiro 		return -rte_errno;
32817b843ebSShahaf Shuler 	}
32929c1d8bbSNélio Laranjeiro 	if (use_app_rss_key &&
33029c1d8bbSNélio Laranjeiro 	    (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
33129c1d8bbSNélio Laranjeiro 	     rss_hash_default_key_len)) {
33229c1d8bbSNélio Laranjeiro 		/* MLX5 RSS only support 40bytes key. */
333a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
334a6d83b6aSNélio Laranjeiro 		return -rte_errno;
33529c1d8bbSNélio Laranjeiro 	}
33629c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key =
33729c1d8bbSNélio Laranjeiro 		rte_realloc(priv->rss_conf.rss_key,
33829c1d8bbSNélio Laranjeiro 			    rss_hash_default_key_len, 0);
33929c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
340a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
3410f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
342a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
343a6d83b6aSNélio Laranjeiro 		return -rte_errno;
34429c1d8bbSNélio Laranjeiro 	}
34529c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
34629c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
34729c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
34829c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
34929c1d8bbSNélio Laranjeiro 	       rss_hash_default_key_len);
35029c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key_len = rss_hash_default_key_len;
35129c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
352e60fbd5bSAdrien Mazarguil 	priv->rxqs = (void *)dev->data->rx_queues;
353e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
354e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
355a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
3560f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
357e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
358e60fbd5bSAdrien Mazarguil 	}
3597fe24446SShahaf Shuler 	if (rxqs_n > priv->config.ind_table_max_size) {
360a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
3610f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
362a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
363a6d83b6aSNélio Laranjeiro 		return -rte_errno;
364634efbc2SNelio Laranjeiro 	}
365e60fbd5bSAdrien Mazarguil 	if (rxqs_n == priv->rxqs_n)
366e60fbd5bSAdrien Mazarguil 		return 0;
367a170a30dSNélio Laranjeiro 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
3680f99970bSNélio Laranjeiro 		dev->data->port_id, priv->rxqs_n, rxqs_n);
369e60fbd5bSAdrien Mazarguil 	priv->rxqs_n = rxqs_n;
370634efbc2SNelio Laranjeiro 	/* If the requested number of RX queues is not a power of two, use the
371634efbc2SNelio Laranjeiro 	 * maximum indirection table size for better balancing.
372634efbc2SNelio Laranjeiro 	 * The result is always rounded to the next power of two. */
373634efbc2SNelio Laranjeiro 	reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ?
3747fe24446SShahaf Shuler 				     priv->config.ind_table_max_size :
375634efbc2SNelio Laranjeiro 				     rxqs_n));
376a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
377a6d83b6aSNélio Laranjeiro 	if (ret)
378a6d83b6aSNélio Laranjeiro 		return ret;
379634efbc2SNelio Laranjeiro 	/* When the number of RX queues is not a power of two, the remaining
380634efbc2SNelio Laranjeiro 	 * table entries are padded with reused WQs and hashes are not spread
381634efbc2SNelio Laranjeiro 	 * uniformly. */
382634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
383634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = j;
384634efbc2SNelio Laranjeiro 		if (++j == rxqs_n)
385634efbc2SNelio Laranjeiro 			j = 0;
386634efbc2SNelio Laranjeiro 	}
387e60fbd5bSAdrien Mazarguil 	return 0;
388e60fbd5bSAdrien Mazarguil }
389e60fbd5bSAdrien Mazarguil 
390e60fbd5bSAdrien Mazarguil /**
391e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
392e60fbd5bSAdrien Mazarguil  *
393e60fbd5bSAdrien Mazarguil  * @param dev
394e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
395e60fbd5bSAdrien Mazarguil  * @param[out] info
396e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
397e60fbd5bSAdrien Mazarguil  */
398e60fbd5bSAdrien Mazarguil void
399e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
400e60fbd5bSAdrien Mazarguil {
40101d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
4027fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
403e60fbd5bSAdrien Mazarguil 	unsigned int max;
404e60fbd5bSAdrien Mazarguil 	char ifname[IF_NAMESIZE];
405e60fbd5bSAdrien Mazarguil 
406c0802544SFerruh Yigit 	info->pci_dev = RTE_ETH_DEV_TO_PCI(dev);
407e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
408e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
409e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
410e60fbd5bSAdrien Mazarguil 	/*
411e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
412e60fbd5bSAdrien Mazarguil 	 * between the two values.
413e60fbd5bSAdrien Mazarguil 	 */
41443e9d979SShachar Beiser 	max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
41543e9d979SShachar Beiser 		      priv->device_attr.orig_attr.max_qp);
416e60fbd5bSAdrien Mazarguil 	/* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
417e60fbd5bSAdrien Mazarguil 	if (max >= 65535)
418e60fbd5bSAdrien Mazarguil 		max = 65535;
419e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
420e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
4210497ddaaSYaacov Hazan 	info->max_mac_addrs = RTE_DIM(priv->mac);
422af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
423af4f09f2SNélio Laranjeiro 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
42417b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
425af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
426af4f09f2SNélio Laranjeiro 	if (mlx5_get_ifname(dev, &ifname) == 0)
427e60fbd5bSAdrien Mazarguil 		info->if_index = if_nametoindex(ifname);
428d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
4297fe24446SShahaf Shuler 		priv->reta_idx_n : config->ind_table_max_size;
43029c1d8bbSNélio Laranjeiro 	info->hash_key_size = priv->rss_conf.rss_key_len;
43175ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
432b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
433e60fbd5bSAdrien Mazarguil }
434e60fbd5bSAdrien Mazarguil 
435fb732b0aSNélio Laranjeiro /**
436fb732b0aSNélio Laranjeiro  * Get supported packet types.
437fb732b0aSNélio Laranjeiro  *
438fb732b0aSNélio Laranjeiro  * @param dev
439fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
440fb732b0aSNélio Laranjeiro  *
441fb732b0aSNélio Laranjeiro  * @return
442fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
443fb732b0aSNélio Laranjeiro  */
44478a38edfSJianfeng Tan const uint32_t *
44578a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
44678a38edfSJianfeng Tan {
44778a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
44878a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
449ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
450c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
451c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
452ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
453ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
454ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
455ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
456c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
457c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
458ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
459ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
460ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
461ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
46278a38edfSJianfeng Tan 		RTE_PTYPE_UNKNOWN
46378a38edfSJianfeng Tan 	};
46478a38edfSJianfeng Tan 
4656cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
4666cb559d6SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_vec)
46778a38edfSJianfeng Tan 		return ptypes;
46878a38edfSJianfeng Tan 	return NULL;
46978a38edfSJianfeng Tan }
47078a38edfSJianfeng Tan 
471e60fbd5bSAdrien Mazarguil /**
4722c960a51SMatthieu Ternisien d'Ouville  * DPDK callback to retrieve physical link information.
473cb8faed7SAdrien Mazarguil  *
474cb8faed7SAdrien Mazarguil  * @param dev
475cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
476*cfee9475SNélio Laranjeiro  * @param[out] link
477*cfee9475SNélio Laranjeiro  *   Storage for current link status.
478fb732b0aSNélio Laranjeiro  *
479fb732b0aSNélio Laranjeiro  * @return
480a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
481cb8faed7SAdrien Mazarguil  */
48218840871SNélio Laranjeiro static int
483*cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
484*cfee9475SNélio Laranjeiro 			       struct rte_eth_link *link)
485cb8faed7SAdrien Mazarguil {
48601d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
487cb8faed7SAdrien Mazarguil 	struct ethtool_cmd edata = {
48875ef62a9SNélio Laranjeiro 		.cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
489cb8faed7SAdrien Mazarguil 	};
490cb8faed7SAdrien Mazarguil 	struct ifreq ifr;
491cb8faed7SAdrien Mazarguil 	struct rte_eth_link dev_link;
492cb8faed7SAdrien Mazarguil 	int link_speed = 0;
493a6d83b6aSNélio Laranjeiro 	int ret;
494cb8faed7SAdrien Mazarguil 
495a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
496a6d83b6aSNélio Laranjeiro 	if (ret) {
497a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
4980f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
499a6d83b6aSNélio Laranjeiro 		return ret;
500cb8faed7SAdrien Mazarguil 	}
501cb8faed7SAdrien Mazarguil 	memset(&dev_link, 0, sizeof(dev_link));
502cb8faed7SAdrien Mazarguil 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
503cb8faed7SAdrien Mazarguil 				(ifr.ifr_flags & IFF_RUNNING));
504d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&edata;
505a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
506a6d83b6aSNélio Laranjeiro 	if (ret) {
507a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
508a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
5090f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
510a6d83b6aSNélio Laranjeiro 		return ret;
511cb8faed7SAdrien Mazarguil 	}
512cb8faed7SAdrien Mazarguil 	link_speed = ethtool_cmd_speed(&edata);
513cb8faed7SAdrien Mazarguil 	if (link_speed == -1)
514cb8faed7SAdrien Mazarguil 		dev_link.link_speed = 0;
515cb8faed7SAdrien Mazarguil 	else
516cb8faed7SAdrien Mazarguil 		dev_link.link_speed = link_speed;
51775ef62a9SNélio Laranjeiro 	priv->link_speed_capa = 0;
51875ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_Autoneg)
51975ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
52075ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_1000baseT_Full |
52175ef62a9SNélio Laranjeiro 			       SUPPORTED_1000baseKX_Full))
52275ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
52375ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_10000baseKR_Full)
52475ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
52575ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_40000baseKR4_Full |
52675ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseCR4_Full |
52775ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseSR4_Full |
52875ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseLR4_Full))
52975ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
530cb8faed7SAdrien Mazarguil 	dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
531cb8faed7SAdrien Mazarguil 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
53282113036SMarc Sune 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
53382113036SMarc Sune 			ETH_LINK_SPEED_FIXED);
534*cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
535*cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
536a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
537a6d83b6aSNélio Laranjeiro 		return -rte_errno;
538cb8faed7SAdrien Mazarguil 	}
539*cfee9475SNélio Laranjeiro 	*link = dev_link;
540*cfee9475SNélio Laranjeiro 	return 0;
541*cfee9475SNélio Laranjeiro }
542cb8faed7SAdrien Mazarguil 
543cb8faed7SAdrien Mazarguil /**
5443a49ffe3SShahaf Shuler  * Retrieve physical link information (unlocked version using new ioctl).
54518840871SNélio Laranjeiro  *
54618840871SNélio Laranjeiro  * @param dev
54718840871SNélio Laranjeiro  *   Pointer to Ethernet device structure.
548*cfee9475SNélio Laranjeiro  * @param[out] link
549*cfee9475SNélio Laranjeiro  *   Storage for current link status.
550fb732b0aSNélio Laranjeiro  *
551fb732b0aSNélio Laranjeiro  * @return
552a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
55318840871SNélio Laranjeiro  */
55418840871SNélio Laranjeiro static int
555*cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
556*cfee9475SNélio Laranjeiro 			     struct rte_eth_link *link)
557*cfee9475SNélio Laranjeiro 
55818840871SNélio Laranjeiro {
55901d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
56037a4406cSNélio Laranjeiro 	struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
56118840871SNélio Laranjeiro 	struct ifreq ifr;
56218840871SNélio Laranjeiro 	struct rte_eth_link dev_link;
56318840871SNélio Laranjeiro 	uint64_t sc;
564a6d83b6aSNélio Laranjeiro 	int ret;
56518840871SNélio Laranjeiro 
566a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
567a6d83b6aSNélio Laranjeiro 	if (ret) {
568a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
5690f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
570a6d83b6aSNélio Laranjeiro 		return ret;
57118840871SNélio Laranjeiro 	}
57218840871SNélio Laranjeiro 	memset(&dev_link, 0, sizeof(dev_link));
57318840871SNélio Laranjeiro 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
57418840871SNélio Laranjeiro 				(ifr.ifr_flags & IFF_RUNNING));
57537a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)&gcmd;
576a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
577a6d83b6aSNélio Laranjeiro 	if (ret) {
578a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
579a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
580a170a30dSNélio Laranjeiro 			" failed: %s",
581a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
582a6d83b6aSNélio Laranjeiro 		return ret;
58318840871SNélio Laranjeiro 	}
58437a4406cSNélio Laranjeiro 	gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
58537a4406cSNélio Laranjeiro 
58637a4406cSNélio Laranjeiro 	alignas(struct ethtool_link_settings)
58737a4406cSNélio Laranjeiro 	uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
58837a4406cSNélio Laranjeiro 		     sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
58937a4406cSNélio Laranjeiro 	struct ethtool_link_settings *ecmd = (void *)data;
59037a4406cSNélio Laranjeiro 
59137a4406cSNélio Laranjeiro 	*ecmd = gcmd;
59237a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)ecmd;
593a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
594a6d83b6aSNélio Laranjeiro 	if (ret) {
595a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
596a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
597a170a30dSNélio Laranjeiro 			" failed: %s",
598a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
599a6d83b6aSNélio Laranjeiro 		return ret;
600ef09a7fcSGowrishankar Muthukrishnan 	}
60190260d57SNélio Laranjeiro 	dev_link.link_speed = ecmd->speed;
60290260d57SNélio Laranjeiro 	sc = ecmd->link_mode_masks[0] |
60390260d57SNélio Laranjeiro 		((uint64_t)ecmd->link_mode_masks[1] << 32);
60418840871SNélio Laranjeiro 	priv->link_speed_capa = 0;
605b113cb5eSEdward Makarov 	if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
60618840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
607b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
608b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
60918840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
610b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
611b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
612b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
61318840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
614b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
615b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
61618840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_20G;
617b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
618b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
619b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
620b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
62118840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
622b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
623b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
624b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
625b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
62618840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_56G;
627b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
628b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
629b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
63018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_25G;
631b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
632b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
63318840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_50G;
634b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
635b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
636b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
637b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
63818840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_100G;
63990260d57SNélio Laranjeiro 	dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
64018840871SNélio Laranjeiro 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
64118840871SNélio Laranjeiro 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
64218840871SNélio Laranjeiro 				  ETH_LINK_SPEED_FIXED);
643*cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
644*cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
645a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
646a6d83b6aSNélio Laranjeiro 		return -rte_errno;
64718840871SNélio Laranjeiro 	}
648*cfee9475SNélio Laranjeiro 	*link = dev_link;
649*cfee9475SNélio Laranjeiro 	return 0;
650*cfee9475SNélio Laranjeiro }
65118840871SNélio Laranjeiro 
65218840871SNélio Laranjeiro /**
653cb8faed7SAdrien Mazarguil  * DPDK callback to retrieve physical link information.
654cb8faed7SAdrien Mazarguil  *
655cb8faed7SAdrien Mazarguil  * @param dev
656cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
657cb8faed7SAdrien Mazarguil  * @param wait_to_complete
658*cfee9475SNélio Laranjeiro  *   Wait for request completion.
659fb732b0aSNélio Laranjeiro  *
660fb732b0aSNélio Laranjeiro  * @return
661*cfee9475SNélio Laranjeiro  *   0 if link status was not updated, positive if it was, a negative errno
662*cfee9475SNélio Laranjeiro  *   value otherwise and rte_errno is set.
663cb8faed7SAdrien Mazarguil  */
664cb8faed7SAdrien Mazarguil int
665*cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
666cb8faed7SAdrien Mazarguil {
667c7bf6225SYongseok Koh 	int ret;
668*cfee9475SNélio Laranjeiro 	struct rte_eth_link dev_link;
669*cfee9475SNélio Laranjeiro 	time_t start_time = time(NULL);
670cb8faed7SAdrien Mazarguil 
671*cfee9475SNélio Laranjeiro 	do {
672*cfee9475SNélio Laranjeiro 		ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
673a6d83b6aSNélio Laranjeiro 		if (ret)
674*cfee9475SNélio Laranjeiro 			ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
675*cfee9475SNélio Laranjeiro 		if (ret == 0)
676*cfee9475SNélio Laranjeiro 			break;
677*cfee9475SNélio Laranjeiro 		/* Handle wait to complete situation. */
678*cfee9475SNélio Laranjeiro 		if (wait_to_complete && ret == -EAGAIN) {
679*cfee9475SNélio Laranjeiro 			if (abs((int)difftime(time(NULL), start_time)) <
680*cfee9475SNélio Laranjeiro 			    MLX5_LINK_STATUS_TIMEOUT) {
681*cfee9475SNélio Laranjeiro 				usleep(0);
682*cfee9475SNélio Laranjeiro 				continue;
683*cfee9475SNélio Laranjeiro 			} else {
684*cfee9475SNélio Laranjeiro 				rte_errno = EBUSY;
685*cfee9475SNélio Laranjeiro 				return -rte_errno;
686*cfee9475SNélio Laranjeiro 			}
687*cfee9475SNélio Laranjeiro 		} else if (ret < 0) {
688*cfee9475SNélio Laranjeiro 			return ret;
689*cfee9475SNélio Laranjeiro 		}
690*cfee9475SNélio Laranjeiro 	} while (wait_to_complete);
691*cfee9475SNélio Laranjeiro 	ret = !!memcmp(&dev->data->dev_link, &dev_link,
692*cfee9475SNélio Laranjeiro 		       sizeof(struct rte_eth_link));
693*cfee9475SNélio Laranjeiro 	dev->data->dev_link = dev_link;
694*cfee9475SNélio Laranjeiro 	return ret;
695cb8faed7SAdrien Mazarguil }
696cb8faed7SAdrien Mazarguil 
697cb8faed7SAdrien Mazarguil /**
698cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
699cf37ca95SAdrien Mazarguil  *
700cf37ca95SAdrien Mazarguil  * @param dev
701cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
702cf37ca95SAdrien Mazarguil  * @param in_mtu
703cf37ca95SAdrien Mazarguil  *   New MTU.
704cf37ca95SAdrien Mazarguil  *
705cf37ca95SAdrien Mazarguil  * @return
706a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
707cf37ca95SAdrien Mazarguil  */
708cf37ca95SAdrien Mazarguil int
709cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
710cf37ca95SAdrien Mazarguil {
711cf37ca95SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
712a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
713a6d83b6aSNélio Laranjeiro 	int ret;
714cf37ca95SAdrien Mazarguil 
715af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
716a0edafe4SNelio Laranjeiro 	if (ret)
717a6d83b6aSNélio Laranjeiro 		return ret;
718cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
719af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
720a0edafe4SNelio Laranjeiro 	if (ret)
721a6d83b6aSNélio Laranjeiro 		return ret;
722af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
723a0edafe4SNelio Laranjeiro 	if (ret)
724a6d83b6aSNélio Laranjeiro 		return ret;
725a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
726a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
727a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
728a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
729a0edafe4SNelio Laranjeiro 		return 0;
730a6d83b6aSNélio Laranjeiro 	}
731a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
732a6d83b6aSNélio Laranjeiro 	return -rte_errno;
733cf37ca95SAdrien Mazarguil }
734cf37ca95SAdrien Mazarguil 
735cf37ca95SAdrien Mazarguil /**
73602d75430SAdrien Mazarguil  * DPDK callback to get flow control status.
73702d75430SAdrien Mazarguil  *
73802d75430SAdrien Mazarguil  * @param dev
73902d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
74002d75430SAdrien Mazarguil  * @param[out] fc_conf
74102d75430SAdrien Mazarguil  *   Flow control output buffer.
74202d75430SAdrien Mazarguil  *
74302d75430SAdrien Mazarguil  * @return
744a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
74502d75430SAdrien Mazarguil  */
74602d75430SAdrien Mazarguil int
74702d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
74802d75430SAdrien Mazarguil {
74902d75430SAdrien Mazarguil 	struct ifreq ifr;
75002d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
75102d75430SAdrien Mazarguil 		.cmd = ETHTOOL_GPAUSEPARAM
75202d75430SAdrien Mazarguil 	};
75302d75430SAdrien Mazarguil 	int ret;
75402d75430SAdrien Mazarguil 
755d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
756a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
757a6d83b6aSNélio Laranjeiro 	if (ret) {
758a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
759a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
760a170a30dSNélio Laranjeiro 			" %s",
761a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
762a6d83b6aSNélio Laranjeiro 		return ret;
76302d75430SAdrien Mazarguil 	}
76402d75430SAdrien Mazarguil 	fc_conf->autoneg = ethpause.autoneg;
76502d75430SAdrien Mazarguil 	if (ethpause.rx_pause && ethpause.tx_pause)
76602d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_FULL;
76702d75430SAdrien Mazarguil 	else if (ethpause.rx_pause)
76802d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_RX_PAUSE;
76902d75430SAdrien Mazarguil 	else if (ethpause.tx_pause)
77002d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_TX_PAUSE;
77102d75430SAdrien Mazarguil 	else
77202d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_NONE;
773a6d83b6aSNélio Laranjeiro 	return 0;
77402d75430SAdrien Mazarguil }
77502d75430SAdrien Mazarguil 
77602d75430SAdrien Mazarguil /**
77702d75430SAdrien Mazarguil  * DPDK callback to modify flow control parameters.
77802d75430SAdrien Mazarguil  *
77902d75430SAdrien Mazarguil  * @param dev
78002d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
78102d75430SAdrien Mazarguil  * @param[in] fc_conf
78202d75430SAdrien Mazarguil  *   Flow control parameters.
78302d75430SAdrien Mazarguil  *
78402d75430SAdrien Mazarguil  * @return
785a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
78602d75430SAdrien Mazarguil  */
78702d75430SAdrien Mazarguil int
78802d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
78902d75430SAdrien Mazarguil {
79002d75430SAdrien Mazarguil 	struct ifreq ifr;
79102d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
79202d75430SAdrien Mazarguil 		.cmd = ETHTOOL_SPAUSEPARAM
79302d75430SAdrien Mazarguil 	};
79402d75430SAdrien Mazarguil 	int ret;
79502d75430SAdrien Mazarguil 
796d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
79702d75430SAdrien Mazarguil 	ethpause.autoneg = fc_conf->autoneg;
79802d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
79902d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_RX_PAUSE))
80002d75430SAdrien Mazarguil 		ethpause.rx_pause = 1;
80102d75430SAdrien Mazarguil 	else
80202d75430SAdrien Mazarguil 		ethpause.rx_pause = 0;
80302d75430SAdrien Mazarguil 
80402d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
80502d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_TX_PAUSE))
80602d75430SAdrien Mazarguil 		ethpause.tx_pause = 1;
80702d75430SAdrien Mazarguil 	else
80802d75430SAdrien Mazarguil 		ethpause.tx_pause = 0;
809a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
810a6d83b6aSNélio Laranjeiro 	if (ret) {
811a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
812a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
813a170a30dSNélio Laranjeiro 			" failed: %s",
814a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
815a6d83b6aSNélio Laranjeiro 		return ret;
81602d75430SAdrien Mazarguil 	}
817a6d83b6aSNélio Laranjeiro 	return 0;
81802d75430SAdrien Mazarguil }
81902d75430SAdrien Mazarguil 
82002d75430SAdrien Mazarguil /**
821771fa900SAdrien Mazarguil  * Get PCI information from struct ibv_device.
822771fa900SAdrien Mazarguil  *
823771fa900SAdrien Mazarguil  * @param device
824771fa900SAdrien Mazarguil  *   Pointer to Ethernet device structure.
825771fa900SAdrien Mazarguil  * @param[out] pci_addr
826771fa900SAdrien Mazarguil  *   PCI bus address output buffer.
827771fa900SAdrien Mazarguil  *
828771fa900SAdrien Mazarguil  * @return
829a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
830771fa900SAdrien Mazarguil  */
831771fa900SAdrien Mazarguil int
832771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
833771fa900SAdrien Mazarguil 			    struct rte_pci_addr *pci_addr)
834771fa900SAdrien Mazarguil {
835771fa900SAdrien Mazarguil 	FILE *file;
836771fa900SAdrien Mazarguil 	char line[32];
837771fa900SAdrien Mazarguil 	MKSTR(path, "%s/device/uevent", device->ibdev_path);
838771fa900SAdrien Mazarguil 
839771fa900SAdrien Mazarguil 	file = fopen(path, "rb");
840a6d83b6aSNélio Laranjeiro 	if (file == NULL) {
841a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
842a6d83b6aSNélio Laranjeiro 		return -rte_errno;
843a6d83b6aSNélio Laranjeiro 	}
844771fa900SAdrien Mazarguil 	while (fgets(line, sizeof(line), file) == line) {
845771fa900SAdrien Mazarguil 		size_t len = strlen(line);
846771fa900SAdrien Mazarguil 		int ret;
847771fa900SAdrien Mazarguil 
848771fa900SAdrien Mazarguil 		/* Truncate long lines. */
849771fa900SAdrien Mazarguil 		if (len == (sizeof(line) - 1))
850771fa900SAdrien Mazarguil 			while (line[(len - 1)] != '\n') {
851771fa900SAdrien Mazarguil 				ret = fgetc(file);
852771fa900SAdrien Mazarguil 				if (ret == EOF)
853771fa900SAdrien Mazarguil 					break;
854771fa900SAdrien Mazarguil 				line[(len - 1)] = ret;
855771fa900SAdrien Mazarguil 			}
856771fa900SAdrien Mazarguil 		/* Extract information. */
857771fa900SAdrien Mazarguil 		if (sscanf(line,
858771fa900SAdrien Mazarguil 			   "PCI_SLOT_NAME="
859463ced95SStephen Hemminger 			   "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
860771fa900SAdrien Mazarguil 			   &pci_addr->domain,
861771fa900SAdrien Mazarguil 			   &pci_addr->bus,
862771fa900SAdrien Mazarguil 			   &pci_addr->devid,
863771fa900SAdrien Mazarguil 			   &pci_addr->function) == 4) {
864771fa900SAdrien Mazarguil 			ret = 0;
865771fa900SAdrien Mazarguil 			break;
866771fa900SAdrien Mazarguil 		}
867771fa900SAdrien Mazarguil 	}
868771fa900SAdrien Mazarguil 	fclose(file);
869771fa900SAdrien Mazarguil 	return 0;
870771fa900SAdrien Mazarguil }
871198a3c33SNelio Laranjeiro 
872198a3c33SNelio Laranjeiro /**
873c26ae069SMatan Azrad  * Device status handler.
874c26ae069SMatan Azrad  *
875af4f09f2SNélio Laranjeiro  * @param dev
876af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
877c26ae069SMatan Azrad  * @param events
878c26ae069SMatan Azrad  *   Pointer to event flags holder.
879c26ae069SMatan Azrad  *
880c26ae069SMatan Azrad  * @return
881c26ae069SMatan Azrad  *   Events bitmap of callback process which can be called immediately.
882c26ae069SMatan Azrad  */
883c26ae069SMatan Azrad static uint32_t
884af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev)
885198a3c33SNelio Laranjeiro {
886af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
887198a3c33SNelio Laranjeiro 	struct ibv_async_event event;
888c26ae069SMatan Azrad 	uint32_t ret = 0;
889198a3c33SNelio Laranjeiro 
890*cfee9475SNélio Laranjeiro 	if (mlx5_link_update(dev, 0) == -EAGAIN) {
891*cfee9475SNélio Laranjeiro 		usleep(0);
892*cfee9475SNélio Laranjeiro 		return 0;
893*cfee9475SNélio Laranjeiro 	}
894198a3c33SNelio Laranjeiro 	/* Read all message and acknowledge them. */
895198a3c33SNelio Laranjeiro 	for (;;) {
8960e83b8e5SNelio Laranjeiro 		if (mlx5_glue->get_async_event(priv->ctx, &event))
897198a3c33SNelio Laranjeiro 			break;
898c26ae069SMatan Azrad 		if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
899c26ae069SMatan Azrad 			event.event_type == IBV_EVENT_PORT_ERR) &&
900af4f09f2SNélio Laranjeiro 			(dev->data->dev_conf.intr_conf.lsc == 1))
901c26ae069SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
9027d7d7ad1SMatan Azrad 		else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
903af4f09f2SNélio Laranjeiro 			dev->data->dev_conf.intr_conf.rmv == 1)
9047d7d7ad1SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
905c26ae069SMatan Azrad 		else
906a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
907a170a30dSNélio Laranjeiro 				"port %u event type %d on not handled",
9080f99970bSNélio Laranjeiro 				dev->data->port_id, event.event_type);
9090e83b8e5SNelio Laranjeiro 		mlx5_glue->ack_async_event(&event);
910198a3c33SNelio Laranjeiro 	}
911198a3c33SNelio Laranjeiro 	return ret;
912198a3c33SNelio Laranjeiro }
913198a3c33SNelio Laranjeiro 
914198a3c33SNelio Laranjeiro /**
915198a3c33SNelio Laranjeiro  * Handle interrupts from the NIC.
916198a3c33SNelio Laranjeiro  *
917198a3c33SNelio Laranjeiro  * @param[in] intr_handle
918198a3c33SNelio Laranjeiro  *   Interrupt handler.
919198a3c33SNelio Laranjeiro  * @param cb_arg
920198a3c33SNelio Laranjeiro  *   Callback argument.
921198a3c33SNelio Laranjeiro  */
922198a3c33SNelio Laranjeiro void
923c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg)
924198a3c33SNelio Laranjeiro {
925198a3c33SNelio Laranjeiro 	struct rte_eth_dev *dev = cb_arg;
926c26ae069SMatan Azrad 	uint32_t events;
927198a3c33SNelio Laranjeiro 
928af4f09f2SNélio Laranjeiro 	events = mlx5_dev_status_handler(dev);
929c26ae069SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
930cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
9317d7d7ad1SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
932cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
933198a3c33SNelio Laranjeiro }
934198a3c33SNelio Laranjeiro 
935198a3c33SNelio Laranjeiro /**
936f8b9a3baSXueming Li  * Handle interrupts from the socket.
937f8b9a3baSXueming Li  *
938f8b9a3baSXueming Li  * @param cb_arg
939f8b9a3baSXueming Li  *   Callback argument.
940f8b9a3baSXueming Li  */
941f8b9a3baSXueming Li static void
942f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg)
943f8b9a3baSXueming Li {
944f8b9a3baSXueming Li 	struct rte_eth_dev *dev = cb_arg;
945f8b9a3baSXueming Li 
946af4f09f2SNélio Laranjeiro 	mlx5_socket_handle(dev);
947f8b9a3baSXueming Li }
948f8b9a3baSXueming Li 
949f8b9a3baSXueming Li /**
950198a3c33SNelio Laranjeiro  * Uninstall interrupt handler.
951198a3c33SNelio Laranjeiro  *
952198a3c33SNelio Laranjeiro  * @param dev
953af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
954198a3c33SNelio Laranjeiro  */
955198a3c33SNelio Laranjeiro void
956af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
957198a3c33SNelio Laranjeiro {
958af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
959af4f09f2SNélio Laranjeiro 
960f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
961f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv)
962198a3c33SNelio Laranjeiro 		rte_intr_callback_unregister(&priv->intr_handle,
963f8b9a3baSXueming Li 					     mlx5_dev_interrupt_handler, dev);
964f8b9a3baSXueming Li 	if (priv->primary_socket)
965f8b9a3baSXueming Li 		rte_intr_callback_unregister(&priv->intr_handle_socket,
966f8b9a3baSXueming Li 					     mlx5_dev_handler_socket, dev);
967198a3c33SNelio Laranjeiro 	priv->intr_handle.fd = 0;
96836351ea3SFerruh Yigit 	priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
969f8b9a3baSXueming Li 	priv->intr_handle_socket.fd = 0;
970f8b9a3baSXueming Li 	priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
971198a3c33SNelio Laranjeiro }
972198a3c33SNelio Laranjeiro 
973198a3c33SNelio Laranjeiro /**
974198a3c33SNelio Laranjeiro  * Install interrupt handler.
975198a3c33SNelio Laranjeiro  *
976198a3c33SNelio Laranjeiro  * @param dev
977af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
978198a3c33SNelio Laranjeiro  */
979198a3c33SNelio Laranjeiro void
980af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
981198a3c33SNelio Laranjeiro {
982af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
983a6d83b6aSNélio Laranjeiro 	int ret;
984a6d83b6aSNélio Laranjeiro 	int flags;
985198a3c33SNelio Laranjeiro 
986198a3c33SNelio Laranjeiro 	assert(priv->ctx->async_fd > 0);
987198a3c33SNelio Laranjeiro 	flags = fcntl(priv->ctx->async_fd, F_GETFL);
988a6d83b6aSNélio Laranjeiro 	ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
989a6d83b6aSNélio Laranjeiro 	if (ret) {
990a170a30dSNélio Laranjeiro 		DRV_LOG(INFO,
991a170a30dSNélio Laranjeiro 			"port %u failed to change file descriptor async event"
992a170a30dSNélio Laranjeiro 			" queue",
993a170a30dSNélio Laranjeiro 			dev->data->port_id);
994198a3c33SNelio Laranjeiro 		dev->data->dev_conf.intr_conf.lsc = 0;
9957d7d7ad1SMatan Azrad 		dev->data->dev_conf.intr_conf.rmv = 0;
996f8b9a3baSXueming Li 	}
997f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
998f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv) {
999198a3c33SNelio Laranjeiro 		priv->intr_handle.fd = priv->ctx->async_fd;
1000198a3c33SNelio Laranjeiro 		priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
1001198a3c33SNelio Laranjeiro 		rte_intr_callback_register(&priv->intr_handle,
1002f8b9a3baSXueming Li 					   mlx5_dev_interrupt_handler, dev);
1003f8b9a3baSXueming Li 	}
1004a6d83b6aSNélio Laranjeiro 	ret = mlx5_socket_init(dev);
1005a6d83b6aSNélio Laranjeiro 	if (ret)
1006a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot initialise socket: %s",
10070f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
1008a6d83b6aSNélio Laranjeiro 	else if (priv->primary_socket) {
1009f8b9a3baSXueming Li 		priv->intr_handle_socket.fd = priv->primary_socket;
1010f8b9a3baSXueming Li 		priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
1011f8b9a3baSXueming Li 		rte_intr_callback_register(&priv->intr_handle_socket,
1012f8b9a3baSXueming Li 					   mlx5_dev_handler_socket, dev);
1013198a3c33SNelio Laranjeiro 	}
1014198a3c33SNelio Laranjeiro }
101562072098SOr Ami 
101662072098SOr Ami /**
101762072098SOr Ami  * DPDK callback to bring the link DOWN.
101862072098SOr Ami  *
101962072098SOr Ami  * @param dev
102062072098SOr Ami  *   Pointer to Ethernet device structure.
102162072098SOr Ami  *
102262072098SOr Ami  * @return
1023a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
102462072098SOr Ami  */
102562072098SOr Ami int
102662072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev)
102762072098SOr Ami {
1028af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
102962072098SOr Ami }
103062072098SOr Ami 
103162072098SOr Ami /**
103262072098SOr Ami  * DPDK callback to bring the link UP.
103362072098SOr Ami  *
103462072098SOr Ami  * @param dev
103562072098SOr Ami  *   Pointer to Ethernet device structure.
103662072098SOr Ami  *
103762072098SOr Ami  * @return
1038a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
103962072098SOr Ami  */
104062072098SOr Ami int
104162072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev)
104262072098SOr Ami {
1043af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
104462072098SOr Ami }
1045a48deadaSOr Ami 
1046a48deadaSOr Ami /**
1047cdab90cbSNélio Laranjeiro  * Configure the TX function to use.
1048cdab90cbSNélio Laranjeiro  *
1049aee1b165SXueming Li  * @param dev
1050af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
10511cfa649bSShahaf Shuler  *
10521cfa649bSShahaf Shuler  * @return
10531cfa649bSShahaf Shuler  *   Pointer to selected Tx burst function.
1054cdab90cbSNélio Laranjeiro  */
10551cfa649bSShahaf Shuler eth_tx_burst_t
1056af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev)
1057cdab90cbSNélio Laranjeiro {
1058af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
10591cfa649bSShahaf Shuler 	eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst;
10607fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
1061dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
1062dbccb4cdSShahaf Shuler 	int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO |
1063dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
1064dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_GRE_TNL_TSO));
1065dbccb4cdSShahaf Shuler 	int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT);
10661cfa649bSShahaf Shuler 
1067aee1b165SXueming Li 	assert(priv != NULL);
1068230189d9SNélio Laranjeiro 	/* Select appropriate TX function. */
1069dbccb4cdSShahaf Shuler 	if (vlan_insert || tso)
1070dbccb4cdSShahaf Shuler 		return tx_pkt_burst;
10717fe24446SShahaf Shuler 	if (config->mps == MLX5_MPW_ENHANCED) {
1072af4f09f2SNélio Laranjeiro 		if (mlx5_check_vec_tx_support(dev) > 0) {
1073af4f09f2SNélio Laranjeiro 			if (mlx5_check_raw_vec_tx_support(dev) > 0)
10741cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_raw_vec;
10756cb559d6SYongseok Koh 			else
10761cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_vec;
1077a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1078a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx vectorized"
1079a170a30dSNélio Laranjeiro 				" function",
1080a170a30dSNélio Laranjeiro 				dev->data->port_id);
10816cb559d6SYongseok Koh 		} else {
10821cfa649bSShahaf Shuler 			tx_pkt_burst = mlx5_tx_burst_empw;
1083a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1084a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx function",
10850f99970bSNélio Laranjeiro 				dev->data->port_id);
10866cb559d6SYongseok Koh 		}
10877fe24446SShahaf Shuler 	} else if (config->mps && (config->txq_inline > 0)) {
10881cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw_inline;
1089a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW inline Tx function",
10900f99970bSNélio Laranjeiro 			dev->data->port_id);
10917fe24446SShahaf Shuler 	} else if (config->mps) {
10921cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw;
1093a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW Tx function",
1094a170a30dSNélio Laranjeiro 			dev->data->port_id);
10952a66cf37SYaacov Hazan 	}
10961cfa649bSShahaf Shuler 	return tx_pkt_burst;
1097cdab90cbSNélio Laranjeiro }
1098cdab90cbSNélio Laranjeiro 
1099cdab90cbSNélio Laranjeiro /**
1100cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
1101cdab90cbSNélio Laranjeiro  *
1102aee1b165SXueming Li  * @param dev
1103af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
11041cfa649bSShahaf Shuler  *
11051cfa649bSShahaf Shuler  * @return
11061cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
1107cdab90cbSNélio Laranjeiro  */
11081cfa649bSShahaf Shuler eth_rx_burst_t
1109af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
1110cdab90cbSNélio Laranjeiro {
11111cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
11121cfa649bSShahaf Shuler 
1113af4f09f2SNélio Laranjeiro 	assert(dev != NULL);
1114af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
11151cfa649bSShahaf Shuler 		rx_pkt_burst = mlx5_rx_burst_vec;
1116a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected Rx vectorized function",
11170f99970bSNélio Laranjeiro 			dev->data->port_id);
1118cdab90cbSNélio Laranjeiro 	}
11191cfa649bSShahaf Shuler 	return rx_pkt_burst;
11206cb559d6SYongseok Koh }
1121d3e0f392SMatan Azrad 
1122d3e0f392SMatan Azrad /**
1123d3e0f392SMatan Azrad  * Check if mlx5 device was removed.
1124d3e0f392SMatan Azrad  *
1125d3e0f392SMatan Azrad  * @param dev
1126d3e0f392SMatan Azrad  *   Pointer to Ethernet device structure.
1127d3e0f392SMatan Azrad  *
1128d3e0f392SMatan Azrad  * @return
1129d3e0f392SMatan Azrad  *   1 when device is removed, otherwise 0.
1130d3e0f392SMatan Azrad  */
1131d3e0f392SMatan Azrad int
1132d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev)
1133d3e0f392SMatan Azrad {
1134d3e0f392SMatan Azrad 	struct ibv_device_attr device_attr;
1135d3e0f392SMatan Azrad 	struct priv *priv = dev->data->dev_private;
1136d3e0f392SMatan Azrad 
11370e83b8e5SNelio Laranjeiro 	if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO)
1138d3e0f392SMatan Azrad 		return 1;
1139d3e0f392SMatan Azrad 	return 0;
1140d3e0f392SMatan Azrad }
1141