]> git.itanic.dy.fi Git - linux-stable/commitdiff
net/mlx5: DR, Manage definers with refcounts
authorYevgeny Kliteynik <kliteyn@nvidia.com>
Thu, 25 Aug 2022 12:35:59 +0000 (15:35 +0300)
committerSaeed Mahameed <saeedm@nvidia.com>
Fri, 9 Dec 2022 00:10:54 +0000 (16:10 -0800)
In many cases different actions will ask for the same definer format.
Instead of allocating new definer general object and running out of
definers, have an xarray of allocated definers and keep track of their
usage with refcounts: allocate a new definer only when there isn't
one with the same format already created, and destroy definer only
when its refcount runs down to zero.

Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Alex Vesker <valex@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h

index a22c32aabf111eadf79f29660ef6bf2a5504cf59..cd4a1ab0ea78e21d80399f3519bf2a36ee8866ef 100644 (file)
@@ -111,6 +111,7 @@ mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o
                                        steering/dr_ste_v2.o \
                                        steering/dr_cmd.o steering/dr_fw.o \
                                        steering/dr_action.o steering/fs_dr.o \
+                                       steering/dr_definer.o \
                                        steering/dr_dbg.o lib/smfs.o
 #
 # SF device
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c
new file mode 100644 (file)
index 0000000..d5ea977
--- /dev/null
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+#include "dr_types.h"
+#include "dr_ste.h"
+
+struct dr_definer_object {
+       u32 id;
+       u16 format_id;
+       u8 dw_selectors[MLX5_IFC_DEFINER_DW_SELECTORS_NUM];
+       u8 byte_selectors[MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM];
+       u8 match_mask[DR_STE_SIZE_MATCH_TAG];
+       refcount_t refcount;
+};
+
+static bool dr_definer_compare(struct dr_definer_object *definer,
+                              u16 format_id, u8 *dw_selectors,
+                              u8 *byte_selectors, u8 *match_mask)
+{
+       int i;
+
+       if (definer->format_id != format_id)
+               return false;
+
+       for (i = 0; i < MLX5_IFC_DEFINER_DW_SELECTORS_NUM; i++)
+               if (definer->dw_selectors[i] != dw_selectors[i])
+                       return false;
+
+       for (i = 0; i < MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM; i++)
+               if (definer->byte_selectors[i] != byte_selectors[i])
+                       return false;
+
+       if (memcmp(definer->match_mask, match_mask, DR_STE_SIZE_MATCH_TAG))
+               return false;
+
+       return true;
+}
+
+static struct dr_definer_object *
+dr_definer_find_obj(struct mlx5dr_domain *dmn, u16 format_id,
+                   u8 *dw_selectors, u8 *byte_selectors, u8 *match_mask)
+{
+       struct dr_definer_object *definer_obj;
+       unsigned long id;
+
+       xa_for_each(&dmn->definers_xa, id, definer_obj) {
+               if (dr_definer_compare(definer_obj, format_id,
+                                      dw_selectors, byte_selectors,
+                                      match_mask))
+                       return definer_obj;
+       }
+
+       return NULL;
+}
+
+static struct dr_definer_object *
+dr_definer_create_obj(struct mlx5dr_domain *dmn, u16 format_id,
+                     u8 *dw_selectors, u8 *byte_selectors, u8 *match_mask)
+{
+       struct dr_definer_object *definer_obj;
+       int ret = 0;
+
+       definer_obj = kzalloc(sizeof(*definer_obj), GFP_KERNEL);
+       if (!definer_obj)
+               return NULL;
+
+       ret = mlx5dr_cmd_create_definer(dmn->mdev,
+                                       format_id,
+                                       dw_selectors,
+                                       byte_selectors,
+                                       match_mask,
+                                       &definer_obj->id);
+       if (ret)
+               goto err_free_definer_obj;
+
+       /* Definer ID can have 32 bits, but STE format
+        * supports only definers with 8 bit IDs.
+        */
+       if (definer_obj->id > 0xff) {
+               mlx5dr_err(dmn, "Unsupported definer ID (%d)\n", definer_obj->id);
+               goto err_destroy_definer;
+       }
+
+       definer_obj->format_id = format_id;
+       memcpy(definer_obj->dw_selectors, dw_selectors, sizeof(definer_obj->dw_selectors));
+       memcpy(definer_obj->byte_selectors, byte_selectors, sizeof(definer_obj->byte_selectors));
+       memcpy(definer_obj->match_mask, match_mask, sizeof(definer_obj->match_mask));
+
+       refcount_set(&definer_obj->refcount, 1);
+
+       ret = xa_insert(&dmn->definers_xa, definer_obj->id, definer_obj, GFP_KERNEL);
+       if (ret) {
+               mlx5dr_dbg(dmn, "Couldn't insert new definer into xarray (%d)\n", ret);
+               goto err_destroy_definer;
+       }
+
+       return definer_obj;
+
+err_destroy_definer:
+       mlx5dr_cmd_destroy_definer(dmn->mdev, definer_obj->id);
+err_free_definer_obj:
+       kfree(definer_obj);
+
+       return NULL;
+}
+
+static void dr_definer_destroy_obj(struct mlx5dr_domain *dmn,
+                                  struct dr_definer_object *definer_obj)
+{
+       mlx5dr_cmd_destroy_definer(dmn->mdev, definer_obj->id);
+       xa_erase(&dmn->definers_xa, definer_obj->id);
+       kfree(definer_obj);
+}
+
+int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
+                      u8 *dw_selectors, u8 *byte_selectors,
+                      u8 *match_mask, u32 *definer_id)
+{
+       struct dr_definer_object *definer_obj;
+       int ret = 0;
+
+       definer_obj = dr_definer_find_obj(dmn, format_id, dw_selectors,
+                                         byte_selectors, match_mask);
+       if (!definer_obj) {
+               definer_obj = dr_definer_create_obj(dmn, format_id,
+                                                   dw_selectors, byte_selectors,
+                                                   match_mask);
+               if (!definer_obj)
+                       return -ENOMEM;
+       } else {
+               refcount_inc(&definer_obj->refcount);
+       }
+
+       *definer_id = definer_obj->id;
+
+       return ret;
+}
+
+void mlx5dr_definer_put(struct mlx5dr_domain *dmn, u32 definer_id)
+{
+       struct dr_definer_object *definer_obj;
+
+       definer_obj = xa_load(&dmn->definers_xa, definer_id);
+       if (!definer_obj) {
+               mlx5dr_err(dmn, "Definer ID %d not found\n", definer_id);
+               return;
+       }
+
+       if (refcount_dec_and_test(&definer_obj->refcount))
+               dr_definer_destroy_obj(dmn, definer_obj);
+}
index 9a9836218c8e88bb155291c3c18255eacdca1258..5b8bb2ca31e614b26ab0f435422a838697c859de 100644 (file)
@@ -425,10 +425,11 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
        refcount_set(&dmn->refcount, 1);
        mutex_init(&dmn->info.rx.mutex);
        mutex_init(&dmn->info.tx.mutex);
