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> 7fc40db99SAdrien Mazarguil #include <inttypes.h> 8771fa900SAdrien Mazarguil #include <unistd.h> 9028669bcSAnatoly Burakov #include <stdbool.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> 365897ac13SViacheslav Ovsiienko #include <rte_cycles.h> 37771fa900SAdrien Mazarguil 387b4f1e6bSMatan Azrad #include <mlx5_glue.h> 397b4f1e6bSMatan Azrad #include <mlx5_devx_cmds.h> 4093e30982SMatan Azrad #include <mlx5_common.h> 417b4f1e6bSMatan Azrad 42771fa900SAdrien Mazarguil #include "mlx5.h" 43e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 44771fa900SAdrien Mazarguil #include "mlx5_utils.h" 45771fa900SAdrien Mazarguil 4679d09892SMoti Haimovsky /* Supported speed values found in /usr/include/linux/ethtool.h */ 4779d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseKR4_Full 4879d09892SMoti Haimovsky #define SUPPORTED_40000baseKR4_Full (1 << 23) 4979d09892SMoti Haimovsky #endif 5079d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseCR4_Full 5179d09892SMoti Haimovsky #define SUPPORTED_40000baseCR4_Full (1 << 24) 5279d09892SMoti Haimovsky #endif 5379d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseSR4_Full 5479d09892SMoti Haimovsky #define SUPPORTED_40000baseSR4_Full (1 << 25) 5579d09892SMoti Haimovsky #endif 5679d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseLR4_Full 5779d09892SMoti Haimovsky #define SUPPORTED_40000baseLR4_Full (1 << 26) 5879d09892SMoti Haimovsky #endif 5979d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseKR4_Full 6079d09892SMoti Haimovsky #define SUPPORTED_56000baseKR4_Full (1 << 27) 6179d09892SMoti Haimovsky #endif 6279d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseCR4_Full 6379d09892SMoti Haimovsky #define SUPPORTED_56000baseCR4_Full (1 << 28) 6479d09892SMoti Haimovsky #endif 6579d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseSR4_Full 6679d09892SMoti Haimovsky #define SUPPORTED_56000baseSR4_Full (1 << 29) 6779d09892SMoti Haimovsky #endif 6879d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseLR4_Full 6979d09892SMoti Haimovsky #define SUPPORTED_56000baseLR4_Full (1 << 30) 7079d09892SMoti Haimovsky #endif 7179d09892SMoti Haimovsky 723a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */ 733a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS 743a49ffe3SShahaf Shuler struct ethtool_link_settings { 753a49ffe3SShahaf Shuler uint32_t cmd; 763a49ffe3SShahaf Shuler uint32_t speed; 773a49ffe3SShahaf Shuler uint8_t duplex; 783a49ffe3SShahaf Shuler uint8_t port; 793a49ffe3SShahaf Shuler uint8_t phy_address; 803a49ffe3SShahaf Shuler uint8_t autoneg; 813a49ffe3SShahaf Shuler uint8_t mdio_support; 823a49ffe3SShahaf Shuler uint8_t eth_to_mdix; 833a49ffe3SShahaf Shuler uint8_t eth_tp_mdix_ctrl; 843a49ffe3SShahaf Shuler int8_t link_mode_masks_nwords; 853a49ffe3SShahaf Shuler uint32_t reserved[8]; 863a49ffe3SShahaf Shuler uint32_t link_mode_masks[]; 873a49ffe3SShahaf Shuler }; 883a49ffe3SShahaf Shuler 896e3a4595SAsaf Penso /* The kernel values can be found in /include/uapi/linux/ethtool.h */ 903a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c 913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5 923a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6 933a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17 943a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18 953a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19 963a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20 973a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21 983a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22 993a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23 1003a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24 1013a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25 1023a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26 1033a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27 1043a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28 1053a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29 1063a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30 1073a49ffe3SShahaf Shuler #endif 1083a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G 1093a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31 1103a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32 1113a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33 1123a49ffe3SShahaf Shuler #endif 1133a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G 1143a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34 1153a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35 1163a49ffe3SShahaf Shuler #endif 1173a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G 1183a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36 1193a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37 1203a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38 1213a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39 1223a49ffe3SShahaf Shuler #endif 1236e3a4595SAsaf Penso #ifndef HAVE_ETHTOOL_LINK_MODE_200G 1246e3a4595SAsaf Penso #define ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT 62 1256e3a4595SAsaf Penso #define ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT 63 1266e3a4595SAsaf Penso #define ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT 0 /* 64 - 64 */ 1276e3a4595SAsaf Penso #define ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT 1 /* 65 - 64 */ 1286e3a4595SAsaf Penso #define ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT 2 /* 66 - 64 */ 1296e3a4595SAsaf Penso #endif 1303a49ffe3SShahaf Shuler 131771fa900SAdrien Mazarguil /** 1322b730263SAdrien Mazarguil * Get master interface name from private structure. 133771fa900SAdrien Mazarguil * 134af4f09f2SNélio Laranjeiro * @param[in] dev 135af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 136771fa900SAdrien Mazarguil * @param[out] ifname 137771fa900SAdrien Mazarguil * Interface name output buffer. 138771fa900SAdrien Mazarguil * 139771fa900SAdrien Mazarguil * @return 140a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 141771fa900SAdrien Mazarguil */ 1429c2bbd04SViacheslav Ovsiienko int 1439c2bbd04SViacheslav Ovsiienko mlx5_get_master_ifname(const char *ibdev_path, char (*ifname)[IF_NAMESIZE]) 144771fa900SAdrien Mazarguil { 145771fa900SAdrien Mazarguil DIR *dir; 146771fa900SAdrien Mazarguil struct dirent *dent; 147771fa900SAdrien Mazarguil unsigned int dev_type = 0; 148771fa900SAdrien Mazarguil unsigned int dev_port_prev = ~0u; 149771fa900SAdrien Mazarguil char match[IF_NAMESIZE] = ""; 150771fa900SAdrien Mazarguil 1518e46d4e1SAlexander Kozyrev MLX5_ASSERT(ibdev_path); 152771fa900SAdrien Mazarguil { 1539c2bbd04SViacheslav Ovsiienko MKSTR(path, "%s/device/net", ibdev_path); 154771fa900SAdrien Mazarguil 155771fa900SAdrien Mazarguil dir = opendir(path); 156a6d83b6aSNélio Laranjeiro if (dir == NULL) { 157a6d83b6aSNélio Laranjeiro rte_errno = errno; 158a6d83b6aSNélio Laranjeiro return -rte_errno; 159a6d83b6aSNélio Laranjeiro } 160771fa900SAdrien Mazarguil } 161771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 162771fa900SAdrien Mazarguil char *name = dent->d_name; 163771fa900SAdrien Mazarguil FILE *file; 164771fa900SAdrien Mazarguil unsigned int dev_port; 165771fa900SAdrien Mazarguil int r; 166771fa900SAdrien Mazarguil 167771fa900SAdrien Mazarguil if ((name[0] == '.') && 168771fa900SAdrien Mazarguil ((name[1] == '\0') || 169771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 170771fa900SAdrien Mazarguil continue; 171771fa900SAdrien Mazarguil 172771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 1739c2bbd04SViacheslav Ovsiienko ibdev_path, name, 174771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 175771fa900SAdrien Mazarguil 176771fa900SAdrien Mazarguil file = fopen(path, "rb"); 177771fa900SAdrien Mazarguil if (file == NULL) { 178771fa900SAdrien Mazarguil if (errno != ENOENT) 179771fa900SAdrien Mazarguil continue; 180771fa900SAdrien Mazarguil /* 181771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 182771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 183771fa900SAdrien Mazarguil */ 184771fa900SAdrien Mazarguil try_dev_id: 185771fa900SAdrien Mazarguil match[0] = '\0'; 186771fa900SAdrien Mazarguil if (dev_type) 187771fa900SAdrien Mazarguil break; 188771fa900SAdrien Mazarguil dev_type = 1; 189771fa900SAdrien Mazarguil dev_port_prev = ~0u; 190771fa900SAdrien Mazarguil rewinddir(dir); 191771fa900SAdrien Mazarguil continue; 192771fa900SAdrien Mazarguil } 193771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 194771fa900SAdrien Mazarguil fclose(file); 195771fa900SAdrien Mazarguil if (r != 1) 196771fa900SAdrien Mazarguil continue; 197771fa900SAdrien Mazarguil /* 198771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 199771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 200771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 201771fa900SAdrien Mazarguil */ 202771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 203771fa900SAdrien Mazarguil goto try_dev_id; 204771fa900SAdrien Mazarguil dev_port_prev = dev_port; 2059083982cSAdrien Mazarguil if (dev_port == 0) 206c022cb40SBruce Richardson strlcpy(match, name, sizeof(match)); 207771fa900SAdrien Mazarguil } 208771fa900SAdrien Mazarguil closedir(dir); 209a6d83b6aSNélio Laranjeiro if (match[0] == '\0') { 210a6d83b6aSNélio Laranjeiro rte_errno = ENOENT; 211a6d83b6aSNélio Laranjeiro return -rte_errno; 212a6d83b6aSNélio Laranjeiro } 213771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 214771fa900SAdrien Mazarguil return 0; 215771fa900SAdrien Mazarguil } 216771fa900SAdrien Mazarguil 217771fa900SAdrien Mazarguil /** 2182b730263SAdrien Mazarguil * Get interface name from private structure. 2192b730263SAdrien Mazarguil * 2202b730263SAdrien Mazarguil * This is a port representor-aware version of mlx5_get_master_ifname(). 2212b730263SAdrien Mazarguil * 2222b730263SAdrien Mazarguil * @param[in] dev 2232b730263SAdrien Mazarguil * Pointer to Ethernet device. 2242b730263SAdrien Mazarguil * @param[out] ifname 2252b730263SAdrien Mazarguil * Interface name output buffer. 2262b730263SAdrien Mazarguil * 2272b730263SAdrien Mazarguil * @return 2282b730263SAdrien Mazarguil * 0 on success, a negative errno value otherwise and rte_errno is set. 2292b730263SAdrien Mazarguil */ 2302b730263SAdrien Mazarguil int 2312b730263SAdrien Mazarguil mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) 2322b730263SAdrien Mazarguil { 233dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 2349c2bbd04SViacheslav Ovsiienko unsigned int ifindex; 2359c2bbd04SViacheslav Ovsiienko 2368e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv); 2378e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv->sh); 238fa2e14d4SViacheslav Ovsiienko ifindex = mlx5_ifindex(dev); 2392b730263SAdrien Mazarguil if (!ifindex) { 2402b730263SAdrien Mazarguil if (!priv->representor) 2419c2bbd04SViacheslav Ovsiienko return mlx5_get_master_ifname(priv->sh->ibdev_path, 2429c2bbd04SViacheslav Ovsiienko ifname); 2432b730263SAdrien Mazarguil rte_errno = ENXIO; 2442b730263SAdrien Mazarguil return -rte_errno; 2452b730263SAdrien Mazarguil } 2462b730263SAdrien Mazarguil if (if_indextoname(ifindex, &(*ifname)[0])) 2472b730263SAdrien Mazarguil return 0; 2482b730263SAdrien Mazarguil rte_errno = errno; 2492b730263SAdrien Mazarguil return -rte_errno; 2502b730263SAdrien Mazarguil } 2512b730263SAdrien Mazarguil 2522b730263SAdrien Mazarguil /** 253ccdcba53SNélio Laranjeiro * Get the interface index from device name. 254ccdcba53SNélio Laranjeiro * 255ccdcba53SNélio Laranjeiro * @param[in] dev 256ccdcba53SNélio Laranjeiro * Pointer to Ethernet device. 257ccdcba53SNélio Laranjeiro * 258ccdcba53SNélio Laranjeiro * @return 2593f8cb05dSAdrien Mazarguil * Nonzero interface index on success, zero otherwise and rte_errno is set. 260ccdcba53SNélio Laranjeiro */ 2613f8cb05dSAdrien Mazarguil unsigned int 262ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev) 263ccdcba53SNélio Laranjeiro { 264fa2e14d4SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 2653f8cb05dSAdrien Mazarguil unsigned int ifindex; 266ccdcba53SNélio Laranjeiro 2678e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv); 2688e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv->if_index); 269fa2e14d4SViacheslav Ovsiienko ifindex = priv->if_index; 2703f8cb05dSAdrien Mazarguil if (!ifindex) 271fa2e14d4SViacheslav Ovsiienko rte_errno = ENXIO; 2723f8cb05dSAdrien Mazarguil return ifindex; 273ccdcba53SNélio Laranjeiro } 274ccdcba53SNélio Laranjeiro 275ccdcba53SNélio Laranjeiro /** 276771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 277771fa900SAdrien Mazarguil * 278af4f09f2SNélio Laranjeiro * @param[in] dev 279af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 280771fa900SAdrien Mazarguil * @param req 281771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 282771fa900SAdrien Mazarguil * @param[out] ifr 283771fa900SAdrien Mazarguil * Interface request structure output buffer. 284771fa900SAdrien Mazarguil * 285771fa900SAdrien Mazarguil * @return 286a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 287771fa900SAdrien Mazarguil */ 288771fa900SAdrien Mazarguil int 2897dd7be29SShahaf Shuler mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr) 290771fa900SAdrien Mazarguil { 291771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 292a6d83b6aSNélio Laranjeiro int ret = 0; 293771fa900SAdrien Mazarguil 294a6d83b6aSNélio Laranjeiro if (sock == -1) { 295a6d83b6aSNélio Laranjeiro rte_errno = errno; 296a6d83b6aSNélio Laranjeiro return -rte_errno; 297a6d83b6aSNélio Laranjeiro } 298a6d83b6aSNélio Laranjeiro ret = mlx5_get_ifname(dev, &ifr->ifr_name); 299a6d83b6aSNélio Laranjeiro if (ret) 300a6d83b6aSNélio Laranjeiro goto error; 301771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 302a6d83b6aSNélio Laranjeiro if (ret == -1) { 303a6d83b6aSNélio Laranjeiro rte_errno = errno; 304a6d83b6aSNélio Laranjeiro goto error; 305a6d83b6aSNélio Laranjeiro } 306771fa900SAdrien Mazarguil close(sock); 307a6d83b6aSNélio Laranjeiro return 0; 308a6d83b6aSNélio Laranjeiro error: 309a6d83b6aSNélio Laranjeiro close(sock); 310a6d83b6aSNélio Laranjeiro return -rte_errno; 311771fa900SAdrien Mazarguil } 312771fa900SAdrien Mazarguil 313771fa900SAdrien Mazarguil /** 314771fa900SAdrien Mazarguil * Get device MTU. 315771fa900SAdrien Mazarguil * 316af4f09f2SNélio Laranjeiro * @param dev 317af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 318771fa900SAdrien Mazarguil * @param[out] mtu 319771fa900SAdrien Mazarguil * MTU value output buffer. 320771fa900SAdrien Mazarguil * 321771fa900SAdrien Mazarguil * @return 322a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 323771fa900SAdrien Mazarguil */ 324771fa900SAdrien Mazarguil int 325af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 326771fa900SAdrien Mazarguil { 327fc40db99SAdrien Mazarguil struct ifreq request; 3287dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request); 329771fa900SAdrien Mazarguil 330fc40db99SAdrien Mazarguil if (ret) 331fc40db99SAdrien Mazarguil return ret; 332fc40db99SAdrien Mazarguil *mtu = request.ifr_mtu; 333859081d3SShahaf Shuler return 0; 334859081d3SShahaf Shuler } 335859081d3SShahaf Shuler 336859081d3SShahaf Shuler /** 337cf37ca95SAdrien Mazarguil * Set device MTU. 338cf37ca95SAdrien Mazarguil * 339af4f09f2SNélio Laranjeiro * @param dev 340af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 341cf37ca95SAdrien Mazarguil * @param mtu 342cf37ca95SAdrien Mazarguil * MTU value to set. 343cf37ca95SAdrien Mazarguil * 344cf37ca95SAdrien Mazarguil * @return 345a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 346cf37ca95SAdrien Mazarguil */ 347cf37ca95SAdrien Mazarguil static int 348af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 349cf37ca95SAdrien Mazarguil { 350fc40db99SAdrien Mazarguil struct ifreq request = { .ifr_mtu = mtu, }; 351f3b492d7SAdrien Mazarguil 3527dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFMTU, &request); 353cf37ca95SAdrien Mazarguil } 354cf37ca95SAdrien Mazarguil 355cf37ca95SAdrien Mazarguil /** 356771fa900SAdrien Mazarguil * Set device flags. 357771fa900SAdrien Mazarguil * 358af4f09f2SNélio Laranjeiro * @param dev 359af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 360771fa900SAdrien Mazarguil * @param keep 361771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 362771fa900SAdrien Mazarguil * @param flags 363771fa900SAdrien Mazarguil * Bitmask for flags to modify. 364771fa900SAdrien Mazarguil * 365771fa900SAdrien Mazarguil * @return 366a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 367771fa900SAdrien Mazarguil */ 368771fa900SAdrien Mazarguil int 369af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags) 370771fa900SAdrien Mazarguil { 371fc40db99SAdrien Mazarguil struct ifreq request; 3727dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request); 373771fa900SAdrien Mazarguil 374fc40db99SAdrien Mazarguil if (ret) 375fc40db99SAdrien Mazarguil return ret; 376fc40db99SAdrien Mazarguil request.ifr_flags &= keep; 377fc40db99SAdrien Mazarguil request.ifr_flags |= flags & ~keep; 3787dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFFLAGS, &request); 379771fa900SAdrien Mazarguil } 380771fa900SAdrien Mazarguil 381771fa900SAdrien Mazarguil /** 3827b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 383e60fbd5bSAdrien Mazarguil * 384e60fbd5bSAdrien Mazarguil * @param dev 385e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 386e60fbd5bSAdrien Mazarguil * 387e60fbd5bSAdrien Mazarguil * @return 388a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 389e60fbd5bSAdrien Mazarguil */ 3907b2423cdSNélio Laranjeiro int 3917b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 392e60fbd5bSAdrien Mazarguil { 393dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 394e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 395e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 39629c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 39721e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 398a6d83b6aSNélio Laranjeiro int ret = 0; 399e60fbd5bSAdrien Mazarguil 40029c1d8bbSNélio Laranjeiro if (use_app_rss_key && 40129c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 402c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN)) { 403c388a2f6SNelio Laranjeiro DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long", 404c388a2f6SNelio Laranjeiro dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 405a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 406a6d83b6aSNélio Laranjeiro return -rte_errno; 40729c1d8bbSNélio Laranjeiro } 40829c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 40929c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 410c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN, 0); 41129c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 412a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)", 4130f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 414a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 415a6d83b6aSNélio Laranjeiro return -rte_errno; 41629c1d8bbSNélio Laranjeiro } 4178b945a7fSPavan Nikhilesh 41873fb89ddSAndrew Rybchenko if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) 4198b945a7fSPavan Nikhilesh dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH; 4208b945a7fSPavan Nikhilesh 42129c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 42229c1d8bbSNélio Laranjeiro use_app_rss_key ? 42329c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 42429c1d8bbSNélio Laranjeiro rss_hash_default_key, 425c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN); 426c388a2f6SNelio Laranjeiro priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN; 42729c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 428e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 429e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 430e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 431a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u", 4320f99970bSNélio Laranjeiro dev->data->port_id, priv->txqs_n, txqs_n); 433e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 434e60fbd5bSAdrien Mazarguil } 4357fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 436a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 4370f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 438a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 439a6d83b6aSNélio Laranjeiro return -rte_errno; 440634efbc2SNelio Laranjeiro } 44109ba4c58SDekel Peled if (rxqs_n != priv->rxqs_n) { 442a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 4430f99970bSNélio Laranjeiro dev->data->port_id, priv->rxqs_n, rxqs_n); 444e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 44563bd1629SOri Kam } 44663bd1629SOri Kam priv->skip_default_rss_reta = 0; 44763bd1629SOri Kam ret = mlx5_proc_priv_init(dev); 44863bd1629SOri Kam if (ret) 44963bd1629SOri Kam return ret; 45063bd1629SOri Kam return 0; 45163bd1629SOri Kam } 45263bd1629SOri Kam 45363bd1629SOri Kam /** 45463bd1629SOri Kam * Configure default RSS reta. 45563bd1629SOri Kam * 45663bd1629SOri Kam * @param dev 45763bd1629SOri Kam * Pointer to Ethernet device structure. 45863bd1629SOri Kam * 45963bd1629SOri Kam * @return 46063bd1629SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 46163bd1629SOri Kam */ 46263bd1629SOri Kam int 46363bd1629SOri Kam mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev) 46463bd1629SOri Kam { 46563bd1629SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 46663bd1629SOri Kam unsigned int rxqs_n = dev->data->nb_rx_queues; 46763bd1629SOri Kam unsigned int i; 46863bd1629SOri Kam unsigned int j; 46963bd1629SOri Kam unsigned int reta_idx_n; 47063bd1629SOri Kam int ret = 0; 47163bd1629SOri Kam unsigned int *rss_queue_arr = NULL; 47263bd1629SOri Kam unsigned int rss_queue_n = 0; 47363bd1629SOri Kam 47463bd1629SOri Kam if (priv->skip_default_rss_reta) 47563bd1629SOri Kam return ret; 47663bd1629SOri Kam rss_queue_arr = rte_malloc("", rxqs_n * sizeof(unsigned int), 0); 47763bd1629SOri Kam if (!rss_queue_arr) { 47863bd1629SOri Kam DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)", 47963bd1629SOri Kam dev->data->port_id, rxqs_n); 48063bd1629SOri Kam rte_errno = ENOMEM; 48163bd1629SOri Kam return -rte_errno; 48263bd1629SOri Kam } 48363bd1629SOri Kam for (i = 0, j = 0; i < rxqs_n; i++) { 48463bd1629SOri Kam struct mlx5_rxq_data *rxq_data; 48563bd1629SOri Kam struct mlx5_rxq_ctrl *rxq_ctrl; 48663bd1629SOri Kam 48763bd1629SOri Kam rxq_data = (*priv->rxqs)[i]; 48863bd1629SOri Kam rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); 489bf864e82STonghao Zhang if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) 49063bd1629SOri Kam rss_queue_arr[j++] = i; 49163bd1629SOri Kam } 49263bd1629SOri Kam rss_queue_n = j; 49363bd1629SOri Kam if (rss_queue_n > priv->config.ind_table_max_size) { 49463bd1629SOri Kam DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 49563bd1629SOri Kam dev->data->port_id, rss_queue_n); 49663bd1629SOri Kam rte_errno = EINVAL; 49763bd1629SOri Kam rte_free(rss_queue_arr); 49863bd1629SOri Kam return -rte_errno; 49963bd1629SOri Kam } 50063bd1629SOri Kam DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 50163bd1629SOri Kam dev->data->port_id, priv->rxqs_n, rxqs_n); 50263bd1629SOri Kam priv->rxqs_n = rxqs_n; 50309ba4c58SDekel Peled /* 50409ba4c58SDekel Peled * If the requested number of RX queues is not a power of two, 50509ba4c58SDekel Peled * use the maximum indirection table size for better balancing. 50609ba4c58SDekel Peled * The result is always rounded to the next power of two. 50709ba4c58SDekel Peled */ 50863bd1629SOri Kam reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ? 5097fe24446SShahaf Shuler priv->config.ind_table_max_size : 51063bd1629SOri Kam rss_queue_n)); 511a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 51263bd1629SOri Kam if (ret) { 51363bd1629SOri Kam rte_free(rss_queue_arr); 514a6d83b6aSNélio Laranjeiro return ret; 51563bd1629SOri Kam } 51609ba4c58SDekel Peled /* 51709ba4c58SDekel Peled * When the number of RX queues is not a power of two, 51809ba4c58SDekel Peled * the remaining table entries are padded with reused WQs 51909ba4c58SDekel Peled * and hashes are not spread uniformly. 52009ba4c58SDekel Peled */ 521634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 52263bd1629SOri Kam (*priv->reta_idx)[i] = rss_queue_arr[j]; 52363bd1629SOri Kam if (++j == rss_queue_n) 524634efbc2SNelio Laranjeiro j = 0; 525634efbc2SNelio Laranjeiro } 52663bd1629SOri Kam rte_free(rss_queue_arr); 527120dc4a7SYongseok Koh return ret; 528e60fbd5bSAdrien Mazarguil } 529e60fbd5bSAdrien Mazarguil 530e60fbd5bSAdrien Mazarguil /** 531d11d651fSShahaf Shuler * Sets default tuning parameters. 532d11d651fSShahaf Shuler * 533d11d651fSShahaf Shuler * @param dev 534d11d651fSShahaf Shuler * Pointer to Ethernet device. 535d11d651fSShahaf Shuler * @param[out] info 536d11d651fSShahaf Shuler * Info structure output buffer. 537d11d651fSShahaf Shuler */ 538d11d651fSShahaf Shuler static void 539d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 540d11d651fSShahaf Shuler { 541dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 542d11d651fSShahaf Shuler 543d11d651fSShahaf Shuler /* Minimum CPU utilization. */ 544d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 256; 545d11d651fSShahaf Shuler info->default_txportconf.ring_size = 256; 546f078ceb6SViacheslav Ovsiienko info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST; 547f078ceb6SViacheslav Ovsiienko info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST; 5486e3a4595SAsaf Penso if ((priv->link_speed_capa & ETH_LINK_SPEED_200G) | 5496e3a4595SAsaf Penso (priv->link_speed_capa & ETH_LINK_SPEED_100G)) { 550d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 16; 551d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 16; 552d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 553d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 554d11d651fSShahaf Shuler /* Max Throughput. */ 555d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 2048; 556d11d651fSShahaf Shuler info->default_txportconf.ring_size = 2048; 557d11d651fSShahaf Shuler } 558d11d651fSShahaf Shuler } else { 559d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 8; 560d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 8; 561d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 562d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 563d11d651fSShahaf Shuler /* Max Throughput. */ 564d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 4096; 565d11d651fSShahaf Shuler info->default_txportconf.ring_size = 4096; 566d11d651fSShahaf Shuler } 567d11d651fSShahaf Shuler } 568d11d651fSShahaf Shuler } 569d11d651fSShahaf Shuler 570d11d651fSShahaf Shuler /** 571cb9cb61eSViacheslav Ovsiienko * Sets tx mbuf limiting parameters. 572cb9cb61eSViacheslav Ovsiienko * 573cb9cb61eSViacheslav Ovsiienko * @param dev 574cb9cb61eSViacheslav Ovsiienko * Pointer to Ethernet device. 575cb9cb61eSViacheslav Ovsiienko * @param[out] info 576cb9cb61eSViacheslav Ovsiienko * Info structure output buffer. 577cb9cb61eSViacheslav Ovsiienko */ 578cb9cb61eSViacheslav Ovsiienko static void 579cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 580cb9cb61eSViacheslav Ovsiienko { 581cb9cb61eSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 582cb9cb61eSViacheslav Ovsiienko struct mlx5_dev_config *config = &priv->config; 583cb9cb61eSViacheslav Ovsiienko unsigned int inlen; 584cb9cb61eSViacheslav Ovsiienko uint16_t nb_max; 585cb9cb61eSViacheslav Ovsiienko 586cb9cb61eSViacheslav Ovsiienko inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ? 587cb9cb61eSViacheslav Ovsiienko MLX5_SEND_DEF_INLINE_LEN : 588cb9cb61eSViacheslav Ovsiienko (unsigned int)config->txq_inline_max; 5898e46d4e1SAlexander Kozyrev MLX5_ASSERT(config->txq_inline_min >= 0); 590cb9cb61eSViacheslav Ovsiienko inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min); 591cb9cb61eSViacheslav Ovsiienko inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX + 592cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 593cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 594cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 595cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE * 2); 596cb9cb61eSViacheslav Ovsiienko nb_max = (MLX5_WQE_SIZE_MAX + 597cb9cb61eSViacheslav Ovsiienko MLX5_ESEG_MIN_INLINE_SIZE - 598cb9cb61eSViacheslav Ovsiienko MLX5_WQE_CSEG_SIZE - 599cb9cb61eSViacheslav Ovsiienko MLX5_WQE_ESEG_SIZE - 600cb9cb61eSViacheslav Ovsiienko MLX5_WQE_DSEG_SIZE - 601cb9cb61eSViacheslav Ovsiienko inlen) / MLX5_WSEG_SIZE; 602cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_seg_max = nb_max; 603cb9cb61eSViacheslav Ovsiienko info->tx_desc_lim.nb_mtu_seg_max = nb_max; 604cb9cb61eSViacheslav Ovsiienko } 605cb9cb61eSViacheslav Ovsiienko 606cb9cb61eSViacheslav Ovsiienko /** 607e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 608e60fbd5bSAdrien Mazarguil * 609e60fbd5bSAdrien Mazarguil * @param dev 610e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 611e60fbd5bSAdrien Mazarguil * @param[out] info 612e60fbd5bSAdrien Mazarguil * Info structure output buffer. 613e60fbd5bSAdrien Mazarguil */ 614bdad90d1SIvan Ilchenko int 615e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 616e60fbd5bSAdrien Mazarguil { 617dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 6187fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 619e60fbd5bSAdrien Mazarguil unsigned int max; 620e60fbd5bSAdrien Mazarguil 621e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 622e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 623e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 6241c7e57f9SDekel Peled info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE; 625e60fbd5bSAdrien Mazarguil /* 626e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 627e60fbd5bSAdrien Mazarguil * between the two values. 628e60fbd5bSAdrien Mazarguil */ 629*e85f623eSOphir Munk max = RTE_MIN(priv->sh->device_attr.max_cq, 630*e85f623eSOphir Munk priv->sh->device_attr.max_qp); 631b689a781SThomas Monjalon /* max_rx_queues is uint16_t. */ 632b689a781SThomas Monjalon max = RTE_MIN(max, (unsigned int)UINT16_MAX); 633e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 634e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 63518c01b98SNélio Laranjeiro info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; 636af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 63717ed314cSMatan Azrad info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 63817b843ebSShahaf Shuler info->rx_queue_offload_capa); 639af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 640fa2e14d4SViacheslav Ovsiienko info->if_index = mlx5_ifindex(dev); 641d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 6427fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 643c388a2f6SNelio Laranjeiro info->hash_key_size = MLX5_RSS_HASH_KEY_LEN; 64475ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 645b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 646d11d651fSShahaf Shuler mlx5_set_default_params(dev, info); 647cb9cb61eSViacheslav Ovsiienko mlx5_set_txlimit_params(dev, info); 6482b730263SAdrien Mazarguil info->switch_info.name = dev->data->name; 6492b730263SAdrien Mazarguil info->switch_info.domain_id = priv->domain_id; 6502b730263SAdrien Mazarguil info->switch_info.port_id = priv->representor_id; 6512b730263SAdrien Mazarguil if (priv->representor) { 652f7e95215SViacheslav Ovsiienko uint16_t port_id; 6532b730263SAdrien Mazarguil 654bee57a0aSViacheslav Ovsiienko if (priv->pf_bond >= 0) { 655bee57a0aSViacheslav Ovsiienko /* 656bee57a0aSViacheslav Ovsiienko * Switch port ID is opaque value with driver defined 657bee57a0aSViacheslav Ovsiienko * format. Push the PF index in bonding configurations 658bee57a0aSViacheslav Ovsiienko * in upper four bits of port ID. If we get too many 659bee57a0aSViacheslav Ovsiienko * representors (more than 4K) or PFs (more than 15) 660bee57a0aSViacheslav Ovsiienko * this approach must be reconsidered. 661bee57a0aSViacheslav Ovsiienko */ 662bee57a0aSViacheslav Ovsiienko if ((info->switch_info.port_id >> 663bee57a0aSViacheslav Ovsiienko MLX5_PORT_ID_BONDING_PF_SHIFT) || 664bee57a0aSViacheslav Ovsiienko priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) { 665bee57a0aSViacheslav Ovsiienko DRV_LOG(ERR, "can't update switch port ID" 666bee57a0aSViacheslav Ovsiienko " for bonding device"); 6678e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 668bee57a0aSViacheslav Ovsiienko return -ENODEV; 669bee57a0aSViacheslav Ovsiienko } 670bee57a0aSViacheslav Ovsiienko info->switch_info.port_id |= 671bee57a0aSViacheslav Ovsiienko priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT; 672bee57a0aSViacheslav Ovsiienko } 673fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 674dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 675f7e95215SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 6762b730263SAdrien Mazarguil 6772b730263SAdrien Mazarguil if (!opriv || 6782b730263SAdrien Mazarguil opriv->representor || 679f7e95215SViacheslav Ovsiienko opriv->sh != priv->sh || 6802b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id) 6812b730263SAdrien Mazarguil continue; 6822b730263SAdrien Mazarguil /* 6832b730263SAdrien Mazarguil * Override switch name with that of the master 6842b730263SAdrien Mazarguil * device. 6852b730263SAdrien Mazarguil */ 6862b730263SAdrien Mazarguil info->switch_info.name = opriv->dev_data->name; 6872b730263SAdrien Mazarguil break; 6882b730263SAdrien Mazarguil } 6892b730263SAdrien Mazarguil } 690bdad90d1SIvan Ilchenko return 0; 691e60fbd5bSAdrien Mazarguil } 692e60fbd5bSAdrien Mazarguil 693fb732b0aSNélio Laranjeiro /** 694e571ad55STom Barbette * Get device current raw clock counter 695e571ad55STom Barbette * 696e571ad55STom Barbette * @param dev 697e571ad55STom Barbette * Pointer to Ethernet device structure. 698e571ad55STom Barbette * @param[out] time 699e571ad55STom Barbette * Current raw clock counter of the device. 700e571ad55STom Barbette * 701e571ad55STom Barbette * @return 702e571ad55STom Barbette * 0 if the clock has correctly been read 703e571ad55STom Barbette * The value of errno in case of error 704e571ad55STom Barbette */ 705e571ad55STom Barbette int 706e571ad55STom Barbette mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock) 707e571ad55STom Barbette { 708e571ad55STom Barbette struct mlx5_priv *priv = dev->data->dev_private; 709e571ad55STom Barbette struct ibv_context *ctx = priv->sh->ctx; 710e571ad55STom Barbette struct ibv_values_ex values; 711e571ad55STom Barbette int err = 0; 712e571ad55STom Barbette 713e571ad55STom Barbette values.comp_mask = IBV_VALUES_MASK_RAW_CLOCK; 714e571ad55STom Barbette err = mlx5_glue->query_rt_values_ex(ctx, &values); 715e571ad55STom Barbette if (err != 0) { 716e571ad55STom Barbette DRV_LOG(WARNING, "Could not query the clock !"); 717e571ad55STom Barbette return err; 718e571ad55STom Barbette } 719e571ad55STom Barbette *clock = values.raw_clock.tv_nsec; 720e571ad55STom Barbette return 0; 721e571ad55STom Barbette } 722e571ad55STom Barbette 723e571ad55STom Barbette /** 724714bf46eSThomas Monjalon * Get firmware version of a device. 725714bf46eSThomas Monjalon * 726714bf46eSThomas Monjalon * @param dev 727714bf46eSThomas Monjalon * Ethernet device port. 728714bf46eSThomas Monjalon * @param fw_ver 729714bf46eSThomas Monjalon * String output allocated by caller. 730714bf46eSThomas Monjalon * @param fw_size 731714bf46eSThomas Monjalon * Size of the output string, including terminating null byte. 732714bf46eSThomas Monjalon * 733714bf46eSThomas Monjalon * @return 734714bf46eSThomas Monjalon * 0 on success, or the size of the non truncated string if too big. 735714bf46eSThomas Monjalon */ 736714bf46eSThomas Monjalon int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 737714bf46eSThomas Monjalon { 738dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 739*e85f623eSOphir Munk struct mlx5_dev_attr *attr = &priv->sh->device_attr; 740714bf46eSThomas Monjalon size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 741714bf46eSThomas Monjalon 742714bf46eSThomas Monjalon if (fw_size < size) 743714bf46eSThomas Monjalon return size; 744714bf46eSThomas Monjalon if (fw_ver != NULL) 745714bf46eSThomas Monjalon strlcpy(fw_ver, attr->fw_ver, fw_size); 746714bf46eSThomas Monjalon return 0; 747714bf46eSThomas Monjalon } 748714bf46eSThomas Monjalon 749714bf46eSThomas Monjalon /** 750fb732b0aSNélio Laranjeiro * Get supported packet types. 751fb732b0aSNélio Laranjeiro * 752fb732b0aSNélio Laranjeiro * @param dev 753fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 754fb732b0aSNélio Laranjeiro * 755fb732b0aSNélio Laranjeiro * @return 756fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 757fb732b0aSNélio Laranjeiro */ 75878a38edfSJianfeng Tan const uint32_t * 75978a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 76078a38edfSJianfeng Tan { 76178a38edfSJianfeng Tan static const uint32_t ptypes[] = { 76278a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 763ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 764c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 765c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 766ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 767ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 768ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 769ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 770c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 771c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 772ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 773ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 774ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 775ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 77678a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 77778a38edfSJianfeng Tan }; 77878a38edfSJianfeng Tan 7796cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 7807d6bf6b8SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_mprq || 7816cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 78278a38edfSJianfeng Tan return ptypes; 78378a38edfSJianfeng Tan return NULL; 78478a38edfSJianfeng Tan } 78578a38edfSJianfeng Tan 786e60fbd5bSAdrien Mazarguil /** 7870333b2f5SViacheslav Ovsiienko * Retrieve the master device for representor in the same switch domain. 7880333b2f5SViacheslav Ovsiienko * 7890333b2f5SViacheslav Ovsiienko * @param dev 7900333b2f5SViacheslav Ovsiienko * Pointer to representor Ethernet device structure. 7910333b2f5SViacheslav Ovsiienko * 7920333b2f5SViacheslav Ovsiienko * @return 7930333b2f5SViacheslav Ovsiienko * Master device structure on success, NULL otherwise. 7940333b2f5SViacheslav Ovsiienko */ 7950333b2f5SViacheslav Ovsiienko 7960333b2f5SViacheslav Ovsiienko static struct rte_eth_dev * 7970333b2f5SViacheslav Ovsiienko mlx5_find_master_dev(struct rte_eth_dev *dev) 7980333b2f5SViacheslav Ovsiienko { 7990333b2f5SViacheslav Ovsiienko struct mlx5_priv *priv; 8000333b2f5SViacheslav Ovsiienko uint16_t port_id; 8010333b2f5SViacheslav Ovsiienko uint16_t domain_id; 8020333b2f5SViacheslav Ovsiienko 8030333b2f5SViacheslav Ovsiienko priv = dev->data->dev_private; 8040333b2f5SViacheslav Ovsiienko domain_id = priv->domain_id; 8058e46d4e1SAlexander Kozyrev MLX5_ASSERT(priv->representor); 806fbc83412SViacheslav Ovsiienko MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 807f7e95215SViacheslav Ovsiienko struct mlx5_priv *opriv = 808f7e95215SViacheslav Ovsiienko rte_eth_devices[port_id].data->dev_private; 809f7e95215SViacheslav Ovsiienko if (opriv && 810f7e95215SViacheslav Ovsiienko opriv->master && 811f7e95215SViacheslav Ovsiienko opriv->domain_id == domain_id && 812f7e95215SViacheslav Ovsiienko opriv->sh == priv->sh) 8130333b2f5SViacheslav Ovsiienko return &rte_eth_devices[port_id]; 8140333b2f5SViacheslav Ovsiienko } 8150333b2f5SViacheslav Ovsiienko return NULL; 8160333b2f5SViacheslav Ovsiienko } 8170333b2f5SViacheslav Ovsiienko 8180333b2f5SViacheslav Ovsiienko /** 8192c960a51SMatthieu Ternisien d'Ouville * DPDK callback to retrieve physical link information. 820cb8faed7SAdrien Mazarguil * 821cb8faed7SAdrien Mazarguil * @param dev 822cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 823cfee9475SNélio Laranjeiro * @param[out] link 824cfee9475SNélio Laranjeiro * Storage for current link status. 825fb732b0aSNélio Laranjeiro * 826fb732b0aSNélio Laranjeiro * @return 827a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 828cb8faed7SAdrien Mazarguil */ 82918840871SNélio Laranjeiro static int 830cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev, 831cfee9475SNélio Laranjeiro struct rte_eth_link *link) 832cb8faed7SAdrien Mazarguil { 833dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 834cb8faed7SAdrien Mazarguil struct ethtool_cmd edata = { 83575ef62a9SNélio Laranjeiro .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */ 836cb8faed7SAdrien Mazarguil }; 837cb8faed7SAdrien Mazarguil struct ifreq ifr; 838cb8faed7SAdrien Mazarguil struct rte_eth_link dev_link; 839cb8faed7SAdrien Mazarguil int link_speed = 0; 840a6d83b6aSNélio Laranjeiro int ret; 841cb8faed7SAdrien Mazarguil 8427dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 843a6d83b6aSNélio Laranjeiro if (ret) { 844a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 8450f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 846a6d83b6aSNélio Laranjeiro return ret; 847cb8faed7SAdrien Mazarguil } 8487bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 8497bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 8507bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 8517bc47fb8SXueming Li }; 8527bc47fb8SXueming Li ifr = (struct ifreq) { 8537bc47fb8SXueming Li .ifr_data = (void *)&edata, 8547bc47fb8SXueming Li }; 8557dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 856a6d83b6aSNélio Laranjeiro if (ret) { 8570333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 8580333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master; 8590333b2f5SViacheslav Ovsiienko 8600333b2f5SViacheslav Ovsiienko /* 8610333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 8620333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 8630333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 8640333b2f5SViacheslav Ovsiienko * for representors due to missing physical 8650333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 8660333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 8670333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 8680333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 8690333b2f5SViacheslav Ovsiienko */ 8700333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 8710333b2f5SViacheslav Ovsiienko if (master) { 8720333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 8730333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&edata, 8740333b2f5SViacheslav Ovsiienko }; 875ff45f462SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 8760333b2f5SViacheslav Ovsiienko } 8770333b2f5SViacheslav Ovsiienko } 8780333b2f5SViacheslav Ovsiienko if (ret) { 879a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 8800333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 8810333b2f5SViacheslav Ovsiienko " ETHTOOL_GSET) failed: %s", 8820f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 883a6d83b6aSNélio Laranjeiro return ret; 884cb8faed7SAdrien Mazarguil } 8850333b2f5SViacheslav Ovsiienko } 886cb8faed7SAdrien Mazarguil link_speed = ethtool_cmd_speed(&edata); 887cb8faed7SAdrien Mazarguil if (link_speed == -1) 8883fef0822SFerruh Yigit dev_link.link_speed = ETH_SPEED_NUM_NONE; 889cb8faed7SAdrien Mazarguil else 890cb8faed7SAdrien Mazarguil dev_link.link_speed = link_speed; 89175ef62a9SNélio Laranjeiro priv->link_speed_capa = 0; 89275ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_Autoneg) 89375ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 89475ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_1000baseT_Full | 89575ef62a9SNélio Laranjeiro SUPPORTED_1000baseKX_Full)) 89675ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 89775ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_10000baseKR_Full) 89875ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 89975ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_40000baseKR4_Full | 90075ef62a9SNélio Laranjeiro SUPPORTED_40000baseCR4_Full | 90175ef62a9SNélio Laranjeiro SUPPORTED_40000baseSR4_Full | 90275ef62a9SNélio Laranjeiro SUPPORTED_40000baseLR4_Full)) 90375ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 904cb8faed7SAdrien Mazarguil dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 905cb8faed7SAdrien Mazarguil ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 90682113036SMarc Sune dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 90782113036SMarc Sune ETH_LINK_SPEED_FIXED); 9087dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 9097bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 910a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 911a6d83b6aSNélio Laranjeiro return -rte_errno; 912cb8faed7SAdrien Mazarguil } 913cfee9475SNélio Laranjeiro *link = dev_link; 914cfee9475SNélio Laranjeiro return 0; 915cfee9475SNélio Laranjeiro } 916cb8faed7SAdrien Mazarguil 917cb8faed7SAdrien Mazarguil /** 9183a49ffe3SShahaf Shuler * Retrieve physical link information (unlocked version using new ioctl). 91918840871SNélio Laranjeiro * 92018840871SNélio Laranjeiro * @param dev 92118840871SNélio Laranjeiro * Pointer to Ethernet device structure. 922cfee9475SNélio Laranjeiro * @param[out] link 923cfee9475SNélio Laranjeiro * Storage for current link status. 924fb732b0aSNélio Laranjeiro * 925fb732b0aSNélio Laranjeiro * @return 926a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 92718840871SNélio Laranjeiro */ 92818840871SNélio Laranjeiro static int 929cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev, 930cfee9475SNélio Laranjeiro struct rte_eth_link *link) 931cfee9475SNélio Laranjeiro 93218840871SNélio Laranjeiro { 933dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 93437a4406cSNélio Laranjeiro struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS }; 93518840871SNélio Laranjeiro struct ifreq ifr; 93618840871SNélio Laranjeiro struct rte_eth_link dev_link; 9370333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master = NULL; 93818840871SNélio Laranjeiro uint64_t sc; 939a6d83b6aSNélio Laranjeiro int ret; 94018840871SNélio Laranjeiro 9417dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 942a6d83b6aSNélio Laranjeiro if (ret) { 943a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 9440f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 945a6d83b6aSNélio Laranjeiro return ret; 94618840871SNélio Laranjeiro } 9477bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 9487bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 9497bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 9507bc47fb8SXueming Li }; 9517bc47fb8SXueming Li ifr = (struct ifreq) { 9527bc47fb8SXueming Li .ifr_data = (void *)&gcmd, 9537bc47fb8SXueming Li }; 9547dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 955a6d83b6aSNélio Laranjeiro if (ret) { 9560333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 9570333b2f5SViacheslav Ovsiienko /* 9580333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 9590333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 9600333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 9610333b2f5SViacheslav Ovsiienko * for representors due to missing physical 9620333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 9630333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 9640333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 9650333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 9660333b2f5SViacheslav Ovsiienko */ 9670333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 9680333b2f5SViacheslav Ovsiienko if (master) { 9690333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 9700333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&gcmd, 9710333b2f5SViacheslav Ovsiienko }; 972ff45f462SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 9730333b2f5SViacheslav Ovsiienko } 9740333b2f5SViacheslav Ovsiienko } 9750333b2f5SViacheslav Ovsiienko if (ret) { 976a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 9770333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 9780333b2f5SViacheslav Ovsiienko " ETHTOOL_GLINKSETTINGS) failed: %s", 979a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 980a6d83b6aSNélio Laranjeiro return ret; 98118840871SNélio Laranjeiro } 9820333b2f5SViacheslav Ovsiienko 9830333b2f5SViacheslav Ovsiienko } 98437a4406cSNélio Laranjeiro gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords; 98537a4406cSNélio Laranjeiro 98637a4406cSNélio Laranjeiro alignas(struct ethtool_link_settings) 98737a4406cSNélio Laranjeiro uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) + 98837a4406cSNélio Laranjeiro sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3]; 98937a4406cSNélio Laranjeiro struct ethtool_link_settings *ecmd = (void *)data; 99037a4406cSNélio Laranjeiro 99137a4406cSNélio Laranjeiro *ecmd = gcmd; 99237a4406cSNélio Laranjeiro ifr.ifr_data = (void *)ecmd; 993ff45f462SViacheslav Ovsiienko ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr); 994a6d83b6aSNélio Laranjeiro if (ret) { 995a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 9960333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 9970333b2f5SViacheslav Ovsiienko "ETHTOOL_GLINKSETTINGS) failed: %s", 998a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 999a6d83b6aSNélio Laranjeiro return ret; 1000ef09a7fcSGowrishankar Muthukrishnan } 10016fd05da9SXiaoyu Min dev_link.link_speed = (ecmd->speed == UINT32_MAX) ? ETH_SPEED_NUM_NONE : 10026fd05da9SXiaoyu Min ecmd->speed; 100390260d57SNélio Laranjeiro sc = ecmd->link_mode_masks[0] | 100490260d57SNélio Laranjeiro ((uint64_t)ecmd->link_mode_masks[1] << 32); 100518840871SNélio Laranjeiro priv->link_speed_capa = 0; 1006b113cb5eSEdward Makarov if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT)) 100718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 1008b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) | 1009b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT))) 101018840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 1011b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) | 1012b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) | 1013b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT))) 101418840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 1015b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) | 1016b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT))) 101718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_20G; 1018b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) | 1019b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) | 1020b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) | 1021b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT))) 102218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 1023b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) | 1024b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) | 1025b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) | 1026b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT))) 102718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_56G; 1028b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) | 1029b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) | 1030b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT))) 103118840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_25G; 1032b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) | 1033b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT))) 103418840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_50G; 1035b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) | 1036b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) | 1037b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) | 1038b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT))) 103918840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_100G; 10406e3a4595SAsaf Penso if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT) | 10416e3a4595SAsaf Penso MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT))) 10426e3a4595SAsaf Penso priv->link_speed_capa |= ETH_LINK_SPEED_200G; 10436e3a4595SAsaf Penso 10446e3a4595SAsaf Penso sc = ecmd->link_mode_masks[2] | 10456e3a4595SAsaf Penso ((uint64_t)ecmd->link_mode_masks[3] << 32); 10466e3a4595SAsaf Penso if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT) | 10476e3a4595SAsaf Penso MLX5_BITSHIFT( 10486e3a4595SAsaf Penso ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT) | 10496e3a4595SAsaf Penso MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT))) 10506e3a4595SAsaf Penso priv->link_speed_capa |= ETH_LINK_SPEED_200G; 105190260d57SNélio Laranjeiro dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ? 105218840871SNélio Laranjeiro ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 105318840871SNélio Laranjeiro dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 105418840871SNélio Laranjeiro ETH_LINK_SPEED_FIXED); 10557dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 10567bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 1057a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 1058a6d83b6aSNélio Laranjeiro return -rte_errno; 105918840871SNélio Laranjeiro } 1060cfee9475SNélio Laranjeiro *link = dev_link; 1061cfee9475SNélio Laranjeiro return 0; 1062cfee9475SNélio Laranjeiro } 106318840871SNélio Laranjeiro 106418840871SNélio Laranjeiro /** 1065cb8faed7SAdrien Mazarguil * DPDK callback to retrieve physical link information. 1066cb8faed7SAdrien Mazarguil * 1067cb8faed7SAdrien Mazarguil * @param dev 1068cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 1069cb8faed7SAdrien Mazarguil * @param wait_to_complete 1070cfee9475SNélio Laranjeiro * Wait for request completion. 1071fb732b0aSNélio Laranjeiro * 1072fb732b0aSNélio Laranjeiro * @return 1073cfee9475SNélio Laranjeiro * 0 if link status was not updated, positive if it was, a negative errno 1074cfee9475SNélio Laranjeiro * value otherwise and rte_errno is set. 1075cb8faed7SAdrien Mazarguil */ 1076cb8faed7SAdrien Mazarguil int 1077cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) 1078cb8faed7SAdrien Mazarguil { 1079c7bf6225SYongseok Koh int ret; 1080cfee9475SNélio Laranjeiro struct rte_eth_link dev_link; 1081cfee9475SNélio Laranjeiro time_t start_time = time(NULL); 108206ee1578SMoti Haimovsky int retry = MLX5_GET_LINK_STATUS_RETRY_COUNT; 1083cb8faed7SAdrien Mazarguil 1084cfee9475SNélio Laranjeiro do { 1085cfee9475SNélio Laranjeiro ret = mlx5_link_update_unlocked_gs(dev, &dev_link); 1086cb1d2cceSAsaf Penso if (ret == -ENOTSUP) 10877d2e32f7SShahaf Shuler ret = mlx5_link_update_unlocked_gset(dev, &dev_link); 1088cfee9475SNélio Laranjeiro if (ret == 0) 1089cfee9475SNélio Laranjeiro break; 1090cfee9475SNélio Laranjeiro /* Handle wait to complete situation. */ 109106ee1578SMoti Haimovsky if ((wait_to_complete || retry) && ret == -EAGAIN) { 1092cfee9475SNélio Laranjeiro if (abs((int)difftime(time(NULL), start_time)) < 1093cfee9475SNélio Laranjeiro MLX5_LINK_STATUS_TIMEOUT) { 1094cfee9475SNélio Laranjeiro usleep(0); 1095cfee9475SNélio Laranjeiro continue; 1096cfee9475SNélio Laranjeiro } else { 1097cfee9475SNélio Laranjeiro rte_errno = EBUSY; 1098cfee9475SNélio Laranjeiro return -rte_errno; 1099cfee9475SNélio Laranjeiro } 1100cfee9475SNélio Laranjeiro } else if (ret < 0) { 1101cfee9475SNélio Laranjeiro return ret; 1102cfee9475SNélio Laranjeiro } 110306ee1578SMoti Haimovsky } while (wait_to_complete || retry-- > 0); 1104cfee9475SNélio Laranjeiro ret = !!memcmp(&dev->data->dev_link, &dev_link, 1105cfee9475SNélio Laranjeiro sizeof(struct rte_eth_link)); 1106cfee9475SNélio Laranjeiro dev->data->dev_link = dev_link; 1107cfee9475SNélio Laranjeiro return ret; 1108cb8faed7SAdrien Mazarguil } 1109cb8faed7SAdrien Mazarguil 1110cb8faed7SAdrien Mazarguil /** 1111cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 1112cf37ca95SAdrien Mazarguil * 1113cf37ca95SAdrien Mazarguil * @param dev 1114cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 1115cf37ca95SAdrien Mazarguil * @param in_mtu 1116cf37ca95SAdrien Mazarguil * New MTU. 1117cf37ca95SAdrien Mazarguil * 1118cf37ca95SAdrien Mazarguil * @return 1119a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1120cf37ca95SAdrien Mazarguil */ 1121cf37ca95SAdrien Mazarguil int 1122cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 1123cf37ca95SAdrien Mazarguil { 1124dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 1125a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 1126a6d83b6aSNélio Laranjeiro int ret; 1127cf37ca95SAdrien Mazarguil 1128af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 1129a0edafe4SNelio Laranjeiro if (ret) 1130a6d83b6aSNélio Laranjeiro return ret; 1131cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 1132af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 1133a0edafe4SNelio Laranjeiro if (ret) 1134a6d83b6aSNélio Laranjeiro return ret; 1135af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 1136a0edafe4SNelio Laranjeiro if (ret) 1137a6d83b6aSNélio Laranjeiro return ret; 1138a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 1139a0edafe4SNelio Laranjeiro priv->mtu = mtu; 1140a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u adapter MTU set to %u", 1141a170a30dSNélio Laranjeiro dev->data->port_id, mtu); 1142a0edafe4SNelio Laranjeiro return 0; 1143a6d83b6aSNélio Laranjeiro } 1144a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 1145a6d83b6aSNélio Laranjeiro return -rte_errno; 1146cf37ca95SAdrien Mazarguil } 1147cf37ca95SAdrien Mazarguil 1148cf37ca95SAdrien Mazarguil /** 114902d75430SAdrien Mazarguil * DPDK callback to get flow control status. 115002d75430SAdrien Mazarguil * 115102d75430SAdrien Mazarguil * @param dev 115202d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 115302d75430SAdrien Mazarguil * @param[out] fc_conf 115402d75430SAdrien Mazarguil * Flow control output buffer. 115502d75430SAdrien Mazarguil * 115602d75430SAdrien Mazarguil * @return 1157a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 115802d75430SAdrien Mazarguil */ 115902d75430SAdrien Mazarguil int 116002d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 116102d75430SAdrien Mazarguil { 116202d75430SAdrien Mazarguil struct ifreq ifr; 116302d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 116402d75430SAdrien Mazarguil .cmd = ETHTOOL_GPAUSEPARAM 116502d75430SAdrien Mazarguil }; 116602d75430SAdrien Mazarguil int ret; 116702d75430SAdrien Mazarguil 1168d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 11697dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1170a6d83b6aSNélio Laranjeiro if (ret) { 1171a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1172a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:" 1173a170a30dSNélio Laranjeiro " %s", 1174a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1175a6d83b6aSNélio Laranjeiro return ret; 117602d75430SAdrien Mazarguil } 117702d75430SAdrien Mazarguil fc_conf->autoneg = ethpause.autoneg; 117802d75430SAdrien Mazarguil if (ethpause.rx_pause && ethpause.tx_pause) 117902d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_FULL; 118002d75430SAdrien Mazarguil else if (ethpause.rx_pause) 118102d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_RX_PAUSE; 118202d75430SAdrien Mazarguil else if (ethpause.tx_pause) 118302d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_TX_PAUSE; 118402d75430SAdrien Mazarguil else 118502d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_NONE; 1186a6d83b6aSNélio Laranjeiro return 0; 118702d75430SAdrien Mazarguil } 118802d75430SAdrien Mazarguil 118902d75430SAdrien Mazarguil /** 119002d75430SAdrien Mazarguil * DPDK callback to modify flow control parameters. 119102d75430SAdrien Mazarguil * 119202d75430SAdrien Mazarguil * @param dev 119302d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 119402d75430SAdrien Mazarguil * @param[in] fc_conf 119502d75430SAdrien Mazarguil * Flow control parameters. 119602d75430SAdrien Mazarguil * 119702d75430SAdrien Mazarguil * @return 1198a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 119902d75430SAdrien Mazarguil */ 120002d75430SAdrien Mazarguil int 120102d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 120202d75430SAdrien Mazarguil { 120302d75430SAdrien Mazarguil struct ifreq ifr; 120402d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 120502d75430SAdrien Mazarguil .cmd = ETHTOOL_SPAUSEPARAM 120602d75430SAdrien Mazarguil }; 120702d75430SAdrien Mazarguil int ret; 120802d75430SAdrien Mazarguil 1209d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 121002d75430SAdrien Mazarguil ethpause.autoneg = fc_conf->autoneg; 121102d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 121202d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_RX_PAUSE)) 121302d75430SAdrien Mazarguil ethpause.rx_pause = 1; 121402d75430SAdrien Mazarguil else 121502d75430SAdrien Mazarguil ethpause.rx_pause = 0; 121602d75430SAdrien Mazarguil 121702d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 121802d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_TX_PAUSE)) 121902d75430SAdrien Mazarguil ethpause.tx_pause = 1; 122002d75430SAdrien Mazarguil else 122102d75430SAdrien Mazarguil ethpause.tx_pause = 0; 12227dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1223a6d83b6aSNélio Laranjeiro if (ret) { 1224a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1225a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 1226a170a30dSNélio Laranjeiro " failed: %s", 1227a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1228a6d83b6aSNélio Laranjeiro return ret; 122902d75430SAdrien Mazarguil } 1230a6d83b6aSNélio Laranjeiro return 0; 123102d75430SAdrien Mazarguil } 123202d75430SAdrien Mazarguil 123302d75430SAdrien Mazarguil /** 123440d9f906SViacheslav Ovsiienko * Handle asynchronous removal event for entire multiport device. 123540d9f906SViacheslav Ovsiienko * 123640d9f906SViacheslav Ovsiienko * @param sh 123740d9f906SViacheslav Ovsiienko * Infiniband device shared context. 123840d9f906SViacheslav Ovsiienko */ 123940d9f906SViacheslav Ovsiienko static void 12406e88bc42SOphir Munk mlx5_dev_interrupt_device_fatal(struct mlx5_dev_ctx_shared *sh) 124140d9f906SViacheslav Ovsiienko { 124240d9f906SViacheslav Ovsiienko uint32_t i; 124340d9f906SViacheslav Ovsiienko 124440d9f906SViacheslav Ovsiienko for (i = 0; i < sh->max_port; ++i) { 124540d9f906SViacheslav Ovsiienko struct rte_eth_dev *dev; 124640d9f906SViacheslav Ovsiienko 124740d9f906SViacheslav Ovsiienko if (sh->port[i].ih_port_id >= RTE_MAX_ETHPORTS) { 124840d9f906SViacheslav Ovsiienko /* 124940d9f906SViacheslav Ovsiienko * Or not existing port either no 125040d9f906SViacheslav Ovsiienko * handler installed for this port. 125140d9f906SViacheslav Ovsiienko */ 125240d9f906SViacheslav Ovsiienko continue; 125340d9f906SViacheslav Ovsiienko } 125440d9f906SViacheslav Ovsiienko dev = &rte_eth_devices[sh->port[i].ih_port_id]; 12558e46d4e1SAlexander Kozyrev MLX5_ASSERT(dev); 125640d9f906SViacheslav Ovsiienko if (dev->data->dev_conf.intr_conf.rmv) 125740d9f906SViacheslav Ovsiienko _rte_eth_dev_callback_process 125840d9f906SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_RMV, NULL); 125940d9f906SViacheslav Ovsiienko } 126040d9f906SViacheslav Ovsiienko } 126140d9f906SViacheslav Ovsiienko 126240d9f906SViacheslav Ovsiienko /** 1263028b2a28SViacheslav Ovsiienko * Handle shared asynchronous events the NIC (removal event 1264028b2a28SViacheslav Ovsiienko * and link status change). Supports multiport IB device. 1265c26ae069SMatan Azrad * 1266198a3c33SNelio Laranjeiro * @param cb_arg 1267198a3c33SNelio Laranjeiro * Callback argument. 1268198a3c33SNelio Laranjeiro */ 1269198a3c33SNelio Laranjeiro void 1270c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg) 1271198a3c33SNelio Laranjeiro { 12726e88bc42SOphir Munk struct mlx5_dev_ctx_shared *sh = cb_arg; 1273028b2a28SViacheslav Ovsiienko struct ibv_async_event event; 1274198a3c33SNelio Laranjeiro 1275028b2a28SViacheslav Ovsiienko /* Read all message from the IB device and acknowledge them. */ 1276028b2a28SViacheslav Ovsiienko for (;;) { 1277028b2a28SViacheslav Ovsiienko struct rte_eth_dev *dev; 1278028b2a28SViacheslav Ovsiienko uint32_t tmp; 1279028b2a28SViacheslav Ovsiienko 1280028b2a28SViacheslav Ovsiienko if (mlx5_glue->get_async_event(sh->ctx, &event)) 1281028b2a28SViacheslav Ovsiienko break; 1282028b2a28SViacheslav Ovsiienko /* Retrieve and check IB port index. */ 1283028b2a28SViacheslav Ovsiienko tmp = (uint32_t)event.element.port_num; 128440d9f906SViacheslav Ovsiienko if (!tmp && event.event_type == IBV_EVENT_DEVICE_FATAL) { 1285028b2a28SViacheslav Ovsiienko /* 128640d9f906SViacheslav Ovsiienko * The DEVICE_FATAL event is called once for 128740d9f906SViacheslav Ovsiienko * entire device without port specifying. 128840d9f906SViacheslav Ovsiienko * We should notify all existing ports. 1289028b2a28SViacheslav Ovsiienko */ 1290028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 129140d9f906SViacheslav Ovsiienko mlx5_dev_interrupt_device_fatal(sh); 129240d9f906SViacheslav Ovsiienko continue; 129340d9f906SViacheslav Ovsiienko } 12948e46d4e1SAlexander Kozyrev MLX5_ASSERT(tmp && (tmp <= sh->max_port)); 129540d9f906SViacheslav Ovsiienko if (!tmp) { 129640d9f906SViacheslav Ovsiienko /* Unsupported devive level event. */ 129740d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 129840d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 129940d9f906SViacheslav Ovsiienko "unsupported common event (type %d)", 130040d9f906SViacheslav Ovsiienko event.event_type); 130140d9f906SViacheslav Ovsiienko continue; 130240d9f906SViacheslav Ovsiienko } 130340d9f906SViacheslav Ovsiienko if (tmp > sh->max_port) { 130440d9f906SViacheslav Ovsiienko /* Invalid IB port index. */ 130540d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 130640d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 130740d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 130840d9f906SViacheslav Ovsiienko "due to invalid IB port index (%u)", 130940d9f906SViacheslav Ovsiienko event.event_type, tmp); 131040d9f906SViacheslav Ovsiienko continue; 131140d9f906SViacheslav Ovsiienko } 131240d9f906SViacheslav Ovsiienko if (sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) { 131340d9f906SViacheslav Ovsiienko /* No handler installed. */ 131440d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 131540d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 131640d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 131740d9f906SViacheslav Ovsiienko "due to no handler installed for port %u", 131840d9f906SViacheslav Ovsiienko event.event_type, tmp); 1319028b2a28SViacheslav Ovsiienko continue; 1320028b2a28SViacheslav Ovsiienko } 1321028b2a28SViacheslav Ovsiienko /* Retrieve ethernet device descriptor. */ 1322028b2a28SViacheslav Ovsiienko tmp = sh->port[tmp - 1].ih_port_id; 1323028b2a28SViacheslav Ovsiienko dev = &rte_eth_devices[tmp]; 13248e46d4e1SAlexander Kozyrev MLX5_ASSERT(dev); 1325028b2a28SViacheslav Ovsiienko if ((event.event_type == IBV_EVENT_PORT_ACTIVE || 1326028b2a28SViacheslav Ovsiienko event.event_type == IBV_EVENT_PORT_ERR) && 1327028b2a28SViacheslav Ovsiienko dev->data->dev_conf.intr_conf.lsc) { 1328028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1329028b2a28SViacheslav Ovsiienko if (mlx5_link_update(dev, 0) == -EAGAIN) { 1330028b2a28SViacheslav Ovsiienko usleep(0); 1331028b2a28SViacheslav Ovsiienko continue; 1332028b2a28SViacheslav Ovsiienko } 1333028b2a28SViacheslav Ovsiienko _rte_eth_dev_callback_process 1334028b2a28SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_LSC, NULL); 1335028b2a28SViacheslav Ovsiienko continue; 1336028b2a28SViacheslav Ovsiienko } 1337028b2a28SViacheslav Ovsiienko DRV_LOG(DEBUG, 133840d9f906SViacheslav Ovsiienko "port %u cannot handle an unknown event (type %d)", 1339028b2a28SViacheslav Ovsiienko dev->data->port_id, event.event_type); 1340028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1341028b2a28SViacheslav Ovsiienko } 1342198a3c33SNelio Laranjeiro } 1343198a3c33SNelio Laranjeiro 13445897ac13SViacheslav Ovsiienko /* 13455897ac13SViacheslav Ovsiienko * Unregister callback handler safely. The handler may be active 13465897ac13SViacheslav Ovsiienko * while we are trying to unregister it, in this case code -EAGAIN 13475897ac13SViacheslav Ovsiienko * is returned by rte_intr_callback_unregister(). This routine checks 13485897ac13SViacheslav Ovsiienko * the return code and tries to unregister handler again. 13495897ac13SViacheslav Ovsiienko * 13505897ac13SViacheslav Ovsiienko * @param handle 13515897ac13SViacheslav Ovsiienko * interrupt handle 13525897ac13SViacheslav Ovsiienko * @param cb_fn 13535897ac13SViacheslav Ovsiienko * pointer to callback routine 13545897ac13SViacheslav Ovsiienko * @cb_arg 13555897ac13SViacheslav Ovsiienko * opaque callback parameter 13565897ac13SViacheslav Ovsiienko */ 13575897ac13SViacheslav Ovsiienko void 13585897ac13SViacheslav Ovsiienko mlx5_intr_callback_unregister(const struct rte_intr_handle *handle, 13595897ac13SViacheslav Ovsiienko rte_intr_callback_fn cb_fn, void *cb_arg) 13605897ac13SViacheslav Ovsiienko { 13615897ac13SViacheslav Ovsiienko /* 13625897ac13SViacheslav Ovsiienko * Try to reduce timeout management overhead by not calling 13635897ac13SViacheslav Ovsiienko * the timer related routines on the first iteration. If the 13645897ac13SViacheslav Ovsiienko * unregistering succeeds on first call there will be no 13655897ac13SViacheslav Ovsiienko * timer calls at all. 13665897ac13SViacheslav Ovsiienko */ 13675897ac13SViacheslav Ovsiienko uint64_t twait = 0; 13685897ac13SViacheslav Ovsiienko uint64_t start = 0; 13695897ac13SViacheslav Ovsiienko 13705897ac13SViacheslav Ovsiienko do { 13715897ac13SViacheslav Ovsiienko int ret; 13725897ac13SViacheslav Ovsiienko 13735897ac13SViacheslav Ovsiienko ret = rte_intr_callback_unregister(handle, cb_fn, cb_arg); 13745897ac13SViacheslav Ovsiienko if (ret >= 0) 13755897ac13SViacheslav Ovsiienko return; 13765897ac13SViacheslav Ovsiienko if (ret != -EAGAIN) { 13775897ac13SViacheslav Ovsiienko DRV_LOG(INFO, "failed to unregister interrupt" 13785897ac13SViacheslav Ovsiienko " handler (error: %d)", ret); 13798e46d4e1SAlexander Kozyrev MLX5_ASSERT(false); 13805897ac13SViacheslav Ovsiienko return; 13815897ac13SViacheslav Ovsiienko } 13825897ac13SViacheslav Ovsiienko if (twait) { 13835897ac13SViacheslav Ovsiienko struct timespec onems; 13845897ac13SViacheslav Ovsiienko 13855897ac13SViacheslav Ovsiienko /* Wait one millisecond and try again. */ 13865897ac13SViacheslav Ovsiienko onems.tv_sec = 0; 13875897ac13SViacheslav Ovsiienko onems.tv_nsec = NS_PER_S / MS_PER_S; 13885897ac13SViacheslav Ovsiienko nanosleep(&onems, 0); 13895897ac13SViacheslav Ovsiienko /* Check whether one second elapsed. */ 13905897ac13SViacheslav Ovsiienko if ((rte_get_timer_cycles() - start) <= twait) 13915897ac13SViacheslav Ovsiienko continue; 13925897ac13SViacheslav Ovsiienko } else { 13935897ac13SViacheslav Ovsiienko /* 13945897ac13SViacheslav Ovsiienko * We get the amount of timer ticks for one second. 13955897ac13SViacheslav Ovsiienko * If this amount elapsed it means we spent one 13965897ac13SViacheslav Ovsiienko * second in waiting. This branch is executed once 13975897ac13SViacheslav Ovsiienko * on first iteration. 13985897ac13SViacheslav Ovsiienko */ 13995897ac13SViacheslav Ovsiienko twait = rte_get_timer_hz(); 14008e46d4e1SAlexander Kozyrev MLX5_ASSERT(twait); 14015897ac13SViacheslav Ovsiienko } 14025897ac13SViacheslav Ovsiienko /* 14035897ac13SViacheslav Ovsiienko * Timeout elapsed, show message (once a second) and retry. 14045897ac13SViacheslav Ovsiienko * We have no other acceptable option here, if we ignore 14055897ac13SViacheslav Ovsiienko * the unregistering return code the handler will not 14065897ac13SViacheslav Ovsiienko * be unregistered, fd will be closed and we may get the 14075897ac13SViacheslav Ovsiienko * crush. Hanging and messaging in the loop seems not to be 14085897ac13SViacheslav Ovsiienko * the worst choice. 14095897ac13SViacheslav Ovsiienko */ 14105897ac13SViacheslav Ovsiienko DRV_LOG(INFO, "Retrying to unregister interrupt handler"); 14115897ac13SViacheslav Ovsiienko start = rte_get_timer_cycles(); 14125897ac13SViacheslav Ovsiienko } while (true); 14135897ac13SViacheslav Ovsiienko } 14145897ac13SViacheslav Ovsiienko 1415198a3c33SNelio Laranjeiro /** 1416f15db67dSMatan Azrad * Handle DEVX interrupts from the NIC. 1417f15db67dSMatan Azrad * This function is probably called from the DPDK host thread. 1418f15db67dSMatan Azrad * 1419f15db67dSMatan Azrad * @param cb_arg 1420f15db67dSMatan Azrad * Callback argument. 1421f15db67dSMatan Azrad */ 1422f15db67dSMatan Azrad void 1423f15db67dSMatan Azrad mlx5_dev_interrupt_handler_devx(void *cb_arg) 1424f15db67dSMatan Azrad { 1425f15db67dSMatan Azrad #ifndef HAVE_IBV_DEVX_ASYNC 1426f15db67dSMatan Azrad (void)cb_arg; 1427f15db67dSMatan Azrad return; 1428f15db67dSMatan Azrad #else 14296e88bc42SOphir Munk struct mlx5_dev_ctx_shared *sh = cb_arg; 1430f15db67dSMatan Azrad union { 1431f15db67dSMatan Azrad struct mlx5dv_devx_async_cmd_hdr cmd_resp; 1432f15db67dSMatan Azrad uint8_t buf[MLX5_ST_SZ_BYTES(query_flow_counter_out) + 1433f15db67dSMatan Azrad MLX5_ST_SZ_BYTES(traffic_counter) + 1434f15db67dSMatan Azrad sizeof(struct mlx5dv_devx_async_cmd_hdr)]; 1435f15db67dSMatan Azrad } out; 1436f15db67dSMatan Azrad uint8_t *buf = out.buf + sizeof(out.cmd_resp); 1437f15db67dSMatan Azrad 1438f15db67dSMatan Azrad while (!mlx5_glue->devx_get_async_cmd_comp(sh->devx_comp, 1439f15db67dSMatan Azrad &out.cmd_resp, 1440f15db67dSMatan Azrad sizeof(out.buf))) 1441f15db67dSMatan Azrad mlx5_flow_async_pool_query_handle 1442f15db67dSMatan Azrad (sh, (uint64_t)out.cmd_resp.wr_id, 1443f15db67dSMatan Azrad mlx5_devx_get_out_command_status(buf)); 1444f15db67dSMatan Azrad #endif /* HAVE_IBV_DEVX_ASYNC */ 1445f15db67dSMatan Azrad } 1446f15db67dSMatan Azrad 1447f15db67dSMatan Azrad /** 144862072098SOr Ami * DPDK callback to bring the link DOWN. 144962072098SOr Ami * 145062072098SOr Ami * @param dev 145162072098SOr Ami * Pointer to Ethernet device structure. 145262072098SOr Ami * 145362072098SOr Ami * @return 1454a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 145562072098SOr Ami */ 145662072098SOr Ami int 145762072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev) 145862072098SOr Ami { 1459af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP); 146062072098SOr Ami } 146162072098SOr Ami 146262072098SOr Ami /** 146362072098SOr Ami * DPDK callback to bring the link UP. 146462072098SOr Ami * 146562072098SOr Ami * @param dev 146662072098SOr Ami * Pointer to Ethernet device structure. 146762072098SOr Ami * 146862072098SOr Ami * @return 1469a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 147062072098SOr Ami */ 147162072098SOr Ami int 147262072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev) 147362072098SOr Ami { 1474af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, IFF_UP); 147562072098SOr Ami } 1476a48deadaSOr Ami 1477a48deadaSOr Ami /** 1478cdab90cbSNélio Laranjeiro * Configure the RX function to use. 1479cdab90cbSNélio Laranjeiro * 1480aee1b165SXueming Li * @param dev 1481af4f09f2SNélio Laranjeiro * Pointer to private data structure. 14821cfa649bSShahaf Shuler * 14831cfa649bSShahaf Shuler * @return 14841cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 1485cdab90cbSNélio Laranjeiro */ 14861cfa649bSShahaf Shuler eth_rx_burst_t 1487af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 1488cdab90cbSNélio Laranjeiro { 14891cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 14901cfa649bSShahaf Shuler 14918e46d4e1SAlexander Kozyrev MLX5_ASSERT(dev != NULL); 1492af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 14931cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 1494a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected Rx vectorized function", 14950f99970bSNélio Laranjeiro dev->data->port_id); 14967d6bf6b8SYongseok Koh } else if (mlx5_mprq_enabled(dev)) { 14977d6bf6b8SYongseok Koh rx_pkt_burst = mlx5_rx_burst_mprq; 1498cdab90cbSNélio Laranjeiro } 14991cfa649bSShahaf Shuler return rx_pkt_burst; 15006cb559d6SYongseok Koh } 1501d3e0f392SMatan Azrad 1502d3e0f392SMatan Azrad /** 1503d3e0f392SMatan Azrad * Check if mlx5 device was removed. 1504d3e0f392SMatan Azrad * 1505d3e0f392SMatan Azrad * @param dev 1506d3e0f392SMatan Azrad * Pointer to Ethernet device structure. 1507d3e0f392SMatan Azrad * 1508d3e0f392SMatan Azrad * @return 1509d3e0f392SMatan Azrad * 1 when device is removed, otherwise 0. 1510d3e0f392SMatan Azrad */ 1511d3e0f392SMatan Azrad int 1512d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev) 1513d3e0f392SMatan Azrad { 1514d3e0f392SMatan Azrad struct ibv_device_attr device_attr; 1515dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 1516d3e0f392SMatan Azrad 1517f048f3d4SViacheslav Ovsiienko if (mlx5_glue->query_device(priv->sh->ctx, &device_attr) == EIO) 1518d3e0f392SMatan Azrad return 1; 1519d3e0f392SMatan Azrad return 0; 1520d3e0f392SMatan Azrad } 15212b730263SAdrien Mazarguil 15222b730263SAdrien Mazarguil /** 152309a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by port id. 15242e4c987aSOri Kam * 15252e4c987aSOri Kam * @param[in] port 15262e4c987aSOri Kam * Device port id. 15275e61bcddSViacheslav Ovsiienko * @param[in] valid 15285e61bcddSViacheslav Ovsiienko * Device port id is valid, skip check. This flag is useful 15295e61bcddSViacheslav Ovsiienko * when trials are performed from probing and device is not 15305e61bcddSViacheslav Ovsiienko * flagged as valid yet (in attaching process). 15312e4c987aSOri Kam * @param[out] es_domain_id 15322e4c987aSOri Kam * E-Switch domain id. 15332e4c987aSOri Kam * @param[out] es_port_id 15342e4c987aSOri Kam * The port id of the port in the E-Switch. 15352e4c987aSOri Kam * 15362e4c987aSOri Kam * @return 153709a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 153809a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 15392e4c987aSOri Kam */ 154009a16bcaSViacheslav Ovsiienko struct mlx5_priv * 15415e61bcddSViacheslav Ovsiienko mlx5_port_to_eswitch_info(uint16_t port, bool valid) 15422e4c987aSOri Kam { 15432e4c987aSOri Kam struct rte_eth_dev *dev; 15442e4c987aSOri Kam struct mlx5_priv *priv; 15452e4c987aSOri Kam 15462e4c987aSOri Kam if (port >= RTE_MAX_ETHPORTS) { 15472e4c987aSOri Kam rte_errno = EINVAL; 154809a16bcaSViacheslav Ovsiienko return NULL; 15492e4c987aSOri Kam } 15505e61bcddSViacheslav Ovsiienko if (!valid && !rte_eth_dev_is_valid_port(port)) { 15512e4c987aSOri Kam rte_errno = ENODEV; 155209a16bcaSViacheslav Ovsiienko return NULL; 15532e4c987aSOri Kam } 15542e4c987aSOri Kam dev = &rte_eth_devices[port]; 15552e4c987aSOri Kam priv = dev->data->dev_private; 15562e4c987aSOri Kam if (!(priv->representor || priv->master)) { 15572e4c987aSOri Kam rte_errno = EINVAL; 155809a16bcaSViacheslav Ovsiienko return NULL; 15592e4c987aSOri Kam } 156009a16bcaSViacheslav Ovsiienko return priv; 156109a16bcaSViacheslav Ovsiienko } 156209a16bcaSViacheslav Ovsiienko 156309a16bcaSViacheslav Ovsiienko /** 156409a16bcaSViacheslav Ovsiienko * Get the E-Switch parameters by device instance. 156509a16bcaSViacheslav Ovsiienko * 156609a16bcaSViacheslav Ovsiienko * @param[in] port 156709a16bcaSViacheslav Ovsiienko * Device port id. 156809a16bcaSViacheslav Ovsiienko * @param[out] es_domain_id 156909a16bcaSViacheslav Ovsiienko * E-Switch domain id. 157009a16bcaSViacheslav Ovsiienko * @param[out] es_port_id 157109a16bcaSViacheslav Ovsiienko * The port id of the port in the E-Switch. 157209a16bcaSViacheslav Ovsiienko * 157309a16bcaSViacheslav Ovsiienko * @return 157409a16bcaSViacheslav Ovsiienko * pointer to device private data structure containing data needed 157509a16bcaSViacheslav Ovsiienko * on success, NULL otherwise and rte_errno is set. 157609a16bcaSViacheslav Ovsiienko */ 157709a16bcaSViacheslav Ovsiienko struct mlx5_priv * 157809a16bcaSViacheslav Ovsiienko mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev) 157909a16bcaSViacheslav Ovsiienko { 158009a16bcaSViacheslav Ovsiienko struct mlx5_priv *priv; 158109a16bcaSViacheslav Ovsiienko 158209a16bcaSViacheslav Ovsiienko priv = dev->data->dev_private; 158309a16bcaSViacheslav Ovsiienko if (!(priv->representor || priv->master)) { 158409a16bcaSViacheslav Ovsiienko rte_errno = EINVAL; 158509a16bcaSViacheslav Ovsiienko return NULL; 158609a16bcaSViacheslav Ovsiienko } 158709a16bcaSViacheslav Ovsiienko return priv; 15882e4c987aSOri Kam } 15892e4c987aSOri Kam 15902e4c987aSOri Kam /** 1591f872b4b9SNelio Laranjeiro * Get switch information associated with network interface. 1592f872b4b9SNelio Laranjeiro * 1593f872b4b9SNelio Laranjeiro * @param ifindex 1594f872b4b9SNelio Laranjeiro * Network interface index. 1595f872b4b9SNelio Laranjeiro * @param[out] info 1596f872b4b9SNelio Laranjeiro * Switch information object, populated in case of success. 1597f872b4b9SNelio Laranjeiro * 1598f872b4b9SNelio Laranjeiro * @return 1599f872b4b9SNelio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1600f872b4b9SNelio Laranjeiro */ 1601f872b4b9SNelio Laranjeiro int 1602f872b4b9SNelio Laranjeiro mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) 1603f872b4b9SNelio Laranjeiro { 1604f872b4b9SNelio Laranjeiro char ifname[IF_NAMESIZE]; 1605b2f3a381SDekel Peled char port_name[IF_NAMESIZE]; 1606f872b4b9SNelio Laranjeiro FILE *file; 1607b2f3a381SDekel Peled struct mlx5_switch_info data = { 1608b2f3a381SDekel Peled .master = 0, 1609b2f3a381SDekel Peled .representor = 0, 161030a86157SViacheslav Ovsiienko .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET, 1611b2f3a381SDekel Peled .port_name = 0, 1612b2f3a381SDekel Peled .switch_id = 0, 1613b2f3a381SDekel Peled }; 1614299d7dc2SViacheslav Ovsiienko DIR *dir; 1615f872b4b9SNelio Laranjeiro bool port_switch_id_set = false; 1616299d7dc2SViacheslav Ovsiienko bool device_dir = false; 1617f872b4b9SNelio Laranjeiro char c; 1618e3bcaf3aSAli Alnubani int ret; 1619f872b4b9SNelio Laranjeiro 1620f872b4b9SNelio Laranjeiro if (!if_indextoname(ifindex, ifname)) { 1621f872b4b9SNelio Laranjeiro rte_errno = errno; 1622f872b4b9SNelio Laranjeiro return -rte_errno; 1623f872b4b9SNelio Laranjeiro } 1624f872b4b9SNelio Laranjeiro 1625f872b4b9SNelio Laranjeiro MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name", 1626f872b4b9SNelio Laranjeiro ifname); 1627f872b4b9SNelio Laranjeiro MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id", 1628f872b4b9SNelio Laranjeiro ifname); 1629299d7dc2SViacheslav Ovsiienko MKSTR(pci_device, "/sys/class/net/%s/device", 1630299d7dc2SViacheslav Ovsiienko ifname); 1631f872b4b9SNelio Laranjeiro 1632f872b4b9SNelio Laranjeiro file = fopen(phys_port_name, "rb"); 1633f872b4b9SNelio Laranjeiro if (file != NULL) { 1634e3bcaf3aSAli Alnubani ret = fscanf(file, "%s", port_name); 1635f872b4b9SNelio Laranjeiro fclose(file); 1636e3bcaf3aSAli Alnubani if (ret == 1) 163730a86157SViacheslav Ovsiienko mlx5_translate_port_name(port_name, &data); 1638f872b4b9SNelio Laranjeiro } 1639f872b4b9SNelio Laranjeiro file = fopen(phys_switch_id, "rb"); 1640f872b4b9SNelio Laranjeiro if (file == NULL) { 1641f872b4b9SNelio Laranjeiro rte_errno = errno; 1642f872b4b9SNelio Laranjeiro return -rte_errno; 1643f872b4b9SNelio Laranjeiro } 1644f872b4b9SNelio Laranjeiro port_switch_id_set = 1645f872b4b9SNelio Laranjeiro fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 && 1646f872b4b9SNelio Laranjeiro c == '\n'; 1647f872b4b9SNelio Laranjeiro fclose(file); 1648299d7dc2SViacheslav Ovsiienko dir = opendir(pci_device); 1649299d7dc2SViacheslav Ovsiienko if (dir != NULL) { 1650299d7dc2SViacheslav Ovsiienko closedir(dir); 1651299d7dc2SViacheslav Ovsiienko device_dir = true; 1652299d7dc2SViacheslav Ovsiienko } 165330a86157SViacheslav Ovsiienko if (port_switch_id_set) { 165430a86157SViacheslav Ovsiienko /* We have some E-Switch configuration. */ 165530a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(device_dir, &data); 165630a86157SViacheslav Ovsiienko } 1657f872b4b9SNelio Laranjeiro *info = data; 16588e46d4e1SAlexander Kozyrev MLX5_ASSERT(!(data.master && data.representor)); 1659299d7dc2SViacheslav Ovsiienko if (data.master && data.representor) { 1660299d7dc2SViacheslav Ovsiienko DRV_LOG(ERR, "ifindex %u device is recognized as master" 1661299d7dc2SViacheslav Ovsiienko " and as representor", ifindex); 1662299d7dc2SViacheslav Ovsiienko rte_errno = ENODEV; 1663299d7dc2SViacheslav Ovsiienko return -rte_errno; 1664299d7dc2SViacheslav Ovsiienko } 1665f872b4b9SNelio Laranjeiro return 0; 1666f872b4b9SNelio Laranjeiro } 1667b2f3a381SDekel Peled 1668b2f3a381SDekel Peled /** 166930a86157SViacheslav Ovsiienko * Analyze gathered port parameters via sysfs to recognize master 167030a86157SViacheslav Ovsiienko * and representor devices for E-Switch configuration. 167130a86157SViacheslav Ovsiienko * 167230a86157SViacheslav Ovsiienko * @param[in] device_dir 167330a86157SViacheslav Ovsiienko * flag of presence of "device" directory under port device key. 167430a86157SViacheslav Ovsiienko * @param[inout] switch_info 167530a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 167630a86157SViacheslav Ovsiienko * type if recognized 167730a86157SViacheslav Ovsiienko * 167830a86157SViacheslav Ovsiienko * @return 167930a86157SViacheslav Ovsiienko * master and representor flags are set in switch_info according to 168030a86157SViacheslav Ovsiienko * recognized parameters (if any). 168130a86157SViacheslav Ovsiienko */ 168230a86157SViacheslav Ovsiienko void 168330a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(bool device_dir, 168430a86157SViacheslav Ovsiienko struct mlx5_switch_info *switch_info) 168530a86157SViacheslav Ovsiienko { 168630a86157SViacheslav Ovsiienko switch (switch_info->name_type) { 168730a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: 168830a86157SViacheslav Ovsiienko /* 168930a86157SViacheslav Ovsiienko * Name is not recognized, assume the master, 169030a86157SViacheslav Ovsiienko * check the device directory presence. 169130a86157SViacheslav Ovsiienko */ 169230a86157SViacheslav Ovsiienko switch_info->master = device_dir; 169330a86157SViacheslav Ovsiienko break; 169430a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: 169530a86157SViacheslav Ovsiienko /* 169630a86157SViacheslav Ovsiienko * Name is not set, this assumes the legacy naming 169730a86157SViacheslav Ovsiienko * schema for master, just check if there is 169830a86157SViacheslav Ovsiienko * a device directory. 169930a86157SViacheslav Ovsiienko */ 170030a86157SViacheslav Ovsiienko switch_info->master = device_dir; 170130a86157SViacheslav Ovsiienko break; 170230a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 170330a86157SViacheslav Ovsiienko /* New uplink naming schema recognized. */ 170430a86157SViacheslav Ovsiienko switch_info->master = 1; 170530a86157SViacheslav Ovsiienko break; 170630a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: 170730a86157SViacheslav Ovsiienko /* Legacy representors naming schema. */ 170830a86157SViacheslav Ovsiienko switch_info->representor = !device_dir; 170930a86157SViacheslav Ovsiienko break; 171030a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 171130a86157SViacheslav Ovsiienko /* New representors naming schema. */ 171230a86157SViacheslav Ovsiienko switch_info->representor = 1; 171330a86157SViacheslav Ovsiienko break; 171430a86157SViacheslav Ovsiienko } 171530a86157SViacheslav Ovsiienko } 171630a86157SViacheslav Ovsiienko 171730a86157SViacheslav Ovsiienko /** 17188a6a09f8SDekel Peled * DPDK callback to retrieve plug-in module EEPROM information (type and size). 17198a6a09f8SDekel Peled * 17208a6a09f8SDekel Peled * @param dev 17218a6a09f8SDekel Peled * Pointer to Ethernet device structure. 17228a6a09f8SDekel Peled * @param[out] modinfo 17238a6a09f8SDekel Peled * Storage for plug-in module EEPROM information. 17248a6a09f8SDekel Peled * 17258a6a09f8SDekel Peled * @return 17268a6a09f8SDekel Peled * 0 on success, a negative errno value otherwise and rte_errno is set. 17278a6a09f8SDekel Peled */ 17288a6a09f8SDekel Peled int 17298a6a09f8SDekel Peled mlx5_get_module_info(struct rte_eth_dev *dev, 17308a6a09f8SDekel Peled struct rte_eth_dev_module_info *modinfo) 17318a6a09f8SDekel Peled { 17328a6a09f8SDekel Peled struct ethtool_modinfo info = { 17338a6a09f8SDekel Peled .cmd = ETHTOOL_GMODULEINFO, 17348a6a09f8SDekel Peled }; 17358a6a09f8SDekel Peled struct ifreq ifr = (struct ifreq) { 17368a6a09f8SDekel Peled .ifr_data = (void *)&info, 17378a6a09f8SDekel Peled }; 17388a6a09f8SDekel Peled int ret = 0; 17398a6a09f8SDekel Peled 17408a6a09f8SDekel Peled if (!dev || !modinfo) { 17418a6a09f8SDekel Peled DRV_LOG(WARNING, "missing argument, cannot get module info"); 17428a6a09f8SDekel Peled rte_errno = EINVAL; 17438a6a09f8SDekel Peled return -rte_errno; 17448a6a09f8SDekel Peled } 17458a6a09f8SDekel Peled ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 17468a6a09f8SDekel Peled if (ret) { 17478a6a09f8SDekel Peled DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s", 17488a6a09f8SDekel Peled dev->data->port_id, strerror(rte_errno)); 17498a6a09f8SDekel Peled return ret; 17508a6a09f8SDekel Peled } 17518a6a09f8SDekel Peled modinfo->type = info.type; 17528a6a09f8SDekel Peled modinfo->eeprom_len = info.eeprom_len; 17538a6a09f8SDekel Peled return ret; 17548a6a09f8SDekel Peled } 17558a6a09f8SDekel Peled 17568a6a09f8SDekel Peled /** 17578a6a09f8SDekel Peled * DPDK callback to retrieve plug-in module EEPROM data. 17588a6a09f8SDekel Peled * 17598a6a09f8SDekel Peled * @param dev 17608a6a09f8SDekel Peled * Pointer to Ethernet device structure. 17618a6a09f8SDekel Peled * @param[out] info 17628a6a09f8SDekel Peled * Storage for plug-in module EEPROM data. 17638a6a09f8SDekel Peled * 17648a6a09f8SDekel Peled * @return 17658a6a09f8SDekel Peled * 0 on success, a negative errno value otherwise and rte_errno is set. 17668a6a09f8SDekel Peled */ 17678a6a09f8SDekel Peled int mlx5_get_module_eeprom(struct rte_eth_dev *dev, 17688a6a09f8SDekel Peled struct rte_dev_eeprom_info *info) 17698a6a09f8SDekel Peled { 17708a6a09f8SDekel Peled struct ethtool_eeprom *eeprom; 17718a6a09f8SDekel Peled struct ifreq ifr; 17728a6a09f8SDekel Peled int ret = 0; 17738a6a09f8SDekel Peled 17748a6a09f8SDekel Peled if (!dev || !info) { 17758a6a09f8SDekel Peled DRV_LOG(WARNING, "missing argument, cannot get module eeprom"); 17768a6a09f8SDekel Peled rte_errno = EINVAL; 17778a6a09f8SDekel Peled return -rte_errno; 17788a6a09f8SDekel Peled } 17798a6a09f8SDekel Peled eeprom = rte_calloc(__func__, 1, 17808a6a09f8SDekel Peled (sizeof(struct ethtool_eeprom) + info->length), 0); 17818a6a09f8SDekel Peled if (!eeprom) { 17828a6a09f8SDekel Peled DRV_LOG(WARNING, "port %u cannot allocate memory for " 17838a6a09f8SDekel Peled "eeprom data", dev->data->port_id); 17848a6a09f8SDekel Peled rte_errno = ENOMEM; 17858a6a09f8SDekel Peled return -rte_errno; 17868a6a09f8SDekel Peled } 17878a6a09f8SDekel Peled eeprom->cmd = ETHTOOL_GMODULEEEPROM; 17888a6a09f8SDekel Peled eeprom->offset = info->offset; 17898a6a09f8SDekel Peled eeprom->len = info->length; 17908a6a09f8SDekel Peled ifr = (struct ifreq) { 17918a6a09f8SDekel Peled .ifr_data = (void *)eeprom, 17928a6a09f8SDekel Peled }; 17938a6a09f8SDekel Peled ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 17948a6a09f8SDekel Peled if (ret) 17958a6a09f8SDekel Peled DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s", 17968a6a09f8SDekel Peled dev->data->port_id, strerror(rte_errno)); 17978a6a09f8SDekel Peled else 17988a6a09f8SDekel Peled rte_memcpy(info->data, eeprom->data, info->length); 17998a6a09f8SDekel Peled rte_free(eeprom); 18008a6a09f8SDekel Peled return ret; 18018a6a09f8SDekel Peled } 1802b6b3bf86SOri Kam 1803b6b3bf86SOri Kam /** 1804b6b3bf86SOri Kam * DPDK callback to retrieve hairpin capabilities. 1805b6b3bf86SOri Kam * 1806b6b3bf86SOri Kam * @param dev 1807b6b3bf86SOri Kam * Pointer to Ethernet device structure. 1808b6b3bf86SOri Kam * @param[out] cap 1809b6b3bf86SOri Kam * Storage for hairpin capability data. 1810b6b3bf86SOri Kam * 1811b6b3bf86SOri Kam * @return 1812b6b3bf86SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 1813b6b3bf86SOri Kam */ 1814b6b3bf86SOri Kam int mlx5_hairpin_cap_get(struct rte_eth_dev *dev, 1815b6b3bf86SOri Kam struct rte_eth_hairpin_cap *cap) 1816b6b3bf86SOri Kam { 1817b6b3bf86SOri Kam struct mlx5_priv *priv = dev->data->dev_private; 1818b6b3bf86SOri Kam 1819b6b3bf86SOri Kam if (priv->sh->devx == 0) { 1820b6b3bf86SOri Kam rte_errno = ENOTSUP; 1821b6b3bf86SOri Kam return -rte_errno; 1822b6b3bf86SOri Kam } 1823b6b3bf86SOri Kam cap->max_nb_queues = UINT16_MAX; 1824b6b3bf86SOri Kam cap->max_rx_2_tx = 1; 1825b6b3bf86SOri Kam cap->max_tx_2_rx = 1; 1826b6b3bf86SOri Kam cap->max_nb_desc = 8192; 1827b6b3bf86SOri Kam return 0; 1828b6b3bf86SOri Kam } 1829