]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx5: E-Switch, introduce generic work queue dispatch helper
authorMark Bloch <mbloch@nvidia.com>
Tue, 28 Apr 2026 05:10:16 +0000 (08:10 +0300)
committerJakub Kicinski <kuba@kernel.org>
Thu, 30 Apr 2026 00:46:27 +0000 (17:46 -0700)
Each E-Switch work item requires the same boilerplate: acquire the
devlink lock, check whether the work is stale, dispatch to the
appropriate handler, and release the lock. Factor this out.

Add a func callback to mlx5_host_work so the generic handler
esw_wq_handler() can dispatch to the right function without
duplicating locking logic. Introduce mlx5_esw_add_work() as the
single enqueue point: it stamps the work item with the current
generation counter and queues it onto the E-Switch work queue.

Refactor esw_vfs_changed_event_handler() to match the new contract:
it no longer receives work_gen or out as parameters. It queries
mlx5_esw_query_functions() itself and owns the kvfree() of the
result. The devlink lock is acquired and released by esw_wq_handler()
before dispatching, so the handler runs with the lock already held.

Update mlx5_esw_funcs_changed_handler() to use mlx5_esw_add_work().

Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260428051018.219093-3-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

index 0c3d2bdebf8c91fd9ed71d6b5705ce0cf6ddb70e..e3ab8a30c174663b44f1b8b3d7971c02c025f97f 100644 (file)
@@ -336,6 +336,7 @@ struct mlx5_host_work {
        struct work_struct      work;
        struct mlx5_eswitch     *esw;
        int                     work_gen;
+       void (*func)(struct mlx5_eswitch *esw);
 };
 
 struct mlx5_esw_functions {
index b2e7294d3a5c29ed3deef30a0d5a0844afc328be..23af5a12dc0765c5b433c088b9f077477b5a3b02 100644 (file)
@@ -3655,20 +3655,15 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
        mutex_destroy(&esw->fdb_table.offloads.vports.lock);
 }
 
-static void
-esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, int work_gen,
-                             const u32 *out)
+static void esw_vfs_changed_event_handler(struct mlx5_eswitch *esw)
 {
-       struct devlink *devlink;
        bool host_pf_disabled;
        u16 new_num_vfs;
+       const u32 *out;
 
-       devlink = priv_to_devlink(esw->dev);
-       devl_lock(devlink);
-
-       /* Stale work from one or more mode changes ago. Bail out. */
-       if (work_gen != atomic_read(&esw->generation))
-               goto unlock;
+       out = mlx5_esw_query_functions(esw->dev);
+       if (IS_ERR(out))
+               return;
 
        new_num_vfs = MLX5_GET(query_esw_functions_out, out,
                               host_params_context.host_num_of_vfs);
@@ -3676,7 +3671,7 @@ esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, int work_gen,
                                    host_params_context.host_pf_disabled);
 
        if (new_num_vfs == esw->esw_funcs.num_vfs || host_pf_disabled)
-               goto unlock;
+               goto free;
 
        /* Number of VFs can only change from "0 to x" or "x to 0". */
        if (esw->esw_funcs.num_vfs > 0) {
@@ -3686,54 +3681,70 @@ esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, int work_gen,
 
                err = mlx5_eswitch_load_vf_vports(esw, new_num_vfs,
                                                  MLX5_VPORT_UC_ADDR_CHANGE);
-               if (err) {
-                       devl_unlock(devlink);
-                       return;
-               }
+               if (err)
+                       goto free;
        }
        esw->esw_funcs.num_vfs = new_num_vfs;
-unlock:
-       devl_unlock(devlink);
+free:
+       kvfree(out);
 }
 
-static void esw_functions_changed_event_handler(struct work_struct *work)
+static void esw_wq_handler(struct work_struct *work)
 {
        struct mlx5_host_work *host_work;
        struct mlx5_eswitch *esw;
-       const u32 *out;
+       struct devlink *devlink;
 
        host_work = container_of(work, struct mlx5_host_work, work);
        esw = host_work->esw;
+       devlink = priv_to_devlink(esw->dev);
 
-       out = mlx5_esw_query_functions(esw->dev);
-       if (IS_ERR(out))
-               goto out;
+       devl_lock(devlink);
 
-       esw_vfs_changed_event_handler(esw, host_work->work_gen, out);
-       kvfree(out);
-out:
+       /* Stale work from one or more mode changes ago. Bail out. */
+       if (host_work->work_gen != atomic_read(&esw->generation))
+               goto unlock;
+
+       host_work->func(esw);
+
+unlock:
+       devl_unlock(devlink);
        kfree(host_work);
 }
 
-int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data)
+static int mlx5_esw_add_work(struct mlx5_eswitch *esw,
+                            void (*func)(struct mlx5_eswitch *esw))
 {
-       struct mlx5_esw_functions *esw_funcs;
        struct mlx5_host_work *host_work;
-       struct mlx5_eswitch *esw;
 
        host_work = kzalloc_obj(*host_work, GFP_ATOMIC);
        if (!host_work)
-               return NOTIFY_DONE;
-
-       esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
-       esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
+               return -ENOMEM;
 
        host_work->esw = esw;
        host_work->work_gen = atomic_read(&esw->generation);
 
-       INIT_WORK(&host_work->work, esw_functions_changed_event_handler);
+       host_work->func = func;
+       INIT_WORK(&host_work->work, esw_wq_handler);
        queue_work(esw->work_queue, &host_work->work);
 
+       return 0;
+}
+
+int mlx5_esw_funcs_changed_handler(struct notifier_block *nb,
+                                  unsigned long type, void *data)
+{
+       struct mlx5_esw_functions *esw_funcs;
+       struct mlx5_eswitch *esw;
+       int ret;
+
+       esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
+       esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
+
+       ret = mlx5_esw_add_work(esw, esw_vfs_changed_event_handler);
+       if (ret)
+               return NOTIFY_DONE;
+
        return NOTIFY_OK;
 }