]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx5: E-Switch, Tie rep load/unload to SD LAG state
authorShay Drory <shayd@nvidia.com>
Fri, 12 Jun 2026 11:39:02 +0000 (14:39 +0300)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Jun 2026 18:40:51 +0000 (11:40 -0700)
On an SD device, vport representors are not functional until the SD
group is combined and shared FDB is active. Skip the initial load and
the reload paths in that window; reps are loaded as part of the SD LAG
activation flow once it becomes active.

In addition, explicitly unload representors when SD LAG is destroyed.

Signed-off-by: Shay Drory <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260612113904.537595-14-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
drivers/net/ethernet/mellanox/mlx5/core/lag/shared_fdb.c

index a5f0774834febc16f7cd5d583f99e8aab9f250ef..b2b3150f1f04119243a0977f2cf611b8d17ff6f9 100644 (file)
@@ -959,6 +959,7 @@ int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
 void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
                                              struct mlx5_eswitch *slave_esw);
 int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw);
+void mlx5_eswitch_unload_reps(struct mlx5_eswitch *esw);
 bool mlx5_eswitch_is_peer(struct mlx5_eswitch *esw,
                          struct mlx5_eswitch *peer_esw);
 
@@ -1063,6 +1064,9 @@ mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw)
        return 0;
 }
 
+static inline void
+mlx5_eswitch_unload_reps(struct mlx5_eswitch *esw) {}
+
 static inline bool
 mlx5_eswitch_block_encap(struct mlx5_core_dev *dev, bool from_fdb)
 {
index a24719cfba34f87f77558454e72f9cdd3b1c7d41..4dc190a4e7b28fb519cc7d3934a2687f36ecc5f1 100644 (file)
@@ -2863,6 +2863,10 @@ static int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
        int rep_type;
        int err;
 
+       if (vport_num != MLX5_VPORT_UPLINK &&
+           mlx5_get_sd(esw->dev) && !mlx5_lag_is_active(esw->dev))
+               return 0;
+
        rep = mlx5_eswitch_get_rep(esw, vport_num);
        for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
                err = __esw_offloads_load_rep(esw, rep, rep_type,
@@ -3779,6 +3783,21 @@ static void esw_destroy_offloads_acl_tables(struct mlx5_eswitch *esw)
                esw_vport_destroy_offloads_acl_tables(esw, vport);
 }
 
+void mlx5_eswitch_unload_reps(struct mlx5_eswitch *esw)
+{
+       struct mlx5_eswitch_rep *rep;
+       unsigned long i;
+
+       if (!esw || esw->mode != MLX5_ESWITCH_OFFLOADS)
+               return;
+
+       mlx5_esw_for_each_rep(esw, i, rep) {
+               if (rep->vport == MLX5_VPORT_UPLINK)
+                       continue;
+               mlx5_esw_offloads_rep_unload(esw, rep->vport);
+       }
+}
+
 int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw)
 {
        struct mlx5_eswitch_rep *rep;
@@ -3805,6 +3824,10 @@ int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw)
                if (!mlx5_sd_is_primary(esw->dev) &&
                    rep->vport == MLX5_VPORT_UPLINK)
                        continue;
+               if (rep->vport != MLX5_VPORT_UPLINK &&
+                   mlx5_get_sd(esw->dev) && !mlx5_lag_is_active(esw->dev))
+                       continue;
+
                if (atomic_read(&rep->rep_data[REP_ETH].state) == REP_LOADED)
                        __esw_offloads_load_rep(esw, rep, REP_IB, NULL);
        }
@@ -4764,6 +4787,9 @@ static void mlx5_eswitch_reload_reps_blocked(struct mlx5_eswitch *esw)
                return;
        }
 
+       if (mlx5_get_sd(esw->dev) && !mlx5_lag_is_active(esw->dev))
+               return;
+
        mlx5_esw_for_each_vport(esw, i, vport) {
                if (!vport)
                        continue;
index 424478e649ef589ceaeaecd9c6c41e15c7928f44..28d16fdc3f061503c58b65e2b56d85077055885a 100644 (file)
@@ -1312,6 +1312,32 @@ int mlx5_lag_reload_ib_reps_from_locked(struct mlx5_lag *ldev, u32 flags,
        return mlx5_lag_reload_ib_reps(ldev, flags, filter, cont_on_fail);
 }
 
+static void mlx5_lag_unload_reps_unlocked(struct mlx5_lag *ldev, u32 filter)
+{
+       struct lag_func *pf;
+       int i;
+
+       mlx5_lag_for_each(i, 0, ldev, filter) {
+               struct mlx5_eswitch *esw;
+
+               pf = mlx5_lag_pf(ldev, i);
+               esw = pf->dev->priv.eswitch;
+               mlx5_esw_reps_block(esw);
+               mlx5_eswitch_unload_reps(esw);
+               mlx5_esw_reps_unblock(esw);
+       }
+}
+
+void mlx5_lag_unload_reps_from_locked(struct mlx5_lag *ldev, u32 filter)
+{
+       /* Same lock dance as mlx5_lag_reload_ib_reps: drop ldev->lock around
+        * the per-eswitch reps_lock to keep the reps_lock -> ldev->lock order.
+        */
+       mlx5_lag_drop_lock_for_reps(ldev, filter);
+       mlx5_lag_unload_reps_unlocked(ldev, filter);
+       mlx5_lag_retake_lock_after_reps(ldev);
+}
+
 void mlx5_disable_lag(struct mlx5_lag *ldev)
 {
        bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
index 8481ce55c10ae9ea021e10964ce5c496fe94cc01..e9f0ef83ce1d258f1f48a33b341b8cc4afaefb29 100644 (file)
@@ -310,6 +310,7 @@ int mlx5_lag_num_devs(struct mlx5_lag *ldev);
 int mlx5_lag_num_netdevs(struct mlx5_lag *ldev);
 int mlx5_lag_reload_ib_reps_from_locked(struct mlx5_lag *ldev, u32 flags,
                                        u32 filter, bool cont_on_fail);
+void mlx5_lag_unload_reps_from_locked(struct mlx5_lag *ldev, u32 filter);
 int mlx5_ldev_add_mdev(struct mlx5_lag *ldev, struct mlx5_core_dev *dev,
                       u32 group_id);
 void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev, struct mlx5_core_dev *dev);
index 8d4f2903a1016c60081165cf3e6dbbae210cb35c..113866494d164bee26b87668700ceac1cfef59e7 100644 (file)
@@ -296,6 +296,7 @@ void mlx5_lag_shared_fdb_destroy(struct mlx5_lag *ldev, u32 group_id)
                        pf->sd_fdb_active = false;
                }
                mlx5_lag_destroy_single_fdb_filter(ldev, group_id);
+               mlx5_lag_unload_reps_from_locked(ldev, filter);
        }
 
        mlx5_lag_add_devices_filter(ldev, filter);