Defined callback to retrieve physical link information - status,
speed and capability using ioctl

Signed-off-by: Srikanth Kaka <srikant...@oneconvergence.com>
Signed-off-by: Vag Singh <vag.si...@oneconvergence.com>
Signed-off-by: Anand Thulasiram <av...@juniper.net>
---
 drivers/net/mlx5/freebsd/mlx5_ethdev_os.c | 349 +++++++---------------
 1 file changed, 108 insertions(+), 241 deletions(-)

diff --git a/drivers/net/mlx5/freebsd/mlx5_ethdev_os.c 
b/drivers/net/mlx5/freebsd/mlx5_ethdev_os.c
index 268649d16c..b046b6e347 100644
--- a/drivers/net/mlx5/freebsd/mlx5_ethdev_os.c
+++ b/drivers/net/mlx5/freebsd/mlx5_ethdev_os.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <dirent.h>
 #include <net/if.h>
+#include <net/if_media.h>
 #include <sys/sockio.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
@@ -308,265 +309,133 @@ mlx5_read_clock(struct rte_eth_dev *dev, uint64_t 
*clock)
        return 0;
 }
 
-/**
- * Retrieve the master device for representor in the same switch domain.
- *
- * @param dev
- *   Pointer to representor Ethernet device structure.
- *
- * @return
- *   Master device structure  on success, NULL otherwise.
- */
-static struct rte_eth_dev *
-mlx5_find_master_dev(struct rte_eth_dev *dev)
-{
-       struct mlx5_priv *priv;
-       uint16_t port_id;
-       uint16_t domain_id;
-
-       priv = dev->data->dev_private;
-       domain_id = priv->domain_id;
-       MLX5_ASSERT(priv->representor);
-       MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
-               struct mlx5_priv *opriv =
-                       rte_eth_devices[port_id].data->dev_private;
-               if (opriv &&
-                   opriv->master &&
-                   opriv->domain_id == domain_id &&
-                   opriv->sh == priv->sh)
-                       return &rte_eth_devices[port_id];
-       }
-       return NULL;
-}
+static const struct ifmedia_baudrate ifmedia_baudrate_desc[] =
+       IFM_BAUDRATE_DESCRIPTIONS;
 
