18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 3771fa900SAdrien Mazarguil * Copyright 2015 Mellanox. 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6f8b9a3baSXueming Li #define _GNU_SOURCE 7f8b9a3baSXueming Li 8771fa900SAdrien Mazarguil #include <stddef.h> 9e60fbd5bSAdrien Mazarguil #include <assert.h> 10fc40db99SAdrien Mazarguil #include <inttypes.h> 11771fa900SAdrien Mazarguil #include <unistd.h> 12771fa900SAdrien Mazarguil #include <stdint.h> 13771fa900SAdrien Mazarguil #include <stdio.h> 14771fa900SAdrien Mazarguil #include <string.h> 15771fa900SAdrien Mazarguil #include <stdlib.h> 16771fa900SAdrien Mazarguil #include <errno.h> 17771fa900SAdrien Mazarguil #include <dirent.h> 18771fa900SAdrien Mazarguil #include <net/if.h> 19771fa900SAdrien Mazarguil #include <sys/ioctl.h> 20771fa900SAdrien Mazarguil #include <sys/socket.h> 213a49ffe3SShahaf Shuler #include <sys/utsname.h> 22771fa900SAdrien Mazarguil #include <netinet/in.h> 23cb8faed7SAdrien Mazarguil #include <linux/ethtool.h> 24cb8faed7SAdrien Mazarguil #include <linux/sockios.h> 253a49ffe3SShahaf Shuler #include <linux/version.h> 26198a3c33SNelio Laranjeiro #include <fcntl.h> 2790260d57SNélio Laranjeiro #include <stdalign.h> 28f8b9a3baSXueming Li #include <sys/un.h> 29771fa900SAdrien Mazarguil 30771fa900SAdrien Mazarguil #include <rte_atomic.h> 31ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 32c752998bSGaetan Rivet #include <rte_bus_pci.h> 33771fa900SAdrien Mazarguil #include <rte_mbuf.h> 34771fa900SAdrien Mazarguil #include <rte_common.h> 35198a3c33SNelio Laranjeiro #include <rte_interrupts.h> 36198a3c33SNelio Laranjeiro #include <rte_alarm.h> 37a48deadaSOr Ami #include <rte_malloc.h> 38771fa900SAdrien Mazarguil 39771fa900SAdrien Mazarguil #include "mlx5.h" 400e83b8e5SNelio Laranjeiro #include "mlx5_glue.h" 41e60fbd5bSAdrien Mazarguil #include "mlx5_rxtx.h" 42771fa900SAdrien Mazarguil #include "mlx5_utils.h" 43771fa900SAdrien Mazarguil 443a49ffe3SShahaf Shuler /* Add defines in case the running kernel is not the same as user headers. */ 453a49ffe3SShahaf Shuler #ifndef ETHTOOL_GLINKSETTINGS 463a49ffe3SShahaf Shuler struct ethtool_link_settings { 473a49ffe3SShahaf Shuler uint32_t cmd; 483a49ffe3SShahaf Shuler uint32_t speed; 493a49ffe3SShahaf Shuler uint8_t duplex; 503a49ffe3SShahaf Shuler uint8_t port; 513a49ffe3SShahaf Shuler uint8_t phy_address; 523a49ffe3SShahaf Shuler uint8_t autoneg; 533a49ffe3SShahaf Shuler uint8_t mdio_support; 543a49ffe3SShahaf Shuler uint8_t eth_to_mdix; 553a49ffe3SShahaf Shuler uint8_t eth_tp_mdix_ctrl; 563a49ffe3SShahaf Shuler int8_t link_mode_masks_nwords; 573a49ffe3SShahaf Shuler uint32_t reserved[8]; 583a49ffe3SShahaf Shuler uint32_t link_mode_masks[]; 593a49ffe3SShahaf Shuler }; 603a49ffe3SShahaf Shuler 613a49ffe3SShahaf Shuler #define ETHTOOL_GLINKSETTINGS 0x0000004c 623a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5 633a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_Autoneg_BIT 6 643a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17 653a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18 663a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19 673a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20 683a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21 693a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22 703a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23 713a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24 723a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25 733a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26 743a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27 753a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28 763a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29 773a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30 783a49ffe3SShahaf Shuler #endif 793a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_25G 803a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31 813a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32 823a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33 833a49ffe3SShahaf Shuler #endif 843a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_50G 853a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34 863a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35 873a49ffe3SShahaf Shuler #endif 883a49ffe3SShahaf Shuler #ifndef HAVE_ETHTOOL_LINK_MODE_100G 893a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36 903a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37 913a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38 923a49ffe3SShahaf Shuler #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39 933a49ffe3SShahaf Shuler #endif 943a49ffe3SShahaf Shuler 95771fa900SAdrien Mazarguil /** 96771fa900SAdrien Mazarguil * Get interface name from private structure. 97771fa900SAdrien Mazarguil * 98af4f09f2SNélio Laranjeiro * @param[in] dev 99af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 100771fa900SAdrien Mazarguil * @param[out] ifname 101771fa900SAdrien Mazarguil * Interface name output buffer. 102771fa900SAdrien Mazarguil * 103771fa900SAdrien Mazarguil * @return 104*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 105771fa900SAdrien Mazarguil */ 106771fa900SAdrien Mazarguil int 107af4f09f2SNélio Laranjeiro mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) 108771fa900SAdrien Mazarguil { 109af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 110771fa900SAdrien Mazarguil DIR *dir; 111771fa900SAdrien Mazarguil struct dirent *dent; 112771fa900SAdrien Mazarguil unsigned int dev_type = 0; 113771fa900SAdrien Mazarguil unsigned int dev_port_prev = ~0u; 114771fa900SAdrien Mazarguil char match[IF_NAMESIZE] = ""; 115771fa900SAdrien Mazarguil 116771fa900SAdrien Mazarguil { 11787ec44ceSXueming Li MKSTR(path, "%s/device/net", priv->ibdev_path); 118771fa900SAdrien Mazarguil 119771fa900SAdrien Mazarguil dir = opendir(path); 120*a6d83b6aSNélio Laranjeiro if (dir == NULL) { 121*a6d83b6aSNélio Laranjeiro rte_errno = errno; 122*a6d83b6aSNélio Laranjeiro return -rte_errno; 123*a6d83b6aSNélio Laranjeiro } 124771fa900SAdrien Mazarguil } 125771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 126771fa900SAdrien Mazarguil char *name = dent->d_name; 127771fa900SAdrien Mazarguil FILE *file; 128771fa900SAdrien Mazarguil unsigned int dev_port; 129771fa900SAdrien Mazarguil int r; 130771fa900SAdrien Mazarguil 131771fa900SAdrien Mazarguil if ((name[0] == '.') && 132771fa900SAdrien Mazarguil ((name[1] == '\0') || 133771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 134771fa900SAdrien Mazarguil continue; 135771fa900SAdrien Mazarguil 136771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 13787ec44ceSXueming Li priv->ibdev_path, name, 138771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 139771fa900SAdrien Mazarguil 140771fa900SAdrien Mazarguil file = fopen(path, "rb"); 141771fa900SAdrien Mazarguil if (file == NULL) { 142771fa900SAdrien Mazarguil if (errno != ENOENT) 143771fa900SAdrien Mazarguil continue; 144771fa900SAdrien Mazarguil /* 145771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 146771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 147771fa900SAdrien Mazarguil */ 148771fa900SAdrien Mazarguil try_dev_id: 149771fa900SAdrien Mazarguil match[0] = '\0'; 150771fa900SAdrien Mazarguil if (dev_type) 151771fa900SAdrien Mazarguil break; 152771fa900SAdrien Mazarguil dev_type = 1; 153771fa900SAdrien Mazarguil dev_port_prev = ~0u; 154771fa900SAdrien Mazarguil rewinddir(dir); 155771fa900SAdrien Mazarguil continue; 156771fa900SAdrien Mazarguil } 157771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 158771fa900SAdrien Mazarguil fclose(file); 159771fa900SAdrien Mazarguil if (r != 1) 160771fa900SAdrien Mazarguil continue; 161771fa900SAdrien Mazarguil /* 162771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 163771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 164771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 165771fa900SAdrien Mazarguil */ 166771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 167771fa900SAdrien Mazarguil goto try_dev_id; 168771fa900SAdrien Mazarguil dev_port_prev = dev_port; 169771fa900SAdrien Mazarguil if (dev_port == (priv->port - 1u)) 170771fa900SAdrien Mazarguil snprintf(match, sizeof(match), "%s", name); 171771fa900SAdrien Mazarguil } 172771fa900SAdrien Mazarguil closedir(dir); 173*a6d83b6aSNélio Laranjeiro if (match[0] == '\0') { 174*a6d83b6aSNélio Laranjeiro rte_errno = ENOENT; 175*a6d83b6aSNélio Laranjeiro return -rte_errno; 176*a6d83b6aSNélio Laranjeiro } 177771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 178771fa900SAdrien Mazarguil return 0; 179771fa900SAdrien Mazarguil } 180771fa900SAdrien Mazarguil 181771fa900SAdrien Mazarguil /** 182771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 183771fa900SAdrien Mazarguil * 184af4f09f2SNélio Laranjeiro * @param[in] dev 185af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 186771fa900SAdrien Mazarguil * @param req 187771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 188771fa900SAdrien Mazarguil * @param[out] ifr 189771fa900SAdrien Mazarguil * Interface request structure output buffer. 190771fa900SAdrien Mazarguil * 191771fa900SAdrien Mazarguil * @return 192*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 193771fa900SAdrien Mazarguil */ 194771fa900SAdrien Mazarguil int 195af4f09f2SNélio Laranjeiro mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr) 196771fa900SAdrien Mazarguil { 197771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 198*a6d83b6aSNélio Laranjeiro int ret = 0; 199771fa900SAdrien Mazarguil 200*a6d83b6aSNélio Laranjeiro if (sock == -1) { 201*a6d83b6aSNélio Laranjeiro rte_errno = errno; 202*a6d83b6aSNélio Laranjeiro return -rte_errno; 203*a6d83b6aSNélio Laranjeiro } 204*a6d83b6aSNélio Laranjeiro ret = mlx5_get_ifname(dev, &ifr->ifr_name); 205*a6d83b6aSNélio Laranjeiro if (ret) 206*a6d83b6aSNélio Laranjeiro goto error; 207771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 208*a6d83b6aSNélio Laranjeiro if (ret == -1) { 209*a6d83b6aSNélio Laranjeiro rte_errno = errno; 210*a6d83b6aSNélio Laranjeiro goto error; 211*a6d83b6aSNélio Laranjeiro } 212771fa900SAdrien Mazarguil close(sock); 213*a6d83b6aSNélio Laranjeiro return 0; 214*a6d83b6aSNélio Laranjeiro error: 215*a6d83b6aSNélio Laranjeiro close(sock); 216*a6d83b6aSNélio Laranjeiro return -rte_errno; 217771fa900SAdrien Mazarguil } 218771fa900SAdrien Mazarguil 219771fa900SAdrien Mazarguil /** 220771fa900SAdrien Mazarguil * Get device MTU. 221771fa900SAdrien Mazarguil * 222af4f09f2SNélio Laranjeiro * @param dev 223af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 224771fa900SAdrien Mazarguil * @param[out] mtu 225771fa900SAdrien Mazarguil * MTU value output buffer. 226771fa900SAdrien Mazarguil * 227771fa900SAdrien Mazarguil * @return 228*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 229771fa900SAdrien Mazarguil */ 230771fa900SAdrien Mazarguil int 231af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 232771fa900SAdrien Mazarguil { 233fc40db99SAdrien Mazarguil struct ifreq request; 234af4f09f2SNélio Laranjeiro int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request); 235771fa900SAdrien Mazarguil 236fc40db99SAdrien Mazarguil if (ret) 237fc40db99SAdrien Mazarguil return ret; 238fc40db99SAdrien Mazarguil *mtu = request.ifr_mtu; 239859081d3SShahaf Shuler return 0; 240859081d3SShahaf Shuler } 241859081d3SShahaf Shuler 242859081d3SShahaf Shuler /** 243cf37ca95SAdrien Mazarguil * Set device MTU. 244cf37ca95SAdrien Mazarguil * 245af4f09f2SNélio Laranjeiro * @param dev 246af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 247cf37ca95SAdrien Mazarguil * @param mtu 248cf37ca95SAdrien Mazarguil * MTU value to set. 249cf37ca95SAdrien Mazarguil * 250cf37ca95SAdrien Mazarguil * @return 251*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 252cf37ca95SAdrien Mazarguil */ 253cf37ca95SAdrien Mazarguil static int 254af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 255cf37ca95SAdrien Mazarguil { 256fc40db99SAdrien Mazarguil struct ifreq request = { .ifr_mtu = mtu, }; 257f3b492d7SAdrien Mazarguil 258af4f09f2SNélio Laranjeiro return mlx5_ifreq(dev, SIOCSIFMTU, &request); 259cf37ca95SAdrien Mazarguil } 260cf37ca95SAdrien Mazarguil 261cf37ca95SAdrien Mazarguil /** 262771fa900SAdrien Mazarguil * Set device flags. 263771fa900SAdrien Mazarguil * 264af4f09f2SNélio Laranjeiro * @param dev 265af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 266771fa900SAdrien Mazarguil * @param keep 267771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 268771fa900SAdrien Mazarguil * @param flags 269771fa900SAdrien Mazarguil * Bitmask for flags to modify. 270771fa900SAdrien Mazarguil * 271771fa900SAdrien Mazarguil * @return 272*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 273771fa900SAdrien Mazarguil */ 274771fa900SAdrien Mazarguil int 275af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags) 276771fa900SAdrien Mazarguil { 277fc40db99SAdrien Mazarguil struct ifreq request; 278af4f09f2SNélio Laranjeiro int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request); 279771fa900SAdrien Mazarguil 280fc40db99SAdrien Mazarguil if (ret) 281fc40db99SAdrien Mazarguil return ret; 282fc40db99SAdrien Mazarguil request.ifr_flags &= keep; 283fc40db99SAdrien Mazarguil request.ifr_flags |= flags & ~keep; 284af4f09f2SNélio Laranjeiro return mlx5_ifreq(dev, SIOCSIFFLAGS, &request); 285771fa900SAdrien Mazarguil } 286771fa900SAdrien Mazarguil 287771fa900SAdrien Mazarguil /** 2887b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 289e60fbd5bSAdrien Mazarguil * 290e60fbd5bSAdrien Mazarguil * @param dev 291e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 292e60fbd5bSAdrien Mazarguil * 293e60fbd5bSAdrien Mazarguil * @return 294*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 295e60fbd5bSAdrien Mazarguil */ 2967b2423cdSNélio Laranjeiro int 2977b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 298e60fbd5bSAdrien Mazarguil { 299e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 300e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 301e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 302634efbc2SNelio Laranjeiro unsigned int i; 303634efbc2SNelio Laranjeiro unsigned int j; 304634efbc2SNelio Laranjeiro unsigned int reta_idx_n; 30529c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 30621e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 307af4f09f2SNélio Laranjeiro uint64_t supp_tx_offloads = mlx5_get_tx_port_offloads(dev); 308dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 30917b843ebSShahaf Shuler uint64_t supp_rx_offloads = 310af4f09f2SNélio Laranjeiro (mlx5_get_rx_port_offloads() | 311af4f09f2SNélio Laranjeiro mlx5_get_rx_queue_offloads(dev)); 31217b843ebSShahaf Shuler uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads; 313*a6d83b6aSNélio Laranjeiro int ret = 0; 314e60fbd5bSAdrien Mazarguil 315dbccb4cdSShahaf Shuler if ((tx_offloads & supp_tx_offloads) != tx_offloads) { 316dbccb4cdSShahaf Shuler ERROR("Some Tx offloads are not supported " 317dbccb4cdSShahaf Shuler "requested 0x%" PRIx64 " supported 0x%" PRIx64, 318dbccb4cdSShahaf Shuler tx_offloads, supp_tx_offloads); 319*a6d83b6aSNélio Laranjeiro rte_errno = ENOTSUP; 320*a6d83b6aSNélio Laranjeiro return -rte_errno; 321dbccb4cdSShahaf Shuler } 32217b843ebSShahaf Shuler if ((rx_offloads & supp_rx_offloads) != rx_offloads) { 32317b843ebSShahaf Shuler ERROR("Some Rx offloads are not supported " 32417b843ebSShahaf Shuler "requested 0x%" PRIx64 " supported 0x%" PRIx64, 32517b843ebSShahaf Shuler rx_offloads, supp_rx_offloads); 326*a6d83b6aSNélio Laranjeiro rte_errno = ENOTSUP; 327*a6d83b6aSNélio Laranjeiro return -rte_errno; 32817b843ebSShahaf Shuler } 32929c1d8bbSNélio Laranjeiro if (use_app_rss_key && 33029c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 33129c1d8bbSNélio Laranjeiro rss_hash_default_key_len)) { 33229c1d8bbSNélio Laranjeiro /* MLX5 RSS only support 40bytes key. */ 333*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 334*a6d83b6aSNélio Laranjeiro return -rte_errno; 33529c1d8bbSNélio Laranjeiro } 33629c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 33729c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 33829c1d8bbSNélio Laranjeiro rss_hash_default_key_len, 0); 33929c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 34029c1d8bbSNélio Laranjeiro ERROR("cannot allocate RSS hash key memory (%u)", rxqs_n); 341*a6d83b6aSNélio Laranjeiro rte_errno = ENOMEM; 342*a6d83b6aSNélio Laranjeiro return -rte_errno; 34329c1d8bbSNélio Laranjeiro } 34429c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 34529c1d8bbSNélio Laranjeiro use_app_rss_key ? 34629c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 34729c1d8bbSNélio Laranjeiro rss_hash_default_key, 34829c1d8bbSNélio Laranjeiro rss_hash_default_key_len); 34929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_hash_default_key_len; 35029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 351e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 352e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 353e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 354e60fbd5bSAdrien Mazarguil INFO("%p: TX queues number update: %u -> %u", 355e60fbd5bSAdrien Mazarguil (void *)dev, priv->txqs_n, txqs_n); 356e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 357e60fbd5bSAdrien Mazarguil } 3587fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 359634efbc2SNelio Laranjeiro ERROR("cannot handle this many RX queues (%u)", rxqs_n); 360*a6d83b6aSNélio Laranjeiro rte_errno = EINVAL; 361*a6d83b6aSNélio Laranjeiro return -rte_errno; 362634efbc2SNelio Laranjeiro } 363e60fbd5bSAdrien Mazarguil if (rxqs_n == priv->rxqs_n) 364e60fbd5bSAdrien Mazarguil return 0; 365e60fbd5bSAdrien Mazarguil INFO("%p: RX queues number update: %u -> %u", 366e60fbd5bSAdrien Mazarguil (void *)dev, priv->rxqs_n, rxqs_n); 367e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 368634efbc2SNelio Laranjeiro /* If the requested number of RX queues is not a power of two, use the 369634efbc2SNelio Laranjeiro * maximum indirection table size for better balancing. 370634efbc2SNelio Laranjeiro * The result is always rounded to the next power of two. */ 371634efbc2SNelio Laranjeiro reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ? 3727fe24446SShahaf Shuler priv->config.ind_table_max_size : 373634efbc2SNelio Laranjeiro rxqs_n)); 374*a6d83b6aSNélio Laranjeiro ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); 375*a6d83b6aSNélio Laranjeiro if (ret) 376*a6d83b6aSNélio Laranjeiro return ret; 377634efbc2SNelio Laranjeiro /* When the number of RX queues is not a power of two, the remaining 378634efbc2SNelio Laranjeiro * table entries are padded with reused WQs and hashes are not spread 379634efbc2SNelio Laranjeiro * uniformly. */ 380634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 381634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = j; 382634efbc2SNelio Laranjeiro if (++j == rxqs_n) 383634efbc2SNelio Laranjeiro j = 0; 384634efbc2SNelio Laranjeiro } 385e60fbd5bSAdrien Mazarguil return 0; 386e60fbd5bSAdrien Mazarguil } 387e60fbd5bSAdrien Mazarguil 388e60fbd5bSAdrien Mazarguil /** 389e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 390e60fbd5bSAdrien Mazarguil * 391e60fbd5bSAdrien Mazarguil * @param dev 392e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 393e60fbd5bSAdrien Mazarguil * @param[out] info 394e60fbd5bSAdrien Mazarguil * Info structure output buffer. 395e60fbd5bSAdrien Mazarguil */ 396e60fbd5bSAdrien Mazarguil void 397e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 398e60fbd5bSAdrien Mazarguil { 39901d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 4007fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 401e60fbd5bSAdrien Mazarguil unsigned int max; 402e60fbd5bSAdrien Mazarguil char ifname[IF_NAMESIZE]; 403e60fbd5bSAdrien Mazarguil 404c0802544SFerruh Yigit info->pci_dev = RTE_ETH_DEV_TO_PCI(dev); 405e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 406e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 407e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 408e60fbd5bSAdrien Mazarguil /* 409e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 410e60fbd5bSAdrien Mazarguil * between the two values. 411e60fbd5bSAdrien Mazarguil */ 41243e9d979SShachar Beiser max = RTE_MIN(priv->device_attr.orig_attr.max_cq, 41343e9d979SShachar Beiser priv->device_attr.orig_attr.max_qp); 414e60fbd5bSAdrien Mazarguil /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 415e60fbd5bSAdrien Mazarguil if (max >= 65535) 416e60fbd5bSAdrien Mazarguil max = 65535; 417e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 418e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 4190497ddaaSYaacov Hazan info->max_mac_addrs = RTE_DIM(priv->mac); 420af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 421af4f09f2SNélio Laranjeiro info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 42217b843ebSShahaf Shuler info->rx_queue_offload_capa); 423af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 424af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(dev, &ifname) == 0) 425e60fbd5bSAdrien Mazarguil info->if_index = if_nametoindex(ifname); 426d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 4277fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 42829c1d8bbSNélio Laranjeiro info->hash_key_size = priv->rss_conf.rss_key_len; 42975ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 430b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 431e60fbd5bSAdrien Mazarguil } 432e60fbd5bSAdrien Mazarguil 433fb732b0aSNélio Laranjeiro /** 434fb732b0aSNélio Laranjeiro * Get supported packet types. 435fb732b0aSNélio Laranjeiro * 436fb732b0aSNélio Laranjeiro * @param dev 437fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 438fb732b0aSNélio Laranjeiro * 439fb732b0aSNélio Laranjeiro * @return 440fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 441fb732b0aSNélio Laranjeiro */ 44278a38edfSJianfeng Tan const uint32_t * 44378a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 44478a38edfSJianfeng Tan { 44578a38edfSJianfeng Tan static const uint32_t ptypes[] = { 44678a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 447ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 448c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 449c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 450ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 451ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 452ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 453ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 454c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 455c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 456ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 457ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 458ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 459ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 46078a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 46178a38edfSJianfeng Tan }; 46278a38edfSJianfeng Tan 4636cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 4646cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 46578a38edfSJianfeng Tan return ptypes; 46678a38edfSJianfeng Tan return NULL; 46778a38edfSJianfeng Tan } 46878a38edfSJianfeng Tan 469e60fbd5bSAdrien Mazarguil /** 4702c960a51SMatthieu Ternisien d'Ouville * DPDK callback to retrieve physical link information. 471cb8faed7SAdrien Mazarguil * 472cb8faed7SAdrien Mazarguil * @param dev 473cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 474fb732b0aSNélio Laranjeiro * 475fb732b0aSNélio Laranjeiro * @return 476*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 477cb8faed7SAdrien Mazarguil */ 47818840871SNélio Laranjeiro static int 47956f08e16SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev) 480cb8faed7SAdrien Mazarguil { 48101d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 482cb8faed7SAdrien Mazarguil struct ethtool_cmd edata = { 48375ef62a9SNélio Laranjeiro .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */ 484cb8faed7SAdrien Mazarguil }; 485cb8faed7SAdrien Mazarguil struct ifreq ifr; 486cb8faed7SAdrien Mazarguil struct rte_eth_link dev_link; 487cb8faed7SAdrien Mazarguil int link_speed = 0; 488*a6d83b6aSNélio Laranjeiro int ret; 489cb8faed7SAdrien Mazarguil 490*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 491*a6d83b6aSNélio Laranjeiro if (ret) { 492*a6d83b6aSNélio Laranjeiro WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(rte_errno)); 493*a6d83b6aSNélio Laranjeiro return ret; 494cb8faed7SAdrien Mazarguil } 495cb8faed7SAdrien Mazarguil memset(&dev_link, 0, sizeof(dev_link)); 496cb8faed7SAdrien Mazarguil dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 497cb8faed7SAdrien Mazarguil (ifr.ifr_flags & IFF_RUNNING)); 498d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)&edata; 499*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 500*a6d83b6aSNélio Laranjeiro if (ret) { 501cb8faed7SAdrien Mazarguil WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s", 502*a6d83b6aSNélio Laranjeiro strerror(rte_errno)); 503*a6d83b6aSNélio Laranjeiro return ret; 504cb8faed7SAdrien Mazarguil } 505cb8faed7SAdrien Mazarguil link_speed = ethtool_cmd_speed(&edata); 506cb8faed7SAdrien Mazarguil if (link_speed == -1) 507cb8faed7SAdrien Mazarguil dev_link.link_speed = 0; 508cb8faed7SAdrien Mazarguil else 509cb8faed7SAdrien Mazarguil dev_link.link_speed = link_speed; 51075ef62a9SNélio Laranjeiro priv->link_speed_capa = 0; 51175ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_Autoneg) 51275ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 51375ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_1000baseT_Full | 51475ef62a9SNélio Laranjeiro SUPPORTED_1000baseKX_Full)) 51575ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 51675ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_10000baseKR_Full) 51775ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 51875ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_40000baseKR4_Full | 51975ef62a9SNélio Laranjeiro SUPPORTED_40000baseCR4_Full | 52075ef62a9SNélio Laranjeiro SUPPORTED_40000baseSR4_Full | 52175ef62a9SNélio Laranjeiro SUPPORTED_40000baseLR4_Full)) 52275ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 523cb8faed7SAdrien Mazarguil dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 524cb8faed7SAdrien Mazarguil ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 52582113036SMarc Sune dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 52682113036SMarc Sune ETH_LINK_SPEED_FIXED); 527cb8faed7SAdrien Mazarguil if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { 528cb8faed7SAdrien Mazarguil /* Link status changed. */ 529cb8faed7SAdrien Mazarguil dev->data->dev_link = dev_link; 530cb8faed7SAdrien Mazarguil return 0; 531cb8faed7SAdrien Mazarguil } 532cb8faed7SAdrien Mazarguil /* Link status is still the same. */ 533*a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 534*a6d83b6aSNélio Laranjeiro return -rte_errno; 535cb8faed7SAdrien Mazarguil } 536cb8faed7SAdrien Mazarguil 537cb8faed7SAdrien Mazarguil /** 5383a49ffe3SShahaf Shuler * Retrieve physical link information (unlocked version using new ioctl). 53918840871SNélio Laranjeiro * 54018840871SNélio Laranjeiro * @param dev 54118840871SNélio Laranjeiro * Pointer to Ethernet device structure. 542fb732b0aSNélio Laranjeiro * 543fb732b0aSNélio Laranjeiro * @return 544*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 54518840871SNélio Laranjeiro */ 54618840871SNélio Laranjeiro static int 54756f08e16SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev) 54818840871SNélio Laranjeiro { 54901d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 55037a4406cSNélio Laranjeiro struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS }; 55118840871SNélio Laranjeiro struct ifreq ifr; 55218840871SNélio Laranjeiro struct rte_eth_link dev_link; 55318840871SNélio Laranjeiro uint64_t sc; 554*a6d83b6aSNélio Laranjeiro int ret; 55518840871SNélio Laranjeiro 556*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr); 557*a6d83b6aSNélio Laranjeiro if (ret) { 558*a6d83b6aSNélio Laranjeiro WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(rte_errno)); 559*a6d83b6aSNélio Laranjeiro return ret; 56018840871SNélio Laranjeiro } 56118840871SNélio Laranjeiro memset(&dev_link, 0, sizeof(dev_link)); 56218840871SNélio Laranjeiro dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 56318840871SNélio Laranjeiro (ifr.ifr_flags & IFF_RUNNING)); 56437a4406cSNélio Laranjeiro ifr.ifr_data = (void *)&gcmd; 565*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 566*a6d83b6aSNélio Laranjeiro if (ret) { 56718840871SNélio Laranjeiro DEBUG("ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS) failed: %s", 568*a6d83b6aSNélio Laranjeiro strerror(rte_errno)); 569*a6d83b6aSNélio Laranjeiro return ret; 57018840871SNélio Laranjeiro } 57137a4406cSNélio Laranjeiro gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords; 57237a4406cSNélio Laranjeiro 57337a4406cSNélio Laranjeiro alignas(struct ethtool_link_settings) 57437a4406cSNélio Laranjeiro uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) + 57537a4406cSNélio Laranjeiro sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3]; 57637a4406cSNélio Laranjeiro struct ethtool_link_settings *ecmd = (void *)data; 57737a4406cSNélio Laranjeiro 57837a4406cSNélio Laranjeiro *ecmd = gcmd; 57937a4406cSNélio Laranjeiro ifr.ifr_data = (void *)ecmd; 580*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 581*a6d83b6aSNélio Laranjeiro if (ret) { 582ef09a7fcSGowrishankar Muthukrishnan DEBUG("ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS) failed: %s", 583*a6d83b6aSNélio Laranjeiro strerror(rte_errno)); 584*a6d83b6aSNélio Laranjeiro return ret; 585ef09a7fcSGowrishankar Muthukrishnan } 58690260d57SNélio Laranjeiro dev_link.link_speed = ecmd->speed; 58790260d57SNélio Laranjeiro sc = ecmd->link_mode_masks[0] | 58890260d57SNélio Laranjeiro ((uint64_t)ecmd->link_mode_masks[1] << 32); 58918840871SNélio Laranjeiro priv->link_speed_capa = 0; 590b113cb5eSEdward Makarov if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT)) 59118840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 592b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) | 593b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT))) 59418840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 595b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) | 596b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) | 597b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT))) 59818840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 599b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) | 600b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT))) 60118840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_20G; 602b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) | 603b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) | 604b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) | 605b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT))) 60618840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 607b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) | 608b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) | 609b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) | 610b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT))) 61118840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_56G; 612b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) | 613b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) | 614b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT))) 61518840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_25G; 616b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) | 617b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT))) 61818840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_50G; 619b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) | 620b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) | 621b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) | 622b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT))) 62318840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_100G; 62490260d57SNélio Laranjeiro dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ? 62518840871SNélio Laranjeiro ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 62618840871SNélio Laranjeiro dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 62718840871SNélio Laranjeiro ETH_LINK_SPEED_FIXED); 62818840871SNélio Laranjeiro if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { 62918840871SNélio Laranjeiro /* Link status changed. */ 63018840871SNélio Laranjeiro dev->data->dev_link = dev_link; 63118840871SNélio Laranjeiro return 0; 63218840871SNélio Laranjeiro } 63318840871SNélio Laranjeiro /* Link status is still the same. */ 634*a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 635*a6d83b6aSNélio Laranjeiro return -rte_errno; 63618840871SNélio Laranjeiro } 63718840871SNélio Laranjeiro 63818840871SNélio Laranjeiro /** 639c7bf6225SYongseok Koh * Enable receiving and transmitting traffic. 640c7bf6225SYongseok Koh * 641af4f09f2SNélio Laranjeiro * @param dev 642af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 643c7bf6225SYongseok Koh */ 644c7bf6225SYongseok Koh static void 645af4f09f2SNélio Laranjeiro mlx5_link_start(struct rte_eth_dev *dev) 646c7bf6225SYongseok Koh { 647af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 648*a6d83b6aSNélio Laranjeiro int ret; 649c7bf6225SYongseok Koh 650af4f09f2SNélio Laranjeiro dev->tx_pkt_burst = mlx5_select_tx_function(dev); 651af4f09f2SNélio Laranjeiro dev->rx_pkt_burst = mlx5_select_rx_function(dev); 652*a6d83b6aSNélio Laranjeiro ret = mlx5_traffic_enable(dev); 653*a6d83b6aSNélio Laranjeiro if (ret) { 654c7bf6225SYongseok Koh ERROR("%p: error occurred while configuring control flows: %s", 655*a6d83b6aSNélio Laranjeiro (void *)dev, strerror(rte_errno)); 656*a6d83b6aSNélio Laranjeiro return; 657*a6d83b6aSNélio Laranjeiro } 658*a6d83b6aSNélio Laranjeiro ret = mlx5_flow_start(dev, &priv->flows); 659*a6d83b6aSNélio Laranjeiro if (ret) { 660c7bf6225SYongseok Koh ERROR("%p: error occurred while configuring flows: %s", 661*a6d83b6aSNélio Laranjeiro (void *)dev, strerror(rte_errno)); 662*a6d83b6aSNélio Laranjeiro } 663c7bf6225SYongseok Koh } 664c7bf6225SYongseok Koh 665c7bf6225SYongseok Koh /** 666c7bf6225SYongseok Koh * Disable receiving and transmitting traffic. 667c7bf6225SYongseok Koh * 668af4f09f2SNélio Laranjeiro * @param dev 669af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 670c7bf6225SYongseok Koh */ 671c7bf6225SYongseok Koh static void 672af4f09f2SNélio Laranjeiro mlx5_link_stop(struct rte_eth_dev *dev) 673c7bf6225SYongseok Koh { 674af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 675c7bf6225SYongseok Koh 676af4f09f2SNélio Laranjeiro mlx5_flow_stop(dev, &priv->flows); 677af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 678c7bf6225SYongseok Koh dev->rx_pkt_burst = removed_rx_burst; 679c7bf6225SYongseok Koh dev->tx_pkt_burst = removed_tx_burst; 680c7bf6225SYongseok Koh } 681c7bf6225SYongseok Koh 682c7bf6225SYongseok Koh /** 683e313ef4cSShahaf Shuler * Querying the link status till it changes to the desired state. 684e313ef4cSShahaf Shuler * Number of query attempts is bounded by MLX5_MAX_LINK_QUERY_ATTEMPTS. 685e313ef4cSShahaf Shuler * 686af4f09f2SNélio Laranjeiro * @param dev 687af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 688e313ef4cSShahaf Shuler * @param status 689e313ef4cSShahaf Shuler * Link desired status. 690e313ef4cSShahaf Shuler * 691e313ef4cSShahaf Shuler * @return 692*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 693e313ef4cSShahaf Shuler */ 694e313ef4cSShahaf Shuler int 695af4f09f2SNélio Laranjeiro mlx5_force_link_status_change(struct rte_eth_dev *dev, int status) 696e313ef4cSShahaf Shuler { 697e313ef4cSShahaf Shuler int try = 0; 698e313ef4cSShahaf Shuler 699e313ef4cSShahaf Shuler while (try < MLX5_MAX_LINK_QUERY_ATTEMPTS) { 700af4f09f2SNélio Laranjeiro mlx5_link_update(dev, 0); 701af4f09f2SNélio Laranjeiro if (dev->data->dev_link.link_status == status) 702e313ef4cSShahaf Shuler return 0; 703e313ef4cSShahaf Shuler try++; 704e313ef4cSShahaf Shuler sleep(1); 705e313ef4cSShahaf Shuler } 706*a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 707*a6d83b6aSNélio Laranjeiro return -rte_errno; 708e313ef4cSShahaf Shuler } 709e313ef4cSShahaf Shuler 710e313ef4cSShahaf Shuler /** 711cb8faed7SAdrien Mazarguil * DPDK callback to retrieve physical link information. 712cb8faed7SAdrien Mazarguil * 713cb8faed7SAdrien Mazarguil * @param dev 714cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 715cb8faed7SAdrien Mazarguil * @param wait_to_complete 716cb8faed7SAdrien Mazarguil * Wait for request completion (ignored). 717fb732b0aSNélio Laranjeiro * 718fb732b0aSNélio Laranjeiro * @return 719*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 720cb8faed7SAdrien Mazarguil */ 721cb8faed7SAdrien Mazarguil int 72256f08e16SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 723cb8faed7SAdrien Mazarguil { 724af4f09f2SNélio Laranjeiro struct utsname utsname; 725af4f09f2SNélio Laranjeiro int ver[3]; 726c7bf6225SYongseok Koh int ret; 727af4f09f2SNélio Laranjeiro struct rte_eth_link dev_link = dev->data->dev_link; 728cb8faed7SAdrien Mazarguil 729af4f09f2SNélio Laranjeiro if (uname(&utsname) == -1 || 730af4f09f2SNélio Laranjeiro sscanf(utsname.release, "%d.%d.%d", 731af4f09f2SNélio Laranjeiro &ver[0], &ver[1], &ver[2]) != 3 || 732af4f09f2SNélio Laranjeiro KERNEL_VERSION(ver[0], ver[1], ver[2]) < KERNEL_VERSION(4, 9, 0)) 733af4f09f2SNélio Laranjeiro ret = mlx5_link_update_unlocked_gset(dev); 734af4f09f2SNélio Laranjeiro else 735af4f09f2SNélio Laranjeiro ret = mlx5_link_update_unlocked_gs(dev); 736*a6d83b6aSNélio Laranjeiro if (ret) 737*a6d83b6aSNélio Laranjeiro return ret; 738af4f09f2SNélio Laranjeiro /* If lsc interrupt is disabled, should always be ready for traffic. */ 739af4f09f2SNélio Laranjeiro if (!dev->data->dev_conf.intr_conf.lsc) { 740af4f09f2SNélio Laranjeiro mlx5_link_start(dev); 741*a6d83b6aSNélio Laranjeiro return 0; 742af4f09f2SNélio Laranjeiro } 743af4f09f2SNélio Laranjeiro /* Re-select burst callbacks only if link status has been changed. */ 744af4f09f2SNélio Laranjeiro if (!ret && dev_link.link_status != dev->data->dev_link.link_status) { 745af4f09f2SNélio Laranjeiro if (dev->data->dev_link.link_status == ETH_LINK_UP) 746af4f09f2SNélio Laranjeiro mlx5_link_start(dev); 747af4f09f2SNélio Laranjeiro else 748af4f09f2SNélio Laranjeiro mlx5_link_stop(dev); 749af4f09f2SNélio Laranjeiro } 750*a6d83b6aSNélio Laranjeiro return 0; 751cb8faed7SAdrien Mazarguil } 752cb8faed7SAdrien Mazarguil 753cb8faed7SAdrien Mazarguil /** 754cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 755cf37ca95SAdrien Mazarguil * 756cf37ca95SAdrien Mazarguil * @param dev 757cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 758cf37ca95SAdrien Mazarguil * @param in_mtu 759cf37ca95SAdrien Mazarguil * New MTU. 760cf37ca95SAdrien Mazarguil * 761cf37ca95SAdrien Mazarguil * @return 762*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 763cf37ca95SAdrien Mazarguil */ 764cf37ca95SAdrien Mazarguil int 765cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 766cf37ca95SAdrien Mazarguil { 767cf37ca95SAdrien Mazarguil struct priv *priv = dev->data->dev_private; 768*a6d83b6aSNélio Laranjeiro uint16_t kern_mtu = 0; 769*a6d83b6aSNélio Laranjeiro int ret; 770cf37ca95SAdrien Mazarguil 771af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 772a0edafe4SNelio Laranjeiro if (ret) 773*a6d83b6aSNélio Laranjeiro return ret; 774cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 775af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 776a0edafe4SNelio Laranjeiro if (ret) 777*a6d83b6aSNélio Laranjeiro return ret; 778af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 779a0edafe4SNelio Laranjeiro if (ret) 780*a6d83b6aSNélio Laranjeiro return ret; 781a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 782a0edafe4SNelio Laranjeiro priv->mtu = mtu; 783a0edafe4SNelio Laranjeiro DEBUG("adapter port %u MTU set to %u", priv->port, mtu); 784a0edafe4SNelio Laranjeiro return 0; 785*a6d83b6aSNélio Laranjeiro } 786*a6d83b6aSNélio Laranjeiro rte_errno = EAGAIN; 787*a6d83b6aSNélio Laranjeiro return -rte_errno; 788cf37ca95SAdrien Mazarguil } 789cf37ca95SAdrien Mazarguil 790cf37ca95SAdrien Mazarguil /** 79102d75430SAdrien Mazarguil * DPDK callback to get flow control status. 79202d75430SAdrien Mazarguil * 79302d75430SAdrien Mazarguil * @param dev 79402d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 79502d75430SAdrien Mazarguil * @param[out] fc_conf 79602d75430SAdrien Mazarguil * Flow control output buffer. 79702d75430SAdrien Mazarguil * 79802d75430SAdrien Mazarguil * @return 799*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 80002d75430SAdrien Mazarguil */ 80102d75430SAdrien Mazarguil int 80202d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 80302d75430SAdrien Mazarguil { 80402d75430SAdrien Mazarguil struct ifreq ifr; 80502d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 80602d75430SAdrien Mazarguil .cmd = ETHTOOL_GPAUSEPARAM 80702d75430SAdrien Mazarguil }; 80802d75430SAdrien Mazarguil int ret; 80902d75430SAdrien Mazarguil 810d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 811*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 812*a6d83b6aSNélio Laranjeiro if (ret) { 813af4f09f2SNélio Laranjeiro WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed: %s", 814*a6d83b6aSNélio Laranjeiro strerror(rte_errno)); 815*a6d83b6aSNélio Laranjeiro return ret; 81602d75430SAdrien Mazarguil } 81702d75430SAdrien Mazarguil fc_conf->autoneg = ethpause.autoneg; 81802d75430SAdrien Mazarguil if (ethpause.rx_pause && ethpause.tx_pause) 81902d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_FULL; 82002d75430SAdrien Mazarguil else if (ethpause.rx_pause) 82102d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_RX_PAUSE; 82202d75430SAdrien Mazarguil else if (ethpause.tx_pause) 82302d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_TX_PAUSE; 82402d75430SAdrien Mazarguil else 82502d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_NONE; 826*a6d83b6aSNélio Laranjeiro return 0; 82702d75430SAdrien Mazarguil } 82802d75430SAdrien Mazarguil 82902d75430SAdrien Mazarguil /** 83002d75430SAdrien Mazarguil * DPDK callback to modify flow control parameters. 83102d75430SAdrien Mazarguil * 83202d75430SAdrien Mazarguil * @param dev 83302d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 83402d75430SAdrien Mazarguil * @param[in] fc_conf 83502d75430SAdrien Mazarguil * Flow control parameters. 83602d75430SAdrien Mazarguil * 83702d75430SAdrien Mazarguil * @return 838*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 83902d75430SAdrien Mazarguil */ 84002d75430SAdrien Mazarguil int 84102d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 84202d75430SAdrien Mazarguil { 84302d75430SAdrien Mazarguil struct ifreq ifr; 84402d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 84502d75430SAdrien Mazarguil .cmd = ETHTOOL_SPAUSEPARAM 84602d75430SAdrien Mazarguil }; 84702d75430SAdrien Mazarguil int ret; 84802d75430SAdrien Mazarguil 849d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 85002d75430SAdrien Mazarguil ethpause.autoneg = fc_conf->autoneg; 85102d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 85202d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_RX_PAUSE)) 85302d75430SAdrien Mazarguil ethpause.rx_pause = 1; 85402d75430SAdrien Mazarguil else 85502d75430SAdrien Mazarguil ethpause.rx_pause = 0; 85602d75430SAdrien Mazarguil 85702d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 85802d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_TX_PAUSE)) 85902d75430SAdrien Mazarguil ethpause.tx_pause = 1; 86002d75430SAdrien Mazarguil else 86102d75430SAdrien Mazarguil ethpause.tx_pause = 0; 862*a6d83b6aSNélio Laranjeiro ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr); 863*a6d83b6aSNélio Laranjeiro if (ret) { 86402d75430SAdrien Mazarguil WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 86502d75430SAdrien Mazarguil " failed: %s", 866*a6d83b6aSNélio Laranjeiro strerror(rte_errno)); 867*a6d83b6aSNélio Laranjeiro return ret; 86802d75430SAdrien Mazarguil } 869*a6d83b6aSNélio Laranjeiro return 0; 87002d75430SAdrien Mazarguil } 87102d75430SAdrien Mazarguil 87202d75430SAdrien Mazarguil /** 873771fa900SAdrien Mazarguil * Get PCI information from struct ibv_device. 874771fa900SAdrien Mazarguil * 875771fa900SAdrien Mazarguil * @param device 876771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 877771fa900SAdrien Mazarguil * @param[out] pci_addr 878771fa900SAdrien Mazarguil * PCI bus address output buffer. 879771fa900SAdrien Mazarguil * 880771fa900SAdrien Mazarguil * @return 881*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 882771fa900SAdrien Mazarguil */ 883771fa900SAdrien Mazarguil int 884771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, 885771fa900SAdrien Mazarguil struct rte_pci_addr *pci_addr) 886771fa900SAdrien Mazarguil { 887771fa900SAdrien Mazarguil FILE *file; 888771fa900SAdrien Mazarguil char line[32]; 889771fa900SAdrien Mazarguil MKSTR(path, "%s/device/uevent", device->ibdev_path); 890771fa900SAdrien Mazarguil 891771fa900SAdrien Mazarguil file = fopen(path, "rb"); 892*a6d83b6aSNélio Laranjeiro if (file == NULL) { 893*a6d83b6aSNélio Laranjeiro rte_errno = errno; 894*a6d83b6aSNélio Laranjeiro return -rte_errno; 895*a6d83b6aSNélio Laranjeiro } 896771fa900SAdrien Mazarguil while (fgets(line, sizeof(line), file) == line) { 897771fa900SAdrien Mazarguil size_t len = strlen(line); 898771fa900SAdrien Mazarguil int ret; 899771fa900SAdrien Mazarguil 900771fa900SAdrien Mazarguil /* Truncate long lines. */ 901771fa900SAdrien Mazarguil if (len == (sizeof(line) - 1)) 902771fa900SAdrien Mazarguil while (line[(len - 1)] != '\n') { 903771fa900SAdrien Mazarguil ret = fgetc(file); 904771fa900SAdrien Mazarguil if (ret == EOF) 905771fa900SAdrien Mazarguil break; 906771fa900SAdrien Mazarguil line[(len - 1)] = ret; 907771fa900SAdrien Mazarguil } 908771fa900SAdrien Mazarguil /* Extract information. */ 909771fa900SAdrien Mazarguil if (sscanf(line, 910771fa900SAdrien Mazarguil "PCI_SLOT_NAME=" 911463ced95SStephen Hemminger "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 912771fa900SAdrien Mazarguil &pci_addr->domain, 913771fa900SAdrien Mazarguil &pci_addr->bus, 914771fa900SAdrien Mazarguil &pci_addr->devid, 915771fa900SAdrien Mazarguil &pci_addr->function) == 4) { 916771fa900SAdrien Mazarguil ret = 0; 917771fa900SAdrien Mazarguil break; 918771fa900SAdrien Mazarguil } 919771fa900SAdrien Mazarguil } 920771fa900SAdrien Mazarguil fclose(file); 921771fa900SAdrien Mazarguil return 0; 922771fa900SAdrien Mazarguil } 923198a3c33SNelio Laranjeiro 924198a3c33SNelio Laranjeiro /** 925c26ae069SMatan Azrad * Update the link status. 926198a3c33SNelio Laranjeiro * 927af4f09f2SNélio Laranjeiro * @param dev 928af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 929198a3c33SNelio Laranjeiro * 930198a3c33SNelio Laranjeiro * @return 931*a6d83b6aSNélio Laranjeiro * Zero if the callback process can be called immediately, negative errno 932*a6d83b6aSNélio Laranjeiro * value otherwise and rte_errno is set. 933198a3c33SNelio Laranjeiro */ 934198a3c33SNelio Laranjeiro static int 935af4f09f2SNélio Laranjeiro mlx5_link_status_update(struct rte_eth_dev *dev) 936c26ae069SMatan Azrad { 937af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 938af4f09f2SNélio Laranjeiro struct rte_eth_link *link = &dev->data->dev_link; 939*a6d83b6aSNélio Laranjeiro int ret; 940c26ae069SMatan Azrad 941*a6d83b6aSNélio Laranjeiro ret = mlx5_link_update(dev, 0); 942*a6d83b6aSNélio Laranjeiro if (ret) 943*a6d83b6aSNélio Laranjeiro return ret; 944c26ae069SMatan Azrad if (((link->link_speed == 0) && link->link_status) || 945c26ae069SMatan Azrad ((link->link_speed != 0) && !link->link_status)) { 946c26ae069SMatan Azrad /* 947c26ae069SMatan Azrad * Inconsistent status. Event likely occurred before the 948c26ae069SMatan Azrad * kernel netdevice exposes the new status. 949c26ae069SMatan Azrad */ 950c26ae069SMatan Azrad if (!priv->pending_alarm) { 951c26ae069SMatan Azrad priv->pending_alarm = 1; 952c26ae069SMatan Azrad rte_eal_alarm_set(MLX5_ALARM_TIMEOUT_US, 953c26ae069SMatan Azrad mlx5_dev_link_status_handler, 954c26ae069SMatan Azrad priv->dev); 955c26ae069SMatan Azrad } 956c26ae069SMatan Azrad return 1; 957c26ae069SMatan Azrad } else if (unlikely(priv->pending_alarm)) { 958c26ae069SMatan Azrad /* Link interrupt occurred while alarm is already scheduled. */ 959c26ae069SMatan Azrad priv->pending_alarm = 0; 960c26ae069SMatan Azrad rte_eal_alarm_cancel(mlx5_dev_link_status_handler, priv->dev); 961c26ae069SMatan Azrad } 962c26ae069SMatan Azrad return 0; 963c26ae069SMatan Azrad } 964c26ae069SMatan Azrad 965c26ae069SMatan Azrad /** 966c26ae069SMatan Azrad * Device status handler. 967c26ae069SMatan Azrad * 968af4f09f2SNélio Laranjeiro * @param dev 969af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 970c26ae069SMatan Azrad * @param events 971c26ae069SMatan Azrad * Pointer to event flags holder. 972c26ae069SMatan Azrad * 973c26ae069SMatan Azrad * @return 974c26ae069SMatan Azrad * Events bitmap of callback process which can be called immediately. 975c26ae069SMatan Azrad */ 976c26ae069SMatan Azrad static uint32_t 977af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev) 978198a3c33SNelio Laranjeiro { 979af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 980198a3c33SNelio Laranjeiro struct ibv_async_event event; 981c26ae069SMatan Azrad uint32_t ret = 0; 982198a3c33SNelio Laranjeiro 983198a3c33SNelio Laranjeiro /* Read all message and acknowledge them. */ 984198a3c33SNelio Laranjeiro for (;;) { 9850e83b8e5SNelio Laranjeiro if (mlx5_glue->get_async_event(priv->ctx, &event)) 986198a3c33SNelio Laranjeiro break; 987c26ae069SMatan Azrad if ((event.event_type == IBV_EVENT_PORT_ACTIVE || 988c26ae069SMatan Azrad event.event_type == IBV_EVENT_PORT_ERR) && 989af4f09f2SNélio Laranjeiro (dev->data->dev_conf.intr_conf.lsc == 1)) 990c26ae069SMatan Azrad ret |= (1 << RTE_ETH_EVENT_INTR_LSC); 9917d7d7ad1SMatan Azrad else if (event.event_type == IBV_EVENT_DEVICE_FATAL && 992af4f09f2SNélio Laranjeiro dev->data->dev_conf.intr_conf.rmv == 1) 9937d7d7ad1SMatan Azrad ret |= (1 << RTE_ETH_EVENT_INTR_RMV); 994c26ae069SMatan Azrad else 995198a3c33SNelio Laranjeiro DEBUG("event type %d on port %d not handled", 996198a3c33SNelio Laranjeiro event.event_type, event.element.port_num); 9970e83b8e5SNelio Laranjeiro mlx5_glue->ack_async_event(&event); 998198a3c33SNelio Laranjeiro } 999c26ae069SMatan Azrad if (ret & (1 << RTE_ETH_EVENT_INTR_LSC)) 1000af4f09f2SNélio Laranjeiro if (mlx5_link_status_update(dev)) 1001c26ae069SMatan Azrad ret &= ~(1 << RTE_ETH_EVENT_INTR_LSC); 1002198a3c33SNelio Laranjeiro return ret; 1003198a3c33SNelio Laranjeiro } 1004198a3c33SNelio Laranjeiro 1005198a3c33SNelio Laranjeiro /** 1006198a3c33SNelio Laranjeiro * Handle delayed link status event. 1007198a3c33SNelio Laranjeiro * 1008198a3c33SNelio Laranjeiro * @param arg 1009198a3c33SNelio Laranjeiro * Registered argument. 1010198a3c33SNelio Laranjeiro */ 1011198a3c33SNelio Laranjeiro void 1012198a3c33SNelio Laranjeiro mlx5_dev_link_status_handler(void *arg) 1013198a3c33SNelio Laranjeiro { 1014198a3c33SNelio Laranjeiro struct rte_eth_dev *dev = arg; 1015198a3c33SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 1016198a3c33SNelio Laranjeiro int ret; 1017198a3c33SNelio Laranjeiro 1018a9f2fbc4SShahaf Shuler priv->pending_alarm = 0; 1019af4f09f2SNélio Laranjeiro ret = mlx5_link_status_update(dev); 1020c26ae069SMatan Azrad if (!ret) 1021cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 1022198a3c33SNelio Laranjeiro } 1023198a3c33SNelio Laranjeiro 1024198a3c33SNelio Laranjeiro /** 1025198a3c33SNelio Laranjeiro * Handle interrupts from the NIC. 1026198a3c33SNelio Laranjeiro * 1027198a3c33SNelio Laranjeiro * @param[in] intr_handle 1028198a3c33SNelio Laranjeiro * Interrupt handler. 1029198a3c33SNelio Laranjeiro * @param cb_arg 1030198a3c33SNelio Laranjeiro * Callback argument. 1031198a3c33SNelio Laranjeiro */ 1032198a3c33SNelio Laranjeiro void 1033c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg) 1034198a3c33SNelio Laranjeiro { 1035198a3c33SNelio Laranjeiro struct rte_eth_dev *dev = cb_arg; 1036c26ae069SMatan Azrad uint32_t events; 1037198a3c33SNelio Laranjeiro 1038af4f09f2SNélio Laranjeiro events = mlx5_dev_status_handler(dev); 1039c26ae069SMatan Azrad if (events & (1 << RTE_ETH_EVENT_INTR_LSC)) 1040cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 10417d7d7ad1SMatan Azrad if (events & (1 << RTE_ETH_EVENT_INTR_RMV)) 1042cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL); 1043198a3c33SNelio Laranjeiro } 1044198a3c33SNelio Laranjeiro 1045198a3c33SNelio Laranjeiro /** 1046f8b9a3baSXueming Li * Handle interrupts from the socket. 1047f8b9a3baSXueming Li * 1048f8b9a3baSXueming Li * @param cb_arg 1049f8b9a3baSXueming Li * Callback argument. 1050f8b9a3baSXueming Li */ 1051f8b9a3baSXueming Li static void 1052f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg) 1053f8b9a3baSXueming Li { 1054f8b9a3baSXueming Li struct rte_eth_dev *dev = cb_arg; 1055f8b9a3baSXueming Li 1056af4f09f2SNélio Laranjeiro mlx5_socket_handle(dev); 1057f8b9a3baSXueming Li } 1058f8b9a3baSXueming Li 1059f8b9a3baSXueming Li /** 1060198a3c33SNelio Laranjeiro * Uninstall interrupt handler. 1061198a3c33SNelio Laranjeiro * 1062198a3c33SNelio Laranjeiro * @param dev 1063af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1064198a3c33SNelio Laranjeiro */ 1065198a3c33SNelio Laranjeiro void 1066af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev) 1067198a3c33SNelio Laranjeiro { 1068af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 1069af4f09f2SNélio Laranjeiro 1070f8b9a3baSXueming Li if (dev->data->dev_conf.intr_conf.lsc || 1071f8b9a3baSXueming Li dev->data->dev_conf.intr_conf.rmv) 1072198a3c33SNelio Laranjeiro rte_intr_callback_unregister(&priv->intr_handle, 1073f8b9a3baSXueming Li mlx5_dev_interrupt_handler, dev); 1074f8b9a3baSXueming Li if (priv->primary_socket) 1075f8b9a3baSXueming Li rte_intr_callback_unregister(&priv->intr_handle_socket, 1076f8b9a3baSXueming Li mlx5_dev_handler_socket, dev); 10776817ad38SYongseok Koh if (priv->pending_alarm) { 1078198a3c33SNelio Laranjeiro priv->pending_alarm = 0; 10796817ad38SYongseok Koh rte_eal_alarm_cancel(mlx5_dev_link_status_handler, dev); 10806817ad38SYongseok Koh } 1081198a3c33SNelio Laranjeiro priv->intr_handle.fd = 0; 108236351ea3SFerruh Yigit priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 1083f8b9a3baSXueming Li priv->intr_handle_socket.fd = 0; 1084f8b9a3baSXueming Li priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN; 1085198a3c33SNelio Laranjeiro } 1086198a3c33SNelio Laranjeiro 1087198a3c33SNelio Laranjeiro /** 1088198a3c33SNelio Laranjeiro * Install interrupt handler. 1089198a3c33SNelio Laranjeiro * 1090198a3c33SNelio Laranjeiro * @param dev 1091af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1092198a3c33SNelio Laranjeiro */ 1093198a3c33SNelio Laranjeiro void 1094af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev) 1095198a3c33SNelio Laranjeiro { 1096af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 1097*a6d83b6aSNélio Laranjeiro int ret; 1098*a6d83b6aSNélio Laranjeiro int flags; 1099198a3c33SNelio Laranjeiro 1100198a3c33SNelio Laranjeiro assert(priv->ctx->async_fd > 0); 1101198a3c33SNelio Laranjeiro flags = fcntl(priv->ctx->async_fd, F_GETFL); 1102*a6d83b6aSNélio Laranjeiro ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); 1103*a6d83b6aSNélio Laranjeiro if (ret) { 1104198a3c33SNelio Laranjeiro INFO("failed to change file descriptor async event queue"); 1105198a3c33SNelio Laranjeiro dev->data->dev_conf.intr_conf.lsc = 0; 11067d7d7ad1SMatan Azrad dev->data->dev_conf.intr_conf.rmv = 0; 1107f8b9a3baSXueming Li } 1108f8b9a3baSXueming Li if (dev->data->dev_conf.intr_conf.lsc || 1109f8b9a3baSXueming Li dev->data->dev_conf.intr_conf.rmv) { 1110198a3c33SNelio Laranjeiro priv->intr_handle.fd = priv->ctx->async_fd; 1111198a3c33SNelio Laranjeiro priv->intr_handle.type = RTE_INTR_HANDLE_EXT; 1112198a3c33SNelio Laranjeiro rte_intr_callback_register(&priv->intr_handle, 1113f8b9a3baSXueming Li mlx5_dev_interrupt_handler, dev); 1114f8b9a3baSXueming Li } 1115*a6d83b6aSNélio Laranjeiro ret = mlx5_socket_init(dev); 1116*a6d83b6aSNélio Laranjeiro if (ret) 1117*a6d83b6aSNélio Laranjeiro ERROR("cannot initialise socket: %s", strerror(rte_errno)); 1118*a6d83b6aSNélio Laranjeiro else if (priv->primary_socket) { 1119f8b9a3baSXueming Li priv->intr_handle_socket.fd = priv->primary_socket; 1120f8b9a3baSXueming Li priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT; 1121f8b9a3baSXueming Li rte_intr_callback_register(&priv->intr_handle_socket, 1122f8b9a3baSXueming Li mlx5_dev_handler_socket, dev); 1123198a3c33SNelio Laranjeiro } 1124198a3c33SNelio Laranjeiro } 112562072098SOr Ami 112662072098SOr Ami /** 112762072098SOr Ami * DPDK callback to bring the link DOWN. 112862072098SOr Ami * 112962072098SOr Ami * @param dev 113062072098SOr Ami * Pointer to Ethernet device structure. 113162072098SOr Ami * 113262072098SOr Ami * @return 1133*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 113462072098SOr Ami */ 113562072098SOr Ami int 113662072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev) 113762072098SOr Ami { 1138af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP); 113962072098SOr Ami } 114062072098SOr Ami 114162072098SOr Ami /** 114262072098SOr Ami * DPDK callback to bring the link UP. 114362072098SOr Ami * 114462072098SOr Ami * @param dev 114562072098SOr Ami * Pointer to Ethernet device structure. 114662072098SOr Ami * 114762072098SOr Ami * @return 1148*a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 114962072098SOr Ami */ 115062072098SOr Ami int 115162072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev) 115262072098SOr Ami { 1153af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, IFF_UP); 115462072098SOr Ami } 1155a48deadaSOr Ami 1156a48deadaSOr Ami /** 1157cdab90cbSNélio Laranjeiro * Configure the TX function to use. 1158cdab90cbSNélio Laranjeiro * 1159aee1b165SXueming Li * @param dev 1160af4f09f2SNélio Laranjeiro * Pointer to private data structure. 11611cfa649bSShahaf Shuler * 11621cfa649bSShahaf Shuler * @return 11631cfa649bSShahaf Shuler * Pointer to selected Tx burst function. 1164cdab90cbSNélio Laranjeiro */ 11651cfa649bSShahaf Shuler eth_tx_burst_t 1166af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev) 1167cdab90cbSNélio Laranjeiro { 1168af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 11691cfa649bSShahaf Shuler eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst; 11707fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 1171dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 1172dbccb4cdSShahaf Shuler int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO | 1173dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 1174dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_GRE_TNL_TSO)); 1175dbccb4cdSShahaf Shuler int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT); 11761cfa649bSShahaf Shuler 1177aee1b165SXueming Li assert(priv != NULL); 1178230189d9SNélio Laranjeiro /* Select appropriate TX function. */ 1179dbccb4cdSShahaf Shuler if (vlan_insert || tso) 1180dbccb4cdSShahaf Shuler return tx_pkt_burst; 11817fe24446SShahaf Shuler if (config->mps == MLX5_MPW_ENHANCED) { 1182af4f09f2SNélio Laranjeiro if (mlx5_check_vec_tx_support(dev) > 0) { 1183af4f09f2SNélio Laranjeiro if (mlx5_check_raw_vec_tx_support(dev) > 0) 11841cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_raw_vec; 11856cb559d6SYongseok Koh else 11861cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_vec; 11876cb559d6SYongseok Koh DEBUG("selected Enhanced MPW TX vectorized function"); 11886cb559d6SYongseok Koh } else { 11891cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_empw; 11906ce84bd8SYongseok Koh DEBUG("selected Enhanced MPW TX function"); 11916cb559d6SYongseok Koh } 11927fe24446SShahaf Shuler } else if (config->mps && (config->txq_inline > 0)) { 11931cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw_inline; 1194230189d9SNélio Laranjeiro DEBUG("selected MPW inline TX function"); 11957fe24446SShahaf Shuler } else if (config->mps) { 11961cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw; 1197230189d9SNélio Laranjeiro DEBUG("selected MPW TX function"); 11982a66cf37SYaacov Hazan } 11991cfa649bSShahaf Shuler return tx_pkt_burst; 1200cdab90cbSNélio Laranjeiro } 1201cdab90cbSNélio Laranjeiro 1202cdab90cbSNélio Laranjeiro /** 1203cdab90cbSNélio Laranjeiro * Configure the RX function to use. 1204cdab90cbSNélio Laranjeiro * 1205aee1b165SXueming Li * @param dev 1206af4f09f2SNélio Laranjeiro * Pointer to private data structure. 12071cfa649bSShahaf Shuler * 12081cfa649bSShahaf Shuler * @return 12091cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 1210cdab90cbSNélio Laranjeiro */ 12111cfa649bSShahaf Shuler eth_rx_burst_t 1212af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 1213cdab90cbSNélio Laranjeiro { 12141cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 12151cfa649bSShahaf Shuler 1216af4f09f2SNélio Laranjeiro assert(dev != NULL); 1217af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 12181cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 12196cb559d6SYongseok Koh DEBUG("selected RX vectorized function"); 1220cdab90cbSNélio Laranjeiro } 12211cfa649bSShahaf Shuler return rx_pkt_burst; 12226cb559d6SYongseok Koh } 1223d3e0f392SMatan Azrad 1224d3e0f392SMatan Azrad /** 1225d3e0f392SMatan Azrad * Check if mlx5 device was removed. 1226d3e0f392SMatan Azrad * 1227d3e0f392SMatan Azrad * @param dev 1228d3e0f392SMatan Azrad * Pointer to Ethernet device structure. 1229d3e0f392SMatan Azrad * 1230d3e0f392SMatan Azrad * @return 1231d3e0f392SMatan Azrad * 1 when device is removed, otherwise 0. 1232d3e0f392SMatan Azrad */ 1233d3e0f392SMatan Azrad int 1234d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev) 1235d3e0f392SMatan Azrad { 1236d3e0f392SMatan Azrad struct ibv_device_attr device_attr; 1237d3e0f392SMatan Azrad struct priv *priv = dev->data->dev_private; 1238d3e0f392SMatan Azrad 12390e83b8e5SNelio Laranjeiro if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO) 1240d3e0f392SMatan Azrad return 1; 1241d3e0f392SMatan Azrad return 0; 1242d3e0f392SMatan Azrad } 1243