The branch main has been updated by gallatin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=9349214a28152a3cb2424459976f571a9c8fc5df

commit 9349214a28152a3cb2424459976f571a9c8fc5df
Author:     Andrew Gallatin <[email protected]>
AuthorDate: 2025-11-05 23:58:33 +0000
Commit:     Andrew Gallatin <[email protected]>
CommitDate: 2025-11-05 23:58:33 +0000

    mlx5: Preallocate ktls tags asynchronously
    
    Change tag preallocation to happen asynchronously when an interface is
    brought up, so as to reduce boot times when preallocating tags.
    
    - A new mlx5-tls-prealloc_wq is allocated when preallocation is
      desired, and started when an interface is opened
    
    - The bulk of the prealloc code remains the same, except the
      allocations are now M_NOWAIT. M_NOWAIT is needed because, since the
      preallocation is done asynchronously, and since tag allocation is
      not instant, we could race with a real TLS session trying to
      allocate a tag. Note that in this case, we take allocation failure
      as a sign that we were unable to obtain the entire zone due to there
      being other consumers.  This was suggested by @markj as a way to
      keep things simple, after discussing why uma_zone_get_cur() didn't
      immediately report a fully allocated zone.  If this turns out to be
      problematic, we could use uma_zone_set_maxaction() to stop
      pre-allocations (also suggested by Mark)
    
    Reviewed by: glebius, kib, markj
    Sponsored by: Netflix
    Differential Revision: https://reviews.freebsd.org/D53570
---
 sys/dev/mlx5/mlx5_en/en_hw_tls.h      |  3 ++
 sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c | 53 +++++++++++++++++++++++++++++------
 sys/dev/mlx5/mlx5_en/mlx5_en_main.c   |  3 ++
 3 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/sys/dev/mlx5/mlx5_en/en_hw_tls.h b/sys/dev/mlx5/mlx5_en/en_hw_tls.h
index d637314e040e..cd57d2ac5f72 100644
--- a/sys/dev/mlx5/mlx5_en/en_hw_tls.h
+++ b/sys/dev/mlx5/mlx5_en/en_hw_tls.h
@@ -82,6 +82,8 @@ struct mlx5e_tls {
        struct sysctl_ctx_list ctx;
        struct mlx5e_tls_stats stats;
        struct workqueue_struct *wq;
+       struct workqueue_struct *prealloc_wq;
+       struct work_struct prealloc_work;
        uma_zone_t zone;
        uint32_t max_resources;         /* max number of resources */
        int zone_max;
@@ -92,6 +94,7 @@ struct mlx5e_tls {
 int mlx5e_tls_init(struct mlx5e_priv *);
 void mlx5e_tls_cleanup(struct mlx5e_priv *);
 int mlx5e_sq_tls_xmit(struct mlx5e_sq *, struct mlx5e_xmit_args *, struct mbuf 
**);
+void mlx5e_tls_prealloc_tags(struct mlx5e_priv *priv);
 
 if_snd_tag_alloc_t mlx5e_tls_snd_tag_alloc;
 
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c 
b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c
index 6c83de5f3580..851316ccfcd7 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls.c
@@ -80,23 +80,39 @@ static const char *mlx5e_tls_stats_desc[] = {
 };
 
 static void mlx5e_tls_work(struct work_struct *);
+static void mlx5e_tls_prealloc_work(struct work_struct *);
 
 /*
- * Expand the tls tag UMA zone in a sleepable context
+ * Expand the tls tag UMA zone in an async context
  */
 
 static void
-mlx5e_prealloc_tags(struct mlx5e_priv *priv, int nitems)
+mlx5e_tls_prealloc_work(struct work_struct *work)
 {
+       struct mlx5e_priv *priv;
+       struct mlx5e_tls *ptls;
        struct mlx5e_tls_tag **tags;
-       int i;
+       int i, nitems;
+
+       ptls = container_of(work, struct mlx5e_tls, prealloc_work);
+       priv = container_of(ptls, struct mlx5e_priv, tls);
+       nitems = ptls->zone_max;
 
        tags = malloc(sizeof(tags[0]) * nitems,
-           M_MLX5E_TLS, M_WAITOK);
-       for (i = 0; i < nitems; i++)
-               tags[i] = uma_zalloc(priv->tls.zone, M_WAITOK);
+           M_MLX5E_TLS, M_WAITOK | M_ZERO);
+       for (i = 0; i < nitems; i++) {
+               tags[i] = uma_zalloc(priv->tls.zone, M_NOWAIT);
+               /*
+                * If the allocation fails, its likely we are competing
+                * with real consumers of tags and the zone is full,
+                * so exit the loop, and release the tags like we would
+                * if we allocated all "nitems"
+                */
+               if (tags[i] == NULL)
+                       break;
+       }
        __compiler_membar();
-       for (i = 0; i < nitems; i++)
+       for (i = 0; i < nitems && tags[i] != NULL; i++)
                uma_zfree(priv->tls.zone, tags[i]);
        free(tags, M_MLX5E_TLS);
 }
@@ -244,8 +260,6 @@ mlx5e_tls_init(struct mlx5e_priv *priv)
        }
 
        uma_zone_set_max(ptls->zone, ptls->zone_max);
-       if (prealloc_tags != 0)
-               mlx5e_prealloc_tags(priv, ptls->zone_max);
 
        for (x = 0; x != MLX5E_TLS_STATS_NUM; x++)
                ptls->stats.arg[x] = counter_u64_alloc(M_WAITOK);
@@ -270,6 +284,23 @@ mlx5e_tls_init(struct mlx5e_priv *priv)
        return (0);
 }
 
+void
+mlx5e_tls_prealloc_tags(struct mlx5e_priv *priv)
+{
+       struct mlx5e_tls *ptls = &priv->tls;
+       int prealloc_tags = 0;
+
+       if (ptls->prealloc_wq != NULL)
+               return;
+
+       TUNABLE_INT_FETCH("hw.mlx5.tls_prealloc_tags", &prealloc_tags);
+       if (prealloc_tags == 0)
+               return;
+       ptls->prealloc_wq = 
create_singlethread_workqueue("mlx5-tls-prealloc_wq");
+       INIT_WORK(&ptls->prealloc_work, mlx5e_tls_prealloc_work);
+       queue_work(ptls->prealloc_wq, &ptls->prealloc_work);
+}
+
 void
 mlx5e_tls_cleanup(struct mlx5e_priv *priv)
 {
@@ -280,6 +311,10 @@ mlx5e_tls_cleanup(struct mlx5e_priv *priv)
                return;
 
        ptls->init = 0;
+       if (ptls->prealloc_wq != NULL) {
+               flush_workqueue(ptls->prealloc_wq);
+               destroy_workqueue(ptls->prealloc_wq);
+       }
        flush_workqueue(ptls->wq);
        sysctl_ctx_free(&ptls->ctx);
        uma_zdestroy(ptls->zone);
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c 
b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
index f83506bda1aa..ee9c53bb0a60 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -3335,6 +3335,9 @@ mlx5e_open_locked(if_t ifp)
 
        mlx5e_update_carrier(priv);
 
+       if ((if_getcapenable(ifp) & (IFCAP_TXTLS4 | IFCAP_TXTLS6)) != 0)
+               mlx5e_tls_prealloc_tags(priv);
+
        return (0);
 
 err_close_channels:

Reply via email to