-/**
- * DPDK callback to retrieve physical link information.
- *
- * @param dev
- *   Pointer to Ethernet device structure.
- * @param[out] link
- *   Storage for current link status.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
-                              struct rte_eth_link *link)
+static uint64_t
+mlx5_ifmedia_baudrate(int mword)
 {
-       struct mlx5_priv *priv = dev->data->dev_private;
-       struct ethtool_cmd edata = {
-               .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
-       };
-       struct ifreq ifr;
-       struct rte_eth_link dev_link;
-       int link_speed = 0;
-       int ret;
+       int i;
 
-       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;
+       for (i = 0; ifmedia_baudrate_desc[i].ifmb_word != 0; i++) {
+               if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_desc[i].ifmb_word))
+                       return (ifmedia_baudrate_desc[i].ifmb_baudrate);
        }
-       dev_link = (struct rte_eth_link) {
-               .link_status = ((ifr.ifr_flags & IFF_UP) &&
-                               (ifr.ifr_flags & IFF_RUNNING)),
-       };
-       ifr = (struct ifreq) {
-               .ifr_data = (void *)&edata,
-       };
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
-       if (ret) {
-               if (ret == -ENOTSUP && priv->representor) {
-                       struct rte_eth_dev *master;
 
-                       /*
-                        * 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 *)&edata,
-                               };
-                               ret = mlx5_ifreq(master, SIOCETHTOOL, &ifr);
-                       }
-               }
-               if (ret) {
-                       DRV_LOG(WARNING,
-                               "port %u ioctl(SIOCETHTOOL,"
-                               " ETHTOOL_GSET) failed: %s",
-                               dev->data->port_id, strerror(rte_errno));
-                       return ret;
-               }
-       }
-       link_speed = ethtool_cmd_speed(&edata);
-       if (link_speed == -1)
-               dev_link.link_speed = ETH_SPEED_NUM_UNKNOWN;
-       else
-               dev_link.link_speed = link_speed;
-       priv->link_speed_capa = 0;
-       if (edata.supported & (SUPPORTED_1000baseT_Full |
-                              SUPPORTED_1000baseKX_Full))
-               priv->link_speed_capa |= ETH_LINK_SPEED_1G;
-       if (edata.supported & SUPPORTED_10000baseKR_Full)
-               priv->link_speed_capa |= ETH_LINK_SPEED_10G;
-       if (edata.supported & (SUPPORTED_40000baseKR4_Full |
-                              SUPPORTED_40000baseCR4_Full |
-                              SUPPORTED_40000baseSR4_Full |
-                              SUPPORTED_40000baseLR4_Full))
-               priv->link_speed_capa |= ETH_LINK_SPEED_40G;
-       dev_link.link_duplex = ((edata.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);
-       *link = dev_link;
-       return 0;
+       return (0);
 }
 
-/**
- * Retrieve physical link information (unlocked version using new ioctl).
- *
- * @param dev
- *   Pointer to Ethernet device structure.
- * @param[out] link
- *   Storage for current link status.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
 static int
-mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
-                            struct rte_eth_link *link)
-
+mlx5_link_update_bsd(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;
+       int link_speed = 0, sock;
+       struct ifmediareq ifmr;
+       char ifname[IF_NAMESIZE];
+       int *media_list;
 
-       ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
-       if (ret) {
-               DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
+       sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+       if (sock == -1) {
+               DRV_LOG(ERR,
+                       "port %u CANT OPEN SOCKET FOR MEDIA REQUEST on FREEBSD: 
%s",
                        dev->data->port_id, strerror(rte_errno));
-               return ret;
+               return sock;
        }
-       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;
-               }
+
+       mlx5_get_ifname(dev, &ifname);
+       memset(&ifmr, 0, sizeof(struct ifmediareq));
+       strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+
+       if (ioctl(sock, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) {
+               DRV_LOG(ERR,
+                       "ioctl(SIOCGIFMEDIA) on %s: %s",
+                       ifname, strerror(errno));
+               close(sock);
+               return errno;
        }
-       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;
+       media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
+       ifmr.ifm_ulist = media_list;
 
-       *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;
+       if (ioctl(sock, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) {
+               DRV_LOG(ERR,
+                       "ioctl(SIOCGIFMEDIA) on %s: %s",
+                       ifname, strerror(errno));
+               close(sock);
+               return errno;
        }
-       dev_link.link_speed = (ecmd->speed == UINT32_MAX) ?
-                               ETH_SPEED_NUM_UNKNOWN : ecmd->speed;
-       sc = ecmd->link_mode_masks[0] |
-               ((uint64_t)ecmd->link_mode_masks[1] << 32);
+
+       if (ifmr.ifm_status == (IFM_AVALID | IFM_ACTIVE))
+               dev_link.link_status = ETH_LINK_UP;
+       else
+               dev_link.link_status = ETH_LINK_DOWN;
+
+       link_speed = ifmr.ifm_status & IFM_AVALID ?
+                       mlx5_ifmedia_baudrate(ifmr.ifm_active) / (1000 * 1000) 
: 0;
+
+       if (link_speed == 0)
+               dev_link.link_speed = ETH_SPEED_NUM_NONE;
+       else
+               dev_link.link_speed = link_speed;
+
        priv->link_speed_capa = 0;
-       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;
-       if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT) |
-                 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT)))
-               priv->link_speed_capa |= ETH_LINK_SPEED_200G;
-
-       sc = ecmd->link_mode_masks[2] |
-               ((uint64_t)ecmd->link_mode_masks[3] << 32);
-       if (sc & (MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT) |
-                 MLX5_BITSHIFT
-                      (ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT) |
-                 MLX5_BITSHIFT(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT)))
-               priv->link_speed_capa |= ETH_LINK_SPEED_200G;
-       dev_link.link_duplex = ((ecmd->duplex == DUPLEX_HALF) ?
-                               ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
+       /* Add support for duplex types */
+       dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+       /* FreeBSD automatically negotiates speed,
+        * so it is displayed in its capabilities.
+        */
+       priv->link_speed_capa |= ETH_LINK_SPEED_AUTONEG;
+
+       for (int i = 1; i < ifmr.ifm_count; i += 2) {
+               switch (mlx5_ifmedia_baudrate(media_list[i]) / (1000 * 1000)) {
+               case 100000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_100G;
+                       break;
+               case 56000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_56G;
+                       break;
+               case 50000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_50G;
+                       break;
+               case 40000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_40G;
+                       break;
+               case 25000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_25G;
+                       break;
+               case 10000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_10G;
+                       break;
+               case 2500:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_2_5G;
+                       break;
+               case 1000:
+                       priv->link_speed_capa |= ETH_LINK_SPEED_1G;
+                       break;
+               case 100:
+                       priv->link_speed_capa |= (dev_link.link_duplex ==
+                                               ETH_LINK_FULL_DUPLEX) ?
+                                               ETH_LINK_SPEED_100M :
+                                               ETH_LINK_SPEED_100M_HD;
+                       break;
+               case 10:
+                       priv->link_speed_capa |= (dev_link.link_duplex ==
+                                               ETH_LINK_FULL_DUPLEX) ?
+                                               ETH_LINK_SPEED_10M :
+                                               ETH_LINK_SPEED_10M_HD;
+                       break;
+               case 0:
+               default:
+                       break;
+               }
+       }
        dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
-                                 ETH_LINK_SPEED_FIXED);
+                               ETH_LINK_SPEED_FIXED);
+       free(media_list);
        *link = dev_link;
+       close(sock);
        return 0;
 }
 
@@ -591,9 +460,7 @@ mlx5_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
        int retry = MLX5_GET_LINK_STATUS_RETRY_COUNT;
 
        do {
-               ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
-               if (ret == -ENOTSUP)
-                       ret = mlx5_link_update_unlocked_gset(dev, &dev_link);
+               ret = mlx5_link_update_bsd(dev, &dev_link);
                if (ret == 0)
                        break;
                /* Handle wait to complete situation. */
-- 
2.30.2

Reply via email to