diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index a5f0774834fe..b2b3150f1f04 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -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) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index a24719cfba34..4dc190a4e7b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -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; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 424478e649ef..28d16fdc3f06 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -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); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index 8481ce55c10a..e9f0ef83ce1d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -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); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/shared_fdb.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/shared_fdb.c index 8d4f2903a101..113866494d16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/shared_fdb.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/shared_fdb.c @@ -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);