- if (mlx5_link_update(dev, 0) == -EAGAIN) {
- usleep(0);
- return 0;
- }
- /* Read all message and acknowledge them. */
- for (;;) {
- if (mlx5_glue->get_async_event(priv->sh->ctx, &event))
- break;
- if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
- event.event_type == IBV_EVENT_PORT_ERR) &&
- (dev->data->dev_conf.intr_conf.lsc == 1))
- ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
- else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
- dev->data->dev_conf.intr_conf.rmv == 1)
- ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
- else
- DRV_LOG(DEBUG,
- "port %u event type %d on not handled",
- dev->data->port_id, event.event_type);
- mlx5_glue->ack_async_event(&event);
- }
- return ret;
-}
-
-/**
- * Handle interrupts from the NIC.
- *
- * @param[in] intr_handle
- * Interrupt handler.
- * @param cb_arg
- * Callback argument.
- */
-void
-mlx5_dev_interrupt_handler(void *cb_arg)
-{
- struct rte_eth_dev *dev = cb_arg;
- uint32_t events;
-
- events = mlx5_dev_status_handler(dev);
- if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
- _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
- if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
- _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
-}
-
-/**
- * Handle interrupts from the socket.
- *
- * @param cb_arg
- * Callback argument.
- */
-static void
-mlx5_dev_handler_socket(void *cb_arg)
-{
- struct rte_eth_dev *dev = cb_arg;
-
- mlx5_socket_handle(dev);
-}
-
-/**
- * Uninstall 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_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].ih_port_id >= RTE_MAX_ETHPORTS)
- goto exit;
- assert(sh->port[priv->ibv_port - 1].ih_port_id ==
- (uint32_t)dev->data->port_id);
- 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;
- rte_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);
-}
-
-/**
- * Install 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_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);
- 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].ih_port_id < RTE_MAX_ETHPORTS) {
- /* The handler is already installed for this port. */
- 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->intr_cnt++;
- goto exit;
- }
- /* No shared handler installed. */
- 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;
- sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
- 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);
- sh->intr_cnt++;
-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)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
-
- mlx5_dev_shared_handler_uninstall(dev);
- if (priv->primary_socket)
- rte_intr_callback_unregister(&priv->intr_handle_socket,
- mlx5_dev_handler_socket, dev);
- priv->intr_handle_socket.fd = 0;
- priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
-}
-
-/**
- * Install interrupt handler.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- int ret;
-
- mlx5_dev_shared_handler_install(dev);
- ret = mlx5_socket_init(dev);
- if (ret)
- DRV_LOG(ERR, "port %u cannot initialise socket: %s",
- dev->data->port_id, strerror(rte_errno));
- else if (priv->primary_socket) {
- priv->intr_handle_socket.fd = priv->primary_socket;
- priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
- rte_intr_callback_register(&priv->intr_handle_socket,
- mlx5_dev_handler_socket, dev);