+       xa_init(&dmn->definers_xa);
 
        if (dr_domain_caps_init(mdev, dmn)) {
                mlx5dr_err(dmn, "Failed init domain, no caps\n");
-               goto free_domain;
+               goto def_xa_destroy;
        }
 
        dmn->info.max_log_action_icm_sz = DR_CHUNK_SIZE_4K;
@@ -453,7 +454,8 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
 
 uninit_caps:
        dr_domain_caps_uninit(dmn);
-free_domain:
+def_xa_destroy:
+       xa_destroy(&dmn->definers_xa);
        kfree(dmn);
        return NULL;
 }
@@ -493,6 +495,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
        dr_domain_uninit_csum_recalc_fts(dmn);
        dr_domain_uninit_resources(dmn);
        dr_domain_caps_uninit(dmn);
+       xa_destroy(&dmn->definers_xa);
        mutex_destroy(&dmn->info.tx.mutex);
        mutex_destroy(&dmn->info.rx.mutex);
        kfree(dmn);
index 804268b487d8601bc37332fcea0d3f21854ad9d2..94093c3b55a5737bb8e8d889825a2ae93b4b77ec 100644 (file)
@@ -925,6 +925,7 @@ struct mlx5dr_domain {
        struct mlx5dr_ste_ctx *ste_ctx;
        struct list_head dbg_tbl_list;
        struct mlx5dr_dbg_dump_info dump_info;
+       struct xarray definers_xa;
 };
 
 struct mlx5dr_table_rx_tx {
index 84ed77763b21651f37600f705896c98025fe414a..6ea50436ea6151482dda4433767ad6d9ccea5843 100644 (file)
@@ -142,6 +142,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn,
 
 int mlx5dr_action_destroy(struct mlx5dr_action *action);
 
+int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
+                      u8 *dw_selectors, u8 *byte_selectors,
+                      u8 *match_mask, u32 *definer_id);
+void mlx5dr_definer_put(struct mlx5dr_domain *dmn, u32 definer_id);
+
 static inline bool
 mlx5dr_is_supported(struct mlx5_core_dev *dev)
 {