net/mlx5e: Fix mqprio_rl handling on devlink reload
authorMoshe Tal <moshet@nvidia.com>
Wed, 4 May 2022 13:00:28 +0000 (16:00 +0300)
committerSaeed Mahameed <saeedm@nvidia.com>
Tue, 19 Jul 2022 20:32:49 +0000 (13:32 -0700)
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>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index da10061..5c88c38 100644 (file)
@@ -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;
index cac4022..fe07180 100644 (file)
@@ -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 @@ err_close_tises:
 
 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,32 +3373,32 @@ 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) {
-               mlx5e_mqprio_rl_cleanup(rl);
-               mlx5e_mqprio_rl_free(rl);
+       if (err) {
+               if (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,
@@ -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));
 }