xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision e7041f5529d129eef57d6ac9405a510b1df69ae4)
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>
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>
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)) {
332a1572312SShahaf Shuler 		DRV_LOG(ERR, "port %u RSS key len must be %zu Bytes long",
333a1572312SShahaf Shuler 			dev->data->port_id, rss_hash_default_key_len);
334a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
335a6d83b6aSNélio Laranjeiro 		return -rte_errno;
33629c1d8bbSNélio Laranjeiro 	}
33729c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key =
33829c1d8bbSNélio Laranjeiro 		rte_realloc(priv->rss_conf.rss_key,
33929c1d8bbSNélio Laranjeiro 			    rss_hash_default_key_len, 0);
34029c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
341a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
3420f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
343a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
344a6d83b6aSNélio Laranjeiro 		return -rte_errno;
34529c1d8bbSNélio Laranjeiro 	}
34629c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
34729c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
34829c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
34929c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
35029c1d8bbSNélio Laranjeiro 	       rss_hash_default_key_len);
35129c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key_len = rss_hash_default_key_len;
35229c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
353e60fbd5bSAdrien Mazarguil 	priv->rxqs = (void *)dev->data->rx_queues;
354e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
355e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
356a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
3570f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
358e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
359e60fbd5bSAdrien Mazarguil 	}
3607fe24446SShahaf Shuler 	if (rxqs_n > priv->config.ind_table_max_size) {
361a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
3620f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
363a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
364a6d83b6aSNélio Laranjeiro 		return -rte_errno;
365634efbc2SNelio Laranjeiro 	}
366e60fbd5bSAdrien Mazarguil 	if (rxqs_n == priv->rxqs_n)
367e60fbd5bSAdrien Mazarguil 		return 0;
368a170a30dSNélio Laranjeiro 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
3690f99970bSNélio Laranjeiro 		dev->data->port_id, priv->rxqs_n, rxqs_n);
370e60fbd5bSAdrien Mazarguil 	priv->rxqs_n = rxqs_n;
371634efbc2SNelio Laranjeiro 	/* If the requested number of RX queues is not a power of two, use the
372634efbc2SNelio Laranjeiro 	 * maximum indirection table size for better balancing.
373634efbc2SNelio Laranjeiro 	 * The result is always rounded to the next power of two. */
374634efbc2SNelio Laranjeiro 	reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ?
3757fe24446SShahaf Shuler 				     priv->config.ind_table_max_size :
376634efbc2SNelio Laranjeiro 				     rxqs_n));
377a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
378a6d83b6aSNélio Laranjeiro 	if (ret)
379a6d83b6aSNélio Laranjeiro 		return ret;
380634efbc2SNelio Laranjeiro 	/* When the number of RX queues is not a power of two, the remaining
381634efbc2SNelio Laranjeiro 	 * table entries are padded with reused WQs and hashes are not spread
382634efbc2SNelio Laranjeiro 	 * uniformly. */
383634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
384634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = j;
385634efbc2SNelio Laranjeiro 		if (++j == rxqs_n)
386634efbc2SNelio Laranjeiro 			j = 0;
387634efbc2SNelio Laranjeiro 	}
388e60fbd5bSAdrien Mazarguil 	return 0;
389e60fbd5bSAdrien Mazarguil }
390e60fbd5bSAdrien Mazarguil 
391e60fbd5bSAdrien Mazarguil /**
392e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
393e60fbd5bSAdrien Mazarguil  *
394e60fbd5bSAdrien Mazarguil  * @param dev
395e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
396e60fbd5bSAdrien Mazarguil  * @param[out] info
397e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
398e60fbd5bSAdrien Mazarguil  */
399e60fbd5bSAdrien Mazarguil void
400e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
401e60fbd5bSAdrien Mazarguil {
40201d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
4037fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
404e60fbd5bSAdrien Mazarguil 	unsigned int max;
405e60fbd5bSAdrien Mazarguil 	char ifname[IF_NAMESIZE];
406e60fbd5bSAdrien Mazarguil 
407c0802544SFerruh Yigit 	info->pci_dev = RTE_ETH_DEV_TO_PCI(dev);
408e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
409e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
410e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
411e60fbd5bSAdrien Mazarguil 	/*
412e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
413e60fbd5bSAdrien Mazarguil 	 * between the two values.
414e60fbd5bSAdrien Mazarguil 	 */
41543e9d979SShachar Beiser 	max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
41643e9d979SShachar Beiser 		      priv->device_attr.orig_attr.max_qp);
417e60fbd5bSAdrien Mazarguil 	/* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
418e60fbd5bSAdrien Mazarguil 	if (max >= 65535)
419e60fbd5bSAdrien Mazarguil 		max = 65535;
420e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
421e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
4220497ddaaSYaacov Hazan 	info->max_mac_addrs = RTE_DIM(priv->mac);
423af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
424af4f09f2SNélio Laranjeiro 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
42517b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
426af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
427af4f09f2SNélio Laranjeiro 	if (mlx5_get_ifname(dev, &ifname) == 0)
428e60fbd5bSAdrien Mazarguil 		info->if_index = if_nametoindex(ifname);
429d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
4307fe24446SShahaf Shuler 		priv->reta_idx_n : config->ind_table_max_size;
431*e7041f55SShahaf Shuler 	info->hash_key_size = rss_hash_default_key_len;
43275ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
433b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
434e60fbd5bSAdrien Mazarguil }
435e60fbd5bSAdrien Mazarguil 
436fb732b0aSNélio Laranjeiro /**
437fb732b0aSNélio Laranjeiro  * Get supported packet types.
438fb732b0aSNélio Laranjeiro  *
439fb732b0aSNélio Laranjeiro  * @param dev
440fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
441fb732b0aSNélio Laranjeiro  *
442fb732b0aSNélio Laranjeiro  * @return
443fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
444fb732b0aSNélio Laranjeiro  */
44578a38edfSJianfeng Tan const uint32_t *
44678a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
44778a38edfSJianfeng Tan {
44878a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
44978a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
450ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
451c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
452c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
453ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
454ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
455ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
456ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
457c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
458c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
459ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
460ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
461ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
462ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
46378a38edfSJianfeng Tan 		RTE_PTYPE_UNKNOWN
46478a38edfSJianfeng Tan 	};
46578a38edfSJianfeng Tan 
4666cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
4676cb559d6SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_vec)
46878a38edfSJianfeng Tan 		return ptypes;
46978a38edfSJianfeng Tan 	return NULL;
47078a38edfSJianfeng Tan }
47178a38edfSJianfeng Tan 
472e60fbd5bSAdrien Mazarguil /**
4732c960a51SMatthieu Ternisien d'Ouville  * DPDK callback to retrieve physical link information.
474cb8faed7SAdrien Mazarguil  *
475cb8faed7SAdrien Mazarguil  * @param dev
476cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
477cfee9475SNélio Laranjeiro  * @param[out] link
478cfee9475SNélio Laranjeiro  *   Storage for current link status.
479fb732b0aSNélio Laranjeiro  *
480fb732b0aSNélio Laranjeiro  * @return
481a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
482cb8faed7SAdrien Mazarguil  */
48318840871SNélio Laranjeiro static int
484cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
485cfee9475SNélio Laranjeiro 			       struct rte_eth_link *link)
486cb8faed7SAdrien Mazarguil {
48701d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
488cb8faed7SAdrien Mazarguil 	struct ethtool_cmd edata = {
48975ef62a9SNélio Laranjeiro 		.cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
490cb8faed7SAdrien Mazarguil 	};
491cb8faed7SAdrien Mazarguil 	struct ifreq ifr;
492cb8faed7SAdrien Mazarguil 	struct rte_eth_link dev_link;
493cb8faed7SAdrien Mazarguil 	int link_speed = 0;
494a6d83b6aSNélio Laranjeiro 	int ret;
495cb8faed7SAdrien Mazarguil 
496a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
497a6d83b6aSNélio Laranjeiro 	if (ret) {
498a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
4990f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
500a6d83b6aSNélio Laranjeiro 		return ret;
501cb8faed7SAdrien Mazarguil 	}
502cb8faed7SAdrien Mazarguil 	memset(&dev_link, 0, sizeof(dev_link));
503cb8faed7SAdrien Mazarguil 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
504cb8faed7SAdrien Mazarguil 				(ifr.ifr_flags & IFF_RUNNING));
505d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&edata;
506a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
507a6d83b6aSNélio Laranjeiro 	if (ret) {
508a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
509a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
5100f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
511a6d83b6aSNélio Laranjeiro 		return ret;
512cb8faed7SAdrien Mazarguil 	}
513cb8faed7SAdrien Mazarguil 	link_speed = ethtool_cmd_speed(&edata);
514cb8faed7SAdrien Mazarguil 	if (link_speed == -1)
515cb8faed7SAdrien Mazarguil 		dev_link.link_speed = 0;
516cb8faed7SAdrien Mazarguil 	else
517cb8faed7SAdrien Mazarguil 		dev_link.link_speed = link_speed;
51875ef62a9SNélio Laranjeiro 	priv->link_speed_capa = 0;
51975ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_Autoneg)
52075ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
52175ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_1000baseT_Full |
52275ef62a9SNélio Laranjeiro 			       SUPPORTED_1000baseKX_Full))
52375ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
52475ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_10000baseKR_Full)
52575ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
52675ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_40000baseKR4_Full |
52775ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseCR4_Full |
52875ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseSR4_Full |
52975ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseLR4_Full))
53075ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
531cb8faed7SAdrien Mazarguil 	dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
532cb8faed7SAdrien Mazarguil 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
53382113036SMarc Sune 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
53482113036SMarc Sune 			ETH_LINK_SPEED_FIXED);
535cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
536cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
537a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
538a6d83b6aSNélio Laranjeiro 		return -rte_errno;
539cb8faed7SAdrien Mazarguil 	}
540cfee9475SNélio Laranjeiro 	*link = dev_link;
541cfee9475SNélio Laranjeiro 	return 0;
542cfee9475SNélio Laranjeiro }
543cb8faed7SAdrien Mazarguil 
544cb8faed7SAdrien Mazarguil /**
5453a49ffe3SShahaf Shuler  * Retrieve physical link information (unlocked version using new ioctl).
54618840871SNélio Laranjeiro  *
54718840871SNélio Laranjeiro  * @param dev
54818840871SNélio Laranjeiro  *   Pointer to Ethernet device structure.
549cfee9475SNélio Laranjeiro  * @param[out] link
550cfee9475SNélio Laranjeiro  *   Storage for current link status.
551fb732b0aSNélio Laranjeiro  *
552fb732b0aSNélio Laranjeiro  * @return
553a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
55418840871SNélio Laranjeiro  */
55518840871SNélio Laranjeiro static int
556cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
557cfee9475SNélio Laranjeiro 			     struct rte_eth_link *link)
558cfee9475SNélio Laranjeiro 
55918840871SNélio Laranjeiro {
56001d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
56137a4406cSNélio Laranjeiro 	struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
56218840871SNélio Laranjeiro 	struct ifreq ifr;
56318840871SNélio Laranjeiro 	struct rte_eth_link dev_link;
56418840871SNélio Laranjeiro 	uint64_t sc;
565a6d83b6aSNélio Laranjeiro 	int ret;
56618840871SNélio Laranjeiro 
567a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
568a6d83b6aSNélio Laranjeiro 	if (ret) {
569a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
5700f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
571a6d83b6aSNélio Laranjeiro 		return ret;
57218840871SNélio Laranjeiro 	}
57318840871SNélio Laranjeiro 	memset(&dev_link, 0, sizeof(dev_link));
57418840871SNélio Laranjeiro 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
57518840871SNélio Laranjeiro 				(ifr.ifr_flags & IFF_RUNNING));
57637a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)&gcmd;
577a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
578a6d83b6aSNélio Laranjeiro 	if (ret) {
579a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
580a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
581a170a30dSNélio Laranjeiro 			" failed: %s",
582a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
583a6d83b6aSNélio Laranjeiro 		return ret;
58418840871SNélio Laranjeiro 	}
58537a4406cSNélio Laranjeiro 	gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
58637a4406cSNélio Laranjeiro 
58737a4406cSNélio Laranjeiro 	alignas(struct ethtool_link_settings)
58837a4406cSNélio Laranjeiro 	uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
58937a4406cSNélio Laranjeiro 		     sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
59037a4406cSNélio Laranjeiro 	struct ethtool_link_settings *ecmd = (void *)data;
59137a4406cSNélio Laranjeiro 
59237a4406cSNélio Laranjeiro 	*ecmd = gcmd;
59337a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)ecmd;
594a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
595a6d83b6aSNélio Laranjeiro 	if (ret) {
596a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
597a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
598a170a30dSNélio Laranjeiro 			" failed: %s",
599a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
600a6d83b6aSNélio Laranjeiro 		return ret;
601ef09a7fcSGowrishankar Muthukrishnan 	}
60290260d57SNélio Laranjeiro 	dev_link.link_speed = ecmd->speed;
60390260d57SNélio Laranjeiro 	sc = ecmd->link_mode_masks[0] |
60490260d57SNélio Laranjeiro 		((uint64_t)ecmd->link_mode_masks[1] << 32);
60518840871SNélio Laranjeiro 	priv->link_speed_capa = 0;
606b113cb5eSEdward Makarov 	if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
60718840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
608b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
609b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
61018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
611b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
612b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
613b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
61418840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
615b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
616b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
61718840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_20G;
618b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
619b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
620b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
621b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
62218840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
623b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
624b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
625b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
626b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
62718840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_56G;
628b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
629b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
630b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
63118840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_25G;
632b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
633b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
63418840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_50G;
635b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
636b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
637b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
638b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
63918840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_100G;
64090260d57SNélio Laranjeiro 	dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
64118840871SNélio Laranjeiro 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
64218840871SNélio Laranjeiro 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
64318840871SNélio Laranjeiro 				  ETH_LINK_SPEED_FIXED);
644cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
645cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
646a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
647a6d83b6aSNélio Laranjeiro 		return -rte_errno;
64818840871SNélio Laranjeiro 	}
649cfee9475SNélio Laranjeiro 	*link = dev_link;
650cfee9475SNélio Laranjeiro 	return 0;
651cfee9475SNélio Laranjeiro }
65218840871SNélio Laranjeiro 
65318840871SNélio Laranjeiro /**
654cb8faed7SAdrien Mazarguil  * DPDK callback to retrieve physical link information.
655cb8faed7SAdrien Mazarguil  *
656cb8faed7SAdrien Mazarguil  * @param dev
657cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
658cb8faed7SAdrien Mazarguil  * @param wait_to_complete
659cfee9475SNélio Laranjeiro  *   Wait for request completion.
660fb732b0aSNélio Laranjeiro  *
661fb732b0aSNélio Laranjeiro  * @return
662cfee9475SNélio Laranjeiro  *   0 if link status was not updated, positive if it was, a negative errno
663cfee9475SNélio Laranjeiro  *   value otherwise and rte_errno is set.
664cb8faed7SAdrien Mazarguil  */
665cb8faed7SAdrien Mazarguil int
666cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
667cb8faed7SAdrien Mazarguil {
668c7bf6225SYongseok Koh 	int ret;
669cfee9475SNélio Laranjeiro 	struct rte_eth_link dev_link;
670cfee9475SNélio Laranjeiro 	time_t start_time = time(NULL);
671cb8faed7SAdrien Mazarguil 
672cfee9475SNélio Laranjeiro 	do {
673cfee9475SNélio Laranjeiro 		ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
674a6d83b6aSNélio Laranjeiro 		if (ret)
675cfee9475SNélio Laranjeiro 			ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
676cfee9475SNélio Laranjeiro 		if (ret == 0)
677cfee9475SNélio Laranjeiro 			break;
678cfee9475SNélio Laranjeiro 		/* Handle wait to complete situation. */
679cfee9475SNélio Laranjeiro 		if (wait_to_complete && ret == -EAGAIN) {
680cfee9475SNélio Laranjeiro 			if (abs((int)difftime(time(NULL), start_time)) <
681cfee9475SNélio Laranjeiro 			    MLX5_LINK_STATUS_TIMEOUT) {
682cfee9475SNélio Laranjeiro 				usleep(0);
683cfee9475SNélio Laranjeiro 				continue;
684cfee9475SNélio Laranjeiro 			} else {
685cfee9475SNélio Laranjeiro 				rte_errno = EBUSY;
686cfee9475SNélio Laranjeiro 				return -rte_errno;
687cfee9475SNélio Laranjeiro 			}
688cfee9475SNélio Laranjeiro 		} else if (ret < 0) {
689cfee9475SNélio Laranjeiro 			return ret;
690cfee9475SNélio Laranjeiro 		}
691cfee9475SNélio Laranjeiro 	} while (wait_to_complete);
692cfee9475SNélio Laranjeiro 	ret = !!memcmp(&dev->data->dev_link, &dev_link,
693cfee9475SNélio Laranjeiro 		       sizeof(struct rte_eth_link));
694cfee9475SNélio Laranjeiro 	dev->data->dev_link = dev_link;
695cfee9475SNélio Laranjeiro 	return ret;
696cb8faed7SAdrien Mazarguil }
697cb8faed7SAdrien Mazarguil 
698cb8faed7SAdrien Mazarguil /**
699cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
700cf37ca95SAdrien Mazarguil  *
701cf37ca95SAdrien Mazarguil  * @param dev
702cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
703cf37ca95SAdrien Mazarguil  * @param in_mtu
704cf37ca95SAdrien Mazarguil  *   New MTU.
705cf37ca95SAdrien Mazarguil  *
706cf37ca95SAdrien Mazarguil  * @return
707a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
708cf37ca95SAdrien Mazarguil  */
709cf37ca95SAdrien Mazarguil int
710cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
711cf37ca95SAdrien Mazarguil {
712cf37ca95SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
713a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
714a6d83b6aSNélio Laranjeiro 	int ret;
715cf37ca95SAdrien Mazarguil 
716af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
717a0edafe4SNelio Laranjeiro 	if (ret)
718a6d83b6aSNélio Laranjeiro 		return ret;
719cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
720af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
721a0edafe4SNelio Laranjeiro 	if (ret)
722a6d83b6aSNélio Laranjeiro 		return ret;
723af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
724a0edafe4SNelio Laranjeiro 	if (ret)
725a6d83b6aSNélio Laranjeiro 		return ret;
726a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
727a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
728a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
729a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
730a0edafe4SNelio Laranjeiro 		return 0;
731a6d83b6aSNélio Laranjeiro 	}
732a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
733a6d83b6aSNélio Laranjeiro 	return -rte_errno;
734cf37ca95SAdrien Mazarguil }
735cf37ca95SAdrien Mazarguil 
736cf37ca95SAdrien Mazarguil /**
73702d75430SAdrien Mazarguil  * DPDK callback to get flow control status.
73802d75430SAdrien Mazarguil  *
73902d75430SAdrien Mazarguil  * @param dev
74002d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
74102d75430SAdrien Mazarguil  * @param[out] fc_conf
74202d75430SAdrien Mazarguil  *   Flow control output buffer.
74302d75430SAdrien Mazarguil  *
74402d75430SAdrien Mazarguil  * @return
745a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
74602d75430SAdrien Mazarguil  */
74702d75430SAdrien Mazarguil int
74802d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
74902d75430SAdrien Mazarguil {
75002d75430SAdrien Mazarguil 	struct ifreq ifr;
75102d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
75202d75430SAdrien Mazarguil 		.cmd = ETHTOOL_GPAUSEPARAM
75302d75430SAdrien Mazarguil 	};
75402d75430SAdrien Mazarguil 	int ret;
75502d75430SAdrien Mazarguil 
756d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
757a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
758a6d83b6aSNélio Laranjeiro 	if (ret) {
759a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
760a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
761a170a30dSNélio Laranjeiro 			" %s",
762a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
763a6d83b6aSNélio Laranjeiro 		return ret;
76402d75430SAdrien Mazarguil 	}
76502d75430SAdrien Mazarguil 	fc_conf->autoneg = ethpause.autoneg;
76602d75430SAdrien Mazarguil 	if (ethpause.rx_pause && ethpause.tx_pause)
76702d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_FULL;
76802d75430SAdrien Mazarguil 	else if (ethpause.rx_pause)
76902d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_RX_PAUSE;
77002d75430SAdrien Mazarguil 	else if (ethpause.tx_pause)
77102d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_TX_PAUSE;
77202d75430SAdrien Mazarguil 	else
77302d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_NONE;
774a6d83b6aSNélio Laranjeiro 	return 0;
77502d75430SAdrien Mazarguil }
77602d75430SAdrien Mazarguil 
77702d75430SAdrien Mazarguil /**
77802d75430SAdrien Mazarguil  * DPDK callback to modify flow control parameters.
77902d75430SAdrien Mazarguil  *
78002d75430SAdrien Mazarguil  * @param dev
78102d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
78202d75430SAdrien Mazarguil  * @param[in] fc_conf
78302d75430SAdrien Mazarguil  *   Flow control parameters.
78402d75430SAdrien Mazarguil  *
78502d75430SAdrien Mazarguil  * @return
786a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
78702d75430SAdrien Mazarguil  */
78802d75430SAdrien Mazarguil int
78902d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
79002d75430SAdrien Mazarguil {
79102d75430SAdrien Mazarguil 	struct ifreq ifr;
79202d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
79302d75430SAdrien Mazarguil 		.cmd = ETHTOOL_SPAUSEPARAM
79402d75430SAdrien Mazarguil 	};
79502d75430SAdrien Mazarguil 	int ret;
79602d75430SAdrien Mazarguil 
797d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
79802d75430SAdrien Mazarguil 	ethpause.autoneg = fc_conf->autoneg;
79902d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
80002d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_RX_PAUSE))
80102d75430SAdrien Mazarguil 		ethpause.rx_pause = 1;
80202d75430SAdrien Mazarguil 	else
80302d75430SAdrien Mazarguil 		ethpause.rx_pause = 0;
80402d75430SAdrien Mazarguil 
80502d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
80602d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_TX_PAUSE))
80702d75430SAdrien Mazarguil 		ethpause.tx_pause = 1;
80802d75430SAdrien Mazarguil 	else
80902d75430SAdrien Mazarguil 		ethpause.tx_pause = 0;
810a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
811a6d83b6aSNélio Laranjeiro 	if (ret) {
812a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
813a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
814a170a30dSNélio Laranjeiro 			" failed: %s",
815a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
816a6d83b6aSNélio Laranjeiro 		return ret;
81702d75430SAdrien Mazarguil 	}
818a6d83b6aSNélio Laranjeiro 	return 0;
81902d75430SAdrien Mazarguil }
82002d75430SAdrien Mazarguil 
82102d75430SAdrien Mazarguil /**
822771fa900SAdrien Mazarguil  * Get PCI information from struct ibv_device.
823771fa900SAdrien Mazarguil  *
824771fa900SAdrien Mazarguil  * @param device
825771fa900SAdrien Mazarguil  *   Pointer to Ethernet device structure.
826771fa900SAdrien Mazarguil  * @param[out] pci_addr
827771fa900SAdrien Mazarguil  *   PCI bus address output buffer.
828771fa900SAdrien Mazarguil  *
829771fa900SAdrien Mazarguil  * @return
830a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
831771fa900SAdrien Mazarguil  */
832771fa900SAdrien Mazarguil int
833771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
834771fa900SAdrien Mazarguil 			    struct rte_pci_addr *pci_addr)
835771fa900SAdrien Mazarguil {
836771fa900SAdrien Mazarguil 	FILE *file;
837771fa900SAdrien Mazarguil 	char line[32];
838771fa900SAdrien Mazarguil 	MKSTR(path, "%s/device/uevent", device->ibdev_path);
839771fa900SAdrien Mazarguil 
840771fa900SAdrien Mazarguil 	file = fopen(path, "rb");
841a6d83b6aSNélio Laranjeiro 	if (file == NULL) {
842a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
843a6d83b6aSNélio Laranjeiro 		return -rte_errno;
844a6d83b6aSNélio Laranjeiro 	}
845771fa900SAdrien Mazarguil 	while (fgets(line, sizeof(line), file) == line) {
846771fa900SAdrien Mazarguil 		size_t len = strlen(line);
847771fa900SAdrien Mazarguil 		int ret;
848771fa900SAdrien Mazarguil 
849771fa900SAdrien Mazarguil 		/* Truncate long lines. */
850771fa900SAdrien Mazarguil 		if (len == (sizeof(line) - 1))
851771fa900SAdrien Mazarguil 			while (line[(len - 1)] != '\n') {
852771fa900SAdrien Mazarguil 				ret = fgetc(file);
853771fa900SAdrien Mazarguil 				if (ret == EOF)
854771fa900SAdrien Mazarguil 					break;
855771fa900SAdrien Mazarguil 				line[(len - 1)] = ret;
856771fa900SAdrien Mazarguil 			}
857771fa900SAdrien Mazarguil 		/* Extract information. */
858771fa900SAdrien Mazarguil 		if (sscanf(line,
859771fa900SAdrien Mazarguil 			   "PCI_SLOT_NAME="
860463ced95SStephen Hemminger 			   "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
861771fa900SAdrien Mazarguil 			   &pci_addr->domain,
862771fa900SAdrien Mazarguil 			   &pci_addr->bus,
863771fa900SAdrien Mazarguil 			   &pci_addr->devid,
864771fa900SAdrien Mazarguil 			   &pci_addr->function) == 4) {
865771fa900SAdrien Mazarguil 			ret = 0;
866771fa900SAdrien Mazarguil 			break;
867771fa900SAdrien Mazarguil 		}
868771fa900SAdrien Mazarguil 	}
869771fa900SAdrien Mazarguil 	fclose(file);
870771fa900SAdrien Mazarguil 	return 0;
871771fa900SAdrien Mazarguil }
872198a3c33SNelio Laranjeiro 
873198a3c33SNelio Laranjeiro /**
874c26ae069SMatan Azrad  * Device status handler.
875c26ae069SMatan Azrad  *
876af4f09f2SNélio Laranjeiro  * @param dev
877af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
878c26ae069SMatan Azrad  * @param events
879c26ae069SMatan Azrad  *   Pointer to event flags holder.
880c26ae069SMatan Azrad  *
881c26ae069SMatan Azrad  * @return
882c26ae069SMatan Azrad  *   Events bitmap of callback process which can be called immediately.
883c26ae069SMatan Azrad  */
884c26ae069SMatan Azrad static uint32_t
885af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev)
886198a3c33SNelio Laranjeiro {
887af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
888198a3c33SNelio Laranjeiro 	struct ibv_async_event event;
889c26ae069SMatan Azrad 	uint32_t ret = 0;
890198a3c33SNelio Laranjeiro 
891cfee9475SNélio Laranjeiro 	if (mlx5_link_update(dev, 0) == -EAGAIN) {
892cfee9475SNélio Laranjeiro 		usleep(0);
893cfee9475SNélio Laranjeiro 		return 0;
894cfee9475SNélio Laranjeiro 	}
895198a3c33SNelio Laranjeiro 	/* Read all message and acknowledge them. */
896198a3c33SNelio Laranjeiro 	for (;;) {
8970e83b8e5SNelio Laranjeiro 		if (mlx5_glue->get_async_event(priv->ctx, &event))
898198a3c33SNelio Laranjeiro 			break;
899c26ae069SMatan Azrad 		if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
900c26ae069SMatan Azrad 			event.event_type == IBV_EVENT_PORT_ERR) &&
901af4f09f2SNélio Laranjeiro 			(dev->data->dev_conf.intr_conf.lsc == 1))
902c26ae069SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
9037d7d7ad1SMatan Azrad 		else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
904af4f09f2SNélio Laranjeiro 			dev->data->dev_conf.intr_conf.rmv == 1)
9057d7d7ad1SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
906c26ae069SMatan Azrad 		else
907a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
908a170a30dSNélio Laranjeiro 				"port %u event type %d on not handled",
9090f99970bSNélio Laranjeiro 				dev->data->port_id, event.event_type);
9100e83b8e5SNelio Laranjeiro 		mlx5_glue->ack_async_event(&event);
911198a3c33SNelio Laranjeiro 	}
912198a3c33SNelio Laranjeiro 	return ret;
913198a3c33SNelio Laranjeiro }
914198a3c33SNelio Laranjeiro 
915198a3c33SNelio Laranjeiro /**
916198a3c33SNelio Laranjeiro  * Handle interrupts from the NIC.
917198a3c33SNelio Laranjeiro  *
918198a3c33SNelio Laranjeiro  * @param[in] intr_handle
919198a3c33SNelio Laranjeiro  *   Interrupt handler.
920198a3c33SNelio Laranjeiro  * @param cb_arg
921198a3c33SNelio Laranjeiro  *   Callback argument.
922198a3c33SNelio Laranjeiro  */
923198a3c33SNelio Laranjeiro void
924c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg)
925198a3c33SNelio Laranjeiro {
926198a3c33SNelio Laranjeiro 	struct rte_eth_dev *dev = cb_arg;
927c26ae069SMatan Azrad 	uint32_t events;
928198a3c33SNelio Laranjeiro 
929af4f09f2SNélio Laranjeiro 	events = mlx5_dev_status_handler(dev);
930c26ae069SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
931cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
9327d7d7ad1SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
933cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
934198a3c33SNelio Laranjeiro }
935198a3c33SNelio Laranjeiro 
936198a3c33SNelio Laranjeiro /**
937f8b9a3baSXueming Li  * Handle interrupts from the socket.
938f8b9a3baSXueming Li  *
939f8b9a3baSXueming Li  * @param cb_arg
940f8b9a3baSXueming Li  *   Callback argument.
941f8b9a3baSXueming Li  */
942f8b9a3baSXueming Li static void
943f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg)
944f8b9a3baSXueming Li {
945f8b9a3baSXueming Li 	struct rte_eth_dev *dev = cb_arg;
946f8b9a3baSXueming Li 
947af4f09f2SNélio Laranjeiro 	mlx5_socket_handle(dev);
948f8b9a3baSXueming Li }
949f8b9a3baSXueming Li 
950f8b9a3baSXueming Li /**
951198a3c33SNelio Laranjeiro  * Uninstall interrupt handler.
952198a3c33SNelio Laranjeiro  *
953198a3c33SNelio Laranjeiro  * @param dev
954af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
955198a3c33SNelio Laranjeiro  */
956198a3c33SNelio Laranjeiro void
957af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
958198a3c33SNelio Laranjeiro {
959af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
960af4f09f2SNélio Laranjeiro 
961f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
962f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv)
963198a3c33SNelio Laranjeiro 		rte_intr_callback_unregister(&priv->intr_handle,
964f8b9a3baSXueming Li 					     mlx5_dev_interrupt_handler, dev);
965f8b9a3baSXueming Li 	if (priv->primary_socket)
966f8b9a3baSXueming Li 		rte_intr_callback_unregister(&priv->intr_handle_socket,
967f8b9a3baSXueming Li 					     mlx5_dev_handler_socket, dev);
968198a3c33SNelio Laranjeiro 	priv->intr_handle.fd = 0;
96936351ea3SFerruh Yigit 	priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
970f8b9a3baSXueming Li 	priv->intr_handle_socket.fd = 0;
971f8b9a3baSXueming Li 	priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
972198a3c33SNelio Laranjeiro }
973198a3c33SNelio Laranjeiro 
974198a3c33SNelio Laranjeiro /**
975198a3c33SNelio Laranjeiro  * Install interrupt handler.
976198a3c33SNelio Laranjeiro  *
977198a3c33SNelio Laranjeiro  * @param dev
978af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
979198a3c33SNelio Laranjeiro  */
980198a3c33SNelio Laranjeiro void
981af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
982198a3c33SNelio Laranjeiro {
983af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
984a6d83b6aSNélio Laranjeiro 	int ret;
985a6d83b6aSNélio Laranjeiro 	int flags;
986198a3c33SNelio Laranjeiro 
987198a3c33SNelio Laranjeiro 	assert(priv->ctx->async_fd > 0);
988198a3c33SNelio Laranjeiro 	flags = fcntl(priv->ctx->async_fd, F_GETFL);
989a6d83b6aSNélio Laranjeiro 	ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
990a6d83b6aSNélio Laranjeiro 	if (ret) {
991a170a30dSNélio Laranjeiro 		DRV_LOG(INFO,
992a170a30dSNélio Laranjeiro 			"port %u failed to change file descriptor async event"
993a170a30dSNélio Laranjeiro 			" queue",
994a170a30dSNélio Laranjeiro 			dev->data->port_id);
995198a3c33SNelio Laranjeiro 		dev->data->dev_conf.intr_conf.lsc = 0;
9967d7d7ad1SMatan Azrad 		dev->data->dev_conf.intr_conf.rmv = 0;
997f8b9a3baSXueming Li 	}
998f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
999f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv) {
1000198a3c33SNelio Laranjeiro 		priv->intr_handle.fd = priv->ctx->async_fd;
1001198a3c33SNelio Laranjeiro 		priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
1002198a3c33SNelio Laranjeiro 		rte_intr_callback_register(&priv->intr_handle,
1003f8b9a3baSXueming Li 					   mlx5_dev_interrupt_handler, dev);
1004f8b9a3baSXueming Li 	}
1005a6d83b6aSNélio Laranjeiro 	ret = mlx5_socket_init(dev);
1006a6d83b6aSNélio Laranjeiro 	if (ret)
1007a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot initialise socket: %s",
10080f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
1009a6d83b6aSNélio Laranjeiro 	else if (priv->primary_socket) {
1010f8b9a3baSXueming Li 		priv->intr_handle_socket.fd = priv->primary_socket;
1011f8b9a3baSXueming Li 		priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
1012f8b9a3baSXueming Li 		rte_intr_callback_register(&priv->intr_handle_socket,
1013f8b9a3baSXueming Li 					   mlx5_dev_handler_socket, dev);
1014198a3c33SNelio Laranjeiro 	}
1015198a3c33SNelio Laranjeiro }
101662072098SOr Ami 
101762072098SOr Ami /**
101862072098SOr Ami  * DPDK callback to bring the link DOWN.
101962072098SOr Ami  *
102062072098SOr Ami  * @param dev
102162072098SOr Ami  *   Pointer to Ethernet device structure.
102262072098SOr Ami  *
102362072098SOr Ami  * @return
1024a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
102562072098SOr Ami  */
102662072098SOr Ami int
102762072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev)
102862072098SOr Ami {
1029af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
103062072098SOr Ami }
103162072098SOr Ami 
103262072098SOr Ami /**
103362072098SOr Ami  * DPDK callback to bring the link UP.
103462072098SOr Ami  *
103562072098SOr Ami  * @param dev
103662072098SOr Ami  *   Pointer to Ethernet device structure.
103762072098SOr Ami  *
103862072098SOr Ami  * @return
1039a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
104062072098SOr Ami  */
104162072098SOr Ami int
104262072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev)
104362072098SOr Ami {
1044af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
104562072098SOr Ami }
1046a48deadaSOr Ami 
1047a48deadaSOr Ami /**
1048cdab90cbSNélio Laranjeiro  * Configure the TX function to use.
1049cdab90cbSNélio Laranjeiro  *
1050aee1b165SXueming Li  * @param dev
1051af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
10521cfa649bSShahaf Shuler  *
10531cfa649bSShahaf Shuler  * @return
10541cfa649bSShahaf Shuler  *   Pointer to selected Tx burst function.
1055cdab90cbSNélio Laranjeiro  */
10561cfa649bSShahaf Shuler eth_tx_burst_t
1057af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev)
1058cdab90cbSNélio Laranjeiro {
1059af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
10601cfa649bSShahaf Shuler 	eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst;
10617fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
1062dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
1063dbccb4cdSShahaf Shuler 	int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO |
1064dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
1065dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_GRE_TNL_TSO));
1066dbccb4cdSShahaf Shuler 	int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT);
10671cfa649bSShahaf Shuler 
1068aee1b165SXueming Li 	assert(priv != NULL);
1069230189d9SNélio Laranjeiro 	/* Select appropriate TX function. */
1070dbccb4cdSShahaf Shuler 	if (vlan_insert || tso)
1071dbccb4cdSShahaf Shuler 		return tx_pkt_burst;
10727fe24446SShahaf Shuler 	if (config->mps == MLX5_MPW_ENHANCED) {
1073af4f09f2SNélio Laranjeiro 		if (mlx5_check_vec_tx_support(dev) > 0) {
1074af4f09f2SNélio Laranjeiro 			if (mlx5_check_raw_vec_tx_support(dev) > 0)
10751cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_raw_vec;
10766cb559d6SYongseok Koh 			else
10771cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_vec;
1078a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1079a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx vectorized"
1080a170a30dSNélio Laranjeiro 				" function",
1081a170a30dSNélio Laranjeiro 				dev->data->port_id);
10826cb559d6SYongseok Koh 		} else {
10831cfa649bSShahaf Shuler 			tx_pkt_burst = mlx5_tx_burst_empw;
1084a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1085a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx function",
10860f99970bSNélio Laranjeiro 				dev->data->port_id);
10876cb559d6SYongseok Koh 		}
10887fe24446SShahaf Shuler 	} else if (config->mps && (config->txq_inline > 0)) {
10891cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw_inline;
1090a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW inline Tx function",
10910f99970bSNélio Laranjeiro 			dev->data->port_id);
10927fe24446SShahaf Shuler 	} else if (config->mps) {
10931cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw;
1094a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW Tx function",
1095a170a30dSNélio Laranjeiro 			dev->data->port_id);
10962a66cf37SYaacov Hazan 	}
10971cfa649bSShahaf Shuler 	return tx_pkt_burst;
1098cdab90cbSNélio Laranjeiro }
1099cdab90cbSNélio Laranjeiro 
1100cdab90cbSNélio Laranjeiro /**
1101cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
1102cdab90cbSNélio Laranjeiro  *
1103aee1b165SXueming Li  * @param dev
1104af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
11051cfa649bSShahaf Shuler  *
11061cfa649bSShahaf Shuler  * @return
11071cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
1108cdab90cbSNélio Laranjeiro  */
11091cfa649bSShahaf Shuler eth_rx_burst_t
1110af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
1111cdab90cbSNélio Laranjeiro {
11121cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
11131cfa649bSShahaf Shuler 
1114af4f09f2SNélio Laranjeiro 	assert(dev != NULL);
1115af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
11161cfa649bSShahaf Shuler 		rx_pkt_burst = mlx5_rx_burst_vec;
1117a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected Rx vectorized function",
11180f99970bSNélio Laranjeiro 			dev->data->port_id);
1119cdab90cbSNélio Laranjeiro 	}
11201cfa649bSShahaf Shuler 	return rx_pkt_burst;
11216cb559d6SYongseok Koh }
1122d3e0f392SMatan Azrad 
1123d3e0f392SMatan Azrad /**
1124d3e0f392SMatan Azrad  * Check if mlx5 device was removed.
1125d3e0f392SMatan Azrad  *
1126d3e0f392SMatan Azrad  * @param dev
1127d3e0f392SMatan Azrad  *   Pointer to Ethernet device structure.
1128d3e0f392SMatan Azrad  *
1129d3e0f392SMatan Azrad  * @return
1130d3e0f392SMatan Azrad  *   1 when device is removed, otherwise 0.
1131d3e0f392SMatan Azrad  */
1132d3e0f392SMatan Azrad int
1133d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev)
1134d3e0f392SMatan Azrad {
1135d3e0f392SMatan Azrad 	struct ibv_device_attr device_attr;
1136d3e0f392SMatan Azrad 	struct priv *priv = dev->data->dev_private;
1137d3e0f392SMatan Azrad 
11380e83b8e5SNelio Laranjeiro 	if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO)
1139d3e0f392SMatan Azrad 		return 1;
1140d3e0f392SMatan Azrad 	return 0;
1141d3e0f392SMatan Azrad }
1142