Definers are a limited resource in the system per GVMI, to
avoid failure we try to improve bt checking if it is possible
to reuse the definers in some cases. Added a cache on the context
for this purpose.

Signed-off-by: Alex Vesker <va...@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr_context.c |  12 ++-
 drivers/net/mlx5/hws/mlx5dr_context.h |   1 +
 drivers/net/mlx5/hws/mlx5dr_definer.c | 122 ++++++++++++++++++++++----
 drivers/net/mlx5/hws/mlx5dr_definer.h |  14 +++
 4 files changed, 130 insertions(+), 19 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr_context.c 
b/drivers/net/mlx5/hws/mlx5dr_context.c
index 6627337d9e..08a5ee92a5 100644
--- a/drivers/net/mlx5/hws/mlx5dr_context.c
+++ b/drivers/net/mlx5/hws/mlx5dr_context.c
@@ -13,6 +13,9 @@ static int mlx5dr_context_pools_init(struct mlx5dr_context 
*ctx)
        if (mlx5dr_pat_init_pattern_cache(&ctx->pattern_cache))
                return rte_errno;
 
+       if (mlx5dr_definer_init_cache(&ctx->definer_cache))
+               goto uninit_pat_cache;
+
        /* Create an STC pool per FT type */
        pool_attr.pool_type = MLX5DR_POOL_TYPE_STC;
        pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STC_POOL;
@@ -35,8 +38,10 @@ static int mlx5dr_context_pools_init(struct mlx5dr_context 
*ctx)
                if (ctx->stc_pool[i])
                        mlx5dr_pool_destroy(ctx->stc_pool[i]);
 
-       mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
+       mlx5dr_definer_uninit_cache(ctx->definer_cache);
 
+uninit_pat_cache:
+       mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
        return rte_errno;
 }
 
@@ -44,12 +49,13 @@ static void mlx5dr_context_pools_uninit(struct 
mlx5dr_context *ctx)
 {
        int i;
 
-       mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
-
        for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) {
                if (ctx->stc_pool[i])
                        mlx5dr_pool_destroy(ctx->stc_pool[i]);
        }
