net/mlx5: probe all port representors
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
index 819f5ba..ea01b39 100644 (file)
@@ -93,7 +93,7 @@ struct ethtool_link_settings {
 #endif
 
 /**
- * Get interface name from private structure.
+ * Get master interface name from private structure.
  *
  * @param[in] dev
  *   Pointer to Ethernet device.
@@ -104,7 +104,8 @@ struct ethtool_link_settings {
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
+mlx5_get_master_ifname(const struct rte_eth_dev *dev,
+                      char (*ifname)[IF_NAMESIZE])
 {
        struct priv *priv = dev->data->dev_private;
        DIR *dir;
@@ -178,6 +179,39 @@ try_dev_id:
        return 0;
 }
 
+/**
+ * Get interface name from private structure.
+ *
+ * This is a port representor-aware version of mlx5_get_master_ifname().
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[out] ifname
+ *   Interface name output buffer.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
+{
+       struct priv *priv = dev->data->dev_private;
+       unsigned int ifindex =
+               priv->nl_socket_rdma >= 0 ?
+               mlx5_nl_ifindex(priv->nl_socket_rdma, priv->ibdev_name) : 0;
+
+       if (!ifindex) {
+               if (!priv->representor)
+                       return mlx5_get_master_ifname(dev, ifname);
+               rte_errno = ENXIO;
+               return -rte_errno;
+       }
+       if (if_indextoname(ifindex, &(*ifname)[0]))
+               return 0;
+       rte_errno = errno;
+       return -rte_errno;
+}
+
 /**
  * Get the interface index from device name.
  *
@@ -214,12 +248,16 @@ mlx5_ifindex(const struct rte_eth_dev *dev)
  *   Request number to pass to ioctl().
  * @param[out] ifr
  *   Interface request structure output buffer.
+ * @param master
+ *   When device is a port representor, perform request on master device
+ *   instead.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
+mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr,
+          int master)
 {
        int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
        int ret = 0;
@@ -228,7 +266,10 @@ mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
                rte_errno = errno;
                return -rte_errno;
        }
-       ret = mlx5_get_ifname(dev, &ifr->ifr_name);
+       if (master)
+               ret = mlx5_get_master_ifname(dev, &ifr->ifr_name);
+       else
+               ret = mlx5_get_ifname(dev, &ifr->ifr_name);
        if (ret)
                goto error;
        ret = ioctl(sock, req, ifr);
@@ -258,7 +299,7 @@ int
 mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
 {
        struct ifreq request;
-       int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
+       int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request, 0);
 
        if (ret)
                return ret;
@@ -282,7 +323,7 @@ mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 {
        struct ifreq request = { .ifr_mtu = mtu, };
 
-       return mlx5_ifreq(dev, SIOCSIFMTU, &request);
+       return mlx5_ifreq(dev, SIOCSIFMTU, &request, 0);
 }
 
 /**
@@ -302,13 +343,13 @@ int
 mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
 {
        struct ifreq request;
-       int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
+       int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request, 0);
 
        if (ret)
                return ret;
        request.ifr_flags &= keep;
        request.ifr_flags |= flags & ~keep;
-       return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
+       return mlx5_ifreq(dev, SIOCSIFFLAGS, &request, 0);
 }
 
 /**
@@ -477,6 +518,30 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
        info->speed_capa = priv->link_speed_capa;
        info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
        mlx5_set_default_params(dev, info);
+       info->switch_info.name = dev->data->name;
+       info->switch_info.domain_id = priv->domain_id;
+       info->switch_info.port_id = priv->representor_id;
+       if (priv->representor) {
+               unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);
+               uint16_t port_id[i];
+
+               i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
+               while (i--) {
+                       struct priv *opriv =
+                               rte_eth_devices[port_id[i]].data->dev_private;
+
+                       if (!opriv ||
+                           opriv->representor ||
+                           opriv->domain_id != priv->domain_id)
+                               continue;
+                       /*
+                        * Override switch name with that of the master
+                        * device.
+                        */
+                       info->switch_info.name = opriv->dev_data->name;
+                       break;
+               }
+       }
 }
 
 /**
@@ -540,7 +605,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
        int link_speed = 0;
        int ret;
 
-       ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
+       ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);
        if (ret) {
                DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
                        dev->data->port_id, strerror(rte_errno));
@@ -550,7 +615,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
        dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
                                (ifr.ifr_flags & IFF_RUNNING));
        ifr.ifr_data = (void *)&edata;
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
        if (ret) {
                DRV_LOG(WARNING,
                        "port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
@@ -611,7 +676,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
        uint64_t sc;
        int ret;
 
-       ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
+       ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);
        if (ret) {
                DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
                        dev->data->port_id, strerror(rte_errno));
@@ -621,7 +686,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
        dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
                                (ifr.ifr_flags & IFF_RUNNING));
        ifr.ifr_data = (void *)&gcmd;
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
        if (ret) {
                DRV_LOG(DEBUG,
                        "port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
@@ -638,7 +703,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
 
        *ecmd = gcmd;
        ifr.ifr_data = (void *)ecmd;
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
        if (ret) {
                DRV_LOG(DEBUG,
                        "port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
@@ -801,7 +866,7 @@ mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        int ret;
 
        ifr.ifr_data = (void *)&ethpause;
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
        if (ret) {
                DRV_LOG(WARNING,
                        "port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
@@ -854,7 +919,7 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
                ethpause.tx_pause = 1;
        else
                ethpause.tx_pause = 0;
-       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 0);
        if (ret) {
                DRV_LOG(WARNING,
                        "port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
@@ -1193,3 +1258,40 @@ mlx5_is_removed(struct rte_eth_dev *dev)
                return 1;
        return 0;
 }
+
+/**
+ * Get port ID list of mlx5 instances sharing a common device.
+ *
+ * @param[in] dev
+ *   Device to look for.
+ * @param[out] port_list
+ *   Result buffer for collected port IDs.
+ * @param port_list_n
+ *   Maximum number of entries in result buffer. If 0, @p port_list can be
+ *   NULL.
+ *
+ * @return
+ *   Number of matching instances regardless of the @p port_list_n
+ *   parameter, 0 if none were found.
+ */
+unsigned int
+mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
+                   unsigned int port_list_n)
+{
+       uint16_t id;
+       unsigned int n = 0;
+
+       RTE_ETH_FOREACH_DEV(id) {
+               struct rte_eth_dev *ldev = &rte_eth_devices[id];
+
+               if (!ldev->device ||
+                   !ldev->device->driver ||
+                   strcmp(ldev->device->driver->name, MLX5_DRIVER_NAME) ||
+                   ldev->device != dev)
+                       continue;
+               if (n < port_list_n)
+                       port_list[n] = id;
+               n++;
+       }
+       return n;
+}