#include <stdlib.h>
#include <errno.h>
#include <net/if.h>
+#include <fcntl.h>
#include <sys/mman.h>
#include <linux/rtnetlink.h>
setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
}
+/**
+ * Install shared asynchronous device events handler.
+ * This function is implemented to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param sh
+ * Pointer to mlx5_ibv_shared object.
+ */
+static void
+mlx5_dev_shared_handler_install(struct mlx5_ibv_shared *sh)
+{
+ int ret;
+ int flags;
+
+ sh->intr_handle.fd = -1;
+ 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");
+ } else {
+ sh->intr_handle.fd = sh->ctx->async_fd;
+ sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
+ if (rte_intr_callback_register(&sh->intr_handle,
+ mlx5_dev_interrupt_handler, sh)) {
+ DRV_LOG(INFO, "Fail to install the shared interrupt.");
+ sh->intr_handle.fd = -1;
+ }
+ }
+ if (sh->devx) {
+#ifdef HAVE_IBV_DEVX_ASYNC
+ sh->intr_handle_devx.fd = -1;
+ sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx);
+ if (!sh->devx_comp) {
+ DRV_LOG(INFO, "failed to allocate devx_comp.");
+ return;
+ }
+ flags = fcntl(sh->devx_comp->fd, F_GETFL);
+ ret = fcntl(sh->devx_comp->fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret) {
+ DRV_LOG(INFO, "failed to change file descriptor"
+ " devx comp");
+ return;
+ }
+ sh->intr_handle_devx.fd = sh->devx_comp->fd;
+ sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT;
+ if (rte_intr_callback_register(&sh->intr_handle_devx,
+ mlx5_dev_interrupt_handler_devx, sh)) {
+ DRV_LOG(INFO, "Fail to install the devx shared"
+ " interrupt.");
+ sh->intr_handle_devx.fd = -1;
+ }
+#endif /* HAVE_IBV_DEVX_ASYNC */
+ }
+}
+
+/**
+ * Uninstall shared asynchronous device events handler.
+ * This function is implemented to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param dev
+ * Pointer to mlx5_ibv_shared object.
+ */
+static void
+mlx5_dev_shared_handler_uninstall(struct mlx5_ibv_shared *sh)
+{
+ if (sh->intr_handle.fd >= 0)
+ mlx5_intr_callback_unregister(&sh->intr_handle,
+ mlx5_dev_interrupt_handler, sh);
+#ifdef HAVE_IBV_DEVX_ASYNC
+ if (sh->intr_handle_devx.fd >= 0)
+ rte_intr_callback_unregister(&sh->intr_handle_devx,
+ mlx5_dev_interrupt_handler_devx, sh);
+ if (sh->devx_comp)
+ mlx5_glue->devx_destroy_cmd_comp(sh->devx_comp);
+#endif
+}
+
/**
* Allocate shared IB device context. If there is multiport device the
* master and representors will share this context, if there is single
sizeof(sh->ibdev_name));
strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path,
sizeof(sh->ibdev_path));
- pthread_mutex_init(&sh->intr_mutex, NULL);
/*
* Setting port_id to max unallowed value means
* there is no interrupt subhandler installed for
err = rte_errno;
goto error;
}
+ mlx5_dev_shared_handler_install(sh);
mlx5_flow_aging_init(sh);
mlx5_flow_counters_mng_init(sh);
mlx5_flow_ipool_create(sh, config);
**/
mlx5_flow_counters_mng_close(sh);
mlx5_flow_ipool_destroy(sh);
- MLX5_ASSERT(!sh->intr_cnt);
- if (sh->intr_cnt)
- mlx5_intr_callback_unregister
- (&sh->intr_handle, mlx5_dev_interrupt_handler, sh);
-#ifdef HAVE_MLX5_DEVX_ASYNC_SUPPORT
- if (sh->devx_intr_cnt) {
- if (sh->intr_handle_devx.fd)
- rte_intr_callback_unregister(&sh->intr_handle_devx,
- mlx5_dev_interrupt_handler_devx, sh);
- if (sh->devx_comp)
- mlx5dv_devx_destroy_cmd_comp(sh->devx_comp);
- }
-#endif
- pthread_mutex_destroy(&sh->intr_mutex);
+ mlx5_dev_shared_handler_uninstall(sh);
if (sh->pd)
claim_zero(mlx5_glue->dealloc_pd(sh->pd));
if (sh->tis)
DRV_LOG(DEBUG, "port %u closing device \"%s\"",
dev->data->port_id,
((priv->sh->ctx != NULL) ? priv->sh->ctx->device->name : ""));
- /* In case mlx5_dev_stop() has not been called. */
- mlx5_dev_interrupt_handler_uninstall(dev);
- mlx5_dev_interrupt_handler_devx_uninstall(dev);
/*
* If default mreg copy action is removed at the stop stage,
* the search will return none and nothing will be done anymore.
rte_eth_copy_pci_info(list[i].eth_dev, pci_dev);
/* Restore non-PCI flags cleared by the above call. */
list[i].eth_dev->data->dev_flags |= restore;
- mlx5_dev_interrupt_handler_devx_install(list[i].eth_dev);
rte_eth_dev_probing_finish(list[i].eth_dev);
}
if (i != ns) {
#endif /* HAVE_IBV_DEVX_ASYNC */
}
-/**
- * Uninstall shared asynchronous device events handler.
- * This function is implemented to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_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);
- MLX5_ASSERT(priv->ibv_port);
- MLX5_ASSERT(priv->ibv_port <= sh->max_port);
- MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS);
- if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS)
- goto exit;
- MLX5_ASSERT(sh->port[priv->ibv_port - 1].ih_port_id ==
- (uint32_t)dev->data->port_id);
- MLX5_ASSERT(sh->intr_cnt);
- sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
- if (!sh->intr_cnt || --sh->intr_cnt)
- goto exit;
- mlx5_intr_callback_unregister(&sh->intr_handle,
- 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);
- MLX5_ASSERT(priv->ibv_port);
- MLX5_ASSERT(priv->ibv_port <= sh->max_port);
- MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS);
- if (sh->port[priv->ibv_port - 1].devx_ih_port_id >= RTE_MAX_ETHPORTS)
- goto exit;
- MLX5_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,
- sh);
- sh->intr_handle_devx.fd = 0;
- sh->intr_handle_devx.type = RTE_INTR_HANDLE_UNKNOWN;
- }
- if (sh->devx_comp) {
- mlx5_glue->devx_destroy_cmd_comp(sh->devx_comp);
- sh->devx_comp = NULL;
- }
-exit:
- pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Install shared asynchronous device events handler.
- * This function is implemented to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_install(struct rte_eth_dev *dev)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_ibv_shared *sh = priv->sh;
- int ret;
- int flags;
-
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return;
- pthread_mutex_lock(&sh->intr_mutex);
- MLX5_ASSERT(priv->ibv_port);
- MLX5_ASSERT(priv->ibv_port <= sh->max_port);
- MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS);
- if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) {
- /* The handler is already installed for this port. */
- MLX5_ASSERT(sh->intr_cnt);
- goto exit;
- }
- if (sh->intr_cnt) {
- sh->port[priv->ibv_port - 1].ih_port_id =
- (uint32_t)dev->data->port_id;
- sh->intr_cnt++;
- goto exit;
- }
- /* No shared handler installed. */
- MLX5_ASSERT(sh->ctx->async_fd > 0);
- 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");
- /* 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);
- MLX5_ASSERT(priv->ibv_port);
- MLX5_ASSERT(priv->ibv_port <= sh->max_port);
- MLX5_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. */
- MLX5_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;
- }
- if (priv->config.devx) {
-#ifndef HAVE_IBV_DEVX_ASYNC
- goto exit;
-#else
- sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx);
- if (sh->devx_comp) {
- 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");
- } 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;
- }
- }
-#endif /* HAVE_IBV_DEVX_ASYNC */
- }
-exit:
- pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Uninstall interrupt handler.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
-{
- mlx5_dev_shared_handler_uninstall(dev);
-}
-
-/**
- * Install interrupt handler.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-void
-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.
*