18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6771fa900SAdrien Mazarguil #include <stddef.h> 7e60fbd5bSAdrien Mazarguil #include <assert.h> 8fc40db99SAdrien Mazarguil #include <inttypes.h> 9771fa900SAdrien Mazarguil #include <unistd.h> 10771fa900SAdrien Mazarguil #include <stdint.h> 11771fa900SAdrien Mazarguil #include <stdio.h> 12771fa900SAdrien Mazarguil #include <string.h> 13771fa900SAdrien Mazarguil #include <stdlib.h> 14771fa900SAdrien Mazarguil #include <errno.h> 15771fa900SAdrien Mazarguil #include <dirent.h> 16771fa900SAdrien Mazarguil #include <net/if.h> 17771fa900SAdrien Mazarguil #include <sys/ioctl.h> 18771fa900SAdrien Mazarguil #include <sys/socket.h> 19771fa900SAdrien Mazarguil #include <netinet/in.h> 20cb8faed7SAdrien Mazarguil #include <linux/ethtool.h> 21cb8faed7SAdrien Mazarguil #include <linux/sockios.h> 22198a3c33SNelio Laranjeiro #include <fcntl.h> 2390260d57SNélio Laranjeiro #include <stdalign.h> 24f8b9a3baSXueming Li #include <sys/un.h> 25cfee9475SNélio Laranjeiro #include <time.h> 26771fa900SAdrien Mazarguil 27771fa900SAdrien Mazarguil #include <rte_atomic.h> 28ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 29c752998bSGaetan Rivet #include <rte_bus_pci.h> 30771fa900SAdrien Mazarguil #include <rte_mbuf.h> 31771fa900SAdrien Mazarguil #include <rte_common.h> 32198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 33a48deadaSOr Ami #include <rte_malloc.h> 34c022cb40SBruce Richardson #include <rte_string_fns.h> 35974f1e7eSYongseok Koh #include <rte_rwlock.h> 36*5897ac13SViacheslav Ovsiienko #include <rte_cycles.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 4379d09892SMoti Haimovsky /* Supported speed values found in /usr/include/linux/ethtool.h */ 4479d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseKR4_Full 4579d09892SMoti Haimovsky #define SUPPORTED_40000baseKR4_Full (1 << 23) 4679d09892SMoti Haimovsky #endif 4779d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseCR4_Full 4879d09892SMoti Haimovsky #define SUPPORTED_40000baseCR4_Full (1 << 24) 4979d09892SMoti Haimovsky #endif 5079d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseSR4_Full 5179d09892SMoti Haimovsky #define SUPPORTED_40000baseSR4_Full (1 << 25) 5279d09892SMoti Haimovsky #endif 5379d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseLR4_Full 5479d09892SMoti Haimovsky #define SUPPORTED_40000baseLR4_Full (1 << 26) 5579d09892SMoti Haimovsky #endif 5679d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseKR4_Full 5779d09892SMoti Haimovsky #define SUPPORTED_56000baseKR4_Full (1 << 27) 5879d09892SMoti Haimovsky #endif 5979d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseCR4_Full 6079d09892SMoti Haimovsky #define SUPPORTED_56000baseCR4_Full (1 << 28) 6179d09892SMoti Haimovsky #endif 6279d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseSR4_Full 6379d09892SMoti Haimovsky #define SUPPORTED_56000baseSR4_Full (1 << 29) 6479d09892SMoti Haimovsky #endif 6579d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseLR4_Full 6679d09892SMoti Haimovsky #define SUPPORTED_56000baseLR4_Full (1 << 30) 6779d09892SMoti Haimovsky #endif 6879d09892SMoti Haimovsky 693a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */ 703a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS 713a49ffe3SShahaf Shuler struct ethtool_link_settings { 723a49ffe3SShahaf Shuler uint32_t cmd; 733a49ffe3SShahaf Shuler uint32_t speed; 743a49ffe3SShahaf Shuler uint8_t duplex; 753a49ffe3SShahaf Shuler uint8_t port; 763a49ffe3SShahaf Shuler uint8_t phy_address; 773a49ffe3SShahaf Shuler uint8_t autoneg; 783a49ffe3SShahaf Shuler uint8_t mdio_support; 793a49ffe3SShahaf Shuler uint8_t eth_to_mdix; 803a49ffe3SShahaf Shuler uint8_t eth_tp_mdix_ctrl; 813a49ffe3SShahaf Shuler int8_t link_mode_masks_nwords; 823a49ffe3SShahaf Shuler uint32_t reserved[8]; 833a49ffe3SShahaf Shuler uint32_t link_mode_masks[]; 843a49ffe3SShahaf Shuler }; 853a49ffe3SShahaf Shuler 863a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c 873a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5 883a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6 893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17 903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18 913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19 923a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20 933a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21 943a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22 953a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23 963a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24 973a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25 983a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26 993a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27 1003a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28 1013a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29 1023a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30 1033a49ffe3SShahaf Shuler #endif 1043a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G 1053a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31 1063a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32 1073a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33 1083a49ffe3SShahaf Shuler #endif 1093a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G 1103a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34 1113a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35 1123a49ffe3SShahaf Shuler #endif 1133a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G 1143a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36 1153a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37 1163a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38 1173a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39 1183a49ffe3SShahaf Shuler #endif 1193a49ffe3SShahaf Shuler 120771fa900SAdrien Mazarguil /** 1212b730263SAdrien Mazarguil * Get master interface name from private structure. 122771fa900SAdrien Mazarguil * 123af4f09f2SNélio Laranjeiro * @param[in] dev 124af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 125771fa900SAdrien Mazarguil * @param[out] ifname 126771fa900SAdrien Mazarguil * Interface name output buffer. 127771fa900SAdrien Mazarguil * 128771fa900SAdrien Mazarguil * @return 129a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 130771fa900SAdrien Mazarguil */ 1319c2bbd04SViacheslav Ovsiienko int 1329c2bbd04SViacheslav Ovsiienko mlx5_get_master_ifname(const char *ibdev_path, char (*ifname)[IF_NAMESIZE]) 133771fa900SAdrien Mazarguil { 134771fa900SAdrien Mazarguil DIR *dir; 135771fa900SAdrien Mazarguil struct dirent *dent; 136771fa900SAdrien Mazarguil unsigned int dev_type = 0; 137771fa900SAdrien Mazarguil unsigned int dev_port_prev = ~0u; 138771fa900SAdrien Mazarguil char match[IF_NAMESIZE] = ""; 139771fa900SAdrien Mazarguil 1409c2bbd04SViacheslav Ovsiienko assert(ibdev_path); 141771fa900SAdrien Mazarguil { 1429c2bbd04SViacheslav Ovsiienko MKSTR(path, "%s/device/net", ibdev_path); 143771fa900SAdrien Mazarguil 144771fa900SAdrien Mazarguil dir = opendir(path); 145a6d83b6aSNélio Laranjeiro if (dir == NULL) { 146a6d83b6aSNélio Laranjeiro rte_errno = errno; 147a6d83b6aSNélio Laranjeiro return -rte_errno; 148a6d83b6aSNélio Laranjeiro } 149771fa900SAdrien Mazarguil } 150771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 151771fa900SAdrien Mazarguil char *name = dent->d_name; 152771fa900SAdrien Mazarguil FILE *file; 153771fa900SAdrien Mazarguil unsigned int dev_port; 154771fa900SAdrien Mazarguil int r; 155771fa900SAdrien Mazarguil 156771fa900SAdrien Mazarguil if ((name[0] == '.') && 157771fa900SAdrien Mazarguil ((name[1] == '\0') || 158771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 159771fa900SAdrien Mazarguil continue; 160771fa900SAdrien Mazarguil 161771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 1629c2bbd04SViacheslav Ovsiienko ibdev_path, name, 163771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 164771fa900SAdrien Mazarguil 165771fa900SAdrien Mazarguil file = fopen(path, "rb"); 166771fa900SAdrien Mazarguil if (file == NULL) { 167771fa900SAdrien Mazarguil if (errno != ENOENT) 168771fa900SAdrien Mazarguil continue; 169771fa900SAdrien Mazarguil /* 170771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 171771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 172771fa900SAdrien Mazarguil */ 173771fa900SAdrien Mazarguil try_dev_id: 174771fa900SAdrien Mazarguil match[0] = '\0'; 175771fa900SAdrien Mazarguil if (dev_type) 176771fa900SAdrien Mazarguil break; 177771fa900SAdrien Mazarguil dev_type = 1; 178771fa900SAdrien Mazarguil dev_port_prev = ~0u; 179771fa900SAdrien Mazarguil rewinddir(dir); 180771fa900SAdrien Mazarguil continue; 181771fa900SAdrien Mazarguil } 182771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 183771fa900SAdrien Mazarguil fclose(file); 184771fa900SAdrien Mazarguil if (r != 1) 185771fa900SAdrien Mazarguil continue; 186771fa900SAdrien Mazarguil /* 187771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 188771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 189771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 190771fa900SAdrien Mazarguil */ 191771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 192771fa900SAdrien Mazarguil goto try_dev_id; 193771fa900SAdrien Mazarguil dev_port_prev = dev_port; 1949083982cSAdrien Mazarguil if (dev_port == 0) 195c022cb40SBruce Richardson strlcpy(match, name, sizeof(match)); 196771fa900SAdrien Mazarguil } 197771fa900SAdrien Mazarguil closedir(dir); 198a6d83b6aSNélio Laranjeiro if (match[0] == '\0') { 199a6d83b6aSNélio Laranjeiro rte_errno = ENOENT; 200a6d83b6aSNélio Laranjeiro return -rte_errno; 201a6d83b6aSNélio Laranjeiro } 202771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 203771fa900SAdrien Mazarguil return 0; 204771fa900SAdrien Mazarguil } 205771fa900SAdrien Mazarguil 206771fa900SAdrien Mazarguil /** 2072b730263SAdrien Mazarguil * Get interface name from private structure. 2082b730263SAdrien Mazarguil * 2092b730263SAdrien Mazarguil * This is a port representor-aware version of mlx5_get_master_ifname(). 2102b730263SAdrien Mazarguil * 2112b730263SAdrien Mazarguil * @param[in] dev 2122b730263SAdrien Mazarguil * Pointer to Ethernet device. 2132b730263SAdrien Mazarguil * @param[out] ifname 2142b730263SAdrien Mazarguil * Interface name output buffer. 2152b730263SAdrien Mazarguil * 2162b730263SAdrien Mazarguil * @return 2172b730263SAdrien Mazarguil * 0 on success, a negative errno value otherwise and rte_errno is set. 2182b730263SAdrien Mazarguil */ 2192b730263SAdrien Mazarguil int 2202b730263SAdrien Mazarguil mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) 2212b730263SAdrien Mazarguil { 222dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 2239c2bbd04SViacheslav Ovsiienko unsigned int ifindex; 2249c2bbd04SViacheslav Ovsiienko 2259c2bbd04SViacheslav Ovsiienko assert(priv); 2269c2bbd04SViacheslav Ovsiienko assert(priv->sh); 2279c2bbd04SViacheslav Ovsiienko ifindex = priv->nl_socket_rdma >= 0 ? 2289c0a9eedSViacheslav Ovsiienko mlx5_nl_ifindex(priv->nl_socket_rdma, 2299c0a9eedSViacheslav Ovsiienko priv->sh->ibdev_name, 2309c0a9eedSViacheslav Ovsiienko priv->ibv_port) : 0; 2312b730263SAdrien Mazarguil if (!ifindex) { 2322b730263SAdrien Mazarguil if (!priv->representor) 2339c2bbd04SViacheslav Ovsiienko return mlx5_get_master_ifname(priv->sh->ibdev_path, 2349c2bbd04SViacheslav Ovsiienko ifname); 2352b730263SAdrien Mazarguil rte_errno = ENXIO; 2362b730263SAdrien Mazarguil return -rte_errno; 2372b730263SAdrien Mazarguil } 2382b730263SAdrien Mazarguil if (if_indextoname(ifindex, &(*ifname)[0])) 2392b730263SAdrien Mazarguil return 0; 2402b730263SAdrien Mazarguil rte_errno = errno; 2412b730263SAdrien Mazarguil return -rte_errno; 2422b730263SAdrien Mazarguil } 2432b730263SAdrien Mazarguil 2442b730263SAdrien Mazarguil /** 245ccdcba53SNélio Laranjeiro * Get the interface index from device name. 246ccdcba53SNélio Laranjeiro * 247ccdcba53SNélio Laranjeiro * @param[in] dev 248ccdcba53SNélio Laranjeiro * Pointer to Ethernet device. 249ccdcba53SNélio Laranjeiro * 250ccdcba53SNélio Laranjeiro * @return 2513f8cb05dSAdrien Mazarguil * Nonzero interface index on success, zero otherwise and rte_errno is set. 252ccdcba53SNélio Laranjeiro */ 2533f8cb05dSAdrien Mazarguil unsigned int 254ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev) 255ccdcba53SNélio Laranjeiro { 256ccdcba53SNélio Laranjeiro char ifname[IF_NAMESIZE]; 2573f8cb05dSAdrien Mazarguil unsigned int ifindex; 258ccdcba53SNélio Laranjeiro 2593f8cb05dSAdrien Mazarguil if (mlx5_get_ifname(dev, &ifname)) 2603f8cb05dSAdrien Mazarguil return 0; 2613f8cb05dSAdrien Mazarguil ifindex = if_nametoindex(ifname); 2623f8cb05dSAdrien Mazarguil if (!ifindex) 263ccdcba53SNélio Laranjeiro rte_errno = errno; 2643f8cb05dSAdrien Mazarguil return ifindex; 265ccdcba53SNélio Laranjeiro } 266ccdcba53SNélio Laranjeiro 267ccdcba53SNélio Laranjeiro /** 268771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 269771fa900SAdrien Mazarguil * 270af4f09f2SNélio Laranjeiro * @param[in] dev 271af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 272771fa900SAdrien Mazarguil * @param req 273771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 274771fa900SAdrien Mazarguil * @param[out] ifr 275771fa900SAdrien Mazarguil * Interface request structure output buffer. 276771fa900SAdrien Mazarguil * 277771fa900SAdrien Mazarguil * @return 278a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 279771fa900SAdrien Mazarguil */ 280771fa900SAdrien Mazarguil int 2817dd7be29SShahaf Shuler mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr) 282771fa900SAdrien Mazarguil { 283771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 284a6d83b6aSNélio Laranjeiro int ret = 0; 285771fa900SAdrien Mazarguil 286a6d83b6aSNélio Laranjeiro if (sock == -1) { 287a6d83b6aSNélio Laranjeiro rte_errno = errno; 288a6d83b6aSNélio Laranjeiro return -rte_errno; 289a6d83b6aSNélio Laranjeiro } 290a6d83b6aSNélio Laranjeiro ret = mlx5_get_ifname(dev, &ifr->ifr_name); 291a6d83b6aSNélio Laranjeiro if (ret) 292a6d83b6aSNélio Laranjeiro goto error; 293771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 294a6d83b6aSNélio Laranjeiro if (ret == -1) { 295a6d83b6aSNélio Laranjeiro rte_errno = errno; 296a6d83b6aSNélio Laranjeiro goto error; 297a6d83b6aSNélio Laranjeiro } 298771fa900SAdrien Mazarguil close(sock); 299a6d83b6aSNélio Laranjeiro return 0; 300a6d83b6aSNélio Laranjeiro error: 301a6d83b6aSNélio Laranjeiro close(sock); 302a6d83b6aSNélio Laranjeiro return -rte_errno; 303771fa900SAdrien Mazarguil } 304771fa900SAdrien Mazarguil 305771fa900SAdrien Mazarguil /** 306771fa900SAdrien Mazarguil * Get device MTU. 307771fa900SAdrien Mazarguil * 308af4f09f2SNélio Laranjeiro * @param dev 309af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 310771fa900SAdrien Mazarguil * @param[out] mtu 311771fa900SAdrien Mazarguil * MTU value output buffer. 312771fa900SAdrien Mazarguil * 313771fa900SAdrien Mazarguil * @return 314a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 315771fa900SAdrien Mazarguil */ 316771fa900SAdrien Mazarguil int 317af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 318771fa900SAdrien Mazarguil { 319fc40db99SAdrien Mazarguil struct ifreq request; 3207dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request); 321771fa900SAdrien Mazarguil 322fc40db99SAdrien Mazarguil if (ret) 323fc40db99SAdrien Mazarguil return ret; 324fc40db99SAdrien Mazarguil *mtu = request.ifr_mtu; 325859081d3SShahaf Shuler return 0; 326859081d3SShahaf Shuler } 327859081d3SShahaf Shuler 328859081d3SShahaf Shuler /** 329cf37ca95SAdrien Mazarguil * Set device MTU. 330cf37ca95SAdrien Mazarguil * 331af4f09f2SNélio Laranjeiro * @param dev 332af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 333cf37ca95SAdrien Mazarguil * @param mtu 334cf37ca95SAdrien Mazarguil * MTU value to set. 335cf37ca95SAdrien Mazarguil * 336cf37ca95SAdrien Mazarguil * @return 337a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 338cf37ca95SAdrien Mazarguil */ 339cf37ca95SAdrien Mazarguil static int 340af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 341cf37ca95SAdrien Mazarguil { 342fc40db99SAdrien Mazarguil struct ifreq request = { .ifr_mtu = mtu, }; 343f3b492d7SAdrien Mazarguil 3447dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFMTU, &request); 345cf37ca95SAdrien Mazarguil } 346cf37ca95SAdrien Mazarguil 347cf37ca95SAdrien Mazarguil /** 348771fa900SAdrien Mazarguil * Set device flags. 349771fa900SAdrien Mazarguil * 350af4f09f2SNélio Laranjeiro * @param dev 351af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 352771fa900SAdrien Mazarguil * @param keep 353771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 354771fa900SAdrien Mazarguil * @param flags 355771fa900SAdrien Mazarguil * Bitmask for flags to modify. 356771fa900SAdrien Mazarguil * 357771fa900SAdrien Mazarguil * @return 358a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 359771fa900SAdrien Mazarguil */ 360771fa900SAdrien Mazarguil int 361af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags) 362771fa900SAdrien Mazarguil { 363fc40db99SAdrien Mazarguil struct ifreq request; 3647dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request); 365771fa900SAdrien Mazarguil 366fc40db99SAdrien Mazarguil if (ret) 367fc40db99SAdrien Mazarguil return ret; 368fc40db99SAdrien Mazarguil request.ifr_flags &= keep; 369fc40db99SAdrien Mazarguil request.ifr_flags |= flags & ~keep; 3707dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFFLAGS, &request); 371771fa900SAdrien Mazarguil } 372771fa900SAdrien Mazarguil 373771fa900SAdrien Mazarguil /** 3747b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 375e60fbd5bSAdrien Mazarguil * 376e60fbd5bSAdrien Mazarguil * @param dev 377e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 378e60fbd5bSAdrien Mazarguil * 379e60fbd5bSAdrien Mazarguil * @return 380a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 381e60fbd5bSAdrien Mazarguil */ 3827b2423cdSNélio Laranjeiro int 3837b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 384e60fbd5bSAdrien Mazarguil { 385dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 386e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 387e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 388634efbc2SNelio Laranjeiro unsigned int i; 389634efbc2SNelio Laranjeiro unsigned int j; 390634efbc2SNelio Laranjeiro unsigned int reta_idx_n; 39129c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 39221e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 393a6d83b6aSNélio Laranjeiro int ret = 0; 394e60fbd5bSAdrien Mazarguil 39529c1d8bbSNélio Laranjeiro if (use_app_rss_key && 39629c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 397c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN)) { 398c388a2f6SNelio Laranjeiro DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long", 399c388a2f6SNelio Laranjeiro dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 400a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 401a6d83b6aSNélio Laranjeiro return -rte_errno; 40229c1d8bbSNélio Laranjeiro } 40329c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 40429c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 405c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN, 0); 40629c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 407a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)", 4080f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 409a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 410a6d83b6aSNélio Laranjeiro return -rte_errno; 41129c1d8bbSNélio Laranjeiro } 41229c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 41329c1d8bbSNélio Laranjeiro use_app_rss_key ? 41429c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 41529c1d8bbSNélio Laranjeiro rss_hash_default_key, 416c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN); 417c388a2f6SNelio Laranjeiro priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN; 41829c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 419e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 420e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 421e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 422a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u", 4230f99970bSNélio Laranjeiro dev->data->port_id, priv->txqs_n, txqs_n); 424e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 425e60fbd5bSAdrien Mazarguil } 4267fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 427a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 4280f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 429a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 430a6d83b6aSNélio Laranjeiro return -rte_errno; 431634efbc2SNelio Laranjeiro } 43209ba4c58SDekel Peled if (rxqs_n != priv->rxqs_n) { 433a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 4340f99970bSNélio Laranjeiro dev->data->port_id, priv->rxqs_n, rxqs_n); 435e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 43609ba4c58SDekel Peled /* 43709ba4c58SDekel Peled * If the requested number of RX queues is not a power of two, 43809ba4c58SDekel Peled * use the maximum indirection table size for better balancing. 43909ba4c58SDekel Peled * The result is always rounded to the next power of two. 44009ba4c58SDekel Peled */ 441634efbc2SNelio Laranjeiro reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ? 4427fe24446SShahaf Shuler priv->config.ind_table_max_size : 443634efbc2SNelio Laranjeiro rxqs_n)); 444a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 445a6d83b6aSNélio Laranjeiro if (ret) 446a6d83b6aSNélio Laranjeiro return ret; 44709ba4c58SDekel Peled /* 44809ba4c58SDekel Peled * When the number of RX queues is not a power of two, 44909ba4c58SDekel Peled * the remaining table entries are padded with reused WQs 45009ba4c58SDekel Peled * and hashes are not spread uniformly. 45109ba4c58SDekel Peled */ 452634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 453634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = j; 454634efbc2SNelio Laranjeiro if (++j == rxqs_n) 455634efbc2SNelio Laranjeiro j = 0; 456634efbc2SNelio Laranjeiro } 45709ba4c58SDekel Peled } 458120dc4a7SYongseok Koh ret = mlx5_proc_priv_init(dev); 459120dc4a7SYongseok Koh if (ret) 460120dc4a7SYongseok Koh return ret; 461e60fbd5bSAdrien Mazarguil return 0; 462e60fbd5bSAdrien Mazarguil } 463e60fbd5bSAdrien Mazarguil 464e60fbd5bSAdrien Mazarguil /** 465d11d651fSShahaf Shuler * Sets default tuning parameters. 466d11d651fSShahaf Shuler * 467d11d651fSShahaf Shuler * @param dev 468d11d651fSShahaf Shuler * Pointer to Ethernet device. 469d11d651fSShahaf Shuler * @param[out] info 470d11d651fSShahaf Shuler * Info structure output buffer. 471d11d651fSShahaf Shuler */ 472d11d651fSShahaf Shuler static void 473d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 474d11d651fSShahaf Shuler { 475dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 476d11d651fSShahaf Shuler 477d11d651fSShahaf Shuler /* Minimum CPU utilization. */ 478d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 256; 479d11d651fSShahaf Shuler info->default_txportconf.ring_size = 256; 480d11d651fSShahaf Shuler info->default_rxportconf.burst_size = 64; 481d11d651fSShahaf Shuler info->default_txportconf.burst_size = 64; 482d11d651fSShahaf Shuler if (priv->link_speed_capa & ETH_LINK_SPEED_100G) { 483d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 16; 484d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 16; 485d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 486d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 487d11d651fSShahaf Shuler /* Max Throughput. */ 488d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 2048; 489d11d651fSShahaf Shuler info->default_txportconf.ring_size = 2048; 490d11d651fSShahaf Shuler } 491d11d651fSShahaf Shuler } else { 492d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 8; 493d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 8; 494d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 495d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 496d11d651fSShahaf Shuler /* Max Throughput. */ 497d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 4096; 498d11d651fSShahaf Shuler info->default_txportconf.ring_size = 4096; 499d11d651fSShahaf Shuler } 500d11d651fSShahaf Shuler } 501d11d651fSShahaf Shuler } 502d11d651fSShahaf Shuler 503d11d651fSShahaf Shuler /** 504e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 505e60fbd5bSAdrien Mazarguil * 506e60fbd5bSAdrien Mazarguil * @param dev 507e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 508e60fbd5bSAdrien Mazarguil * @param[out] info 509e60fbd5bSAdrien Mazarguil * Info structure output buffer. 510e60fbd5bSAdrien Mazarguil */ 511e60fbd5bSAdrien Mazarguil void 512e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 513e60fbd5bSAdrien Mazarguil { 514dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 5157fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 516e60fbd5bSAdrien Mazarguil unsigned int max; 517e60fbd5bSAdrien Mazarguil char ifname[IF_NAMESIZE]; 518e60fbd5bSAdrien Mazarguil 519e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 520e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 521e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 522e60fbd5bSAdrien Mazarguil /* 523e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 524e60fbd5bSAdrien Mazarguil * between the two values. 525e60fbd5bSAdrien Mazarguil */ 526d485cdcaSViacheslav Ovsiienko max = RTE_MIN(priv->sh->device_attr.orig_attr.max_cq, 527d485cdcaSViacheslav Ovsiienko priv->sh->device_attr.orig_attr.max_qp); 528e60fbd5bSAdrien Mazarguil /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 529e60fbd5bSAdrien Mazarguil if (max >= 65535) 530e60fbd5bSAdrien Mazarguil max = 65535; 531e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 532e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 53318c01b98SNélio Laranjeiro info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; 534af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 535af4f09f2SNélio Laranjeiro info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 53617b843ebSShahaf Shuler info->rx_queue_offload_capa); 537af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 538af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(dev, &ifname) == 0) 539e60fbd5bSAdrien Mazarguil info->if_index = if_nametoindex(ifname); 540d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 5417fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 542c388a2f6SNelio Laranjeiro info->hash_key_size = MLX5_RSS_HASH_KEY_LEN; 54375ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 544b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 545d11d651fSShahaf Shuler mlx5_set_default_params(dev, info); 5462b730263SAdrien Mazarguil info->switch_info.name = dev->data->name; 5472b730263SAdrien Mazarguil info->switch_info.domain_id = priv->domain_id; 5482b730263SAdrien Mazarguil info->switch_info.port_id = priv->representor_id; 5492b730263SAdrien Mazarguil if (priv->representor) { 5502b730263SAdrien Mazarguil unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0); 5512b730263SAdrien Mazarguil uint16_t port_id[i]; 5522b730263SAdrien Mazarguil 5532b730263SAdrien Mazarguil i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i); 5542b730263SAdrien Mazarguil while (i--) { 555dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 5562b730263SAdrien Mazarguil rte_eth_devices[port_id[i]].data->dev_private; 5572b730263SAdrien Mazarguil 5582b730263SAdrien Mazarguil if (!opriv || 5592b730263SAdrien Mazarguil opriv->representor || 5602b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id) 5612b730263SAdrien Mazarguil continue; 5622b730263SAdrien Mazarguil /* 5632b730263SAdrien Mazarguil * Override switch name with that of the master 5642b730263SAdrien Mazarguil * device. 5652b730263SAdrien Mazarguil */ 5662b730263SAdrien Mazarguil info->switch_info.name = opriv->dev_data->name; 5672b730263SAdrien Mazarguil break; 5682b730263SAdrien Mazarguil } 5692b730263SAdrien Mazarguil } 570e60fbd5bSAdrien Mazarguil } 571e60fbd5bSAdrien Mazarguil 572fb732b0aSNélio Laranjeiro /** 573e571ad55STom Barbette * Get device current raw clock counter 574e571ad55STom Barbette * 575e571ad55STom Barbette * @param dev 576e571ad55STom Barbette * Pointer to Ethernet device structure. 577e571ad55STom Barbette * @param[out] time 578e571ad55STom Barbette * Current raw clock counter of the device. 579e571ad55STom Barbette * 580e571ad55STom Barbette * @return 581e571ad55STom Barbette * 0 if the clock has correctly been read 582e571ad55STom Barbette * The value of errno in case of error 583e571ad55STom Barbette */ 584e571ad55STom Barbette int 585e571ad55STom Barbette mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock) 586e571ad55STom Barbette { 587e571ad55STom Barbette struct mlx5_priv *priv = dev->data->dev_private; 588e571ad55STom Barbette struct ibv_context *ctx = priv->sh->ctx; 589e571ad55STom Barbette struct ibv_values_ex values; 590e571ad55STom Barbette int err = 0; 591e571ad55STom Barbette 592e571ad55STom Barbette values.comp_mask = IBV_VALUES_MASK_RAW_CLOCK; 593e571ad55STom Barbette err = mlx5_glue->query_rt_values_ex(ctx, &values); 594e571ad55STom Barbette if (err != 0) { 595e571ad55STom Barbette DRV_LOG(WARNING, "Could not query the clock !"); 596e571ad55STom Barbette return err; 597e571ad55STom Barbette } 598e571ad55STom Barbette *clock = values.raw_clock.tv_nsec; 599e571ad55STom Barbette return 0; 600e571ad55STom Barbette } 601e571ad55STom Barbette 602e571ad55STom Barbette /** 603714bf46eSThomas Monjalon * Get firmware version of a device. 604714bf46eSThomas Monjalon * 605714bf46eSThomas Monjalon * @param dev 606714bf46eSThomas Monjalon * Ethernet device port. 607714bf46eSThomas Monjalon * @param fw_ver 608714bf46eSThomas Monjalon * String output allocated by caller. 609714bf46eSThomas Monjalon * @param fw_size 610714bf46eSThomas Monjalon * Size of the output string, including terminating null byte. 611714bf46eSThomas Monjalon * 612714bf46eSThomas Monjalon * @return 613714bf46eSThomas Monjalon * 0 on success, or the size of the non truncated string if too big. 614714bf46eSThomas Monjalon */ 615714bf46eSThomas Monjalon int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 616714bf46eSThomas Monjalon { 617dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 618d485cdcaSViacheslav Ovsiienko struct ibv_device_attr *attr = &priv->sh->device_attr.orig_attr; 619714bf46eSThomas Monjalon size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 620714bf46eSThomas Monjalon 621714bf46eSThomas Monjalon if (fw_size < size) 622714bf46eSThomas Monjalon return size; 623714bf46eSThomas Monjalon if (fw_ver != NULL) 624714bf46eSThomas Monjalon strlcpy(fw_ver, attr->fw_ver, fw_size); 625714bf46eSThomas Monjalon return 0; 626714bf46eSThomas Monjalon } 627714bf46eSThomas Monjalon 628714bf46eSThomas Monjalon /** 629fb732b0aSNélio Laranjeiro * Get supported packet types. 630fb732b0aSNélio Laranjeiro * 631fb732b0aSNélio Laranjeiro * @param dev 632fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 633fb732b0aSNélio Laranjeiro * 634fb732b0aSNélio Laranjeiro * @return 635fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 636fb732b0aSNélio Laranjeiro */ 63778a38edfSJianfeng Tan const uint32_t * 63878a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 63978a38edfSJianfeng Tan { 64078a38edfSJianfeng Tan static const uint32_t ptypes[] = { 64178a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 642ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 643c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 644c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 645ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 646ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 647ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 648ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 649c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 650c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 651ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 652ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 653ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 654ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 65578a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 65678a38edfSJianfeng Tan }; 65778a38edfSJianfeng Tan 6586cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 6597d6bf6b8SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_mprq || 6606cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 66178a38edfSJianfeng Tan return ptypes; 66278a38edfSJianfeng Tan return NULL; 66378a38edfSJianfeng Tan } 66478a38edfSJianfeng Tan 665e60fbd5bSAdrien Mazarguil /** 6660333b2f5SViacheslav Ovsiienko * Retrieve the master device for representor in the same switch domain. 6670333b2f5SViacheslav Ovsiienko * 6680333b2f5SViacheslav Ovsiienko * @param dev 6690333b2f5SViacheslav Ovsiienko * Pointer to representor Ethernet device structure. 6700333b2f5SViacheslav Ovsiienko * 6710333b2f5SViacheslav Ovsiienko * @return 6720333b2f5SViacheslav Ovsiienko * Master device structure on success, NULL otherwise. 6730333b2f5SViacheslav Ovsiienko */ 6740333b2f5SViacheslav Ovsiienko 6750333b2f5SViacheslav Ovsiienko static struct rte_eth_dev * 6760333b2f5SViacheslav Ovsiienko mlx5_find_master_dev(struct rte_eth_dev *dev) 6770333b2f5SViacheslav Ovsiienko { 6780333b2f5SViacheslav Ovsiienko struct mlx5_priv *priv; 6790333b2f5SViacheslav Ovsiienko uint16_t port_id; 6800333b2f5SViacheslav Ovsiienko uint16_t domain_id; 6810333b2f5SViacheslav Ovsiienko 6820333b2f5SViacheslav Ovsiienko priv = dev->data->dev_private; 6830333b2f5SViacheslav Ovsiienko domain_id = priv->domain_id; 6840333b2f5SViacheslav Ovsiienko assert(priv->representor); 6850333b2f5SViacheslav Ovsiienko RTE_ETH_FOREACH_DEV_OF(port_id, dev->device) { 6860333b2f5SViacheslav Ovsiienko priv = rte_eth_devices[port_id].data->dev_private; 6870333b2f5SViacheslav Ovsiienko if (priv && 6880333b2f5SViacheslav Ovsiienko priv->master && 6890333b2f5SViacheslav Ovsiienko priv->domain_id == domain_id) 6900333b2f5SViacheslav Ovsiienko return &rte_eth_devices[port_id]; 6910333b2f5SViacheslav Ovsiienko } 6920333b2f5SViacheslav Ovsiienko return NULL; 6930333b2f5SViacheslav Ovsiienko } 6940333b2f5SViacheslav Ovsiienko 6950333b2f5SViacheslav Ovsiienko /** 6962c960a51SMatthieu Ternisien d'Ouville * DPDK callback to retrieve physical link information. 697cb8faed7SAdrien Mazarguil * 698cb8faed7SAdrien Mazarguil * @param dev 699cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 700cfee9475SNélio Laranjeiro * @param[out] link 701cfee9475SNélio Laranjeiro * Storage for current link status. 702fb732b0aSNélio Laranjeiro * 703fb732b0aSNélio Laranjeiro * @return 704a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 705cb8faed7SAdrien Mazarguil */ 70618840871SNélio Laranjeiro static int 707cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev, 708cfee9475SNélio Laranjeiro struct rte_eth_link *link) 709cb8faed7SAdrien Mazarguil { 710dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 711cb8faed7SAdrien Mazarguil struct ethtool_cmd edata = { 71275ef62a9SNélio Laranjeiro .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */ 713cb8faed7SAdrien Mazarguil }; 714cb8faed7SAdrien Mazarguil struct ifreq ifr; 715cb8faed7SAdrien Mazarguil struct rte_eth_link dev_link; 716cb8faed7SAdrien Mazarguil int link_speed = 0; 717a6d83b6aSNélio Laranjeiro int ret; 718cb8faed7SAdrien Mazarguil 7197dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 720a6d83b6aSNélio Laranjeiro if (ret) { 721a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 7220f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 723a6d83b6aSNélio Laranjeiro return ret; 724cb8faed7SAdrien Mazarguil } 7257bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 7267bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 7277bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 7287bc47fb8SXueming Li }; 7297bc47fb8SXueming Li ifr = (struct ifreq) { 7307bc47fb8SXueming Li .ifr_data = (void *)&edata, 7317bc47fb8SXueming Li }; 7327dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 733a6d83b6aSNélio Laranjeiro if (ret) { 7340333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 7350333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master; 7360333b2f5SViacheslav Ovsiienko 7370333b2f5SViacheslav Ovsiienko /* 7380333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 7390333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 7400333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 7410333b2f5SViacheslav Ovsiienko * for representors due to missing physical 7420333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 7430333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 7440333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 7450333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 7460333b2f5SViacheslav Ovsiienko */ 7470333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 7480333b2f5SViacheslav Ovsiienko if (master) { 7490333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 7500333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&edata, 7510333b2f5SViacheslav Ovsiienko }; 7520333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 7530333b2f5SViacheslav Ovsiienko } 7540333b2f5SViacheslav Ovsiienko } 7550333b2f5SViacheslav Ovsiienko if (ret) { 756a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 7570333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 7580333b2f5SViacheslav Ovsiienko " ETHTOOL_GSET) failed: %s", 7590f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 760a6d83b6aSNélio Laranjeiro return ret; 761cb8faed7SAdrien Mazarguil } 7620333b2f5SViacheslav Ovsiienko } 763cb8faed7SAdrien Mazarguil link_speed = ethtool_cmd_speed(&edata); 764cb8faed7SAdrien Mazarguil if (link_speed == -1) 7653fef0822SFerruh Yigit dev_link.link_speed = ETH_SPEED_NUM_NONE; 766cb8faed7SAdrien Mazarguil else 767cb8faed7SAdrien Mazarguil dev_link.link_speed = link_speed; 76875ef62a9SNélio Laranjeiro priv->link_speed_capa = 0; 76975ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_Autoneg) 77075ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 77175ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_1000baseT_Full | 77275ef62a9SNélio Laranjeiro SUPPORTED_1000baseKX_Full)) 77375ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 77475ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_10000baseKR_Full) 77575ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 77675ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_40000baseKR4_Full | 77775ef62a9SNélio Laranjeiro SUPPORTED_40000baseCR4_Full | 77875ef62a9SNélio Laranjeiro SUPPORTED_40000baseSR4_Full | 77975ef62a9SNélio Laranjeiro SUPPORTED_40000baseLR4_Full)) 78075ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 781cb8faed7SAdrien Mazarguil dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 782cb8faed7SAdrien Mazarguil ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 78382113036SMarc Sune dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 78482113036SMarc Sune ETH_LINK_SPEED_FIXED); 7857dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 7867bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 787a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 788a6d83b6aSNélio Laranjeiro return -rte_errno; 789cb8faed7SAdrien Mazarguil } 790cfee9475SNélio Laranjeiro *link = dev_link; 791cfee9475SNélio Laranjeiro return 0; 792cfee9475SNélio Laranjeiro } 793cb8faed7SAdrien Mazarguil 794cb8faed7SAdrien Mazarguil /** 7953a49ffe3SShahaf Shuler * Retrieve physical link information (unlocked version using new ioctl). 79618840871SNélio Laranjeiro * 79718840871SNélio Laranjeiro * @param dev 79818840871SNélio Laranjeiro * Pointer to Ethernet device structure. 799cfee9475SNélio Laranjeiro * @param[out] link 800cfee9475SNélio Laranjeiro * Storage for current link status. 801fb732b0aSNélio Laranjeiro * 802fb732b0aSNélio Laranjeiro * @return 803a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 80418840871SNélio Laranjeiro */ 80518840871SNélio Laranjeiro static int 806cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev, 807cfee9475SNélio Laranjeiro struct rte_eth_link *link) 808cfee9475SNélio Laranjeiro 80918840871SNélio Laranjeiro { 810dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 81137a4406cSNélio Laranjeiro struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS }; 81218840871SNélio Laranjeiro struct ifreq ifr; 81318840871SNélio Laranjeiro struct rte_eth_link dev_link; 8140333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master = NULL; 81518840871SNélio Laranjeiro uint64_t sc; 816a6d83b6aSNélio Laranjeiro int ret; 81718840871SNélio Laranjeiro 8187dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 819a6d83b6aSNélio Laranjeiro if (ret) { 820a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 8210f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 822a6d83b6aSNélio Laranjeiro return ret; 82318840871SNélio Laranjeiro } 8247bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 8257bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 8267bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 8277bc47fb8SXueming Li }; 8287bc47fb8SXueming Li ifr = (struct ifreq) { 8297bc47fb8SXueming Li .ifr_data = (void *)&gcmd, 8307bc47fb8SXueming Li }; 8317dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 832a6d83b6aSNélio Laranjeiro if (ret) { 8330333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 8340333b2f5SViacheslav Ovsiienko /* 8350333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 8360333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 8370333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 8380333b2f5SViacheslav Ovsiienko * for representors due to missing physical 8390333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 8400333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 8410333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 8420333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 8430333b2f5SViacheslav Ovsiienko */ 8440333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 8450333b2f5SViacheslav Ovsiienko if (master) { 8460333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 8470333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&gcmd, 8480333b2f5SViacheslav Ovsiienko }; 8490333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 8500333b2f5SViacheslav Ovsiienko } 8510333b2f5SViacheslav Ovsiienko } 8520333b2f5SViacheslav Ovsiienko if (ret) { 853a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 8540333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 8550333b2f5SViacheslav Ovsiienko " ETHTOOL_GLINKSETTINGS) failed: %s", 856a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 857a6d83b6aSNélio Laranjeiro return ret; 85818840871SNélio Laranjeiro } 8590333b2f5SViacheslav Ovsiienko 8600333b2f5SViacheslav Ovsiienko } 86137a4406cSNélio Laranjeiro gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords; 86237a4406cSNélio Laranjeiro 86337a4406cSNélio Laranjeiro alignas(struct ethtool_link_settings) 86437a4406cSNélio Laranjeiro uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) + 86537a4406cSNélio Laranjeiro sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3]; 86637a4406cSNélio Laranjeiro struct ethtool_link_settings *ecmd = (void *)data; 86737a4406cSNélio Laranjeiro 86837a4406cSNélio Laranjeiro *ecmd = gcmd; 86937a4406cSNélio Laranjeiro ifr.ifr_data = (void *)ecmd; 8700333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr); 871a6d83b6aSNélio Laranjeiro if (ret) { 872a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 8730333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 8740333b2f5SViacheslav Ovsiienko "ETHTOOL_GLINKSETTINGS) failed: %s", 875a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 876a6d83b6aSNélio Laranjeiro return ret; 877ef09a7fcSGowrishankar Muthukrishnan } 87890260d57SNélio Laranjeiro dev_link.link_speed = ecmd->speed; 87990260d57SNélio Laranjeiro sc = ecmd->link_mode_masks[0] | 88090260d57SNélio Laranjeiro ((uint64_t)ecmd->link_mode_masks[1] << 32); 88118840871SNélio Laranjeiro priv->link_speed_capa = 0; 882b113cb5eSEdward Makarov if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT)) 88318840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 884b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) | 885b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT))) 88618840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 887b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) | 888b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) | 889b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT))) 89018840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 891b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) | 892b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT))) 89318840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_20G; 894b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) | 895b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) | 896b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) | 897b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT))) 89818840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 899b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) | 900b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) | 901b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) | 902b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT))) 90318840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_56G; 904b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) | 905b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) | 906b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT))) 90718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_25G; 908b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) | 909b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT))) 91018840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_50G; 911b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) | 912b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) | 913b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) | 914b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT))) 91518840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_100G; 91690260d57SNélio Laranjeiro dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ? 91718840871SNélio Laranjeiro ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 91818840871SNélio Laranjeiro dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 91918840871SNélio Laranjeiro ETH_LINK_SPEED_FIXED); 9207dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 9217bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 922a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 923a6d83b6aSNélio Laranjeiro return -rte_errno; 92418840871SNélio Laranjeiro } 925cfee9475SNélio Laranjeiro *link = dev_link; 926cfee9475SNélio Laranjeiro return 0; 927cfee9475SNélio Laranjeiro } 92818840871SNélio Laranjeiro 92918840871SNélio Laranjeiro /** 930cb8faed7SAdrien Mazarguil * DPDK callback to retrieve physical link information. 931cb8faed7SAdrien Mazarguil * 932cb8faed7SAdrien Mazarguil * @param dev 933cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 934cb8faed7SAdrien Mazarguil * @param wait_to_complete 935cfee9475SNélio Laranjeiro * Wait for request completion. 936fb732b0aSNélio Laranjeiro * 937fb732b0aSNélio Laranjeiro * @return 938cfee9475SNélio Laranjeiro * 0 if link status was not updated, positive if it was, a negative errno 939cfee9475SNélio Laranjeiro * value otherwise and rte_errno is set. 940cb8faed7SAdrien Mazarguil */ 941cb8faed7SAdrien Mazarguil int 942cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) 943cb8faed7SAdrien Mazarguil { 944c7bf6225SYongseok Koh int ret; 945cfee9475SNélio Laranjeiro struct rte_eth_link dev_link; 946cfee9475SNélio Laranjeiro time_t start_time = time(NULL); 947cb8faed7SAdrien Mazarguil 948cfee9475SNélio Laranjeiro do { 949cfee9475SNélio Laranjeiro ret = mlx5_link_update_unlocked_gs(dev, &dev_link); 9507d2e32f7SShahaf Shuler if (ret) 9517d2e32f7SShahaf Shuler ret = mlx5_link_update_unlocked_gset(dev, &dev_link); 952cfee9475SNélio Laranjeiro if (ret == 0) 953cfee9475SNélio Laranjeiro break; 954cfee9475SNélio Laranjeiro /* Handle wait to complete situation. */ 955cfee9475SNélio Laranjeiro if (wait_to_complete && ret == -EAGAIN) { 956cfee9475SNélio Laranjeiro if (abs((int)difftime(time(NULL), start_time)) < 957cfee9475SNélio Laranjeiro MLX5_LINK_STATUS_TIMEOUT) { 958cfee9475SNélio Laranjeiro usleep(0); 959cfee9475SNélio Laranjeiro continue; 960cfee9475SNélio Laranjeiro } else { 961cfee9475SNélio Laranjeiro rte_errno = EBUSY; 962cfee9475SNélio Laranjeiro return -rte_errno; 963cfee9475SNélio Laranjeiro } 964cfee9475SNélio Laranjeiro } else if (ret < 0) { 965cfee9475SNélio Laranjeiro return ret; 966cfee9475SNélio Laranjeiro } 967cfee9475SNélio Laranjeiro } while (wait_to_complete); 968cfee9475SNélio Laranjeiro ret = !!memcmp(&dev->data->dev_link, &dev_link, 969cfee9475SNélio Laranjeiro sizeof(struct rte_eth_link)); 970cfee9475SNélio Laranjeiro dev->data->dev_link = dev_link; 971cfee9475SNélio Laranjeiro return ret; 972cb8faed7SAdrien Mazarguil } 973cb8faed7SAdrien Mazarguil 974cb8faed7SAdrien Mazarguil /** 975cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 976cf37ca95SAdrien Mazarguil * 977cf37ca95SAdrien Mazarguil * @param dev 978cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 979cf37ca95SAdrien Mazarguil * @param in_mtu 980cf37ca95SAdrien Mazarguil * New MTU. 981cf37ca95SAdrien Mazarguil * 982cf37ca95SAdrien Mazarguil * @return 983a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 984cf37ca95SAdrien Mazarguil */ 985cf37ca95SAdrien Mazarguil int 986cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 987cf37ca95SAdrien Mazarguil { 988dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 989a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 990a6d83b6aSNélio Laranjeiro int ret; 991cf37ca95SAdrien Mazarguil 992af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 993a0edafe4SNelio Laranjeiro if (ret) 994a6d83b6aSNélio Laranjeiro return ret; 995cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 996af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 997a0edafe4SNelio Laranjeiro if (ret) 998a6d83b6aSNélio Laranjeiro return ret; 999af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 1000a0edafe4SNelio Laranjeiro if (ret) 1001a6d83b6aSNélio Laranjeiro return ret; 1002a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 1003a0edafe4SNelio Laranjeiro priv->mtu = mtu; 1004a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u adapter MTU set to %u", 1005a170a30dSNélio Laranjeiro dev->data->port_id, mtu); 1006a0edafe4SNelio Laranjeiro return 0; 1007a6d83b6aSNélio Laranjeiro } 1008a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 1009a6d83b6aSNélio Laranjeiro return -rte_errno; 1010cf37ca95SAdrien Mazarguil } 1011cf37ca95SAdrien Mazarguil 1012cf37ca95SAdrien Mazarguil /** 101302d75430SAdrien Mazarguil * DPDK callback to get flow control status. 101402d75430SAdrien Mazarguil * 101502d75430SAdrien Mazarguil * @param dev 101602d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 101702d75430SAdrien Mazarguil * @param[out] fc_conf 101802d75430SAdrien Mazarguil * Flow control output buffer. 101902d75430SAdrien Mazarguil * 102002d75430SAdrien Mazarguil * @return 1021a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 102202d75430SAdrien Mazarguil */ 102302d75430SAdrien Mazarguil int 102402d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 102502d75430SAdrien Mazarguil { 102602d75430SAdrien Mazarguil struct ifreq ifr; 102702d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 102802d75430SAdrien Mazarguil .cmd = ETHTOOL_GPAUSEPARAM 102902d75430SAdrien Mazarguil }; 103002d75430SAdrien Mazarguil int ret; 103102d75430SAdrien Mazarguil 1032d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 10337dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1034a6d83b6aSNélio Laranjeiro if (ret) { 1035a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1036a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:" 1037a170a30dSNélio Laranjeiro " %s", 1038a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1039a6d83b6aSNélio Laranjeiro return ret; 104002d75430SAdrien Mazarguil } 104102d75430SAdrien Mazarguil fc_conf->autoneg = ethpause.autoneg; 104202d75430SAdrien Mazarguil if (ethpause.rx_pause && ethpause.tx_pause) 104302d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_FULL; 104402d75430SAdrien Mazarguil else if (ethpause.rx_pause) 104502d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_RX_PAUSE; 104602d75430SAdrien Mazarguil else if (ethpause.tx_pause) 104702d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_TX_PAUSE; 104802d75430SAdrien Mazarguil else 104902d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_NONE; 1050a6d83b6aSNélio Laranjeiro return 0; 105102d75430SAdrien Mazarguil } 105202d75430SAdrien Mazarguil 105302d75430SAdrien Mazarguil /** 105402d75430SAdrien Mazarguil * DPDK callback to modify flow control parameters. 105502d75430SAdrien Mazarguil * 105602d75430SAdrien Mazarguil * @param dev 105702d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 105802d75430SAdrien Mazarguil * @param[in] fc_conf 105902d75430SAdrien Mazarguil * Flow control parameters. 106002d75430SAdrien Mazarguil * 106102d75430SAdrien Mazarguil * @return 1062a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 106302d75430SAdrien Mazarguil */ 106402d75430SAdrien Mazarguil int 106502d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 106602d75430SAdrien Mazarguil { 106702d75430SAdrien Mazarguil struct ifreq ifr; 106802d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 106902d75430SAdrien Mazarguil .cmd = ETHTOOL_SPAUSEPARAM 107002d75430SAdrien Mazarguil }; 107102d75430SAdrien Mazarguil int ret; 107202d75430SAdrien Mazarguil 1073d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 107402d75430SAdrien Mazarguil ethpause.autoneg = fc_conf->autoneg; 107502d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 107602d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_RX_PAUSE)) 107702d75430SAdrien Mazarguil ethpause.rx_pause = 1; 107802d75430SAdrien Mazarguil else 107902d75430SAdrien Mazarguil ethpause.rx_pause = 0; 108002d75430SAdrien Mazarguil 108102d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 108202d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_TX_PAUSE)) 108302d75430SAdrien Mazarguil ethpause.tx_pause = 1; 108402d75430SAdrien Mazarguil else 108502d75430SAdrien Mazarguil ethpause.tx_pause = 0; 10867dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1087a6d83b6aSNélio Laranjeiro if (ret) { 1088a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1089a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 1090a170a30dSNélio Laranjeiro " failed: %s", 1091a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1092a6d83b6aSNélio Laranjeiro return ret; 109302d75430SAdrien Mazarguil } 1094a6d83b6aSNélio Laranjeiro return 0; 109502d75430SAdrien Mazarguil } 109602d75430SAdrien Mazarguil 109702d75430SAdrien Mazarguil /** 1098771fa900SAdrien Mazarguil * Get PCI information from struct ibv_device. 1099771fa900SAdrien Mazarguil * 1100771fa900SAdrien Mazarguil * @param device 1101771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 1102771fa900SAdrien Mazarguil * @param[out] pci_addr 1103771fa900SAdrien Mazarguil * PCI bus address output buffer. 1104771fa900SAdrien Mazarguil * 1105771fa900SAdrien Mazarguil * @return 1106a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1107771fa900SAdrien Mazarguil */ 1108771fa900SAdrien Mazarguil int 1109771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, 1110771fa900SAdrien Mazarguil struct rte_pci_addr *pci_addr) 1111771fa900SAdrien Mazarguil { 1112771fa900SAdrien Mazarguil FILE *file; 1113771fa900SAdrien Mazarguil char line[32]; 1114771fa900SAdrien Mazarguil MKSTR(path, "%s/device/uevent", device->ibdev_path); 1115771fa900SAdrien Mazarguil 1116771fa900SAdrien Mazarguil file = fopen(path, "rb"); 1117a6d83b6aSNélio Laranjeiro if (file == NULL) { 1118a6d83b6aSNélio Laranjeiro rte_errno = errno; 1119a6d83b6aSNélio Laranjeiro return -rte_errno; 1120a6d83b6aSNélio Laranjeiro } 1121771fa900SAdrien Mazarguil while (fgets(line, sizeof(line), file) == line) { 1122771fa900SAdrien Mazarguil size_t len = strlen(line); 1123771fa900SAdrien Mazarguil int ret; 1124771fa900SAdrien Mazarguil 1125771fa900SAdrien Mazarguil /* Truncate long lines. */ 1126771fa900SAdrien Mazarguil if (len == (sizeof(line) - 1)) 1127771fa900SAdrien Mazarguil while (line[(len - 1)] != '\n') { 1128771fa900SAdrien Mazarguil ret = fgetc(file); 1129771fa900SAdrien Mazarguil if (ret == EOF) 1130771fa900SAdrien Mazarguil break; 1131771fa900SAdrien Mazarguil line[(len - 1)] = ret; 1132771fa900SAdrien Mazarguil } 1133771fa900SAdrien Mazarguil /* Extract information. */ 1134771fa900SAdrien Mazarguil if (sscanf(line, 1135771fa900SAdrien Mazarguil "PCI_SLOT_NAME=" 1136463ced95SStephen Hemminger "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 1137771fa900SAdrien Mazarguil &pci_addr->domain, 1138771fa900SAdrien Mazarguil &pci_addr->bus, 1139771fa900SAdrien Mazarguil &pci_addr->devid, 1140771fa900SAdrien Mazarguil &pci_addr->function) == 4) { 1141771fa900SAdrien Mazarguil ret = 0; 1142771fa900SAdrien Mazarguil break; 1143771fa900SAdrien Mazarguil } 1144771fa900SAdrien Mazarguil } 1145771fa900SAdrien Mazarguil fclose(file); 1146771fa900SAdrien Mazarguil return 0; 1147771fa900SAdrien Mazarguil } 1148198a3c33SNelio Laranjeiro 1149198a3c33SNelio Laranjeiro /** 115040d9f906SViacheslav Ovsiienko * Handle asynchronous removal event for entire multiport device. 115140d9f906SViacheslav Ovsiienko * 115240d9f906SViacheslav Ovsiienko * @param sh 115340d9f906SViacheslav Ovsiienko * Infiniband device shared context. 115440d9f906SViacheslav Ovsiienko */ 115540d9f906SViacheslav Ovsiienko static void 115640d9f906SViacheslav Ovsiienko mlx5_dev_interrupt_device_fatal(struct mlx5_ibv_shared *sh) 115740d9f906SViacheslav Ovsiienko { 115840d9f906SViacheslav Ovsiienko uint32_t i; 115940d9f906SViacheslav Ovsiienko 116040d9f906SViacheslav Ovsiienko for (i = 0; i < sh->max_port; ++i) { 116140d9f906SViacheslav Ovsiienko struct rte_eth_dev *dev; 116240d9f906SViacheslav Ovsiienko 116340d9f906SViacheslav Ovsiienko if (sh->port[i].ih_port_id >= RTE_MAX_ETHPORTS) { 116440d9f906SViacheslav Ovsiienko /* 116540d9f906SViacheslav Ovsiienko * Or not existing port either no 116640d9f906SViacheslav Ovsiienko * handler installed for this port. 116740d9f906SViacheslav Ovsiienko */ 116840d9f906SViacheslav Ovsiienko continue; 116940d9f906SViacheslav Ovsiienko } 117040d9f906SViacheslav Ovsiienko dev = &rte_eth_devices[sh->port[i].ih_port_id]; 117140d9f906SViacheslav Ovsiienko assert(dev); 117240d9f906SViacheslav Ovsiienko if (dev->data->dev_conf.intr_conf.rmv) 117340d9f906SViacheslav Ovsiienko _rte_eth_dev_callback_process 117440d9f906SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_RMV, NULL); 117540d9f906SViacheslav Ovsiienko } 117640d9f906SViacheslav Ovsiienko } 117740d9f906SViacheslav Ovsiienko 117840d9f906SViacheslav Ovsiienko /** 1179028b2a28SViacheslav Ovsiienko * Handle shared asynchronous events the NIC (removal event 1180028b2a28SViacheslav Ovsiienko * and link status change). Supports multiport IB device. 1181c26ae069SMatan Azrad * 1182198a3c33SNelio Laranjeiro * @param cb_arg 1183198a3c33SNelio Laranjeiro * Callback argument. 1184198a3c33SNelio Laranjeiro */ 1185198a3c33SNelio Laranjeiro void 1186c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg) 1187198a3c33SNelio Laranjeiro { 1188028b2a28SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = cb_arg; 1189028b2a28SViacheslav Ovsiienko struct ibv_async_event event; 1190198a3c33SNelio Laranjeiro 1191028b2a28SViacheslav Ovsiienko /* Read all message from the IB device and acknowledge them. */ 1192028b2a28SViacheslav Ovsiienko for (;;) { 1193028b2a28SViacheslav Ovsiienko struct rte_eth_dev *dev; 1194028b2a28SViacheslav Ovsiienko uint32_t tmp; 1195028b2a28SViacheslav Ovsiienko 1196028b2a28SViacheslav Ovsiienko if (mlx5_glue->get_async_event(sh->ctx, &event)) 1197028b2a28SViacheslav Ovsiienko break; 1198028b2a28SViacheslav Ovsiienko /* Retrieve and check IB port index. */ 1199028b2a28SViacheslav Ovsiienko tmp = (uint32_t)event.element.port_num; 120040d9f906SViacheslav Ovsiienko if (!tmp && event.event_type == IBV_EVENT_DEVICE_FATAL) { 1201028b2a28SViacheslav Ovsiienko /* 120240d9f906SViacheslav Ovsiienko * The DEVICE_FATAL event is called once for 120340d9f906SViacheslav Ovsiienko * entire device without port specifying. 120440d9f906SViacheslav Ovsiienko * We should notify all existing ports. 1205028b2a28SViacheslav Ovsiienko */ 1206028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 120740d9f906SViacheslav Ovsiienko mlx5_dev_interrupt_device_fatal(sh); 120840d9f906SViacheslav Ovsiienko continue; 120940d9f906SViacheslav Ovsiienko } 121040d9f906SViacheslav Ovsiienko assert(tmp && (tmp <= sh->max_port)); 121140d9f906SViacheslav Ovsiienko if (!tmp) { 121240d9f906SViacheslav Ovsiienko /* Unsupported devive level event. */ 121340d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 121440d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 121540d9f906SViacheslav Ovsiienko "unsupported common event (type %d)", 121640d9f906SViacheslav Ovsiienko event.event_type); 121740d9f906SViacheslav Ovsiienko continue; 121840d9f906SViacheslav Ovsiienko } 121940d9f906SViacheslav Ovsiienko if (tmp > sh->max_port) { 122040d9f906SViacheslav Ovsiienko /* Invalid IB port index. */ 122140d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 122240d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 122340d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 122440d9f906SViacheslav Ovsiienko "due to invalid IB port index (%u)", 122540d9f906SViacheslav Ovsiienko event.event_type, tmp); 122640d9f906SViacheslav Ovsiienko continue; 122740d9f906SViacheslav Ovsiienko } 122840d9f906SViacheslav Ovsiienko if (sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) { 122940d9f906SViacheslav Ovsiienko /* No handler installed. */ 123040d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 123140d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 123240d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 123340d9f906SViacheslav Ovsiienko "due to no handler installed for port %u", 123440d9f906SViacheslav Ovsiienko event.event_type, tmp); 1235028b2a28SViacheslav Ovsiienko continue; 1236028b2a28SViacheslav Ovsiienko } 1237028b2a28SViacheslav Ovsiienko /* Retrieve ethernet device descriptor. */ 1238028b2a28SViacheslav Ovsiienko tmp = sh->port[tmp - 1].ih_port_id; 1239028b2a28SViacheslav Ovsiienko dev = &rte_eth_devices[tmp]; 1240028b2a28SViacheslav Ovsiienko assert(dev); 1241028b2a28SViacheslav Ovsiienko if ((event.event_type == IBV_EVENT_PORT_ACTIVE || 1242028b2a28SViacheslav Ovsiienko event.event_type == IBV_EVENT_PORT_ERR) && 1243028b2a28SViacheslav Ovsiienko dev->data->dev_conf.intr_conf.lsc) { 1244028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1245028b2a28SViacheslav Ovsiienko if (mlx5_link_update(dev, 0) == -EAGAIN) { 1246028b2a28SViacheslav Ovsiienko usleep(0); 1247028b2a28SViacheslav Ovsiienko continue; 1248028b2a28SViacheslav Ovsiienko } 1249028b2a28SViacheslav Ovsiienko _rte_eth_dev_callback_process 1250028b2a28SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_LSC, NULL); 1251028b2a28SViacheslav Ovsiienko continue; 1252028b2a28SViacheslav Ovsiienko } 1253028b2a28SViacheslav Ovsiienko DRV_LOG(DEBUG, 125440d9f906SViacheslav Ovsiienko "port %u cannot handle an unknown event (type %d)", 1255028b2a28SViacheslav Ovsiienko dev->data->port_id, event.event_type); 1256028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1257028b2a28SViacheslav Ovsiienko } 1258198a3c33SNelio Laranjeiro } 1259198a3c33SNelio Laranjeiro 1260*5897ac13SViacheslav Ovsiienko /* 1261*5897ac13SViacheslav Ovsiienko * Unregister callback handler safely. The handler may be active 1262*5897ac13SViacheslav Ovsiienko * while we are trying to unregister it, in this case code -EAGAIN 1263*5897ac13SViacheslav Ovsiienko * is returned by rte_intr_callback_unregister(). This routine checks 1264*5897ac13SViacheslav Ovsiienko * the return code and tries to unregister handler again. 1265*5897ac13SViacheslav Ovsiienko * 1266*5897ac13SViacheslav Ovsiienko * @param handle 1267*5897ac13SViacheslav Ovsiienko * interrupt handle 1268*5897ac13SViacheslav Ovsiienko * @param cb_fn 1269*5897ac13SViacheslav Ovsiienko * pointer to callback routine 1270*5897ac13SViacheslav Ovsiienko * @cb_arg 1271*5897ac13SViacheslav Ovsiienko * opaque callback parameter 1272*5897ac13SViacheslav Ovsiienko */ 1273*5897ac13SViacheslav Ovsiienko void 1274*5897ac13SViacheslav Ovsiienko mlx5_intr_callback_unregister(const struct rte_intr_handle *handle, 1275*5897ac13SViacheslav Ovsiienko rte_intr_callback_fn cb_fn, void *cb_arg) 1276*5897ac13SViacheslav Ovsiienko { 1277*5897ac13SViacheslav Ovsiienko /* 1278*5897ac13SViacheslav Ovsiienko * Try to reduce timeout management overhead by not calling 1279*5897ac13SViacheslav Ovsiienko * the timer related routines on the first iteration. If the 1280*5897ac13SViacheslav Ovsiienko * unregistering succeeds on first call there will be no 1281*5897ac13SViacheslav Ovsiienko * timer calls at all. 1282*5897ac13SViacheslav Ovsiienko */ 1283*5897ac13SViacheslav Ovsiienko uint64_t twait = 0; 1284*5897ac13SViacheslav Ovsiienko uint64_t start = 0; 1285*5897ac13SViacheslav Ovsiienko 1286*5897ac13SViacheslav Ovsiienko do { 1287*5897ac13SViacheslav Ovsiienko int ret; 1288*5897ac13SViacheslav Ovsiienko 1289*5897ac13SViacheslav Ovsiienko ret = rte_intr_callback_unregister(handle, cb_fn, cb_arg); 1290*5897ac13SViacheslav Ovsiienko if (ret >= 0) 1291*5897ac13SViacheslav Ovsiienko return; 1292*5897ac13SViacheslav Ovsiienko if (ret != -EAGAIN) { 1293*5897ac13SViacheslav Ovsiienko DRV_LOG(INFO, "failed to unregister interrupt" 1294*5897ac13SViacheslav Ovsiienko " handler (error: %d)", ret); 1295*5897ac13SViacheslav Ovsiienko assert(false); 1296*5897ac13SViacheslav Ovsiienko return; 1297*5897ac13SViacheslav Ovsiienko } 1298*5897ac13SViacheslav Ovsiienko if (twait) { 1299*5897ac13SViacheslav Ovsiienko struct timespec onems; 1300*5897ac13SViacheslav Ovsiienko 1301*5897ac13SViacheslav Ovsiienko /* Wait one millisecond and try again. */ 1302*5897ac13SViacheslav Ovsiienko onems.tv_sec = 0; 1303*5897ac13SViacheslav Ovsiienko onems.tv_nsec = NS_PER_S / MS_PER_S; 1304*5897ac13SViacheslav Ovsiienko nanosleep(&onems, 0); 1305*5897ac13SViacheslav Ovsiienko /* Check whether one second elapsed. */ 1306*5897ac13SViacheslav Ovsiienko if ((rte_get_timer_cycles() - start) <= twait) 1307*5897ac13SViacheslav Ovsiienko continue; 1308*5897ac13SViacheslav Ovsiienko } else { 1309*5897ac13SViacheslav Ovsiienko /* 1310*5897ac13SViacheslav Ovsiienko * We get the amount of timer ticks for one second. 1311*5897ac13SViacheslav Ovsiienko * If this amount elapsed it means we spent one 1312*5897ac13SViacheslav Ovsiienko * second in waiting. This branch is executed once 1313*5897ac13SViacheslav Ovsiienko * on first iteration. 1314*5897ac13SViacheslav Ovsiienko */ 1315*5897ac13SViacheslav Ovsiienko twait = rte_get_timer_hz(); 1316*5897ac13SViacheslav Ovsiienko assert(twait); 1317*5897ac13SViacheslav Ovsiienko } 1318*5897ac13SViacheslav Ovsiienko /* 1319*5897ac13SViacheslav Ovsiienko * Timeout elapsed, show message (once a second) and retry. 1320*5897ac13SViacheslav Ovsiienko * We have no other acceptable option here, if we ignore 1321*5897ac13SViacheslav Ovsiienko * the unregistering return code the handler will not 1322*5897ac13SViacheslav Ovsiienko * be unregistered, fd will be closed and we may get the 1323*5897ac13SViacheslav Ovsiienko * crush. Hanging and messaging in the loop seems not to be 1324*5897ac13SViacheslav Ovsiienko * the worst choice. 1325*5897ac13SViacheslav Ovsiienko */ 1326*5897ac13SViacheslav Ovsiienko DRV_LOG(INFO, "Retrying to unregister interrupt handler"); 1327*5897ac13SViacheslav Ovsiienko start = rte_get_timer_cycles(); 1328*5897ac13SViacheslav Ovsiienko } while (true); 1329*5897ac13SViacheslav Ovsiienko } 1330*5897ac13SViacheslav Ovsiienko 1331198a3c33SNelio Laranjeiro /** 133253e5a82fSViacheslav Ovsiienko * Uninstall shared asynchronous device events handler. 1333*5897ac13SViacheslav Ovsiienko * This function is implemented to support event sharing 133453e5a82fSViacheslav Ovsiienko * between multiple ports of single IB device. 133553e5a82fSViacheslav Ovsiienko * 133653e5a82fSViacheslav Ovsiienko * @param dev 133753e5a82fSViacheslav Ovsiienko * Pointer to Ethernet device. 133853e5a82fSViacheslav Ovsiienko */ 133953e5a82fSViacheslav Ovsiienko static void 134053e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev) 134153e5a82fSViacheslav Ovsiienko { 134253e5a82fSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 134353e5a82fSViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 134453e5a82fSViacheslav Ovsiienko 134553e5a82fSViacheslav Ovsiienko if (rte_eal_process_type() != RTE_PROC_PRIMARY) 134653e5a82fSViacheslav Ovsiienko return; 134753e5a82fSViacheslav Ovsiienko pthread_mutex_lock(&sh->intr_mutex); 134853e5a82fSViacheslav Ovsiienko assert(priv->ibv_port); 134953e5a82fSViacheslav Ovsiienko assert(priv->ibv_port <= sh->max_port); 135053e5a82fSViacheslav Ovsiienko assert(dev->data->port_id < RTE_MAX_ETHPORTS); 135153e5a82fSViacheslav Ovsiienko if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS) 135253e5a82fSViacheslav Ovsiienko goto exit; 135353e5a82fSViacheslav Ovsiienko assert(sh->port[priv->ibv_port - 1].ih_port_id == 135453e5a82fSViacheslav Ovsiienko (uint32_t)dev->data->port_id); 135553e5a82fSViacheslav Ovsiienko assert(sh->intr_cnt); 135653e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; 135753e5a82fSViacheslav Ovsiienko if (!sh->intr_cnt || --sh->intr_cnt) 135853e5a82fSViacheslav Ovsiienko goto exit; 1359*5897ac13SViacheslav Ovsiienko mlx5_intr_callback_unregister(&sh->intr_handle, 136053e5a82fSViacheslav Ovsiienko mlx5_dev_interrupt_handler, sh); 136153e5a82fSViacheslav Ovsiienko sh->intr_handle.fd = 0; 136253e5a82fSViacheslav Ovsiienko sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 136353e5a82fSViacheslav Ovsiienko exit: 136453e5a82fSViacheslav Ovsiienko pthread_mutex_unlock(&sh->intr_mutex); 136553e5a82fSViacheslav Ovsiienko } 136653e5a82fSViacheslav Ovsiienko 136753e5a82fSViacheslav Ovsiienko /** 1368*5897ac13SViacheslav Ovsiienko * Install shared asynchronous device events handler. 1369*5897ac13SViacheslav Ovsiienko * This function is implemented to support event sharing 137053e5a82fSViacheslav Ovsiienko * between multiple ports of single IB device. 137153e5a82fSViacheslav Ovsiienko * 137253e5a82fSViacheslav Ovsiienko * @param dev 137353e5a82fSViacheslav Ovsiienko * Pointer to Ethernet device. 137453e5a82fSViacheslav Ovsiienko */ 137553e5a82fSViacheslav Ovsiienko static void 137653e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_install(struct rte_eth_dev *dev) 137753e5a82fSViacheslav Ovsiienko { 137853e5a82fSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 137953e5a82fSViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 138053e5a82fSViacheslav Ovsiienko int ret; 138153e5a82fSViacheslav Ovsiienko int flags; 138253e5a82fSViacheslav Ovsiienko 138353e5a82fSViacheslav Ovsiienko if (rte_eal_process_type() != RTE_PROC_PRIMARY) 138453e5a82fSViacheslav Ovsiienko return; 138553e5a82fSViacheslav Ovsiienko pthread_mutex_lock(&sh->intr_mutex); 138653e5a82fSViacheslav Ovsiienko assert(priv->ibv_port); 138753e5a82fSViacheslav Ovsiienko assert(priv->ibv_port <= sh->max_port); 138853e5a82fSViacheslav Ovsiienko assert(dev->data->port_id < RTE_MAX_ETHPORTS); 138953e5a82fSViacheslav Ovsiienko if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) { 139053e5a82fSViacheslav Ovsiienko /* The handler is already installed for this port. */ 139153e5a82fSViacheslav Ovsiienko assert(sh->intr_cnt); 139253e5a82fSViacheslav Ovsiienko goto exit; 139353e5a82fSViacheslav Ovsiienko } 139453e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = (uint32_t)dev->data->port_id; 139553e5a82fSViacheslav Ovsiienko if (sh->intr_cnt) { 139653e5a82fSViacheslav Ovsiienko sh->intr_cnt++; 139753e5a82fSViacheslav Ovsiienko goto exit; 139853e5a82fSViacheslav Ovsiienko } 139953e5a82fSViacheslav Ovsiienko /* No shared handler installed. */ 140053e5a82fSViacheslav Ovsiienko assert(sh->ctx->async_fd > 0); 140153e5a82fSViacheslav Ovsiienko flags = fcntl(sh->ctx->async_fd, F_GETFL); 140253e5a82fSViacheslav Ovsiienko ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); 140353e5a82fSViacheslav Ovsiienko if (ret) { 140453e5a82fSViacheslav Ovsiienko DRV_LOG(INFO, "failed to change file descriptor" 140553e5a82fSViacheslav Ovsiienko " async event queue"); 140653e5a82fSViacheslav Ovsiienko /* Indicate there will be no interrupts. */ 140753e5a82fSViacheslav Ovsiienko dev->data->dev_conf.intr_conf.lsc = 0; 140853e5a82fSViacheslav Ovsiienko dev->data->dev_conf.intr_conf.rmv = 0; 140953e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; 141053e5a82fSViacheslav Ovsiienko goto exit; 141153e5a82fSViacheslav Ovsiienko } 141253e5a82fSViacheslav Ovsiienko sh->intr_handle.fd = sh->ctx->async_fd; 141353e5a82fSViacheslav Ovsiienko sh->intr_handle.type = RTE_INTR_HANDLE_EXT; 141453e5a82fSViacheslav Ovsiienko rte_intr_callback_register(&sh->intr_handle, 141553e5a82fSViacheslav Ovsiienko mlx5_dev_interrupt_handler, sh); 141653e5a82fSViacheslav Ovsiienko sh->intr_cnt++; 141753e5a82fSViacheslav Ovsiienko exit: 141853e5a82fSViacheslav Ovsiienko pthread_mutex_unlock(&sh->intr_mutex); 141953e5a82fSViacheslav Ovsiienko } 142053e5a82fSViacheslav Ovsiienko 142153e5a82fSViacheslav Ovsiienko /** 1422198a3c33SNelio Laranjeiro * Uninstall interrupt handler. 1423198a3c33SNelio Laranjeiro * 1424198a3c33SNelio Laranjeiro * @param dev 1425af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1426198a3c33SNelio Laranjeiro */ 1427198a3c33SNelio Laranjeiro void 1428af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev) 1429198a3c33SNelio Laranjeiro { 143053e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_uninstall(dev); 1431198a3c33SNelio Laranjeiro } 1432198a3c33SNelio Laranjeiro 1433198a3c33SNelio Laranjeiro /** 1434198a3c33SNelio Laranjeiro * Install interrupt handler. 1435198a3c33SNelio Laranjeiro * 1436198a3c33SNelio Laranjeiro * @param dev 1437af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1438198a3c33SNelio Laranjeiro */ 1439198a3c33SNelio Laranjeiro void 1440af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev) 1441198a3c33SNelio Laranjeiro { 144253e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_install(dev); 1443198a3c33SNelio Laranjeiro } 144462072098SOr Ami 144562072098SOr Ami /** 144662072098SOr Ami * DPDK callback to bring the link DOWN. 144762072098SOr Ami * 144862072098SOr Ami * @param dev 144962072098SOr Ami * Pointer to Ethernet device structure. 145062072098SOr Ami * 145162072098SOr Ami * @return 1452a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 145362072098SOr Ami */ 145462072098SOr Ami int 145562072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev) 145662072098SOr Ami { 1457af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP); 145862072098SOr Ami } 145962072098SOr Ami 146062072098SOr Ami /** 146162072098SOr Ami * DPDK callback to bring the link UP. 146262072098SOr Ami * 146362072098SOr Ami * @param dev 146462072098SOr Ami * Pointer to Ethernet device structure. 146562072098SOr Ami * 146662072098SOr Ami * @return 1467a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 146862072098SOr Ami */ 146962072098SOr Ami int 147062072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev) 147162072098SOr Ami { 1472af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, IFF_UP); 147362072098SOr Ami } 1474a48deadaSOr Ami 1475a48deadaSOr Ami /** 1476cdab90cbSNélio Laranjeiro * Configure the TX function to use. 1477cdab90cbSNélio Laranjeiro * 1478aee1b165SXueming Li * @param dev 1479af4f09f2SNélio Laranjeiro * Pointer to private data structure. 14801cfa649bSShahaf Shuler * 14811cfa649bSShahaf Shuler * @return 14821cfa649bSShahaf Shuler * Pointer to selected Tx burst function. 1483cdab90cbSNélio Laranjeiro */ 14841cfa649bSShahaf Shuler eth_tx_burst_t 1485af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev) 1486cdab90cbSNélio Laranjeiro { 1487dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 14881cfa649bSShahaf Shuler eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst; 14897fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 1490dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 1491dbccb4cdSShahaf Shuler int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO | 1492dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 149332d4246cSXueming Li DEV_TX_OFFLOAD_GRE_TNL_TSO | 149432d4246cSXueming Li DEV_TX_OFFLOAD_IP_TNL_TSO | 149532d4246cSXueming Li DEV_TX_OFFLOAD_UDP_TNL_TSO)); 14965f8ba81cSXueming Li int swp = !!(tx_offloads & (DEV_TX_OFFLOAD_IP_TNL_TSO | 14975f8ba81cSXueming Li DEV_TX_OFFLOAD_UDP_TNL_TSO | 14985f8ba81cSXueming Li DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)); 1499dbccb4cdSShahaf Shuler int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT); 15001cfa649bSShahaf Shuler 1501aee1b165SXueming Li assert(priv != NULL); 1502230189d9SNélio Laranjeiro /* Select appropriate TX function. */ 15035f8ba81cSXueming Li if (vlan_insert || tso || swp) 1504dbccb4cdSShahaf Shuler return tx_pkt_burst; 15057fe24446SShahaf Shuler if (config->mps == MLX5_MPW_ENHANCED) { 1506af4f09f2SNélio Laranjeiro if (mlx5_check_vec_tx_support(dev) > 0) { 1507af4f09f2SNélio Laranjeiro if (mlx5_check_raw_vec_tx_support(dev) > 0) 15081cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_raw_vec; 15096cb559d6SYongseok Koh else 15101cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_vec; 1511a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 1512a170a30dSNélio Laranjeiro "port %u selected enhanced MPW Tx vectorized" 1513a170a30dSNélio Laranjeiro " function", 1514a170a30dSNélio Laranjeiro dev->data->port_id); 15156cb559d6SYongseok Koh } else { 15161cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_empw; 1517a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 1518a170a30dSNélio Laranjeiro "port %u selected enhanced MPW Tx function", 15190f99970bSNélio Laranjeiro dev->data->port_id); 15206cb559d6SYongseok Koh } 15217fe24446SShahaf Shuler } else if (config->mps && (config->txq_inline > 0)) { 15221cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw_inline; 1523a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected MPW inline Tx function", 15240f99970bSNélio Laranjeiro dev->data->port_id); 15257fe24446SShahaf Shuler } else if (config->mps) { 15261cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw; 1527a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected MPW Tx function", 1528a170a30dSNélio Laranjeiro dev->data->port_id); 15292a66cf37SYaacov Hazan } 15301cfa649bSShahaf Shuler return tx_pkt_burst; 1531cdab90cbSNélio Laranjeiro } 1532cdab90cbSNélio Laranjeiro 1533cdab90cbSNélio Laranjeiro /** 1534cdab90cbSNélio Laranjeiro * Configure the RX function to use. 1535cdab90cbSNélio Laranjeiro * 1536aee1b165SXueming Li * @param dev 1537af4f09f2SNélio Laranjeiro * Pointer to private data structure. 15381cfa649bSShahaf Shuler * 15391cfa649bSShahaf Shuler * @return 15401cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 1541cdab90cbSNélio Laranjeiro */ 15421cfa649bSShahaf Shuler eth_rx_burst_t 1543af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 1544cdab90cbSNélio Laranjeiro { 15451cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 15461cfa649bSShahaf Shuler 1547af4f09f2SNélio Laranjeiro assert(dev != NULL); 1548af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 15491cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 1550a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected Rx vectorized function", 15510f99970bSNélio Laranjeiro dev->data->port_id); 15527d6bf6b8SYongseok Koh } else if (mlx5_mprq_enabled(dev)) { 15537d6bf6b8SYongseok Koh rx_pkt_burst = mlx5_rx_burst_mprq; 1554cdab90cbSNélio Laranjeiro } 15551cfa649bSShahaf Shuler return rx_pkt_burst; 15566cb559d6SYongseok Koh } 1557d3e0f392SMatan Azrad 1558d3e0f392SMatan Azrad /** 1559d3e0f392SMatan Azrad * Check if mlx5 device was removed. 1560d3e0f392SMatan Azrad * 1561d3e0f392SMatan Azrad * @param dev 1562d3e0f392SMatan Azrad * Pointer to Ethernet device structure. 1563d3e0f392SMatan Azrad * 1564d3e0f392SMatan Azrad * @return 1565d3e0f392SMatan Azrad * 1 when device is removed, otherwise 0. 1566d3e0f392SMatan Azrad */ 1567d3e0f392SMatan Azrad int 1568d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev) 1569d3e0f392SMatan Azrad { 1570d3e0f392SMatan Azrad struct ibv_device_attr device_attr; 1571dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 1572d3e0f392SMatan Azrad 1573f048f3d4SViacheslav Ovsiienko if (mlx5_glue->query_device(priv->sh->ctx, &device_attr) == EIO) 1574d3e0f392SMatan Azrad return 1; 1575d3e0f392SMatan Azrad return 0; 1576d3e0f392SMatan Azrad } 15772b730263SAdrien Mazarguil 15782b730263SAdrien Mazarguil /** 15792b730263SAdrien Mazarguil * Get port ID list of mlx5 instances sharing a common device. 15802b730263SAdrien Mazarguil * 15812b730263SAdrien Mazarguil * @param[in] dev 15822b730263SAdrien Mazarguil * Device to look for. 15832b730263SAdrien Mazarguil * @param[out] port_list 15842b730263SAdrien Mazarguil * Result buffer for collected port IDs. 15852b730263SAdrien Mazarguil * @param port_list_n 15862b730263SAdrien Mazarguil * Maximum number of entries in result buffer. If 0, @p port_list can be 15872b730263SAdrien Mazarguil * NULL. 15882b730263SAdrien Mazarguil * 15892b730263SAdrien Mazarguil * @return 15902b730263SAdrien Mazarguil * Number of matching instances regardless of the @p port_list_n 15912b730263SAdrien Mazarguil * parameter, 0 if none were found. 15922b730263SAdrien Mazarguil */ 15932b730263SAdrien Mazarguil unsigned int 15942b730263SAdrien Mazarguil mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list, 15952b730263SAdrien Mazarguil unsigned int port_list_n) 15962b730263SAdrien Mazarguil { 15972b730263SAdrien Mazarguil uint16_t id; 15982b730263SAdrien Mazarguil unsigned int n = 0; 15992b730263SAdrien Mazarguil 1600d874a4eeSThomas Monjalon RTE_ETH_FOREACH_DEV_OF(id, dev) { 16012b730263SAdrien Mazarguil if (n < port_list_n) 16022b730263SAdrien Mazarguil port_list[n] = id; 16032b730263SAdrien Mazarguil n++; 16042b730263SAdrien Mazarguil } 16052b730263SAdrien Mazarguil return n; 16062b730263SAdrien Mazarguil } 1607f872b4b9SNelio Laranjeiro 1608f872b4b9SNelio Laranjeiro /** 16092e4c987aSOri Kam * Get the E-Switch domain id this port belongs to. 16102e4c987aSOri Kam * 16112e4c987aSOri Kam * @param[in] port 16122e4c987aSOri Kam * Device port id. 16132e4c987aSOri Kam * @param[out] es_domain_id 16142e4c987aSOri Kam * E-Switch domain id. 16152e4c987aSOri Kam * @param[out] es_port_id 16162e4c987aSOri Kam * The port id of the port in the E-Switch. 16172e4c987aSOri Kam * 16182e4c987aSOri Kam * @return 16192e4c987aSOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 16202e4c987aSOri Kam */ 16212e4c987aSOri Kam int 16222e4c987aSOri Kam mlx5_port_to_eswitch_info(uint16_t port, 16232e4c987aSOri Kam uint16_t *es_domain_id, uint16_t *es_port_id) 16242e4c987aSOri Kam { 16252e4c987aSOri Kam struct rte_eth_dev *dev; 16262e4c987aSOri Kam struct mlx5_priv *priv; 16272e4c987aSOri Kam 16282e4c987aSOri Kam if (port >= RTE_MAX_ETHPORTS) { 16292e4c987aSOri Kam rte_errno = EINVAL; 16302e4c987aSOri Kam return -rte_errno; 16312e4c987aSOri Kam } 16322e4c987aSOri Kam if (!rte_eth_dev_is_valid_port(port)) { 16332e4c987aSOri Kam rte_errno = ENODEV; 16342e4c987aSOri Kam return -rte_errno; 16352e4c987aSOri Kam } 16362e4c987aSOri Kam dev = &rte_eth_devices[port]; 16372e4c987aSOri Kam priv = dev->data->dev_private; 16382e4c987aSOri Kam if (!(priv->representor || priv->master)) { 16392e4c987aSOri Kam rte_errno = EINVAL; 16402e4c987aSOri Kam return -rte_errno; 16412e4c987aSOri Kam } 16422e4c987aSOri Kam if (es_domain_id) 16432e4c987aSOri Kam *es_domain_id = priv->domain_id; 16442e4c987aSOri Kam if (es_port_id) 16452e4c987aSOri Kam *es_port_id = priv->vport_id; 16462e4c987aSOri Kam return 0; 16472e4c987aSOri Kam } 16482e4c987aSOri Kam 16492e4c987aSOri Kam /** 1650f872b4b9SNelio Laranjeiro * Get switch information associated with network interface. 1651f872b4b9SNelio Laranjeiro * 1652f872b4b9SNelio Laranjeiro * @param ifindex 1653f872b4b9SNelio Laranjeiro * Network interface index. 1654f872b4b9SNelio Laranjeiro * @param[out] info 1655f872b4b9SNelio Laranjeiro * Switch information object, populated in case of success. 1656f872b4b9SNelio Laranjeiro * 1657f872b4b9SNelio Laranjeiro * @return 1658f872b4b9SNelio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1659f872b4b9SNelio Laranjeiro */ 1660f872b4b9SNelio Laranjeiro int 1661f872b4b9SNelio Laranjeiro mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) 1662f872b4b9SNelio Laranjeiro { 1663f872b4b9SNelio Laranjeiro char ifname[IF_NAMESIZE]; 1664b2f3a381SDekel Peled char port_name[IF_NAMESIZE]; 1665f872b4b9SNelio Laranjeiro FILE *file; 1666b2f3a381SDekel Peled struct mlx5_switch_info data = { 1667b2f3a381SDekel Peled .master = 0, 1668b2f3a381SDekel Peled .representor = 0, 166930a86157SViacheslav Ovsiienko .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET, 1670b2f3a381SDekel Peled .port_name = 0, 1671b2f3a381SDekel Peled .switch_id = 0, 1672b2f3a381SDekel Peled }; 1673299d7dc2SViacheslav Ovsiienko DIR *dir; 1674f872b4b9SNelio Laranjeiro bool port_switch_id_set = false; 1675299d7dc2SViacheslav Ovsiienko bool device_dir = false; 1676f872b4b9SNelio Laranjeiro char c; 1677e3bcaf3aSAli Alnubani int ret; 1678f872b4b9SNelio Laranjeiro 1679f872b4b9SNelio Laranjeiro if (!if_indextoname(ifindex, ifname)) { 1680f872b4b9SNelio Laranjeiro rte_errno = errno; 1681f872b4b9SNelio Laranjeiro return -rte_errno; 1682f872b4b9SNelio Laranjeiro } 1683f872b4b9SNelio Laranjeiro 1684f872b4b9SNelio Laranjeiro MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name", 1685f872b4b9SNelio Laranjeiro ifname); 1686f872b4b9SNelio Laranjeiro MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id", 1687f872b4b9SNelio Laranjeiro ifname); 1688299d7dc2SViacheslav Ovsiienko MKSTR(pci_device, "/sys/class/net/%s/device", 1689299d7dc2SViacheslav Ovsiienko ifname); 1690f872b4b9SNelio Laranjeiro 1691f872b4b9SNelio Laranjeiro file = fopen(phys_port_name, "rb"); 1692f872b4b9SNelio Laranjeiro if (file != NULL) { 1693e3bcaf3aSAli Alnubani ret = fscanf(file, "%s", port_name); 1694f872b4b9SNelio Laranjeiro fclose(file); 1695e3bcaf3aSAli Alnubani if (ret == 1) 169630a86157SViacheslav Ovsiienko mlx5_translate_port_name(port_name, &data); 1697f872b4b9SNelio Laranjeiro } 1698f872b4b9SNelio Laranjeiro file = fopen(phys_switch_id, "rb"); 1699f872b4b9SNelio Laranjeiro if (file == NULL) { 1700f872b4b9SNelio Laranjeiro rte_errno = errno; 1701f872b4b9SNelio Laranjeiro return -rte_errno; 1702f872b4b9SNelio Laranjeiro } 1703f872b4b9SNelio Laranjeiro port_switch_id_set = 1704f872b4b9SNelio Laranjeiro fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 && 1705f872b4b9SNelio Laranjeiro c == '\n'; 1706f872b4b9SNelio Laranjeiro fclose(file); 1707299d7dc2SViacheslav Ovsiienko dir = opendir(pci_device); 1708299d7dc2SViacheslav Ovsiienko if (dir != NULL) { 1709299d7dc2SViacheslav Ovsiienko closedir(dir); 1710299d7dc2SViacheslav Ovsiienko device_dir = true; 1711299d7dc2SViacheslav Ovsiienko } 171230a86157SViacheslav Ovsiienko if (port_switch_id_set) { 171330a86157SViacheslav Ovsiienko /* We have some E-Switch configuration. */ 171430a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(device_dir, &data); 171530a86157SViacheslav Ovsiienko } 1716f872b4b9SNelio Laranjeiro *info = data; 1717299d7dc2SViacheslav Ovsiienko assert(!(data.master && data.representor)); 1718299d7dc2SViacheslav Ovsiienko if (data.master && data.representor) { 1719299d7dc2SViacheslav Ovsiienko DRV_LOG(ERR, "ifindex %u device is recognized as master" 1720299d7dc2SViacheslav Ovsiienko " and as representor", ifindex); 1721299d7dc2SViacheslav Ovsiienko rte_errno = ENODEV; 1722299d7dc2SViacheslav Ovsiienko return -rte_errno; 1723299d7dc2SViacheslav Ovsiienko } 1724f872b4b9SNelio Laranjeiro return 0; 1725f872b4b9SNelio Laranjeiro } 1726b2f3a381SDekel Peled 1727b2f3a381SDekel Peled /** 172830a86157SViacheslav Ovsiienko * Analyze gathered port parameters via Netlink to recognize master 172930a86157SViacheslav Ovsiienko * and representor devices for E-Switch configuration. 173030a86157SViacheslav Ovsiienko * 173130a86157SViacheslav Ovsiienko * @param[in] num_vf_set 173230a86157SViacheslav Ovsiienko * flag of presence of number of VFs port attribute. 173330a86157SViacheslav Ovsiienko * @param[inout] switch_info 173430a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 173530a86157SViacheslav Ovsiienko * type if recognized 173630a86157SViacheslav Ovsiienko * 173730a86157SViacheslav Ovsiienko * @return 173830a86157SViacheslav Ovsiienko * master and representor flags are set in switch_info according to 173930a86157SViacheslav Ovsiienko * recognized parameters (if any). 174030a86157SViacheslav Ovsiienko */ 174130a86157SViacheslav Ovsiienko void 174230a86157SViacheslav Ovsiienko mlx5_nl_check_switch_info(bool num_vf_set, 174330a86157SViacheslav Ovsiienko struct mlx5_switch_info *switch_info) 174430a86157SViacheslav Ovsiienko { 174530a86157SViacheslav Ovsiienko switch (switch_info->name_type) { 174630a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: 174730a86157SViacheslav Ovsiienko /* 174830a86157SViacheslav Ovsiienko * Name is not recognized, assume the master, 174930a86157SViacheslav Ovsiienko * check the number of VFs key presence. 175030a86157SViacheslav Ovsiienko */ 175130a86157SViacheslav Ovsiienko switch_info->master = num_vf_set; 175230a86157SViacheslav Ovsiienko break; 175330a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: 175430a86157SViacheslav Ovsiienko /* 175530a86157SViacheslav Ovsiienko * Name is not set, this assumes the legacy naming 175630a86157SViacheslav Ovsiienko * schema for master, just check if there is a 175730a86157SViacheslav Ovsiienko * number of VFs key. 175830a86157SViacheslav Ovsiienko */ 175930a86157SViacheslav Ovsiienko switch_info->master = num_vf_set; 176030a86157SViacheslav Ovsiienko break; 176130a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 176230a86157SViacheslav Ovsiienko /* New uplink naming schema recognized. */ 176330a86157SViacheslav Ovsiienko switch_info->master = 1; 176430a86157SViacheslav Ovsiienko break; 176530a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: 176630a86157SViacheslav Ovsiienko /* Legacy representors naming schema. */ 176730a86157SViacheslav Ovsiienko switch_info->representor = !num_vf_set; 176830a86157SViacheslav Ovsiienko break; 176930a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 177030a86157SViacheslav Ovsiienko /* New representors naming schema. */ 177130a86157SViacheslav Ovsiienko switch_info->representor = 1; 177230a86157SViacheslav Ovsiienko break; 177330a86157SViacheslav Ovsiienko } 177430a86157SViacheslav Ovsiienko } 177530a86157SViacheslav Ovsiienko 177630a86157SViacheslav Ovsiienko /** 177730a86157SViacheslav Ovsiienko * Analyze gathered port parameters via sysfs to recognize master 177830a86157SViacheslav Ovsiienko * and representor devices for E-Switch configuration. 177930a86157SViacheslav Ovsiienko * 178030a86157SViacheslav Ovsiienko * @param[in] device_dir 178130a86157SViacheslav Ovsiienko * flag of presence of "device" directory under port device key. 178230a86157SViacheslav Ovsiienko * @param[inout] switch_info 178330a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 178430a86157SViacheslav Ovsiienko * type if recognized 178530a86157SViacheslav Ovsiienko * 178630a86157SViacheslav Ovsiienko * @return 178730a86157SViacheslav Ovsiienko * master and representor flags are set in switch_info according to 178830a86157SViacheslav Ovsiienko * recognized parameters (if any). 178930a86157SViacheslav Ovsiienko */ 179030a86157SViacheslav Ovsiienko void 179130a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(bool device_dir, 179230a86157SViacheslav Ovsiienko struct mlx5_switch_info *switch_info) 179330a86157SViacheslav Ovsiienko { 179430a86157SViacheslav Ovsiienko switch (switch_info->name_type) { 179530a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: 179630a86157SViacheslav Ovsiienko /* 179730a86157SViacheslav Ovsiienko * Name is not recognized, assume the master, 179830a86157SViacheslav Ovsiienko * check the device directory presence. 179930a86157SViacheslav Ovsiienko */ 180030a86157SViacheslav Ovsiienko switch_info->master = device_dir; 180130a86157SViacheslav Ovsiienko break; 180230a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: 180330a86157SViacheslav Ovsiienko /* 180430a86157SViacheslav Ovsiienko * Name is not set, this assumes the legacy naming 180530a86157SViacheslav Ovsiienko * schema for master, just check if there is 180630a86157SViacheslav Ovsiienko * a device directory. 180730a86157SViacheslav Ovsiienko */ 180830a86157SViacheslav Ovsiienko switch_info->master = device_dir; 180930a86157SViacheslav Ovsiienko break; 181030a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 181130a86157SViacheslav Ovsiienko /* New uplink naming schema recognized. */ 181230a86157SViacheslav Ovsiienko switch_info->master = 1; 181330a86157SViacheslav Ovsiienko break; 181430a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: 181530a86157SViacheslav Ovsiienko /* Legacy representors naming schema. */ 181630a86157SViacheslav Ovsiienko switch_info->representor = !device_dir; 181730a86157SViacheslav Ovsiienko break; 181830a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 181930a86157SViacheslav Ovsiienko /* New representors naming schema. */ 182030a86157SViacheslav Ovsiienko switch_info->representor = 1; 182130a86157SViacheslav Ovsiienko break; 182230a86157SViacheslav Ovsiienko } 182330a86157SViacheslav Ovsiienko } 182430a86157SViacheslav Ovsiienko 182530a86157SViacheslav Ovsiienko /** 1826b2f3a381SDekel Peled * Extract port name, as a number, from sysfs or netlink information. 1827b2f3a381SDekel Peled * 1828b2f3a381SDekel Peled * @param[in] port_name_in 1829b2f3a381SDekel Peled * String representing the port name. 1830b2f3a381SDekel Peled * @param[out] port_info_out 183130a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 183230a86157SViacheslav Ovsiienko * type if recognized 1833b2f3a381SDekel Peled * 1834b2f3a381SDekel Peled * @return 183530a86157SViacheslav Ovsiienko * port_name field set according to recognized name format. 1836b2f3a381SDekel Peled */ 183730a86157SViacheslav Ovsiienko void 1838b2f3a381SDekel Peled mlx5_translate_port_name(const char *port_name_in, 1839b2f3a381SDekel Peled struct mlx5_switch_info *port_info_out) 1840b2f3a381SDekel Peled { 1841b2f3a381SDekel Peled char pf_c1, pf_c2, vf_c1, vf_c2; 1842b2f3a381SDekel Peled char *end; 184330a86157SViacheslav Ovsiienko int sc_items; 1844b2f3a381SDekel Peled 1845b2f3a381SDekel Peled /* 1846b2f3a381SDekel Peled * Check for port-name as a string of the form pf0vf0 184730a86157SViacheslav Ovsiienko * (support kernel ver >= 5.0 or OFED ver >= 4.6). 1848b2f3a381SDekel Peled */ 184930a86157SViacheslav Ovsiienko sc_items = sscanf(port_name_in, "%c%c%d%c%c%d", 185030a86157SViacheslav Ovsiienko &pf_c1, &pf_c2, &port_info_out->pf_num, 185130a86157SViacheslav Ovsiienko &vf_c1, &vf_c2, &port_info_out->port_name); 185230a86157SViacheslav Ovsiienko if (sc_items == 6 && 185330a86157SViacheslav Ovsiienko pf_c1 == 'p' && pf_c2 == 'f' && 185430a86157SViacheslav Ovsiienko vf_c1 == 'v' && vf_c2 == 'f') { 185530a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF; 185630a86157SViacheslav Ovsiienko return; 185730a86157SViacheslav Ovsiienko } 185830a86157SViacheslav Ovsiienko /* 185930a86157SViacheslav Ovsiienko * Check for port-name as a string of the form p0 186030a86157SViacheslav Ovsiienko * (support kernel ver >= 5.0, or OFED ver >= 4.6). 186130a86157SViacheslav Ovsiienko */ 186230a86157SViacheslav Ovsiienko sc_items = sscanf(port_name_in, "%c%d", 186330a86157SViacheslav Ovsiienko &pf_c1, &port_info_out->port_name); 186430a86157SViacheslav Ovsiienko if (sc_items == 2 && pf_c1 == 'p') { 186530a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK; 186630a86157SViacheslav Ovsiienko return; 186730a86157SViacheslav Ovsiienko } 1868b2f3a381SDekel Peled /* Check for port-name as a number (support kernel ver < 5.0 */ 1869b2f3a381SDekel Peled errno = 0; 1870b2f3a381SDekel Peled port_info_out->port_name = strtol(port_name_in, &end, 0); 1871b2f3a381SDekel Peled if (!errno && 187230a86157SViacheslav Ovsiienko (size_t)(end - port_name_in) == strlen(port_name_in)) { 187330a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY; 187430a86157SViacheslav Ovsiienko return; 1875b2f3a381SDekel Peled } 187630a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; 187730a86157SViacheslav Ovsiienko return; 1878b2f3a381SDekel Peled } 1879