net/ixgbe: fix zeroing of RSS config
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
index aa645d0..2278b24 100644 (file)
@@ -601,7 +601,7 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
                        info->switch_info.port_id |=
                                priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT;
                }
-               MLX5_ETH_FOREACH_DEV(port_id) {
+               MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
                        struct mlx5_priv *opriv =
                                rte_eth_devices[port_id].data->dev_private;
 
@@ -734,7 +734,7 @@ mlx5_find_master_dev(struct rte_eth_dev *dev)
        priv = dev->data->dev_private;
        domain_id = priv->domain_id;
        assert(priv->representor);
-       MLX5_ETH_FOREACH_DEV(port_id) {
+       MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) {
                struct mlx5_priv *opriv =
                        rte_eth_devices[port_id].data->dev_private;
                if (opriv &&
@@ -999,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);
@@ -1007,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);
@@ -1019,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;
@@ -1447,6 +1448,37 @@ mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev)
                                     mlx5_dev_interrupt_handler, sh);
        sh->intr_handle.fd = 0;
        sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+exit:
+       pthread_mutex_unlock(&sh->intr_mutex);
+}
+
+/**
+ * Uninstall devx shared asynchronous device events handler.
+ * This function is implemeted to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ */
+static void
+mlx5_dev_shared_handler_devx_uninstall(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_ibv_shared *sh = priv->sh;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return;
+       pthread_mutex_lock(&sh->intr_mutex);
+       assert(priv->ibv_port);
+       assert(priv->ibv_port <= sh->max_port);
+       assert(dev->data->port_id < RTE_MAX_ETHPORTS);
+       if (sh->port[priv->ibv_port - 1].devx_ih_port_id >= RTE_MAX_ETHPORTS)
+               goto exit;
+       assert(sh->port[priv->ibv_port - 1].devx_ih_port_id ==
+                                       (uint32_t)dev->data->port_id);
+       sh->port[priv->ibv_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS;
+       if (!sh->devx_intr_cnt || --sh->devx_intr_cnt)
+               goto exit;
        if (sh->intr_handle_devx.fd) {
                rte_intr_callback_unregister(&sh->intr_handle_devx,
                                             mlx5_dev_interrupt_handler_devx,
@@ -1489,8 +1521,9 @@ mlx5_dev_shared_handler_install(struct rte_eth_dev *dev)
                assert(sh->intr_cnt);
                goto exit;
        }
-       sh->port[priv->ibv_port - 1].ih_port_id = (uint32_t)dev->data->port_id;
        if (sh->intr_cnt) {
+               sh->port[priv->ibv_port - 1].ih_port_id =
+                                               (uint32_t)dev->data->port_id;
                sh->intr_cnt++;
                goto exit;
        }
@@ -1499,52 +1532,81 @@ mlx5_dev_shared_handler_install(struct rte_eth_dev *dev)
        flags = fcntl(sh->ctx->async_fd, F_GETFL);
        ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
        if (ret) {
-               DRV_LOG(INFO, "failed to change file descriptor"
-                             " async event queue");
-               goto error;
+               DRV_LOG(INFO, "failed to change file descriptor async event"
+                       " queue");
+               /* Indicate there will be no interrupts. */
+               dev->data->dev_conf.intr_conf.lsc = 0;
+               dev->data->dev_conf.intr_conf.rmv = 0;
+       } else {
+               sh->intr_handle.fd = sh->ctx->async_fd;
+               sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
+               rte_intr_callback_register(&sh->intr_handle,
+                                          mlx5_dev_interrupt_handler, sh);
+               sh->intr_cnt++;
+               sh->port[priv->ibv_port - 1].ih_port_id =
+                                               (uint32_t)dev->data->port_id;
+       }
+exit:
+       pthread_mutex_unlock(&sh->intr_mutex);
+}
+
+/**
+ * Install devx shared asyncronous device events handler.
+ * This function is implemeted to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ */
+static void
+mlx5_dev_shared_handler_devx_install(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_ibv_shared *sh = priv->sh;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return;
+       pthread_mutex_lock(&sh->intr_mutex);
+       assert(priv->ibv_port);
+       assert(priv->ibv_port <= sh->max_port);
+       assert(dev->data->port_id < RTE_MAX_ETHPORTS);
+       if (sh->port[priv->ibv_port - 1].devx_ih_port_id < RTE_MAX_ETHPORTS) {
+               /* The handler is already installed for this port. */
+               assert(sh->devx_intr_cnt);
+               goto exit;
+       }
+       if (sh->devx_intr_cnt) {
+               sh->devx_intr_cnt++;
+               sh->port[priv->ibv_port - 1].devx_ih_port_id =
+                                       (uint32_t)dev->data->port_id;
+               goto exit;
        }
-       sh->intr_handle.fd = sh->ctx->async_fd;
-       sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
-       rte_intr_callback_register(&sh->intr_handle,
-                                  mlx5_dev_interrupt_handler, sh);
        if (priv->config.devx) {
 #ifndef HAVE_IBV_DEVX_ASYNC
-               goto error_unregister;
+               goto exit;
 #else
                sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx);
                if (sh->devx_comp) {
-                       flags = fcntl(sh->devx_comp->fd, F_GETFL);
-                       ret = fcntl(sh->devx_comp->fd, F_SETFL,
+                       int flags = fcntl(sh->devx_comp->fd, F_GETFL);
+                       int ret = fcntl(sh->devx_comp->fd, F_SETFL,
                                    flags | O_NONBLOCK);
+
                        if (ret) {
                                DRV_LOG(INFO, "failed to change file descriptor"
-                                             " devx async event queue");
-                               goto error_unregister;
+                                       " devx async event queue");
+                       } else {
+                               sh->intr_handle_devx.fd = sh->devx_comp->fd;
+                               sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT;
+                               rte_intr_callback_register
+                                       (&sh->intr_handle_devx,
+                                        mlx5_dev_interrupt_handler_devx, sh);
+                               sh->devx_intr_cnt++;
+                               sh->port[priv->ibv_port - 1].devx_ih_port_id =
+                                               (uint32_t)dev->data->port_id;
                        }
-                       sh->intr_handle_devx.fd = sh->devx_comp->fd;
-                       sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT;
-                       rte_intr_callback_register
-                               (&sh->intr_handle_devx,
-                                mlx5_dev_interrupt_handler_devx, sh);
-               } else {
-                       DRV_LOG(INFO, "failed to create devx async command "
-                               "completion");
-                       goto error_unregister;
                }
 #endif /* HAVE_IBV_DEVX_ASYNC */
        }
-       sh->intr_cnt++;
-       goto exit;
-error_unregister:
-       rte_intr_callback_unregister(&sh->intr_handle,
-                                    mlx5_dev_interrupt_handler, sh);
-error:
-       /* Indicate there will be no interrupts. */
-       dev->data->dev_conf.intr_conf.lsc = 0;
-       dev->data->dev_conf.intr_conf.rmv = 0;
-       sh->intr_handle.fd = 0;
-       sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
-       sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
 exit:
        pthread_mutex_unlock(&sh->intr_mutex);
 }
@@ -1573,6 +1635,30 @@ mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
        mlx5_dev_shared_handler_install(dev);
 }
 
+/**
+ * Devx uninstall interrupt handler.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ */
+void
+mlx5_dev_interrupt_handler_devx_uninstall(struct rte_eth_dev *dev)
+{
+       mlx5_dev_shared_handler_devx_uninstall(dev);
+}
+
+/**
+ * Devx install interrupt handler.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ */
+void
+mlx5_dev_interrupt_handler_devx_install(struct rte_eth_dev *dev)
+{
+       mlx5_dev_shared_handler_devx_install(dev);
+}
+
 /**
  * DPDK callback to bring the link DOWN.
  *