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 * 98*af4f09f2SNélio Laranjeiro * @param[in] dev 99*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 100771fa900SAdrien Mazarguil * @param[out] ifname 101771fa900SAdrien Mazarguil * Interface name output buffer. 102771fa900SAdrien Mazarguil * 103771fa900SAdrien Mazarguil * @return 104771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 105771fa900SAdrien Mazarguil */ 106771fa900SAdrien Mazarguil int 107*af4f09f2SNélio Laranjeiro mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) 108771fa900SAdrien Mazarguil { 109*af4f09f2SNé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); 120771fa900SAdrien Mazarguil if (dir == NULL) 121771fa900SAdrien Mazarguil return -1; 122771fa900SAdrien Mazarguil } 123771fa900SAdrien Mazarguil while ((dent = readdir(dir)) != NULL) { 124771fa900SAdrien Mazarguil char *name = dent->d_name; 125771fa900SAdrien Mazarguil FILE *file; 126771fa900SAdrien Mazarguil unsigned int dev_port; 127771fa900SAdrien Mazarguil int r; 128771fa900SAdrien Mazarguil 129771fa900SAdrien Mazarguil if ((name[0] == '.') && 130771fa900SAdrien Mazarguil ((name[1] == '\0') || 131771fa900SAdrien Mazarguil ((name[1] == '.') && (name[2] == '\0')))) 132771fa900SAdrien Mazarguil continue; 133771fa900SAdrien Mazarguil 134771fa900SAdrien Mazarguil MKSTR(path, "%s/device/net/%s/%s", 13587ec44ceSXueming Li priv->ibdev_path, name, 136771fa900SAdrien Mazarguil (dev_type ? "dev_id" : "dev_port")); 137771fa900SAdrien Mazarguil 138771fa900SAdrien Mazarguil file = fopen(path, "rb"); 139771fa900SAdrien Mazarguil if (file == NULL) { 140771fa900SAdrien Mazarguil if (errno != ENOENT) 141771fa900SAdrien Mazarguil continue; 142771fa900SAdrien Mazarguil /* 143771fa900SAdrien Mazarguil * Switch to dev_id when dev_port does not exist as 144771fa900SAdrien Mazarguil * is the case with Linux kernel versions < 3.15. 145771fa900SAdrien Mazarguil */ 146771fa900SAdrien Mazarguil try_dev_id: 147771fa900SAdrien Mazarguil match[0] = '\0'; 148771fa900SAdrien Mazarguil if (dev_type) 149771fa900SAdrien Mazarguil break; 150771fa900SAdrien Mazarguil dev_type = 1; 151771fa900SAdrien Mazarguil dev_port_prev = ~0u; 152771fa900SAdrien Mazarguil rewinddir(dir); 153771fa900SAdrien Mazarguil continue; 154771fa900SAdrien Mazarguil } 155771fa900SAdrien Mazarguil r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); 156771fa900SAdrien Mazarguil fclose(file); 157771fa900SAdrien Mazarguil if (r != 1) 158771fa900SAdrien Mazarguil continue; 159771fa900SAdrien Mazarguil /* 160771fa900SAdrien Mazarguil * Switch to dev_id when dev_port returns the same value for 161771fa900SAdrien Mazarguil * all ports. May happen when using a MOFED release older than 162771fa900SAdrien Mazarguil * 3.0 with a Linux kernel >= 3.15. 163771fa900SAdrien Mazarguil */ 164771fa900SAdrien Mazarguil if (dev_port == dev_port_prev) 165771fa900SAdrien Mazarguil goto try_dev_id; 166771fa900SAdrien Mazarguil dev_port_prev = dev_port; 167771fa900SAdrien Mazarguil if (dev_port == (priv->port - 1u)) 168771fa900SAdrien Mazarguil snprintf(match, sizeof(match), "%s", name); 169771fa900SAdrien Mazarguil } 170771fa900SAdrien Mazarguil closedir(dir); 171771fa900SAdrien Mazarguil if (match[0] == '\0') 172771fa900SAdrien Mazarguil return -1; 173771fa900SAdrien Mazarguil strncpy(*ifname, match, sizeof(*ifname)); 174771fa900SAdrien Mazarguil return 0; 175771fa900SAdrien Mazarguil } 176771fa900SAdrien Mazarguil 177771fa900SAdrien Mazarguil /** 178771fa900SAdrien Mazarguil * Perform ifreq ioctl() on associated Ethernet device. 179771fa900SAdrien Mazarguil * 180*af4f09f2SNélio Laranjeiro * @param[in] dev 181*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 182771fa900SAdrien Mazarguil * @param req 183771fa900SAdrien Mazarguil * Request number to pass to ioctl(). 184771fa900SAdrien Mazarguil * @param[out] ifr 185771fa900SAdrien Mazarguil * Interface request structure output buffer. 186771fa900SAdrien Mazarguil * 187771fa900SAdrien Mazarguil * @return 188771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 189771fa900SAdrien Mazarguil */ 190771fa900SAdrien Mazarguil int 191*af4f09f2SNélio Laranjeiro mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr) 192771fa900SAdrien Mazarguil { 193771fa900SAdrien Mazarguil int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 194771fa900SAdrien Mazarguil int ret = -1; 195771fa900SAdrien Mazarguil 196771fa900SAdrien Mazarguil if (sock == -1) 197771fa900SAdrien Mazarguil return ret; 198*af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(dev, &ifr->ifr_name) == 0) 199771fa900SAdrien Mazarguil ret = ioctl(sock, req, ifr); 200771fa900SAdrien Mazarguil close(sock); 201771fa900SAdrien Mazarguil return ret; 202771fa900SAdrien Mazarguil } 203771fa900SAdrien Mazarguil 204771fa900SAdrien Mazarguil /** 205771fa900SAdrien Mazarguil * Get device MTU. 206771fa900SAdrien Mazarguil * 207*af4f09f2SNélio Laranjeiro * @param dev 208*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 209771fa900SAdrien Mazarguil * @param[out] mtu 210771fa900SAdrien Mazarguil * MTU value output buffer. 211771fa900SAdrien Mazarguil * 212771fa900SAdrien Mazarguil * @return 213771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 214771fa900SAdrien Mazarguil */ 215771fa900SAdrien Mazarguil int 216*af4f09f2SNélio Laranjeiro mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 217771fa900SAdrien Mazarguil { 218fc40db99SAdrien Mazarguil struct ifreq request; 219*af4f09f2SNélio Laranjeiro int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request); 220771fa900SAdrien Mazarguil 221fc40db99SAdrien Mazarguil if (ret) 222fc40db99SAdrien Mazarguil return ret; 223fc40db99SAdrien Mazarguil *mtu = request.ifr_mtu; 224859081d3SShahaf Shuler return 0; 225859081d3SShahaf Shuler } 226859081d3SShahaf Shuler 227859081d3SShahaf Shuler /** 228cf37ca95SAdrien Mazarguil * Set device MTU. 229cf37ca95SAdrien Mazarguil * 230*af4f09f2SNélio Laranjeiro * @param dev 231*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 232cf37ca95SAdrien Mazarguil * @param mtu 233cf37ca95SAdrien Mazarguil * MTU value to set. 234cf37ca95SAdrien Mazarguil * 235cf37ca95SAdrien Mazarguil * @return 236cf37ca95SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 237cf37ca95SAdrien Mazarguil */ 238cf37ca95SAdrien Mazarguil static int 239*af4f09f2SNélio Laranjeiro mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 240cf37ca95SAdrien Mazarguil { 241fc40db99SAdrien Mazarguil struct ifreq request = { .ifr_mtu = mtu, }; 242f3b492d7SAdrien Mazarguil 243*af4f09f2SNélio Laranjeiro return mlx5_ifreq(dev, SIOCSIFMTU, &request); 244cf37ca95SAdrien Mazarguil } 245cf37ca95SAdrien Mazarguil 246cf37ca95SAdrien Mazarguil /** 247771fa900SAdrien Mazarguil * Set device flags. 248771fa900SAdrien Mazarguil * 249*af4f09f2SNélio Laranjeiro * @param dev 250*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 251771fa900SAdrien Mazarguil * @param keep 252771fa900SAdrien Mazarguil * Bitmask for flags that must remain untouched. 253771fa900SAdrien Mazarguil * @param flags 254771fa900SAdrien Mazarguil * Bitmask for flags to modify. 255771fa900SAdrien Mazarguil * 256771fa900SAdrien Mazarguil * @return 257771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 258771fa900SAdrien Mazarguil */ 259771fa900SAdrien Mazarguil int 260*af4f09f2SNélio Laranjeiro mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags) 261771fa900SAdrien Mazarguil { 262fc40db99SAdrien Mazarguil struct ifreq request; 263*af4f09f2SNélio Laranjeiro int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request); 264771fa900SAdrien Mazarguil 265fc40db99SAdrien Mazarguil if (ret) 266fc40db99SAdrien Mazarguil return ret; 267fc40db99SAdrien Mazarguil request.ifr_flags &= keep; 268fc40db99SAdrien Mazarguil request.ifr_flags |= flags & ~keep; 269*af4f09f2SNélio Laranjeiro return mlx5_ifreq(dev, SIOCSIFFLAGS, &request); 270771fa900SAdrien Mazarguil } 271771fa900SAdrien Mazarguil 272771fa900SAdrien Mazarguil /** 2737b2423cdSNélio Laranjeiro * DPDK callback for Ethernet device configuration. 274e60fbd5bSAdrien Mazarguil * 275e60fbd5bSAdrien Mazarguil * @param dev 276e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 277e60fbd5bSAdrien Mazarguil * 278e60fbd5bSAdrien Mazarguil * @return 2797b2423cdSNélio Laranjeiro * 0 on success, negative errno value on failure. 280e60fbd5bSAdrien Mazarguil */ 2817b2423cdSNélio Laranjeiro int 2827b2423cdSNélio Laranjeiro mlx5_dev_configure(struct rte_eth_dev *dev) 283e60fbd5bSAdrien Mazarguil { 284e60fbd5bSAdrien Mazarguil struct priv *priv = dev->data->dev_private; 285e60fbd5bSAdrien Mazarguil unsigned int rxqs_n = dev->data->nb_rx_queues; 286e60fbd5bSAdrien Mazarguil unsigned int txqs_n = dev->data->nb_tx_queues; 287634efbc2SNelio Laranjeiro unsigned int i; 288634efbc2SNelio Laranjeiro unsigned int j; 289634efbc2SNelio Laranjeiro unsigned int reta_idx_n; 29029c1d8bbSNélio Laranjeiro const uint8_t use_app_rss_key = 29121e3a974SShahaf Shuler !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; 292*af4f09f2SNélio Laranjeiro uint64_t supp_tx_offloads = mlx5_get_tx_port_offloads(dev); 293dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 29417b843ebSShahaf Shuler uint64_t supp_rx_offloads = 295*af4f09f2SNélio Laranjeiro (mlx5_get_rx_port_offloads() | 296*af4f09f2SNélio Laranjeiro mlx5_get_rx_queue_offloads(dev)); 29717b843ebSShahaf Shuler uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads; 298e60fbd5bSAdrien Mazarguil 299dbccb4cdSShahaf Shuler if ((tx_offloads & supp_tx_offloads) != tx_offloads) { 300dbccb4cdSShahaf Shuler ERROR("Some Tx offloads are not supported " 301dbccb4cdSShahaf Shuler "requested 0x%" PRIx64 " supported 0x%" PRIx64, 302dbccb4cdSShahaf Shuler tx_offloads, supp_tx_offloads); 303dbccb4cdSShahaf Shuler return ENOTSUP; 304dbccb4cdSShahaf Shuler } 30517b843ebSShahaf Shuler if ((rx_offloads & supp_rx_offloads) != rx_offloads) { 30617b843ebSShahaf Shuler ERROR("Some Rx offloads are not supported " 30717b843ebSShahaf Shuler "requested 0x%" PRIx64 " supported 0x%" PRIx64, 30817b843ebSShahaf Shuler rx_offloads, supp_rx_offloads); 30917b843ebSShahaf Shuler return ENOTSUP; 31017b843ebSShahaf Shuler } 31129c1d8bbSNélio Laranjeiro if (use_app_rss_key && 31229c1d8bbSNélio Laranjeiro (dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len != 31329c1d8bbSNélio Laranjeiro rss_hash_default_key_len)) { 31429c1d8bbSNélio Laranjeiro /* MLX5 RSS only support 40bytes key. */ 31529c1d8bbSNélio Laranjeiro return EINVAL; 31629c1d8bbSNélio Laranjeiro } 31729c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key = 31829c1d8bbSNélio Laranjeiro rte_realloc(priv->rss_conf.rss_key, 31929c1d8bbSNélio Laranjeiro rss_hash_default_key_len, 0); 32029c1d8bbSNélio Laranjeiro if (!priv->rss_conf.rss_key) { 32129c1d8bbSNélio Laranjeiro ERROR("cannot allocate RSS hash key memory (%u)", rxqs_n); 32229c1d8bbSNélio Laranjeiro return ENOMEM; 32329c1d8bbSNélio Laranjeiro } 32429c1d8bbSNélio Laranjeiro memcpy(priv->rss_conf.rss_key, 32529c1d8bbSNélio Laranjeiro use_app_rss_key ? 32629c1d8bbSNélio Laranjeiro dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : 32729c1d8bbSNélio Laranjeiro rss_hash_default_key, 32829c1d8bbSNélio Laranjeiro rss_hash_default_key_len); 32929c1d8bbSNélio Laranjeiro priv->rss_conf.rss_key_len = rss_hash_default_key_len; 33029c1d8bbSNélio Laranjeiro priv->rss_conf.rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 331e60fbd5bSAdrien Mazarguil priv->rxqs = (void *)dev->data->rx_queues; 332e60fbd5bSAdrien Mazarguil priv->txqs = (void *)dev->data->tx_queues; 333e60fbd5bSAdrien Mazarguil if (txqs_n != priv->txqs_n) { 334e60fbd5bSAdrien Mazarguil INFO("%p: TX queues number update: %u -> %u", 335e60fbd5bSAdrien Mazarguil (void *)dev, priv->txqs_n, txqs_n); 336e60fbd5bSAdrien Mazarguil priv->txqs_n = txqs_n; 337e60fbd5bSAdrien Mazarguil } 3387fe24446SShahaf Shuler if (rxqs_n > priv->config.ind_table_max_size) { 339634efbc2SNelio Laranjeiro ERROR("cannot handle this many RX queues (%u)", rxqs_n); 340634efbc2SNelio Laranjeiro return EINVAL; 341634efbc2SNelio Laranjeiro } 342e60fbd5bSAdrien Mazarguil if (rxqs_n == priv->rxqs_n) 343e60fbd5bSAdrien Mazarguil return 0; 344e60fbd5bSAdrien Mazarguil INFO("%p: RX queues number update: %u -> %u", 345e60fbd5bSAdrien Mazarguil (void *)dev, priv->rxqs_n, rxqs_n); 346e60fbd5bSAdrien Mazarguil priv->rxqs_n = rxqs_n; 347634efbc2SNelio Laranjeiro /* If the requested number of RX queues is not a power of two, use the 348634efbc2SNelio Laranjeiro * maximum indirection table size for better balancing. 349634efbc2SNelio Laranjeiro * The result is always rounded to the next power of two. */ 350634efbc2SNelio Laranjeiro reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ? 3517fe24446SShahaf Shuler priv->config.ind_table_max_size : 352634efbc2SNelio Laranjeiro rxqs_n)); 353*af4f09f2SNélio Laranjeiro if (mlx5_rss_reta_index_resize(dev, reta_idx_n)) 354634efbc2SNelio Laranjeiro return ENOMEM; 355634efbc2SNelio Laranjeiro /* When the number of RX queues is not a power of two, the remaining 356634efbc2SNelio Laranjeiro * table entries are padded with reused WQs and hashes are not spread 357634efbc2SNelio Laranjeiro * uniformly. */ 358634efbc2SNelio Laranjeiro for (i = 0, j = 0; (i != reta_idx_n); ++i) { 359634efbc2SNelio Laranjeiro (*priv->reta_idx)[i] = j; 360634efbc2SNelio Laranjeiro if (++j == rxqs_n) 361634efbc2SNelio Laranjeiro j = 0; 362634efbc2SNelio Laranjeiro } 363e60fbd5bSAdrien Mazarguil return 0; 364e60fbd5bSAdrien Mazarguil 365e60fbd5bSAdrien Mazarguil } 366e60fbd5bSAdrien Mazarguil 367e60fbd5bSAdrien Mazarguil /** 368e60fbd5bSAdrien Mazarguil * DPDK callback to get information about the device. 369e60fbd5bSAdrien Mazarguil * 370e60fbd5bSAdrien Mazarguil * @param dev 371e60fbd5bSAdrien Mazarguil * Pointer to Ethernet device structure. 372e60fbd5bSAdrien Mazarguil * @param[out] info 373e60fbd5bSAdrien Mazarguil * Info structure output buffer. 374e60fbd5bSAdrien Mazarguil */ 375e60fbd5bSAdrien Mazarguil void 376e60fbd5bSAdrien Mazarguil mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 377e60fbd5bSAdrien Mazarguil { 37801d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 3797fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 380e60fbd5bSAdrien Mazarguil unsigned int max; 381e60fbd5bSAdrien Mazarguil char ifname[IF_NAMESIZE]; 382e60fbd5bSAdrien Mazarguil 383c0802544SFerruh Yigit info->pci_dev = RTE_ETH_DEV_TO_PCI(dev); 384e60fbd5bSAdrien Mazarguil /* FIXME: we should ask the device for these values. */ 385e60fbd5bSAdrien Mazarguil info->min_rx_bufsize = 32; 386e60fbd5bSAdrien Mazarguil info->max_rx_pktlen = 65536; 387e60fbd5bSAdrien Mazarguil /* 388e60fbd5bSAdrien Mazarguil * Since we need one CQ per QP, the limit is the minimum number 389e60fbd5bSAdrien Mazarguil * between the two values. 390e60fbd5bSAdrien Mazarguil */ 39143e9d979SShachar Beiser max = RTE_MIN(priv->device_attr.orig_attr.max_cq, 39243e9d979SShachar Beiser priv->device_attr.orig_attr.max_qp); 393e60fbd5bSAdrien Mazarguil /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ 394e60fbd5bSAdrien Mazarguil if (max >= 65535) 395e60fbd5bSAdrien Mazarguil max = 65535; 396e60fbd5bSAdrien Mazarguil info->max_rx_queues = max; 397e60fbd5bSAdrien Mazarguil info->max_tx_queues = max; 3980497ddaaSYaacov Hazan info->max_mac_addrs = RTE_DIM(priv->mac); 399*af4f09f2SNélio Laranjeiro info->rx_queue_offload_capa = mlx5_get_rx_queue_offloads(dev); 400*af4f09f2SNélio Laranjeiro info->rx_offload_capa = (mlx5_get_rx_port_offloads() | 40117b843ebSShahaf Shuler info->rx_queue_offload_capa); 402*af4f09f2SNélio Laranjeiro info->tx_offload_capa = mlx5_get_tx_port_offloads(dev); 403*af4f09f2SNélio Laranjeiro if (mlx5_get_ifname(dev, &ifname) == 0) 404e60fbd5bSAdrien Mazarguil info->if_index = if_nametoindex(ifname); 405d365210eSYongseok Koh info->reta_size = priv->reta_idx_n ? 4067fe24446SShahaf Shuler priv->reta_idx_n : config->ind_table_max_size; 40729c1d8bbSNélio Laranjeiro info->hash_key_size = priv->rss_conf.rss_key_len; 40875ef62a9SNélio Laranjeiro info->speed_capa = priv->link_speed_capa; 409b233b027SShahaf Shuler info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK; 410e60fbd5bSAdrien Mazarguil } 411e60fbd5bSAdrien Mazarguil 412fb732b0aSNélio Laranjeiro /** 413fb732b0aSNélio Laranjeiro * Get supported packet types. 414fb732b0aSNélio Laranjeiro * 415fb732b0aSNélio Laranjeiro * @param dev 416fb732b0aSNélio Laranjeiro * Pointer to Ethernet device structure. 417fb732b0aSNélio Laranjeiro * 418fb732b0aSNélio Laranjeiro * @return 419fb732b0aSNélio Laranjeiro * A pointer to the supported Packet types array. 420fb732b0aSNélio Laranjeiro */ 42178a38edfSJianfeng Tan const uint32_t * 42278a38edfSJianfeng Tan mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) 42378a38edfSJianfeng Tan { 42478a38edfSJianfeng Tan static const uint32_t ptypes[] = { 42578a38edfSJianfeng Tan /* refers to rxq_cq_to_pkt_type() */ 426ea16068cSYongseok Koh RTE_PTYPE_L2_ETHER, 427c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, 428c4ba5434SNélio Laranjeiro RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, 429ea16068cSYongseok Koh RTE_PTYPE_L4_NONFRAG, 430ea16068cSYongseok Koh RTE_PTYPE_L4_FRAG, 431ea16068cSYongseok Koh RTE_PTYPE_L4_TCP, 432ea16068cSYongseok Koh RTE_PTYPE_L4_UDP, 433c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, 434c4ba5434SNélio Laranjeiro RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, 435ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_NONFRAG, 436ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_FRAG, 437ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_TCP, 438ea16068cSYongseok Koh RTE_PTYPE_INNER_L4_UDP, 43978a38edfSJianfeng Tan RTE_PTYPE_UNKNOWN 44078a38edfSJianfeng Tan }; 44178a38edfSJianfeng Tan 4426cb559d6SYongseok Koh if (dev->rx_pkt_burst == mlx5_rx_burst || 4436cb559d6SYongseok Koh dev->rx_pkt_burst == mlx5_rx_burst_vec) 44478a38edfSJianfeng Tan return ptypes; 44578a38edfSJianfeng Tan return NULL; 44678a38edfSJianfeng Tan } 44778a38edfSJianfeng Tan 448e60fbd5bSAdrien Mazarguil /** 4492c960a51SMatthieu Ternisien d'Ouville * DPDK callback to retrieve physical link information. 450cb8faed7SAdrien Mazarguil * 451cb8faed7SAdrien Mazarguil * @param dev 452cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 453fb732b0aSNélio Laranjeiro * 454fb732b0aSNélio Laranjeiro * @return 455fb732b0aSNélio Laranjeiro * 0 on success, -1 on error. 456cb8faed7SAdrien Mazarguil */ 45718840871SNélio Laranjeiro static int 45856f08e16SNélio Laranjeiro mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev) 459cb8faed7SAdrien Mazarguil { 46001d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 461cb8faed7SAdrien Mazarguil struct ethtool_cmd edata = { 46275ef62a9SNélio Laranjeiro .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */ 463cb8faed7SAdrien Mazarguil }; 464cb8faed7SAdrien Mazarguil struct ifreq ifr; 465cb8faed7SAdrien Mazarguil struct rte_eth_link dev_link; 466cb8faed7SAdrien Mazarguil int link_speed = 0; 467cb8faed7SAdrien Mazarguil 468*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr)) { 469cb8faed7SAdrien Mazarguil WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno)); 470cb8faed7SAdrien Mazarguil return -1; 471cb8faed7SAdrien Mazarguil } 472cb8faed7SAdrien Mazarguil memset(&dev_link, 0, sizeof(dev_link)); 473cb8faed7SAdrien Mazarguil dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 474cb8faed7SAdrien Mazarguil (ifr.ifr_flags & IFF_RUNNING)); 475d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)&edata; 476*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCETHTOOL, &ifr)) { 477cb8faed7SAdrien Mazarguil WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s", 478cb8faed7SAdrien Mazarguil strerror(errno)); 479cb8faed7SAdrien Mazarguil return -1; 480cb8faed7SAdrien Mazarguil } 481cb8faed7SAdrien Mazarguil link_speed = ethtool_cmd_speed(&edata); 482cb8faed7SAdrien Mazarguil if (link_speed == -1) 483cb8faed7SAdrien Mazarguil dev_link.link_speed = 0; 484cb8faed7SAdrien Mazarguil else 485cb8faed7SAdrien Mazarguil dev_link.link_speed = link_speed; 48675ef62a9SNélio Laranjeiro priv->link_speed_capa = 0; 48775ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_Autoneg) 48875ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 48975ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_1000baseT_Full | 49075ef62a9SNélio Laranjeiro SUPPORTED_1000baseKX_Full)) 49175ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 49275ef62a9SNélio Laranjeiro if (edata.supported & SUPPORTED_10000baseKR_Full) 49375ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 49475ef62a9SNélio Laranjeiro if (edata.supported & (SUPPORTED_40000baseKR4_Full | 49575ef62a9SNélio Laranjeiro SUPPORTED_40000baseCR4_Full | 49675ef62a9SNélio Laranjeiro SUPPORTED_40000baseSR4_Full | 49775ef62a9SNélio Laranjeiro SUPPORTED_40000baseLR4_Full)) 49875ef62a9SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 499cb8faed7SAdrien Mazarguil dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? 500cb8faed7SAdrien Mazarguil ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 50182113036SMarc Sune dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 50282113036SMarc Sune ETH_LINK_SPEED_FIXED); 503cb8faed7SAdrien Mazarguil if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { 504cb8faed7SAdrien Mazarguil /* Link status changed. */ 505cb8faed7SAdrien Mazarguil dev->data->dev_link = dev_link; 506cb8faed7SAdrien Mazarguil return 0; 507cb8faed7SAdrien Mazarguil } 508cb8faed7SAdrien Mazarguil /* Link status is still the same. */ 509cb8faed7SAdrien Mazarguil return -1; 510cb8faed7SAdrien Mazarguil } 511cb8faed7SAdrien Mazarguil 512cb8faed7SAdrien Mazarguil /** 5133a49ffe3SShahaf Shuler * Retrieve physical link information (unlocked version using new ioctl). 51418840871SNélio Laranjeiro * 51518840871SNélio Laranjeiro * @param dev 51618840871SNélio Laranjeiro * Pointer to Ethernet device structure. 517fb732b0aSNélio Laranjeiro * 518fb732b0aSNélio Laranjeiro * @return 519fb732b0aSNélio Laranjeiro * 0 on success, -1 on error. 52018840871SNélio Laranjeiro */ 52118840871SNélio Laranjeiro static int 52256f08e16SNélio Laranjeiro mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev) 52318840871SNélio Laranjeiro { 52401d79216SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 52537a4406cSNélio Laranjeiro struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS }; 52618840871SNélio Laranjeiro struct ifreq ifr; 52718840871SNélio Laranjeiro struct rte_eth_link dev_link; 52818840871SNélio Laranjeiro uint64_t sc; 52918840871SNélio Laranjeiro 530*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr)) { 53118840871SNélio Laranjeiro WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno)); 53218840871SNélio Laranjeiro return -1; 53318840871SNélio Laranjeiro } 53418840871SNélio Laranjeiro memset(&dev_link, 0, sizeof(dev_link)); 53518840871SNélio Laranjeiro dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && 53618840871SNélio Laranjeiro (ifr.ifr_flags & IFF_RUNNING)); 53737a4406cSNélio Laranjeiro ifr.ifr_data = (void *)&gcmd; 538*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCETHTOOL, &ifr)) { 53918840871SNélio Laranjeiro DEBUG("ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS) failed: %s", 54018840871SNélio Laranjeiro strerror(errno)); 54118840871SNélio Laranjeiro return -1; 54218840871SNélio Laranjeiro } 54337a4406cSNélio Laranjeiro gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords; 54437a4406cSNélio Laranjeiro 54537a4406cSNélio Laranjeiro alignas(struct ethtool_link_settings) 54637a4406cSNélio Laranjeiro uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) + 54737a4406cSNélio Laranjeiro sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3]; 54837a4406cSNélio Laranjeiro struct ethtool_link_settings *ecmd = (void *)data; 54937a4406cSNélio Laranjeiro 55037a4406cSNélio Laranjeiro *ecmd = gcmd; 55137a4406cSNélio Laranjeiro ifr.ifr_data = (void *)ecmd; 552*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCETHTOOL, &ifr)) { 553ef09a7fcSGowrishankar Muthukrishnan DEBUG("ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS) failed: %s", 554ef09a7fcSGowrishankar Muthukrishnan strerror(errno)); 555ef09a7fcSGowrishankar Muthukrishnan return -1; 556ef09a7fcSGowrishankar Muthukrishnan } 55790260d57SNélio Laranjeiro dev_link.link_speed = ecmd->speed; 55890260d57SNélio Laranjeiro sc = ecmd->link_mode_masks[0] | 55990260d57SNélio Laranjeiro ((uint64_t)ecmd->link_mode_masks[1] << 32); 56018840871SNélio Laranjeiro priv->link_speed_capa = 0; 561b113cb5eSEdward Makarov if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT)) 56218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG; 563b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) | 564b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT))) 56518840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_1G; 566b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) | 567b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) | 568b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT))) 56918840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_10G; 570b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) | 571b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT))) 57218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_20G; 573b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) | 574b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) | 575b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) | 576b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT))) 57718840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_40G; 578b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) | 579b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) | 580b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) | 581b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT))) 58218840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_56G; 583b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) | 584b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) | 585b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT))) 58618840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_25G; 587b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) | 588b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT))) 58918840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_50G; 590b113cb5eSEdward Makarov if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) | 591b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) | 592b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) | 593b113cb5eSEdward Makarov MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT))) 59418840871SNélio Laranjeiro priv->link_speed_capa |= ETH_LINK_SPEED_100G; 59590260d57SNélio Laranjeiro dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ? 59618840871SNélio Laranjeiro ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); 59718840871SNélio Laranjeiro dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & 59818840871SNélio Laranjeiro ETH_LINK_SPEED_FIXED); 59918840871SNélio Laranjeiro if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { 60018840871SNélio Laranjeiro /* Link status changed. */ 60118840871SNélio Laranjeiro dev->data->dev_link = dev_link; 60218840871SNélio Laranjeiro return 0; 60318840871SNélio Laranjeiro } 60418840871SNélio Laranjeiro /* Link status is still the same. */ 60518840871SNélio Laranjeiro return -1; 60618840871SNélio Laranjeiro } 60718840871SNélio Laranjeiro 60818840871SNélio Laranjeiro /** 609c7bf6225SYongseok Koh * Enable receiving and transmitting traffic. 610c7bf6225SYongseok Koh * 611*af4f09f2SNélio Laranjeiro * @param dev 612*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 613c7bf6225SYongseok Koh */ 614c7bf6225SYongseok Koh static void 615*af4f09f2SNélio Laranjeiro mlx5_link_start(struct rte_eth_dev *dev) 616c7bf6225SYongseok Koh { 617*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 618c7bf6225SYongseok Koh int err; 619c7bf6225SYongseok Koh 620*af4f09f2SNélio Laranjeiro dev->tx_pkt_burst = mlx5_select_tx_function(dev); 621*af4f09f2SNélio Laranjeiro dev->rx_pkt_burst = mlx5_select_rx_function(dev); 622*af4f09f2SNélio Laranjeiro err = mlx5_traffic_enable(dev); 623c7bf6225SYongseok Koh if (err) 624c7bf6225SYongseok Koh ERROR("%p: error occurred while configuring control flows: %s", 625*af4f09f2SNélio Laranjeiro (void *)dev, strerror(err)); 626*af4f09f2SNélio Laranjeiro err = mlx5_flow_start(dev, &priv->flows); 627c7bf6225SYongseok Koh if (err) 628c7bf6225SYongseok Koh ERROR("%p: error occurred while configuring flows: %s", 629*af4f09f2SNélio Laranjeiro (void *)dev, strerror(err)); 630c7bf6225SYongseok Koh } 631c7bf6225SYongseok Koh 632c7bf6225SYongseok Koh /** 633c7bf6225SYongseok Koh * Disable receiving and transmitting traffic. 634c7bf6225SYongseok Koh * 635*af4f09f2SNélio Laranjeiro * @param dev 636*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 637c7bf6225SYongseok Koh */ 638c7bf6225SYongseok Koh static void 639*af4f09f2SNélio Laranjeiro mlx5_link_stop(struct rte_eth_dev *dev) 640c7bf6225SYongseok Koh { 641*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 642c7bf6225SYongseok Koh 643*af4f09f2SNélio Laranjeiro mlx5_flow_stop(dev, &priv->flows); 644*af4f09f2SNélio Laranjeiro mlx5_traffic_disable(dev); 645c7bf6225SYongseok Koh dev->rx_pkt_burst = removed_rx_burst; 646c7bf6225SYongseok Koh dev->tx_pkt_burst = removed_tx_burst; 647c7bf6225SYongseok Koh } 648c7bf6225SYongseok Koh 649c7bf6225SYongseok Koh /** 650e313ef4cSShahaf Shuler * Querying the link status till it changes to the desired state. 651e313ef4cSShahaf Shuler * Number of query attempts is bounded by MLX5_MAX_LINK_QUERY_ATTEMPTS. 652e313ef4cSShahaf Shuler * 653*af4f09f2SNélio Laranjeiro * @param dev 654*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 655e313ef4cSShahaf Shuler * @param status 656e313ef4cSShahaf Shuler * Link desired status. 657e313ef4cSShahaf Shuler * 658e313ef4cSShahaf Shuler * @return 659e313ef4cSShahaf Shuler * 0 on success, negative errno value on failure. 660e313ef4cSShahaf Shuler */ 661e313ef4cSShahaf Shuler int 662*af4f09f2SNélio Laranjeiro mlx5_force_link_status_change(struct rte_eth_dev *dev, int status) 663e313ef4cSShahaf Shuler { 664e313ef4cSShahaf Shuler int try = 0; 665e313ef4cSShahaf Shuler 666e313ef4cSShahaf Shuler while (try < MLX5_MAX_LINK_QUERY_ATTEMPTS) { 667*af4f09f2SNélio Laranjeiro mlx5_link_update(dev, 0); 668*af4f09f2SNélio Laranjeiro if (dev->data->dev_link.link_status == status) 669e313ef4cSShahaf Shuler return 0; 670e313ef4cSShahaf Shuler try++; 671e313ef4cSShahaf Shuler sleep(1); 672e313ef4cSShahaf Shuler } 673e313ef4cSShahaf Shuler return -EAGAIN; 674e313ef4cSShahaf Shuler } 675e313ef4cSShahaf Shuler 676e313ef4cSShahaf Shuler /** 677cb8faed7SAdrien Mazarguil * DPDK callback to retrieve physical link information. 678cb8faed7SAdrien Mazarguil * 679cb8faed7SAdrien Mazarguil * @param dev 680cb8faed7SAdrien Mazarguil * Pointer to Ethernet device structure. 681cb8faed7SAdrien Mazarguil * @param wait_to_complete 682cb8faed7SAdrien Mazarguil * Wait for request completion (ignored). 683fb732b0aSNélio Laranjeiro * 684fb732b0aSNélio Laranjeiro * @return 685fb732b0aSNélio Laranjeiro * 0 on success, -1 on error. 686cb8faed7SAdrien Mazarguil */ 687cb8faed7SAdrien Mazarguil int 68856f08e16SNélio Laranjeiro mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 689cb8faed7SAdrien Mazarguil { 690*af4f09f2SNélio Laranjeiro struct utsname utsname; 691*af4f09f2SNélio Laranjeiro int ver[3]; 692c7bf6225SYongseok Koh int ret; 693*af4f09f2SNélio Laranjeiro struct rte_eth_link dev_link = dev->data->dev_link; 694cb8faed7SAdrien Mazarguil 695*af4f09f2SNélio Laranjeiro if (uname(&utsname) == -1 || 696*af4f09f2SNélio Laranjeiro sscanf(utsname.release, "%d.%d.%d", 697*af4f09f2SNélio Laranjeiro &ver[0], &ver[1], &ver[2]) != 3 || 698*af4f09f2SNélio Laranjeiro KERNEL_VERSION(ver[0], ver[1], ver[2]) < KERNEL_VERSION(4, 9, 0)) 699*af4f09f2SNélio Laranjeiro ret = mlx5_link_update_unlocked_gset(dev); 700*af4f09f2SNélio Laranjeiro else 701*af4f09f2SNélio Laranjeiro ret = mlx5_link_update_unlocked_gs(dev); 702*af4f09f2SNélio Laranjeiro /* If lsc interrupt is disabled, should always be ready for traffic. */ 703*af4f09f2SNélio Laranjeiro if (!dev->data->dev_conf.intr_conf.lsc) { 704*af4f09f2SNélio Laranjeiro mlx5_link_start(dev); 705*af4f09f2SNélio Laranjeiro return ret; 706*af4f09f2SNélio Laranjeiro } 707*af4f09f2SNélio Laranjeiro /* Re-select burst callbacks only if link status has been changed. */ 708*af4f09f2SNélio Laranjeiro if (!ret && dev_link.link_status != dev->data->dev_link.link_status) { 709*af4f09f2SNélio Laranjeiro if (dev->data->dev_link.link_status == ETH_LINK_UP) 710*af4f09f2SNélio Laranjeiro mlx5_link_start(dev); 711*af4f09f2SNélio Laranjeiro else 712*af4f09f2SNélio Laranjeiro mlx5_link_stop(dev); 713*af4f09f2SNélio Laranjeiro } 714c7bf6225SYongseok Koh return ret; 715cb8faed7SAdrien Mazarguil } 716cb8faed7SAdrien Mazarguil 717cb8faed7SAdrien Mazarguil /** 718cf37ca95SAdrien Mazarguil * DPDK callback to change the MTU. 719cf37ca95SAdrien Mazarguil * 720cf37ca95SAdrien Mazarguil * @param dev 721cf37ca95SAdrien Mazarguil * Pointer to Ethernet device structure. 722cf37ca95SAdrien Mazarguil * @param in_mtu 723cf37ca95SAdrien Mazarguil * New MTU. 724cf37ca95SAdrien Mazarguil * 725cf37ca95SAdrien Mazarguil * @return 726cf37ca95SAdrien Mazarguil * 0 on success, negative errno value on failure. 727cf37ca95SAdrien Mazarguil */ 728cf37ca95SAdrien Mazarguil int 729cf37ca95SAdrien Mazarguil mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 730cf37ca95SAdrien Mazarguil { 731cf37ca95SAdrien Mazarguil struct priv *priv = dev->data->dev_private; 732a0edafe4SNelio Laranjeiro uint16_t kern_mtu; 733cf37ca95SAdrien Mazarguil int ret = 0; 734cf37ca95SAdrien Mazarguil 735*af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 736a0edafe4SNelio Laranjeiro if (ret) 737a0edafe4SNelio Laranjeiro goto out; 738cf37ca95SAdrien Mazarguil /* Set kernel interface MTU first. */ 739*af4f09f2SNélio Laranjeiro ret = mlx5_set_mtu(dev, mtu); 740a0edafe4SNelio Laranjeiro if (ret) 741a0edafe4SNelio Laranjeiro goto out; 742*af4f09f2SNélio Laranjeiro ret = mlx5_get_mtu(dev, &kern_mtu); 743a0edafe4SNelio Laranjeiro if (ret) 744a0edafe4SNelio Laranjeiro goto out; 745a0edafe4SNelio Laranjeiro if (kern_mtu == mtu) { 746a0edafe4SNelio Laranjeiro priv->mtu = mtu; 747a0edafe4SNelio Laranjeiro DEBUG("adapter port %u MTU set to %u", priv->port, mtu); 748a0edafe4SNelio Laranjeiro } 749a0edafe4SNelio Laranjeiro return 0; 750a0edafe4SNelio Laranjeiro out: 751cf37ca95SAdrien Mazarguil ret = errno; 752cf37ca95SAdrien Mazarguil WARN("cannot set port %u MTU to %u: %s", priv->port, mtu, 753cf37ca95SAdrien Mazarguil strerror(ret)); 754cf37ca95SAdrien Mazarguil assert(ret >= 0); 755cf37ca95SAdrien Mazarguil return -ret; 756cf37ca95SAdrien Mazarguil } 757cf37ca95SAdrien Mazarguil 758cf37ca95SAdrien Mazarguil /** 75902d75430SAdrien Mazarguil * DPDK callback to get flow control status. 76002d75430SAdrien Mazarguil * 76102d75430SAdrien Mazarguil * @param dev 76202d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 76302d75430SAdrien Mazarguil * @param[out] fc_conf 76402d75430SAdrien Mazarguil * Flow control output buffer. 76502d75430SAdrien Mazarguil * 76602d75430SAdrien Mazarguil * @return 76702d75430SAdrien Mazarguil * 0 on success, negative errno value on failure. 76802d75430SAdrien Mazarguil */ 76902d75430SAdrien Mazarguil int 77002d75430SAdrien Mazarguil mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 77102d75430SAdrien Mazarguil { 77202d75430SAdrien Mazarguil struct ifreq ifr; 77302d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 77402d75430SAdrien Mazarguil .cmd = ETHTOOL_GPAUSEPARAM 77502d75430SAdrien Mazarguil }; 77602d75430SAdrien Mazarguil int ret; 77702d75430SAdrien Mazarguil 778d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 779*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCETHTOOL, &ifr)) { 78002d75430SAdrien Mazarguil ret = errno; 781*af4f09f2SNélio Laranjeiro WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed: %s", 78202d75430SAdrien Mazarguil strerror(ret)); 78302d75430SAdrien Mazarguil goto out; 78402d75430SAdrien Mazarguil } 78502d75430SAdrien Mazarguil fc_conf->autoneg = ethpause.autoneg; 78602d75430SAdrien Mazarguil if (ethpause.rx_pause && ethpause.tx_pause) 78702d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_FULL; 78802d75430SAdrien Mazarguil else if (ethpause.rx_pause) 78902d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_RX_PAUSE; 79002d75430SAdrien Mazarguil else if (ethpause.tx_pause) 79102d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_TX_PAUSE; 79202d75430SAdrien Mazarguil else 79302d75430SAdrien Mazarguil fc_conf->mode = RTE_FC_NONE; 79402d75430SAdrien Mazarguil ret = 0; 79502d75430SAdrien Mazarguil out: 79602d75430SAdrien Mazarguil assert(ret >= 0); 79702d75430SAdrien Mazarguil return -ret; 79802d75430SAdrien Mazarguil } 79902d75430SAdrien Mazarguil 80002d75430SAdrien Mazarguil /** 80102d75430SAdrien Mazarguil * DPDK callback to modify flow control parameters. 80202d75430SAdrien Mazarguil * 80302d75430SAdrien Mazarguil * @param dev 80402d75430SAdrien Mazarguil * Pointer to Ethernet device structure. 80502d75430SAdrien Mazarguil * @param[in] fc_conf 80602d75430SAdrien Mazarguil * Flow control parameters. 80702d75430SAdrien Mazarguil * 80802d75430SAdrien Mazarguil * @return 80902d75430SAdrien Mazarguil * 0 on success, negative errno value on failure. 81002d75430SAdrien Mazarguil */ 81102d75430SAdrien Mazarguil int 81202d75430SAdrien Mazarguil mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 81302d75430SAdrien Mazarguil { 81402d75430SAdrien Mazarguil struct ifreq ifr; 81502d75430SAdrien Mazarguil struct ethtool_pauseparam ethpause = { 81602d75430SAdrien Mazarguil .cmd = ETHTOOL_SPAUSEPARAM 81702d75430SAdrien Mazarguil }; 81802d75430SAdrien Mazarguil int ret; 81902d75430SAdrien Mazarguil 820d06c608cSAdrien Mazarguil ifr.ifr_data = (void *)ðpause; 82102d75430SAdrien Mazarguil ethpause.autoneg = fc_conf->autoneg; 82202d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 82302d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_RX_PAUSE)) 82402d75430SAdrien Mazarguil ethpause.rx_pause = 1; 82502d75430SAdrien Mazarguil else 82602d75430SAdrien Mazarguil ethpause.rx_pause = 0; 82702d75430SAdrien Mazarguil 82802d75430SAdrien Mazarguil if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 82902d75430SAdrien Mazarguil (fc_conf->mode & RTE_FC_TX_PAUSE)) 83002d75430SAdrien Mazarguil ethpause.tx_pause = 1; 83102d75430SAdrien Mazarguil else 83202d75430SAdrien Mazarguil ethpause.tx_pause = 0; 833*af4f09f2SNélio Laranjeiro if (mlx5_ifreq(dev, SIOCETHTOOL, &ifr)) { 83402d75430SAdrien Mazarguil ret = errno; 83502d75430SAdrien Mazarguil WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" 83602d75430SAdrien Mazarguil " failed: %s", 83702d75430SAdrien Mazarguil strerror(ret)); 83802d75430SAdrien Mazarguil goto out; 83902d75430SAdrien Mazarguil } 84002d75430SAdrien Mazarguil ret = 0; 84102d75430SAdrien Mazarguil out: 84202d75430SAdrien Mazarguil assert(ret >= 0); 84302d75430SAdrien Mazarguil return -ret; 84402d75430SAdrien Mazarguil } 84502d75430SAdrien Mazarguil 84602d75430SAdrien Mazarguil /** 847771fa900SAdrien Mazarguil * Get PCI information from struct ibv_device. 848771fa900SAdrien Mazarguil * 849771fa900SAdrien Mazarguil * @param device 850771fa900SAdrien Mazarguil * Pointer to Ethernet device structure. 851771fa900SAdrien Mazarguil * @param[out] pci_addr 852771fa900SAdrien Mazarguil * PCI bus address output buffer. 853771fa900SAdrien Mazarguil * 854771fa900SAdrien Mazarguil * @return 855771fa900SAdrien Mazarguil * 0 on success, -1 on failure and errno is set. 856771fa900SAdrien Mazarguil */ 857771fa900SAdrien Mazarguil int 858771fa900SAdrien Mazarguil mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, 859771fa900SAdrien Mazarguil struct rte_pci_addr *pci_addr) 860771fa900SAdrien Mazarguil { 861771fa900SAdrien Mazarguil FILE *file; 862771fa900SAdrien Mazarguil char line[32]; 863771fa900SAdrien Mazarguil MKSTR(path, "%s/device/uevent", device->ibdev_path); 864771fa900SAdrien Mazarguil 865771fa900SAdrien Mazarguil file = fopen(path, "rb"); 866771fa900SAdrien Mazarguil if (file == NULL) 867771fa900SAdrien Mazarguil return -1; 868771fa900SAdrien Mazarguil while (fgets(line, sizeof(line), file) == line) { 869771fa900SAdrien Mazarguil size_t len = strlen(line); 870771fa900SAdrien Mazarguil int ret; 871771fa900SAdrien Mazarguil 872771fa900SAdrien Mazarguil /* Truncate long lines. */ 873771fa900SAdrien Mazarguil if (len == (sizeof(line) - 1)) 874771fa900SAdrien Mazarguil while (line[(len - 1)] != '\n') { 875771fa900SAdrien Mazarguil ret = fgetc(file); 876771fa900SAdrien Mazarguil if (ret == EOF) 877771fa900SAdrien Mazarguil break; 878771fa900SAdrien Mazarguil line[(len - 1)] = ret; 879771fa900SAdrien Mazarguil } 880771fa900SAdrien Mazarguil /* Extract information. */ 881771fa900SAdrien Mazarguil if (sscanf(line, 882771fa900SAdrien Mazarguil "PCI_SLOT_NAME=" 883463ced95SStephen Hemminger "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 884771fa900SAdrien Mazarguil &pci_addr->domain, 885771fa900SAdrien Mazarguil &pci_addr->bus, 886771fa900SAdrien Mazarguil &pci_addr->devid, 887771fa900SAdrien Mazarguil &pci_addr->function) == 4) { 888771fa900SAdrien Mazarguil ret = 0; 889771fa900SAdrien Mazarguil break; 890771fa900SAdrien Mazarguil } 891771fa900SAdrien Mazarguil } 892771fa900SAdrien Mazarguil fclose(file); 893771fa900SAdrien Mazarguil return 0; 894771fa900SAdrien Mazarguil } 895198a3c33SNelio Laranjeiro 896198a3c33SNelio Laranjeiro /** 897c26ae069SMatan Azrad * Update the link status. 898198a3c33SNelio Laranjeiro * 899*af4f09f2SNélio Laranjeiro * @param dev 900*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 901198a3c33SNelio Laranjeiro * 902198a3c33SNelio Laranjeiro * @return 903c26ae069SMatan Azrad * Zero if the callback process can be called immediately. 904198a3c33SNelio Laranjeiro */ 905198a3c33SNelio Laranjeiro static int 906*af4f09f2SNélio Laranjeiro mlx5_link_status_update(struct rte_eth_dev *dev) 907c26ae069SMatan Azrad { 908*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 909*af4f09f2SNélio Laranjeiro struct rte_eth_link *link = &dev->data->dev_link; 910c26ae069SMatan Azrad 911*af4f09f2SNélio Laranjeiro mlx5_link_update(dev, 0); 912c26ae069SMatan Azrad if (((link->link_speed == 0) && link->link_status) || 913c26ae069SMatan Azrad ((link->link_speed != 0) && !link->link_status)) { 914c26ae069SMatan Azrad /* 915c26ae069SMatan Azrad * Inconsistent status. Event likely occurred before the 916c26ae069SMatan Azrad * kernel netdevice exposes the new status. 917c26ae069SMatan Azrad */ 918c26ae069SMatan Azrad if (!priv->pending_alarm) { 919c26ae069SMatan Azrad priv->pending_alarm = 1; 920c26ae069SMatan Azrad rte_eal_alarm_set(MLX5_ALARM_TIMEOUT_US, 921c26ae069SMatan Azrad mlx5_dev_link_status_handler, 922c26ae069SMatan Azrad priv->dev); 923c26ae069SMatan Azrad } 924c26ae069SMatan Azrad return 1; 925c26ae069SMatan Azrad } else if (unlikely(priv->pending_alarm)) { 926c26ae069SMatan Azrad /* Link interrupt occurred while alarm is already scheduled. */ 927c26ae069SMatan Azrad priv->pending_alarm = 0; 928c26ae069SMatan Azrad rte_eal_alarm_cancel(mlx5_dev_link_status_handler, priv->dev); 929c26ae069SMatan Azrad } 930c26ae069SMatan Azrad return 0; 931c26ae069SMatan Azrad } 932c26ae069SMatan Azrad 933c26ae069SMatan Azrad /** 934c26ae069SMatan Azrad * Device status handler. 935c26ae069SMatan Azrad * 936*af4f09f2SNélio Laranjeiro * @param dev 937*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 938c26ae069SMatan Azrad * @param events 939c26ae069SMatan Azrad * Pointer to event flags holder. 940c26ae069SMatan Azrad * 941c26ae069SMatan Azrad * @return 942c26ae069SMatan Azrad * Events bitmap of callback process which can be called immediately. 943c26ae069SMatan Azrad */ 944c26ae069SMatan Azrad static uint32_t 945*af4f09f2SNélio Laranjeiro mlx5_dev_status_handler(struct rte_eth_dev *dev) 946198a3c33SNelio Laranjeiro { 947*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 948198a3c33SNelio Laranjeiro struct ibv_async_event event; 949c26ae069SMatan Azrad uint32_t ret = 0; 950198a3c33SNelio Laranjeiro 951198a3c33SNelio Laranjeiro /* Read all message and acknowledge them. */ 952198a3c33SNelio Laranjeiro for (;;) { 9530e83b8e5SNelio Laranjeiro if (mlx5_glue->get_async_event(priv->ctx, &event)) 954198a3c33SNelio Laranjeiro break; 955c26ae069SMatan Azrad if ((event.event_type == IBV_EVENT_PORT_ACTIVE || 956c26ae069SMatan Azrad event.event_type == IBV_EVENT_PORT_ERR) && 957*af4f09f2SNélio Laranjeiro (dev->data->dev_conf.intr_conf.lsc == 1)) 958c26ae069SMatan Azrad ret |= (1 << RTE_ETH_EVENT_INTR_LSC); 9597d7d7ad1SMatan Azrad else if (event.event_type == IBV_EVENT_DEVICE_FATAL && 960*af4f09f2SNélio Laranjeiro dev->data->dev_conf.intr_conf.rmv == 1) 9617d7d7ad1SMatan Azrad ret |= (1 << RTE_ETH_EVENT_INTR_RMV); 962c26ae069SMatan Azrad else 963198a3c33SNelio Laranjeiro DEBUG("event type %d on port %d not handled", 964198a3c33SNelio Laranjeiro event.event_type, event.element.port_num); 9650e83b8e5SNelio Laranjeiro mlx5_glue->ack_async_event(&event); 966198a3c33SNelio Laranjeiro } 967c26ae069SMatan Azrad if (ret & (1 << RTE_ETH_EVENT_INTR_LSC)) 968*af4f09f2SNélio Laranjeiro if (mlx5_link_status_update(dev)) 969c26ae069SMatan Azrad ret &= ~(1 << RTE_ETH_EVENT_INTR_LSC); 970198a3c33SNelio Laranjeiro return ret; 971198a3c33SNelio Laranjeiro } 972198a3c33SNelio Laranjeiro 973198a3c33SNelio Laranjeiro /** 974198a3c33SNelio Laranjeiro * Handle delayed link status event. 975198a3c33SNelio Laranjeiro * 976198a3c33SNelio Laranjeiro * @param arg 977198a3c33SNelio Laranjeiro * Registered argument. 978198a3c33SNelio Laranjeiro */ 979198a3c33SNelio Laranjeiro void 980198a3c33SNelio Laranjeiro mlx5_dev_link_status_handler(void *arg) 981198a3c33SNelio Laranjeiro { 982198a3c33SNelio Laranjeiro struct rte_eth_dev *dev = arg; 983198a3c33SNelio Laranjeiro struct priv *priv = dev->data->dev_private; 984198a3c33SNelio Laranjeiro int ret; 985198a3c33SNelio Laranjeiro 986a9f2fbc4SShahaf Shuler priv->pending_alarm = 0; 987*af4f09f2SNélio Laranjeiro ret = mlx5_link_status_update(dev); 988c26ae069SMatan Azrad if (!ret) 989cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 990198a3c33SNelio Laranjeiro } 991198a3c33SNelio Laranjeiro 992198a3c33SNelio Laranjeiro /** 993198a3c33SNelio Laranjeiro * Handle interrupts from the NIC. 994198a3c33SNelio Laranjeiro * 995198a3c33SNelio Laranjeiro * @param[in] intr_handle 996198a3c33SNelio Laranjeiro * Interrupt handler. 997198a3c33SNelio Laranjeiro * @param cb_arg 998198a3c33SNelio Laranjeiro * Callback argument. 999198a3c33SNelio Laranjeiro */ 1000198a3c33SNelio Laranjeiro void 1001c23a1a30SQi Zhang mlx5_dev_interrupt_handler(void *cb_arg) 1002198a3c33SNelio Laranjeiro { 1003198a3c33SNelio Laranjeiro struct rte_eth_dev *dev = cb_arg; 1004c26ae069SMatan Azrad uint32_t events; 1005198a3c33SNelio Laranjeiro 1006*af4f09f2SNélio Laranjeiro events = mlx5_dev_status_handler(dev); 1007c26ae069SMatan Azrad if (events & (1 << RTE_ETH_EVENT_INTR_LSC)) 1008cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); 10097d7d7ad1SMatan Azrad if (events & (1 << RTE_ETH_EVENT_INTR_RMV)) 1010cebe3d7bSThomas Monjalon _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL); 1011198a3c33SNelio Laranjeiro } 1012198a3c33SNelio Laranjeiro 1013198a3c33SNelio Laranjeiro /** 1014f8b9a3baSXueming Li * Handle interrupts from the socket. 1015f8b9a3baSXueming Li * 1016f8b9a3baSXueming Li * @param cb_arg 1017f8b9a3baSXueming Li * Callback argument. 1018f8b9a3baSXueming Li */ 1019f8b9a3baSXueming Li static void 1020f8b9a3baSXueming Li mlx5_dev_handler_socket(void *cb_arg) 1021f8b9a3baSXueming Li { 1022f8b9a3baSXueming Li struct rte_eth_dev *dev = cb_arg; 1023f8b9a3baSXueming Li 1024*af4f09f2SNélio Laranjeiro mlx5_socket_handle(dev); 1025f8b9a3baSXueming Li } 1026f8b9a3baSXueming Li 1027f8b9a3baSXueming Li /** 1028198a3c33SNelio Laranjeiro * Uninstall interrupt handler. 1029198a3c33SNelio Laranjeiro * 1030198a3c33SNelio Laranjeiro * @param dev 1031*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1032198a3c33SNelio Laranjeiro */ 1033198a3c33SNelio Laranjeiro void 1034*af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev) 1035198a3c33SNelio Laranjeiro { 1036*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 1037*af4f09f2SNélio Laranjeiro 1038f8b9a3baSXueming Li if (dev->data->dev_conf.intr_conf.lsc || 1039f8b9a3baSXueming Li dev->data->dev_conf.intr_conf.rmv) 1040198a3c33SNelio Laranjeiro rte_intr_callback_unregister(&priv->intr_handle, 1041f8b9a3baSXueming Li mlx5_dev_interrupt_handler, dev); 1042f8b9a3baSXueming Li if (priv->primary_socket) 1043f8b9a3baSXueming Li rte_intr_callback_unregister(&priv->intr_handle_socket, 1044f8b9a3baSXueming Li mlx5_dev_handler_socket, dev); 10456817ad38SYongseok Koh if (priv->pending_alarm) { 1046198a3c33SNelio Laranjeiro priv->pending_alarm = 0; 10476817ad38SYongseok Koh rte_eal_alarm_cancel(mlx5_dev_link_status_handler, dev); 10486817ad38SYongseok Koh } 1049198a3c33SNelio Laranjeiro priv->intr_handle.fd = 0; 105036351ea3SFerruh Yigit priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 1051f8b9a3baSXueming Li priv->intr_handle_socket.fd = 0; 1052f8b9a3baSXueming Li priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN; 1053198a3c33SNelio Laranjeiro } 1054198a3c33SNelio Laranjeiro 1055198a3c33SNelio Laranjeiro /** 1056198a3c33SNelio Laranjeiro * Install interrupt handler. 1057198a3c33SNelio Laranjeiro * 1058198a3c33SNelio Laranjeiro * @param dev 1059*af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 1060198a3c33SNelio Laranjeiro */ 1061198a3c33SNelio Laranjeiro void 1062*af4f09f2SNélio Laranjeiro mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev) 1063198a3c33SNelio Laranjeiro { 1064*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 1065198a3c33SNelio Laranjeiro int rc, flags; 1066198a3c33SNelio Laranjeiro 1067198a3c33SNelio Laranjeiro assert(priv->ctx->async_fd > 0); 1068198a3c33SNelio Laranjeiro flags = fcntl(priv->ctx->async_fd, F_GETFL); 1069198a3c33SNelio Laranjeiro rc = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); 1070198a3c33SNelio Laranjeiro if (rc < 0) { 1071198a3c33SNelio Laranjeiro INFO("failed to change file descriptor async event queue"); 1072198a3c33SNelio Laranjeiro dev->data->dev_conf.intr_conf.lsc = 0; 10737d7d7ad1SMatan Azrad dev->data->dev_conf.intr_conf.rmv = 0; 1074f8b9a3baSXueming Li } 1075f8b9a3baSXueming Li if (dev->data->dev_conf.intr_conf.lsc || 1076f8b9a3baSXueming Li dev->data->dev_conf.intr_conf.rmv) { 1077198a3c33SNelio Laranjeiro priv->intr_handle.fd = priv->ctx->async_fd; 1078198a3c33SNelio Laranjeiro priv->intr_handle.type = RTE_INTR_HANDLE_EXT; 1079198a3c33SNelio Laranjeiro rte_intr_callback_register(&priv->intr_handle, 1080f8b9a3baSXueming Li mlx5_dev_interrupt_handler, dev); 1081f8b9a3baSXueming Li } 1082*af4f09f2SNélio Laranjeiro rc = mlx5_socket_init(dev); 1083f8b9a3baSXueming Li if (!rc && priv->primary_socket) { 1084f8b9a3baSXueming Li priv->intr_handle_socket.fd = priv->primary_socket; 1085f8b9a3baSXueming Li priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT; 1086f8b9a3baSXueming Li rte_intr_callback_register(&priv->intr_handle_socket, 1087f8b9a3baSXueming Li mlx5_dev_handler_socket, dev); 1088198a3c33SNelio Laranjeiro } 1089198a3c33SNelio Laranjeiro } 109062072098SOr Ami 109162072098SOr Ami /** 109262072098SOr Ami * DPDK callback to bring the link DOWN. 109362072098SOr Ami * 109462072098SOr Ami * @param dev 109562072098SOr Ami * Pointer to Ethernet device structure. 109662072098SOr Ami * 109762072098SOr Ami * @return 109862072098SOr Ami * 0 on success, errno value on failure. 109962072098SOr Ami */ 110062072098SOr Ami int 110162072098SOr Ami mlx5_set_link_down(struct rte_eth_dev *dev) 110262072098SOr Ami { 1103*af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP); 110462072098SOr Ami } 110562072098SOr Ami 110662072098SOr Ami /** 110762072098SOr Ami * DPDK callback to bring the link UP. 110862072098SOr Ami * 110962072098SOr Ami * @param dev 111062072098SOr Ami * Pointer to Ethernet device structure. 111162072098SOr Ami * 111262072098SOr Ami * @return 111362072098SOr Ami * 0 on success, errno value on failure. 111462072098SOr Ami */ 111562072098SOr Ami int 111662072098SOr Ami mlx5_set_link_up(struct rte_eth_dev *dev) 111762072098SOr Ami { 1118*af4f09f2SNélio Laranjeiro return mlx5_set_flags(dev, ~IFF_UP, IFF_UP); 111962072098SOr Ami } 1120a48deadaSOr Ami 1121a48deadaSOr Ami /** 1122cdab90cbSNélio Laranjeiro * Configure the TX function to use. 1123cdab90cbSNélio Laranjeiro * 1124aee1b165SXueming Li * @param dev 1125*af4f09f2SNélio Laranjeiro * Pointer to private data structure. 11261cfa649bSShahaf Shuler * 11271cfa649bSShahaf Shuler * @return 11281cfa649bSShahaf Shuler * Pointer to selected Tx burst function. 1129cdab90cbSNélio Laranjeiro */ 11301cfa649bSShahaf Shuler eth_tx_burst_t 1131*af4f09f2SNélio Laranjeiro mlx5_select_tx_function(struct rte_eth_dev *dev) 1132cdab90cbSNélio Laranjeiro { 1133*af4f09f2SNélio Laranjeiro struct priv *priv = dev->data->dev_private; 11341cfa649bSShahaf Shuler eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst; 11357fe24446SShahaf Shuler struct mlx5_dev_config *config = &priv->config; 1136dbccb4cdSShahaf Shuler uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; 1137dbccb4cdSShahaf Shuler int tso = !!(tx_offloads & (DEV_TX_OFFLOAD_TCP_TSO | 1138dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 1139dbccb4cdSShahaf Shuler DEV_TX_OFFLOAD_GRE_TNL_TSO)); 1140dbccb4cdSShahaf Shuler int vlan_insert = !!(tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT); 11411cfa649bSShahaf Shuler 1142aee1b165SXueming Li assert(priv != NULL); 1143230189d9SNélio Laranjeiro /* Select appropriate TX function. */ 1144dbccb4cdSShahaf Shuler if (vlan_insert || tso) 1145dbccb4cdSShahaf Shuler return tx_pkt_burst; 11467fe24446SShahaf Shuler if (config->mps == MLX5_MPW_ENHANCED) { 1147*af4f09f2SNélio Laranjeiro if (mlx5_check_vec_tx_support(dev) > 0) { 1148*af4f09f2SNélio Laranjeiro if (mlx5_check_raw_vec_tx_support(dev) > 0) 11491cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_raw_vec; 11506cb559d6SYongseok Koh else 11511cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_vec; 11526cb559d6SYongseok Koh DEBUG("selected Enhanced MPW TX vectorized function"); 11536cb559d6SYongseok Koh } else { 11541cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_empw; 11556ce84bd8SYongseok Koh DEBUG("selected Enhanced MPW TX function"); 11566cb559d6SYongseok Koh } 11577fe24446SShahaf Shuler } else if (config->mps && (config->txq_inline > 0)) { 11581cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw_inline; 1159230189d9SNélio Laranjeiro DEBUG("selected MPW inline TX function"); 11607fe24446SShahaf Shuler } else if (config->mps) { 11611cfa649bSShahaf Shuler tx_pkt_burst = mlx5_tx_burst_mpw; 1162230189d9SNélio Laranjeiro DEBUG("selected MPW TX function"); 11632a66cf37SYaacov Hazan } 11641cfa649bSShahaf Shuler return tx_pkt_burst; 1165cdab90cbSNélio Laranjeiro } 1166cdab90cbSNélio Laranjeiro 1167cdab90cbSNélio Laranjeiro /** 1168cdab90cbSNélio Laranjeiro * Configure the RX function to use. 1169cdab90cbSNélio Laranjeiro * 1170aee1b165SXueming Li * @param dev 1171*af4f09f2SNélio Laranjeiro * Pointer to private data structure. 11721cfa649bSShahaf Shuler * 11731cfa649bSShahaf Shuler * @return 11741cfa649bSShahaf Shuler * Pointer to selected Rx burst function. 1175cdab90cbSNélio Laranjeiro */ 11761cfa649bSShahaf Shuler eth_rx_burst_t 1177*af4f09f2SNélio Laranjeiro mlx5_select_rx_function(struct rte_eth_dev *dev) 1178cdab90cbSNélio Laranjeiro { 11791cfa649bSShahaf Shuler eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; 11801cfa649bSShahaf Shuler 1181*af4f09f2SNélio Laranjeiro assert(dev != NULL); 1182*af4f09f2SNélio Laranjeiro if (mlx5_check_vec_rx_support(dev) > 0) { 11831cfa649bSShahaf Shuler rx_pkt_burst = mlx5_rx_burst_vec; 11846cb559d6SYongseok Koh DEBUG("selected RX vectorized function"); 1185cdab90cbSNélio Laranjeiro } 11861cfa649bSShahaf Shuler return rx_pkt_burst; 11876cb559d6SYongseok Koh } 1188d3e0f392SMatan Azrad 1189d3e0f392SMatan Azrad /** 1190d3e0f392SMatan Azrad * Check if mlx5 device was removed. 1191d3e0f392SMatan Azrad * 1192d3e0f392SMatan Azrad * @param dev 1193d3e0f392SMatan Azrad * Pointer to Ethernet device structure. 1194d3e0f392SMatan Azrad * 1195d3e0f392SMatan Azrad * @return 1196d3e0f392SMatan Azrad * 1 when device is removed, otherwise 0. 1197d3e0f392SMatan Azrad */ 1198d3e0f392SMatan Azrad int 1199d3e0f392SMatan Azrad mlx5_is_removed(struct rte_eth_dev *dev) 1200d3e0f392SMatan Azrad { 1201d3e0f392SMatan Azrad struct ibv_device_attr device_attr; 1202d3e0f392SMatan Azrad struct priv *priv = dev->data->dev_private; 1203d3e0f392SMatan Azrad 12040e83b8e5SNelio Laranjeiro if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO) 1205d3e0f392SMatan Azrad return 1; 1206d3e0f392SMatan Azrad return 0; 1207d3e0f392SMatan Azrad } 1208