From: Mark Bloch Date: Sun, 3 May 2026 20:27:26 +0000 (+0300) Subject: net/mlx5: E-Switch, load reps via work queue after registration X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25933aca10121a436ac7540be2650b35d9909d3f;p=thirdparty%2Flinux.git net/mlx5: E-Switch, load reps via work queue after registration mlx5_eswitch_register_vport_reps() only installs representor callbacks and marks the rep type as registered. If the E-Switch is already in switchdev mode, the newly registered rep type must then be loaded for already enabled vports. That load path needs to run under the devlink lock, which is not held by the auxiliary driver registration context. Queue the reload to the E-Switch workqueue, whose handler acquires the devlink lock, and load the relevant representors from there. Since representor registration runs from sleepable auxiliary-driver context, queue the late reload with GFP_KERNEL. The functions-change notifier path remains the GFP_ATOMIC user of mlx5_esw_add_work(). The unregister path is unchanged and still unloads representors synchronously while tearing down the registered callbacks. Signed-off-by: Mark Bloch Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20260503202726.266415-8-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 8a7491e9f13d..dea5647de548 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4565,6 +4565,38 @@ mlx5_eswitch_register_vport_reps_blocked(struct mlx5_eswitch *esw, } } +static void mlx5_eswitch_reload_reps_blocked(struct mlx5_eswitch *esw) +{ + struct mlx5_vport *vport; + unsigned long i; + + if (esw->mode != MLX5_ESWITCH_OFFLOADS) + return; + + if (mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK)) + return; + + mlx5_esw_for_each_vport(esw, i, vport) { + if (!vport) + continue; + if (!vport->enabled) + continue; + if (vport->vport == MLX5_VPORT_UPLINK) + continue; + if (!mlx5_eswitch_vport_has_rep(esw, vport->vport)) + continue; + + mlx5_esw_offloads_rep_load(esw, vport->vport); + } +} + +static void mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) +{ + mlx5_esw_reps_block(esw); + mlx5_eswitch_reload_reps_blocked(esw); + mlx5_esw_reps_unblock(esw); +} + static void mlx5_eswitch_register_vport_reps_locked(struct mlx5_eswitch *esw, const struct mlx5_eswitch_rep_ops *ops, @@ -4576,6 +4608,8 @@ mlx5_eswitch_register_vport_reps_locked(struct mlx5_eswitch *esw, mlx5_esw_reps_block(esw); mlx5_eswitch_register_vport_reps_blocked(esw, ops, rep_type); mlx5_esw_reps_unblock(esw); + + mlx5_esw_add_work(esw, mlx5_eswitch_reload_reps, GFP_KERNEL); } void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,