xref: /dpdk/drivers/net/mlx5/mlx5_ethdev.c (revision 5feecc57d90b97c579b16d1083ea167f7564530b)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2771fa900SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
3*5feecc57SShahaf Shuler  * Copyright 2015 Mellanox Technologies, Ltd
4771fa900SAdrien Mazarguil  */
5771fa900SAdrien Mazarguil 
6f8b9a3baSXueming Li #define _GNU_SOURCE
7f8b9a3baSXueming Li 
8771fa900SAdrien Mazarguil #include <stddef.h>
9e60fbd5bSAdrien Mazarguil #include <assert.h>
10fc40db99SAdrien Mazarguil #include <inttypes.h>
11771fa900SAdrien Mazarguil #include <unistd.h>
12771fa900SAdrien Mazarguil #include <stdint.h>
13771fa900SAdrien Mazarguil #include <stdio.h>
14771fa900SAdrien Mazarguil #include <string.h>
15771fa900SAdrien Mazarguil #include <stdlib.h>
16771fa900SAdrien Mazarguil #include <errno.h>
17771fa900SAdrien Mazarguil #include <dirent.h>
18771fa900SAdrien Mazarguil #include <net/if.h>
19771fa900SAdrien Mazarguil #include <sys/ioctl.h>
20771fa900SAdrien Mazarguil #include <sys/socket.h>
21771fa900SAdrien Mazarguil #include <netinet/in.h>
22cb8faed7SAdrien Mazarguil #include <linux/ethtool.h>
23cb8faed7SAdrien Mazarguil #include <linux/sockios.h>
24198a3c33SNelio Laranjeiro #include <fcntl.h>
2590260d57SNélio Laranjeiro #include <stdalign.h>
26f8b9a3baSXueming Li #include <sys/un.h>
27cfee9475SNélio Laranjeiro #include <time.h>
28771fa900SAdrien Mazarguil 
29771fa900SAdrien Mazarguil #include <rte_atomic.h>
30ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
31c752998bSGaetan Rivet #include <rte_bus_pci.h>
32771fa900SAdrien Mazarguil #include <rte_mbuf.h>
33771fa900SAdrien Mazarguil #include <rte_common.h>
34198a3c33SNelio Laranjeiro #include <rte_interrupts.h>
35a48deadaSOr Ami #include <rte_malloc.h>
36c022cb40SBruce Richardson #include <rte_string_fns.h>
37771fa900SAdrien Mazarguil 
38771fa900SAdrien Mazarguil #include "mlx5.h"
390e83b8e5SNelio Laranjeiro #include "mlx5_glue.h"
40e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h"
41771fa900SAdrien Mazarguil #include "mlx5_utils.h"
42771fa900SAdrien Mazarguil 
433a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */
443a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS
453a49ffe3SShahaf Shuler struct ethtool_link_settings {
463a49ffe3SShahaf Shuler 	uint32_t cmd;
473a49ffe3SShahaf Shuler 	uint32_t speed;
483a49ffe3SShahaf Shuler 	uint8_t duplex;
493a49ffe3SShahaf Shuler 	uint8_t port;
503a49ffe3SShahaf Shuler 	uint8_t phy_address;
513a49ffe3SShahaf Shuler 	uint8_t autoneg;
523a49ffe3SShahaf Shuler 	uint8_t mdio_support;
533a49ffe3SShahaf Shuler 	uint8_t eth_to_mdix;
543a49ffe3SShahaf Shuler 	uint8_t eth_tp_mdix_ctrl;
553a49ffe3SShahaf Shuler 	int8_t link_mode_masks_nwords;
563a49ffe3SShahaf Shuler 	uint32_t reserved[8];
573a49ffe3SShahaf Shuler 	uint32_t link_mode_masks[];
583a49ffe3SShahaf Shuler };
593a49ffe3SShahaf Shuler 
603a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c
613a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5
623a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6
633a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17
643a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18
653a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19
663a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20
673a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21
683a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22
693a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23
703a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24
713a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25
723a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26
733a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27
743a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28
753a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29
763a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30
773a49ffe3SShahaf Shuler #endif
783a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G
793a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31
803a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32
813a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33
823a49ffe3SShahaf Shuler #endif
833a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G
843a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34
853a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35
863a49ffe3SShahaf Shuler #endif
873a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G
883a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36
893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37
903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38
913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39
923a49ffe3SShahaf Shuler #endif
933a49ffe3SShahaf Shuler 
94771fa900SAdrien Mazarguil /**
95771fa900SAdrien Mazarguil  * Get interface name from private structure.
96771fa900SAdrien Mazarguil  *
97af4f09f2SNélio Laranjeiro  * @param[in] dev
98af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
99771fa900SAdrien Mazarguil  * @param[out] ifname
100771fa900SAdrien Mazarguil  *   Interface name output buffer.
101771fa900SAdrien Mazarguil  *
102771fa900SAdrien Mazarguil  * @return
103a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
104771fa900SAdrien Mazarguil  */
105771fa900SAdrien Mazarguil int
106af4f09f2SNélio Laranjeiro mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
107771fa900SAdrien Mazarguil {
108af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
109771fa900SAdrien Mazarguil 	DIR *dir;
110771fa900SAdrien Mazarguil 	struct dirent *dent;
111771fa900SAdrien Mazarguil 	unsigned int dev_type = 0;
112771fa900SAdrien Mazarguil 	unsigned int dev_port_prev = ~0u;
113771fa900SAdrien Mazarguil 	char match[IF_NAMESIZE] = "";
114771fa900SAdrien Mazarguil 
115771fa900SAdrien Mazarguil 	{
11687ec44ceSXueming Li 		MKSTR(path, "%s/device/net", priv->ibdev_path);
117771fa900SAdrien Mazarguil 
118771fa900SAdrien Mazarguil 		dir = opendir(path);
119a6d83b6aSNélio Laranjeiro 		if (dir == NULL) {
120a6d83b6aSNélio Laranjeiro 			rte_errno = errno;
121a6d83b6aSNélio Laranjeiro 			return -rte_errno;
122a6d83b6aSNélio Laranjeiro 		}
123771fa900SAdrien Mazarguil 	}
124771fa900SAdrien Mazarguil 	while ((dent = readdir(dir)) != NULL) {
125771fa900SAdrien Mazarguil 		char *name = dent->d_name;
126771fa900SAdrien Mazarguil 		FILE *file;
127771fa900SAdrien Mazarguil 		unsigned int dev_port;
128771fa900SAdrien Mazarguil 		int r;
129771fa900SAdrien Mazarguil 
130771fa900SAdrien Mazarguil 		if ((name[0] == '.') &&
131771fa900SAdrien Mazarguil 		    ((name[1] == '\0') ||
132771fa900SAdrien Mazarguil 		     ((name[1] == '.') && (name[2] == '\0'))))
133771fa900SAdrien Mazarguil 			continue;
134771fa900SAdrien Mazarguil 
135771fa900SAdrien Mazarguil 		MKSTR(path, "%s/device/net/%s/%s",
13687ec44ceSXueming Li 		      priv->ibdev_path, name,
137771fa900SAdrien Mazarguil 		      (dev_type ? "dev_id" : "dev_port"));
138771fa900SAdrien Mazarguil 
139771fa900SAdrien Mazarguil 		file = fopen(path, "rb");
140771fa900SAdrien Mazarguil 		if (file == NULL) {
141771fa900SAdrien Mazarguil 			if (errno != ENOENT)
142771fa900SAdrien Mazarguil 				continue;
143771fa900SAdrien Mazarguil 			/*
144771fa900SAdrien Mazarguil 			 * Switch to dev_id when dev_port does not exist as
145771fa900SAdrien Mazarguil 			 * is the case with Linux kernel versions < 3.15.
146771fa900SAdrien Mazarguil 			 */
147771fa900SAdrien Mazarguil try_dev_id:
148771fa900SAdrien Mazarguil 			match[0] = '\0';
149771fa900SAdrien Mazarguil 			if (dev_type)
150771fa900SAdrien Mazarguil 				break;
151771fa900SAdrien Mazarguil 			dev_type = 1;
152771fa900SAdrien Mazarguil 			dev_port_prev = ~0u;
153771fa900SAdrien Mazarguil 			rewinddir(dir);
154771fa900SAdrien Mazarguil 			continue;
155771fa900SAdrien Mazarguil 		}
156771fa900SAdrien Mazarguil 		r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
157771fa900SAdrien Mazarguil 		fclose(file);
158771fa900SAdrien Mazarguil 		if (r != 1)
159771fa900SAdrien Mazarguil 			continue;
160771fa900SAdrien Mazarguil 		/*
161771fa900SAdrien Mazarguil 		 * Switch to dev_id when dev_port returns the same value for
162771fa900SAdrien Mazarguil 		 * all ports. May happen when using a MOFED release older than
163771fa900SAdrien Mazarguil 		 * 3.0 with a Linux kernel >= 3.15.
164771fa900SAdrien Mazarguil 		 */
165771fa900SAdrien Mazarguil 		if (dev_port == dev_port_prev)
166771fa900SAdrien Mazarguil 			goto try_dev_id;
167771fa900SAdrien Mazarguil 		dev_port_prev = dev_port;
168771fa900SAdrien Mazarguil 		if (dev_port == (priv->port - 1u))
169c022cb40SBruce Richardson 			strlcpy(match, name, sizeof(match));
170771fa900SAdrien Mazarguil 	}
171771fa900SAdrien Mazarguil 	closedir(dir);
172a6d83b6aSNélio Laranjeiro 	if (match[0] == '\0') {
173a6d83b6aSNélio Laranjeiro 		rte_errno = ENOENT;
174a6d83b6aSNélio Laranjeiro 		return -rte_errno;
175a6d83b6aSNélio Laranjeiro 	}
176771fa900SAdrien Mazarguil 	strncpy(*ifname, match, sizeof(*ifname));
177771fa900SAdrien Mazarguil 	return 0;
178771fa900SAdrien Mazarguil }
179771fa900SAdrien Mazarguil 
180771fa900SAdrien Mazarguil /**
181771fa900SAdrien Mazarguil  * Perform ifreq ioctl() on associated Ethernet device.
182771fa900SAdrien Mazarguil  *
183af4f09f2SNélio Laranjeiro  * @param[in] dev
184af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
185771fa900SAdrien Mazarguil  * @param req
186771fa900SAdrien Mazarguil  *   Request number to pass to ioctl().
187771fa900SAdrien Mazarguil  * @param[out] ifr
188771fa900SAdrien Mazarguil  *   Interface request structure output buffer.
189771fa900SAdrien Mazarguil  *
190771fa900SAdrien Mazarguil  * @return
191a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
192771fa900SAdrien Mazarguil  */
193771fa900SAdrien Mazarguil int
194af4f09f2SNélio Laranjeiro mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
195771fa900SAdrien Mazarguil {
196771fa900SAdrien Mazarguil 	int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
197a6d83b6aSNélio Laranjeiro 	int ret = 0;
198771fa900SAdrien Mazarguil 
199a6d83b6aSNélio Laranjeiro 	if (sock == -1) {
200a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
201a6d83b6aSNélio Laranjeiro 		return -rte_errno;
202a6d83b6aSNélio Laranjeiro 	}
203a6d83b6aSNélio Laranjeiro 	ret = mlx5_get_ifname(dev, &ifr->ifr_name);
204a6d83b6aSNélio Laranjeiro 	if (ret)
205a6d83b6aSNélio Laranjeiro 		goto error;
206771fa900SAdrien Mazarguil 	ret = ioctl(sock, req, ifr);
207a6d83b6aSNélio Laranjeiro 	if (ret == -1) {
208a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
209a6d83b6aSNélio Laranjeiro 		goto error;
210a6d83b6aSNélio Laranjeiro 	}
211771fa900SAdrien Mazarguil 	close(sock);
212a6d83b6aSNélio Laranjeiro 	return 0;
213a6d83b6aSNélio Laranjeiro error:
214a6d83b6aSNélio Laranjeiro 	close(sock);
215a6d83b6aSNélio Laranjeiro 	return -rte_errno;
216771fa900SAdrien Mazarguil }
217771fa900SAdrien Mazarguil 
218771fa900SAdrien Mazarguil /**
219771fa900SAdrien Mazarguil  * Get device MTU.
220771fa900SAdrien Mazarguil  *
221af4f09f2SNélio Laranjeiro  * @param dev
222af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
223771fa900SAdrien Mazarguil  * @param[out] mtu
224771fa900SAdrien Mazarguil  *   MTU value output buffer.
225771fa900SAdrien Mazarguil  *
226771fa900SAdrien Mazarguil  * @return
227a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
228771fa900SAdrien Mazarguil  */
229771fa900SAdrien Mazarguil int
230af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
231771fa900SAdrien Mazarguil {
232fc40db99SAdrien Mazarguil 	struct ifreq request;
233af4f09f2SNélio Laranjeiro 	int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
234771fa900SAdrien Mazarguil 
235fc40db99SAdrien Mazarguil 	if (ret)
236fc40db99SAdrien Mazarguil 		return ret;
237fc40db99SAdrien Mazarguil 	*mtu = request.ifr_mtu;
238859081d3SShahaf Shuler 	return 0;
239859081d3SShahaf Shuler }
240859081d3SShahaf Shuler 
241859081d3SShahaf Shuler /**
242cf37ca95SAdrien Mazarguil  * Set device MTU.
243cf37ca95SAdrien Mazarguil  *
244af4f09f2SNélio Laranjeiro  * @param dev
245af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
246cf37ca95SAdrien Mazarguil  * @param mtu
247cf37ca95SAdrien Mazarguil  *   MTU value to set.
248cf37ca95SAdrien Mazarguil  *
249cf37ca95SAdrien Mazarguil  * @return
250a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
251cf37ca95SAdrien Mazarguil  */
252cf37ca95SAdrien Mazarguil static int
253af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
254cf37ca95SAdrien Mazarguil {
255fc40db99SAdrien Mazarguil 	struct ifreq request = { .ifr_mtu = mtu, };
256f3b492d7SAdrien Mazarguil 
257af4f09f2SNélio Laranjeiro 	return mlx5_ifreq(dev, SIOCSIFMTU, &request);
258cf37ca95SAdrien Mazarguil }
259cf37ca95SAdrien Mazarguil 
260cf37ca95SAdrien Mazarguil /**
261771fa900SAdrien Mazarguil  * Set device flags.
262771fa900SAdrien Mazarguil  *
263af4f09f2SNélio Laranjeiro  * @param dev
264af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
265771fa900SAdrien Mazarguil  * @param keep
266771fa900SAdrien Mazarguil  *   Bitmask for flags that must remain untouched.
267771fa900SAdrien Mazarguil  * @param flags
268771fa900SAdrien Mazarguil  *   Bitmask for flags to modify.
269771fa900SAdrien Mazarguil  *
270771fa900SAdrien Mazarguil  * @return
271a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
272771fa900SAdrien Mazarguil  */
273771fa900SAdrien Mazarguil int
274af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
275771fa900SAdrien Mazarguil {
276fc40db99SAdrien Mazarguil 	struct ifreq request;
277af4f09f2SNélio Laranjeiro 	int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
278771fa900SAdrien Mazarguil 
279fc40db99SAdrien Mazarguil 	if (ret)
280fc40db99SAdrien Mazarguil 		return ret;
281fc40db99SAdrien Mazarguil 	request.ifr_flags &= keep;
282fc40db99SAdrien Mazarguil 	request.ifr_flags |= flags & ~keep;
283af4f09f2SNélio Laranjeiro 	return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
284771fa900SAdrien Mazarguil }
285771fa900SAdrien Mazarguil 
286771fa900SAdrien Mazarguil /**
2877b2423cdSNélio Laranjeiro  * DPDK callback for Ethernet device configuration.
288e60fbd5bSAdrien Mazarguil  *
289e60fbd5bSAdrien Mazarguil  * @param dev
290e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
291e60fbd5bSAdrien Mazarguil  *
292e60fbd5bSAdrien Mazarguil  * @return
293a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
294e60fbd5bSAdrien Mazarguil  */
2957b2423cdSNélio Laranjeiro int
2967b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev)
297e60fbd5bSAdrien Mazarguil {
298e60fbd5bSAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
299e60fbd5bSAdrien Mazarguil 	unsigned int rxqs_n = dev->data->nb_rx_queues;
300e60fbd5bSAdrien Mazarguil 	unsigned int txqs_n = dev->data->nb_tx_queues;
301634efbc2SNelio Laranjeiro 	unsigned int i;
302634efbc2SNelio Laranjeiro 	unsigned int j;
303634efbc2SNelio Laranjeiro 	unsigned int reta_idx_n;
30429c1d8bbSNélio Laranjeiro 	const uint8_t use_app_rss_key =
30521e3a974SShahaf Shuler 		!!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
306af4f09f2SNélio Laranjeiro 	uint64_t supp_tx_offloads = mlx5_get_tx_port_offloads(dev);
307dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
30817b843ebSShahaf Shuler 	uint64_t supp_rx_offloads =
309af4f09f2SNélio Laranjeiro 		(mlx5_get_rx_port_offloads() |
310af4f09f2SNélio Laranjeiro 		 mlx5_get_rx_queue_offloads(dev));
31117b843ebSShahaf Shuler 	uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
312a6d83b6aSNélio Laranjeiro 	int ret = 0;
313e60fbd5bSAdrien Mazarguil 
314dbccb4cdSShahaf Shuler 	if ((tx_offloads & supp_tx_offloads) != tx_offloads) {
315a170a30dSNélio Laranjeiro 		DRV_LOG(ERR,
316a170a30dSNélio Laranjeiro 			"port %u some Tx offloads are not supported requested"
317a170a30dSNélio Laranjeiro 			" 0x%" PRIx64 " supported 0x%" PRIx64,
3180f99970bSNélio Laranjeiro 			dev->data->port_id, tx_offloads, supp_tx_offloads);
319a6d83b6aSNélio Laranjeiro 		rte_errno = ENOTSUP;
320a6d83b6aSNélio Laranjeiro 		return -rte_errno;
321dbccb4cdSShahaf Shuler 	}
32217b843ebSShahaf Shuler 	if ((rx_offloads & supp_rx_offloads) != rx_offloads) {
323a170a30dSNélio Laranjeiro 		DRV_LOG(ERR,
324a170a30dSNélio Laranjeiro 			"port %u some Rx offloads are not supported requested"
325a170a30dSNélio Laranjeiro 			" 0x%" PRIx64 " supported 0x%" PRIx64,
3260f99970bSNélio Laranjeiro 			dev->data->port_id, rx_offloads, supp_rx_offloads);
327a6d83b6aSNélio Laranjeiro 		rte_errno = ENOTSUP;
328a6d83b6aSNélio Laranjeiro 		return -rte_errno;
32917b843ebSShahaf Shuler 	}
33029c1d8bbSNélio Laranjeiro 	if (use_app_rss_key &&
33129c1d8bbSNélio Laranjeiro 	    (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len !=
33229c1d8bbSNélio Laranjeiro 	     rss_hash_default_key_len)) {
333a1572312SShahaf Shuler 		DRV_LOG(ERR, "port %u RSS key len must be %zu Bytes long",
334a1572312SShahaf Shuler 			dev->data->port_id, rss_hash_default_key_len);
335a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
336a6d83b6aSNélio Laranjeiro 		return -rte_errno;
33729c1d8bbSNélio Laranjeiro 	}
33829c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key =
33929c1d8bbSNélio Laranjeiro 		rte_realloc(priv->rss_conf.rss_key,
34029c1d8bbSNélio Laranjeiro 			    rss_hash_default_key_len, 0);
34129c1d8bbSNélio Laranjeiro 	if (!priv->rss_conf.rss_key) {
342a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
3430f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
344a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
345a6d83b6aSNélio Laranjeiro 		return -rte_errno;
34629c1d8bbSNélio Laranjeiro 	}
34729c1d8bbSNélio Laranjeiro 	memcpy(priv->rss_conf.rss_key,
34829c1d8bbSNélio Laranjeiro 	       use_app_rss_key ?
34929c1d8bbSNélio Laranjeiro 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
35029c1d8bbSNélio Laranjeiro 	       rss_hash_default_key,
35129c1d8bbSNélio Laranjeiro 	       rss_hash_default_key_len);
35229c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_key_len = rss_hash_default_key_len;
35329c1d8bbSNélio Laranjeiro 	priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
354e60fbd5bSAdrien Mazarguil 	priv->rxqs = (void *)dev->data->rx_queues;
355e60fbd5bSAdrien Mazarguil 	priv->txqs = (void *)dev->data->tx_queues;
356e60fbd5bSAdrien Mazarguil 	if (txqs_n != priv->txqs_n) {
357a170a30dSNélio Laranjeiro 		DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u",
3580f99970bSNélio Laranjeiro 			dev->data->port_id, priv->txqs_n, txqs_n);
359e60fbd5bSAdrien Mazarguil 		priv->txqs_n = txqs_n;
360e60fbd5bSAdrien Mazarguil 	}
3617fe24446SShahaf Shuler 	if (rxqs_n > priv->config.ind_table_max_size) {
362a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)",
3630f99970bSNélio Laranjeiro 			dev->data->port_id, rxqs_n);
364a6d83b6aSNélio Laranjeiro 		rte_errno = EINVAL;
365a6d83b6aSNélio Laranjeiro 		return -rte_errno;
366634efbc2SNelio Laranjeiro 	}
367e60fbd5bSAdrien Mazarguil 	if (rxqs_n == priv->rxqs_n)
368e60fbd5bSAdrien Mazarguil 		return 0;
369a170a30dSNélio Laranjeiro 	DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
3700f99970bSNélio Laranjeiro 		dev->data->port_id, priv->rxqs_n, rxqs_n);
371e60fbd5bSAdrien Mazarguil 	priv->rxqs_n = rxqs_n;
372634efbc2SNelio Laranjeiro 	/* If the requested number of RX queues is not a power of two, use the
373634efbc2SNelio Laranjeiro 	 * maximum indirection table size for better balancing.
374634efbc2SNelio Laranjeiro 	 * The result is always rounded to the next power of two. */
375634efbc2SNelio Laranjeiro 	reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ?
3767fe24446SShahaf Shuler 				     priv->config.ind_table_max_size :
377634efbc2SNelio Laranjeiro 				     rxqs_n));
378a6d83b6aSNélio Laranjeiro 	ret = mlx5_rss_reta_index_resize(dev, reta_idx_n);
379a6d83b6aSNélio Laranjeiro 	if (ret)
380a6d83b6aSNélio Laranjeiro 		return ret;
381634efbc2SNelio Laranjeiro 	/* When the number of RX queues is not a power of two, the remaining
382634efbc2SNelio Laranjeiro 	 * table entries are padded with reused WQs and hashes are not spread
383634efbc2SNelio Laranjeiro 	 * uniformly. */
384634efbc2SNelio Laranjeiro 	for (i = 0, j = 0; (i != reta_idx_n); ++i) {
385634efbc2SNelio Laranjeiro 		(*priv->reta_idx)[i] = j;
386634efbc2SNelio Laranjeiro 		if (++j == rxqs_n)
387634efbc2SNelio Laranjeiro 			j = 0;
388634efbc2SNelio Laranjeiro 	}
389e60fbd5bSAdrien Mazarguil 	return 0;
390e60fbd5bSAdrien Mazarguil }
391e60fbd5bSAdrien Mazarguil 
392e60fbd5bSAdrien Mazarguil /**
393e60fbd5bSAdrien Mazarguil  * DPDK callback to get information about the device.
394e60fbd5bSAdrien Mazarguil  *
395e60fbd5bSAdrien Mazarguil  * @param dev
396e60fbd5bSAdrien Mazarguil  *   Pointer to Ethernet device structure.
397e60fbd5bSAdrien Mazarguil  * @param[out] info
398e60fbd5bSAdrien Mazarguil  *   Info structure output buffer.
399e60fbd5bSAdrien Mazarguil  */
400e60fbd5bSAdrien Mazarguil void
401e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
402e60fbd5bSAdrien Mazarguil {
40301d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
4047fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
405e60fbd5bSAdrien Mazarguil 	unsigned int max;
406e60fbd5bSAdrien Mazarguil 	char ifname[IF_NAMESIZE];
407e60fbd5bSAdrien Mazarguil 
408c0802544SFerruh Yigit 	info->pci_dev = RTE_ETH_DEV_TO_PCI(dev);
409e60fbd5bSAdrien Mazarguil 	/* FIXME: we should ask the device for these values. */
410e60fbd5bSAdrien Mazarguil 	info->min_rx_bufsize = 32;
411e60fbd5bSAdrien Mazarguil 	info->max_rx_pktlen = 65536;
412e60fbd5bSAdrien Mazarguil 	/*
413e60fbd5bSAdrien Mazarguil 	 * Since we need one CQ per QP, the limit is the minimum number
414e60fbd5bSAdrien Mazarguil 	 * between the two values.
415e60fbd5bSAdrien Mazarguil 	 */
41643e9d979SShachar Beiser 	max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
41743e9d979SShachar Beiser 		      priv->device_attr.orig_attr.max_qp);
418e60fbd5bSAdrien Mazarguil 	/* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
419e60fbd5bSAdrien Mazarguil 	if (max >= 65535)
420e60fbd5bSAdrien Mazarguil 		max = 65535;
421e60fbd5bSAdrien Mazarguil 	info->max_rx_queues = max;
422e60fbd5bSAdrien Mazarguil 	info->max_tx_queues = max;
4230497ddaaSYaacov Hazan 	info->max_mac_addrs = RTE_DIM(priv->mac);
424af4f09f2SNélio Laranjeiro 	info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev);
425af4f09f2SNélio Laranjeiro 	info->rx_offload_capa = (mlx5_get_rx_port_offloads() |
42617b843ebSShahaf Shuler 				 info->rx_queue_offload_capa);
427af4f09f2SNélio Laranjeiro 	info->tx_offload_capa = mlx5_get_tx_port_offloads(dev);
428af4f09f2SNélio Laranjeiro 	if (mlx5_get_ifname(dev, &ifname) == 0)
429e60fbd5bSAdrien Mazarguil 		info->if_index = if_nametoindex(ifname);
430d365210eSYongseok Koh 	info->reta_size = priv->reta_idx_n ?
4317fe24446SShahaf Shuler 		priv->reta_idx_n : config->ind_table_max_size;
432e7041f55SShahaf Shuler 	info->hash_key_size = rss_hash_default_key_len;
43375ef62a9SNélio Laranjeiro 	info->speed_capa = priv->link_speed_capa;
434b233b027SShahaf Shuler 	info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
435e60fbd5bSAdrien Mazarguil }
436e60fbd5bSAdrien Mazarguil 
437fb732b0aSNélio Laranjeiro /**
438fb732b0aSNélio Laranjeiro  * Get supported packet types.
439fb732b0aSNélio Laranjeiro  *
440fb732b0aSNélio Laranjeiro  * @param dev
441fb732b0aSNélio Laranjeiro  *   Pointer to Ethernet device structure.
442fb732b0aSNélio Laranjeiro  *
443fb732b0aSNélio Laranjeiro  * @return
444fb732b0aSNélio Laranjeiro  *   A pointer to the supported Packet types array.
445fb732b0aSNélio Laranjeiro  */
44678a38edfSJianfeng Tan const uint32_t *
44778a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
44878a38edfSJianfeng Tan {
44978a38edfSJianfeng Tan 	static const uint32_t ptypes[] = {
45078a38edfSJianfeng Tan 		/* refers to rxq_cq_to_pkt_type() */
451ea16068cSYongseok Koh 		RTE_PTYPE_L2_ETHER,
452c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
453c4ba5434SNélio Laranjeiro 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
454ea16068cSYongseok Koh 		RTE_PTYPE_L4_NONFRAG,
455ea16068cSYongseok Koh 		RTE_PTYPE_L4_FRAG,
456ea16068cSYongseok Koh 		RTE_PTYPE_L4_TCP,
457ea16068cSYongseok Koh 		RTE_PTYPE_L4_UDP,
458c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
459c4ba5434SNélio Laranjeiro 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
460ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_NONFRAG,
461ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_FRAG,
462ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_TCP,
463ea16068cSYongseok Koh 		RTE_PTYPE_INNER_L4_UDP,
46478a38edfSJianfeng Tan 		RTE_PTYPE_UNKNOWN
46578a38edfSJianfeng Tan 	};
46678a38edfSJianfeng Tan 
4676cb559d6SYongseok Koh 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
4686cb559d6SYongseok Koh 	    dev->rx_pkt_burst == mlx5_rx_burst_vec)
46978a38edfSJianfeng Tan 		return ptypes;
47078a38edfSJianfeng Tan 	return NULL;
47178a38edfSJianfeng Tan }
47278a38edfSJianfeng Tan 
473e60fbd5bSAdrien Mazarguil /**
4742c960a51SMatthieu Ternisien d'Ouville  * DPDK callback to retrieve physical link information.
475cb8faed7SAdrien Mazarguil  *
476cb8faed7SAdrien Mazarguil  * @param dev
477cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
478cfee9475SNélio Laranjeiro  * @param[out] link
479cfee9475SNélio Laranjeiro  *   Storage for current link status.
480fb732b0aSNélio Laranjeiro  *
481fb732b0aSNélio Laranjeiro  * @return
482a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
483cb8faed7SAdrien Mazarguil  */
48418840871SNélio Laranjeiro static int
485cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
486cfee9475SNélio Laranjeiro 			       struct rte_eth_link *link)
487cb8faed7SAdrien Mazarguil {
48801d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
489cb8faed7SAdrien Mazarguil 	struct ethtool_cmd edata = {
49075ef62a9SNélio Laranjeiro 		.cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
491cb8faed7SAdrien Mazarguil 	};
492cb8faed7SAdrien Mazarguil 	struct ifreq ifr;
493cb8faed7SAdrien Mazarguil 	struct rte_eth_link dev_link;
494cb8faed7SAdrien Mazarguil 	int link_speed = 0;
495a6d83b6aSNélio Laranjeiro 	int ret;
496cb8faed7SAdrien Mazarguil 
497a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
498a6d83b6aSNélio Laranjeiro 	if (ret) {
499a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
5000f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
501a6d83b6aSNélio Laranjeiro 		return ret;
502cb8faed7SAdrien Mazarguil 	}
503cb8faed7SAdrien Mazarguil 	memset(&dev_link, 0, sizeof(dev_link));
504cb8faed7SAdrien Mazarguil 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
505cb8faed7SAdrien Mazarguil 				(ifr.ifr_flags & IFF_RUNNING));
506d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&edata;
507a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
508a6d83b6aSNélio Laranjeiro 	if (ret) {
509a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
510a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
5110f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
512a6d83b6aSNélio Laranjeiro 		return ret;
513cb8faed7SAdrien Mazarguil 	}
514cb8faed7SAdrien Mazarguil 	link_speed = ethtool_cmd_speed(&edata);
515cb8faed7SAdrien Mazarguil 	if (link_speed == -1)
516cb8faed7SAdrien Mazarguil 		dev_link.link_speed = 0;
517cb8faed7SAdrien Mazarguil 	else
518cb8faed7SAdrien Mazarguil 		dev_link.link_speed = link_speed;
51975ef62a9SNélio Laranjeiro 	priv->link_speed_capa = 0;
52075ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_Autoneg)
52175ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
52275ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_1000baseT_Full |
52375ef62a9SNélio Laranjeiro 			       SUPPORTED_1000baseKX_Full))
52475ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
52575ef62a9SNélio Laranjeiro 	if (edata.supported & SUPPORTED_10000baseKR_Full)
52675ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
52775ef62a9SNélio Laranjeiro 	if (edata.supported & (SUPPORTED_40000baseKR4_Full |
52875ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseCR4_Full |
52975ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseSR4_Full |
53075ef62a9SNélio Laranjeiro 			       SUPPORTED_40000baseLR4_Full))
53175ef62a9SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
532cb8faed7SAdrien Mazarguil 	dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
533cb8faed7SAdrien Mazarguil 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
53482113036SMarc Sune 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
53582113036SMarc Sune 			ETH_LINK_SPEED_FIXED);
536cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
537cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
538a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
539a6d83b6aSNélio Laranjeiro 		return -rte_errno;
540cb8faed7SAdrien Mazarguil 	}
541cfee9475SNélio Laranjeiro 	*link = dev_link;
542cfee9475SNélio Laranjeiro 	return 0;
543cfee9475SNélio Laranjeiro }
544cb8faed7SAdrien Mazarguil 
545cb8faed7SAdrien Mazarguil /**
5463a49ffe3SShahaf Shuler  * Retrieve physical link information (unlocked version using new ioctl).
54718840871SNélio Laranjeiro  *
54818840871SNélio Laranjeiro  * @param dev
54918840871SNélio Laranjeiro  *   Pointer to Ethernet device structure.
550cfee9475SNélio Laranjeiro  * @param[out] link
551cfee9475SNélio Laranjeiro  *   Storage for current link status.
552fb732b0aSNélio Laranjeiro  *
553fb732b0aSNélio Laranjeiro  * @return
554a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
55518840871SNélio Laranjeiro  */
55618840871SNélio Laranjeiro static int
557cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
558cfee9475SNélio Laranjeiro 			     struct rte_eth_link *link)
559cfee9475SNélio Laranjeiro 
56018840871SNélio Laranjeiro {
56101d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
56237a4406cSNélio Laranjeiro 	struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
56318840871SNélio Laranjeiro 	struct ifreq ifr;
56418840871SNélio Laranjeiro 	struct rte_eth_link dev_link;
56518840871SNélio Laranjeiro 	uint64_t sc;
566a6d83b6aSNélio Laranjeiro 	int ret;
56718840871SNélio Laranjeiro 
568a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
569a6d83b6aSNélio Laranjeiro 	if (ret) {
570a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
5710f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
572a6d83b6aSNélio Laranjeiro 		return ret;
57318840871SNélio Laranjeiro 	}
57418840871SNélio Laranjeiro 	memset(&dev_link, 0, sizeof(dev_link));
57518840871SNélio Laranjeiro 	dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
57618840871SNélio Laranjeiro 				(ifr.ifr_flags & IFF_RUNNING));
57737a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)&gcmd;
578a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
579a6d83b6aSNélio Laranjeiro 	if (ret) {
580a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
581a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
582a170a30dSNélio Laranjeiro 			" failed: %s",
583a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
584a6d83b6aSNélio Laranjeiro 		return ret;
58518840871SNélio Laranjeiro 	}
58637a4406cSNélio Laranjeiro 	gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
58737a4406cSNélio Laranjeiro 
58837a4406cSNélio Laranjeiro 	alignas(struct ethtool_link_settings)
58937a4406cSNélio Laranjeiro 	uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
59037a4406cSNélio Laranjeiro 		     sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
59137a4406cSNélio Laranjeiro 	struct ethtool_link_settings *ecmd = (void *)data;
59237a4406cSNélio Laranjeiro 
59337a4406cSNélio Laranjeiro 	*ecmd = gcmd;
59437a4406cSNélio Laranjeiro 	ifr.ifr_data = (void *)ecmd;
595a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
596a6d83b6aSNélio Laranjeiro 	if (ret) {
597a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG,
598a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
599a170a30dSNélio Laranjeiro 			" failed: %s",
600a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
601a6d83b6aSNélio Laranjeiro 		return ret;
602ef09a7fcSGowrishankar Muthukrishnan 	}
60390260d57SNélio Laranjeiro 	dev_link.link_speed = ecmd->speed;
60490260d57SNélio Laranjeiro 	sc = ecmd->link_mode_masks[0] |
60590260d57SNélio Laranjeiro 		((uint64_t)ecmd->link_mode_masks[1] << 32);
60618840871SNélio Laranjeiro 	priv->link_speed_capa = 0;
607b113cb5eSEdward Makarov 	if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
60818840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
609b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
610b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
61118840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_1G;
612b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
613b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
614b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
61518840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_10G;
616b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
617b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
61818840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_20G;
619b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
620b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
621b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
622b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
62318840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_40G;
624b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
625b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
626b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
627b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
62818840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_56G;
629b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
630b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
631b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
63218840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_25G;
633b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
634b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
63518840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_50G;
636b113cb5eSEdward Makarov 	if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
637b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
638b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
639b113cb5eSEdward Makarov 		  MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
64018840871SNélio Laranjeiro 		priv->link_speed_capa |= ETH_LINK_SPEED_100G;
64190260d57SNélio Laranjeiro 	dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
64218840871SNélio Laranjeiro 				ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
64318840871SNélio Laranjeiro 	dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
64418840871SNélio Laranjeiro 				  ETH_LINK_SPEED_FIXED);
645cfee9475SNélio Laranjeiro 	if ((dev_link.link_speed && !dev_link.link_status) ||
646cfee9475SNélio Laranjeiro 	    (!dev_link.link_speed && dev_link.link_status)) {
647a6d83b6aSNélio Laranjeiro 		rte_errno = EAGAIN;
648a6d83b6aSNélio Laranjeiro 		return -rte_errno;
64918840871SNélio Laranjeiro 	}
650cfee9475SNélio Laranjeiro 	*link = dev_link;
651cfee9475SNélio Laranjeiro 	return 0;
652cfee9475SNélio Laranjeiro }
65318840871SNélio Laranjeiro 
65418840871SNélio Laranjeiro /**
655cb8faed7SAdrien Mazarguil  * DPDK callback to retrieve physical link information.
656cb8faed7SAdrien Mazarguil  *
657cb8faed7SAdrien Mazarguil  * @param dev
658cb8faed7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
659cb8faed7SAdrien Mazarguil  * @param wait_to_complete
660cfee9475SNélio Laranjeiro  *   Wait for request completion.
661fb732b0aSNélio Laranjeiro  *
662fb732b0aSNélio Laranjeiro  * @return
663cfee9475SNélio Laranjeiro  *   0 if link status was not updated, positive if it was, a negative errno
664cfee9475SNélio Laranjeiro  *   value otherwise and rte_errno is set.
665cb8faed7SAdrien Mazarguil  */
666cb8faed7SAdrien Mazarguil int
667cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
668cb8faed7SAdrien Mazarguil {
669c7bf6225SYongseok Koh 	int ret;
670cfee9475SNélio Laranjeiro 	struct rte_eth_link dev_link;
671cfee9475SNélio Laranjeiro 	time_t start_time = time(NULL);
672cb8faed7SAdrien Mazarguil 
673cfee9475SNélio Laranjeiro 	do {
674cfee9475SNélio Laranjeiro 		ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
675a6d83b6aSNélio Laranjeiro 		if (ret)
676cfee9475SNélio Laranjeiro 			ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
677cfee9475SNélio Laranjeiro 		if (ret == 0)
678cfee9475SNélio Laranjeiro 			break;
679cfee9475SNélio Laranjeiro 		/* Handle wait to complete situation. */
680cfee9475SNélio Laranjeiro 		if (wait_to_complete && ret == -EAGAIN) {
681cfee9475SNélio Laranjeiro 			if (abs((int)difftime(time(NULL), start_time)) <
682cfee9475SNélio Laranjeiro 			    MLX5_LINK_STATUS_TIMEOUT) {
683cfee9475SNélio Laranjeiro 				usleep(0);
684cfee9475SNélio Laranjeiro 				continue;
685cfee9475SNélio Laranjeiro 			} else {
686cfee9475SNélio Laranjeiro 				rte_errno = EBUSY;
687cfee9475SNélio Laranjeiro 				return -rte_errno;
688cfee9475SNélio Laranjeiro 			}
689cfee9475SNélio Laranjeiro 		} else if (ret < 0) {
690cfee9475SNélio Laranjeiro 			return ret;
691cfee9475SNélio Laranjeiro 		}
692cfee9475SNélio Laranjeiro 	} while (wait_to_complete);
693cfee9475SNélio Laranjeiro 	ret = !!memcmp(&dev->data->dev_link, &dev_link,
694cfee9475SNélio Laranjeiro 		       sizeof(struct rte_eth_link));
695cfee9475SNélio Laranjeiro 	dev->data->dev_link = dev_link;
696cfee9475SNélio Laranjeiro 	return ret;
697cb8faed7SAdrien Mazarguil }
698cb8faed7SAdrien Mazarguil 
699cb8faed7SAdrien Mazarguil /**
700cf37ca95SAdrien Mazarguil  * DPDK callback to change the MTU.
701cf37ca95SAdrien Mazarguil  *
702cf37ca95SAdrien Mazarguil  * @param dev
703cf37ca95SAdrien Mazarguil  *   Pointer to Ethernet device structure.
704cf37ca95SAdrien Mazarguil  * @param in_mtu
705cf37ca95SAdrien Mazarguil  *   New MTU.
706cf37ca95SAdrien Mazarguil  *
707cf37ca95SAdrien Mazarguil  * @return
708a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
709cf37ca95SAdrien Mazarguil  */
710cf37ca95SAdrien Mazarguil int
711cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
712cf37ca95SAdrien Mazarguil {
713cf37ca95SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
714a6d83b6aSNélio Laranjeiro 	uint16_t kern_mtu = 0;
715a6d83b6aSNélio Laranjeiro 	int ret;
716cf37ca95SAdrien Mazarguil 
717af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
718a0edafe4SNelio Laranjeiro 	if (ret)
719a6d83b6aSNélio Laranjeiro 		return ret;
720cf37ca95SAdrien Mazarguil 	/* Set kernel interface MTU first. */
721af4f09f2SNélio Laranjeiro 	ret = mlx5_set_mtu(dev, mtu);
722a0edafe4SNelio Laranjeiro 	if (ret)
723a6d83b6aSNélio Laranjeiro 		return ret;
724af4f09f2SNélio Laranjeiro 	ret = mlx5_get_mtu(dev, &kern_mtu);
725a0edafe4SNelio Laranjeiro 	if (ret)
726a6d83b6aSNélio Laranjeiro 		return ret;
727a0edafe4SNelio Laranjeiro 	if (kern_mtu == mtu) {
728a0edafe4SNelio Laranjeiro 		priv->mtu = mtu;
729a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
730a170a30dSNélio Laranjeiro 			dev->data->port_id, mtu);
731a0edafe4SNelio Laranjeiro 		return 0;
732a6d83b6aSNélio Laranjeiro 	}
733a6d83b6aSNélio Laranjeiro 	rte_errno = EAGAIN;
734a6d83b6aSNélio Laranjeiro 	return -rte_errno;
735cf37ca95SAdrien Mazarguil }
736cf37ca95SAdrien Mazarguil 
737cf37ca95SAdrien Mazarguil /**
73802d75430SAdrien Mazarguil  * DPDK callback to get flow control status.
73902d75430SAdrien Mazarguil  *
74002d75430SAdrien Mazarguil  * @param dev
74102d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
74202d75430SAdrien Mazarguil  * @param[out] fc_conf
74302d75430SAdrien Mazarguil  *   Flow control output buffer.
74402d75430SAdrien Mazarguil  *
74502d75430SAdrien Mazarguil  * @return
746a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
74702d75430SAdrien Mazarguil  */
74802d75430SAdrien Mazarguil int
74902d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
75002d75430SAdrien Mazarguil {
75102d75430SAdrien Mazarguil 	struct ifreq ifr;
75202d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
75302d75430SAdrien Mazarguil 		.cmd = ETHTOOL_GPAUSEPARAM
75402d75430SAdrien Mazarguil 	};
75502d75430SAdrien Mazarguil 	int ret;
75602d75430SAdrien Mazarguil 
757d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
758a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
759a6d83b6aSNélio Laranjeiro 	if (ret) {
760a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
761a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
762a170a30dSNélio Laranjeiro 			" %s",
763a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
764a6d83b6aSNélio Laranjeiro 		return ret;
76502d75430SAdrien Mazarguil 	}
76602d75430SAdrien Mazarguil 	fc_conf->autoneg = ethpause.autoneg;
76702d75430SAdrien Mazarguil 	if (ethpause.rx_pause && ethpause.tx_pause)
76802d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_FULL;
76902d75430SAdrien Mazarguil 	else if (ethpause.rx_pause)
77002d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_RX_PAUSE;
77102d75430SAdrien Mazarguil 	else if (ethpause.tx_pause)
77202d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_TX_PAUSE;
77302d75430SAdrien Mazarguil 	else
77402d75430SAdrien Mazarguil 		fc_conf->mode = RTE_FC_NONE;
775a6d83b6aSNélio Laranjeiro 	return 0;
77602d75430SAdrien Mazarguil }
77702d75430SAdrien Mazarguil 
77802d75430SAdrien Mazarguil /**
77902d75430SAdrien Mazarguil  * DPDK callback to modify flow control parameters.
78002d75430SAdrien Mazarguil  *
78102d75430SAdrien Mazarguil  * @param dev
78202d75430SAdrien Mazarguil  *   Pointer to Ethernet device structure.
78302d75430SAdrien Mazarguil  * @param[in] fc_conf
78402d75430SAdrien Mazarguil  *   Flow control parameters.
78502d75430SAdrien Mazarguil  *
78602d75430SAdrien Mazarguil  * @return
787a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
78802d75430SAdrien Mazarguil  */
78902d75430SAdrien Mazarguil int
79002d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
79102d75430SAdrien Mazarguil {
79202d75430SAdrien Mazarguil 	struct ifreq ifr;
79302d75430SAdrien Mazarguil 	struct ethtool_pauseparam ethpause = {
79402d75430SAdrien Mazarguil 		.cmd = ETHTOOL_SPAUSEPARAM
79502d75430SAdrien Mazarguil 	};
79602d75430SAdrien Mazarguil 	int ret;
79702d75430SAdrien Mazarguil 
798d06c608cSAdrien Mazarguil 	ifr.ifr_data = (void *)&ethpause;
79902d75430SAdrien Mazarguil 	ethpause.autoneg = fc_conf->autoneg;
80002d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
80102d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_RX_PAUSE))
80202d75430SAdrien Mazarguil 		ethpause.rx_pause = 1;
80302d75430SAdrien Mazarguil 	else
80402d75430SAdrien Mazarguil 		ethpause.rx_pause = 0;
80502d75430SAdrien Mazarguil 
80602d75430SAdrien Mazarguil 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
80702d75430SAdrien Mazarguil 	    (fc_conf->mode & RTE_FC_TX_PAUSE))
80802d75430SAdrien Mazarguil 		ethpause.tx_pause = 1;
80902d75430SAdrien Mazarguil 	else
81002d75430SAdrien Mazarguil 		ethpause.tx_pause = 0;
811a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
812a6d83b6aSNélio Laranjeiro 	if (ret) {
813a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
814a170a30dSNélio Laranjeiro 			"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
815a170a30dSNélio Laranjeiro 			" failed: %s",
816a170a30dSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
817a6d83b6aSNélio Laranjeiro 		return ret;
81802d75430SAdrien Mazarguil 	}
819a6d83b6aSNélio Laranjeiro 	return 0;
82002d75430SAdrien Mazarguil }
82102d75430SAdrien Mazarguil 
82202d75430SAdrien Mazarguil /**
823771fa900SAdrien Mazarguil  * Get PCI information from struct ibv_device.
824771fa900SAdrien Mazarguil  *
825771fa900SAdrien Mazarguil  * @param device
826771fa900SAdrien Mazarguil  *   Pointer to Ethernet device structure.
827771fa900SAdrien Mazarguil  * @param[out] pci_addr
828771fa900SAdrien Mazarguil  *   PCI bus address output buffer.
829771fa900SAdrien Mazarguil  *
830771fa900SAdrien Mazarguil  * @return
831a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
832771fa900SAdrien Mazarguil  */
833771fa900SAdrien Mazarguil int
834771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
835771fa900SAdrien Mazarguil 			    struct rte_pci_addr *pci_addr)
836771fa900SAdrien Mazarguil {
837771fa900SAdrien Mazarguil 	FILE *file;
838771fa900SAdrien Mazarguil 	char line[32];
839771fa900SAdrien Mazarguil 	MKSTR(path, "%s/device/uevent", device->ibdev_path);
840771fa900SAdrien Mazarguil 
841771fa900SAdrien Mazarguil 	file = fopen(path, "rb");
842a6d83b6aSNélio Laranjeiro 	if (file == NULL) {
843a6d83b6aSNélio Laranjeiro 		rte_errno = errno;
844a6d83b6aSNélio Laranjeiro 		return -rte_errno;
845a6d83b6aSNélio Laranjeiro 	}
846771fa900SAdrien Mazarguil 	while (fgets(line, sizeof(line), file) == line) {
847771fa900SAdrien Mazarguil 		size_t len = strlen(line);
848771fa900SAdrien Mazarguil 		int ret;
849771fa900SAdrien Mazarguil 
850771fa900SAdrien Mazarguil 		/* Truncate long lines. */
851771fa900SAdrien Mazarguil 		if (len == (sizeof(line) - 1))
852771fa900SAdrien Mazarguil 			while (line[(len - 1)] != '\n') {
853771fa900SAdrien Mazarguil 				ret = fgetc(file);
854771fa900SAdrien Mazarguil 				if (ret == EOF)
855771fa900SAdrien Mazarguil 					break;
856771fa900SAdrien Mazarguil 				line[(len - 1)] = ret;
857771fa900SAdrien Mazarguil 			}
858771fa900SAdrien Mazarguil 		/* Extract information. */
859771fa900SAdrien Mazarguil 		if (sscanf(line,
860771fa900SAdrien Mazarguil 			   "PCI_SLOT_NAME="
861463ced95SStephen Hemminger 			   "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
862771fa900SAdrien Mazarguil 			   &pci_addr->domain,
863771fa900SAdrien Mazarguil 			   &pci_addr->bus,
864771fa900SAdrien Mazarguil 			   &pci_addr->devid,
865771fa900SAdrien Mazarguil 			   &pci_addr->function) == 4) {
866771fa900SAdrien Mazarguil 			ret = 0;
867771fa900SAdrien Mazarguil 			break;
868771fa900SAdrien Mazarguil 		}
869771fa900SAdrien Mazarguil 	}
870771fa900SAdrien Mazarguil 	fclose(file);
871771fa900SAdrien Mazarguil 	return 0;
872771fa900SAdrien Mazarguil }
873198a3c33SNelio Laranjeiro 
874198a3c33SNelio Laranjeiro /**
875c26ae069SMatan Azrad  * Device status handler.
876c26ae069SMatan Azrad  *
877af4f09f2SNélio Laranjeiro  * @param dev
878af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
879c26ae069SMatan Azrad  * @param events
880c26ae069SMatan Azrad  *   Pointer to event flags holder.
881c26ae069SMatan Azrad  *
882c26ae069SMatan Azrad  * @return
883c26ae069SMatan Azrad  *   Events bitmap of callback process which can be called immediately.
884c26ae069SMatan Azrad  */
885c26ae069SMatan Azrad static uint32_t
886af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev)
887198a3c33SNelio Laranjeiro {
888af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
889198a3c33SNelio Laranjeiro 	struct ibv_async_event event;
890c26ae069SMatan Azrad 	uint32_t ret = 0;
891198a3c33SNelio Laranjeiro 
892cfee9475SNélio Laranjeiro 	if (mlx5_link_update(dev, 0) == -EAGAIN) {
893cfee9475SNélio Laranjeiro 		usleep(0);
894cfee9475SNélio Laranjeiro 		return 0;
895cfee9475SNélio Laranjeiro 	}
896198a3c33SNelio Laranjeiro 	/* Read all message and acknowledge them. */
897198a3c33SNelio Laranjeiro 	for (;;) {
8980e83b8e5SNelio Laranjeiro 		if (mlx5_glue->get_async_event(priv->ctx, &event))
899198a3c33SNelio Laranjeiro 			break;
900c26ae069SMatan Azrad 		if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
901c26ae069SMatan Azrad 			event.event_type == IBV_EVENT_PORT_ERR) &&
902af4f09f2SNélio Laranjeiro 			(dev->data->dev_conf.intr_conf.lsc == 1))
903c26ae069SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
9047d7d7ad1SMatan Azrad 		else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
905af4f09f2SNélio Laranjeiro 			dev->data->dev_conf.intr_conf.rmv == 1)
9067d7d7ad1SMatan Azrad 			ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
907c26ae069SMatan Azrad 		else
908a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
909a170a30dSNélio Laranjeiro 				"port %u event type %d on not handled",
9100f99970bSNélio Laranjeiro 				dev->data->port_id, event.event_type);
9110e83b8e5SNelio Laranjeiro 		mlx5_glue->ack_async_event(&event);
912198a3c33SNelio Laranjeiro 	}
913198a3c33SNelio Laranjeiro 	return ret;
914198a3c33SNelio Laranjeiro }
915198a3c33SNelio Laranjeiro 
916198a3c33SNelio Laranjeiro /**
917198a3c33SNelio Laranjeiro  * Handle interrupts from the NIC.
918198a3c33SNelio Laranjeiro  *
919198a3c33SNelio Laranjeiro  * @param[in] intr_handle
920198a3c33SNelio Laranjeiro  *   Interrupt handler.
921198a3c33SNelio Laranjeiro  * @param cb_arg
922198a3c33SNelio Laranjeiro  *   Callback argument.
923198a3c33SNelio Laranjeiro  */
924198a3c33SNelio Laranjeiro void
925c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg)
926198a3c33SNelio Laranjeiro {
927198a3c33SNelio Laranjeiro 	struct rte_eth_dev *dev = cb_arg;
928c26ae069SMatan Azrad 	uint32_t events;
929198a3c33SNelio Laranjeiro 
930af4f09f2SNélio Laranjeiro 	events = mlx5_dev_status_handler(dev);
931c26ae069SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
932cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
9337d7d7ad1SMatan Azrad 	if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
934cebe3d7bSThomas Monjalon 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
935198a3c33SNelio Laranjeiro }
936198a3c33SNelio Laranjeiro 
937198a3c33SNelio Laranjeiro /**
938f8b9a3baSXueming Li  * Handle interrupts from the socket.
939f8b9a3baSXueming Li  *
940f8b9a3baSXueming Li  * @param cb_arg
941f8b9a3baSXueming Li  *   Callback argument.
942f8b9a3baSXueming Li  */
943f8b9a3baSXueming Li static void
944f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg)
945f8b9a3baSXueming Li {
946f8b9a3baSXueming Li 	struct rte_eth_dev *dev = cb_arg;
947f8b9a3baSXueming Li 
948af4f09f2SNélio Laranjeiro 	mlx5_socket_handle(dev);
949f8b9a3baSXueming Li }
950f8b9a3baSXueming Li 
951f8b9a3baSXueming Li /**
952198a3c33SNelio Laranjeiro  * Uninstall interrupt handler.
953198a3c33SNelio Laranjeiro  *
954198a3c33SNelio Laranjeiro  * @param dev
955af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
956198a3c33SNelio Laranjeiro  */
957198a3c33SNelio Laranjeiro void
958af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
959198a3c33SNelio Laranjeiro {
960af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
961af4f09f2SNélio Laranjeiro 
962f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
963f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv)
964198a3c33SNelio Laranjeiro 		rte_intr_callback_unregister(&priv->intr_handle,
965f8b9a3baSXueming Li 					     mlx5_dev_interrupt_handler, dev);
966f8b9a3baSXueming Li 	if (priv->primary_socket)
967f8b9a3baSXueming Li 		rte_intr_callback_unregister(&priv->intr_handle_socket,
968f8b9a3baSXueming Li 					     mlx5_dev_handler_socket, dev);
969198a3c33SNelio Laranjeiro 	priv->intr_handle.fd = 0;
97036351ea3SFerruh Yigit 	priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
971f8b9a3baSXueming Li 	priv->intr_handle_socket.fd = 0;
972f8b9a3baSXueming Li 	priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
973198a3c33SNelio Laranjeiro }
974198a3c33SNelio Laranjeiro 
975198a3c33SNelio Laranjeiro /**
976198a3c33SNelio Laranjeiro  * Install interrupt handler.
977198a3c33SNelio Laranjeiro  *
978198a3c33SNelio Laranjeiro  * @param dev
979af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
980198a3c33SNelio Laranjeiro  */
981198a3c33SNelio Laranjeiro void
982af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
983198a3c33SNelio Laranjeiro {
984af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
985a6d83b6aSNélio Laranjeiro 	int ret;
986a6d83b6aSNélio Laranjeiro 	int flags;
987198a3c33SNelio Laranjeiro 
988198a3c33SNelio Laranjeiro 	assert(priv->ctx->async_fd > 0);
989198a3c33SNelio Laranjeiro 	flags = fcntl(priv->ctx->async_fd, F_GETFL);
990a6d83b6aSNélio Laranjeiro 	ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
991a6d83b6aSNélio Laranjeiro 	if (ret) {
992a170a30dSNélio Laranjeiro 		DRV_LOG(INFO,
993a170a30dSNélio Laranjeiro 			"port %u failed to change file descriptor async event"
994a170a30dSNélio Laranjeiro 			" queue",
995a170a30dSNélio Laranjeiro 			dev->data->port_id);
996198a3c33SNelio Laranjeiro 		dev->data->dev_conf.intr_conf.lsc = 0;
9977d7d7ad1SMatan Azrad 		dev->data->dev_conf.intr_conf.rmv = 0;
998f8b9a3baSXueming Li 	}
999f8b9a3baSXueming Li 	if (dev->data->dev_conf.intr_conf.lsc ||
1000f8b9a3baSXueming Li 	    dev->data->dev_conf.intr_conf.rmv) {
1001198a3c33SNelio Laranjeiro 		priv->intr_handle.fd = priv->ctx->async_fd;
1002198a3c33SNelio Laranjeiro 		priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
1003198a3c33SNelio Laranjeiro 		rte_intr_callback_register(&priv->intr_handle,
1004f8b9a3baSXueming Li 					   mlx5_dev_interrupt_handler, dev);
1005f8b9a3baSXueming Li 	}
1006a6d83b6aSNélio Laranjeiro 	ret = mlx5_socket_init(dev);
1007a6d83b6aSNélio Laranjeiro 	if (ret)
1008a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot initialise socket: %s",
10090f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
1010a6d83b6aSNélio Laranjeiro 	else if (priv->primary_socket) {
1011f8b9a3baSXueming Li 		priv->intr_handle_socket.fd = priv->primary_socket;
1012f8b9a3baSXueming Li 		priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
1013f8b9a3baSXueming Li 		rte_intr_callback_register(&priv->intr_handle_socket,
1014f8b9a3baSXueming Li 					   mlx5_dev_handler_socket, dev);
1015198a3c33SNelio Laranjeiro 	}
1016198a3c33SNelio Laranjeiro }
101762072098SOr Ami 
101862072098SOr Ami /**
101962072098SOr Ami  * DPDK callback to bring the link DOWN.
102062072098SOr Ami  *
102162072098SOr Ami  * @param dev
102262072098SOr Ami  *   Pointer to Ethernet device structure.
102362072098SOr Ami  *
102462072098SOr Ami  * @return
1025a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
102662072098SOr Ami  */
102762072098SOr Ami int
102862072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev)
102962072098SOr Ami {
1030af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
103162072098SOr Ami }
103262072098SOr Ami 
103362072098SOr Ami /**
103462072098SOr Ami  * DPDK callback to bring the link UP.
103562072098SOr Ami  *
103662072098SOr Ami  * @param dev
103762072098SOr Ami  *   Pointer to Ethernet device structure.
103862072098SOr Ami  *
103962072098SOr Ami  * @return
1040a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
104162072098SOr Ami  */
104262072098SOr Ami int
104362072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev)
104462072098SOr Ami {
1045af4f09f2SNélio Laranjeiro 	return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
104662072098SOr Ami }
1047a48deadaSOr Ami 
1048a48deadaSOr Ami /**
1049cdab90cbSNélio Laranjeiro  * Configure the TX function to use.
1050cdab90cbSNélio Laranjeiro  *
1051aee1b165SXueming Li  * @param dev
1052af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
10531cfa649bSShahaf Shuler  *
10541cfa649bSShahaf Shuler  * @return
10551cfa649bSShahaf Shuler  *   Pointer to selected Tx burst function.
1056cdab90cbSNélio Laranjeiro  */
10571cfa649bSShahaf Shuler eth_tx_burst_t
1058af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev)
1059cdab90cbSNélio Laranjeiro {
1060af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
10611cfa649bSShahaf Shuler 	eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst;
10627fe24446SShahaf Shuler 	struct mlx5_dev_config *config = &priv->config;
1063dbccb4cdSShahaf Shuler 	uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
1064dbccb4cdSShahaf Shuler 	int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO |
1065dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
1066dbccb4cdSShahaf Shuler 				    DEV_TX_OFFLOAD_GRE_TNL_TSO));
1067dbccb4cdSShahaf Shuler 	int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT);
10681cfa649bSShahaf Shuler 
1069aee1b165SXueming Li 	assert(priv != NULL);
1070230189d9SNélio Laranjeiro 	/* Select appropriate TX function. */
1071dbccb4cdSShahaf Shuler 	if (vlan_insert || tso)
1072dbccb4cdSShahaf Shuler 		return tx_pkt_burst;
10737fe24446SShahaf Shuler 	if (config->mps == MLX5_MPW_ENHANCED) {
1074af4f09f2SNélio Laranjeiro 		if (mlx5_check_vec_tx_support(dev) > 0) {
1075af4f09f2SNélio Laranjeiro 			if (mlx5_check_raw_vec_tx_support(dev) > 0)
10761cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_raw_vec;
10776cb559d6SYongseok Koh 			else
10781cfa649bSShahaf Shuler 				tx_pkt_burst = mlx5_tx_burst_vec;
1079a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1080a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx vectorized"
1081a170a30dSNélio Laranjeiro 				" function",
1082a170a30dSNélio Laranjeiro 				dev->data->port_id);
10836cb559d6SYongseok Koh 		} else {
10841cfa649bSShahaf Shuler 			tx_pkt_burst = mlx5_tx_burst_empw;
1085a170a30dSNélio Laranjeiro 			DRV_LOG(DEBUG,
1086a170a30dSNélio Laranjeiro 				"port %u selected enhanced MPW Tx function",
10870f99970bSNélio Laranjeiro 				dev->data->port_id);
10886cb559d6SYongseok Koh 		}
10897fe24446SShahaf Shuler 	} else if (config->mps && (config->txq_inline > 0)) {
10901cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw_inline;
1091a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW inline Tx function",
10920f99970bSNélio Laranjeiro 			dev->data->port_id);
10937fe24446SShahaf Shuler 	} else if (config->mps) {
10941cfa649bSShahaf Shuler 		tx_pkt_burst = mlx5_tx_burst_mpw;
1095a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected MPW Tx function",
1096a170a30dSNélio Laranjeiro 			dev->data->port_id);
10972a66cf37SYaacov Hazan 	}
10981cfa649bSShahaf Shuler 	return tx_pkt_burst;
1099cdab90cbSNélio Laranjeiro }
1100cdab90cbSNélio Laranjeiro 
1101cdab90cbSNélio Laranjeiro /**
1102cdab90cbSNélio Laranjeiro  * Configure the RX function to use.
1103cdab90cbSNélio Laranjeiro  *
1104aee1b165SXueming Li  * @param dev
1105af4f09f2SNélio Laranjeiro  *   Pointer to private data structure.
11061cfa649bSShahaf Shuler  *
11071cfa649bSShahaf Shuler  * @return
11081cfa649bSShahaf Shuler  *   Pointer to selected Rx burst function.
1109cdab90cbSNélio Laranjeiro  */
11101cfa649bSShahaf Shuler eth_rx_burst_t
1111af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev)
1112cdab90cbSNélio Laranjeiro {
11131cfa649bSShahaf Shuler 	eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst;
11141cfa649bSShahaf Shuler 
1115af4f09f2SNélio Laranjeiro 	assert(dev != NULL);
1116af4f09f2SNélio Laranjeiro 	if (mlx5_check_vec_rx_support(dev) > 0) {
11171cfa649bSShahaf Shuler 		rx_pkt_burst = mlx5_rx_burst_vec;
1118a170a30dSNélio Laranjeiro 		DRV_LOG(DEBUG, "port %u selected Rx vectorized function",
11190f99970bSNélio Laranjeiro 			dev->data->port_id);
1120cdab90cbSNélio Laranjeiro 	}
11211cfa649bSShahaf Shuler 	return rx_pkt_burst;
11226cb559d6SYongseok Koh }
1123d3e0f392SMatan Azrad 
1124d3e0f392SMatan Azrad /**
1125d3e0f392SMatan Azrad  * Check if mlx5 device was removed.
1126d3e0f392SMatan Azrad  *
1127d3e0f392SMatan Azrad  * @param dev
1128d3e0f392SMatan Azrad  *   Pointer to Ethernet device structure.
1129d3e0f392SMatan Azrad  *
1130d3e0f392SMatan Azrad  * @return
1131d3e0f392SMatan Azrad  *   1 when device is removed, otherwise 0.
1132d3e0f392SMatan Azrad  */
1133d3e0f392SMatan Azrad int
1134d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev)
1135d3e0f392SMatan Azrad {
1136d3e0f392SMatan Azrad 	struct ibv_device_attr device_attr;
1137d3e0f392SMatan Azrad 	struct priv *priv = dev->data->dev_private;
1138d3e0f392SMatan Azrad 
11390e83b8e5SNelio Laranjeiro 	if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO)
1140d3e0f392SMatan Azrad 		return 1;
1141d3e0f392SMatan Azrad 	return 0;
1142d3e0f392SMatan Azrad }
1143