> -----Original Message-----
> From: Ori Kam <or...@mellanox.com>
> Sent: Thursday, September 26, 2019 9:29
> To: Matan Azrad <ma...@mellanox.com>; Shahaf Shuler
> <shah...@mellanox.com>; Slava Ovsiienko <viachesl...@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <or...@mellanox.com>; jingjing...@intel.com;
> step...@networkplumber.org
> Subject: [PATCH 07/13] net/mlx5: add hairpin binding function
> 
> When starting the port, in addition to creating the queues we need to bind
> the hairpin queues.
> 
> Signed-off-by: Ori Kam <or...@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viachesl...@mellanox.com>

> ---
>  drivers/net/mlx5/mlx5.h           |  1 +
>  drivers/net/mlx5/mlx5_devx_cmds.c |  1 +
>  drivers/net/mlx5/mlx5_prm.h       |  6 +++
>  drivers/net/mlx5/mlx5_trigger.c   | 97
> +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 105 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> 506920e..41eb35a 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -188,6 +188,7 @@ struct mlx5_hca_attr {
>       uint32_t log_max_hairpin_queues:5;
>       uint32_t log_max_hairpin_wq_data_sz:5;
>       uint32_t log_max_hairpin_num_packets:5;
> +     uint32_t vhca_id:16;
>  };
> 
>  /* Flow list . */
> diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c
> b/drivers/net/mlx5/mlx5_devx_cmds.c
> index 917bbf9..0243733 100644
> --- a/drivers/net/mlx5/mlx5_devx_cmds.c
> +++ b/drivers/net/mlx5/mlx5_devx_cmds.c
> @@ -334,6 +334,7 @@ struct mlx5_devx_obj *
> 
> log_max_hairpin_wq_data_sz);
>       attr->log_max_hairpin_num_packets = MLX5_GET
>               (cmd_hca_cap, hcattr, log_min_hairpin_wq_data_sz);
> +     attr->vhca_id = MLX5_GET(cmd_hca_cap, hcattr, vhca_id);
>       attr->eth_net_offloads = MLX5_GET(cmd_hca_cap, hcattr,
>                                         eth_net_offloads);
>       attr->eth_virt = MLX5_GET(cmd_hca_cap, hcattr, eth_virt); diff --git
> a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h index
> faa7996..d4084db 100644
> --- a/drivers/net/mlx5/mlx5_prm.h
> +++ b/drivers/net/mlx5/mlx5_prm.h
> @@ -1611,6 +1611,12 @@ struct mlx5_ifc_create_rqt_in_bits {  #pragma
> GCC diagnostic error "-Wpedantic"
>  #endif
> 
> +enum {
> +     MLX5_SQC_STATE_RST  = 0x0,
> +     MLX5_SQC_STATE_RDY  = 0x1,
> +     MLX5_SQC_STATE_ERR  = 0x3,
> +};
> +
>  struct mlx5_ifc_sqc_bits {
>       u8 rlky[0x1];
>       u8 cd_master[0x1];
> diff --git a/drivers/net/mlx5/mlx5_trigger.c
> b/drivers/net/mlx5/mlx5_trigger.c index 3ec86c4..a4fcdb3 100644
> --- a/drivers/net/mlx5/mlx5_trigger.c
> +++ b/drivers/net/mlx5/mlx5_trigger.c
> @@ -162,6 +162,96 @@
>  }
> 
>  /**
> + * Binds Tx queues to Rx queues for hairpin.
> + *
> + * Binds Tx queues to the target Rx queues.
> + *
> + * @param dev
> + *   Pointer to Ethernet device structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +mlx5_hairpin_bind(struct rte_eth_dev *dev) {
> +     struct mlx5_priv *priv = dev->data->dev_private;
> +     struct mlx5_devx_modify_sq_attr sq_attr = { 0 };
> +     struct mlx5_devx_modify_rq_attr rq_attr = { 0 };
> +     struct mlx5_txq_ctrl *txq_ctrl;
> +     struct mlx5_rxq_ctrl *rxq_ctrl;
> +     struct mlx5_devx_obj *sq;
> +     struct mlx5_devx_obj *rq;
> +     unsigned int i;
> +     int ret = 0;
> +
> +     for (i = 0; i != priv->txqs_n; ++i) {
> +             txq_ctrl = mlx5_txq_get(dev, i);
> +             if (!txq_ctrl)
> +                     continue;
> +             if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
> +                     mlx5_txq_release(dev, i);
> +                     continue;
> +             }
> +             if (!txq_ctrl->obj) {
> +                     rte_errno = ENOMEM;
> +                     DRV_LOG(ERR, "port %u no txq object found: %d",
> +                             dev->data->port_id, i);
> +                     mlx5_txq_release(dev, i);
> +                     return -rte_errno;
> +             }
> +             sq = txq_ctrl->obj->sq;
> +             rxq_ctrl = mlx5_rxq_get(dev,
> +                                     txq_ctrl-
> >hairpin_conf.peers[0].queue);
> +             if (!rxq_ctrl) {
> +                     mlx5_txq_release(dev, i);
> +                     rte_errno = EINVAL;
> +                     DRV_LOG(ERR, "port %u no rxq object found: %d",
> +                             dev->data->port_id,
> +                             txq_ctrl->hairpin_conf.peers[0].queue);
> +                     return -rte_errno;
> +             }
> +             if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
> +                 rxq_ctrl->hairpin_conf.peers[0].queue != i) {
> +                     rte_errno = ENOMEM;
> +                     DRV_LOG(ERR, "port %u Tx queue %d can't be binded
> to "
> +                             "Rx queue %d", dev->data->port_id,
> +                             i, txq_ctrl->hairpin_conf.peers[0].queue);
> +                     goto error;
> +             }
> +             rq = rxq_ctrl->obj->rq;
> +             if (!rq) {
> +                     rte_errno = ENOMEM;
> +                     DRV_LOG(ERR, "port %u hairpin no matching rxq:
> %d",
> +                             dev->data->port_id,
> +                             txq_ctrl->hairpin_conf.peers[0].queue);
> +                     goto error;
> +             }
> +             sq_attr.state = MLX5_SQC_STATE_RDY;
> +             sq_attr.sq_state = MLX5_SQC_STATE_RST;
> +             sq_attr.hairpin_peer_rq = rq->id;
> +             sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
> +             ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr);
> +             if (ret)
> +                     goto error;
> +             rq_attr.state = MLX5_SQC_STATE_RDY;
> +             rq_attr.rq_state = MLX5_SQC_STATE_RST;
> +             rq_attr.hairpin_peer_sq = sq->id;
> +             rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
> +             ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr);
> +             if (ret)
> +                     goto error;
> +             mlx5_txq_release(dev, i);
> +             mlx5_rxq_release(dev, txq_ctrl-
> >hairpin_conf.peers[0].queue);
> +     }
> +     return 0;
> +error:
> +     mlx5_txq_release(dev, i);
> +     mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
> +     return -rte_errno;
> +}
> +
> +/**
>   * DPDK callback to start the device.
>   *
>   * Simulate device start by attaching all configured flows.
> @@ -192,6 +282,13 @@
>               mlx5_txq_stop(dev);
>               return -rte_errno;
>       }
> +     ret = mlx5_hairpin_bind(dev);
> +     if (ret) {
> +             DRV_LOG(ERR, "port %u hairpin binding failed: %s",
> +                     dev->data->port_id, strerror(rte_errno));
> +             mlx5_txq_stop(dev);
> +             return -rte_errno;
> +     }
>       dev->data->dev_started = 1;
>       ret = mlx5_rx_intr_vec_enable(dev);
>       if (ret) {
> --
> 1.8.3.1

Reply via email to