net/mlx5: retry on link update failure
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
index ad53721..5f05b2b 100644 (file)
@@ -580,16 +580,34 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
        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];
+               uint16_t port_id;
 
-               i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
-               while (i--) {
+               if (priv->pf_bond >= 0) {
+                       /*
+                        * Switch port ID is opaque value with driver defined
+                        * format. Push the PF index in bonding configurations
+                        * in upper four bits of port ID. If we get too many
+                        * representors (more than 4K) or PFs (more than 15)
+                        * this approach must be reconsidered.
+                        */
+                       if ((info->switch_info.port_id >>
+                               MLX5_PORT_ID_BONDING_PF_SHIFT) ||
+                           priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) {
+                               DRV_LOG(ERR, "can't update switch port ID"
+                                            " for bonding device");
+                               assert(false);
+                               return -ENODEV;
+                       }
+                       info->switch_info.port_id |=
+                               priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT;
+               }
+               MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
                        struct mlx5_priv *opriv =
-                               rte_eth_devices[port_id[i]].data->dev_private;
+                               rte_eth_devices[port_id].data->dev_private;
 
                        if (!opriv ||
                            opriv->representor ||
+                           opriv->sh != priv->sh ||
                            opriv->domain_id != priv->domain_id)
                                continue;
                        /*
@@ -600,7 +618,6 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
                        break;
                }
        }
-
        return 0;
 }
 
@@ -717,11 +734,13 @@ mlx5_find_master_dev(struct rte_eth_dev *dev)
        priv = dev->data->dev_private;
        domain_id = priv->domain_id;
        assert(priv->representor);
-       RTE_ETH_FOREACH_DEV_OF(port_id, dev->device) {
-               priv = rte_eth_devices[port_id].data->dev_private;
-               if (priv &&
-                   priv->master &&
-                   priv->domain_id == domain_id)
+       MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
+               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;
@@ -980,6 +999,7 @@ 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);
+       int retry = MLX5_GET_LINK_STATUS_RETRY_COUNT;
 
        do {
                ret = mlx5_link_update_unlocked_gs(dev, &dev_link);
@@ -988,7 +1008,7 @@ mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
                if (ret == 0)
                        break;
                /* Handle wait to complete situation. */
-               if (wait_to_complete && ret == -EAGAIN) {
+               if ((wait_to_complete || retry) && ret == -EAGAIN) {
                        if (abs((int)difftime(time(NULL), start_time)) <
                            MLX5_LINK_STATUS_TIMEOUT) {
                                usleep(0);
@@ -1000,7 +1020,7 @@ mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
                } else if (ret < 0) {
                        return ret;
                }
-       } while (wait_to_complete);
+       } while (wait_to_complete || retry-- > 0);
        ret = !!memcmp(&dev->data->dev_link, &dev_link,
                       sizeof(struct rte_eth_link));
        dev->data->dev_link = dev_link;
@@ -1131,10 +1151,10 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 }
 
 /**
- * Get PCI information from struct ibv_device.
+ * Get PCI information by sysfs device path.
  *
- * @param device
- *   Pointer to Ethernet device structure.
+ * @param dev_path
+ *   Pointer to device sysfs folder name.
  * @param[out] pci_addr
  *   PCI bus address output buffer.
  *
@@ -1142,12 +1162,12 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
-                           struct rte_pci_addr *pci_addr)
+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", device->ibdev_path);
+       MKSTR(path, "%s/device/uevent", dev_path);
 
        file = fopen(path, "rb");
        if (file == NULL) {
@@ -1630,37 +1650,44 @@ mlx5_is_removed(struct rte_eth_dev *dev)
 }
 
 /**
- * Get port ID list of mlx5 instances sharing a common device.
+ * Get the E-Switch parameters by port id.
  *
- * @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.
+ * @param[in] port
+ *   Device port id.
+ * @param[out] es_domain_id
+ *   E-Switch domain id.
+ * @param[out] es_port_id
+ *   The port id of the port in the E-Switch.
  *
  * @return
- *   Number of matching instances regardless of the @p port_list_n
- *   parameter, 0 if none were found.
+ *   pointer to device private data structure containing data needed
+ *   on success, NULL otherwise and rte_errno is set.
  */
-unsigned int
-mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
-                   unsigned int port_list_n)
+struct mlx5_priv *
+mlx5_port_to_eswitch_info(uint16_t port)
 {
-       uint16_t id;
-       unsigned int n = 0;
+       struct rte_eth_dev *dev;
+       struct mlx5_priv *priv;
 
-       RTE_ETH_FOREACH_DEV_OF(id, dev) {
-               if (n < port_list_n)
-                       port_list[n] = id;
-               n++;
+       if (port >= RTE_MAX_ETHPORTS) {
+               rte_errno = EINVAL;
+               return NULL;
+       }
+       if (!rte_eth_dev_is_valid_port(port)) {
+               rte_errno = ENODEV;
+               return NULL;
+       }
+       dev = &rte_eth_devices[port];
+       priv = dev->data->dev_private;
+       if (!(priv->representor || priv->master)) {
+               rte_errno = EINVAL;
+               return NULL;
        }
-       return n;
+       return priv;
 }
 
 /**
- * Get the E-Switch domain id this port belongs to.
+ * Get the E-Switch parameters by device instance.
  *
  * @param[in] port
  *   Device port id.
@@ -1670,34 +1697,20 @@ mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
  *   The port id of the port in the E-Switch.
  *
  * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
+ *   pointer to device private data structure containing data needed
+ *   on success, NULL otherwise and rte_errno is set.
  */
-int
-mlx5_port_to_eswitch_info(uint16_t port,
-                         uint16_t *es_domain_id, uint16_t *es_port_id)
+struct mlx5_priv *
+mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev)
 {
-       struct rte_eth_dev *dev;
        struct mlx5_priv *priv;
 
-       if (port >= RTE_MAX_ETHPORTS) {
-               rte_errno = EINVAL;
-               return -rte_errno;
-       }
-       if (!rte_eth_dev_is_valid_port(port)) {
-               rte_errno = ENODEV;
-               return -rte_errno;
-       }
-       dev = &rte_eth_devices[port];
        priv = dev->data->dev_private;
        if (!(priv->representor || priv->master)) {
                rte_errno = EINVAL;
-               return -rte_errno;
+               return NULL;
        }
-       if (es_domain_id)
-               *es_domain_id = priv->domain_id;
-       if (es_port_id)
-               *es_port_id = priv->vport_id;
-       return 0;
+       return priv;
 }
 
 /**