]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net/mlx5: E-Switch, load reps via work queue after registration
authorMark Bloch <mbloch@nvidia.com>
Sun, 3 May 2026 20:27:26 +0000 (23:27 +0300)
committerJakub Kicinski <kuba@kernel.org>
Thu, 7 May 2026 02:03:37 +0000 (19:03 -0700)
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 <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260503202726.266415-8-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

index 8a7491e9f13d1866ed24bf34ee33aa2d06f3af3a..dea5647de54803761645330118f06ed4d5f5dc5d 100644 (file)
@@ -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,