12d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
22d9fd380Sjfb8856606 * Copyright 2015 6WIND S.A.
32d9fd380Sjfb8856606 * Copyright 2015 Mellanox Technologies, Ltd
42d9fd380Sjfb8856606 */
52d9fd380Sjfb8856606
62d9fd380Sjfb8856606 #include <stddef.h>
72d9fd380Sjfb8856606 #include <inttypes.h>
82d9fd380Sjfb8856606 #include <unistd.h>
92d9fd380Sjfb8856606 #include <stdbool.h>
102d9fd380Sjfb8856606 #include <stdint.h>
112d9fd380Sjfb8856606 #include <stdio.h>
122d9fd380Sjfb8856606 #include <string.h>
132d9fd380Sjfb8856606 #include <stdlib.h>
142d9fd380Sjfb8856606 #include <errno.h>
152d9fd380Sjfb8856606 #include <dirent.h>
162d9fd380Sjfb8856606 #include <net/if.h>
172d9fd380Sjfb8856606 #include <sys/ioctl.h>
182d9fd380Sjfb8856606 #include <sys/socket.h>
192d9fd380Sjfb8856606 #include <netinet/in.h>
202d9fd380Sjfb8856606 #include <linux/ethtool.h>
212d9fd380Sjfb8856606 #include <linux/sockios.h>
222d9fd380Sjfb8856606 #include <fcntl.h>
232d9fd380Sjfb8856606 #include <stdalign.h>
242d9fd380Sjfb8856606 #include <sys/un.h>
252d9fd380Sjfb8856606 #include <time.h>
26*16a456d6Sfengbojiang #include <dlfcn.h>
272d9fd380Sjfb8856606
282d9fd380Sjfb8856606 #include <rte_ethdev_driver.h>
292d9fd380Sjfb8856606 #include <rte_bus_pci.h>
302d9fd380Sjfb8856606 #include <rte_mbuf.h>
312d9fd380Sjfb8856606 #include <rte_common.h>
322d9fd380Sjfb8856606 #include <rte_interrupts.h>
332d9fd380Sjfb8856606 #include <rte_malloc.h>
342d9fd380Sjfb8856606 #include <rte_string_fns.h>
352d9fd380Sjfb8856606 #include <rte_rwlock.h>
362d9fd380Sjfb8856606 #include <rte_cycles.h>
372d9fd380Sjfb8856606
382d9fd380Sjfb8856606 #include <mlx5_glue.h>
392d9fd380Sjfb8856606 #include <mlx5_devx_cmds.h>
402d9fd380Sjfb8856606 #include <mlx5_common.h>
412d9fd380Sjfb8856606 #include <mlx5_malloc.h>
422d9fd380Sjfb8856606
432d9fd380Sjfb8856606 #include "mlx5.h"
442d9fd380Sjfb8856606 #include "mlx5_rxtx.h"
452d9fd380Sjfb8856606 #include "mlx5_utils.h"
462d9fd380Sjfb8856606
472d9fd380Sjfb8856606 /* Supported speed values found in /usr/include/linux/ethtool.h */
482d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_40000baseKR4_Full
492d9fd380Sjfb8856606 #define SUPPORTED_40000baseKR4_Full (1 << 23)
502d9fd380Sjfb8856606 #endif
512d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_40000baseCR4_Full
522d9fd380Sjfb8856606 #define SUPPORTED_40000baseCR4_Full (1 << 24)
532d9fd380Sjfb8856606 #endif
542d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_40000baseSR4_Full
552d9fd380Sjfb8856606 #define SUPPORTED_40000baseSR4_Full (1 << 25)
562d9fd380Sjfb8856606 #endif
572d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_40000baseLR4_Full
582d9fd380Sjfb8856606 #define SUPPORTED_40000baseLR4_Full (1 << 26)
592d9fd380Sjfb8856606 #endif
602d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_56000baseKR4_Full
612d9fd380Sjfb8856606 #define SUPPORTED_56000baseKR4_Full (1 << 27)
622d9fd380Sjfb8856606 #endif
632d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_56000baseCR4_Full
642d9fd380Sjfb8856606 #define SUPPORTED_56000baseCR4_Full (1 << 28)
652d9fd380Sjfb8856606 #endif
662d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_56000baseSR4_Full
672d9fd380Sjfb8856606 #define SUPPORTED_56000baseSR4_Full (1 << 29)
682d9fd380Sjfb8856606 #endif
692d9fd380Sjfb8856606 #ifndef HAVE_SUPPORTED_56000baseLR4_Full
702d9fd380Sjfb8856606 #define SUPPORTED_56000baseLR4_Full (1 << 30)
712d9fd380Sjfb8856606 #endif
722d9fd380Sjfb8856606
732d9fd380Sjfb8856606 /* Add defines in case the running kernel is not the same as user headers. */
742d9fd380Sjfb8856606 #ifndef ETHTOOL_GLINKSETTINGS
752d9fd380Sjfb8856606 struct ethtool_link_settings {
762d9fd380Sjfb8856606 uint32_t cmd;
772d9fd380Sjfb8856606 uint32_t speed;
782d9fd380Sjfb8856606 uint8_t duplex;
792d9fd380Sjfb8856606 uint8_t port;
802d9fd380Sjfb8856606 uint8_t phy_address;
812d9fd380Sjfb8856606 uint8_t autoneg;
822d9fd380Sjfb8856606 uint8_t mdio_support;
832d9fd380Sjfb8856606 uint8_t eth_to_mdix;
842d9fd380Sjfb8856606 uint8_t eth_tp_mdix_ctrl;
852d9fd380Sjfb8856606 int8_t link_mode_masks_nwords;
862d9fd380Sjfb8856606 uint32_t reserved[8];
872d9fd380Sjfb8856606 uint32_t link_mode_masks[];
882d9fd380Sjfb8856606 };
892d9fd380Sjfb8856606
902d9fd380Sjfb8856606 /* The kernel values can be found in /include/uapi/linux/ethtool.h */
912d9fd380Sjfb8856606 #define ETHTOOL_GLINKSETTINGS 0x0000004c
922d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_1000baseT_Full_BIT 5
932d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_Autoneg_BIT 6
942d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_1000baseKX_Full_BIT 17
952d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT 18
962d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_10000baseKR_Full_BIT 19
972d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_10000baseR_FEC_BIT 20
982d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT 21
992d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT 22
1002d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT 23
1012d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT 24
1022d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT 25
1032d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT 26
1042d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT 27
1052d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT 28
1062d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT 29
1072d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT 30
1082d9fd380Sjfb8856606 #endif
1092d9fd380Sjfb8856606 #ifndef HAVE_ETHTOOL_LINK_MODE_25G
1102d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31
1112d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32
1122d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33
1132d9fd380Sjfb8856606 #endif
1142d9fd380Sjfb8856606 #ifndef HAVE_ETHTOOL_LINK_MODE_50G
1152d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34
1162d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35
1172d9fd380Sjfb8856606 #endif
1182d9fd380Sjfb8856606 #ifndef HAVE_ETHTOOL_LINK_MODE_100G
1192d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36
1202d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37
1212d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38
1222d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39
1232d9fd380Sjfb8856606 #endif
1242d9fd380Sjfb8856606 #ifndef HAVE_ETHTOOL_LINK_MODE_200G
1252d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT 62
1262d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT 63
1272d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT 0 /* 64 - 64 */
1282d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT 1 /* 65 - 64 */
1292d9fd380Sjfb8856606 #define ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT 2 /* 66 - 64 */
1302d9fd380Sjfb8856606 #endif
1312d9fd380Sjfb8856606
1322d9fd380Sjfb8856606
1332d9fd380Sjfb8856606 /**
1342d9fd380Sjfb8856606 * Get interface name from private structure.
1352d9fd380Sjfb8856606 *
1362d9fd380Sjfb8856606 * This is a port representor-aware version of mlx5_get_ifname_sysfs().
1372d9fd380Sjfb8856606 *
1382d9fd380Sjfb8856606 * @param[in] dev
1392d9fd380Sjfb8856606 * Pointer to Ethernet device.
1402d9fd380Sjfb8856606 * @param[out] ifname
1412d9fd380Sjfb8856606 * Interface name output buffer.
1422d9fd380Sjfb8856606 *
1432d9fd380Sjfb8856606 * @return
1442d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
1452d9fd380Sjfb8856606 */
1462d9fd380Sjfb8856606 int
mlx5_get_ifname(const struct rte_eth_dev * dev,char (* ifname)[IF_NAMESIZE])1472d9fd380Sjfb8856606 mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
1482d9fd380Sjfb8856606 {
1492d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
1502d9fd380Sjfb8856606 unsigned int ifindex;
1512d9fd380Sjfb8856606
1522d9fd380Sjfb8856606 MLX5_ASSERT(priv);
1532d9fd380Sjfb8856606 MLX5_ASSERT(priv->sh);
1542d9fd380Sjfb8856606 if (priv->bond_ifindex > 0) {
1552d9fd380Sjfb8856606 memcpy(ifname, priv->bond_name, IF_NAMESIZE);
1562d9fd380Sjfb8856606 return 0;
1572d9fd380Sjfb8856606 }
1582d9fd380Sjfb8856606 ifindex = mlx5_ifindex(dev);
1592d9fd380Sjfb8856606 if (!ifindex) {
1602d9fd380Sjfb8856606 if (!priv->representor)
1612d9fd380Sjfb8856606 return mlx5_get_ifname_sysfs(priv->sh->ibdev_path,
1622d9fd380Sjfb8856606 *ifname);
1632d9fd380Sjfb8856606 rte_errno = ENXIO;
1642d9fd380Sjfb8856606 return -rte_errno;
1652d9fd380Sjfb8856606 }
1662d9fd380Sjfb8856606 if (if_indextoname(ifindex, &(*ifname)[0]))
1672d9fd380Sjfb8856606 return 0;
1682d9fd380Sjfb8856606 rte_errno = errno;
1692d9fd380Sjfb8856606 return -rte_errno;
1702d9fd380Sjfb8856606 }
1712d9fd380Sjfb8856606
1722d9fd380Sjfb8856606 /**
1732d9fd380Sjfb8856606 * Perform ifreq ioctl() on associated Ethernet device.
1742d9fd380Sjfb8856606 *
1752d9fd380Sjfb8856606 * @param[in] dev
1762d9fd380Sjfb8856606 * Pointer to Ethernet device.
1772d9fd380Sjfb8856606 * @param req
1782d9fd380Sjfb8856606 * Request number to pass to ioctl().
1792d9fd380Sjfb8856606 * @param[out] ifr
1802d9fd380Sjfb8856606 * Interface request structure output buffer.
1812d9fd380Sjfb8856606 *
1822d9fd380Sjfb8856606 * @return
1832d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
1842d9fd380Sjfb8856606 */
1852d9fd380Sjfb8856606 static int
mlx5_ifreq(const struct rte_eth_dev * dev,int req,struct ifreq * ifr)1862d9fd380Sjfb8856606 mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
1872d9fd380Sjfb8856606 {
1882d9fd380Sjfb8856606 int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1892d9fd380Sjfb8856606 int ret = 0;
1902d9fd380Sjfb8856606
1912d9fd380Sjfb8856606 if (sock == -1) {
1922d9fd380Sjfb8856606 rte_errno = errno;
1932d9fd380Sjfb8856606 return -rte_errno;
1942d9fd380Sjfb8856606 }
1952d9fd380Sjfb8856606 ret = mlx5_get_ifname(dev, &ifr->ifr_name);
1962d9fd380Sjfb8856606 if (ret)
1972d9fd380Sjfb8856606 goto error;
1982d9fd380Sjfb8856606 ret = ioctl(sock, req, ifr);
1992d9fd380Sjfb8856606 if (ret == -1) {
2002d9fd380Sjfb8856606 rte_errno = errno;
2012d9fd380Sjfb8856606 goto error;
2022d9fd380Sjfb8856606 }
2032d9fd380Sjfb8856606 close(sock);
2042d9fd380Sjfb8856606 return 0;
2052d9fd380Sjfb8856606 error:
2062d9fd380Sjfb8856606 close(sock);
2072d9fd380Sjfb8856606 return -rte_errno;
2082d9fd380Sjfb8856606 }
2092d9fd380Sjfb8856606
2102d9fd380Sjfb8856606 /**
2112d9fd380Sjfb8856606 * Get device MTU.
2122d9fd380Sjfb8856606 *
2132d9fd380Sjfb8856606 * @param dev
2142d9fd380Sjfb8856606 * Pointer to Ethernet device.
2152d9fd380Sjfb8856606 * @param[out] mtu
2162d9fd380Sjfb8856606 * MTU value output buffer.
2172d9fd380Sjfb8856606 *
2182d9fd380Sjfb8856606 * @return
2192d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
2202d9fd380Sjfb8856606 */
2212d9fd380Sjfb8856606 int
mlx5_get_mtu(struct rte_eth_dev * dev,uint16_t * mtu)2222d9fd380Sjfb8856606 mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
2232d9fd380Sjfb8856606 {
2242d9fd380Sjfb8856606 struct ifreq request;
2252d9fd380Sjfb8856606 int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
2262d9fd380Sjfb8856606
2272d9fd380Sjfb8856606 if (ret)
2282d9fd380Sjfb8856606 return ret;
2292d9fd380Sjfb8856606 *mtu = request.ifr_mtu;
2302d9fd380Sjfb8856606 return 0;
2312d9fd380Sjfb8856606 }
2322d9fd380Sjfb8856606
2332d9fd380Sjfb8856606 /**
2342d9fd380Sjfb8856606 * Set device MTU.
2352d9fd380Sjfb8856606 *
2362d9fd380Sjfb8856606 * @param dev
2372d9fd380Sjfb8856606 * Pointer to Ethernet device.
2382d9fd380Sjfb8856606 * @param mtu
2392d9fd380Sjfb8856606 * MTU value to set.
2402d9fd380Sjfb8856606 *
2412d9fd380Sjfb8856606 * @return
2422d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
2432d9fd380Sjfb8856606 */
2442d9fd380Sjfb8856606 int
mlx5_set_mtu(struct rte_eth_dev * dev,uint16_t mtu)2452d9fd380Sjfb8856606 mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
2462d9fd380Sjfb8856606 {
2472d9fd380Sjfb8856606 struct ifreq request = { .ifr_mtu = mtu, };
2482d9fd380Sjfb8856606
2492d9fd380Sjfb8856606 return mlx5_ifreq(dev, SIOCSIFMTU, &request);
2502d9fd380Sjfb8856606 }
2512d9fd380Sjfb8856606
2522d9fd380Sjfb8856606 /**
2532d9fd380Sjfb8856606 * Set device flags.
2542d9fd380Sjfb8856606 *
2552d9fd380Sjfb8856606 * @param dev
2562d9fd380Sjfb8856606 * Pointer to Ethernet device.
2572d9fd380Sjfb8856606 * @param keep
2582d9fd380Sjfb8856606 * Bitmask for flags that must remain untouched.
2592d9fd380Sjfb8856606 * @param flags
2602d9fd380Sjfb8856606 * Bitmask for flags to modify.
2612d9fd380Sjfb8856606 *
2622d9fd380Sjfb8856606 * @return
2632d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
2642d9fd380Sjfb8856606 */
2652d9fd380Sjfb8856606 static int
mlx5_set_flags(struct rte_eth_dev * dev,unsigned int keep,unsigned int flags)2662d9fd380Sjfb8856606 mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
2672d9fd380Sjfb8856606 {
2682d9fd380Sjfb8856606 struct ifreq request;
2692d9fd380Sjfb8856606 int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
2702d9fd380Sjfb8856606
2712d9fd380Sjfb8856606 if (ret)
2722d9fd380Sjfb8856606 return ret;
2732d9fd380Sjfb8856606 request.ifr_flags &= keep;
2742d9fd380Sjfb8856606 request.ifr_flags |= flags & ~keep;
2752d9fd380Sjfb8856606 return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
2762d9fd380Sjfb8856606 }
2772d9fd380Sjfb8856606
2782d9fd380Sjfb8856606 /**
2792d9fd380Sjfb8856606 * Get device current raw clock counter
2802d9fd380Sjfb8856606 *
2812d9fd380Sjfb8856606 * @param dev
2822d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
2832d9fd380Sjfb8856606 * @param[out] time
2842d9fd380Sjfb8856606 * Current raw clock counter of the device.
2852d9fd380Sjfb8856606 *
2862d9fd380Sjfb8856606 * @return
2872d9fd380Sjfb8856606 * 0 if the clock has correctly been read
2882d9fd380Sjfb8856606 * The value of errno in case of error
2892d9fd380Sjfb8856606 */
2902d9fd380Sjfb8856606 int
mlx5_read_clock(struct rte_eth_dev * dev,uint64_t * clock)2912d9fd380Sjfb8856606 mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
2922d9fd380Sjfb8856606 {
2932d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
2942d9fd380Sjfb8856606 struct ibv_context *ctx = priv->sh->ctx;
2952d9fd380Sjfb8856606 struct ibv_values_ex values;
2962d9fd380Sjfb8856606 int err = 0;
2972d9fd380Sjfb8856606
2982d9fd380Sjfb8856606 values.comp_mask = IBV_VALUES_MASK_RAW_CLOCK;
2992d9fd380Sjfb8856606 err = mlx5_glue->query_rt_values_ex(ctx, &values);
3002d9fd380Sjfb8856606 if (err != 0) {
3012d9fd380Sjfb8856606 DRV_LOG(WARNING, "Could not query the clock !");
3022d9fd380Sjfb8856606 return err;
3032d9fd380Sjfb8856606 }
3042d9fd380Sjfb8856606 *clock = values.raw_clock.tv_nsec;
3052d9fd380Sjfb8856606 return 0;
3062d9fd380Sjfb8856606 }
3072d9fd380Sjfb8856606
3082d9fd380Sjfb8856606 /**
3092d9fd380Sjfb8856606 * Retrieve the master device for representor in the same switch domain.
3102d9fd380Sjfb8856606 *
3112d9fd380Sjfb8856606 * @param dev
3122d9fd380Sjfb8856606 * Pointer to representor Ethernet device structure.
3132d9fd380Sjfb8856606 *
3142d9fd380Sjfb8856606 * @return
3152d9fd380Sjfb8856606 * Master device structure on success, NULL otherwise.
3162d9fd380Sjfb8856606 */
3172d9fd380Sjfb8856606 static struct rte_eth_dev *
mlx5_find_master_dev(struct rte_eth_dev * dev)3182d9fd380Sjfb8856606 mlx5_find_master_dev(struct rte_eth_dev *dev)
3192d9fd380Sjfb8856606 {
3202d9fd380Sjfb8856606 struct mlx5_priv *priv;
3212d9fd380Sjfb8856606 uint16_t port_id;
3222d9fd380Sjfb8856606 uint16_t domain_id;
3232d9fd380Sjfb8856606
3242d9fd380Sjfb8856606 priv = dev->data->dev_private;
3252d9fd380Sjfb8856606 domain_id = priv->domain_id;
3262d9fd380Sjfb8856606 MLX5_ASSERT(priv->representor);
3272d9fd380Sjfb8856606 MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
3282d9fd380Sjfb8856606 struct mlx5_priv *opriv =
3292d9fd380Sjfb8856606 rte_eth_devices[port_id].data->dev_private;
3302d9fd380Sjfb8856606 if (opriv &&
3312d9fd380Sjfb8856606 opriv->master &&
3322d9fd380Sjfb8856606 opriv->domain_id == domain_id &&
3332d9fd380Sjfb8856606 opriv->sh == priv->sh)
3342d9fd380Sjfb8856606 return &rte_eth_devices[port_id];
3352d9fd380Sjfb8856606 }
3362d9fd380Sjfb8856606 return NULL;
3372d9fd380Sjfb8856606 }
3382d9fd380Sjfb8856606
3392d9fd380Sjfb8856606 /**
3402d9fd380Sjfb8856606 * DPDK callback to retrieve physical link information.
3412d9fd380Sjfb8856606 *
3422d9fd380Sjfb8856606 * @param dev
3432d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
3442d9fd380Sjfb8856606 * @param[out] link
3452d9fd380Sjfb8856606 * Storage for current link status.
3462d9fd380Sjfb8856606 *
3472d9fd380Sjfb8856606 * @return
3482d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
3492d9fd380Sjfb8856606 */
3502d9fd380Sjfb8856606 static int
mlx5_link_update_unlocked_gset(struct rte_eth_dev * dev,struct rte_eth_link * link)3512d9fd380Sjfb8856606 mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
3522d9fd380Sjfb8856606 struct rte_eth_link *link)
3532d9fd380Sjfb8856606 {
3542d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
3552d9fd380Sjfb8856606 struct ethtool_cmd edata = {
3562d9fd380Sjfb8856606 .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
3572d9fd380Sjfb8856606 };
3582d9fd380Sjfb8856606 struct ifreq ifr;
3592d9fd380Sjfb8856606 struct rte_eth_link dev_link;
3602d9fd380Sjfb8856606 int link_speed = 0;
3612d9fd380Sjfb8856606 int ret;
3622d9fd380Sjfb8856606
3632d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
3642d9fd380Sjfb8856606 if (ret) {
3652d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
3662d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
3672d9fd380Sjfb8856606 return ret;
3682d9fd380Sjfb8856606 }
3692d9fd380Sjfb8856606 dev_link = (struct rte_eth_link) {
3702d9fd380Sjfb8856606 .link_status = ((ifr.ifr_flags & IFF_UP) &&
3712d9fd380Sjfb8856606 (ifr.ifr_flags & IFF_RUNNING)),
3722d9fd380Sjfb8856606 };
3732d9fd380Sjfb8856606 ifr = (struct ifreq) {
3742d9fd380Sjfb8856606 .ifr_data = (void *)&edata,
3752d9fd380Sjfb8856606 };
3762d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
3772d9fd380Sjfb8856606 if (ret) {
3782d9fd380Sjfb8856606 if (ret == -ENOTSUP && priv->representor) {
3792d9fd380Sjfb8856606 struct rte_eth_dev *master;
3802d9fd380Sjfb8856606
3812d9fd380Sjfb8856606 /*
3822d9fd380Sjfb8856606 * For representors we can try to inherit link
3832d9fd380Sjfb8856606 * settings from the master device. Actually
3842d9fd380Sjfb8856606 * link settings do not make a lot of sense
3852d9fd380Sjfb8856606 * for representors due to missing physical
3862d9fd380Sjfb8856606 * link. The old kernel drivers supported
3872d9fd380Sjfb8856606 * emulated settings query for representors,
3882d9fd380Sjfb8856606 * the new ones do not, so we have to add
3892d9fd380Sjfb8856606 * this code for compatibility issues.
3902d9fd380Sjfb8856606 */
3912d9fd380Sjfb8856606 master = mlx5_find_master_dev(dev);
3922d9fd380Sjfb8856606 if (master) {
3932d9fd380Sjfb8856606 ifr = (struct ifreq) {
3942d9fd380Sjfb8856606 .ifr_data = (void *)&edata,
3952d9fd380Sjfb8856606 };
3962d9fd380Sjfb8856606 ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
3972d9fd380Sjfb8856606 }
3982d9fd380Sjfb8856606 }
3992d9fd380Sjfb8856606 if (ret) {
4002d9fd380Sjfb8856606 DRV_LOG(WARNING,
4012d9fd380Sjfb8856606 "port %u ioctl(SIOCETHTOOL,"
4022d9fd380Sjfb8856606 " ETHTOOL_GSET) failed: %s",
4032d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
4042d9fd380Sjfb8856606 return ret;
4052d9fd380Sjfb8856606 }
4062d9fd380Sjfb8856606 }
4072d9fd380Sjfb8856606 link_speed = ethtool_cmd_speed(&edata);
4082d9fd380Sjfb8856606 if (link_speed == -1)
4092d9fd380Sjfb8856606 dev_link.link_speed = ETH_SPEED_NUM_UNKNOWN;
4102d9fd380Sjfb8856606 else
4112d9fd380Sjfb8856606 dev_link.link_speed = link_speed;
4122d9fd380Sjfb8856606 priv->link_speed_capa = 0;
4132d9fd380Sjfb8856606 if (edata.supported & SUPPORTED_Autoneg)
4142d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
4152d9fd380Sjfb8856606 if (edata.supported & (SUPPORTED_1000baseT_Full |
4162d9fd380Sjfb8856606 SUPPORTED_1000baseKX_Full))
4172d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_1G;
4182d9fd380Sjfb8856606 if (edata.supported & SUPPORTED_10000baseKR_Full)
4192d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_10G;
4202d9fd380Sjfb8856606 if (edata.supported & (SUPPORTED_40000baseKR4_Full |
4212d9fd380Sjfb8856606 SUPPORTED_40000baseCR4_Full |
4222d9fd380Sjfb8856606 SUPPORTED_40000baseSR4_Full |
4232d9fd380Sjfb8856606 SUPPORTED_40000baseLR4_Full))
4242d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_40G;
4252d9fd380Sjfb8856606 dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
4262d9fd380Sjfb8856606 ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
4272d9fd380Sjfb8856606 dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
4282d9fd380Sjfb8856606 ETH_LINK_SPEED_FIXED);
4292d9fd380Sjfb8856606 *link = dev_link;
4302d9fd380Sjfb8856606 return 0;
4312d9fd380Sjfb8856606 }
4322d9fd380Sjfb8856606
4332d9fd380Sjfb8856606 /**
4342d9fd380Sjfb8856606 * Retrieve physical link information (unlocked version using new ioctl).
4352d9fd380Sjfb8856606 *
4362d9fd380Sjfb8856606 * @param dev
4372d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
4382d9fd380Sjfb8856606 * @param[out] link
4392d9fd380Sjfb8856606 * Storage for current link status.
4402d9fd380Sjfb8856606 *
4412d9fd380Sjfb8856606 * @return
4422d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
4432d9fd380Sjfb8856606 */
4442d9fd380Sjfb8856606 static int
mlx5_link_update_unlocked_gs(struct rte_eth_dev * dev,struct rte_eth_link * link)4452d9fd380Sjfb8856606 mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
4462d9fd380Sjfb8856606 struct rte_eth_link *link)
4472d9fd380Sjfb8856606
4482d9fd380Sjfb8856606 {
4492d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
4502d9fd380Sjfb8856606 struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
4512d9fd380Sjfb8856606 struct ifreq ifr;
4522d9fd380Sjfb8856606 struct rte_eth_link dev_link;
4532d9fd380Sjfb8856606 struct rte_eth_dev *master = NULL;
4542d9fd380Sjfb8856606 uint64_t sc;
4552d9fd380Sjfb8856606 int ret;
4562d9fd380Sjfb8856606
4572d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
4582d9fd380Sjfb8856606 if (ret) {
4592d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
4602d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
4612d9fd380Sjfb8856606 return ret;
4622d9fd380Sjfb8856606 }
4632d9fd380Sjfb8856606 dev_link = (struct rte_eth_link) {
4642d9fd380Sjfb8856606 .link_status = ((ifr.ifr_flags & IFF_UP) &&
4652d9fd380Sjfb8856606 (ifr.ifr_flags & IFF_RUNNING)),
4662d9fd380Sjfb8856606 };
4672d9fd380Sjfb8856606 ifr = (struct ifreq) {
4682d9fd380Sjfb8856606 .ifr_data = (void *)&gcmd,
4692d9fd380Sjfb8856606 };
4702d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
4712d9fd380Sjfb8856606 if (ret) {
4722d9fd380Sjfb8856606 if (ret == -ENOTSUP && priv->representor) {
4732d9fd380Sjfb8856606 /*
4742d9fd380Sjfb8856606 * For representors we can try to inherit link
4752d9fd380Sjfb8856606 * settings from the master device. Actually
4762d9fd380Sjfb8856606 * link settings do not make a lot of sense
4772d9fd380Sjfb8856606 * for representors due to missing physical
4782d9fd380Sjfb8856606 * link. The old kernel drivers supported
4792d9fd380Sjfb8856606 * emulated settings query for representors,
4802d9fd380Sjfb8856606 * the new ones do not, so we have to add
4812d9fd380Sjfb8856606 * this code for compatibility issues.
4822d9fd380Sjfb8856606 */
4832d9fd380Sjfb8856606 master = mlx5_find_master_dev(dev);
4842d9fd380Sjfb8856606 if (master) {
4852d9fd380Sjfb8856606 ifr = (struct ifreq) {
4862d9fd380Sjfb8856606 .ifr_data = (void *)&gcmd,
4872d9fd380Sjfb8856606 };
4882d9fd380Sjfb8856606 ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
4892d9fd380Sjfb8856606 }
4902d9fd380Sjfb8856606 }
4912d9fd380Sjfb8856606 if (ret) {
4922d9fd380Sjfb8856606 DRV_LOG(DEBUG,
4932d9fd380Sjfb8856606 "port %u ioctl(SIOCETHTOOL,"
4942d9fd380Sjfb8856606 " ETHTOOL_GLINKSETTINGS) failed: %s",
4952d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
4962d9fd380Sjfb8856606 return ret;
4972d9fd380Sjfb8856606 }
4982d9fd380Sjfb8856606 }
4992d9fd380Sjfb8856606 gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
5002d9fd380Sjfb8856606
5012d9fd380Sjfb8856606 alignas(struct ethtool_link_settings)
5022d9fd380Sjfb8856606 uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
5032d9fd380Sjfb8856606 sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
5042d9fd380Sjfb8856606 struct ethtool_link_settings *ecmd = (void *)data;
5052d9fd380Sjfb8856606
5062d9fd380Sjfb8856606 *ecmd = gcmd;
5072d9fd380Sjfb8856606 ifr.ifr_data = (void *)ecmd;
5082d9fd380Sjfb8856606 ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr);
5092d9fd380Sjfb8856606 if (ret) {
5102d9fd380Sjfb8856606 DRV_LOG(DEBUG,
5112d9fd380Sjfb8856606 "port %u ioctl(SIOCETHTOOL,"
5122d9fd380Sjfb8856606 "ETHTOOL_GLINKSETTINGS) failed: %s",
5132d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
5142d9fd380Sjfb8856606 return ret;
5152d9fd380Sjfb8856606 }
5162d9fd380Sjfb8856606 dev_link.link_speed = (ecmd->speed == UINT32_MAX) ?
5172d9fd380Sjfb8856606 ETH_SPEED_NUM_UNKNOWN : ecmd->speed;
5182d9fd380Sjfb8856606 sc = ecmd->link_mode_masks[0] |
5192d9fd380Sjfb8856606 ((uint64_t)ecmd->link_mode_masks[1] << 32);
5202d9fd380Sjfb8856606 priv->link_speed_capa = 0;
5212d9fd380Sjfb8856606 if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
5222d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
5232d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
5242d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
5252d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_1G;
5262d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
5272d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
5282d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
5292d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_10G;
5302d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
5312d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
5322d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_20G;
5332d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
5342d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
5352d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
5362d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
5372d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_40G;
5382d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
5392d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
5402d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
5412d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
5422d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_56G;
5432d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
5442d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
5452d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
5462d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_25G;
5472d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
5482d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
5492d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_50G;
5502d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
5512d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
5522d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
5532d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
5542d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_100G;
5552d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT) |
5562d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT)))
5572d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_200G;
5582d9fd380Sjfb8856606
5592d9fd380Sjfb8856606 sc = ecmd->link_mode_masks[2] |
5602d9fd380Sjfb8856606 ((uint64_t)ecmd->link_mode_masks[3] << 32);
5612d9fd380Sjfb8856606 if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT) |
5622d9fd380Sjfb8856606 MLX5_BITSHIFT
5632d9fd380Sjfb8856606 (ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT) |
5642d9fd380Sjfb8856606 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT)))
5652d9fd380Sjfb8856606 priv->link_speed_capa |= ETH_LINK_SPEED_200G;
5662d9fd380Sjfb8856606 dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
5672d9fd380Sjfb8856606 ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
5682d9fd380Sjfb8856606 dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
5692d9fd380Sjfb8856606 ETH_LINK_SPEED_FIXED);
5702d9fd380Sjfb8856606 *link = dev_link;
5712d9fd380Sjfb8856606 return 0;
5722d9fd380Sjfb8856606 }
5732d9fd380Sjfb8856606
5742d9fd380Sjfb8856606 /**
5752d9fd380Sjfb8856606 * DPDK callback to retrieve physical link information.
5762d9fd380Sjfb8856606 *
5772d9fd380Sjfb8856606 * @param dev
5782d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
5792d9fd380Sjfb8856606 * @param wait_to_complete
5802d9fd380Sjfb8856606 * Wait for request completion.
5812d9fd380Sjfb8856606 *
5822d9fd380Sjfb8856606 * @return
5832d9fd380Sjfb8856606 * 0 if link status was not updated, positive if it was, a negative errno
5842d9fd380Sjfb8856606 * value otherwise and rte_errno is set.
5852d9fd380Sjfb8856606 */
5862d9fd380Sjfb8856606 int
mlx5_link_update(struct rte_eth_dev * dev,int wait_to_complete)5872d9fd380Sjfb8856606 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
5882d9fd380Sjfb8856606 {
5892d9fd380Sjfb8856606 int ret;
5902d9fd380Sjfb8856606 struct rte_eth_link dev_link;
5912d9fd380Sjfb8856606 time_t start_time = time(NULL);
5922d9fd380Sjfb8856606 int retry = MLX5_GET_LINK_STATUS_RETRY_COUNT;
5932d9fd380Sjfb8856606
5942d9fd380Sjfb8856606 do {
5952d9fd380Sjfb8856606 ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
5962d9fd380Sjfb8856606 if (ret == -ENOTSUP)
5972d9fd380Sjfb8856606 ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
5982d9fd380Sjfb8856606 if (ret == 0)
5992d9fd380Sjfb8856606 break;
6002d9fd380Sjfb8856606 /* Handle wait to complete situation. */
6012d9fd380Sjfb8856606 if ((wait_to_complete || retry) && ret == -EAGAIN) {
6022d9fd380Sjfb8856606 if (abs((int)difftime(time(NULL), start_time)) <
6032d9fd380Sjfb8856606 MLX5_LINK_STATUS_TIMEOUT) {
6042d9fd380Sjfb8856606 usleep(0);
6052d9fd380Sjfb8856606 continue;
6062d9fd380Sjfb8856606 } else {
6072d9fd380Sjfb8856606 rte_errno = EBUSY;
6082d9fd380Sjfb8856606 return -rte_errno;
6092d9fd380Sjfb8856606 }
6102d9fd380Sjfb8856606 } else if (ret < 0) {
6112d9fd380Sjfb8856606 return ret;
6122d9fd380Sjfb8856606 }
6132d9fd380Sjfb8856606 } while (wait_to_complete || retry-- > 0);
6142d9fd380Sjfb8856606 ret = !!memcmp(&dev->data->dev_link, &dev_link,
6152d9fd380Sjfb8856606 sizeof(struct rte_eth_link));
6162d9fd380Sjfb8856606 dev->data->dev_link = dev_link;
6172d9fd380Sjfb8856606 return ret;
6182d9fd380Sjfb8856606 }
6192d9fd380Sjfb8856606
6202d9fd380Sjfb8856606 /**
6212d9fd380Sjfb8856606 * DPDK callback to get flow control status.
6222d9fd380Sjfb8856606 *
6232d9fd380Sjfb8856606 * @param dev
6242d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
6252d9fd380Sjfb8856606 * @param[out] fc_conf
6262d9fd380Sjfb8856606 * Flow control output buffer.
6272d9fd380Sjfb8856606 *
6282d9fd380Sjfb8856606 * @return
6292d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
6302d9fd380Sjfb8856606 */
6312d9fd380Sjfb8856606 int
mlx5_dev_get_flow_ctrl(struct rte_eth_dev * dev,struct rte_eth_fc_conf * fc_conf)6322d9fd380Sjfb8856606 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
6332d9fd380Sjfb8856606 {
6342d9fd380Sjfb8856606 struct ifreq ifr;
6352d9fd380Sjfb8856606 struct ethtool_pauseparam ethpause = {
6362d9fd380Sjfb8856606 .cmd = ETHTOOL_GPAUSEPARAM
6372d9fd380Sjfb8856606 };
6382d9fd380Sjfb8856606 int ret;
6392d9fd380Sjfb8856606
6402d9fd380Sjfb8856606 ifr.ifr_data = (void *)ðpause;
6412d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
6422d9fd380Sjfb8856606 if (ret) {
6432d9fd380Sjfb8856606 DRV_LOG(WARNING,
6442d9fd380Sjfb8856606 "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
6452d9fd380Sjfb8856606 " %s",
6462d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
6472d9fd380Sjfb8856606 return ret;
6482d9fd380Sjfb8856606 }
6492d9fd380Sjfb8856606 fc_conf->autoneg = ethpause.autoneg;
6502d9fd380Sjfb8856606 if (ethpause.rx_pause && ethpause.tx_pause)
6512d9fd380Sjfb8856606 fc_conf->mode = RTE_FC_FULL;
6522d9fd380Sjfb8856606 else if (ethpause.rx_pause)
6532d9fd380Sjfb8856606 fc_conf->mode = RTE_FC_RX_PAUSE;
6542d9fd380Sjfb8856606 else if (ethpause.tx_pause)
6552d9fd380Sjfb8856606 fc_conf->mode = RTE_FC_TX_PAUSE;
6562d9fd380Sjfb8856606 else
6572d9fd380Sjfb8856606 fc_conf->mode = RTE_FC_NONE;
6582d9fd380Sjfb8856606 return 0;
6592d9fd380Sjfb8856606 }
6602d9fd380Sjfb8856606
6612d9fd380Sjfb8856606 /**
6622d9fd380Sjfb8856606 * DPDK callback to modify flow control parameters.
6632d9fd380Sjfb8856606 *
6642d9fd380Sjfb8856606 * @param dev
6652d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
6662d9fd380Sjfb8856606 * @param[in] fc_conf
6672d9fd380Sjfb8856606 * Flow control parameters.
6682d9fd380Sjfb8856606 *
6692d9fd380Sjfb8856606 * @return
6702d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
6712d9fd380Sjfb8856606 */
6722d9fd380Sjfb8856606 int
mlx5_dev_set_flow_ctrl(struct rte_eth_dev * dev,struct rte_eth_fc_conf * fc_conf)6732d9fd380Sjfb8856606 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
6742d9fd380Sjfb8856606 {
6752d9fd380Sjfb8856606 struct ifreq ifr;
6762d9fd380Sjfb8856606 struct ethtool_pauseparam ethpause = {
6772d9fd380Sjfb8856606 .cmd = ETHTOOL_SPAUSEPARAM
6782d9fd380Sjfb8856606 };
6792d9fd380Sjfb8856606 int ret;
6802d9fd380Sjfb8856606
6812d9fd380Sjfb8856606 ifr.ifr_data = (void *)ðpause;
6822d9fd380Sjfb8856606 ethpause.autoneg = fc_conf->autoneg;
6832d9fd380Sjfb8856606 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
6842d9fd380Sjfb8856606 (fc_conf->mode & RTE_FC_RX_PAUSE))
6852d9fd380Sjfb8856606 ethpause.rx_pause = 1;
6862d9fd380Sjfb8856606 else
6872d9fd380Sjfb8856606 ethpause.rx_pause = 0;
6882d9fd380Sjfb8856606
6892d9fd380Sjfb8856606 if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
6902d9fd380Sjfb8856606 (fc_conf->mode & RTE_FC_TX_PAUSE))
6912d9fd380Sjfb8856606 ethpause.tx_pause = 1;
6922d9fd380Sjfb8856606 else
6932d9fd380Sjfb8856606 ethpause.tx_pause = 0;
6942d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
6952d9fd380Sjfb8856606 if (ret) {
6962d9fd380Sjfb8856606 DRV_LOG(WARNING,
6972d9fd380Sjfb8856606 "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
6982d9fd380Sjfb8856606 " failed: %s",
6992d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
7002d9fd380Sjfb8856606 return ret;
7012d9fd380Sjfb8856606 }
7022d9fd380Sjfb8856606 return 0;
7032d9fd380Sjfb8856606 }
7042d9fd380Sjfb8856606
7052d9fd380Sjfb8856606 /**
7062d9fd380Sjfb8856606 * Handle asynchronous removal event for entire multiport device.
7072d9fd380Sjfb8856606 *
7082d9fd380Sjfb8856606 * @param sh
7092d9fd380Sjfb8856606 * Infiniband device shared context.
7102d9fd380Sjfb8856606 */
7112d9fd380Sjfb8856606 static void
mlx5_dev_interrupt_device_fatal(struct mlx5_dev_ctx_shared * sh)7122d9fd380Sjfb8856606 mlx5_dev_interrupt_device_fatal(struct mlx5_dev_ctx_shared *sh)
7132d9fd380Sjfb8856606 {
7142d9fd380Sjfb8856606 uint32_t i;
7152d9fd380Sjfb8856606
7162d9fd380Sjfb8856606 for (i = 0; i < sh->max_port; ++i) {
7172d9fd380Sjfb8856606 struct rte_eth_dev *dev;
7182d9fd380Sjfb8856606
7192d9fd380Sjfb8856606 if (sh->port[i].ih_port_id >= RTE_MAX_ETHPORTS) {
7202d9fd380Sjfb8856606 /*
7212d9fd380Sjfb8856606 * Or not existing port either no
7222d9fd380Sjfb8856606 * handler installed for this port.
7232d9fd380Sjfb8856606 */
7242d9fd380Sjfb8856606 continue;
7252d9fd380Sjfb8856606 }
7262d9fd380Sjfb8856606 dev = &rte_eth_devices[sh->port[i].ih_port_id];
7272d9fd380Sjfb8856606 MLX5_ASSERT(dev);
7282d9fd380Sjfb8856606 if (dev->data->dev_conf.intr_conf.rmv)
7292d9fd380Sjfb8856606 rte_eth_dev_callback_process
7302d9fd380Sjfb8856606 (dev, RTE_ETH_EVENT_INTR_RMV, NULL);
7312d9fd380Sjfb8856606 }
7322d9fd380Sjfb8856606 }
7332d9fd380Sjfb8856606
7342d9fd380Sjfb8856606 /**
7352d9fd380Sjfb8856606 * Handle shared asynchronous events the NIC (removal event
7362d9fd380Sjfb8856606 * and link status change). Supports multiport IB device.
7372d9fd380Sjfb8856606 *
7382d9fd380Sjfb8856606 * @param cb_arg
7392d9fd380Sjfb8856606 * Callback argument.
7402d9fd380Sjfb8856606 */
7412d9fd380Sjfb8856606 void
mlx5_dev_interrupt_handler(void * cb_arg)7422d9fd380Sjfb8856606 mlx5_dev_interrupt_handler(void *cb_arg)
7432d9fd380Sjfb8856606 {
7442d9fd380Sjfb8856606 struct mlx5_dev_ctx_shared *sh = cb_arg;
7452d9fd380Sjfb8856606 struct ibv_async_event event;
7462d9fd380Sjfb8856606
7472d9fd380Sjfb8856606 /* Read all message from the IB device and acknowledge them. */
7482d9fd380Sjfb8856606 for (;;) {
7492d9fd380Sjfb8856606 struct rte_eth_dev *dev;
7502d9fd380Sjfb8856606 uint32_t tmp;
7512d9fd380Sjfb8856606
7522d9fd380Sjfb8856606 if (mlx5_glue->get_async_event(sh->ctx, &event))
7532d9fd380Sjfb8856606 break;
7542d9fd380Sjfb8856606 /* Retrieve and check IB port index. */
7552d9fd380Sjfb8856606 tmp = (uint32_t)event.element.port_num;
7562d9fd380Sjfb8856606 if (!tmp && event.event_type == IBV_EVENT_DEVICE_FATAL) {
7572d9fd380Sjfb8856606 /*
7582d9fd380Sjfb8856606 * The DEVICE_FATAL event is called once for
7592d9fd380Sjfb8856606 * entire device without port specifying.
7602d9fd380Sjfb8856606 * We should notify all existing ports.
7612d9fd380Sjfb8856606 */
7622d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
7632d9fd380Sjfb8856606 mlx5_dev_interrupt_device_fatal(sh);
7642d9fd380Sjfb8856606 continue;
7652d9fd380Sjfb8856606 }
7662d9fd380Sjfb8856606 MLX5_ASSERT(tmp && (tmp <= sh->max_port));
7672d9fd380Sjfb8856606 if (!tmp) {
7682d9fd380Sjfb8856606 /* Unsupported device level event. */
7692d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
7702d9fd380Sjfb8856606 DRV_LOG(DEBUG,
7712d9fd380Sjfb8856606 "unsupported common event (type %d)",
7722d9fd380Sjfb8856606 event.event_type);
7732d9fd380Sjfb8856606 continue;
7742d9fd380Sjfb8856606 }
7752d9fd380Sjfb8856606 if (tmp > sh->max_port) {
7762d9fd380Sjfb8856606 /* Invalid IB port index. */
7772d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
7782d9fd380Sjfb8856606 DRV_LOG(DEBUG,
7792d9fd380Sjfb8856606 "cannot handle an event (type %d)"
7802d9fd380Sjfb8856606 "due to invalid IB port index (%u)",
7812d9fd380Sjfb8856606 event.event_type, tmp);
7822d9fd380Sjfb8856606 continue;
7832d9fd380Sjfb8856606 }
7842d9fd380Sjfb8856606 if (sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) {
7852d9fd380Sjfb8856606 /* No handler installed. */
7862d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
7872d9fd380Sjfb8856606 DRV_LOG(DEBUG,
7882d9fd380Sjfb8856606 "cannot handle an event (type %d)"
7892d9fd380Sjfb8856606 "due to no handler installed for port %u",
7902d9fd380Sjfb8856606 event.event_type, tmp);
7912d9fd380Sjfb8856606 continue;
7922d9fd380Sjfb8856606 }
7932d9fd380Sjfb8856606 /* Retrieve ethernet device descriptor. */
7942d9fd380Sjfb8856606 tmp = sh->port[tmp - 1].ih_port_id;
7952d9fd380Sjfb8856606 dev = &rte_eth_devices[tmp];
7962d9fd380Sjfb8856606 MLX5_ASSERT(dev);
7972d9fd380Sjfb8856606 if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
7982d9fd380Sjfb8856606 event.event_type == IBV_EVENT_PORT_ERR) &&
7992d9fd380Sjfb8856606 dev->data->dev_conf.intr_conf.lsc) {
8002d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
8012d9fd380Sjfb8856606 if (mlx5_link_update(dev, 0) == -EAGAIN) {
8022d9fd380Sjfb8856606 usleep(0);
8032d9fd380Sjfb8856606 continue;
8042d9fd380Sjfb8856606 }
8052d9fd380Sjfb8856606 rte_eth_dev_callback_process
8062d9fd380Sjfb8856606 (dev, RTE_ETH_EVENT_INTR_LSC, NULL);
8072d9fd380Sjfb8856606 continue;
8082d9fd380Sjfb8856606 }
8092d9fd380Sjfb8856606 DRV_LOG(DEBUG,
8102d9fd380Sjfb8856606 "port %u cannot handle an unknown event (type %d)",
8112d9fd380Sjfb8856606 dev->data->port_id, event.event_type);
8122d9fd380Sjfb8856606 mlx5_glue->ack_async_event(&event);
8132d9fd380Sjfb8856606 }
8142d9fd380Sjfb8856606 }
8152d9fd380Sjfb8856606
8162d9fd380Sjfb8856606 /*
8172d9fd380Sjfb8856606 * Unregister callback handler safely. The handler may be active
8182d9fd380Sjfb8856606 * while we are trying to unregister it, in this case code -EAGAIN
8192d9fd380Sjfb8856606 * is returned by rte_intr_callback_unregister(). This routine checks
8202d9fd380Sjfb8856606 * the return code and tries to unregister handler again.
8212d9fd380Sjfb8856606 *
8222d9fd380Sjfb8856606 * @param handle
8232d9fd380Sjfb8856606 * interrupt handle
8242d9fd380Sjfb8856606 * @param cb_fn
8252d9fd380Sjfb8856606 * pointer to callback routine
8262d9fd380Sjfb8856606 * @cb_arg
8272d9fd380Sjfb8856606 * opaque callback parameter
8282d9fd380Sjfb8856606 */
8292d9fd380Sjfb8856606 void
mlx5_intr_callback_unregister(const struct rte_intr_handle * handle,rte_intr_callback_fn cb_fn,void * cb_arg)8302d9fd380Sjfb8856606 mlx5_intr_callback_unregister(const struct rte_intr_handle *handle,
8312d9fd380Sjfb8856606 rte_intr_callback_fn cb_fn, void *cb_arg)
8322d9fd380Sjfb8856606 {
8332d9fd380Sjfb8856606 /*
8342d9fd380Sjfb8856606 * Try to reduce timeout management overhead by not calling
8352d9fd380Sjfb8856606 * the timer related routines on the first iteration. If the
8362d9fd380Sjfb8856606 * unregistering succeeds on first call there will be no
8372d9fd380Sjfb8856606 * timer calls at all.
8382d9fd380Sjfb8856606 */
8392d9fd380Sjfb8856606 uint64_t twait = 0;
8402d9fd380Sjfb8856606 uint64_t start = 0;
8412d9fd380Sjfb8856606
8422d9fd380Sjfb8856606 do {
8432d9fd380Sjfb8856606 int ret;
8442d9fd380Sjfb8856606
8452d9fd380Sjfb8856606 ret = rte_intr_callback_unregister(handle, cb_fn, cb_arg);
8462d9fd380Sjfb8856606 if (ret >= 0)
8472d9fd380Sjfb8856606 return;
8482d9fd380Sjfb8856606 if (ret != -EAGAIN) {
8492d9fd380Sjfb8856606 DRV_LOG(INFO, "failed to unregister interrupt"
8502d9fd380Sjfb8856606 " handler (error: %d)", ret);
8512d9fd380Sjfb8856606 MLX5_ASSERT(false);
8522d9fd380Sjfb8856606 return;
8532d9fd380Sjfb8856606 }
8542d9fd380Sjfb8856606 if (twait) {
8552d9fd380Sjfb8856606 struct timespec onems;
8562d9fd380Sjfb8856606
8572d9fd380Sjfb8856606 /* Wait one millisecond and try again. */
8582d9fd380Sjfb8856606 onems.tv_sec = 0;
8592d9fd380Sjfb8856606 onems.tv_nsec = NS_PER_S / MS_PER_S;
8602d9fd380Sjfb8856606 nanosleep(&onems, 0);
8612d9fd380Sjfb8856606 /* Check whether one second elapsed. */
8622d9fd380Sjfb8856606 if ((rte_get_timer_cycles() - start) <= twait)
8632d9fd380Sjfb8856606 continue;
8642d9fd380Sjfb8856606 } else {
8652d9fd380Sjfb8856606 /*
8662d9fd380Sjfb8856606 * We get the amount of timer ticks for one second.
8672d9fd380Sjfb8856606 * If this amount elapsed it means we spent one
8682d9fd380Sjfb8856606 * second in waiting. This branch is executed once
8692d9fd380Sjfb8856606 * on first iteration.
8702d9fd380Sjfb8856606 */
8712d9fd380Sjfb8856606 twait = rte_get_timer_hz();
8722d9fd380Sjfb8856606 MLX5_ASSERT(twait);
8732d9fd380Sjfb8856606 }
8742d9fd380Sjfb8856606 /*
8752d9fd380Sjfb8856606 * Timeout elapsed, show message (once a second) and retry.
8762d9fd380Sjfb8856606 * We have no other acceptable option here, if we ignore
8772d9fd380Sjfb8856606 * the unregistering return code the handler will not
8782d9fd380Sjfb8856606 * be unregistered, fd will be closed and we may get the
8792d9fd380Sjfb8856606 * crush. Hanging and messaging in the loop seems not to be
8802d9fd380Sjfb8856606 * the worst choice.
8812d9fd380Sjfb8856606 */
8822d9fd380Sjfb8856606 DRV_LOG(INFO, "Retrying to unregister interrupt handler");
8832d9fd380Sjfb8856606 start = rte_get_timer_cycles();
8842d9fd380Sjfb8856606 } while (true);
8852d9fd380Sjfb8856606 }
8862d9fd380Sjfb8856606
8872d9fd380Sjfb8856606 /**
8882d9fd380Sjfb8856606 * Handle DEVX interrupts from the NIC.
8892d9fd380Sjfb8856606 * This function is probably called from the DPDK host thread.
8902d9fd380Sjfb8856606 *
8912d9fd380Sjfb8856606 * @param cb_arg
8922d9fd380Sjfb8856606 * Callback argument.
8932d9fd380Sjfb8856606 */
8942d9fd380Sjfb8856606 void
mlx5_dev_interrupt_handler_devx(void * cb_arg)8952d9fd380Sjfb8856606 mlx5_dev_interrupt_handler_devx(void *cb_arg)
8962d9fd380Sjfb8856606 {
8972d9fd380Sjfb8856606 #ifndef HAVE_IBV_DEVX_ASYNC
8982d9fd380Sjfb8856606 (void)cb_arg;
8992d9fd380Sjfb8856606 return;
9002d9fd380Sjfb8856606 #else
9012d9fd380Sjfb8856606 struct mlx5_dev_ctx_shared *sh = cb_arg;
9022d9fd380Sjfb8856606 union {
9032d9fd380Sjfb8856606 struct mlx5dv_devx_async_cmd_hdr cmd_resp;
9042d9fd380Sjfb8856606 uint8_t buf[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
9052d9fd380Sjfb8856606 MLX5_ST_SZ_BYTES(traffic_counter) +
9062d9fd380Sjfb8856606 sizeof(struct mlx5dv_devx_async_cmd_hdr)];
9072d9fd380Sjfb8856606 } out;
9082d9fd380Sjfb8856606 uint8_t *buf = out.buf + sizeof(out.cmd_resp);
9092d9fd380Sjfb8856606
9102d9fd380Sjfb8856606 while (!mlx5_glue->devx_get_async_cmd_comp(sh->devx_comp,
9112d9fd380Sjfb8856606 &out.cmd_resp,
9122d9fd380Sjfb8856606 sizeof(out.buf)))
9132d9fd380Sjfb8856606 mlx5_flow_async_pool_query_handle
9142d9fd380Sjfb8856606 (sh, (uint64_t)out.cmd_resp.wr_id,
9152d9fd380Sjfb8856606 mlx5_devx_get_out_command_status(buf));
9162d9fd380Sjfb8856606 #endif /* HAVE_IBV_DEVX_ASYNC */
9172d9fd380Sjfb8856606 }
9182d9fd380Sjfb8856606
9192d9fd380Sjfb8856606 /**
9202d9fd380Sjfb8856606 * DPDK callback to bring the link DOWN.
9212d9fd380Sjfb8856606 *
9222d9fd380Sjfb8856606 * @param dev
9232d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
9242d9fd380Sjfb8856606 *
9252d9fd380Sjfb8856606 * @return
9262d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
9272d9fd380Sjfb8856606 */
9282d9fd380Sjfb8856606 int
mlx5_set_link_down(struct rte_eth_dev * dev)9292d9fd380Sjfb8856606 mlx5_set_link_down(struct rte_eth_dev *dev)
9302d9fd380Sjfb8856606 {
9312d9fd380Sjfb8856606 return mlx5_set_flags(dev, ~IFF_UP, ~IFF_UP);
9322d9fd380Sjfb8856606 }
9332d9fd380Sjfb8856606
9342d9fd380Sjfb8856606 /**
9352d9fd380Sjfb8856606 * DPDK callback to bring the link UP.
9362d9fd380Sjfb8856606 *
9372d9fd380Sjfb8856606 * @param dev
9382d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
9392d9fd380Sjfb8856606 *
9402d9fd380Sjfb8856606 * @return
9412d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
9422d9fd380Sjfb8856606 */
9432d9fd380Sjfb8856606 int
mlx5_set_link_up(struct rte_eth_dev * dev)9442d9fd380Sjfb8856606 mlx5_set_link_up(struct rte_eth_dev *dev)
9452d9fd380Sjfb8856606 {
9462d9fd380Sjfb8856606 return mlx5_set_flags(dev, ~IFF_UP, IFF_UP);
9472d9fd380Sjfb8856606 }
9482d9fd380Sjfb8856606
9492d9fd380Sjfb8856606 /**
9502d9fd380Sjfb8856606 * Check if mlx5 device was removed.
9512d9fd380Sjfb8856606 *
9522d9fd380Sjfb8856606 * @param dev
9532d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
9542d9fd380Sjfb8856606 *
9552d9fd380Sjfb8856606 * @return
9562d9fd380Sjfb8856606 * 1 when device is removed, otherwise 0.
9572d9fd380Sjfb8856606 */
9582d9fd380Sjfb8856606 int
mlx5_is_removed(struct rte_eth_dev * dev)9592d9fd380Sjfb8856606 mlx5_is_removed(struct rte_eth_dev *dev)
9602d9fd380Sjfb8856606 {
9612d9fd380Sjfb8856606 struct ibv_device_attr device_attr;
9622d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
9632d9fd380Sjfb8856606
9642d9fd380Sjfb8856606 if (mlx5_glue->query_device(priv->sh->ctx, &device_attr) == EIO)
9652d9fd380Sjfb8856606 return 1;
9662d9fd380Sjfb8856606 return 0;
9672d9fd380Sjfb8856606 }
9682d9fd380Sjfb8856606
9692d9fd380Sjfb8856606 /**
9702d9fd380Sjfb8856606 * Analyze gathered port parameters via sysfs to recognize master
9712d9fd380Sjfb8856606 * and representor devices for E-Switch configuration.
9722d9fd380Sjfb8856606 *
9732d9fd380Sjfb8856606 * @param[in] device_dir
9742d9fd380Sjfb8856606 * flag of presence of "device" directory under port device key.
9752d9fd380Sjfb8856606 * @param[inout] switch_info
9762d9fd380Sjfb8856606 * Port information, including port name as a number and port name
9772d9fd380Sjfb8856606 * type if recognized
9782d9fd380Sjfb8856606 *
9792d9fd380Sjfb8856606 * @return
9802d9fd380Sjfb8856606 * master and representor flags are set in switch_info according to
9812d9fd380Sjfb8856606 * recognized parameters (if any).
9822d9fd380Sjfb8856606 */
9832d9fd380Sjfb8856606 static void
mlx5_sysfs_check_switch_info(bool device_dir,struct mlx5_switch_info * switch_info)9842d9fd380Sjfb8856606 mlx5_sysfs_check_switch_info(bool device_dir,
9852d9fd380Sjfb8856606 struct mlx5_switch_info *switch_info)
9862d9fd380Sjfb8856606 {
9872d9fd380Sjfb8856606 switch (switch_info->name_type) {
9882d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
9892d9fd380Sjfb8856606 /*
9902d9fd380Sjfb8856606 * Name is not recognized, assume the master,
9912d9fd380Sjfb8856606 * check the device directory presence.
9922d9fd380Sjfb8856606 */
9932d9fd380Sjfb8856606 switch_info->master = device_dir;
9942d9fd380Sjfb8856606 break;
9952d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_NOTSET:
9962d9fd380Sjfb8856606 /*
9972d9fd380Sjfb8856606 * Name is not set, this assumes the legacy naming
9982d9fd380Sjfb8856606 * schema for master, just check if there is
9992d9fd380Sjfb8856606 * a device directory.
10002d9fd380Sjfb8856606 */
10012d9fd380Sjfb8856606 switch_info->master = device_dir;
10022d9fd380Sjfb8856606 break;
10032d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
10042d9fd380Sjfb8856606 /* New uplink naming schema recognized. */
10052d9fd380Sjfb8856606 switch_info->master = 1;
10062d9fd380Sjfb8856606 break;
10072d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_LEGACY:
10082d9fd380Sjfb8856606 /* Legacy representors naming schema. */
10092d9fd380Sjfb8856606 switch_info->representor = !device_dir;
10102d9fd380Sjfb8856606 break;
10112d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_PFHPF:
10122d9fd380Sjfb8856606 /* Fallthrough */
10132d9fd380Sjfb8856606 case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
10142d9fd380Sjfb8856606 /* New representors naming schema. */
10152d9fd380Sjfb8856606 switch_info->representor = 1;
10162d9fd380Sjfb8856606 break;
10172d9fd380Sjfb8856606 }
10182d9fd380Sjfb8856606 }
10192d9fd380Sjfb8856606
10202d9fd380Sjfb8856606 /**
10212d9fd380Sjfb8856606 * Get switch information associated with network interface.
10222d9fd380Sjfb8856606 *
10232d9fd380Sjfb8856606 * @param ifindex
10242d9fd380Sjfb8856606 * Network interface index.
10252d9fd380Sjfb8856606 * @param[out] info
10262d9fd380Sjfb8856606 * Switch information object, populated in case of success.
10272d9fd380Sjfb8856606 *
10282d9fd380Sjfb8856606 * @return
10292d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
10302d9fd380Sjfb8856606 */
1031*16a456d6Sfengbojiang static int (*real_if_indextoname)(unsigned int, char *);
10322d9fd380Sjfb8856606 int
mlx5_sysfs_switch_info(unsigned int ifindex,struct mlx5_switch_info * info)10332d9fd380Sjfb8856606 mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
10342d9fd380Sjfb8856606 {
10352d9fd380Sjfb8856606 char ifname[IF_NAMESIZE];
10362d9fd380Sjfb8856606 char port_name[IF_NAMESIZE];
10372d9fd380Sjfb8856606 FILE *file;
10382d9fd380Sjfb8856606 struct mlx5_switch_info data = {
10392d9fd380Sjfb8856606 .master = 0,
10402d9fd380Sjfb8856606 .representor = 0,
10412d9fd380Sjfb8856606 .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,
10422d9fd380Sjfb8856606 .port_name = 0,
10432d9fd380Sjfb8856606 .switch_id = 0,
10442d9fd380Sjfb8856606 };
10452d9fd380Sjfb8856606 DIR *dir;
10462d9fd380Sjfb8856606 bool port_switch_id_set = false;
10472d9fd380Sjfb8856606 bool device_dir = false;
10482d9fd380Sjfb8856606 char c;
10492d9fd380Sjfb8856606 int ret;
10502d9fd380Sjfb8856606
1051*16a456d6Sfengbojiang // for ff tools
1052*16a456d6Sfengbojiang if (!real_if_indextoname) {
1053*16a456d6Sfengbojiang real_if_indextoname = dlsym(RTLD_NEXT, "if_indextoname");
1054*16a456d6Sfengbojiang if (!real_if_indextoname) {
1055*16a456d6Sfengbojiang rte_errno = errno;
1056*16a456d6Sfengbojiang return -rte_errno;
1057*16a456d6Sfengbojiang }
1058*16a456d6Sfengbojiang }
1059*16a456d6Sfengbojiang
1060*16a456d6Sfengbojiang if (!real_if_indextoname(ifindex, ifname)) {
10612d9fd380Sjfb8856606 rte_errno = errno;
10622d9fd380Sjfb8856606 return -rte_errno;
10632d9fd380Sjfb8856606 }
10642d9fd380Sjfb8856606
10652d9fd380Sjfb8856606 MKSTR(phys_port_name, "/sys/class/net/%s/phys_port_name",
10662d9fd380Sjfb8856606 ifname);
10672d9fd380Sjfb8856606 MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id",
10682d9fd380Sjfb8856606 ifname);
10692d9fd380Sjfb8856606 MKSTR(pci_device, "/sys/class/net/%s/device",
10702d9fd380Sjfb8856606 ifname);
10712d9fd380Sjfb8856606
10722d9fd380Sjfb8856606 file = fopen(phys_port_name, "rb");
10732d9fd380Sjfb8856606 if (file != NULL) {
10742d9fd380Sjfb8856606 ret = fscanf(file, "%" RTE_STR(IF_NAMESIZE) "s", port_name);
10752d9fd380Sjfb8856606 fclose(file);
10762d9fd380Sjfb8856606 if (ret == 1)
10772d9fd380Sjfb8856606 mlx5_translate_port_name(port_name, &data);
10782d9fd380Sjfb8856606 }
10792d9fd380Sjfb8856606 file = fopen(phys_switch_id, "rb");
10802d9fd380Sjfb8856606 if (file == NULL) {
10812d9fd380Sjfb8856606 rte_errno = errno;
10822d9fd380Sjfb8856606 return -rte_errno;
10832d9fd380Sjfb8856606 }
10842d9fd380Sjfb8856606 port_switch_id_set =
10852d9fd380Sjfb8856606 fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 &&
10862d9fd380Sjfb8856606 c == '\n';
10872d9fd380Sjfb8856606 fclose(file);
10882d9fd380Sjfb8856606 dir = opendir(pci_device);
10892d9fd380Sjfb8856606 if (dir != NULL) {
10902d9fd380Sjfb8856606 closedir(dir);
10912d9fd380Sjfb8856606 device_dir = true;
10922d9fd380Sjfb8856606 }
10932d9fd380Sjfb8856606 if (port_switch_id_set) {
10942d9fd380Sjfb8856606 /* We have some E-Switch configuration. */
10952d9fd380Sjfb8856606 mlx5_sysfs_check_switch_info(device_dir, &data);
10962d9fd380Sjfb8856606 }
10972d9fd380Sjfb8856606 *info = data;
10982d9fd380Sjfb8856606 MLX5_ASSERT(!(data.master && data.representor));
10992d9fd380Sjfb8856606 if (data.master && data.representor) {
11002d9fd380Sjfb8856606 DRV_LOG(ERR, "ifindex %u device is recognized as master"
11012d9fd380Sjfb8856606 " and as representor", ifindex);
11022d9fd380Sjfb8856606 rte_errno = ENODEV;
11032d9fd380Sjfb8856606 return -rte_errno;
11042d9fd380Sjfb8856606 }
11052d9fd380Sjfb8856606 return 0;
11062d9fd380Sjfb8856606 }
11072d9fd380Sjfb8856606
11082d9fd380Sjfb8856606 /**
11092d9fd380Sjfb8856606 * Get bond information associated with network interface.
11102d9fd380Sjfb8856606 *
11112d9fd380Sjfb8856606 * @param pf_ifindex
11122d9fd380Sjfb8856606 * Network interface index of bond slave interface
11132d9fd380Sjfb8856606 * @param[out] ifindex
11142d9fd380Sjfb8856606 * Pointer to bond ifindex.
11152d9fd380Sjfb8856606 * @param[out] ifname
11162d9fd380Sjfb8856606 * Pointer to bond ifname.
11172d9fd380Sjfb8856606 *
11182d9fd380Sjfb8856606 * @return
11192d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
11202d9fd380Sjfb8856606 */
11212d9fd380Sjfb8856606 int
mlx5_sysfs_bond_info(unsigned int pf_ifindex,unsigned int * ifindex,char * ifname)11222d9fd380Sjfb8856606 mlx5_sysfs_bond_info(unsigned int pf_ifindex, unsigned int *ifindex,
11232d9fd380Sjfb8856606 char *ifname)
11242d9fd380Sjfb8856606 {
11252d9fd380Sjfb8856606 char name[IF_NAMESIZE];
11262d9fd380Sjfb8856606 FILE *file;
11272d9fd380Sjfb8856606 unsigned int index;
11282d9fd380Sjfb8856606 int ret;
11292d9fd380Sjfb8856606
11302d9fd380Sjfb8856606 if (!if_indextoname(pf_ifindex, name) || !strlen(name)) {
11312d9fd380Sjfb8856606 rte_errno = errno;
11322d9fd380Sjfb8856606 return -rte_errno;
11332d9fd380Sjfb8856606 }
11342d9fd380Sjfb8856606 MKSTR(bond_if, "/sys/class/net/%s/master/ifindex", name);
11352d9fd380Sjfb8856606 /* read bond ifindex */
11362d9fd380Sjfb8856606 file = fopen(bond_if, "rb");
11372d9fd380Sjfb8856606 if (file == NULL) {
11382d9fd380Sjfb8856606 rte_errno = errno;
11392d9fd380Sjfb8856606 return -rte_errno;
11402d9fd380Sjfb8856606 }
11412d9fd380Sjfb8856606 ret = fscanf(file, "%u", &index);
11422d9fd380Sjfb8856606 fclose(file);
11432d9fd380Sjfb8856606 if (ret <= 0) {
11442d9fd380Sjfb8856606 rte_errno = errno;
11452d9fd380Sjfb8856606 return -rte_errno;
11462d9fd380Sjfb8856606 }
11472d9fd380Sjfb8856606 if (ifindex)
11482d9fd380Sjfb8856606 *ifindex = index;
11492d9fd380Sjfb8856606
11502d9fd380Sjfb8856606 /* read bond device name from symbol link */
11512d9fd380Sjfb8856606 if (ifname) {
11522d9fd380Sjfb8856606 if (!if_indextoname(index, ifname)) {
11532d9fd380Sjfb8856606 rte_errno = errno;
11542d9fd380Sjfb8856606 return -rte_errno;
11552d9fd380Sjfb8856606 }
11562d9fd380Sjfb8856606 }
11572d9fd380Sjfb8856606 return 0;
11582d9fd380Sjfb8856606 }
11592d9fd380Sjfb8856606
11602d9fd380Sjfb8856606 /**
11612d9fd380Sjfb8856606 * DPDK callback to retrieve plug-in module EEPROM information (type and size).
11622d9fd380Sjfb8856606 *
11632d9fd380Sjfb8856606 * @param dev
11642d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
11652d9fd380Sjfb8856606 * @param[out] modinfo
11662d9fd380Sjfb8856606 * Storage for plug-in module EEPROM information.
11672d9fd380Sjfb8856606 *
11682d9fd380Sjfb8856606 * @return
11692d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
11702d9fd380Sjfb8856606 */
11712d9fd380Sjfb8856606 int
mlx5_get_module_info(struct rte_eth_dev * dev,struct rte_eth_dev_module_info * modinfo)11722d9fd380Sjfb8856606 mlx5_get_module_info(struct rte_eth_dev *dev,
11732d9fd380Sjfb8856606 struct rte_eth_dev_module_info *modinfo)
11742d9fd380Sjfb8856606 {
11752d9fd380Sjfb8856606 struct ethtool_modinfo info = {
11762d9fd380Sjfb8856606 .cmd = ETHTOOL_GMODULEINFO,
11772d9fd380Sjfb8856606 };
11782d9fd380Sjfb8856606 struct ifreq ifr = (struct ifreq) {
11792d9fd380Sjfb8856606 .ifr_data = (void *)&info,
11802d9fd380Sjfb8856606 };
11812d9fd380Sjfb8856606 int ret = 0;
11822d9fd380Sjfb8856606
11832d9fd380Sjfb8856606 if (!dev || !modinfo) {
11842d9fd380Sjfb8856606 DRV_LOG(WARNING, "missing argument, cannot get module info");
11852d9fd380Sjfb8856606 rte_errno = EINVAL;
11862d9fd380Sjfb8856606 return -rte_errno;
11872d9fd380Sjfb8856606 }
11882d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
11892d9fd380Sjfb8856606 if (ret) {
11902d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s",
11912d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
11922d9fd380Sjfb8856606 return ret;
11932d9fd380Sjfb8856606 }
11942d9fd380Sjfb8856606 modinfo->type = info.type;
11952d9fd380Sjfb8856606 modinfo->eeprom_len = info.eeprom_len;
11962d9fd380Sjfb8856606 return ret;
11972d9fd380Sjfb8856606 }
11982d9fd380Sjfb8856606
11992d9fd380Sjfb8856606 /**
12002d9fd380Sjfb8856606 * DPDK callback to retrieve plug-in module EEPROM data.
12012d9fd380Sjfb8856606 *
12022d9fd380Sjfb8856606 * @param dev
12032d9fd380Sjfb8856606 * Pointer to Ethernet device structure.
12042d9fd380Sjfb8856606 * @param[out] info
12052d9fd380Sjfb8856606 * Storage for plug-in module EEPROM data.
12062d9fd380Sjfb8856606 *
12072d9fd380Sjfb8856606 * @return
12082d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
12092d9fd380Sjfb8856606 */
mlx5_get_module_eeprom(struct rte_eth_dev * dev,struct rte_dev_eeprom_info * info)12102d9fd380Sjfb8856606 int mlx5_get_module_eeprom(struct rte_eth_dev *dev,
12112d9fd380Sjfb8856606 struct rte_dev_eeprom_info *info)
12122d9fd380Sjfb8856606 {
12132d9fd380Sjfb8856606 struct ethtool_eeprom *eeprom;
12142d9fd380Sjfb8856606 struct ifreq ifr;
12152d9fd380Sjfb8856606 int ret = 0;
12162d9fd380Sjfb8856606
12172d9fd380Sjfb8856606 if (!dev || !info) {
12182d9fd380Sjfb8856606 DRV_LOG(WARNING, "missing argument, cannot get module eeprom");
12192d9fd380Sjfb8856606 rte_errno = EINVAL;
12202d9fd380Sjfb8856606 return -rte_errno;
12212d9fd380Sjfb8856606 }
12222d9fd380Sjfb8856606 eeprom = mlx5_malloc(MLX5_MEM_ZERO,
12232d9fd380Sjfb8856606 (sizeof(struct ethtool_eeprom) + info->length), 0,
12242d9fd380Sjfb8856606 SOCKET_ID_ANY);
12252d9fd380Sjfb8856606 if (!eeprom) {
12262d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u cannot allocate memory for "
12272d9fd380Sjfb8856606 "eeprom data", dev->data->port_id);
12282d9fd380Sjfb8856606 rte_errno = ENOMEM;
12292d9fd380Sjfb8856606 return -rte_errno;
12302d9fd380Sjfb8856606 }
12312d9fd380Sjfb8856606 eeprom->cmd = ETHTOOL_GMODULEEEPROM;
12322d9fd380Sjfb8856606 eeprom->offset = info->offset;
12332d9fd380Sjfb8856606 eeprom->len = info->length;
12342d9fd380Sjfb8856606 ifr = (struct ifreq) {
12352d9fd380Sjfb8856606 .ifr_data = (void *)eeprom,
12362d9fd380Sjfb8856606 };
12372d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
12382d9fd380Sjfb8856606 if (ret)
12392d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u ioctl(SIOCETHTOOL) failed: %s",
12402d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
12412d9fd380Sjfb8856606 else
12422d9fd380Sjfb8856606 rte_memcpy(info->data, eeprom->data, info->length);
12432d9fd380Sjfb8856606 mlx5_free(eeprom);
12442d9fd380Sjfb8856606 return ret;
12452d9fd380Sjfb8856606 }
12462d9fd380Sjfb8856606
12472d9fd380Sjfb8856606 /**
12482d9fd380Sjfb8856606 * Read device counters table.
12492d9fd380Sjfb8856606 *
12502d9fd380Sjfb8856606 * @param dev
12512d9fd380Sjfb8856606 * Pointer to Ethernet device.
12522d9fd380Sjfb8856606 * @param[out] stats
12532d9fd380Sjfb8856606 * Counters table output buffer.
12542d9fd380Sjfb8856606 *
12552d9fd380Sjfb8856606 * @return
12562d9fd380Sjfb8856606 * 0 on success and stats is filled, negative errno value otherwise and
12572d9fd380Sjfb8856606 * rte_errno is set.
12582d9fd380Sjfb8856606 */
12592d9fd380Sjfb8856606 int
mlx5_os_read_dev_counters(struct rte_eth_dev * dev,uint64_t * stats)12602d9fd380Sjfb8856606 mlx5_os_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
12612d9fd380Sjfb8856606 {
12622d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
12632d9fd380Sjfb8856606 struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
12642d9fd380Sjfb8856606 unsigned int i;
12652d9fd380Sjfb8856606 struct ifreq ifr;
12662d9fd380Sjfb8856606 unsigned int stats_sz = xstats_ctrl->stats_n * sizeof(uint64_t);
12672d9fd380Sjfb8856606 unsigned char et_stat_buf[sizeof(struct ethtool_stats) + stats_sz];
12682d9fd380Sjfb8856606 struct ethtool_stats *et_stats = (struct ethtool_stats *)et_stat_buf;
12692d9fd380Sjfb8856606 int ret;
12702d9fd380Sjfb8856606
12712d9fd380Sjfb8856606 et_stats->cmd = ETHTOOL_GSTATS;
12722d9fd380Sjfb8856606 et_stats->n_stats = xstats_ctrl->stats_n;
12732d9fd380Sjfb8856606 ifr.ifr_data = (caddr_t)et_stats;
12742d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
12752d9fd380Sjfb8856606 if (ret) {
12762d9fd380Sjfb8856606 DRV_LOG(WARNING,
12772d9fd380Sjfb8856606 "port %u unable to read statistic values from device",
12782d9fd380Sjfb8856606 dev->data->port_id);
12792d9fd380Sjfb8856606 return ret;
12802d9fd380Sjfb8856606 }
12812d9fd380Sjfb8856606 for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
12822d9fd380Sjfb8856606 if (xstats_ctrl->info[i].dev) {
12832d9fd380Sjfb8856606 ret = mlx5_os_read_dev_stat(priv,
12842d9fd380Sjfb8856606 xstats_ctrl->info[i].ctr_name,
12852d9fd380Sjfb8856606 &stats[i]);
12862d9fd380Sjfb8856606 /* return last xstats counter if fail to read. */
12872d9fd380Sjfb8856606 if (ret == 0)
12882d9fd380Sjfb8856606 xstats_ctrl->xstats[i] = stats[i];
12892d9fd380Sjfb8856606 else
12902d9fd380Sjfb8856606 stats[i] = xstats_ctrl->xstats[i];
12912d9fd380Sjfb8856606 } else {
12922d9fd380Sjfb8856606 stats[i] = (uint64_t)
12932d9fd380Sjfb8856606 et_stats->data[xstats_ctrl->dev_table_idx[i]];
12942d9fd380Sjfb8856606 }
12952d9fd380Sjfb8856606 }
12962d9fd380Sjfb8856606 return 0;
12972d9fd380Sjfb8856606 }
12982d9fd380Sjfb8856606
12992d9fd380Sjfb8856606 /**
13002d9fd380Sjfb8856606 * Query the number of statistics provided by ETHTOOL.
13012d9fd380Sjfb8856606 *
13022d9fd380Sjfb8856606 * @param dev
13032d9fd380Sjfb8856606 * Pointer to Ethernet device.
13042d9fd380Sjfb8856606 *
13052d9fd380Sjfb8856606 * @return
13062d9fd380Sjfb8856606 * Number of statistics on success, negative errno value otherwise and
13072d9fd380Sjfb8856606 * rte_errno is set.
13082d9fd380Sjfb8856606 */
13092d9fd380Sjfb8856606 int
mlx5_os_get_stats_n(struct rte_eth_dev * dev)13102d9fd380Sjfb8856606 mlx5_os_get_stats_n(struct rte_eth_dev *dev)
13112d9fd380Sjfb8856606 {
13122d9fd380Sjfb8856606 struct ethtool_drvinfo drvinfo;
13132d9fd380Sjfb8856606 struct ifreq ifr;
13142d9fd380Sjfb8856606 int ret;
13152d9fd380Sjfb8856606
13162d9fd380Sjfb8856606 drvinfo.cmd = ETHTOOL_GDRVINFO;
13172d9fd380Sjfb8856606 ifr.ifr_data = (caddr_t)&drvinfo;
13182d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
13192d9fd380Sjfb8856606 if (ret) {
13202d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u unable to query number of statistics",
13212d9fd380Sjfb8856606 dev->data->port_id);
13222d9fd380Sjfb8856606 return ret;
13232d9fd380Sjfb8856606 }
13242d9fd380Sjfb8856606 return drvinfo.n_stats;
13252d9fd380Sjfb8856606 }
13262d9fd380Sjfb8856606
13272d9fd380Sjfb8856606 static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
13282d9fd380Sjfb8856606 {
13292d9fd380Sjfb8856606 .dpdk_name = "rx_unicast_bytes",
13302d9fd380Sjfb8856606 .ctr_name = "rx_vport_unicast_bytes",
13312d9fd380Sjfb8856606 },
13322d9fd380Sjfb8856606 {
13332d9fd380Sjfb8856606 .dpdk_name = "rx_multicast_bytes",
13342d9fd380Sjfb8856606 .ctr_name = "rx_vport_multicast_bytes",
13352d9fd380Sjfb8856606 },
13362d9fd380Sjfb8856606 {
13372d9fd380Sjfb8856606 .dpdk_name = "rx_broadcast_bytes",
13382d9fd380Sjfb8856606 .ctr_name = "rx_vport_broadcast_bytes",
13392d9fd380Sjfb8856606 },
13402d9fd380Sjfb8856606 {
13412d9fd380Sjfb8856606 .dpdk_name = "rx_unicast_packets",
13422d9fd380Sjfb8856606 .ctr_name = "rx_vport_unicast_packets",
13432d9fd380Sjfb8856606 },
13442d9fd380Sjfb8856606 {
13452d9fd380Sjfb8856606 .dpdk_name = "rx_multicast_packets",
13462d9fd380Sjfb8856606 .ctr_name = "rx_vport_multicast_packets",
13472d9fd380Sjfb8856606 },
13482d9fd380Sjfb8856606 {
13492d9fd380Sjfb8856606 .dpdk_name = "rx_broadcast_packets",
13502d9fd380Sjfb8856606 .ctr_name = "rx_vport_broadcast_packets",
13512d9fd380Sjfb8856606 },
13522d9fd380Sjfb8856606 {
13532d9fd380Sjfb8856606 .dpdk_name = "tx_unicast_bytes",
13542d9fd380Sjfb8856606 .ctr_name = "tx_vport_unicast_bytes",
13552d9fd380Sjfb8856606 },
13562d9fd380Sjfb8856606 {
13572d9fd380Sjfb8856606 .dpdk_name = "tx_multicast_bytes",
13582d9fd380Sjfb8856606 .ctr_name = "tx_vport_multicast_bytes",
13592d9fd380Sjfb8856606 },
13602d9fd380Sjfb8856606 {
13612d9fd380Sjfb8856606 .dpdk_name = "tx_broadcast_bytes",
13622d9fd380Sjfb8856606 .ctr_name = "tx_vport_broadcast_bytes",
13632d9fd380Sjfb8856606 },
13642d9fd380Sjfb8856606 {
13652d9fd380Sjfb8856606 .dpdk_name = "tx_unicast_packets",
13662d9fd380Sjfb8856606 .ctr_name = "tx_vport_unicast_packets",
13672d9fd380Sjfb8856606 },
13682d9fd380Sjfb8856606 {
13692d9fd380Sjfb8856606 .dpdk_name = "tx_multicast_packets",
13702d9fd380Sjfb8856606 .ctr_name = "tx_vport_multicast_packets",
13712d9fd380Sjfb8856606 },
13722d9fd380Sjfb8856606 {
13732d9fd380Sjfb8856606 .dpdk_name = "tx_broadcast_packets",
13742d9fd380Sjfb8856606 .ctr_name = "tx_vport_broadcast_packets",
13752d9fd380Sjfb8856606 },
13762d9fd380Sjfb8856606 {
13772d9fd380Sjfb8856606 .dpdk_name = "rx_wqe_errors",
13782d9fd380Sjfb8856606 .ctr_name = "rx_wqe_err",
13792d9fd380Sjfb8856606 },
13802d9fd380Sjfb8856606 {
13812d9fd380Sjfb8856606 .dpdk_name = "rx_phy_crc_errors",
13822d9fd380Sjfb8856606 .ctr_name = "rx_crc_errors_phy",
13832d9fd380Sjfb8856606 },
13842d9fd380Sjfb8856606 {
13852d9fd380Sjfb8856606 .dpdk_name = "rx_phy_in_range_len_errors",
13862d9fd380Sjfb8856606 .ctr_name = "rx_in_range_len_errors_phy",
13872d9fd380Sjfb8856606 },
13882d9fd380Sjfb8856606 {
13892d9fd380Sjfb8856606 .dpdk_name = "rx_phy_symbol_errors",
13902d9fd380Sjfb8856606 .ctr_name = "rx_symbol_err_phy",
13912d9fd380Sjfb8856606 },
13922d9fd380Sjfb8856606 {
13932d9fd380Sjfb8856606 .dpdk_name = "tx_phy_errors",
13942d9fd380Sjfb8856606 .ctr_name = "tx_errors_phy",
13952d9fd380Sjfb8856606 },
13962d9fd380Sjfb8856606 {
13972d9fd380Sjfb8856606 .dpdk_name = "rx_out_of_buffer",
13982d9fd380Sjfb8856606 .ctr_name = "out_of_buffer",
13992d9fd380Sjfb8856606 .dev = 1,
14002d9fd380Sjfb8856606 },
14012d9fd380Sjfb8856606 {
14022d9fd380Sjfb8856606 .dpdk_name = "tx_phy_packets",
14032d9fd380Sjfb8856606 .ctr_name = "tx_packets_phy",
14042d9fd380Sjfb8856606 },
14052d9fd380Sjfb8856606 {
14062d9fd380Sjfb8856606 .dpdk_name = "rx_phy_packets",
14072d9fd380Sjfb8856606 .ctr_name = "rx_packets_phy",
14082d9fd380Sjfb8856606 },
14092d9fd380Sjfb8856606 {
14102d9fd380Sjfb8856606 .dpdk_name = "tx_phy_discard_packets",
14112d9fd380Sjfb8856606 .ctr_name = "tx_discards_phy",
14122d9fd380Sjfb8856606 },
14132d9fd380Sjfb8856606 {
14142d9fd380Sjfb8856606 .dpdk_name = "rx_phy_discard_packets",
14152d9fd380Sjfb8856606 .ctr_name = "rx_discards_phy",
14162d9fd380Sjfb8856606 },
14172d9fd380Sjfb8856606 {
14182d9fd380Sjfb8856606 .dpdk_name = "tx_phy_bytes",
14192d9fd380Sjfb8856606 .ctr_name = "tx_bytes_phy",
14202d9fd380Sjfb8856606 },
14212d9fd380Sjfb8856606 {
14222d9fd380Sjfb8856606 .dpdk_name = "rx_phy_bytes",
14232d9fd380Sjfb8856606 .ctr_name = "rx_bytes_phy",
14242d9fd380Sjfb8856606 },
14252d9fd380Sjfb8856606 /* Representor only */
14262d9fd380Sjfb8856606 {
14272d9fd380Sjfb8856606 .dpdk_name = "rx_vport_packets",
14282d9fd380Sjfb8856606 .ctr_name = "vport_rx_packets",
14292d9fd380Sjfb8856606 },
14302d9fd380Sjfb8856606 {
14312d9fd380Sjfb8856606 .dpdk_name = "rx_vport_bytes",
14322d9fd380Sjfb8856606 .ctr_name = "vport_rx_bytes",
14332d9fd380Sjfb8856606 },
14342d9fd380Sjfb8856606 {
14352d9fd380Sjfb8856606 .dpdk_name = "tx_vport_packets",
14362d9fd380Sjfb8856606 .ctr_name = "vport_tx_packets",
14372d9fd380Sjfb8856606 },
14382d9fd380Sjfb8856606 {
14392d9fd380Sjfb8856606 .dpdk_name = "tx_vport_bytes",
14402d9fd380Sjfb8856606 .ctr_name = "vport_tx_bytes",
14412d9fd380Sjfb8856606 },
14422d9fd380Sjfb8856606 };
14432d9fd380Sjfb8856606
14442d9fd380Sjfb8856606 static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
14452d9fd380Sjfb8856606
14462d9fd380Sjfb8856606 /**
14472d9fd380Sjfb8856606 * Init the structures to read device counters.
14482d9fd380Sjfb8856606 *
14492d9fd380Sjfb8856606 * @param dev
14502d9fd380Sjfb8856606 * Pointer to Ethernet device.
14512d9fd380Sjfb8856606 */
14522d9fd380Sjfb8856606 void
mlx5_os_stats_init(struct rte_eth_dev * dev)14532d9fd380Sjfb8856606 mlx5_os_stats_init(struct rte_eth_dev *dev)
14542d9fd380Sjfb8856606 {
14552d9fd380Sjfb8856606 struct mlx5_priv *priv = dev->data->dev_private;
14562d9fd380Sjfb8856606 struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
14572d9fd380Sjfb8856606 struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
14582d9fd380Sjfb8856606 unsigned int i;
14592d9fd380Sjfb8856606 unsigned int j;
14602d9fd380Sjfb8856606 struct ifreq ifr;
14612d9fd380Sjfb8856606 struct ethtool_gstrings *strings = NULL;
14622d9fd380Sjfb8856606 unsigned int dev_stats_n;
14632d9fd380Sjfb8856606 unsigned int str_sz;
14642d9fd380Sjfb8856606 int ret;
14652d9fd380Sjfb8856606
14662d9fd380Sjfb8856606 /* So that it won't aggregate for each init. */
14672d9fd380Sjfb8856606 xstats_ctrl->mlx5_stats_n = 0;
14682d9fd380Sjfb8856606 ret = mlx5_os_get_stats_n(dev);
14692d9fd380Sjfb8856606 if (ret < 0) {
14702d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u no extended statistics available",
14712d9fd380Sjfb8856606 dev->data->port_id);
14722d9fd380Sjfb8856606 return;
14732d9fd380Sjfb8856606 }
14742d9fd380Sjfb8856606 dev_stats_n = ret;
14752d9fd380Sjfb8856606 /* Allocate memory to grab stat names and values. */
14762d9fd380Sjfb8856606 str_sz = dev_stats_n * ETH_GSTRING_LEN;
14772d9fd380Sjfb8856606 strings = (struct ethtool_gstrings *)
14782d9fd380Sjfb8856606 mlx5_malloc(0, str_sz + sizeof(struct ethtool_gstrings), 0,
14792d9fd380Sjfb8856606 SOCKET_ID_ANY);
14802d9fd380Sjfb8856606 if (!strings) {
14812d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u unable to allocate memory for xstats",
14822d9fd380Sjfb8856606 dev->data->port_id);
14832d9fd380Sjfb8856606 return;
14842d9fd380Sjfb8856606 }
14852d9fd380Sjfb8856606 strings->cmd = ETHTOOL_GSTRINGS;
14862d9fd380Sjfb8856606 strings->string_set = ETH_SS_STATS;
14872d9fd380Sjfb8856606 strings->len = dev_stats_n;
14882d9fd380Sjfb8856606 ifr.ifr_data = (caddr_t)strings;
14892d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
14902d9fd380Sjfb8856606 if (ret) {
14912d9fd380Sjfb8856606 DRV_LOG(WARNING, "port %u unable to get statistic names",
14922d9fd380Sjfb8856606 dev->data->port_id);
14932d9fd380Sjfb8856606 goto free;
14942d9fd380Sjfb8856606 }
14952d9fd380Sjfb8856606 for (i = 0; i != dev_stats_n; ++i) {
14962d9fd380Sjfb8856606 const char *curr_string = (const char *)
14972d9fd380Sjfb8856606 &strings->data[i * ETH_GSTRING_LEN];
14982d9fd380Sjfb8856606
14992d9fd380Sjfb8856606 for (j = 0; j != xstats_n; ++j) {
15002d9fd380Sjfb8856606 if (!strcmp(mlx5_counters_init[j].ctr_name,
15012d9fd380Sjfb8856606 curr_string)) {
15022d9fd380Sjfb8856606 unsigned int idx = xstats_ctrl->mlx5_stats_n++;
15032d9fd380Sjfb8856606
15042d9fd380Sjfb8856606 xstats_ctrl->dev_table_idx[idx] = i;
15052d9fd380Sjfb8856606 xstats_ctrl->info[idx] = mlx5_counters_init[j];
15062d9fd380Sjfb8856606 break;
15072d9fd380Sjfb8856606 }
15082d9fd380Sjfb8856606 }
15092d9fd380Sjfb8856606 }
15102d9fd380Sjfb8856606 /* Add dev counters. */
15112d9fd380Sjfb8856606 for (i = 0; i != xstats_n; ++i) {
15122d9fd380Sjfb8856606 if (mlx5_counters_init[i].dev) {
15132d9fd380Sjfb8856606 unsigned int idx = xstats_ctrl->mlx5_stats_n++;
15142d9fd380Sjfb8856606
15152d9fd380Sjfb8856606 xstats_ctrl->info[idx] = mlx5_counters_init[i];
15162d9fd380Sjfb8856606 xstats_ctrl->hw_stats[idx] = 0;
15172d9fd380Sjfb8856606 }
15182d9fd380Sjfb8856606 }
15192d9fd380Sjfb8856606 MLX5_ASSERT(xstats_ctrl->mlx5_stats_n <= MLX5_MAX_XSTATS);
15202d9fd380Sjfb8856606 xstats_ctrl->stats_n = dev_stats_n;
15212d9fd380Sjfb8856606 /* Copy to base at first time. */
15222d9fd380Sjfb8856606 ret = mlx5_os_read_dev_counters(dev, xstats_ctrl->base);
15232d9fd380Sjfb8856606 if (ret)
15242d9fd380Sjfb8856606 DRV_LOG(ERR, "port %u cannot read device counters: %s",
15252d9fd380Sjfb8856606 dev->data->port_id, strerror(rte_errno));
15262d9fd380Sjfb8856606 mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
15272d9fd380Sjfb8856606 stats_ctrl->imissed = 0;
15282d9fd380Sjfb8856606 free:
15292d9fd380Sjfb8856606 mlx5_free(strings);
15302d9fd380Sjfb8856606 }
15312d9fd380Sjfb8856606
15322d9fd380Sjfb8856606 /**
15332d9fd380Sjfb8856606 * Get MAC address by querying netdevice.
15342d9fd380Sjfb8856606 *
15352d9fd380Sjfb8856606 * @param[in] dev
15362d9fd380Sjfb8856606 * Pointer to Ethernet device.
15372d9fd380Sjfb8856606 * @param[out] mac
15382d9fd380Sjfb8856606 * MAC address output buffer.
15392d9fd380Sjfb8856606 *
15402d9fd380Sjfb8856606 * @return
15412d9fd380Sjfb8856606 * 0 on success, a negative errno value otherwise and rte_errno is set.
15422d9fd380Sjfb8856606 */
15432d9fd380Sjfb8856606 int
mlx5_get_mac(struct rte_eth_dev * dev,uint8_t (* mac)[RTE_ETHER_ADDR_LEN])15442d9fd380Sjfb8856606 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN])
15452d9fd380Sjfb8856606 {
15462d9fd380Sjfb8856606 struct ifreq request;
15472d9fd380Sjfb8856606 int ret;
15482d9fd380Sjfb8856606
15492d9fd380Sjfb8856606 ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request);
15502d9fd380Sjfb8856606 if (ret)
15512d9fd380Sjfb8856606 return ret;
15522d9fd380Sjfb8856606 memcpy(mac, request.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
15532d9fd380Sjfb8856606 return 0;
15542d9fd380Sjfb8856606 }
15552d9fd380Sjfb8856606
1556