18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6771fa900SAdrien Mazarguil #include <stddef.h> 7e60fbd5bSAdrien Mazarguil #include <assert.h> 8fc40db99SAdrien Mazarguil #include <inttypes.h> 9771fa900SAdrien Mazarguil #include <unistd.h> 10771fa900SAdrien Mazarguil #include <stdint.h> 11771fa900SAdrien Mazarguil #include <stdio.h> 12771fa900SAdrien Mazarguil #include <string.h> 13771fa900SAdrien Mazarguil #include <stdlib.h> 14771fa900SAdrien Mazarguil #include <errno.h> 15771fa900SAdrien Mazarguil #include <dirent.h> 16771fa900SAdrien Mazarguil #include <net/if.h> 17771fa900SAdrien Mazarguil #include <sys/ioctl.h> 18771fa900SAdrien Mazarguil #include <sys/socket.h> 19771fa900SAdrien Mazarguil #include <netinet/in.h> 20cb8faed7SAdrien Mazarguil #include <linux/ethtool.h> 21cb8faed7SAdrien Mazarguil #include <linux/sockios.h> 22198a3c33SNelio Laranjeiro #include <fcntl.h> 2390260d57SNélio Laranjeiro #include <stdalign.h> 24f8b9a3baSXueming Li #include <sys/un.h> 25cfee9475SNélio Laranjeiro #include <time.h> 26771fa900SAdrien Mazarguil 27771fa900SAdrien Mazarguil #include <rte_atomic.h> 28ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 29c752998bSGaetan Rivet #include <rte_bus_pci.h> 30771fa900SAdrien Mazarguil #include <rte_mbuf.h> 31771fa900SAdrien Mazarguil #include <rte_common.h> 32198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 33a48deadaSOr Ami #include <rte_malloc.h> 34c022cb40SBruce Richardson #include <rte_string_fns.h> 35974f1e7eSYongseok Koh #include <rte_rwlock.h> 36771fa900SAdrien Mazarguil 37771fa900SAdrien Mazarguil #include "mlx5.h" 380e83b8e5SNelio Laranjeiro #include "mlx5_glue.h" 39e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 40771fa900SAdrien Mazarguil #include "mlx5_utils.h" 41771fa900SAdrien Mazarguil 4279d09892SMoti Haimovsky /* Supported speed values found in /usr/include/linux/ethtool.h */ 4379d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseKR4_Full 4479d09892SMoti Haimovsky #define SUPPORTED_40000baseKR4_Full (1 << 23) 4579d09892SMoti Haimovsky #endif 4679d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseCR4_Full 4779d09892SMoti Haimovsky #define SUPPORTED_40000baseCR4_Full (1 << 24) 4879d09892SMoti Haimovsky #endif 4979d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseSR4_Full 5079d09892SMoti Haimovsky #define SUPPORTED_40000baseSR4_Full (1 << 25) 5179d09892SMoti Haimovsky #endif 5279d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_40000baseLR4_Full 5379d09892SMoti Haimovsky #define SUPPORTED_40000baseLR4_Full (1 << 26) 5479d09892SMoti Haimovsky #endif 5579d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseKR4_Full 5679d09892SMoti Haimovsky #define SUPPORTED_56000baseKR4_Full (1 << 27) 5779d09892SMoti Haimovsky #endif 5879d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseCR4_Full 5979d09892SMoti Haimovsky #define SUPPORTED_56000baseCR4_Full (1 << 28) 6079d09892SMoti Haimovsky #endif 6179d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseSR4_Full 6279d09892SMoti Haimovsky #define SUPPORTED_56000baseSR4_Full (1 << 29) 6379d09892SMoti Haimovsky #endif 6479d09892SMoti Haimovsky #ifndef HAVE_SUPPORTED_56000baseLR4_Full 6579d09892SMoti Haimovsky #define SUPPORTED_56000baseLR4_Full (1 << 30) 6679d09892SMoti Haimovsky #endif 6779d09892SMoti Haimovsky 683a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */ 693a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS 703a49ffe3SShahaf Shuler struct ethtool_link_settings { 713a49ffe3SShahaf Shuler uint32_t cmd; 723a49ffe3SShahaf Shuler uint32_t speed; 733a49ffe3SShahaf Shuler uint8_t duplex; 743a49ffe3SShahaf Shuler uint8_t port; 753a49ffe3SShahaf Shuler uint8_t phy_address; 763a49ffe3SShahaf Shuler uint8_t autoneg; 773a49ffe3SShahaf Shuler uint8_t mdio_support; 783a49ffe3SShahaf Shuler uint8_t eth_to_mdix; 793a49ffe3SShahaf Shuler uint8_t eth_tp_mdix_ctrl; 803a49ffe3SShahaf Shuler int8_t link_mode_masks_nwords; 813a49ffe3SShahaf Shuler uint32_t reserved[8]; 823a49ffe3SShahaf Shuler uint32_t link_mode_masks[]; 833a49ffe3SShahaf Shuler }; 843a49ffe3SShahaf Shuler 853a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c 863a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5 873a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6 883a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17 893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18 903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19 913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20 923a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21 933a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22 943a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23 953a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24 963a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25 973a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26 983a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27 993a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28 1003a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29 1013a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30 1023a49ffe3SShahaf Shuler #endif 1033a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G 1043a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31 1053a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32 1063a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33 1073a49ffe3SShahaf Shuler #endif 1083a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G 1093a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34 1103a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35 1113a49ffe3SShahaf Shuler #endif 1123a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G 1133a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36 1143a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37 1153a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38 1163a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39 1173a49ffe3SShahaf Shuler #endif 1183a49ffe3SShahaf Shuler 119771fa900SAdrien Mazarguil /** 1202b730263SAdrien Mazarguil * Get master interface name from private structure. 121771fa900SAdrien Mazarguil * 122af4f09f2SNélio Laranjeiro * @param[in] dev 123af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 124771fa900SAdrien Mazarguil * @param[out] ifname 125771fa900SAdrien Mazarguil * Interface name output buffer. 126771fa900SAdrien Mazarguil * 127771fa900SAdrien Mazarguil * @return 128a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 129771fa900SAdrien Mazarguil */ 1309c2bbd04SViacheslav Ovsiienko int 1319c2bbd04SViacheslav Ovsiienko mlx5_get_master_ifname(const char *ibdev_path, char (*ifname)[IF_NAMESIZE]) 132771fa900SAdrien Mazarguil { 133771fa900SAdrien Mazarguil DIR *dir; 134771fa900SAdrien Mazarguil struct dirent *dent; 135771fa900SAdrien Mazarguil unsigned int dev_type = 0; 136771fa900SAdrien Mazarguil unsigned int dev_port_prev = ~0u; 137771fa900SAdrien Mazarguil char match[IF_NAMESIZE] = ""; 138771fa900SAdrien Mazarguil 1399c2bbd04SViacheslav Ovsiienko assert(ibdev_path); 140771fa900SAdrien Mazarguil { 1419c2bbd04SViacheslav Ovsiienko MKSTR(path, "%s/device/net", ibdev_path); 142771fa900SAdrien Mazarguil 143771fa900SAdrien Mazarguil dir = opendir(path); 144a6d83b6aSNélio Laranjeiro if (dir == NULL) { 145a6d83b6aSNélio Laranjeiro rte_errno = errno; 146a6d83b6aSNélio Laranjeiro return -rte_errno; 147a6d83b6aSNélio Laranjeiro } 148771fa900SAdrien Mazarguil } 149771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 150771fa900SAdrien Mazarguil char *name = dent->d_name; 151771fa900SAdrien Mazarguil FILE *file; 152771fa900SAdrien Mazarguil unsigned int dev_port; 153771fa900SAdrien Mazarguil int r; 154771fa900SAdrien Mazarguil 155771fa900SAdrien Mazarguil if ((name[0] == '.') && 156771fa900SAdrien Mazarguil ((name[1] == '\0') || 157771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 158771fa900SAdrien Mazarguil continue; 159771fa900SAdrien Mazarguil 160771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 1619c2bbd04SViacheslav Ovsiienko ibdev_path, name, 162771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 163771fa900SAdrien Mazarguil 164771fa900SAdrien Mazarguil file = fopen(path, "rb"); 165771fa900SAdrien Mazarguil if (file == NULL) { 166771fa900SAdrien Mazarguil if (errno != ENOENT) 167771fa900SAdrien Mazarguil continue; 168771fa900SAdrien Mazarguil /* 169771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 170771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 171771fa900SAdrien Mazarguil */ 172771fa900SAdrien Mazarguil try_dev_id: 173771fa900SAdrien Mazarguil match[0] = '\0'; 174771fa900SAdrien Mazarguil if (dev_type) 175771fa900SAdrien Mazarguil break; 176771fa900SAdrien Mazarguil dev_type = 1; 177771fa900SAdrien Mazarguil dev_port_prev = ~0u; 178771fa900SAdrien Mazarguil rewinddir(dir); 179771fa900SAdrien Mazarguil continue; 180771fa900SAdrien Mazarguil } 181771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 182771fa900SAdrien Mazarguil fclose(file); 183771fa900SAdrien Mazarguil if (r != 1) 184771fa900SAdrien Mazarguil continue; 185771fa900SAdrien Mazarguil /* 186771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 187771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 188771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 189771fa900SAdrien Mazarguil */ 190771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 191771fa900SAdrien Mazarguil goto try_dev_id; 192771fa900SAdrien Mazarguil dev_port_prev = dev_port; 1939083982cSAdrien Mazarguil if (dev_port == 0) 194c022cb40SBruce Richardson strlcpy(match, name, sizeof(match)); 195771fa900SAdrien Mazarguil } 196771fa900SAdrien Mazarguil closedir(dir); 197a6d83b6aSNélio Laranjeiro if (match[0] == '\0') { 198a6d83b6aSNélio Laranjeiro rte_errno = ENOENT; 199a6d83b6aSNélio Laranjeiro return -rte_errno; 200a6d83b6aSNélio Laranjeiro } 201771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 202771fa900SAdrien Mazarguil return 0; 203771fa900SAdrien Mazarguil } 204771fa900SAdrien Mazarguil 205771fa900SAdrien Mazarguil /** 2062b730263SAdrien Mazarguil * Get interface name from private structure. 2072b730263SAdrien Mazarguil * 2082b730263SAdrien Mazarguil * This is a port representor-aware version of mlx5_get_master_ifname(). 2092b730263SAdrien Mazarguil * 2102b730263SAdrien Mazarguil * @param[in] dev 2112b730263SAdrien Mazarguil * Pointer to Ethernet device. 2122b730263SAdrien Mazarguil * @param[out] ifname 2132b730263SAdrien Mazarguil * Interface name output buffer. 2142b730263SAdrien Mazarguil * 2152b730263SAdrien Mazarguil * @return 2162b730263SAdrien Mazarguil * 0 on success, a negative errno value otherwise and rte_errno is set. 2172b730263SAdrien Mazarguil */ 2182b730263SAdrien Mazarguil int 2192b730263SAdrien Mazarguil mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) 2202b730263SAdrien Mazarguil { 221dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 2229c2bbd04SViacheslav Ovsiienko unsigned int ifindex; 2239c2bbd04SViacheslav Ovsiienko 2249c2bbd04SViacheslav Ovsiienko assert(priv); 2259c2bbd04SViacheslav Ovsiienko assert(priv->sh); 2269c2bbd04SViacheslav Ovsiienko ifindex = priv->nl_socket_rdma >= 0 ? 2279c0a9eedSViacheslav Ovsiienko mlx5_nl_ifindex(priv->nl_socket_rdma, 2289c0a9eedSViacheslav Ovsiienko priv->sh->ibdev_name, 2299c0a9eedSViacheslav Ovsiienko priv->ibv_port) : 0; 2302b730263SAdrien Mazarguil if (!ifindex) { 2312b730263SAdrien Mazarguil if (!priv->representor) 2329c2bbd04SViacheslav Ovsiienko return mlx5_get_master_ifname(priv->sh->ibdev_path, 2339c2bbd04SViacheslav Ovsiienko ifname); 2342b730263SAdrien Mazarguil rte_errno = ENXIO; 2352b730263SAdrien Mazarguil return -rte_errno; 2362b730263SAdrien Mazarguil } 2372b730263SAdrien Mazarguil if (if_indextoname(ifindex, &(*ifname)[0])) 2382b730263SAdrien Mazarguil return 0; 2392b730263SAdrien Mazarguil rte_errno = errno; 2402b730263SAdrien Mazarguil return -rte_errno; 2412b730263SAdrien Mazarguil } 2422b730263SAdrien Mazarguil 2432b730263SAdrien Mazarguil /** 244ccdcba53SNélio Laranjeiro * Get the interface index from device name. 245ccdcba53SNélio Laranjeiro * 246ccdcba53SNélio Laranjeiro * @param[in] dev 247ccdcba53SNélio Laranjeiro * Pointer to Ethernet device. 248ccdcba53SNélio Laranjeiro * 249ccdcba53SNélio Laranjeiro * @return 2503f8cb05dSAdrien Mazarguil * Nonzero interface index on success, zero otherwise and rte_errno is set. 251ccdcba53SNélio Laranjeiro */ 2523f8cb05dSAdrien Mazarguil unsigned int 253ccdcba53SNélio Laranjeiro mlx5_ifindex(const struct rte_eth_dev *dev) 254ccdcba53SNélio Laranjeiro { 255ccdcba53SNélio Laranjeiro char ifname[IF_NAMESIZE]; 2563f8cb05dSAdrien Mazarguil unsigned int ifindex; 257ccdcba53SNélio Laranjeiro 2583f8cb05dSAdrien Mazarguil if (mlx5_get_ifname(dev, &ifname)) 2593f8cb05dSAdrien Mazarguil return 0; 2603f8cb05dSAdrien Mazarguil ifindex = if_nametoindex(ifname); 2613f8cb05dSAdrien Mazarguil if (!ifindex) 262ccdcba53SNélio Laranjeiro rte_errno = errno; 2633f8cb05dSAdrien Mazarguil return ifindex; 264ccdcba53SNélio Laranjeiro } 265ccdcba53SNélio Laranjeiro 266ccdcba53SNélio Laranjeiro /** 267771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 268771fa900SAdrien Mazarguil * 269af4f09f2SNélio Laranjeiro * @param[in] dev 270af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 271771fa900SAdrien Mazarguil * @param req 272771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 273771fa900SAdrien Mazarguil * @param[out] ifr 274771fa900SAdrien Mazarguil * Interface request structure output buffer. 275771fa900SAdrien Mazarguil * 276771fa900SAdrien Mazarguil * @return 277a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 278771fa900SAdrien Mazarguil */ 279771fa900SAdrien Mazarguil int 2807dd7be29SShahaf Shuler mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr) 281771fa900SAdrien Mazarguil { 282771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 283a6d83b6aSNélio Laranjeiro int ret = 0; 284771fa900SAdrien Mazarguil 285a6d83b6aSNélio Laranjeiro if (sock == -1) { 286a6d83b6aSNélio Laranjeiro rte_errno = errno; 287a6d83b6aSNélio Laranjeiro return -rte_errno; 288a6d83b6aSNélio Laranjeiro } 289a6d83b6aSNélio Laranjeiro ret = mlx5_get_ifname(dev, &ifr->ifr_name); 290a6d83b6aSNélio Laranjeiro if (ret) 291a6d83b6aSNélio Laranjeiro goto error; 292771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 293a6d83b6aSNélio Laranjeiro if (ret == -1) { 294a6d83b6aSNélio Laranjeiro rte_errno = errno; 295a6d83b6aSNélio Laranjeiro goto error; 296a6d83b6aSNélio Laranjeiro } 297771fa900SAdrien Mazarguil close(sock); 298a6d83b6aSNélio Laranjeiro return 0; 299a6d83b6aSNélio Laranjeiro error: 300a6d83b6aSNélio Laranjeiro close(sock); 301a6d83b6aSNélio Laranjeiro return -rte_errno; 302771fa900SAdrien Mazarguil } 303771fa900SAdrien Mazarguil 304771fa900SAdrien Mazarguil /** 305771fa900SAdrien Mazarguil * Get device MTU. 306771fa900SAdrien Mazarguil * 307af4f09f2SNélio Laranjeiro * @param dev 308af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 309771fa900SAdrien Mazarguil * @param[out] mtu 310771fa900SAdrien Mazarguil * MTU value output buffer. 311771fa900SAdrien Mazarguil * 312771fa900SAdrien Mazarguil * @return 313a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 314771fa900SAdrien Mazarguil */ 315771fa900SAdrien Mazarguil int 316af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 317771fa900SAdrien Mazarguil { 318fc40db99SAdrien Mazarguil struct ifreq request; 3197dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request); 320771fa900SAdrien Mazarguil 321fc40db99SAdrien Mazarguil if (ret) 322fc40db99SAdrien Mazarguil return ret; 323fc40db99SAdrien Mazarguil *mtu = request.ifr_mtu; 324859081d3SShahaf Shuler return 0; 325859081d3SShahaf Shuler } 326859081d3SShahaf Shuler 327859081d3SShahaf Shuler /** 328cf37ca95SAdrien Mazarguil * Set device MTU. 329cf37ca95SAdrien Mazarguil * 330af4f09f2SNélio Laranjeiro * @param dev 331af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 332cf37ca95SAdrien Mazarguil * @param mtu 333cf37ca95SAdrien Mazarguil * MTU value to set. 334cf37ca95SAdrien Mazarguil * 335cf37ca95SAdrien Mazarguil * @return 336a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 337cf37ca95SAdrien Mazarguil */ 338cf37ca95SAdrien Mazarguil static int 339af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 340cf37ca95SAdrien Mazarguil { 341fc40db99SAdrien Mazarguil struct ifreq request = { .ifr_mtu = mtu, }; 342f3b492d7SAdrien Mazarguil 3437dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFMTU, &request); 344cf37ca95SAdrien Mazarguil } 345cf37ca95SAdrien Mazarguil 346cf37ca95SAdrien Mazarguil /** 347771fa900SAdrien Mazarguil * Set device flags. 348771fa900SAdrien Mazarguil * 349af4f09f2SNélio Laranjeiro * @param dev 350af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 351771fa900SAdrien Mazarguil * @param keep 352771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 353771fa900SAdrien Mazarguil * @param flags 354771fa900SAdrien Mazarguil * Bitmask for flags to modify. 355771fa900SAdrien Mazarguil * 356771fa900SAdrien Mazarguil * @return 357a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 358771fa900SAdrien Mazarguil */ 359771fa900SAdrien Mazarguil int 360af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags) 361771fa900SAdrien Mazarguil { 362fc40db99SAdrien Mazarguil struct ifreq request; 3637dd7be29SShahaf Shuler int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request); 364771fa900SAdrien Mazarguil 365fc40db99SAdrien Mazarguil if (ret) 366fc40db99SAdrien Mazarguil return ret; 367fc40db99SAdrien Mazarguil request.ifr_flags &= keep; 368fc40db99SAdrien Mazarguil request.ifr_flags |= flags & ~keep; 3697dd7be29SShahaf Shuler return mlx5_ifreq(dev, SIOCSIFFLAGS, &request); 370771fa900SAdrien Mazarguil } 371771fa900SAdrien Mazarguil 372771fa900SAdrien Mazarguil /** 3737b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 374e60fbd5bSAdrien Mazarguil * 375e60fbd5bSAdrien Mazarguil * @param dev 376e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 377e60fbd5bSAdrien Mazarguil * 378e60fbd5bSAdrien Mazarguil * @return 379a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 380e60fbd5bSAdrien Mazarguil */ 3817b2423cdSNélio Laranjeiro int 3827b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 383e60fbd5bSAdrien Mazarguil { 384dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 385e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 386e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 387634efbc2SNelio Laranjeiro unsigned int i; 388634efbc2SNelio Laranjeiro unsigned int j; 389634efbc2SNelio Laranjeiro unsigned int reta_idx_n; 39029c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 39121e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 392a6d83b6aSNélio Laranjeiro int ret = 0; 393e60fbd5bSAdrien Mazarguil 39429c1d8bbSNélio Laranjeiro if (use_app_rss_key && 39529c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 396c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN)) { 397c388a2f6SNelio Laranjeiro DRV_LOG(ERR, "port %u RSS key len must be %s Bytes long", 398c388a2f6SNelio Laranjeiro dev->data->port_id, RTE_STR(MLX5_RSS_HASH_KEY_LEN)); 399a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 400a6d83b6aSNélio Laranjeiro return -rte_errno; 40129c1d8bbSNélio Laranjeiro } 40229c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 40329c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 404c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN, 0); 40529c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 406a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)", 4070f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 408a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 409a6d83b6aSNélio Laranjeiro return -rte_errno; 41029c1d8bbSNélio Laranjeiro } 41129c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 41229c1d8bbSNélio Laranjeiro use_app_rss_key ? 41329c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 41429c1d8bbSNélio Laranjeiro rss_hash_default_key, 415c388a2f6SNelio Laranjeiro MLX5_RSS_HASH_KEY_LEN); 416c388a2f6SNelio Laranjeiro priv->rss_conf.rss_key_len = MLX5_RSS_HASH_KEY_LEN; 41729c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 418e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 419e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 420e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 421a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Tx queues number update: %u -> %u", 4220f99970bSNélio Laranjeiro dev->data->port_id, priv->txqs_n, txqs_n); 423e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 424e60fbd5bSAdrien Mazarguil } 4257fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 426a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", 4270f99970bSNélio Laranjeiro dev->data->port_id, rxqs_n); 428a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 429a6d83b6aSNélio Laranjeiro return -rte_errno; 430634efbc2SNelio Laranjeiro } 43109ba4c58SDekel Peled if (rxqs_n != priv->rxqs_n) { 432a170a30dSNélio Laranjeiro DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", 4330f99970bSNélio Laranjeiro dev->data->port_id, priv->rxqs_n, rxqs_n); 434e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 43509ba4c58SDekel Peled /* 43609ba4c58SDekel Peled * If the requested number of RX queues is not a power of two, 43709ba4c58SDekel Peled * use the maximum indirection table size for better balancing. 43809ba4c58SDekel Peled * The result is always rounded to the next power of two. 43909ba4c58SDekel Peled */ 440634efbc2SNelio Laranjeiro reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ? 4417fe24446SShahaf Shuler priv->config.ind_table_max_size : 442634efbc2SNelio Laranjeiro rxqs_n)); 443a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 444a6d83b6aSNélio Laranjeiro if (ret) 445a6d83b6aSNélio Laranjeiro return ret; 44609ba4c58SDekel Peled /* 44709ba4c58SDekel Peled * When the number of RX queues is not a power of two, 44809ba4c58SDekel Peled * the remaining table entries are padded with reused WQs 44909ba4c58SDekel Peled * and hashes are not spread uniformly. 45009ba4c58SDekel Peled */ 451634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 452634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = j; 453634efbc2SNelio Laranjeiro if (++j == rxqs_n) 454634efbc2SNelio Laranjeiro j = 0; 455634efbc2SNelio Laranjeiro } 45609ba4c58SDekel Peled } 457120dc4a7SYongseok Koh ret = mlx5_proc_priv_init(dev); 458120dc4a7SYongseok Koh if (ret) 459120dc4a7SYongseok Koh return ret; 460e60fbd5bSAdrien Mazarguil return 0; 461e60fbd5bSAdrien Mazarguil } 462e60fbd5bSAdrien Mazarguil 463e60fbd5bSAdrien Mazarguil /** 464d11d651fSShahaf Shuler * Sets default tuning parameters. 465d11d651fSShahaf Shuler * 466d11d651fSShahaf Shuler * @param dev 467d11d651fSShahaf Shuler * Pointer to Ethernet device. 468d11d651fSShahaf Shuler * @param[out] info 469d11d651fSShahaf Shuler * Info structure output buffer. 470d11d651fSShahaf Shuler */ 471d11d651fSShahaf Shuler static void 472d11d651fSShahaf Shuler mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 473d11d651fSShahaf Shuler { 474dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 475d11d651fSShahaf Shuler 476d11d651fSShahaf Shuler /* Minimum CPU utilization. */ 477d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 256; 478d11d651fSShahaf Shuler info->default_txportconf.ring_size = 256; 479d11d651fSShahaf Shuler info->default_rxportconf.burst_size = 64; 480d11d651fSShahaf Shuler info->default_txportconf.burst_size = 64; 481d11d651fSShahaf Shuler if (priv->link_speed_capa & ETH_LINK_SPEED_100G) { 482d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 16; 483d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 16; 484d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 485d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 486d11d651fSShahaf Shuler /* Max Throughput. */ 487d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 2048; 488d11d651fSShahaf Shuler info->default_txportconf.ring_size = 2048; 489d11d651fSShahaf Shuler } 490d11d651fSShahaf Shuler } else { 491d11d651fSShahaf Shuler info->default_rxportconf.nb_queues = 8; 492d11d651fSShahaf Shuler info->default_txportconf.nb_queues = 8; 493d11d651fSShahaf Shuler if (dev->data->nb_rx_queues > 2 || 494d11d651fSShahaf Shuler dev->data->nb_tx_queues > 2) { 495d11d651fSShahaf Shuler /* Max Throughput. */ 496d11d651fSShahaf Shuler info->default_rxportconf.ring_size = 4096; 497d11d651fSShahaf Shuler info->default_txportconf.ring_size = 4096; 498d11d651fSShahaf Shuler } 499d11d651fSShahaf Shuler } 500d11d651fSShahaf Shuler } 501d11d651fSShahaf Shuler 502d11d651fSShahaf Shuler /** 503e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 504e60fbd5bSAdrien Mazarguil * 505e60fbd5bSAdrien Mazarguil * @param dev 506e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 507e60fbd5bSAdrien Mazarguil * @param[out] info 508e60fbd5bSAdrien Mazarguil * Info structure output buffer. 509e60fbd5bSAdrien Mazarguil */ 510e60fbd5bSAdrien Mazarguil void 511e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 512e60fbd5bSAdrien Mazarguil { 513dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 5147fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 515e60fbd5bSAdrien Mazarguil unsigned int max; 516e60fbd5bSAdrien Mazarguil char ifname[IF_NAMESIZE]; 517e60fbd5bSAdrien Mazarguil 518e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 519e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 520e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 521e60fbd5bSAdrien Mazarguil /* 522e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 523e60fbd5bSAdrien Mazarguil * between the two values. 524e60fbd5bSAdrien Mazarguil */ 525d485cdcaSViacheslav Ovsiienko max = RTE_MIN(priv->sh->device_attr.orig_attr.max_cq, 526d485cdcaSViacheslav Ovsiienko priv->sh->device_attr.orig_attr.max_qp); 527e60fbd5bSAdrien Mazarguil /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 528e60fbd5bSAdrien Mazarguil if (max >= 65535) 529e60fbd5bSAdrien Mazarguil max = 65535; 530e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 531e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 53218c01b98SNélio Laranjeiro info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; 533af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 534af4f09f2SNélio Laranjeiro info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 53517b843ebSShahaf Shuler info->rx_queue_offload_capa); 536af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 537af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(dev, &ifname) == 0) 538e60fbd5bSAdrien Mazarguil info->if_index = if_nametoindex(ifname); 539d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 5407fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 541c388a2f6SNelio Laranjeiro info->hash_key_size = MLX5_RSS_HASH_KEY_LEN; 54275ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 543b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 544d11d651fSShahaf Shuler mlx5_set_default_params(dev, info); 5452b730263SAdrien Mazarguil info->switch_info.name = dev->data->name; 5462b730263SAdrien Mazarguil info->switch_info.domain_id = priv->domain_id; 5472b730263SAdrien Mazarguil info->switch_info.port_id = priv->representor_id; 5482b730263SAdrien Mazarguil if (priv->representor) { 5492b730263SAdrien Mazarguil unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0); 5502b730263SAdrien Mazarguil uint16_t port_id[i]; 5512b730263SAdrien Mazarguil 5522b730263SAdrien Mazarguil i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i); 5532b730263SAdrien Mazarguil while (i--) { 554dbeba4cfSThomas Monjalon struct mlx5_priv *opriv = 5552b730263SAdrien Mazarguil rte_eth_devices[port_id[i]].data->dev_private; 5562b730263SAdrien Mazarguil 5572b730263SAdrien Mazarguil if (!opriv || 5582b730263SAdrien Mazarguil opriv->representor || 5592b730263SAdrien Mazarguil opriv->domain_id != priv->domain_id) 5602b730263SAdrien Mazarguil continue; 5612b730263SAdrien Mazarguil /* 5622b730263SAdrien Mazarguil * Override switch name with that of the master 5632b730263SAdrien Mazarguil * device. 5642b730263SAdrien Mazarguil */ 5652b730263SAdrien Mazarguil info->switch_info.name = opriv->dev_data->name; 5662b730263SAdrien Mazarguil break; 5672b730263SAdrien Mazarguil } 5682b730263SAdrien Mazarguil } 569e60fbd5bSAdrien Mazarguil } 570e60fbd5bSAdrien Mazarguil 571fb732b0aSNélio Laranjeiro /** 572*e571ad55STom Barbette * Get device current raw clock counter 573*e571ad55STom Barbette * 574*e571ad55STom Barbette * @param dev 575*e571ad55STom Barbette * Pointer to Ethernet device structure. 576*e571ad55STom Barbette * @param[out] time 577*e571ad55STom Barbette * Current raw clock counter of the device. 578*e571ad55STom Barbette * 579*e571ad55STom Barbette * @return 580*e571ad55STom Barbette * 0 if the clock has correctly been read 581*e571ad55STom Barbette * The value of errno in case of error 582*e571ad55STom Barbette */ 583*e571ad55STom Barbette int 584*e571ad55STom Barbette mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock) 585*e571ad55STom Barbette { 586*e571ad55STom Barbette struct mlx5_priv *priv = dev->data->dev_private; 587*e571ad55STom Barbette struct ibv_context *ctx = priv->sh->ctx; 588*e571ad55STom Barbette struct ibv_values_ex values; 589*e571ad55STom Barbette int err = 0; 590*e571ad55STom Barbette 591*e571ad55STom Barbette values.comp_mask = IBV_VALUES_MASK_RAW_CLOCK; 592*e571ad55STom Barbette err = mlx5_glue->query_rt_values_ex(ctx, &values); 593*e571ad55STom Barbette if (err != 0) { 594*e571ad55STom Barbette DRV_LOG(WARNING, "Could not query the clock !"); 595*e571ad55STom Barbette return err; 596*e571ad55STom Barbette } 597*e571ad55STom Barbette *clock = values.raw_clock.tv_nsec; 598*e571ad55STom Barbette return 0; 599*e571ad55STom Barbette } 600*e571ad55STom Barbette 601*e571ad55STom Barbette /** 602714bf46eSThomas Monjalon * Get firmware version of a device. 603714bf46eSThomas Monjalon * 604714bf46eSThomas Monjalon * @param dev 605714bf46eSThomas Monjalon * Ethernet device port. 606714bf46eSThomas Monjalon * @param fw_ver 607714bf46eSThomas Monjalon * String output allocated by caller. 608714bf46eSThomas Monjalon * @param fw_size 609714bf46eSThomas Monjalon * Size of the output string, including terminating null byte. 610714bf46eSThomas Monjalon * 611714bf46eSThomas Monjalon * @return 612714bf46eSThomas Monjalon * 0 on success, or the size of the non truncated string if too big. 613714bf46eSThomas Monjalon */ 614714bf46eSThomas Monjalon int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) 615714bf46eSThomas Monjalon { 616dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 617d485cdcaSViacheslav Ovsiienko struct ibv_device_attr *attr = &priv->sh->device_attr.orig_attr; 618714bf46eSThomas Monjalon size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1; 619714bf46eSThomas Monjalon 620714bf46eSThomas Monjalon if (fw_size < size) 621714bf46eSThomas Monjalon return size; 622714bf46eSThomas Monjalon if (fw_ver != NULL) 623714bf46eSThomas Monjalon strlcpy(fw_ver, attr->fw_ver, fw_size); 624714bf46eSThomas Monjalon return 0; 625714bf46eSThomas Monjalon } 626714bf46eSThomas Monjalon 627714bf46eSThomas Monjalon /** 628fb732b0aSNélio Laranjeiro * Get supported packet types. 629fb732b0aSNélio Laranjeiro * 630fb732b0aSNélio Laranjeiro * @param dev 631fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 632fb732b0aSNélio Laranjeiro * 633fb732b0aSNélio Laranjeiro * @return 634fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 635fb732b0aSNélio Laranjeiro */ 63678a38edfSJianfeng Tan const uint32_t * 63778a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 63878a38edfSJianfeng Tan { 63978a38edfSJianfeng Tan static const uint32_t ptypes[] = { 64078a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 641ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 642c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 643c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 644ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 645ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 646ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 647ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 648c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 649c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 650ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 651ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 652ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 653ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 65478a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 65578a38edfSJianfeng Tan }; 65678a38edfSJianfeng Tan 6576cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 6587d6bf6b8SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_mprq || 6596cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 66078a38edfSJianfeng Tan return ptypes; 66178a38edfSJianfeng Tan return NULL; 66278a38edfSJianfeng Tan } 66378a38edfSJianfeng Tan 664e60fbd5bSAdrien Mazarguil /** 6650333b2f5SViacheslav Ovsiienko * Retrieve the master device for representor in the same switch domain. 6660333b2f5SViacheslav Ovsiienko * 6670333b2f5SViacheslav Ovsiienko * @param dev 6680333b2f5SViacheslav Ovsiienko * Pointer to representor Ethernet device structure. 6690333b2f5SViacheslav Ovsiienko * 6700333b2f5SViacheslav Ovsiienko * @return 6710333b2f5SViacheslav Ovsiienko * Master device structure on success, NULL otherwise. 6720333b2f5SViacheslav Ovsiienko */ 6730333b2f5SViacheslav Ovsiienko 6740333b2f5SViacheslav Ovsiienko static struct rte_eth_dev * 6750333b2f5SViacheslav Ovsiienko mlx5_find_master_dev(struct rte_eth_dev *dev) 6760333b2f5SViacheslav Ovsiienko { 6770333b2f5SViacheslav Ovsiienko struct mlx5_priv *priv; 6780333b2f5SViacheslav Ovsiienko uint16_t port_id; 6790333b2f5SViacheslav Ovsiienko uint16_t domain_id; 6800333b2f5SViacheslav Ovsiienko 6810333b2f5SViacheslav Ovsiienko priv = dev->data->dev_private; 6820333b2f5SViacheslav Ovsiienko domain_id = priv->domain_id; 6830333b2f5SViacheslav Ovsiienko assert(priv->representor); 6840333b2f5SViacheslav Ovsiienko RTE_ETH_FOREACH_DEV_OF(port_id, dev->device) { 6850333b2f5SViacheslav Ovsiienko priv = rte_eth_devices[port_id].data->dev_private; 6860333b2f5SViacheslav Ovsiienko if (priv && 6870333b2f5SViacheslav Ovsiienko priv->master && 6880333b2f5SViacheslav Ovsiienko priv->domain_id == domain_id) 6890333b2f5SViacheslav Ovsiienko return &rte_eth_devices[port_id]; 6900333b2f5SViacheslav Ovsiienko } 6910333b2f5SViacheslav Ovsiienko return NULL; 6920333b2f5SViacheslav Ovsiienko } 6930333b2f5SViacheslav Ovsiienko 6940333b2f5SViacheslav Ovsiienko /** 6952c960a51SMatthieu Ternisien d'Ouville * DPDK callback to retrieve physical link information. 696cb8faed7SAdrien Mazarguil * 697cb8faed7SAdrien Mazarguil * @param dev 698cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 699cfee9475SNélio Laranjeiro * @param[out] link 700cfee9475SNélio Laranjeiro * Storage for current link status. 701fb732b0aSNélio Laranjeiro * 702fb732b0aSNélio Laranjeiro * @return 703a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 704cb8faed7SAdrien Mazarguil */ 70518840871SNélio Laranjeiro static int 706cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev, 707cfee9475SNélio Laranjeiro struct rte_eth_link *link) 708cb8faed7SAdrien Mazarguil { 709dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 710cb8faed7SAdrien Mazarguil struct ethtool_cmd edata = { 71175ef62a9SNélio Laranjeiro .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */ 712cb8faed7SAdrien Mazarguil }; 713cb8faed7SAdrien Mazarguil struct ifreq ifr; 714cb8faed7SAdrien Mazarguil struct rte_eth_link dev_link; 715cb8faed7SAdrien Mazarguil int link_speed = 0; 716a6d83b6aSNélio Laranjeiro int ret; 717cb8faed7SAdrien Mazarguil 7187dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 719a6d83b6aSNélio Laranjeiro if (ret) { 720a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 7210f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 722a6d83b6aSNélio Laranjeiro return ret; 723cb8faed7SAdrien Mazarguil } 7247bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 7257bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 7267bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 7277bc47fb8SXueming Li }; 7287bc47fb8SXueming Li ifr = (struct ifreq) { 7297bc47fb8SXueming Li .ifr_data = (void *)&edata, 7307bc47fb8SXueming Li }; 7317dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 732a6d83b6aSNélio Laranjeiro if (ret) { 7330333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 7340333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master; 7350333b2f5SViacheslav Ovsiienko 7360333b2f5SViacheslav Ovsiienko /* 7370333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 7380333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 7390333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 7400333b2f5SViacheslav Ovsiienko * for representors due to missing physical 7410333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 7420333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 7430333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 7440333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 7450333b2f5SViacheslav Ovsiienko */ 7460333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 7470333b2f5SViacheslav Ovsiienko if (master) { 7480333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 7490333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&edata, 7500333b2f5SViacheslav Ovsiienko }; 7510333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 7520333b2f5SViacheslav Ovsiienko } 7530333b2f5SViacheslav Ovsiienko } 7540333b2f5SViacheslav Ovsiienko if (ret) { 755a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 7560333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 7570333b2f5SViacheslav Ovsiienko " ETHTOOL_GSET) failed: %s", 7580f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 759a6d83b6aSNélio Laranjeiro return ret; 760cb8faed7SAdrien Mazarguil } 7610333b2f5SViacheslav Ovsiienko } 762cb8faed7SAdrien Mazarguil link_speed = ethtool_cmd_speed(&edata); 763cb8faed7SAdrien Mazarguil if (link_speed == -1) 7643fef0822SFerruh Yigit dev_link.link_speed = ETH_SPEED_NUM_NONE; 765cb8faed7SAdrien Mazarguil else 766cb8faed7SAdrien Mazarguil dev_link.link_speed = link_speed; 76775ef62a9SNélio Laranjeiro priv->link_speed_capa = 0; 76875ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_Autoneg) 76975ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 77075ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_1000baseT_Full | 77175ef62a9SNélio Laranjeiro SUPPORTED_1000baseKX_Full)) 77275ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 77375ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_10000baseKR_Full) 77475ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 77575ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_40000baseKR4_Full | 77675ef62a9SNélio Laranjeiro SUPPORTED_40000baseCR4_Full | 77775ef62a9SNélio Laranjeiro SUPPORTED_40000baseSR4_Full | 77875ef62a9SNélio Laranjeiro SUPPORTED_40000baseLR4_Full)) 77975ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 780cb8faed7SAdrien Mazarguil dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 781cb8faed7SAdrien Mazarguil ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 78282113036SMarc Sune dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 78382113036SMarc Sune ETH_LINK_SPEED_FIXED); 7847dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 7857bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 786a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 787a6d83b6aSNélio Laranjeiro return -rte_errno; 788cb8faed7SAdrien Mazarguil } 789cfee9475SNélio Laranjeiro *link = dev_link; 790cfee9475SNélio Laranjeiro return 0; 791cfee9475SNélio Laranjeiro } 792cb8faed7SAdrien Mazarguil 793cb8faed7SAdrien Mazarguil /** 7943a49ffe3SShahaf Shuler * Retrieve physical link information (unlocked version using new ioctl). 79518840871SNélio Laranjeiro * 79618840871SNélio Laranjeiro * @param dev 79718840871SNélio Laranjeiro * Pointer to Ethernet device structure. 798cfee9475SNélio Laranjeiro * @param[out] link 799cfee9475SNélio Laranjeiro * Storage for current link status. 800fb732b0aSNélio Laranjeiro * 801fb732b0aSNélio Laranjeiro * @return 802a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 80318840871SNélio Laranjeiro */ 80418840871SNélio Laranjeiro static int 805cfee9475SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev, 806cfee9475SNélio Laranjeiro struct rte_eth_link *link) 807cfee9475SNélio Laranjeiro 80818840871SNélio Laranjeiro { 809dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 81037a4406cSNélio Laranjeiro struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS }; 81118840871SNélio Laranjeiro struct ifreq ifr; 81218840871SNélio Laranjeiro struct rte_eth_link dev_link; 8130333b2f5SViacheslav Ovsiienko struct rte_eth_dev *master = NULL; 81418840871SNélio Laranjeiro uint64_t sc; 815a6d83b6aSNélio Laranjeiro int ret; 81618840871SNélio Laranjeiro 8177dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 818a6d83b6aSNélio Laranjeiro if (ret) { 819a170a30dSNélio Laranjeiro DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s", 8200f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 821a6d83b6aSNélio Laranjeiro return ret; 82218840871SNélio Laranjeiro } 8237bc47fb8SXueming Li dev_link = (struct rte_eth_link) { 8247bc47fb8SXueming Li .link_status = ((ifr.ifr_flags & IFF_UP) && 8257bc47fb8SXueming Li (ifr.ifr_flags & IFF_RUNNING)), 8267bc47fb8SXueming Li }; 8277bc47fb8SXueming Li ifr = (struct ifreq) { 8287bc47fb8SXueming Li .ifr_data = (void *)&gcmd, 8297bc47fb8SXueming Li }; 8307dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 831a6d83b6aSNélio Laranjeiro if (ret) { 8320333b2f5SViacheslav Ovsiienko if (ret == -ENOTSUP && priv->representor) { 8330333b2f5SViacheslav Ovsiienko /* 8340333b2f5SViacheslav Ovsiienko * For representors we can try to inherit link 8350333b2f5SViacheslav Ovsiienko * settings from the master device. Actually 8360333b2f5SViacheslav Ovsiienko * link settings do not make a lot of sense 8370333b2f5SViacheslav Ovsiienko * for representors due to missing physical 8380333b2f5SViacheslav Ovsiienko * link. The old kernel drivers supported 8390333b2f5SViacheslav Ovsiienko * emulated settings query for representors, 8400333b2f5SViacheslav Ovsiienko * the new ones do not, so we have to add 8410333b2f5SViacheslav Ovsiienko * this code for compatibility issues. 8420333b2f5SViacheslav Ovsiienko */ 8430333b2f5SViacheslav Ovsiienko master = mlx5_find_master_dev(dev); 8440333b2f5SViacheslav Ovsiienko if (master) { 8450333b2f5SViacheslav Ovsiienko ifr = (struct ifreq) { 8460333b2f5SViacheslav Ovsiienko .ifr_data = (void *)&gcmd, 8470333b2f5SViacheslav Ovsiienko }; 8480333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr); 8490333b2f5SViacheslav Ovsiienko } 8500333b2f5SViacheslav Ovsiienko } 8510333b2f5SViacheslav Ovsiienko if (ret) { 852a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 8530333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 8540333b2f5SViacheslav Ovsiienko " ETHTOOL_GLINKSETTINGS) failed: %s", 855a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 856a6d83b6aSNélio Laranjeiro return ret; 85718840871SNélio Laranjeiro } 8580333b2f5SViacheslav Ovsiienko 8590333b2f5SViacheslav Ovsiienko } 86037a4406cSNélio Laranjeiro gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords; 86137a4406cSNélio Laranjeiro 86237a4406cSNélio Laranjeiro alignas(struct ethtool_link_settings) 86337a4406cSNélio Laranjeiro uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) + 86437a4406cSNélio Laranjeiro sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3]; 86537a4406cSNélio Laranjeiro struct ethtool_link_settings *ecmd = (void *)data; 86637a4406cSNélio Laranjeiro 86737a4406cSNélio Laranjeiro *ecmd = gcmd; 86837a4406cSNélio Laranjeiro ifr.ifr_data = (void *)ecmd; 8690333b2f5SViacheslav Ovsiienko ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr); 870a6d83b6aSNélio Laranjeiro if (ret) { 871a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 8720333b2f5SViacheslav Ovsiienko "port %u ioctl(SIOCETHTOOL," 8730333b2f5SViacheslav Ovsiienko "ETHTOOL_GLINKSETTINGS) failed: %s", 874a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 875a6d83b6aSNélio Laranjeiro return ret; 876ef09a7fcSGowrishankar Muthukrishnan } 87790260d57SNélio Laranjeiro dev_link.link_speed = ecmd->speed; 87890260d57SNélio Laranjeiro sc = ecmd->link_mode_masks[0] | 87990260d57SNélio Laranjeiro ((uint64_t)ecmd->link_mode_masks[1] << 32); 88018840871SNélio Laranjeiro priv->link_speed_capa = 0; 881b113cb5eSEdward Makarov if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT)) 88218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 883b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) | 884b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT))) 88518840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 886b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) | 887b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) | 888b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT))) 88918840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 890b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) | 891b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT))) 89218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_20G; 893b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) | 894b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) | 895b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) | 896b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT))) 89718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 898b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) | 899b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) | 900b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) | 901b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT))) 90218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_56G; 903b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) | 904b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) | 905b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT))) 90618840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_25G; 907b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) | 908b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT))) 90918840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_50G; 910b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) | 911b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) | 912b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) | 913b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT))) 91418840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_100G; 91590260d57SNélio Laranjeiro dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ? 91618840871SNélio Laranjeiro ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 91718840871SNélio Laranjeiro dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 91818840871SNélio Laranjeiro ETH_LINK_SPEED_FIXED); 9197dd7be29SShahaf Shuler if (((dev_link.link_speed && !dev_link.link_status) || 9207bc47fb8SXueming Li (!dev_link.link_speed && dev_link.link_status))) { 921a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 922a6d83b6aSNélio Laranjeiro return -rte_errno; 92318840871SNélio Laranjeiro } 924cfee9475SNélio Laranjeiro *link = dev_link; 925cfee9475SNélio Laranjeiro return 0; 926cfee9475SNélio Laranjeiro } 92718840871SNélio Laranjeiro 92818840871SNélio Laranjeiro /** 929cb8faed7SAdrien Mazarguil * DPDK callback to retrieve physical link information. 930cb8faed7SAdrien Mazarguil * 931cb8faed7SAdrien Mazarguil * @param dev 932cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 933cb8faed7SAdrien Mazarguil * @param wait_to_complete 934cfee9475SNélio Laranjeiro * Wait for request completion. 935fb732b0aSNélio Laranjeiro * 936fb732b0aSNélio Laranjeiro * @return 937cfee9475SNélio Laranjeiro * 0 if link status was not updated, positive if it was, a negative errno 938cfee9475SNélio Laranjeiro * value otherwise and rte_errno is set. 939cb8faed7SAdrien Mazarguil */ 940cb8faed7SAdrien Mazarguil int 941cfee9475SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) 942cb8faed7SAdrien Mazarguil { 943c7bf6225SYongseok Koh int ret; 944cfee9475SNélio Laranjeiro struct rte_eth_link dev_link; 945cfee9475SNélio Laranjeiro time_t start_time = time(NULL); 946cb8faed7SAdrien Mazarguil 947cfee9475SNélio Laranjeiro do { 948cfee9475SNélio Laranjeiro ret = mlx5_link_update_unlocked_gs(dev, &dev_link); 9497d2e32f7SShahaf Shuler if (ret) 9507d2e32f7SShahaf Shuler ret = mlx5_link_update_unlocked_gset(dev, &dev_link); 951cfee9475SNélio Laranjeiro if (ret == 0) 952cfee9475SNélio Laranjeiro break; 953cfee9475SNélio Laranjeiro /* Handle wait to complete situation. */ 954cfee9475SNélio Laranjeiro if (wait_to_complete && ret == -EAGAIN) { 955cfee9475SNélio Laranjeiro if (abs((int)difftime(time(NULL), start_time)) < 956cfee9475SNélio Laranjeiro MLX5_LINK_STATUS_TIMEOUT) { 957cfee9475SNélio Laranjeiro usleep(0); 958cfee9475SNélio Laranjeiro continue; 959cfee9475SNélio Laranjeiro } else { 960cfee9475SNélio Laranjeiro rte_errno = EBUSY; 961cfee9475SNélio Laranjeiro return -rte_errno; 962cfee9475SNélio Laranjeiro } 963cfee9475SNélio Laranjeiro } else if (ret < 0) { 964cfee9475SNélio Laranjeiro return ret; 965cfee9475SNélio Laranjeiro } 966cfee9475SNélio Laranjeiro } while (wait_to_complete); 967cfee9475SNélio Laranjeiro ret = !!memcmp(&dev->data->dev_link, &dev_link, 968cfee9475SNélio Laranjeiro sizeof(struct rte_eth_link)); 969cfee9475SNélio Laranjeiro dev->data->dev_link = dev_link; 970cfee9475SNélio Laranjeiro return ret; 971cb8faed7SAdrien Mazarguil } 972cb8faed7SAdrien Mazarguil 973cb8faed7SAdrien Mazarguil /** 974cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 975cf37ca95SAdrien Mazarguil * 976cf37ca95SAdrien Mazarguil * @param dev 977cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 978cf37ca95SAdrien Mazarguil * @param in_mtu 979cf37ca95SAdrien Mazarguil * New MTU. 980cf37ca95SAdrien Mazarguil * 981cf37ca95SAdrien Mazarguil * @return 982a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 983cf37ca95SAdrien Mazarguil */ 984cf37ca95SAdrien Mazarguil int 985cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 986cf37ca95SAdrien Mazarguil { 987dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 988a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 989a6d83b6aSNélio Laranjeiro int ret; 990cf37ca95SAdrien Mazarguil 991af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 992a0edafe4SNelio Laranjeiro if (ret) 993a6d83b6aSNélio Laranjeiro return ret; 994cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 995af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 996a0edafe4SNelio Laranjeiro if (ret) 997a6d83b6aSNélio Laranjeiro return ret; 998af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 999a0edafe4SNelio Laranjeiro if (ret) 1000a6d83b6aSNélio Laranjeiro return ret; 1001a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 1002a0edafe4SNelio Laranjeiro priv->mtu = mtu; 1003a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u adapter MTU set to %u", 1004a170a30dSNélio Laranjeiro dev->data->port_id, mtu); 1005a0edafe4SNelio Laranjeiro return 0; 1006a6d83b6aSNélio Laranjeiro } 1007a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 1008a6d83b6aSNélio Laranjeiro return -rte_errno; 1009cf37ca95SAdrien Mazarguil } 1010cf37ca95SAdrien Mazarguil 1011cf37ca95SAdrien Mazarguil /** 101202d75430SAdrien Mazarguil * DPDK callback to get flow control status. 101302d75430SAdrien Mazarguil * 101402d75430SAdrien Mazarguil * @param dev 101502d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 101602d75430SAdrien Mazarguil * @param[out] fc_conf 101702d75430SAdrien Mazarguil * Flow control output buffer. 101802d75430SAdrien Mazarguil * 101902d75430SAdrien Mazarguil * @return 1020a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 102102d75430SAdrien Mazarguil */ 102202d75430SAdrien Mazarguil int 102302d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 102402d75430SAdrien Mazarguil { 102502d75430SAdrien Mazarguil struct ifreq ifr; 102602d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 102702d75430SAdrien Mazarguil .cmd = ETHTOOL_GPAUSEPARAM 102802d75430SAdrien Mazarguil }; 102902d75430SAdrien Mazarguil int ret; 103002d75430SAdrien Mazarguil 1031d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 10327dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1033a6d83b6aSNélio Laranjeiro if (ret) { 1034a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1035a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:" 1036a170a30dSNélio Laranjeiro " %s", 1037a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1038a6d83b6aSNélio Laranjeiro return ret; 103902d75430SAdrien Mazarguil } 104002d75430SAdrien Mazarguil fc_conf->autoneg = ethpause.autoneg; 104102d75430SAdrien Mazarguil if (ethpause.rx_pause && ethpause.tx_pause) 104202d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_FULL; 104302d75430SAdrien Mazarguil else if (ethpause.rx_pause) 104402d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_RX_PAUSE; 104502d75430SAdrien Mazarguil else if (ethpause.tx_pause) 104602d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_TX_PAUSE; 104702d75430SAdrien Mazarguil else 104802d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_NONE; 1049a6d83b6aSNélio Laranjeiro return 0; 105002d75430SAdrien Mazarguil } 105102d75430SAdrien Mazarguil 105202d75430SAdrien Mazarguil /** 105302d75430SAdrien Mazarguil * DPDK callback to modify flow control parameters. 105402d75430SAdrien Mazarguil * 105502d75430SAdrien Mazarguil * @param dev 105602d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 105702d75430SAdrien Mazarguil * @param[in] fc_conf 105802d75430SAdrien Mazarguil * Flow control parameters. 105902d75430SAdrien Mazarguil * 106002d75430SAdrien Mazarguil * @return 1061a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 106202d75430SAdrien Mazarguil */ 106302d75430SAdrien Mazarguil int 106402d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 106502d75430SAdrien Mazarguil { 106602d75430SAdrien Mazarguil struct ifreq ifr; 106702d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 106802d75430SAdrien Mazarguil .cmd = ETHTOOL_SPAUSEPARAM 106902d75430SAdrien Mazarguil }; 107002d75430SAdrien Mazarguil int ret; 107102d75430SAdrien Mazarguil 1072d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 107302d75430SAdrien Mazarguil ethpause.autoneg = fc_conf->autoneg; 107402d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 107502d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_RX_PAUSE)) 107602d75430SAdrien Mazarguil ethpause.rx_pause = 1; 107702d75430SAdrien Mazarguil else 107802d75430SAdrien Mazarguil ethpause.rx_pause = 0; 107902d75430SAdrien Mazarguil 108002d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 108102d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_TX_PAUSE)) 108202d75430SAdrien Mazarguil ethpause.tx_pause = 1; 108302d75430SAdrien Mazarguil else 108402d75430SAdrien Mazarguil ethpause.tx_pause = 0; 10857dd7be29SShahaf Shuler ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 1086a6d83b6aSNélio Laranjeiro if (ret) { 1087a170a30dSNélio Laranjeiro DRV_LOG(WARNING, 1088a170a30dSNélio Laranjeiro "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 1089a170a30dSNélio Laranjeiro " failed: %s", 1090a170a30dSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 1091a6d83b6aSNélio Laranjeiro return ret; 109202d75430SAdrien Mazarguil } 1093a6d83b6aSNélio Laranjeiro return 0; 109402d75430SAdrien Mazarguil } 109502d75430SAdrien Mazarguil 109602d75430SAdrien Mazarguil /** 1097771fa900SAdrien Mazarguil * Get PCI information from struct ibv_device. 1098771fa900SAdrien Mazarguil * 1099771fa900SAdrien Mazarguil * @param device 1100771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 1101771fa900SAdrien Mazarguil * @param[out] pci_addr 1102771fa900SAdrien Mazarguil * PCI bus address output buffer. 1103771fa900SAdrien Mazarguil * 1104771fa900SAdrien Mazarguil * @return 1105a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1106771fa900SAdrien Mazarguil */ 1107771fa900SAdrien Mazarguil int 1108771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, 1109771fa900SAdrien Mazarguil struct rte_pci_addr *pci_addr) 1110771fa900SAdrien Mazarguil { 1111771fa900SAdrien Mazarguil FILE *file; 1112771fa900SAdrien Mazarguil char line[32]; 1113771fa900SAdrien Mazarguil MKSTR(path, "%s/device/uevent", device->ibdev_path); 1114771fa900SAdrien Mazarguil 1115771fa900SAdrien Mazarguil file = fopen(path, "rb"); 1116a6d83b6aSNélio Laranjeiro if (file == NULL) { 1117a6d83b6aSNélio Laranjeiro rte_errno = errno; 1118a6d83b6aSNélio Laranjeiro return -rte_errno; 1119a6d83b6aSNélio Laranjeiro } 1120771fa900SAdrien Mazarguil while (fgets(line, sizeof(line), file) == line) { 1121771fa900SAdrien Mazarguil size_t len = strlen(line); 1122771fa900SAdrien Mazarguil int ret; 1123771fa900SAdrien Mazarguil 1124771fa900SAdrien Mazarguil /* Truncate long lines. */ 1125771fa900SAdrien Mazarguil if (len == (sizeof(line) - 1)) 1126771fa900SAdrien Mazarguil while (line[(len - 1)] != '\n') { 1127771fa900SAdrien Mazarguil ret = fgetc(file); 1128771fa900SAdrien Mazarguil if (ret == EOF) 1129771fa900SAdrien Mazarguil break; 1130771fa900SAdrien Mazarguil line[(len - 1)] = ret; 1131771fa900SAdrien Mazarguil } 1132771fa900SAdrien Mazarguil /* Extract information. */ 1133771fa900SAdrien Mazarguil if (sscanf(line, 1134771fa900SAdrien Mazarguil "PCI_SLOT_NAME=" 1135463ced95SStephen Hemminger "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 1136771fa900SAdrien Mazarguil &pci_addr->domain, 1137771fa900SAdrien Mazarguil &pci_addr->bus, 1138771fa900SAdrien Mazarguil &pci_addr->devid, 1139771fa900SAdrien Mazarguil &pci_addr->function) == 4) { 1140771fa900SAdrien Mazarguil ret = 0; 1141771fa900SAdrien Mazarguil break; 1142771fa900SAdrien Mazarguil } 1143771fa900SAdrien Mazarguil } 1144771fa900SAdrien Mazarguil fclose(file); 1145771fa900SAdrien Mazarguil return 0; 1146771fa900SAdrien Mazarguil } 1147198a3c33SNelio Laranjeiro 1148198a3c33SNelio Laranjeiro /** 114940d9f906SViacheslav Ovsiienko * Handle asynchronous removal event for entire multiport device. 115040d9f906SViacheslav Ovsiienko * 115140d9f906SViacheslav Ovsiienko * @param sh 115240d9f906SViacheslav Ovsiienko * Infiniband device shared context. 115340d9f906SViacheslav Ovsiienko */ 115440d9f906SViacheslav Ovsiienko static void 115540d9f906SViacheslav Ovsiienko mlx5_dev_interrupt_device_fatal(struct mlx5_ibv_shared *sh) 115640d9f906SViacheslav Ovsiienko { 115740d9f906SViacheslav Ovsiienko uint32_t i; 115840d9f906SViacheslav Ovsiienko 115940d9f906SViacheslav Ovsiienko for (i = 0; i < sh->max_port; ++i) { 116040d9f906SViacheslav Ovsiienko struct rte_eth_dev *dev; 116140d9f906SViacheslav Ovsiienko 116240d9f906SViacheslav Ovsiienko if (sh->port[i].ih_port_id >= RTE_MAX_ETHPORTS) { 116340d9f906SViacheslav Ovsiienko /* 116440d9f906SViacheslav Ovsiienko * Or not existing port either no 116540d9f906SViacheslav Ovsiienko * handler installed for this port. 116640d9f906SViacheslav Ovsiienko */ 116740d9f906SViacheslav Ovsiienko continue; 116840d9f906SViacheslav Ovsiienko } 116940d9f906SViacheslav Ovsiienko dev = &rte_eth_devices[sh->port[i].ih_port_id]; 117040d9f906SViacheslav Ovsiienko assert(dev); 117140d9f906SViacheslav Ovsiienko if (dev->data->dev_conf.intr_conf.rmv) 117240d9f906SViacheslav Ovsiienko _rte_eth_dev_callback_process 117340d9f906SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_RMV, NULL); 117440d9f906SViacheslav Ovsiienko } 117540d9f906SViacheslav Ovsiienko } 117640d9f906SViacheslav Ovsiienko 117740d9f906SViacheslav Ovsiienko /** 1178028b2a28SViacheslav Ovsiienko * Handle shared asynchronous events the NIC (removal event 1179028b2a28SViacheslav Ovsiienko * and link status change). Supports multiport IB device. 1180c26ae069SMatan Azrad * 1181198a3c33SNelio Laranjeiro * @param cb_arg 1182198a3c33SNelio Laranjeiro * Callback argument. 1183198a3c33SNelio Laranjeiro */ 1184198a3c33SNelio Laranjeiro void 1185c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg) 1186198a3c33SNelio Laranjeiro { 1187028b2a28SViacheslav Ovsiienko struct mlx5_ibv_shared *sh = cb_arg; 1188028b2a28SViacheslav Ovsiienko struct ibv_async_event event; 1189198a3c33SNelio Laranjeiro 1190028b2a28SViacheslav Ovsiienko /* Read all message from the IB device and acknowledge them. */ 1191028b2a28SViacheslav Ovsiienko for (;;) { 1192028b2a28SViacheslav Ovsiienko struct rte_eth_dev *dev; 1193028b2a28SViacheslav Ovsiienko uint32_t tmp; 1194028b2a28SViacheslav Ovsiienko 1195028b2a28SViacheslav Ovsiienko if (mlx5_glue->get_async_event(sh->ctx, &event)) 1196028b2a28SViacheslav Ovsiienko break; 1197028b2a28SViacheslav Ovsiienko /* Retrieve and check IB port index. */ 1198028b2a28SViacheslav Ovsiienko tmp = (uint32_t)event.element.port_num; 119940d9f906SViacheslav Ovsiienko if (!tmp && event.event_type == IBV_EVENT_DEVICE_FATAL) { 1200028b2a28SViacheslav Ovsiienko /* 120140d9f906SViacheslav Ovsiienko * The DEVICE_FATAL event is called once for 120240d9f906SViacheslav Ovsiienko * entire device without port specifying. 120340d9f906SViacheslav Ovsiienko * We should notify all existing ports. 1204028b2a28SViacheslav Ovsiienko */ 1205028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 120640d9f906SViacheslav Ovsiienko mlx5_dev_interrupt_device_fatal(sh); 120740d9f906SViacheslav Ovsiienko continue; 120840d9f906SViacheslav Ovsiienko } 120940d9f906SViacheslav Ovsiienko assert(tmp && (tmp <= sh->max_port)); 121040d9f906SViacheslav Ovsiienko if (!tmp) { 121140d9f906SViacheslav Ovsiienko /* Unsupported devive level event. */ 121240d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 121340d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 121440d9f906SViacheslav Ovsiienko "unsupported common event (type %d)", 121540d9f906SViacheslav Ovsiienko event.event_type); 121640d9f906SViacheslav Ovsiienko continue; 121740d9f906SViacheslav Ovsiienko } 121840d9f906SViacheslav Ovsiienko if (tmp > sh->max_port) { 121940d9f906SViacheslav Ovsiienko /* Invalid IB port index. */ 122040d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 122140d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 122240d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 122340d9f906SViacheslav Ovsiienko "due to invalid IB port index (%u)", 122440d9f906SViacheslav Ovsiienko event.event_type, tmp); 122540d9f906SViacheslav Ovsiienko continue; 122640d9f906SViacheslav Ovsiienko } 122740d9f906SViacheslav Ovsiienko if (sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) { 122840d9f906SViacheslav Ovsiienko /* No handler installed. */ 122940d9f906SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 123040d9f906SViacheslav Ovsiienko DRV_LOG(DEBUG, 123140d9f906SViacheslav Ovsiienko "cannot handle an event (type %d)" 123240d9f906SViacheslav Ovsiienko "due to no handler installed for port %u", 123340d9f906SViacheslav Ovsiienko event.event_type, tmp); 1234028b2a28SViacheslav Ovsiienko continue; 1235028b2a28SViacheslav Ovsiienko } 1236028b2a28SViacheslav Ovsiienko /* Retrieve ethernet device descriptor. */ 1237028b2a28SViacheslav Ovsiienko tmp = sh->port[tmp - 1].ih_port_id; 1238028b2a28SViacheslav Ovsiienko dev = &rte_eth_devices[tmp]; 1239028b2a28SViacheslav Ovsiienko assert(dev); 1240028b2a28SViacheslav Ovsiienko if ((event.event_type == IBV_EVENT_PORT_ACTIVE || 1241028b2a28SViacheslav Ovsiienko event.event_type == IBV_EVENT_PORT_ERR) && 1242028b2a28SViacheslav Ovsiienko dev->data->dev_conf.intr_conf.lsc) { 1243028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1244028b2a28SViacheslav Ovsiienko if (mlx5_link_update(dev, 0) == -EAGAIN) { 1245028b2a28SViacheslav Ovsiienko usleep(0); 1246028b2a28SViacheslav Ovsiienko continue; 1247028b2a28SViacheslav Ovsiienko } 1248028b2a28SViacheslav Ovsiienko _rte_eth_dev_callback_process 1249028b2a28SViacheslav Ovsiienko (dev, RTE_ETH_EVENT_INTR_LSC, NULL); 1250028b2a28SViacheslav Ovsiienko continue; 1251028b2a28SViacheslav Ovsiienko } 1252028b2a28SViacheslav Ovsiienko DRV_LOG(DEBUG, 125340d9f906SViacheslav Ovsiienko "port %u cannot handle an unknown event (type %d)", 1254028b2a28SViacheslav Ovsiienko dev->data->port_id, event.event_type); 1255028b2a28SViacheslav Ovsiienko mlx5_glue->ack_async_event(&event); 1256028b2a28SViacheslav Ovsiienko } 1257198a3c33SNelio Laranjeiro } 1258198a3c33SNelio Laranjeiro 1259198a3c33SNelio Laranjeiro /** 126053e5a82fSViacheslav Ovsiienko * Uninstall shared asynchronous device events handler. 126153e5a82fSViacheslav Ovsiienko * This function is implemeted to support event sharing 126253e5a82fSViacheslav Ovsiienko * between multiple ports of single IB device. 126353e5a82fSViacheslav Ovsiienko * 126453e5a82fSViacheslav Ovsiienko * @param dev 126553e5a82fSViacheslav Ovsiienko * Pointer to Ethernet device. 126653e5a82fSViacheslav Ovsiienko */ 126753e5a82fSViacheslav Ovsiienko static void 126853e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev) 126953e5a82fSViacheslav Ovsiienko { 127053e5a82fSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 127153e5a82fSViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 127253e5a82fSViacheslav Ovsiienko 127353e5a82fSViacheslav Ovsiienko if (rte_eal_process_type() != RTE_PROC_PRIMARY) 127453e5a82fSViacheslav Ovsiienko return; 127553e5a82fSViacheslav Ovsiienko pthread_mutex_lock(&sh->intr_mutex); 127653e5a82fSViacheslav Ovsiienko assert(priv->ibv_port); 127753e5a82fSViacheslav Ovsiienko assert(priv->ibv_port <= sh->max_port); 127853e5a82fSViacheslav Ovsiienko assert(dev->data->port_id < RTE_MAX_ETHPORTS); 127953e5a82fSViacheslav Ovsiienko if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS) 128053e5a82fSViacheslav Ovsiienko goto exit; 128153e5a82fSViacheslav Ovsiienko assert(sh->port[priv->ibv_port - 1].ih_port_id == 128253e5a82fSViacheslav Ovsiienko (uint32_t)dev->data->port_id); 128353e5a82fSViacheslav Ovsiienko assert(sh->intr_cnt); 128453e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; 128553e5a82fSViacheslav Ovsiienko if (!sh->intr_cnt || --sh->intr_cnt) 128653e5a82fSViacheslav Ovsiienko goto exit; 128753e5a82fSViacheslav Ovsiienko rte_intr_callback_unregister(&sh->intr_handle, 128853e5a82fSViacheslav Ovsiienko mlx5_dev_interrupt_handler, sh); 128953e5a82fSViacheslav Ovsiienko sh->intr_handle.fd = 0; 129053e5a82fSViacheslav Ovsiienko sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 129153e5a82fSViacheslav Ovsiienko exit: 129253e5a82fSViacheslav Ovsiienko pthread_mutex_unlock(&sh->intr_mutex); 129353e5a82fSViacheslav Ovsiienko } 129453e5a82fSViacheslav Ovsiienko 129553e5a82fSViacheslav Ovsiienko /** 129653e5a82fSViacheslav Ovsiienko * Install shared asyncronous device events handler. 129753e5a82fSViacheslav Ovsiienko * This function is implemeted to support event sharing 129853e5a82fSViacheslav Ovsiienko * between multiple ports of single IB device. 129953e5a82fSViacheslav Ovsiienko * 130053e5a82fSViacheslav Ovsiienko * @param dev 130153e5a82fSViacheslav Ovsiienko * Pointer to Ethernet device. 130253e5a82fSViacheslav Ovsiienko */ 130353e5a82fSViacheslav Ovsiienko static void 130453e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_install(struct rte_eth_dev *dev) 130553e5a82fSViacheslav Ovsiienko { 130653e5a82fSViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 130753e5a82fSViacheslav Ovsiienko struct mlx5_ibv_shared *sh = priv->sh; 130853e5a82fSViacheslav Ovsiienko int ret; 130953e5a82fSViacheslav Ovsiienko int flags; 131053e5a82fSViacheslav Ovsiienko 131153e5a82fSViacheslav Ovsiienko if (rte_eal_process_type() != RTE_PROC_PRIMARY) 131253e5a82fSViacheslav Ovsiienko return; 131353e5a82fSViacheslav Ovsiienko pthread_mutex_lock(&sh->intr_mutex); 131453e5a82fSViacheslav Ovsiienko assert(priv->ibv_port); 131553e5a82fSViacheslav Ovsiienko assert(priv->ibv_port <= sh->max_port); 131653e5a82fSViacheslav Ovsiienko assert(dev->data->port_id < RTE_MAX_ETHPORTS); 131753e5a82fSViacheslav Ovsiienko if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) { 131853e5a82fSViacheslav Ovsiienko /* The handler is already installed for this port. */ 131953e5a82fSViacheslav Ovsiienko assert(sh->intr_cnt); 132053e5a82fSViacheslav Ovsiienko goto exit; 132153e5a82fSViacheslav Ovsiienko } 132253e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = (uint32_t)dev->data->port_id; 132353e5a82fSViacheslav Ovsiienko if (sh->intr_cnt) { 132453e5a82fSViacheslav Ovsiienko sh->intr_cnt++; 132553e5a82fSViacheslav Ovsiienko goto exit; 132653e5a82fSViacheslav Ovsiienko } 132753e5a82fSViacheslav Ovsiienko /* No shared handler installed. */ 132853e5a82fSViacheslav Ovsiienko assert(sh->ctx->async_fd > 0); 132953e5a82fSViacheslav Ovsiienko flags = fcntl(sh->ctx->async_fd, F_GETFL); 133053e5a82fSViacheslav Ovsiienko ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); 133153e5a82fSViacheslav Ovsiienko if (ret) { 133253e5a82fSViacheslav Ovsiienko DRV_LOG(INFO, "failed to change file descriptor" 133353e5a82fSViacheslav Ovsiienko " async event queue"); 133453e5a82fSViacheslav Ovsiienko /* Indicate there will be no interrupts. */ 133553e5a82fSViacheslav Ovsiienko dev->data->dev_conf.intr_conf.lsc = 0; 133653e5a82fSViacheslav Ovsiienko dev->data->dev_conf.intr_conf.rmv = 0; 133753e5a82fSViacheslav Ovsiienko sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; 133853e5a82fSViacheslav Ovsiienko goto exit; 133953e5a82fSViacheslav Ovsiienko } 134053e5a82fSViacheslav Ovsiienko sh->intr_handle.fd = sh->ctx->async_fd; 134153e5a82fSViacheslav Ovsiienko sh->intr_handle.type = RTE_INTR_HANDLE_EXT; 134253e5a82fSViacheslav Ovsiienko rte_intr_callback_register(&sh->intr_handle, 134353e5a82fSViacheslav Ovsiienko mlx5_dev_interrupt_handler, sh); 134453e5a82fSViacheslav Ovsiienko sh->intr_cnt++; 134553e5a82fSViacheslav Ovsiienko exit: 134653e5a82fSViacheslav Ovsiienko pthread_mutex_unlock(&sh->intr_mutex); 134753e5a82fSViacheslav Ovsiienko } 134853e5a82fSViacheslav Ovsiienko 134953e5a82fSViacheslav Ovsiienko /** 1350198a3c33SNelio Laranjeiro * Uninstall interrupt handler. 1351198a3c33SNelio Laranjeiro * 1352198a3c33SNelio Laranjeiro * @param dev 1353af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1354198a3c33SNelio Laranjeiro */ 1355198a3c33SNelio Laranjeiro void 1356af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev) 1357198a3c33SNelio Laranjeiro { 135853e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_uninstall(dev); 1359198a3c33SNelio Laranjeiro } 1360198a3c33SNelio Laranjeiro 1361198a3c33SNelio Laranjeiro /** 1362198a3c33SNelio Laranjeiro * Install interrupt handler. 1363198a3c33SNelio Laranjeiro * 1364198a3c33SNelio Laranjeiro * @param dev 1365af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1366198a3c33SNelio Laranjeiro */ 1367198a3c33SNelio Laranjeiro void 1368af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev) 1369198a3c33SNelio Laranjeiro { 137053e5a82fSViacheslav Ovsiienko mlx5_dev_shared_handler_install(dev); 1371198a3c33SNelio Laranjeiro } 137262072098SOr Ami 137362072098SOr Ami /** 137462072098SOr Ami * DPDK callback to bring the link DOWN. 137562072098SOr Ami * 137662072098SOr Ami * @param dev 137762072098SOr Ami * Pointer to Ethernet device structure. 137862072098SOr Ami * 137962072098SOr Ami * @return 1380a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 138162072098SOr Ami */ 138262072098SOr Ami int 138362072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev) 138462072098SOr Ami { 1385af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP); 138662072098SOr Ami } 138762072098SOr Ami 138862072098SOr Ami /** 138962072098SOr Ami * DPDK callback to bring the link UP. 139062072098SOr Ami * 139162072098SOr Ami * @param dev 139262072098SOr Ami * Pointer to Ethernet device structure. 139362072098SOr Ami * 139462072098SOr Ami * @return 1395a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 139662072098SOr Ami */ 139762072098SOr Ami int 139862072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev) 139962072098SOr Ami { 1400af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, IFF_UP); 140162072098SOr Ami } 1402a48deadaSOr Ami 1403a48deadaSOr Ami /** 1404cdab90cbSNélio Laranjeiro * Configure the TX function to use. 1405cdab90cbSNélio Laranjeiro * 1406aee1b165SXueming Li * @param dev 1407af4f09f2SNélio Laranjeiro * Pointer to private data structure. 14081cfa649bSShahaf Shuler * 14091cfa649bSShahaf Shuler * @return 14101cfa649bSShahaf Shuler * Pointer to selected Tx burst function. 1411cdab90cbSNélio Laranjeiro */ 14121cfa649bSShahaf Shuler eth_tx_burst_t 1413af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev) 1414cdab90cbSNélio Laranjeiro { 1415dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 14161cfa649bSShahaf Shuler eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst; 14177fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 1418dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 1419dbccb4cdSShahaf Shuler int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO | 1420dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 142132d4246cSXueming Li DEV_TX_OFFLOAD_GRE_TNL_TSO | 142232d4246cSXueming Li DEV_TX_OFFLOAD_IP_TNL_TSO | 142332d4246cSXueming Li DEV_TX_OFFLOAD_UDP_TNL_TSO)); 14245f8ba81cSXueming Li int swp = !!(tx_offloads & (DEV_TX_OFFLOAD_IP_TNL_TSO | 14255f8ba81cSXueming Li DEV_TX_OFFLOAD_UDP_TNL_TSO | 14265f8ba81cSXueming Li DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)); 1427dbccb4cdSShahaf Shuler int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT); 14281cfa649bSShahaf Shuler 1429aee1b165SXueming Li assert(priv != NULL); 1430230189d9SNélio Laranjeiro /* Select appropriate TX function. */ 14315f8ba81cSXueming Li if (vlan_insert || tso || swp) 1432dbccb4cdSShahaf Shuler return tx_pkt_burst; 14337fe24446SShahaf Shuler if (config->mps == MLX5_MPW_ENHANCED) { 1434af4f09f2SNélio Laranjeiro if (mlx5_check_vec_tx_support(dev) > 0) { 1435af4f09f2SNélio Laranjeiro if (mlx5_check_raw_vec_tx_support(dev) > 0) 14361cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_raw_vec; 14376cb559d6SYongseok Koh else 14381cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_vec; 1439a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 1440a170a30dSNélio Laranjeiro "port %u selected enhanced MPW Tx vectorized" 1441a170a30dSNélio Laranjeiro " function", 1442a170a30dSNélio Laranjeiro dev->data->port_id); 14436cb559d6SYongseok Koh } else { 14441cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_empw; 1445a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, 1446a170a30dSNélio Laranjeiro "port %u selected enhanced MPW Tx function", 14470f99970bSNélio Laranjeiro dev->data->port_id); 14486cb559d6SYongseok Koh } 14497fe24446SShahaf Shuler } else if (config->mps && (config->txq_inline > 0)) { 14501cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw_inline; 1451a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected MPW inline Tx function", 14520f99970bSNélio Laranjeiro dev->data->port_id); 14537fe24446SShahaf Shuler } else if (config->mps) { 14541cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw; 1455a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected MPW Tx function", 1456a170a30dSNélio Laranjeiro dev->data->port_id); 14572a66cf37SYaacov Hazan } 14581cfa649bSShahaf Shuler return tx_pkt_burst; 1459cdab90cbSNélio Laranjeiro } 1460cdab90cbSNélio Laranjeiro 1461cdab90cbSNélio Laranjeiro /** 1462cdab90cbSNélio Laranjeiro * Configure the RX function to use. 1463cdab90cbSNélio Laranjeiro * 1464aee1b165SXueming Li * @param dev 1465af4f09f2SNélio Laranjeiro * Pointer to private data structure. 14661cfa649bSShahaf Shuler * 14671cfa649bSShahaf Shuler * @return 14681cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 1469cdab90cbSNélio Laranjeiro */ 14701cfa649bSShahaf Shuler eth_rx_burst_t 1471af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 1472cdab90cbSNélio Laranjeiro { 14731cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 14741cfa649bSShahaf Shuler 1475af4f09f2SNélio Laranjeiro assert(dev != NULL); 1476af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 14771cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 1478a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u selected Rx vectorized function", 14790f99970bSNélio Laranjeiro dev->data->port_id); 14807d6bf6b8SYongseok Koh } else if (mlx5_mprq_enabled(dev)) { 14817d6bf6b8SYongseok Koh rx_pkt_burst = mlx5_rx_burst_mprq; 1482cdab90cbSNélio Laranjeiro } 14831cfa649bSShahaf Shuler return rx_pkt_burst; 14846cb559d6SYongseok Koh } 1485d3e0f392SMatan Azrad 1486d3e0f392SMatan Azrad /** 1487d3e0f392SMatan Azrad * Check if mlx5 device was removed. 1488d3e0f392SMatan Azrad * 1489d3e0f392SMatan Azrad * @param dev 1490d3e0f392SMatan Azrad * Pointer to Ethernet device structure. 1491d3e0f392SMatan Azrad * 1492d3e0f392SMatan Azrad * @return 1493d3e0f392SMatan Azrad * 1 when device is removed, otherwise 0. 1494d3e0f392SMatan Azrad */ 1495d3e0f392SMatan Azrad int 1496d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev) 1497d3e0f392SMatan Azrad { 1498d3e0f392SMatan Azrad struct ibv_device_attr device_attr; 1499dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 1500d3e0f392SMatan Azrad 1501f048f3d4SViacheslav Ovsiienko if (mlx5_glue->query_device(priv->sh->ctx, &device_attr) == EIO) 1502d3e0f392SMatan Azrad return 1; 1503d3e0f392SMatan Azrad return 0; 1504d3e0f392SMatan Azrad } 15052b730263SAdrien Mazarguil 15062b730263SAdrien Mazarguil /** 15072b730263SAdrien Mazarguil * Get port ID list of mlx5 instances sharing a common device. 15082b730263SAdrien Mazarguil * 15092b730263SAdrien Mazarguil * @param[in] dev 15102b730263SAdrien Mazarguil * Device to look for. 15112b730263SAdrien Mazarguil * @param[out] port_list 15122b730263SAdrien Mazarguil * Result buffer for collected port IDs. 15132b730263SAdrien Mazarguil * @param port_list_n 15142b730263SAdrien Mazarguil * Maximum number of entries in result buffer. If 0, @p port_list can be 15152b730263SAdrien Mazarguil * NULL. 15162b730263SAdrien Mazarguil * 15172b730263SAdrien Mazarguil * @return 15182b730263SAdrien Mazarguil * Number of matching instances regardless of the @p port_list_n 15192b730263SAdrien Mazarguil * parameter, 0 if none were found. 15202b730263SAdrien Mazarguil */ 15212b730263SAdrien Mazarguil unsigned int 15222b730263SAdrien Mazarguil mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list, 15232b730263SAdrien Mazarguil unsigned int port_list_n) 15242b730263SAdrien Mazarguil { 15252b730263SAdrien Mazarguil uint16_t id; 15262b730263SAdrien Mazarguil unsigned int n = 0; 15272b730263SAdrien Mazarguil 1528d874a4eeSThomas Monjalon RTE_ETH_FOREACH_DEV_OF(id, dev) { 15292b730263SAdrien Mazarguil if (n < port_list_n) 15302b730263SAdrien Mazarguil port_list[n] = id; 15312b730263SAdrien Mazarguil n++; 15322b730263SAdrien Mazarguil } 15332b730263SAdrien Mazarguil return n; 15342b730263SAdrien Mazarguil } 1535f872b4b9SNelio Laranjeiro 1536f872b4b9SNelio Laranjeiro /** 15372e4c987aSOri Kam * Get the E-Switch domain id this port belongs to. 15382e4c987aSOri Kam * 15392e4c987aSOri Kam * @param[in] port 15402e4c987aSOri Kam * Device port id. 15412e4c987aSOri Kam * @param[out] es_domain_id 15422e4c987aSOri Kam * E-Switch domain id. 15432e4c987aSOri Kam * @param[out] es_port_id 15442e4c987aSOri Kam * The port id of the port in the E-Switch. 15452e4c987aSOri Kam * 15462e4c987aSOri Kam * @return 15472e4c987aSOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 15482e4c987aSOri Kam */ 15492e4c987aSOri Kam int 15502e4c987aSOri Kam mlx5_port_to_eswitch_info(uint16_t port, 15512e4c987aSOri Kam uint16_t *es_domain_id, uint16_t *es_port_id) 15522e4c987aSOri Kam { 15532e4c987aSOri Kam struct rte_eth_dev *dev; 15542e4c987aSOri Kam struct mlx5_priv *priv; 15552e4c987aSOri Kam 15562e4c987aSOri Kam if (port >= RTE_MAX_ETHPORTS) { 15572e4c987aSOri Kam rte_errno = EINVAL; 15582e4c987aSOri Kam return -rte_errno; 15592e4c987aSOri Kam } 15602e4c987aSOri Kam if (!rte_eth_dev_is_valid_port(port)) { 15612e4c987aSOri Kam rte_errno = ENODEV; 15622e4c987aSOri Kam return -rte_errno; 15632e4c987aSOri Kam } 15642e4c987aSOri Kam dev = &rte_eth_devices[port]; 15652e4c987aSOri Kam priv = dev->data->dev_private; 15662e4c987aSOri Kam if (!(priv->representor || priv->master)) { 15672e4c987aSOri Kam rte_errno = EINVAL; 15682e4c987aSOri Kam return -rte_errno; 15692e4c987aSOri Kam } 15702e4c987aSOri Kam if (es_domain_id) 15712e4c987aSOri Kam *es_domain_id = priv->domain_id; 15722e4c987aSOri Kam if (es_port_id) 15732e4c987aSOri Kam *es_port_id = priv->vport_id; 15742e4c987aSOri Kam return 0; 15752e4c987aSOri Kam } 15762e4c987aSOri Kam 15772e4c987aSOri Kam /** 1578f872b4b9SNelio Laranjeiro * Get switch information associated with network interface. 1579f872b4b9SNelio Laranjeiro * 1580f872b4b9SNelio Laranjeiro * @param ifindex 1581f872b4b9SNelio Laranjeiro * Network interface index. 1582f872b4b9SNelio Laranjeiro * @param[out] info 1583f872b4b9SNelio Laranjeiro * Switch information object, populated in case of success. 1584f872b4b9SNelio Laranjeiro * 1585f872b4b9SNelio Laranjeiro * @return 1586f872b4b9SNelio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1587f872b4b9SNelio Laranjeiro */ 1588f872b4b9SNelio Laranjeiro int 1589f872b4b9SNelio Laranjeiro mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) 1590f872b4b9SNelio Laranjeiro { 1591f872b4b9SNelio Laranjeiro char ifname[IF_NAMESIZE]; 1592b2f3a381SDekel Peled char port_name[IF_NAMESIZE]; 1593f872b4b9SNelio Laranjeiro FILE *file; 1594b2f3a381SDekel Peled struct mlx5_switch_info data = { 1595b2f3a381SDekel Peled .master = 0, 1596b2f3a381SDekel Peled .representor = 0, 159730a86157SViacheslav Ovsiienko .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET, 1598b2f3a381SDekel Peled .port_name = 0, 1599b2f3a381SDekel Peled .switch_id = 0, 1600b2f3a381SDekel Peled }; 1601299d7dc2SViacheslav Ovsiienko DIR *dir; 1602f872b4b9SNelio Laranjeiro bool port_switch_id_set = false; 1603299d7dc2SViacheslav Ovsiienko bool device_dir = false; 1604f872b4b9SNelio Laranjeiro char c; 1605e3bcaf3aSAli Alnubani int ret; 1606f872b4b9SNelio Laranjeiro 1607f872b4b9SNelio Laranjeiro if (!if_indextoname(ifindex, ifname)) { 1608f872b4b9SNelio Laranjeiro rte_errno = errno; 1609f872b4b9SNelio Laranjeiro return -rte_errno; 1610f872b4b9SNelio Laranjeiro } 1611f872b4b9SNelio Laranjeiro 1612f872b4b9SNelio Laranjeiro MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name", 1613f872b4b9SNelio Laranjeiro ifname); 1614f872b4b9SNelio Laranjeiro MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id", 1615f872b4b9SNelio Laranjeiro ifname); 1616299d7dc2SViacheslav Ovsiienko MKSTR(pci_device, "/sys/class/net/%s/device", 1617299d7dc2SViacheslav Ovsiienko ifname); 1618f872b4b9SNelio Laranjeiro 1619f872b4b9SNelio Laranjeiro file = fopen(phys_port_name, "rb"); 1620f872b4b9SNelio Laranjeiro if (file != NULL) { 1621e3bcaf3aSAli Alnubani ret = fscanf(file, "%s", port_name); 1622f872b4b9SNelio Laranjeiro fclose(file); 1623e3bcaf3aSAli Alnubani if (ret == 1) 162430a86157SViacheslav Ovsiienko mlx5_translate_port_name(port_name, &data); 1625f872b4b9SNelio Laranjeiro } 1626f872b4b9SNelio Laranjeiro file = fopen(phys_switch_id, "rb"); 1627f872b4b9SNelio Laranjeiro if (file == NULL) { 1628f872b4b9SNelio Laranjeiro rte_errno = errno; 1629f872b4b9SNelio Laranjeiro return -rte_errno; 1630f872b4b9SNelio Laranjeiro } 1631f872b4b9SNelio Laranjeiro port_switch_id_set = 1632f872b4b9SNelio Laranjeiro fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 && 1633f872b4b9SNelio Laranjeiro c == '\n'; 1634f872b4b9SNelio Laranjeiro fclose(file); 1635299d7dc2SViacheslav Ovsiienko dir = opendir(pci_device); 1636299d7dc2SViacheslav Ovsiienko if (dir != NULL) { 1637299d7dc2SViacheslav Ovsiienko closedir(dir); 1638299d7dc2SViacheslav Ovsiienko device_dir = true; 1639299d7dc2SViacheslav Ovsiienko } 164030a86157SViacheslav Ovsiienko if (port_switch_id_set) { 164130a86157SViacheslav Ovsiienko /* We have some E-Switch configuration. */ 164230a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(device_dir, &data); 164330a86157SViacheslav Ovsiienko } 1644f872b4b9SNelio Laranjeiro *info = data; 1645299d7dc2SViacheslav Ovsiienko assert(!(data.master && data.representor)); 1646299d7dc2SViacheslav Ovsiienko if (data.master && data.representor) { 1647299d7dc2SViacheslav Ovsiienko DRV_LOG(ERR, "ifindex %u device is recognized as master" 1648299d7dc2SViacheslav Ovsiienko " and as representor", ifindex); 1649299d7dc2SViacheslav Ovsiienko rte_errno = ENODEV; 1650299d7dc2SViacheslav Ovsiienko return -rte_errno; 1651299d7dc2SViacheslav Ovsiienko } 1652f872b4b9SNelio Laranjeiro return 0; 1653f872b4b9SNelio Laranjeiro } 1654b2f3a381SDekel Peled 1655b2f3a381SDekel Peled /** 165630a86157SViacheslav Ovsiienko * Analyze gathered port parameters via Netlink to recognize master 165730a86157SViacheslav Ovsiienko * and representor devices for E-Switch configuration. 165830a86157SViacheslav Ovsiienko * 165930a86157SViacheslav Ovsiienko * @param[in] num_vf_set 166030a86157SViacheslav Ovsiienko * flag of presence of number of VFs port attribute. 166130a86157SViacheslav Ovsiienko * @param[inout] switch_info 166230a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 166330a86157SViacheslav Ovsiienko * type if recognized 166430a86157SViacheslav Ovsiienko * 166530a86157SViacheslav Ovsiienko * @return 166630a86157SViacheslav Ovsiienko * master and representor flags are set in switch_info according to 166730a86157SViacheslav Ovsiienko * recognized parameters (if any). 166830a86157SViacheslav Ovsiienko */ 166930a86157SViacheslav Ovsiienko void 167030a86157SViacheslav Ovsiienko mlx5_nl_check_switch_info(bool num_vf_set, 167130a86157SViacheslav Ovsiienko struct mlx5_switch_info *switch_info) 167230a86157SViacheslav Ovsiienko { 167330a86157SViacheslav Ovsiienko switch (switch_info->name_type) { 167430a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: 167530a86157SViacheslav Ovsiienko /* 167630a86157SViacheslav Ovsiienko * Name is not recognized, assume the master, 167730a86157SViacheslav Ovsiienko * check the number of VFs key presence. 167830a86157SViacheslav Ovsiienko */ 167930a86157SViacheslav Ovsiienko switch_info->master = num_vf_set; 168030a86157SViacheslav Ovsiienko break; 168130a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: 168230a86157SViacheslav Ovsiienko /* 168330a86157SViacheslav Ovsiienko * Name is not set, this assumes the legacy naming 168430a86157SViacheslav Ovsiienko * schema for master, just check if there is a 168530a86157SViacheslav Ovsiienko * number of VFs key. 168630a86157SViacheslav Ovsiienko */ 168730a86157SViacheslav Ovsiienko switch_info->master = num_vf_set; 168830a86157SViacheslav Ovsiienko break; 168930a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 169030a86157SViacheslav Ovsiienko /* New uplink naming schema recognized. */ 169130a86157SViacheslav Ovsiienko switch_info->master = 1; 169230a86157SViacheslav Ovsiienko break; 169330a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: 169430a86157SViacheslav Ovsiienko /* Legacy representors naming schema. */ 169530a86157SViacheslav Ovsiienko switch_info->representor = !num_vf_set; 169630a86157SViacheslav Ovsiienko break; 169730a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 169830a86157SViacheslav Ovsiienko /* New representors naming schema. */ 169930a86157SViacheslav Ovsiienko switch_info->representor = 1; 170030a86157SViacheslav Ovsiienko break; 170130a86157SViacheslav Ovsiienko } 170230a86157SViacheslav Ovsiienko } 170330a86157SViacheslav Ovsiienko 170430a86157SViacheslav Ovsiienko /** 170530a86157SViacheslav Ovsiienko * Analyze gathered port parameters via sysfs to recognize master 170630a86157SViacheslav Ovsiienko * and representor devices for E-Switch configuration. 170730a86157SViacheslav Ovsiienko * 170830a86157SViacheslav Ovsiienko * @param[in] device_dir 170930a86157SViacheslav Ovsiienko * flag of presence of "device" directory under port device key. 171030a86157SViacheslav Ovsiienko * @param[inout] switch_info 171130a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 171230a86157SViacheslav Ovsiienko * type if recognized 171330a86157SViacheslav Ovsiienko * 171430a86157SViacheslav Ovsiienko * @return 171530a86157SViacheslav Ovsiienko * master and representor flags are set in switch_info according to 171630a86157SViacheslav Ovsiienko * recognized parameters (if any). 171730a86157SViacheslav Ovsiienko */ 171830a86157SViacheslav Ovsiienko void 171930a86157SViacheslav Ovsiienko mlx5_sysfs_check_switch_info(bool device_dir, 172030a86157SViacheslav Ovsiienko struct mlx5_switch_info *switch_info) 172130a86157SViacheslav Ovsiienko { 172230a86157SViacheslav Ovsiienko switch (switch_info->name_type) { 172330a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: 172430a86157SViacheslav Ovsiienko /* 172530a86157SViacheslav Ovsiienko * Name is not recognized, assume the master, 172630a86157SViacheslav Ovsiienko * check the device directory presence. 172730a86157SViacheslav Ovsiienko */ 172830a86157SViacheslav Ovsiienko switch_info->master = device_dir; 172930a86157SViacheslav Ovsiienko break; 173030a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: 173130a86157SViacheslav Ovsiienko /* 173230a86157SViacheslav Ovsiienko * Name is not set, this assumes the legacy naming 173330a86157SViacheslav Ovsiienko * schema for master, just check if there is 173430a86157SViacheslav Ovsiienko * a device directory. 173530a86157SViacheslav Ovsiienko */ 173630a86157SViacheslav Ovsiienko switch_info->master = device_dir; 173730a86157SViacheslav Ovsiienko break; 173830a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: 173930a86157SViacheslav Ovsiienko /* New uplink naming schema recognized. */ 174030a86157SViacheslav Ovsiienko switch_info->master = 1; 174130a86157SViacheslav Ovsiienko break; 174230a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: 174330a86157SViacheslav Ovsiienko /* Legacy representors naming schema. */ 174430a86157SViacheslav Ovsiienko switch_info->representor = !device_dir; 174530a86157SViacheslav Ovsiienko break; 174630a86157SViacheslav Ovsiienko case MLX5_PHYS_PORT_NAME_TYPE_PFVF: 174730a86157SViacheslav Ovsiienko /* New representors naming schema. */ 174830a86157SViacheslav Ovsiienko switch_info->representor = 1; 174930a86157SViacheslav Ovsiienko break; 175030a86157SViacheslav Ovsiienko } 175130a86157SViacheslav Ovsiienko } 175230a86157SViacheslav Ovsiienko 175330a86157SViacheslav Ovsiienko /** 1754b2f3a381SDekel Peled * Extract port name, as a number, from sysfs or netlink information. 1755b2f3a381SDekel Peled * 1756b2f3a381SDekel Peled * @param[in] port_name_in 1757b2f3a381SDekel Peled * String representing the port name. 1758b2f3a381SDekel Peled * @param[out] port_info_out 175930a86157SViacheslav Ovsiienko * Port information, including port name as a number and port name 176030a86157SViacheslav Ovsiienko * type if recognized 1761b2f3a381SDekel Peled * 1762b2f3a381SDekel Peled * @return 176330a86157SViacheslav Ovsiienko * port_name field set according to recognized name format. 1764b2f3a381SDekel Peled */ 176530a86157SViacheslav Ovsiienko void 1766b2f3a381SDekel Peled mlx5_translate_port_name(const char *port_name_in, 1767b2f3a381SDekel Peled struct mlx5_switch_info *port_info_out) 1768b2f3a381SDekel Peled { 1769b2f3a381SDekel Peled char pf_c1, pf_c2, vf_c1, vf_c2; 1770b2f3a381SDekel Peled char *end; 177130a86157SViacheslav Ovsiienko int sc_items; 1772b2f3a381SDekel Peled 1773b2f3a381SDekel Peled /* 1774b2f3a381SDekel Peled * Check for port-name as a string of the form pf0vf0 177530a86157SViacheslav Ovsiienko * (support kernel ver >= 5.0 or OFED ver >= 4.6). 1776b2f3a381SDekel Peled */ 177730a86157SViacheslav Ovsiienko sc_items = sscanf(port_name_in, "%c%c%d%c%c%d", 177830a86157SViacheslav Ovsiienko &pf_c1, &pf_c2, &port_info_out->pf_num, 177930a86157SViacheslav Ovsiienko &vf_c1, &vf_c2, &port_info_out->port_name); 178030a86157SViacheslav Ovsiienko if (sc_items == 6 && 178130a86157SViacheslav Ovsiienko pf_c1 == 'p' && pf_c2 == 'f' && 178230a86157SViacheslav Ovsiienko vf_c1 == 'v' && vf_c2 == 'f') { 178330a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF; 178430a86157SViacheslav Ovsiienko return; 178530a86157SViacheslav Ovsiienko } 178630a86157SViacheslav Ovsiienko /* 178730a86157SViacheslav Ovsiienko * Check for port-name as a string of the form p0 178830a86157SViacheslav Ovsiienko * (support kernel ver >= 5.0, or OFED ver >= 4.6). 178930a86157SViacheslav Ovsiienko */ 179030a86157SViacheslav Ovsiienko sc_items = sscanf(port_name_in, "%c%d", 179130a86157SViacheslav Ovsiienko &pf_c1, &port_info_out->port_name); 179230a86157SViacheslav Ovsiienko if (sc_items == 2 && pf_c1 == 'p') { 179330a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK; 179430a86157SViacheslav Ovsiienko return; 179530a86157SViacheslav Ovsiienko } 1796b2f3a381SDekel Peled /* Check for port-name as a number (support kernel ver < 5.0 */ 1797b2f3a381SDekel Peled errno = 0; 1798b2f3a381SDekel Peled port_info_out->port_name = strtol(port_name_in, &end, 0); 1799b2f3a381SDekel Peled if (!errno && 180030a86157SViacheslav Ovsiienko (size_t)(end - port_name_in) == strlen(port_name_in)) { 180130a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY; 180230a86157SViacheslav Ovsiienko return; 1803b2f3a381SDekel Peled } 180430a86157SViacheslav Ovsiienko port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; 180530a86157SViacheslav Ovsiienko return; 1806b2f3a381SDekel Peled } 1807