-static int
-mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
-
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
- struct ifreq ifr;
- struct rte_eth_link dev_link;
- struct rte_eth_dev *master = NULL;
- uint64_t sc;
- int ret;
-
- ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
- if (ret) {
- DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
- dev->data->port_id, strerror(rte_errno));
- return ret;
- }
- dev_link = (struct rte_eth_link) {
- .link_status = ((ifr.ifr_flags & IFF_UP) &&
- (ifr.ifr_flags & IFF_RUNNING)),
- };
- ifr = (struct ifreq) {
- .ifr_data = (void *)&gcmd,
- };
- ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
- if (ret) {
- if (ret == -ENOTSUP && priv->representor) {
- /*
- * For representors we can try to inherit link
- * settings from the master device. Actually
- * link settings do not make a lot of sense
- * for representors due to missing physical
- * link. The old kernel drivers supported
- * emulated settings query for representors,
- * the new ones do not, so we have to add
- * this code for compatibility issues.
- */
- master = mlx5_find_master_dev(dev);
- if (master) {
- ifr = (struct ifreq) {
- .ifr_data = (void *)&gcmd,
- };
- ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
- }
- }
- if (ret) {
- DRV_LOG(DEBUG,
- "port %u ioctl(SIOCETHTOOL,"
- " ETHTOOL_GLINKSETTINGS) failed: %s",
- dev->data->port_id, strerror(rte_errno));
- return ret;
- }
-
- }
- gcmd.link_mode_masks_nwords = -gcmd.link_mode_masks_nwords;
-
- alignas(struct ethtool_link_settings)
- uint8_t data[offsetof(struct ethtool_link_settings, link_mode_masks) +
- sizeof(uint32_t) * gcmd.link_mode_masks_nwords * 3];
- struct ethtool_link_settings *ecmd = (void *)data;
-
- *ecmd = gcmd;
- ifr.ifr_data = (void *)ecmd;
- ret = mlx5_ifreq(master ? master : dev, SIOCETHTOOL, &ifr);
- if (ret) {
- DRV_LOG(DEBUG,
- "port %u ioctl(SIOCETHTOOL,"
- "ETHTOOL_GLINKSETTINGS) failed: %s",
- dev->data->port_id, strerror(rte_errno));
- return ret;
- }
- dev_link.link_speed = (ecmd->speed == UINT32_MAX) ? ETH_SPEED_NUM_NONE :
- ecmd->speed;
- sc = ecmd->link_mode_masks[0] |
- ((uint64_t)ecmd->link_mode_masks[1] << 32);
- priv->link_speed_capa = 0;
- if (sc & MLX5_BITSHIFT(ETHTOOL_LINK_MODE_Autoneg_BIT))
- priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseT_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_1G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_10G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_20G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_40G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_56G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_25G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_50G;
- if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT) |
- MLX5_BITSHIFT(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT)))
- priv->link_speed_capa |= ETH_LINK_SPEED_100G;
- dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
- ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
- dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
- ETH_LINK_SPEED_FIXED);
- if (((dev_link.link_speed && !dev_link.link_status) ||
- (!dev_link.link_speed && dev_link.link_status))) {
- rte_errno = EAGAIN;
- return -rte_errno;
- }
- *link = dev_link;
- return 0;
-}
-
-/**
- * DPDK callback to retrieve physical link information.
- *
- * @param dev
- * Pointer to Ethernet device structure.
- * @param wait_to_complete
- * Wait for request completion.
- *
- * @return
- * 0 if link status was not updated, positive if it was, a negative errno
- * value otherwise and rte_errno is set.
- */
-int
-mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
-{
- int ret;
- struct rte_eth_link dev_link;
- time_t start_time = time(NULL);
-
- do {
- ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
- if (ret == -ENOTSUP)
- ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
- if (ret == 0)
- break;
- /* Handle wait to complete situation. */
- if (wait_to_complete && ret == -EAGAIN) {
- if (abs((int)difftime(time(NULL), start_time)) <
- MLX5_LINK_STATUS_TIMEOUT) {
- usleep(0);
- continue;
- } else {
- rte_errno = EBUSY;
- return -rte_errno;
- }
- } else if (ret < 0) {
- return ret;
- }
- } while (wait_to_complete);
- ret = !!memcmp(&dev->data->dev_link, &dev_link,
- sizeof(struct rte_eth_link));
- dev->data->dev_link = dev_link;
- return ret;
-}
-
-/**
- * DPDK callback to change the MTU.
- *
- * @param dev
- * Pointer to Ethernet device structure.
- * @param in_mtu
- * New MTU.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-int
-mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- uint16_t kern_mtu = 0;
- int ret;
-
- ret = mlx5_get_mtu(dev, &kern_mtu);
- if (ret)
- return ret;
- /* Set kernel interface MTU first. */
- ret = mlx5_set_mtu(dev, mtu);
- if (ret)
- return ret;
- ret = mlx5_get_mtu(dev, &kern_mtu);
- if (ret)
- return ret;
- if (kern_mtu == mtu) {
- priv->mtu = mtu;
- DRV_LOG(DEBUG, "port %u adapter MTU set to %u",
- dev->data->port_id, mtu);
- return 0;
- }
- rte_errno = EAGAIN;
- return -rte_errno;
-}
-
-/**
- * DPDK callback to get flow control status.
- *
- * @param dev
- * Pointer to Ethernet device structure.
- * @param[out] fc_conf
- * Flow control output buffer.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-int
-mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
-{
- struct ifreq ifr;
- struct ethtool_pauseparam ethpause = {
- .cmd = ETHTOOL_GPAUSEPARAM
- };
- int ret;
-
- ifr.ifr_data = (void *)ðpause;
- ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
- if (ret) {
- DRV_LOG(WARNING,
- "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
- " %s",
- dev->data->port_id, strerror(rte_errno));
- return ret;
- }
- fc_conf->autoneg = ethpause.autoneg;
- if (ethpause.rx_pause && ethpause.tx_pause)
- fc_conf->mode = RTE_FC_FULL;
- else if (ethpause.rx_pause)
- fc_conf->mode = RTE_FC_RX_PAUSE;
- else if (ethpause.tx_pause)
- fc_conf->mode = RTE_FC_TX_PAUSE;
- else
- fc_conf->mode = RTE_FC_NONE;
- return 0;
-}
-
-/**
- * DPDK callback to modify flow control parameters.
- *
- * @param dev
- * Pointer to Ethernet device structure.
- * @param[in] fc_conf
- * Flow control parameters.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-int
-mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
-{
- struct ifreq ifr;
- struct ethtool_pauseparam ethpause = {
- .cmd = ETHTOOL_SPAUSEPARAM
- };
- int ret;
-
- ifr.ifr_data = (void *)ðpause;
- ethpause.autoneg = fc_conf->autoneg;
- if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
- (fc_conf->mode & RTE_FC_RX_PAUSE))
- ethpause.rx_pause = 1;
- else
- ethpause.rx_pause = 0;
-
- if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
- (fc_conf->mode & RTE_FC_TX_PAUSE))
- ethpause.tx_pause = 1;
- else
- ethpause.tx_pause = 0;
- ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
- if (ret) {
- DRV_LOG(WARNING,
- "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
- " failed: %s",
- dev->data->port_id, strerror(rte_errno));
- return ret;
- }
- return 0;
-}
-
-/**
- * Get PCI information by sysfs device path.
- *
- * @param dev_path
- * Pointer to device sysfs folder name.
- * @param[out] pci_addr
- * PCI bus address output buffer.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-int
-mlx5_dev_to_pci_addr(const char *dev_path,
- struct rte_pci_addr *pci_addr)
-{
- FILE *file;
- char line[32];
- MKSTR(path, "%s/device/uevent", dev_path);
-
- file = fopen(path, "rb");
- if (file == NULL) {
- rte_errno = errno;
- return -rte_errno;
- }
- while (fgets(line, sizeof(line), file) == line) {
- size_t len = strlen(line);
- int ret;
-
- /* Truncate long lines. */
- if (len == (sizeof(line) - 1))
- while (line[(len - 1)] != '\n') {
- ret = fgetc(file);
- if (ret == EOF)
- break;
- line[(len - 1)] = ret;
- }
- /* Extract information. */
- if (sscanf(line,
- "PCI_SLOT_NAME="
- "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n",
- &pci_addr->domain,
- &pci_addr->bus,
- &pci_addr->devid,
- &pci_addr->function) == 4) {
- ret = 0;
- break;
- }
- }
- fclose(file);
- return 0;
-}
-
-/**
- * Handle asynchronous removal event for entire multiport device.
- *
- * @param sh
- * Infiniband device shared context.
- */
-static void
-mlx5_dev_interrupt_device_fatal(struct mlx5_ibv_shared *sh)