From patchwork Mon Jul 13 06:15:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Somnath Kotur X-Patchwork-Id: 73863 X-Patchwork-Delegate: ajit.khaparde@broadcom.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 350D6A0540; Mon, 13 Jul 2020 08:21:33 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7D1801C1EB; Mon, 13 Jul 2020 08:21:15 +0200 (CEST) Received: from relay.smtp.broadcom.com (relay.smtp.broadcom.com [192.19.211.62]) by dpdk.org (Postfix) with ESMTP id 383C81C1B2 for ; Mon, 13 Jul 2020 08:21:10 +0200 (CEST) Received: from dhcp-10-123-153-55.dhcp.broadcom.net (dhcp-10-123-153-55.dhcp.broadcom.net [10.123.153.55]) by relay.smtp.broadcom.com (Postfix) with ESMTP id 62A3929C61E; Sun, 12 Jul 2020 23:21:09 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.10.3 relay.smtp.broadcom.com 62A3929C61E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1594621269; bh=oz01cxplkzFTnXIdsgKMfs0Ei3gjpP2HZjHTRzrhq1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AyLcn+ChZXvyuyUlxonLjKNAGW1Alx4SI1QFpebbk3fl7T4fYbd5rO37g7sfluDhh 0RN6bsfNeRxHVRnLCpeXSIf5GJx/fDfS2CI012tTvm1Xh7elrSEoHPAT4CjS1cqJgX BBWmFK017Gr7Fir5KOzKrzxKnr0Egdf9vYavIkA4= From: Somnath Kotur To: dev@dpdk.org Cc: ferruh.yigit@intel.com Date: Mon, 13 Jul 2020 11:45:52 +0530 Message-Id: <20200713061600.19456-3-somnath.kotur@broadcom.com> X-Mailer: git-send-email 2.10.1.613.g2cc2e70 In-Reply-To: <20200713061600.19456-1-somnath.kotur@broadcom.com> References: <20200713061600.19456-1-somnath.kotur@broadcom.com> Subject: [dpdk-dev] [PATCH 02/10] net/bnxt: implement TF Identifier search X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Jay Ding Implement shadow copy DB to hold reference count for each ID in each identifier type. Implement identifier search functionality. Signed-off-by: Jay Ding Reviewed-by: Randy Schacher Signed-off-by: Somnath Kotur --- drivers/net/bnxt/meson.build | 3 +- drivers/net/bnxt/tf_core/Makefile | 1 + drivers/net/bnxt/tf_core/tf_core.c | 61 +++++++ drivers/net/bnxt/tf_core/tf_core.h | 70 +++++++- drivers/net/bnxt/tf_core/tf_device.h | 20 +++ drivers/net/bnxt/tf_core/tf_device_p4.c | 2 + drivers/net/bnxt/tf_core/tf_identifier.c | 148 +++++++++++++++ drivers/net/bnxt/tf_core/tf_identifier.h | 47 +++++ drivers/net/bnxt/tf_core/tf_rm.c | 2 + drivers/net/bnxt/tf_core/tf_rm.h | 8 + drivers/net/bnxt/tf_core/tf_shadow_identifier.c | 190 ++++++++++++++++++++ drivers/net/bnxt/tf_core/tf_shadow_identifier.h | 229 ++++++++++++++++++++++++ 12 files changed, 777 insertions(+), 4 deletions(-) create mode 100644 drivers/net/bnxt/tf_core/tf_shadow_identifier.c create mode 100644 drivers/net/bnxt/tf_core/tf_shadow_identifier.h diff --git a/drivers/net/bnxt/meson.build b/drivers/net/bnxt/meson.build index 0b93c31..8529b33 100644 --- a/drivers/net/bnxt/meson.build +++ b/drivers/net/bnxt/meson.build @@ -46,7 +46,7 @@ sources = files('bnxt_cpr.c', 'tf_core/ll.c', 'tf_core/tf_global_cfg.c', 'tf_core/tf_em_host.c', - 'tf_ulp/ulp_fc_mgr.c', + 'tf_core/tf_shadow_identifier.c', 'hcapi/hcapi_cfa_p4.c', @@ -63,6 +63,7 @@ sources = files('bnxt_cpr.c', 'tf_ulp/bnxt_ulp_flow.c', 'tf_ulp/ulp_port_db.c', 'tf_ulp/ulp_def_rules.c', + 'tf_ulp/ulp_fc_mgr.c', 'rte_pmd_bnxt.c') diff --git a/drivers/net/bnxt/tf_core/Makefile b/drivers/net/bnxt/tf_core/Makefile index 8064714..9c2735d 100644 --- a/drivers/net/bnxt/tf_core/Makefile +++ b/drivers/net/bnxt/tf_core/Makefile @@ -31,3 +31,4 @@ SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_tcam.c SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_util.c SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_if_tbl.c SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_global_cfg.c +SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_shadow_identifier.c diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c index a404cb8..97e7952 100644 --- a/drivers/net/bnxt/tf_core/tf_core.c +++ b/drivers/net/bnxt/tf_core/tf_core.c @@ -534,6 +534,7 @@ tf_free_identifier(struct tf *tfp, fparms.dir = parms->dir; fparms.type = parms->ident_type; fparms.id = parms->id; + fparms.ref_cnt = &parms->ref_cnt; rc = dev->ops->tf_dev_free_ident(tfp, &fparms); if (rc) { TFP_DRV_LOG(ERR, @@ -547,6 +548,66 @@ tf_free_identifier(struct tf *tfp, } int +tf_search_identifier(struct tf *tfp, + struct tf_search_identifier_parms *parms) +{ + int rc; + struct tf_session *tfs; + struct tf_dev_info *dev; + struct tf_ident_search_parms sparms; + + TF_CHECK_PARMS2(tfp, parms); + + /* Can't do static initialization due to UT enum check */ + memset(&sparms, 0, sizeof(struct tf_ident_search_parms)); + + /* Retrieve the session information */ + rc = tf_session_get_session(tfp, &tfs); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Failed to lookup session, rc:%s\n", + tf_dir_2_str(parms->dir), + strerror(-rc)); + return rc; + } + + /* Retrieve the device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Failed to lookup device, rc:%s\n", + tf_dir_2_str(parms->dir), + strerror(-rc)); + return rc; + } + + if (dev->ops->tf_dev_search_ident == NULL) { + rc = -EOPNOTSUPP; + TFP_DRV_LOG(ERR, + "%s: Operation not supported, rc:%s\n", + tf_dir_2_str(parms->dir), + strerror(-rc)); + return rc; + } + + sparms.dir = parms->dir; + sparms.type = parms->ident_type; + sparms.search_id = parms->search_id; + sparms.hit = &parms->hit; + sparms.ref_cnt = &parms->ref_cnt; + rc = dev->ops->tf_dev_search_ident(tfp, &sparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Identifier search failed, rc:%s\n", + tf_dir_2_str(parms->dir), + strerror(-rc)); + return rc; + } + + return 0; +} + +int tf_alloc_tcam_entry(struct tf *tfp, struct tf_alloc_tcam_entry_parms *parms) { diff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h index 9e80426..9a5e816 100644 --- a/drivers/net/bnxt/tf_core/tf_core.h +++ b/drivers/net/bnxt/tf_core/tf_core.h @@ -695,9 +695,9 @@ struct tf_alloc_identifier_parms { */ enum tf_identifier_type ident_type; /** - * [out] Identifier allocated + * [out] Allocated identifier */ - uint16_t id; + uint32_t id; }; /** @@ -715,7 +715,38 @@ struct tf_free_identifier_parms { /** * [in] ID to free */ - uint16_t id; + uint32_t id; + /** + * (experimental) + * [out] Current refcnt after free + */ + uint32_t ref_cnt; +}; + +/** + * tf_search_identifier parameter definition (experimental) + */ +struct tf_search_identifier_parms { + /** + * [in] receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Identifier type + */ + enum tf_identifier_type ident_type; + /** + * [in] Identifier data to search for + */ + uint32_t search_id; + /** + * [out] Set if matching identifier found + */ + bool hit; + /** + * [out] Current ref count after allocation + */ + uint32_t ref_cnt; }; /** @@ -724,6 +755,9 @@ struct tf_free_identifier_parms { * TruFlow core will allocate a free id from the per identifier resource type * pool reserved for the session during tf_open(). No firmware is involved. * + * If shadow copy is enabled, the internal ref_cnt is set to 1 in the + * shadow table for a newly allocated resource. + * * Returns success or failure code. */ int tf_alloc_identifier(struct tf *tfp, @@ -736,12 +770,42 @@ int tf_alloc_identifier(struct tf *tfp, * reserved for the session. No firmware is involved. During tf_close, the * complete pool is returned to the firmware. * + * additional operation (experimental) + * Decrement reference count. Only release resource once refcnt goes to 0 if + * shadow copy is enabled. + * * Returns success or failure code. */ int tf_free_identifier(struct tf *tfp, struct tf_free_identifier_parms *parms); /** + * Search identifier resource (experimental) + * + * If the shadow copy is enabled search_id is used to search for a matching + * entry in the shadow table. The shadow table consists of an array of + * reference counts indexed by identifier. If a matching entry is found hit is + * set to TRUE, refcnt is increased by 1 and returned. Otherwise, hit is + * set to false and refcnt is set to 0. + * + * TODO: we may need a per table internal shadow copy enable flag to stage + * the shadow table implementation. We do not need the shadow table for other + * tables at this time so we may only want to enable the identifier shadow. + * + * TODO: remove this pseudocode below added to show that if search fails + * we shouldn't allocate a new entry but return. + * + * identifier alloc (search_en=1) + * if (ident is allocated and ref_cnt >=1) + * return ident - hit is set, incr refcnt + * else (not found) + * return + * + */ +int tf_search_identifier(struct tf *tfp, + struct tf_search_identifier_parms *parms); + +/** * @page dram_table DRAM Table Scope Interface * * @ref tf_alloc_tbl_scope diff --git a/drivers/net/bnxt/tf_core/tf_device.h b/drivers/net/bnxt/tf_core/tf_device.h index 0bc7090..fce7f25 100644 --- a/drivers/net/bnxt/tf_core/tf_device.h +++ b/drivers/net/bnxt/tf_core/tf_device.h @@ -199,6 +199,26 @@ struct tf_dev_ops { struct tf_ident_free_parms *parms); /** + * Search of an identifier element. + * + * This API search the specified identifier element from a + * device specific identifier shadow DB. The allocated element + * is returned. + * + * [in] tfp + * Pointer to TF handle + * + * [in] parms + * Pointer to identifier search parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ + int (*tf_dev_search_ident)(struct tf *tfp, + struct tf_ident_search_parms *parms); + + /** * Allocation of a table type element. * * This API allocates the specified table type element from a diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c index dfe626c..f38c38e 100644 --- a/drivers/net/bnxt/tf_core/tf_device_p4.c +++ b/drivers/net/bnxt/tf_core/tf_device_p4.c @@ -86,6 +86,7 @@ const struct tf_dev_ops tf_dev_ops_p4_init = { .tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info, .tf_dev_alloc_ident = NULL, .tf_dev_free_ident = NULL, + .tf_dev_search_ident = NULL, .tf_dev_alloc_ext_tbl = NULL, .tf_dev_alloc_tbl = NULL, .tf_dev_free_ext_tbl = NULL, @@ -120,6 +121,7 @@ const struct tf_dev_ops tf_dev_ops_p4 = { .tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info, .tf_dev_alloc_ident = tf_ident_alloc, .tf_dev_free_ident = tf_ident_free, + .tf_dev_search_ident = tf_ident_search, .tf_dev_alloc_tbl = tf_tbl_alloc, .tf_dev_alloc_ext_tbl = tf_tbl_ext_alloc, .tf_dev_free_tbl = tf_tbl_free, diff --git a/drivers/net/bnxt/tf_core/tf_identifier.c b/drivers/net/bnxt/tf_core/tf_identifier.c index 90aeaa4..273d629 100644 --- a/drivers/net/bnxt/tf_core/tf_identifier.c +++ b/drivers/net/bnxt/tf_core/tf_identifier.c @@ -6,6 +6,7 @@ #include #include "tf_identifier.h" +#include "tf_shadow_identifier.h" #include "tf_common.h" #include "tf_rm.h" #include "tf_util.h" @@ -23,6 +24,16 @@ static void *ident_db[TF_DIR_MAX]; */ static uint8_t init; +/** + * Identifier shadow DBs. + */ +static void *ident_shadow_db[TF_DIR_MAX]; + +/** + * Shadow DB Init flag, set on bind and cleared on unbind + */ +static uint8_t shadow_init; + int tf_ident_bind(struct tf *tfp, struct tf_ident_cfg_parms *parms) @@ -30,6 +41,8 @@ tf_ident_bind(struct tf *tfp, int rc; int i; struct tf_rm_create_db_parms db_cfg = { 0 }; + struct tf_shadow_ident_cfg_parms shadow_cfg = { 0 }; + struct tf_shadow_ident_create_db_parms shadow_cdb = { 0 }; TF_CHECK_PARMS2(tfp, parms); @@ -55,6 +68,23 @@ tf_ident_bind(struct tf *tfp, return rc; } + + if (parms->shadow_copy) { + shadow_cfg.alloc_cnt = + parms->resources->ident_cnt[i].cnt; + shadow_cdb.num_elements = parms->num_elements; + shadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i]; + shadow_cdb.cfg = &shadow_cfg; + rc = tf_shadow_ident_create_db(&shadow_cdb); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Ident shadow DB creation failed\n", + tf_dir_2_str(i)); + + return rc; + } + shadow_init = 1; + } } init = 1; @@ -71,6 +101,7 @@ tf_ident_unbind(struct tf *tfp) int rc = 0; int i; struct tf_rm_free_db_parms fparms = { 0 }; + struct tf_shadow_ident_free_db_parms sparms = { 0 }; TF_CHECK_PARMS1(tfp); @@ -89,10 +120,22 @@ tf_ident_unbind(struct tf *tfp) TFP_DRV_LOG(ERR, "rm free failed on unbind\n"); } + if (shadow_init) { + sparms.tf_shadow_ident_db = ident_shadow_db[i]; + rc = tf_shadow_ident_free_db(&sparms); + if (rc) { + /* TODO: If there are failures on unbind we + * really just have to try until all DBs are + * attempted to be cleared. + */ + } + ident_shadow_db[i] = NULL; + } ident_db[i] = NULL; } init = 0; + shadow_init = 0; return 0; } @@ -103,7 +146,9 @@ tf_ident_alloc(struct tf *tfp __rte_unused, { int rc; uint32_t id; + uint32_t base_id; struct tf_rm_allocate_parms aparms = { 0 }; + struct tf_shadow_ident_insert_parms iparms = { 0 }; TF_CHECK_PARMS2(tfp, parms); @@ -118,6 +163,7 @@ tf_ident_alloc(struct tf *tfp __rte_unused, aparms.rm_db = ident_db[parms->dir]; aparms.db_index = parms->type; aparms.index = &id; + aparms.base_index = &base_id; rc = tf_rm_allocate(&aparms); if (rc) { TFP_DRV_LOG(ERR, @@ -127,6 +173,21 @@ tf_ident_alloc(struct tf *tfp __rte_unused, return rc; } + if (shadow_init) { + iparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; + iparms.type = parms->type; + iparms.id = base_id; + + rc = tf_shadow_ident_insert(&iparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Failed insert shadow DB, type:%d\n", + tf_dir_2_str(parms->dir), + parms->type); + return rc; + } + } + *parms->id = id; return 0; @@ -139,7 +200,9 @@ tf_ident_free(struct tf *tfp __rte_unused, int rc; struct tf_rm_is_allocated_parms aparms = { 0 }; struct tf_rm_free_parms fparms = { 0 }; + struct tf_shadow_ident_remove_parms rparms = { 0 }; int allocated = 0; + uint32_t base_id; TF_CHECK_PARMS2(tfp, parms); @@ -154,6 +217,7 @@ tf_ident_free(struct tf *tfp __rte_unused, aparms.rm_db = ident_db[parms->dir]; aparms.db_index = parms->type; aparms.index = parms->id; + aparms.base_index = &base_id; aparms.allocated = &allocated; rc = tf_rm_is_allocated(&aparms); if (rc) @@ -168,6 +232,27 @@ tf_ident_free(struct tf *tfp __rte_unused, return -EINVAL; } + if (shadow_init) { + rparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; + rparms.type = parms->type; + rparms.id = base_id; + rparms.ref_cnt = parms->ref_cnt; + + rc = tf_shadow_ident_remove(&rparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: ref_cnt was 0 in shadow DB," + " type:%d, index:%d\n", + tf_dir_2_str(parms->dir), + parms->type, + parms->id); + return rc; + } + + if (*rparms.ref_cnt > 0) + return 0; + } + /* Free requested element */ fparms.rm_db = ident_db[parms->dir]; fparms.db_index = parms->type; @@ -184,3 +269,66 @@ tf_ident_free(struct tf *tfp __rte_unused, return 0; } + +int +tf_ident_search(struct tf *tfp __rte_unused, + struct tf_ident_search_parms *parms) +{ + int rc; + struct tf_rm_is_allocated_parms aparms = { 0 }; + struct tf_shadow_ident_search_parms sparms = { 0 }; + int allocated = 0; + uint32_t base_id; + + TF_CHECK_PARMS2(tfp, parms); + + if (!init) { + TFP_DRV_LOG(ERR, + "%s: No Identifier DBs created\n", + tf_dir_2_str(parms->dir)); + return -EINVAL; + } + + if (!shadow_init) { + TFP_DRV_LOG(ERR, + "%s: Identifier Shadow copy is not enabled\n", + tf_dir_2_str(parms->dir)); + return -EINVAL; + } + + /* Check if element is in use */ + aparms.rm_db = ident_db[parms->dir]; + aparms.db_index = parms->type; + aparms.index = parms->search_id; + aparms.base_index = &base_id; + aparms.allocated = &allocated; + rc = tf_rm_is_allocated(&aparms); + if (rc) + return rc; + + if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { + TFP_DRV_LOG(ERR, + "%s: Entry not allocated, type:%d, index:%d\n", + tf_dir_2_str(parms->dir), + parms->type, + parms->search_id); + return -EINVAL; + } + + sparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; + sparms.type = parms->type; + sparms.search_id = base_id; + sparms.hit = parms->hit; + sparms.ref_cnt = parms->ref_cnt; + + rc = tf_shadow_ident_search(&sparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Failed search shadow DB, type:%d\n", + tf_dir_2_str(parms->dir), + parms->type); + return rc; + } + + return 0; +} diff --git a/drivers/net/bnxt/tf_core/tf_identifier.h b/drivers/net/bnxt/tf_core/tf_identifier.h index 6e36c52..6d9fa08 100644 --- a/drivers/net/bnxt/tf_core/tf_identifier.h +++ b/drivers/net/bnxt/tf_core/tf_identifier.h @@ -66,6 +66,37 @@ struct tf_ident_free_parms { * [in] ID to free */ uint16_t id; + /** + * (experimental) + * [out] Current refcnt after free + */ + uint32_t *ref_cnt; +}; + +/** + * Identifier search parameter definition + */ +struct tf_ident_search_parms { + /** + * [in] receive or transmit direction + */ + enum tf_dir dir; + /** + * [in] Identifier type + */ + enum tf_identifier_type type; + /** + * [in] Identifier data to search for + */ + uint16_t search_id; + /** + * [out] Set if matching identifier found + */ + bool *hit; + /** + * [out] Current ref count after allocation + */ + uint32_t *ref_cnt; }; /** @@ -144,4 +175,20 @@ int tf_ident_alloc(struct tf *tfp, int tf_ident_free(struct tf *tfp, struct tf_ident_free_parms *parms); +/** + * Search a single identifier type. + * + * [in] tfp + * Pointer to TF handle, used for HCAPI communication + * + * [in] parms + * Pointer to parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_ident_search(struct tf *tfp, + struct tf_ident_search_parms *parms); + #endif /* _TF_IDENTIFIER_H_ */ diff --git a/drivers/net/bnxt/tf_core/tf_rm.c b/drivers/net/bnxt/tf_core/tf_rm.c index fdb87ec..78bc231 100644 --- a/drivers/net/bnxt/tf_core/tf_rm.c +++ b/drivers/net/bnxt/tf_core/tf_rm.c @@ -755,6 +755,7 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms) } *parms->index = index; + *parms->base_index = id; return rc; } @@ -841,6 +842,7 @@ tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms) if (rc) return rc; + *parms->base_index = adj_index; *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool, adj_index); diff --git a/drivers/net/bnxt/tf_core/tf_rm.h b/drivers/net/bnxt/tf_core/tf_rm.h index 775f0aa..971120a 100644 --- a/drivers/net/bnxt/tf_core/tf_rm.h +++ b/drivers/net/bnxt/tf_core/tf_rm.h @@ -204,6 +204,10 @@ struct tf_rm_allocate_parms { * available index) */ uint32_t priority; + /** + * [in] Pointer to the allocated index before adjusted. + */ + uint32_t *base_index; }; /** @@ -246,6 +250,10 @@ struct tf_rm_is_allocated_parms { * [in] Pointer to flag that indicates the state of the query */ int *allocated; + /** + * [in] Pointer to the allocated index before adjusted. + */ + uint32_t *base_index; }; /** diff --git a/drivers/net/bnxt/tf_core/tf_shadow_identifier.c b/drivers/net/bnxt/tf_core/tf_shadow_identifier.c new file mode 100644 index 0000000..390d22f --- /dev/null +++ b/drivers/net/bnxt/tf_core/tf_shadow_identifier.c @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019-2020 Broadcom + * All rights reserved. + */ + +#include + +#include "tf_shadow_identifier.h" +#include "tf_common.h" +#include "tf_util.h" +#include "tfp.h" + +/** + * Shadow identifier DB element + */ +struct tf_shadow_ident_element { + /** + * Identifier + */ + uint32_t *id; + + /** + * Reference count, array of number of identifier type entries + */ + uint32_t *ref_count; +}; + +/** + * Shadow identifier DB definition + */ +struct tf_shadow_ident_db { + /** + * Number of elements in the DB + */ + uint16_t num_entries; + + /** + * The DB consists of an array of elements + */ + struct tf_shadow_ident_element *db; +}; + +int +tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms) +{ + int rc; + int i; + struct tfp_calloc_parms cparms; + struct tf_shadow_ident_db *shadow_db; + struct tf_shadow_ident_element *db; + + TF_CHECK_PARMS1(parms); + + /* Build the shadow DB per the request */ + cparms.nitems = 1; + cparms.size = sizeof(struct tf_shadow_ident_db); + cparms.alignment = 0; + rc = tfp_calloc(&cparms); + if (rc) + return rc; + shadow_db = (void *)cparms.mem_va; + + /* Build the DB within shadow DB */ + cparms.nitems = parms->num_elements; + cparms.size = sizeof(struct tf_shadow_ident_element); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + shadow_db->db = (struct tf_shadow_ident_element *)cparms.mem_va; + shadow_db->num_entries = parms->num_elements; + + db = shadow_db->db; + for (i = 0; i < parms->num_elements; i++) { + /* If the element didn't request an allocation no need + * to create a pool nor verify if we got a reservation. + */ + if (parms->cfg->alloc_cnt[i] == 0) + continue; + + /* Create array */ + cparms.nitems = parms->cfg->alloc_cnt[i]; + cparms.size = sizeof(uint32_t); + rc = tfp_calloc(&cparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Array alloc failed, type:%d\n", + tf_dir_2_str(parms->dir), + i); + goto fail; + } + db[i].ref_count = (uint32_t *)cparms.mem_va; + } + + *parms->tf_shadow_ident_db = (void *)shadow_db; + + return 0; +fail: + tfp_free((void *)db->ref_count); + tfp_free((void *)db); + tfp_free((void *)shadow_db); + parms->tf_shadow_ident_db = NULL; + + return -EINVAL; +} + +int +tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms) +{ + int i; + struct tf_shadow_ident_db *shadow_db; + + TF_CHECK_PARMS1(parms); + + shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; + for (i = 0; i < shadow_db->num_entries; i++) + tfp_free((void *)shadow_db->db[i].ref_count); + + tfp_free((void *)shadow_db->db); + tfp_free((void *)parms->tf_shadow_ident_db); + + return 0; +} + +int +tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms) +{ + struct tf_shadow_ident_db *shadow_db; + uint32_t ref_cnt = 0; + + TF_CHECK_PARMS1(parms); + + shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; + ref_cnt = shadow_db->db[parms->type].ref_count[parms->search_id]; + if (ref_cnt > 0) { + *parms->hit = 1; + *parms->ref_cnt = ++ref_cnt; + shadow_db->db[parms->type].ref_count[parms->search_id] = + ref_cnt; + } else { + *parms->hit = 0; + *parms->ref_cnt = 0; + } + + + return 0; +} + +#define ID_REF_CNT_MAX 0xffffffff +int +tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms) +{ + struct tf_shadow_ident_db *shadow_db; + + TF_CHECK_PARMS1(parms); + + shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; + + /* In case of overflow, ref count keeps the max value */ + if (shadow_db->db[parms->type].ref_count[parms->id] < ID_REF_CNT_MAX) + shadow_db->db[parms->type].ref_count[parms->id]++; + else + TFP_DRV_LOG(ERR, + "Identifier %d in type %d reaches the max ref_cnt\n", + parms->type, + parms->id); + + parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; + + return 0; +} + +int +tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms) +{ + struct tf_shadow_ident_db *shadow_db; + uint32_t ref_cnt = 0; + + TF_CHECK_PARMS1(parms); + + shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; + ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; + if (ref_cnt > 0) + shadow_db->db[parms->type].ref_count[parms->id]--; + else + return -EINVAL; + + *parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; + + return 0; +} diff --git a/drivers/net/bnxt/tf_core/tf_shadow_identifier.h b/drivers/net/bnxt/tf_core/tf_shadow_identifier.h new file mode 100644 index 0000000..dd633af --- /dev/null +++ b/drivers/net/bnxt/tf_core/tf_shadow_identifier.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019-2020 Broadcom + * All rights reserved. + */ + +#ifndef _TF_SHADOW_IDENTIFIER_H_ +#define _TF_SHADOW_IDENTIFIER_H_ + +#include "tf_core.h" + +struct tf; + +/** + * The Shadow Identifier module provides shadow DB handling for identifier based + * TF types. A shadow DB provides the capability that allows for reuse + * of TF resources. + * + * A Shadow identifier DB is intended to be used by the Identifier Type module + * only. + */ + +/** + * Shadow DB configuration information for a single identifier type. + * + * It is used in an array of identifier types. The array must be ordered + * by the TF type is represents. + */ +struct tf_shadow_ident_cfg_parms { + /** + * TF Identifier type + */ + enum tf_identifier_type type; + + /** + * Number of entries the Shadow DB needs to hold + */ + int num_entries; + + /** + * Resource allocation count array. This array content + * originates from the tf_session_resources that is passed in + * on session open. + * Array size is num_elements. + */ + uint16_t *alloc_cnt; +}; + +/** + * Shadow identifier DB creation parameters + */ +struct tf_shadow_ident_create_db_parms { + /** + * [in] Receive or transmit direction. + */ + enum tf_dir dir; + /** + * [in] Configuration information for the shadow db + */ + struct tf_shadow_ident_cfg_parms *cfg; + /** + * [in] Number of elements in the parms structure + */ + uint16_t num_elements; + /** + * [out] Shadow identifier DB handle + */ + void **tf_shadow_ident_db; +}; + +/** + * Shadow identifier DB free parameters + */ +struct tf_shadow_ident_free_db_parms { + /** + * Shadow identifier DB handle + */ + void *tf_shadow_ident_db; +}; + +/** + * Shadow identifier search parameters + */ +struct tf_shadow_ident_search_parms { + /** + * [in] Shadow identifier DB handle + */ + void *tf_shadow_ident_db; + /** + * [in] Identifier type + */ + enum tf_identifier_type type; + /** + * [in] id to search + */ + uint16_t search_id; + /** + * [out] Index of the found element returned if hit + */ + bool *hit; + /** + * [out] Reference count incremented if hit + */ + uint32_t *ref_cnt; +}; + +/** + * Shadow identifier insert parameters + */ +struct tf_shadow_ident_insert_parms { + /** + * [in] Shadow identifier DB handle + */ + void *tf_shadow_ident_db; + /** + * [in] Tbl type + */ + enum tf_identifier_type type; + /** + * [in] Entry to update + */ + uint16_t id; + /** + * [out] Reference count after insert + */ + uint32_t ref_cnt; +}; + +/** + * Shadow identifier remove parameters + */ +struct tf_shadow_ident_remove_parms { + /** + * [in] Shadow identifier DB handle + */ + void *tf_shadow_ident_db; + /** + * [in] Tbl type + */ + enum tf_identifier_type type; + /** + * [in] Entry to update + */ + uint16_t id; + /** + * [out] Reference count after removal + */ + uint32_t *ref_cnt; +}; + +/** + * @page shadow_ident Shadow identifier DB + * + * @ref tf_shadow_ident_create_db + * + * @ref tf_shadow_ident_free_db + * + * @reg tf_shadow_ident_search + * + * @reg tf_shadow_ident_insert + * + * @reg tf_shadow_ident_remove + */ + +/** + * Creates and fills a Shadow identifier DB. The DB is indexed per the + * parms structure. + * + * [in] parms + * Pointer to create db parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms); + +/** + * Closes the Shadow identifier DB and frees all allocated + * resources per the associated database. + * + * [in] parms + * Pointer to the free DB parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms); + +/** + * Search Shadow identifier db for matching result + * + * [in] parms + * Pointer to the search parameters + * + * Returns + * - (0) if successful, element was found. + * - (-EINVAL) on failure. + */ +int tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms); + +/** + * Inserts an element into the Shadow identifier DB. Ref_count after insert + * will be incremented. + * + * [in] parms + * Pointer to insert parameters + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms); + +/** + * Removes an element from the Shadow identifier DB. Will fail if the + * elements ref_count is 0. Ref_count after removal will be + * decremented. + * + * [in] parms + * Pointer to remove parameter + * + * Returns + * - (0) if successful. + * - (-EINVAL) on failure. + */ +int tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms); + +#endif /* _TF_SHADOW_IDENTIFIER_H_ */