Commit 0bb7228f authored by Moshe Tal's avatar Moshe Tal Committed by Saeed Mahameed
Browse files

net/mlx5e: Fix mqprio_rl handling on devlink reload



Keep mqprio_rl data to params and restore the configuration in case of
devlink reload.
Change the location of mqprio_rl resources cleanup so it will be done
also in reload flow.

Also, remove the rl pointer from the params, since this is dynamic object
and saved to priv.

Signed-off-by: default avatarMoshe Tal <moshet@nvidia.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 07071e47
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -321,7 +321,8 @@ struct mlx5e_params {
		u8 num_tc;
		struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
		struct {
			struct mlx5e_mqprio_rl *rl;
			u64 max_rate[TC_MAX_QUEUE];
			u32 hw_id[TC_MAX_QUEUE];
		} channel;
	} mqprio;
	bool rx_cqe_compress_def;
+104 −40
Original line number Diff line number Diff line
@@ -1912,8 +1912,7 @@ static int mlx5e_txq_get_qos_node_hw_id(struct mlx5e_params *params, int txq_ix,
{
	int tc;

	if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL ||
	    !params->mqprio.channel.rl) {
	if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL) {
		*hw_id = 0;
		return 0;
	}
@@ -1922,7 +1921,14 @@ static int mlx5e_txq_get_qos_node_hw_id(struct mlx5e_params *params, int txq_ix,
	if (tc < 0)
		return tc;

	return mlx5e_mqprio_rl_get_node_hw_id(params->mqprio.channel.rl, tc, hw_id);
	if (tc >= params->mqprio.num_tc) {
		WARN(1, "Unexpected TCs configuration. tc %d is out of range of %u",
		     tc, params->mqprio.num_tc);
		return -EINVAL;
	}

	*hw_id = params->mqprio.channel.hw_id[tc];
	return 0;
}

static int mlx5e_open_sqs(struct mlx5e_channel *c,
@@ -2615,13 +2621,6 @@ static int mlx5e_update_netdev_queues(struct mlx5e_priv *priv)
		netdev_warn(netdev, "netif_set_real_num_rx_queues failed, %d\n", err);
		goto err_txqs;
	}
	if (priv->mqprio_rl != priv->channels.params.mqprio.channel.rl) {
		if (priv->mqprio_rl) {
			mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
			mlx5e_mqprio_rl_free(priv->mqprio_rl);
		}
		priv->mqprio_rl = priv->channels.params.mqprio.channel.rl;
	}

	return 0;

@@ -3135,6 +3134,11 @@ int mlx5e_create_tises(struct mlx5e_priv *priv)

static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
{
	if (priv->mqprio_rl) {
		mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
		mlx5e_mqprio_rl_free(priv->mqprio_rl);
		priv->mqprio_rl = NULL;
	}
	mlx5e_destroy_tises(priv);
}

@@ -3203,19 +3207,38 @@ static void mlx5e_params_mqprio_dcb_set(struct mlx5e_params *params, u8 num_tc)
{
	params->mqprio.mode = TC_MQPRIO_MODE_DCB;
	params->mqprio.num_tc = num_tc;
	params->mqprio.channel.rl = NULL;
	mlx5e_mqprio_build_default_tc_to_txq(params->mqprio.tc_to_txq, num_tc,
					     params->num_channels);
}

static void mlx5e_mqprio_rl_update_params(struct mlx5e_params *params,
					  struct mlx5e_mqprio_rl *rl)
{
	int tc;

	for (tc = 0; tc < TC_MAX_QUEUE; tc++) {
		u32 hw_id = 0;

		if (rl)
			mlx5e_mqprio_rl_get_node_hw_id(rl, tc, &hw_id);
		params->mqprio.channel.hw_id[tc] = hw_id;
	}
}

static void mlx5e_params_mqprio_channel_set(struct mlx5e_params *params,
					    struct tc_mqprio_qopt *qopt,
					    struct tc_mqprio_qopt_offload *mqprio,
					    struct mlx5e_mqprio_rl *rl)
{
	int tc;

	params->mqprio.mode = TC_MQPRIO_MODE_CHANNEL;
	params->mqprio.num_tc = qopt->num_tc;
	params->mqprio.channel.rl = rl;
	mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, qopt);
	params->mqprio.num_tc = mqprio->qopt.num_tc;

	for (tc = 0; tc < TC_MAX_QUEUE; tc++)
		params->mqprio.channel.max_rate[tc] = mqprio->max_rate[tc];

	mlx5e_mqprio_rl_update_params(params, rl);
	mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, &mqprio->qopt);
}

