net/mlx5e: Introduce switch channels
authorSaeed Mahameed <saeedm@mellanox.com>
Tue, 27 Dec 2016 12:57:03 +0000 (14:57 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 27 Mar 2017 12:08:20 +0000 (15:08 +0300)
A fail safe helper functions that allows switching to new channels on the
fly,  In simple words:

make_new_config(new_params)
{
    new_channels = open_channels(new_params);
    if (!new_channels)
         return "Failed, but current channels are still active :)"

    switch_channels(new_channels);

    return "SUCCESS";
}

Demonstrate mlx5e_switch_priv_channels usage in set channels ethtool
callback and make it fail-safe using the new switch channels mechanism.

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index 44c454b34754246e7e27a2ee8ccfcfcdc8acff50..2f259dfbf8442f08aa8654596cd7393e5062f41d 100644 (file)
@@ -863,6 +863,13 @@ void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
 
 int mlx5e_open_locked(struct net_device *netdev);
 int mlx5e_close_locked(struct net_device *netdev);
+
+int mlx5e_open_channels(struct mlx5e_priv *priv,
+                       struct mlx5e_channels *chs);
+void mlx5e_close_channels(struct mlx5e_channels *chs);
+void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
+                               struct mlx5e_channels *new_chs);
+
 void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
                                   u32 *indirection_rqt, int len,
                                   int num_channels);
index b2cd0ef7921e509e6f8d9d25881d4242b29f54cd..e5cee400a4d33c04236e36ea897b5842065959b2 100644 (file)
@@ -556,8 +556,8 @@ static int mlx5e_set_channels(struct net_device *dev,
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        unsigned int count = ch->combined_count;
+       struct mlx5e_channels new_channels = {};
        bool arfs_enabled;
-       bool was_opened;
        int err = 0;
 
        if (!count) {
@@ -571,22 +571,27 @@ static int mlx5e_set_channels(struct net_device *dev,
 
        mutex_lock(&priv->state_lock);
 
-       was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
-       if (was_opened)
-               mlx5e_close_locked(dev);
+       new_channels.params = priv->channels.params;
+       new_channels.params.num_channels = count;
+       mlx5e_build_default_indir_rqt(priv->mdev, new_channels.params.indirection_rqt,
+                                     MLX5E_INDIR_RQT_SIZE, count);
+
+       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+               priv->channels.params = new_channels.params;
+               goto out;
+       }
+
+       /* Create fresh channels with new parameters */
+       err = mlx5e_open_channels(priv, &new_channels);
+       if (err)
+               goto out;
 
        arfs_enabled = dev->features & NETIF_F_NTUPLE;
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
-       priv->channels.params.num_channels = count;
-       mlx5e_build_default_indir_rqt(priv->mdev, priv->channels.params.indirection_rqt,
-                                     MLX5E_INDIR_RQT_SIZE, count);
-
-       if (was_opened)
-               err = mlx5e_open_locked(dev);
-       if (err)
-               goto out;
+       /* Switch to new channels, set new parameters and close old ones */
+       mlx5e_switch_priv_channels(priv, &new_channels);
 
        if (arfs_enabled) {
                err = mlx5e_arfs_enable(priv);
index a94f84ec2c1a84eecdfe3527fc06a4315099e837..97e153209834aa8409c05135b7db2a3837459307 100644 (file)
@@ -1972,8 +1972,8 @@ static void mlx5e_build_channel_param(struct mlx5e_priv *priv,
        mlx5e_build_ico_cq_param(priv, icosq_log_wq_sz, &cparam->icosq_cq);
 }
 
-static int mlx5e_open_channels(struct mlx5e_priv *priv,
-                              struct mlx5e_channels *chs)
+int mlx5e_open_channels(struct mlx5e_priv *priv,
+                       struct mlx5e_channels *chs)
 {
        struct mlx5e_channel_param *cparam;
        int err = -ENOMEM;
@@ -2037,7 +2037,7 @@ static void mlx5e_deactivate_channels(struct mlx5e_channels *chs)
                mlx5e_deactivate_channel(chs->c[i]);
 }
 
-static void mlx5e_close_channels(struct mlx5e_channels *chs)
+void mlx5e_close_channels(struct mlx5e_channels *chs)
 {
        int i;
 
@@ -2533,6 +2533,30 @@ static void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
        mlx5e_deactivate_channels(&priv->channels);
 }
 
+void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
+                               struct mlx5e_channels *new_chs)
+{
+       struct net_device *netdev = priv->netdev;
+       int new_num_txqs;
+
+       new_num_txqs = new_chs->num * new_chs->params.num_tc;
+
+       netif_carrier_off(netdev);
+
+       if (new_num_txqs < netdev->real_num_tx_queues)
+               netif_set_real_num_tx_queues(netdev, new_num_txqs);
+
+       mlx5e_deactivate_priv_channels(priv);
+       mlx5e_close_channels(&priv->channels);
+
+       priv->channels = *new_chs;
+
+       mlx5e_refresh_tirs(priv, false);
+       mlx5e_activate_priv_channels(priv);
+
+       mlx5e_update_carrier(priv);
+}
+
 int mlx5e_open_locked(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);