net/mlx5: Lag, use lag lock
authorMark Bloch <mbloch@nvidia.com>
Wed, 15 Dec 2021 06:51:18 +0000 (06:51 +0000)
committerSaeed Mahameed <saeedm@nvidia.com>
Tue, 10 May 2022 05:54:01 +0000 (22:54 -0700)
Use a lag specific lock instead of depending on external locks to
synchronise the lag creation/destruction.

With this, taking E-Switch mode lock is no longer needed for syncing
lag logic.

Cleanup any dead code that is left over and don't export functions that
aren't used outside the E-Switch core code.

Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Maor Gottlieb <maorg@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h

index 8ef22893e5e67bba1d01c25f8e6c9991b2a33244..719ef26d23c020254b272e3be719414890ef5e47 100644 (file)
@@ -1569,9 +1569,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        ida_init(&esw->offloads.vport_metadata_ida);
        xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
        mutex_init(&esw->state_lock);
-       lockdep_register_key(&esw->mode_lock_key);
        init_rwsem(&esw->mode_lock);
-       lockdep_set_class(&esw->mode_lock, &esw->mode_lock_key);
        refcount_set(&esw->qos.refcnt, 0);
 
        esw->enabled_vports = 0;
@@ -1615,7 +1613,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
        esw->dev->priv.eswitch = NULL;
        destroy_workqueue(esw->work_queue);
        WARN_ON(refcount_read(&esw->qos.refcnt));
-       lockdep_unregister_key(&esw->mode_lock_key);
        mutex_destroy(&esw->state_lock);
        WARN_ON(!xa_empty(&esw->offloads.vhca_map));
        xa_destroy(&esw->offloads.vhca_map);
@@ -2003,17 +2000,6 @@ void mlx5_esw_unlock(struct mlx5_eswitch *esw)
        up_write(&esw->mode_lock);
 }
 
-/**
- * mlx5_esw_lock() - Take write lock on esw mode lock
- * @esw: eswitch device.
- */
-void mlx5_esw_lock(struct mlx5_eswitch *esw)
-{
-       if (!mlx5_esw_allowed(esw))
-               return;
-       down_write(&esw->mode_lock);
-}
-
 /**
  * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
  *
index a5ae5df4d6f104e8e3348f26179c393bdbb5efab..2754a732914de12334452590af1d47d222ff9895 100644 (file)
@@ -331,7 +331,6 @@ struct mlx5_eswitch {
                u32             large_group_num;
        }  params;
        struct blocking_notifier_head n_head;
-       struct lock_class_key mode_lock_key;
 };
 
 void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -704,7 +703,6 @@ void mlx5_esw_get(struct mlx5_core_dev *dev);
 void mlx5_esw_put(struct mlx5_core_dev *dev);
 int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
 void mlx5_esw_unlock(struct mlx5_eswitch *esw);
-void mlx5_esw_lock(struct mlx5_eswitch *esw);
 
 void esw_vport_change_handle_locked(struct mlx5_vport *vport);
 
@@ -730,9 +728,6 @@ static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
        return ERR_PTR(-EOPNOTSUPP);
 }
 
-static inline void mlx5_esw_unlock(struct mlx5_eswitch *esw) { return; }
-static inline void mlx5_esw_lock(struct mlx5_eswitch *esw) { return; }
-
 static inline struct mlx5_flow_handle *
 esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
 {
index 1de843d2f248a2e5f04f9682c386d39a43f72900..fc32f3e05191a8517799ad9b91a4a577e23fa6b4 100644 (file)
@@ -121,6 +121,7 @@ static void mlx5_ldev_free(struct kref *ref)
        mlx5_lag_mp_cleanup(ldev);
        cancel_delayed_work_sync(&ldev->bond_work);
        destroy_workqueue(ldev->wq);
+       mutex_destroy(&ldev->lock);
        kfree(ldev);
 }
 
@@ -150,6 +151,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev)
        }
 
        kref_init(&ldev->ref);
+       mutex_init(&ldev->lock);
        INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
 
        ldev->nb.notifier_call = mlx5_lag_netdev_event;
@@ -643,31 +645,11 @@ static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay)
        queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
 }
 
-static void mlx5_lag_lock_eswitches(struct mlx5_core_dev *dev0,
-                                   struct mlx5_core_dev *dev1)
-{
-       if (dev0)
-               mlx5_esw_lock(dev0->priv.eswitch);
-       if (dev1)
-               mlx5_esw_lock(dev1->priv.eswitch);
-}
-
-static void mlx5_lag_unlock_eswitches(struct mlx5_core_dev *dev0,
-                                     struct mlx5_core_dev *dev1)
-{
-       if (dev1)
-               mlx5_esw_unlock(dev1->priv.eswitch);
-       if (dev0)
-               mlx5_esw_unlock(dev0->priv.eswitch);
-}
-
 static void mlx5_do_bond_work(struct work_struct *work)
 {
        struct delayed_work *delayed_work = to_delayed_work(work);
        struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
                                             bond_work);
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
-       struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
        int status;
 
        status = mlx5_dev_list_trylock();
@@ -676,15 +658,16 @@ static void mlx5_do_bond_work(struct work_struct *work)
                return;
        }
 
+       mutex_lock(&ldev->lock);
        if (ldev->mode_changes_in_progress) {
+               mutex_unlock(&ldev->lock);
                mlx5_dev_list_unlock();
                mlx5_queue_bond_work(ldev, HZ);
                return;
        }
 
-       mlx5_lag_lock_eswitches(dev0, dev1);
        mlx5_do_bond(ldev);
-       mlx5_lag_unlock_eswitches(dev0, dev1);
+       mutex_unlock(&ldev->lock);
        mlx5_dev_list_unlock();
 }
 
@@ -908,7 +891,6 @@ static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev,
        dev->priv.lag = ldev;
 }
 
-/* Must be called with intf_mutex held */
 static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,
                                  struct mlx5_core_dev *dev)
 {
@@ -946,13 +928,18 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev)
                        mlx5_core_err(dev, "Failed to alloc lag dev\n");
                        return 0;
                }