+
+       mlx5dr_definer_uninit_cache(ctx->definer_cache);
+       mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
 }
 
 static int mlx5dr_context_init_pd(struct mlx5dr_context *ctx,
diff --git a/drivers/net/mlx5/hws/mlx5dr_context.h 
b/drivers/net/mlx5/hws/mlx5dr_context.h
index a38d9484b3..0ba8d0c92e 100644
--- a/drivers/net/mlx5/hws/mlx5dr_context.h
+++ b/drivers/net/mlx5/hws/mlx5dr_context.h
@@ -39,6 +39,7 @@ struct mlx5dr_context {
        struct mlx5dr_context_common_res common_res[MLX5DR_TABLE_TYPE_MAX];
        struct mlx5dr_context_shared_gvmi_res gvmi_res[MLX5DR_TABLE_TYPE_MAX];
        struct mlx5dr_pattern_cache *pattern_cache;
+       struct mlx5dr_definer_cache *definer_cache;
        pthread_spinlock_t ctrl_lock;
        enum mlx5dr_context_flags flags;
        struct mlx5dr_send_engine *send_queue;
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c 
b/drivers/net/mlx5/hws/mlx5dr_definer.c
index ed91a0998c..fc6b59dd6b 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -2061,6 +2061,7 @@ mlx5dr_definer_compare(struct mlx5dr_definer *definer_a,
 {
        int i;
 
+       /* Future: Optimize by comparing selectors with valid mask only */
        for (i = 0; i < BYTE_SELECTORS; i++)
                if (definer_a->byte_selector[i] != definer_b->byte_selector[i])
                        return 1;
@@ -2133,15 +2134,106 @@ mlx5dr_definer_calc_layout(struct mlx5dr_matcher 
*matcher,
        return rte_errno;
 }
 
+int mlx5dr_definer_init_cache(struct mlx5dr_definer_cache **cache)
+{
+       struct mlx5dr_definer_cache *new_cache;
+
+       new_cache = simple_calloc(1, sizeof(*new_cache));
+       if (!new_cache) {
+               rte_errno = ENOMEM;
+               return rte_errno;
+       }
+       LIST_INIT(&new_cache->head);
+       *cache = new_cache;
+
+       return 0;
+}
+
+void mlx5dr_definer_uninit_cache(struct mlx5dr_definer_cache *cache)
+{
+       simple_free(cache);
+}
+
+static struct mlx5dr_devx_obj *
+mlx5dr_definer_get_obj(struct mlx5dr_context *ctx,
+                      struct mlx5dr_definer *definer)
+{
+       struct mlx5dr_definer_cache *cache = ctx->definer_cache;
+       struct mlx5dr_cmd_definer_create_attr def_attr = {0};
+       struct mlx5dr_definer_cache_item *cached_definer;
+       struct mlx5dr_devx_obj *obj;
+
+       /* Search definer cache for requested definer */
+       LIST_FOREACH(cached_definer, &cache->head, next) {
+               if (mlx5dr_definer_compare(&cached_definer->definer, definer))
+                       continue;
+
+               /* Reuse definer and set LRU (move to be first in the list) */
+               LIST_REMOVE(cached_definer, next);
+               LIST_INSERT_HEAD(&cache->head, cached_definer, next);
+               cached_definer->refcount++;
+               return cached_definer->definer.obj;
+       }
+
+       /* Allocate and create definer based on the bitmask tag */
+       def_attr.match_mask = definer->mask.jumbo;
+       def_attr.dw_selector = definer->dw_selector;
+       def_attr.byte_selector = definer->byte_selector;
+
+       obj = mlx5dr_cmd_definer_create(ctx->ibv_ctx, &def_attr);
+       if (!obj)
+               return NULL;
+
+       cached_definer = simple_calloc(1, sizeof(*cached_definer));
+       if (!cached_definer) {
+               rte_errno = ENOMEM;
+               goto free_definer_obj;
+       }
+
+       memcpy(&cached_definer->definer, definer, sizeof(*definer));
+       cached_definer->definer.obj = obj;
+       cached_definer->refcount = 1;
+       LIST_INSERT_HEAD(&cache->head, cached_definer, next);
+
+       return obj;
+
+free_definer_obj:
+       mlx5dr_cmd_destroy_obj(obj);
+       return NULL;
+}
+
+static void
+mlx5dr_definer_put_obj(struct mlx5dr_context *ctx,
+                      struct mlx5dr_devx_obj *obj)
+{
+       struct mlx5dr_definer_cache_item *cached_definer;
+
+       LIST_FOREACH(cached_definer, &ctx->definer_cache->head, next) {
+               if (cached_definer->definer.obj != obj)
+                       continue;
+
+               /* Object found */
+               if (--cached_definer->refcount)
+                       return;
+
+               LIST_REMOVE(cached_definer, next);
+               mlx5dr_cmd_destroy_obj(cached_definer->definer.obj);
+               simple_free(cached_definer);
+               return;
+       }
+
+       /* Programming error, object must be part of cache */
+       assert(false);
+}
+
 static struct mlx5dr_definer *
-mlx5dr_definer_alloc(struct ibv_context *ibv_ctx,
+mlx5dr_definer_alloc(struct mlx5dr_context *ctx,
                     struct mlx5dr_definer_fc *fc,
                     int fc_sz,
                     struct rte_flow_item *items,
                     struct mlx5dr_definer *layout,
                     bool bind_fc)
 {
-       struct mlx5dr_cmd_definer_create_attr def_attr = {0};
        struct mlx5dr_definer *definer;
        int ret;
 
@@ -2166,12 +2258,7 @@ mlx5dr_definer_alloc(struct ibv_context *ibv_ctx,
        /* Create the tag mask used for definer creation */
        mlx5dr_definer_create_tag_mask(items, fc, fc_sz, definer->mask.jumbo);
 
-       /* Create definer based on the bitmask tag */
-       def_attr.match_mask = definer->mask.jumbo;
-       def_attr.dw_selector = layout->dw_selector;
-       def_attr.byte_selector = layout->byte_selector;
-
-       definer->obj = mlx5dr_cmd_definer_create(ibv_ctx, &def_attr);
+       definer->obj = mlx5dr_definer_get_obj(ctx, definer);
        if (!definer->obj)
                goto free_definer;
 
@@ -2183,9 +2270,10 @@ mlx5dr_definer_alloc(struct ibv_context *ibv_ctx,
 }
 
 static void
-mlx5dr_definer_free(struct mlx5dr_definer *definer)
+mlx5dr_definer_free(struct mlx5dr_context *ctx,
+                   struct mlx5dr_definer *definer)
 {
-       mlx5dr_cmd_destroy_obj(definer->obj);
+       mlx5dr_definer_put_obj(ctx, definer->obj);
        simple_free(definer);
 }
 
@@ -2199,7 +2287,7 @@ mlx5dr_definer_matcher_match_init(struct mlx5dr_context 
*ctx,
 
        /* Create mendatory match definer */
        for (i = 0; i < matcher->num_of_mt; i++) {
-               mt[i].definer = mlx5dr_definer_alloc(ctx->ibv_ctx,
+               mt[i].definer = mlx5dr_definer_alloc(ctx,
                                                     mt[i].fc,
                                                     mt[i].fc_sz,
                                                     mt[i].items,
@@ -2214,7 +2302,7 @@ mlx5dr_definer_matcher_match_init(struct mlx5dr_context 
*ctx,
 
 free_definers:
        while (i--)
-               mlx5dr_definer_free(mt[i].definer);
+               mlx5dr_definer_free(ctx, mt[i].definer);
 
        return rte_errno;
 }
@@ -2222,10 +2310,11 @@ mlx5dr_definer_matcher_match_init(struct mlx5dr_context 
*ctx,
 static void
 mlx5dr_definer_matcher_match_uninit(struct mlx5dr_matcher *matcher)
 {
+       struct mlx5dr_context *ctx = matcher->tbl->ctx;
        int i;
 
        for (i = 0; i < matcher->num_of_mt; i++)
-               mlx5dr_definer_free(matcher->mt[i].definer);
+               mlx5dr_definer_free(ctx, matcher->mt[i].definer);
 }
 
 static int
@@ -2249,7 +2338,7 @@ mlx5dr_definer_matcher_range_init(struct mlx5dr_context 
*ctx,
 
                matcher->flags |= MLX5DR_MATCHER_FLAGS_RANGE_DEFINER;
                /* Create definer without fcr binding, already binded */
-               mt[i].range_definer = mlx5dr_definer_alloc(ctx->ibv_ctx,
+               mt[i].range_definer = mlx5dr_definer_alloc(ctx,
                                                           mt[i].fcr,
                                                           mt[i].fcr_sz,
                                                           mt[i].items,
@@ -2265,7 +2354,7 @@ mlx5dr_definer_matcher_range_init(struct mlx5dr_context 
*ctx,
 free_definers:
        while (i--)
                if (mt[i].range_definer)
-                       mlx5dr_definer_free(mt[i].range_definer);
+                       mlx5dr_definer_free(ctx, mt[i].range_definer);
 
        return rte_errno;
 }
@@ -2273,11 +2362,12 @@ mlx5dr_definer_matcher_range_init(struct mlx5dr_context 
*ctx,
 static void
 mlx5dr_definer_matcher_range_uninit(struct mlx5dr_matcher *matcher)
 {
+       struct mlx5dr_context *ctx = matcher->tbl->ctx;
        int i;
 
        for (i = 0; i < matcher->num_of_mt; i++)
                if (matcher->mt[i].range_definer)
-                       mlx5dr_definer_free(matcher->mt[i].range_definer);
+                       mlx5dr_definer_free(ctx, matcher->mt[i].range_definer);
 }
 
 static int
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.h 
b/drivers/net/mlx5/hws/mlx5dr_definer.h
index dd9a297007..464872acd6 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.h
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.h
@@ -569,6 +569,16 @@ struct mlx5dr_definer {
        struct mlx5dr_devx_obj *obj;
 };
 
+struct mlx5dr_definer_cache {
+       LIST_HEAD(definer_head, mlx5dr_definer_cache_item) head;
+};
+
+struct mlx5dr_definer_cache_item {
+       struct mlx5dr_definer definer;
+       uint32_t refcount;
+       LIST_ENTRY(mlx5dr_definer_cache_item) next;
+};
+
 static inline bool
 mlx5dr_definer_is_jumbo(struct mlx5dr_definer *definer)
 {
@@ -592,4 +602,8 @@ int mlx5dr_definer_matcher_init(struct mlx5dr_context *ctx,
 
 void mlx5dr_definer_matcher_uninit(struct mlx5dr_matcher *matcher);
 
+int mlx5dr_definer_init_cache(struct mlx5dr_definer_cache **cache);
+
+void mlx5dr_definer_uninit_cache(struct mlx5dr_definer_cache *cache);
+
 #endif
-- 
2.18.1

Reply via email to