mlx5: support link status update
authorAdrien Mazarguil <adrien.mazarguil@6wind.com>
Fri, 30 Oct 2015 18:52:38 +0000 (19:52 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Fri, 30 Oct 2015 21:32:05 +0000 (22:32 +0100)
Link information is retrieved using ethtool ioctls.

Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
drivers/net/mlx5/mlx5.c
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_ethdev.c

index ee63bdf..5ed828d 100644 (file)
@@ -137,6 +137,7 @@ static const struct eth_dev_ops mlx5_dev_ops = {
        .promiscuous_disable = mlx5_promiscuous_disable,
        .allmulticast_enable = mlx5_allmulticast_enable,
        .allmulticast_disable = mlx5_allmulticast_disable,
+       .link_update = mlx5_link_update,
        .stats_get = mlx5_stats_get,
        .stats_reset = mlx5_stats_reset,
        .dev_infos_get = mlx5_dev_infos_get,
index 56da43c..1a18326 100644 (file)
@@ -164,6 +164,7 @@ int priv_get_mtu(struct priv *, uint16_t *);
 int priv_set_flags(struct priv *, unsigned int, unsigned int);
 int mlx5_dev_configure(struct rte_eth_dev *);
 void mlx5_dev_infos_get(struct rte_eth_dev *, struct rte_eth_dev_info *);
+int mlx5_link_update(struct rte_eth_dev *, int);
 int mlx5_dev_set_mtu(struct rte_eth_dev *, uint16_t);
 int mlx5_ibv_device_to_pci_addr(const struct ibv_device *,
                                struct rte_pci_addr *);
index 26b6d73..d01dee5 100644 (file)
@@ -45,6 +45,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <linux/if.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
 
 /* DPDK headers don't like -pedantic. */
 #ifdef PEDANTIC
@@ -534,6 +536,75 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
        priv_unlock(priv);
 }
 
+/**
+ * DPDK callback to retrieve physical link information (unlocked version).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ */
+static int
+mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
+{
+       struct priv *priv = dev->data->dev_private;
+       struct ethtool_cmd edata = {
+               .cmd = ETHTOOL_GSET
+       };
+       struct ifreq ifr;
+       struct rte_eth_link dev_link;
+       int link_speed = 0;
+
+       (void)wait_to_complete;
+       if (priv_ifreq(priv, SIOCGIFFLAGS, &ifr)) {
+               WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno));
+               return -1;
+       }
+       memset(&dev_link, 0, sizeof(dev_link));
+       dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
+                               (ifr.ifr_flags & IFF_RUNNING));
+       ifr.ifr_data = &edata;
+       if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) {
+               WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
+                    strerror(errno));
+               return -1;
+       }
+       link_speed = ethtool_cmd_speed(&edata);
+       if (link_speed == -1)
+               dev_link.link_speed = 0;
+       else
+               dev_link.link_speed = link_speed;
+       dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
+                               ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
+       if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) {
+               /* Link status changed. */
+               dev->data->dev_link = dev_link;
+               return 0;
+       }
+       /* Link status is still the same. */
+       return -1;
+}
+
+/**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ */
+int
+mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+       struct priv *priv = dev->data->dev_private;
+       int ret;
+
+       priv_lock(priv);
+       ret = mlx5_link_update_unlocked(dev, wait_to_complete);
+       priv_unlock(priv);
+       return ret;
+}
+
 /**
  * DPDK callback to change the MTU.
  *