-       } else {
-               if (ldev->mode_changes_in_progress)
-                       return -EAGAIN;
-               mlx5_ldev_get(ldev);
+               mlx5_ldev_add_mdev(ldev, dev);
+               return 0;
        }
 
+       mutex_lock(&ldev->lock);
+       if (ldev->mode_changes_in_progress) {
+               mutex_unlock(&ldev->lock);
+               return -EAGAIN;
+       }
+       mlx5_ldev_get(ldev);
        mlx5_ldev_add_mdev(ldev, dev);
+       mutex_unlock(&ldev->lock);
 
        return 0;
 }
@@ -966,14 +953,14 @@ void mlx5_lag_remove_mdev(struct mlx5_core_dev *dev)
                return;
 
 recheck:
-       mlx5_dev_list_lock();
+       mutex_lock(&ldev->lock);
        if (ldev->mode_changes_in_progress) {
-               mlx5_dev_list_unlock();
+               mutex_unlock(&ldev->lock);
                msleep(100);
                goto recheck;
        }
        mlx5_ldev_remove_mdev(ldev, dev);
-       mlx5_dev_list_unlock();
+       mutex_unlock(&ldev->lock);
        mlx5_ldev_put(ldev);
 }
 
@@ -984,32 +971,35 @@ void mlx5_lag_add_mdev(struct mlx5_core_dev *dev)
 recheck:
        mlx5_dev_list_lock();
        err = __mlx5_lag_dev_add_mdev(dev);
+       mlx5_dev_list_unlock();
+
        if (err) {
-               mlx5_dev_list_unlock();
                msleep(100);
                goto recheck;
        }
-       mlx5_dev_list_unlock();
 }
 
-/* Must be called with intf_mutex held */
 void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,
                            struct net_device *netdev)
 {
        struct mlx5_lag *ldev;
+       bool lag_is_active;
 
        ldev = mlx5_lag_dev(dev);
        if (!ldev)
                return;
 
+       mutex_lock(&ldev->lock);
        mlx5_ldev_remove_netdev(ldev, netdev);
        ldev->flags &= ~MLX5_LAG_FLAG_READY;
 
-       if (__mlx5_lag_is_active(ldev))
+       lag_is_active = __mlx5_lag_is_active(ldev);
+       mutex_unlock(&ldev->lock);
+
+       if (lag_is_active)
                mlx5_queue_bond_work(ldev, 0);
 }
 
-/* Must be called with intf_mutex held */
 void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
                         struct net_device *netdev)
 {
@@ -1020,6 +1010,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
        if (!ldev)
                return;
 
+       mutex_lock(&ldev->lock);
        mlx5_ldev_add_netdev(ldev, dev, netdev);
 
        for (i = 0; i < MLX5_MAX_PORTS; i++)
@@ -1028,6 +1019,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
 
        if (i >= MLX5_MAX_PORTS)
                ldev->flags |= MLX5_LAG_FLAG_READY;
+       mutex_unlock(&ldev->lock);
        mlx5_queue_bond_work(ldev, 0);
 }
 
@@ -1104,8 +1096,6 @@ EXPORT_SYMBOL(mlx5_lag_is_shared_fdb);
 
 void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
 {
-       struct mlx5_core_dev *dev0;
-       struct mlx5_core_dev *dev1;
        struct mlx5_lag *ldev;
 
        ldev = mlx5_lag_dev(dev);
@@ -1113,16 +1103,13 @@ void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
                return;
 
        mlx5_dev_list_lock();
-
-       dev0 = ldev->pf[MLX5_LAG_P1].dev;
-       dev1 = ldev->pf[MLX5_LAG_P2].dev;
+       mutex_lock(&ldev->lock);
 
        ldev->mode_changes_in_progress++;
-       if (__mlx5_lag_is_active(ldev)) {
-               mlx5_lag_lock_eswitches(dev0, dev1);
+       if (__mlx5_lag_is_active(ldev))
                mlx5_disable_lag(ldev);
-               mlx5_lag_unlock_eswitches(dev0, dev1);
-       }
+
+       mutex_unlock(&ldev->lock);
        mlx5_dev_list_unlock();
 }
 
@@ -1134,9 +1121,9 @@ void mlx5_lag_enable_change(struct mlx5_core_dev *dev)
        if (!ldev)
                return;
 
-       mlx5_dev_list_lock();
+       mutex_lock(&ldev->lock);
        ldev->mode_changes_in_progress--;
-       mlx5_dev_list_unlock();
+       mutex_unlock(&ldev->lock);
        mlx5_queue_bond_work(ldev, 0);
 }
 
index cbf9a9003e55b0f3326e864af28280559817dca9..03a7ea07ce9678b89d1e833ca2f1ba4dcff3060b 100644 (file)
@@ -56,6 +56,8 @@ struct mlx5_lag {
        struct notifier_block     nb;
        struct lag_mp             lag_mp;
        struct mlx5_lag_port_sel  port_sel;
+       /* Protect lag fields/state changes */
+       struct mutex              lock;
 };
 
 static inline struct mlx5_lag *