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: Moshe Tal <moshet@nvidia.com> Reviewed-by: Tariq Toukan <tariqt@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
parent
07071e47da
commit
0bb7228f70
2 changed files with 106 additions and 41 deletions
|
@ -321,7 +321,8 @@ struct mlx5e_params {
|
||||||
u8 num_tc;
|
u8 num_tc;
|
||||||
struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
|
struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
|
||||||
struct {
|
struct {
|
||||||
struct mlx5e_mqprio_rl *rl;
|
u64 max_rate[TC_MAX_QUEUE];
|
||||||
|
u32 hw_id[TC_MAX_QUEUE];
|
||||||
} channel;
|
} channel;
|
||||||
} mqprio;
|
} mqprio;
|
||||||
bool rx_cqe_compress_def;
|
bool rx_cqe_compress_def;
|
||||||
|
|
|
@ -1912,8 +1912,7 @@ static int mlx5e_txq_get_qos_node_hw_id(struct mlx5e_params *params, int txq_ix,
|
||||||
{
|
{
|
||||||
int tc;
|
int tc;
|
||||||
|
|
||||||
if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL ||
|
if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL) {
|
||||||
!params->mqprio.channel.rl) {
|
|
||||||
*hw_id = 0;
|
*hw_id = 0;
|
||||||
return 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)
|
if (tc < 0)
|
||||||
return tc;
|
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,
|
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);
|
netdev_warn(netdev, "netif_set_real_num_rx_queues failed, %d\n", err);
|
||||||
goto err_txqs;
|
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;
|
return 0;
|
||||||
|
|
||||||
|
@ -3135,6 +3134,11 @@ err_close_tises:
|
||||||
|
|
||||||
static void mlx5e_cleanup_nic_tx(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);
|
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.mode = TC_MQPRIO_MODE_DCB;
|
||||||
params->mqprio.num_tc = num_tc;
|
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,
|
mlx5e_mqprio_build_default_tc_to_txq(params->mqprio.tc_to_txq, num_tc,
|
||||||
params->num_channels);
|
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,
|
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)
|
struct mlx5e_mqprio_rl *rl)
|
||||||
{
|
{
|
||||||
|
int tc;
|
||||||
|
|
||||||
params->mqprio.mode = TC_MQPRIO_MODE_CHANNEL;
|
params->mqprio.mode = TC_MQPRIO_MODE_CHANNEL;
|
||||||
params->mqprio.num_tc = qopt->num_tc;
|
params->mqprio.num_tc = mqprio->qopt.num_tc;
|
||||||
params->mqprio.channel.rl = rl;
|
|
||||||
mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, qopt);
|
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)
|
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,
|
err = mlx5e_safe_switch_params(priv, &new_params,
|
||||||
mlx5e_num_channels_changed_ctx, NULL, true);
|
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,
|
priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
|
||||||
mlx5e_get_dcb_num_tc(&priv->channels.params));
|
mlx5e_get_dcb_num_tc(&priv->channels.params));
|
||||||
return err;
|
return err;
|
||||||
|
@ -3299,16 +3328,38 @@ static int mlx5e_mqprio_channel_validate(struct mlx5e_priv *priv,
|
||||||
return 0;
|
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;
|
int tc;
|
||||||
|
|
||||||
for (tc = 0; tc < mqprio->qopt.num_tc; tc++)
|
for (tc = 0; tc < num_tc; tc++)
|
||||||
if (mqprio->max_rate[tc])
|
if (max_rate[tc])
|
||||||
return true;
|
return true;
|
||||||
return false;
|
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,
|
static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv,
|
||||||
struct tc_mqprio_qopt_offload *mqprio)
|
struct tc_mqprio_qopt_offload *mqprio)
|
||||||
{
|
{
|
||||||
|
@ -3322,32 +3373,32 @@ static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
rl = NULL;
|
rl = mlx5e_mqprio_rl_create(priv->mdev, mqprio->qopt.num_tc, mqprio->max_rate);
|
||||||
if (mlx5e_mqprio_rate_limit(mqprio)) {
|
if (IS_ERR(rl))
|
||||||
rl = mlx5e_mqprio_rl_alloc();
|
return PTR_ERR(rl);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new_params = priv->channels.params;
|
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;
|
nch_changed = mlx5e_get_dcb_num_tc(&priv->channels.params) > 1;
|
||||||
preactivate = nch_changed ? mlx5e_num_channels_changed_ctx :
|
preactivate = nch_changed ? mlx5e_num_channels_changed_ctx :
|
||||||
mlx5e_update_netdev_queues_ctx;
|
mlx5e_update_netdev_queues_ctx;
|
||||||
err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true);
|
err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true);
|
||||||
if (err && rl) {
|
if (err) {
|
||||||
mlx5e_mqprio_rl_cleanup(rl);
|
if (rl) {
|
||||||
mlx5e_mqprio_rl_free(rl);
|
mlx5e_mqprio_rl_cleanup(rl);
|
||||||
|
mlx5e_mqprio_rl_free(rl);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv,
|
||||||
|
@ -5102,6 +5153,23 @@ static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
|
||||||
priv->rx_res = NULL;
|
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)
|
static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -5112,6 +5180,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mlx5e_set_mqprio_rl(priv);
|
||||||
mlx5e_dcbnl_initialize(priv);
|
mlx5e_dcbnl_initialize(priv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5346,11 +5415,6 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
|
||||||
kfree(priv->htb.qos_sq_stats[i]);
|
kfree(priv->htb.qos_sq_stats[i]);
|
||||||
kvfree(priv->htb.qos_sq_stats);
|
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));
|
memset(priv, 0, sizeof(*priv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue