Re: [PATCH net-next v3 10/12] net/mlx5e: Implement queue mgmt ops and single channel swap

Mina Almasry
2025-06-12T05:33:55Z

On Mon, Jun 9, 2025 at 8:08 AM Mark Bloch <mbloch@nvidia.com> wrote:
>
> From: Saeed Mahameed <saeedm@nvidia.com>
>
> The bulk of the work is done in mlx5e_queue_mem_alloc, where we allocate
> and create the new channel resources, similar to
> mlx5e_safe_switch_params, but here we do it for a single channel using
> existing params, sort of a clone channel.
> To swap the old channel with the new one, we deactivate and close the
> old channel then replace it with the new one, since the swap procedure
> doesn't fail in mlx5, we do it all in one place (mlx5e_queue_start).
>
> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
> Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> Signed-off-by: Mark Bloch <mbloch@nvidia.com>
> ---
> .../net/ethernet/mellanox/mlx5/core/en_main.c | 97 +++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> index a51e204bd364..90687392545c 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> @@ -5494,6 +5494,102 @@ static const struct netdev_stat_ops mlx5e_stat_ops = {
> .get_base_stats = mlx5e_get_base_stats,
> };
>
> +struct mlx5_qmgmt_data {
> + struct mlx5e_channel *c;
> + struct mlx5e_channel_param cparam;
> +};
> +
> +static int mlx5e_queue_mem_alloc(struct net_device *dev, void *newq,
> + int queue_index)
> +{
> + struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
> + struct mlx5e_priv *priv = netdev_priv(dev);
> + struct mlx5e_channels *chs = &priv->channels;
> + struct mlx5e_params params = chs->params;
> + struct mlx5_core_dev *mdev;
> + int err;
> +
> + mutex_lock(&priv->state_lock);
> + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
> + err = -ENODEV;
> + goto unlock;
> + }
> +
> + if (queue_index >= chs->num) {
> + err = -ERANGE;
> + goto unlock;
> + }
> +
> + if (MLX5E_GET_PFLAG(&chs->params, MLX5E_PFLAG_TX_PORT_TS) ||
> + chs->params.ptp_rx ||
> + chs->params.xdp_prog ||
> + priv->htb) {
> + netdev_err(priv->netdev,
> + "Cloning channels with Port/rx PTP, XDP or HTB is not supported\n");
> + err = -EOPNOTSUPP;
> + goto unlock;
> + }
> +
> + mdev = mlx5_sd_ch_ix_get_dev(priv->mdev, queue_index);
> + err = mlx5e_build_channel_param(mdev, &params, &new->cparam);
> + if (err) {
> + return err;
> + goto unlock;
> + }
> +
> + err = mlx5e_open_channel(priv, queue_index, &params, NULL, &new->c);
> +unlock:
> + mutex_unlock(&priv->state_lock);
> + return err;
> +}
> +
> +static void mlx5e_queue_mem_free(struct net_device *dev, void *mem)
> +{
> + struct mlx5_qmgmt_data *data = (struct mlx5_qmgmt_data *)mem;
> +
> + /* not supposed to happen since mlx5e_queue_start never fails
> + * but this is how this should be implemented just in case
> + */
> + if (data->c)
> + mlx5e_close_channel(data->c);
> +}
> +
> +static int mlx5e_queue_stop(struct net_device *dev, void *oldq, int queue_index)
> +{
> + /* mlx5e_queue_start does not fail, we stop the old queue there */
> + return 0;
> +}

Is this really better than maintaining uniformity of behavior between
the drivers that support the queue mgmt api and just doing the
mlx5e_deactivate_priv_channels and mlx5e_close_channel in the stop
like core sorta expects?

We currently use the ndos to restart a queue, but I'm imagining in the
future we can expand it to create queues on behalf of the queues. The
stop queue API may be reused in other contexts, like maybe to kill a
dynamically created devmem queue or something, and this specific
driver may stop working because stop actually doesn't do anything?

--
Thanks,
Mina