static void mlx5e_params_mqprio_reset(struct mlx5e_params *params)
@@ -3241,6 +3264,12 @@ static int mlx5e_setup_tc_mqprio_dcb(struct mlx5e_priv *priv,
	err = mlx5e_safe_switch_params(priv, &new_params,
				       mlx5e_num_channels_changed_ctx, NULL, true);

	if (!err && priv->mqprio_rl) {
		mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
		mlx5e_mqprio_rl_free(priv->mqprio_rl);
		priv->mqprio_rl = NULL;
	}

	priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
				    mlx5e_get_dcb_num_tc(&priv->channels.params));
	return err;
@@ -3299,16 +3328,38 @@ static int mlx5e_mqprio_channel_validate(struct mlx5e_priv *priv,
	return 0;
}

static bool mlx5e_mqprio_rate_limit(struct tc_mqprio_qopt_offload *mqprio)
static bool mlx5e_mqprio_rate_limit(u8 num_tc, u64 max_rate[])
{
	int tc;

	for (tc = 0; tc < mqprio->qopt.num_tc; tc++)
		if (mqprio->max_rate[tc])
	for (tc = 0; tc < num_tc; tc++)
		if (max_rate[tc])
			return true;
	return false;
}

static struct mlx5e_mqprio_rl *mlx5e_mqprio_rl_create(struct mlx5_core_dev *mdev,
						      u8 num_tc, u64 max_rate[])
{
	struct mlx5e_mqprio_rl *rl;
	int err;

	if (!mlx5e_mqprio_rate_limit(num_tc, max_rate))
		return NULL;

	rl = mlx5e_mqprio_rl_alloc();
	if (!rl)
		return ERR_PTR(-ENOMEM);

	err = mlx5e_mqprio_rl_init(rl, mdev, num_tc, max_rate);
	if (err) {
		mlx5e_mqprio_rl_free(rl);
		return ERR_PTR(err);
	}

	return rl;
}

static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv,
					 struct tc_mqprio_qopt_offload *mqprio)
{
@@ -3322,34 +3373,34 @@ static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv,
	if (err)
		return err;

	rl = NULL;
	if (mlx5e_mqprio_rate_limit(mqprio)) {
		rl = mlx5e_mqprio_rl_alloc();
		if (!rl)
			return -ENOMEM;
		err = mlx5e_mqprio_rl_init(rl, priv->mdev, mqprio->qopt.num_tc,
					   mqprio->max_rate);
		if (err) {
			mlx5e_mqprio_rl_free(rl);
			return err;
		}
	}
	rl = mlx5e_mqprio_rl_create(priv->mdev, mqprio->qopt.num_tc, mqprio->max_rate);
	if (IS_ERR(rl))
		return PTR_ERR(rl);

	new_params = priv->channels.params;
	mlx5e_params_mqprio_channel_set(&new_params, &mqprio->qopt, rl);
	mlx5e_params_mqprio_channel_set(&new_params, mqprio, rl);

	nch_changed = mlx5e_get_dcb_num_tc(&priv->channels.params) > 1;
	preactivate = nch_changed ? mlx5e_num_channels_changed_ctx :
		mlx5e_update_netdev_queues_ctx;
	err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true);
	if (err && rl) {
	if (err) {
		if (rl) {
			mlx5e_mqprio_rl_cleanup(rl);
			mlx5e_mqprio_rl_free(rl);
		}

		return err;
	}

	if (priv->mqprio_rl) {
		mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
		mlx5e_mqprio_rl_free(priv->mqprio_rl);
	}
	priv->mqprio_rl = rl;

	return 0;
}

static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv,
				 struct tc_mqprio_qopt_offload *mqprio)
{
@@ -5102,6 +5153,23 @@ static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
	priv->rx_res = NULL;
}

static void mlx5e_set_mqprio_rl(struct mlx5e_priv *priv)
{
	struct mlx5e_params *params;
	struct mlx5e_mqprio_rl *rl;

	params = &priv->channels.params;
	if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL)
		return;

	rl = mlx5e_mqprio_rl_create(priv->mdev, params->mqprio.num_tc,
				    params->mqprio.channel.max_rate);
	if (IS_ERR(rl))
		rl = NULL;
	priv->mqprio_rl = rl;
	mlx5e_mqprio_rl_update_params(params, rl);
}

static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
{
	int err;
@@ -5112,6 +5180,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
		return err;
	}

	mlx5e_set_mqprio_rl(priv);
	mlx5e_dcbnl_initialize(priv);
	return 0;
}
@@ -5346,11 +5415,6 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
		kfree(priv->htb.qos_sq_stats[i]);
	kvfree(priv->htb.qos_sq_stats);

	if (priv->mqprio_rl) {
		mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
		mlx5e_mqprio_rl_free(priv->mqprio_rl);
	}

	memset(priv, 0, sizeof(*priv));
}