mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
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
This commit is contained in:
1 parent
a7c558b4ad
commit
9349214a28
3 files changed
+50
-9
No files matched your search
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user