Thursday, March 21, 2019 10:11 AM, Viacheslav Ovsiienko:
> Subject: [PATCH 12/14] net/mlx5: update install/uninstall int handler routines
> 
> We are implementing the support for multport Infiniband device withj
> representors attached to these multiple ports. Asynchronous device event
> notifications (link status change, removal event, etc.) should be shared
> between ports. We are going to implement shared event handler and this
> patch introduces appropriate device structure changes and updated event
> handler install and uninstall routines.
> 
> Signed-off-by: Viacheslav Ovsiienko <viachesl...@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5.c        |  14 ++++-
>  drivers/net/mlx5/mlx5.h        |   3 +-
>  drivers/net/mlx5/mlx5_ethdev.c | 118
> ++++++++++++++++++++++++++++++++---------
>  3 files changed, 107 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index
> 312c42b..44b7a87 100644
> --- a/drivers/net/mlx5/mlx5.c
> +++ b/drivers/net/mlx5/mlx5.c
> @@ -165,6 +165,7 @@ struct mlx5_dev_spawn_data {  {
>       struct mlx5_ibv_shared *sh;
>       int err = 0;
> +     uint32_t i;
> 
>       assert(spawn);
>       /* Search for IB context by device name. */ @@ -212,6 +213,9 @@
> struct mlx5_dev_spawn_data {
>               sizeof(sh->ibdev_name));
>       strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path,
>               sizeof(sh->ibdev_path));
> +     pthread_mutex_init(&sh->intr_mutex, NULL);
> +     for (i = 0; i < sh->max_port; i++)
> +             sh->port[i].port_id = RTE_MAX_ETHPORTS;

Why you need struct here? You port array is not just of uint32_t type?

>       if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
>               /*
>                * For secondary process we just open the IB device @@ -
> 276,6 +280,15 @@ struct mlx5_dev_spawn_data {
>               assert(!sh->pd);
>       }
>       LIST_REMOVE(sh, next);
> +     /*
> +      *  Ensure there is no async event handler installed.
> +      *  Only primary process handles async device events.
> +      **/
> +     assert(!sh->intr_cnt);
> +     if (sh->intr_cnt)
> +             rte_intr_callback_unregister
> +                     (&sh->intr_handle, mlx5_dev_interrupt_handler,
> sh);
> +     pthread_mutex_destroy(&sh->intr_mutex);
>       if (sh->pd)
>               claim_zero(mlx5_glue->dealloc_pd(sh->pd));
>       if (sh->ctx)
> @@ -283,7 +296,6 @@ struct mlx5_dev_spawn_data {
>       rte_free(sh);
>  }
> 
> -
>  /**
>   * Prepare shared data between primary and secondary process.
>   */
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> d816d24..f23298e 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -216,6 +216,8 @@ struct mlx5_ibv_shared {
>       char ibdev_name[IBV_SYSFS_NAME_MAX]; /* IB device name. */
>       char ibdev_path[IBV_SYSFS_PATH_MAX]; /* IB device path for
> secondary */
>       struct ibv_device_attr_ex device_attr; /* Device properties. */
> +     pthread_mutex_t intr_mutex; /* Interrupt config mutex. */
> +     uint32_t intr_cnt; /* Interrupt handler reference counter. */
>       struct rte_intr_handle intr_handle; /* Interrupt handler for device.
> */
>       struct mlx5_ibv_shared_port port[]; /* per device port data array. */
> }; @@ -245,7 +247,6 @@ struct mlx5_priv {
>       struct mlx5_txq_data *(*txqs)[]; /* TX queues. */
>       struct rte_mempool *mprq_mp; /* Mempool for Multi-Packet RQ.
> */
>       struct rte_eth_rss_conf rss_conf; /* RSS configuration. */
> -     struct rte_intr_handle intr_handle; /* Interrupt handler. */
>       unsigned int (*reta_idx)[]; /* RETA index table. */
>       unsigned int reta_idx_n; /* RETA index size. */
>       struct mlx5_drop drop_queue; /* Flow drop queues. */ diff --git
> a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index
> 1b2173b..8358cd2 100644
> --- a/drivers/net/mlx5/mlx5_ethdev.c
> +++ b/drivers/net/mlx5/mlx5_ethdev.c
> @@ -1109,6 +1109,96 @@ int mlx5_fw_version_get(struct rte_eth_dev
> *dev, char *fw_ver, size_t fw_size)  }
> 
>  /**
> + * 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].port_id >= RTE_MAX_ETHPORTS)
> +             goto exit;
> +     assert(sh->port[priv->ibv_port - 1].port_id ==
> +                                     (uint32_t)dev->data->port_id);
> +     assert(sh->intr_cnt);
> +     sh->port[priv->ibv_port - 1].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].port_id < RTE_MAX_ETHPORTS) {

I don't understand why need an array to understand handler is already exists. 
Why not the refcnt?

> +             /* The handler is already installed for this port. */
> +             assert(sh->intr_cnt++);

Asserts are compiled only in debug mode. You should not put any logic (++) into 
them. 

> +             goto exit;
> +     }
> +     sh->port[priv->ibv_port - 1].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].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
> @@ -1119,15 +1209,10 @@ int mlx5_fw_version_get(struct rte_eth_dev
> *dev, char *fw_ver, size_t fw_size)  {
>       struct mlx5_priv *priv = dev->data->dev_private;
> 
> -     if (dev->data->dev_conf.intr_conf.lsc ||
> -         dev->data->dev_conf.intr_conf.rmv)
> -             rte_intr_callback_unregister(&priv->intr_handle,
> -                                          mlx5_dev_interrupt_handler,
> dev);
> +     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.fd = 0;
> -     priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
>       priv->intr_handle_socket.fd = 0;
>       priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;  }
> @@ -1142,28 +1227,9 @@ int mlx5_fw_version_get(struct rte_eth_dev
> *dev, char *fw_ver, size_t fw_size)
> mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)  {
>       struct mlx5_priv *priv = dev->data->dev_private;
> -     struct ibv_context *ctx = priv->sh->ctx;
>       int ret;
> -     int flags;
> 
> -     assert(ctx->async_fd > 0);
> -     flags = fcntl(ctx->async_fd, F_GETFL);
> -     ret = fcntl(ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
> -     if (ret) {
> -             DRV_LOG(INFO,
> -                     "port %u failed to change file descriptor async event"
> -                     " queue",
> -                     dev->data->port_id);
> -             dev->data->dev_conf.intr_conf.lsc = 0;
> -             dev->data->dev_conf.intr_conf.rmv = 0;
> -     }
> -     if (dev->data->dev_conf.intr_conf.lsc ||
> -         dev->data->dev_conf.intr_conf.rmv) {
> -             priv->intr_handle.fd = ctx->async_fd;
> -             priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
> -             rte_intr_callback_register(&priv->intr_handle,
> -                                        mlx5_dev_interrupt_handler, dev);
> -     }
> +     mlx5_dev_shared_handler_install(dev);
>       ret = mlx5_socket_init(dev);
>       if (ret)
>               DRV_LOG(ERR, "port %u cannot initialise socket: %s",
> --
> 1.8.3.1

Reply via email to