summaryrefslogtreecommitdiff
path: root/drivers/net/mlx5/mlx5_ethdev.c
diff options
context:
space:
mode:
authorMatan Azrad <matan@mellanox.com>2019-10-22 07:33:35 +0000
committerFerruh Yigit <ferruh.yigit@intel.com>2019-10-23 16:43:10 +0200
commit2324206337c551e0f19c223530361248167c613e (patch)
treec08e0117c9ee96c326cbda49ed023e11aeb1a593 /drivers/net/mlx5/mlx5_ethdev.c
parent368f9f2f777627f367bcdc91c6541a89f006afe1 (diff)
downloaddpdk-next-eventdev-2324206337c551e0f19c223530361248167c613e.zip
dpdk-next-eventdev-2324206337c551e0f19c223530361248167c613e.tar.gz
dpdk-next-eventdev-2324206337c551e0f19c223530361248167c613e.tar.xz
net/mlx5: fix DevX event registration timing
The DevX counter management triggers an asynchronous event to get back the new counters values from the HW. The counter management doesn't trigger 2 parallel events for the same pool, hence, the pool cannot be updated again in the event waiting time. When the port is stopped, the DevX event mechanism wrongly was destroyed what remained all the waiting pools in waiting state forever. As a result, the counters of the stuck pools were never updated again. Separate the DevX interrupt installation from the dev installation and remove the DevX interrupt unregistration\registration from the stop\start operations. Now, the DevX interrupt should be installed in probe and uninstalled in close. Cc: stable@dpdk.org Fixes: f15db67df09c ("net/mlx5: accelerate DV flow counter query") Signed-off-by: Matan Azrad <matan@mellanox.com> Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
Diffstat (limited to 'drivers/net/mlx5/mlx5_ethdev.c')
-rw-r--r--drivers/net/mlx5/mlx5_ethdev.c153
1 files changed, 119 insertions, 34 deletions
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index 5f05b2b..2278b24 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -1448,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,
@@ -1490,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;
}
@@ -1500,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);
}
@@ -1575,6 +1636,30 @@ mlx5_dev_interrupt_handler_install(struct rte_eth_dev *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.
*
* @param dev