get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/73878/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 73878,
    "url": "http://patchwork.dpdk.org/api/patches/73878/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20200713062828.19626-3-somnath.kotur@broadcom.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200713062828.19626-3-somnath.kotur@broadcom.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200713062828.19626-3-somnath.kotur@broadcom.com",
    "date": "2020-07-13T06:28:20",
    "name": "[02/10] net/bnxt: implement TF Identifier search",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "bbbfdf4d94ad92e0f7419e11559657a52116433c",
    "submitter": {
        "id": 908,
        "url": "http://patchwork.dpdk.org/api/people/908/?format=api",
        "name": "Somnath Kotur",
        "email": "somnath.kotur@broadcom.com"
    },
    "delegate": {
        "id": 1766,
        "url": "http://patchwork.dpdk.org/api/users/1766/?format=api",
        "username": "ajitkhaparde",
        "first_name": "Ajit",
        "last_name": "Khaparde",
        "email": "ajit.khaparde@broadcom.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20200713062828.19626-3-somnath.kotur@broadcom.com/mbox/",
    "series": [
        {
            "id": 10978,
            "url": "http://patchwork.dpdk.org/api/series/10978/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=10978",
            "date": "2020-07-13T06:28:18",
            "name": "bnxt patches",
            "version": 2,
            "mbox": "http://patchwork.dpdk.org/series/10978/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/73878/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/73878/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 06345A0540;\n\tMon, 13 Jul 2020 08:33:55 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id C59C51D182;\n\tMon, 13 Jul 2020 08:33:42 +0200 (CEST)",
            "from relay.smtp.broadcom.com (unknown [192.19.211.62])\n by dpdk.org (Postfix) with ESMTP id 357CB1C2FA\n for <dev@dpdk.org>; Mon, 13 Jul 2020 08:33:38 +0200 (CEST)",
            "from dhcp-10-123-153-55.dhcp.broadcom.net\n (dhcp-10-123-153-55.dhcp.broadcom.net [10.123.153.55])\n by relay.smtp.broadcom.com (Postfix) with ESMTP id 60F9E29C651;\n Sun, 12 Jul 2020 23:33:37 -0700 (PDT)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.10.3 relay.smtp.broadcom.com 60F9E29C651",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com;\n s=dkimrelay; t=1594622017;\n bh=oz01cxplkzFTnXIdsgKMfs0Ei3gjpP2HZjHTRzrhq1Q=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=ERVE5mL7PPopx+5qxNcPtCl4qXHeGY0XHw+DklEDKDcnN5MArfiU6yq6oYEx5O5ds\n qdSXXBR7wCU3WzV6RmgjsexaST01qQzMPiTihNlV57uYV9rgyJ8QnsPyv+J/Tb7FHN\n duQUiBIe4oEtLaWn+y8rKHYDfwB+I2Yi9Z17ddb4=",
        "From": "Somnath Kotur <somnath.kotur@broadcom.com>",
        "To": "dev@dpdk.org",
        "Cc": "ferruh.yigit@intel.com",
        "Date": "Mon, 13 Jul 2020 11:58:20 +0530",
        "Message-Id": "<20200713062828.19626-3-somnath.kotur@broadcom.com>",
        "X-Mailer": "git-send-email 2.10.1.613.g2cc2e70",
        "In-Reply-To": "<20200713062828.19626-1-somnath.kotur@broadcom.com>",
        "References": "<20200713062828.19626-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 <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Jay Ding <jay.ding@broadcom.com>\n\nImplement shadow copy DB to hold reference count for\neach ID in each identifier type. Implement identifier\nsearch functionality.\n\nSigned-off-by: Jay Ding <jay.ding@broadcom.com>\nReviewed-by: Randy Schacher <stuart.schacher@broadcom.com>\nSigned-off-by: Somnath Kotur <somnath.kotur@broadcom.com>\n---\n drivers/net/bnxt/meson.build                    |   3 +-\n drivers/net/bnxt/tf_core/Makefile               |   1 +\n drivers/net/bnxt/tf_core/tf_core.c              |  61 +++++++\n drivers/net/bnxt/tf_core/tf_core.h              |  70 +++++++-\n drivers/net/bnxt/tf_core/tf_device.h            |  20 +++\n drivers/net/bnxt/tf_core/tf_device_p4.c         |   2 +\n drivers/net/bnxt/tf_core/tf_identifier.c        | 148 +++++++++++++++\n drivers/net/bnxt/tf_core/tf_identifier.h        |  47 +++++\n drivers/net/bnxt/tf_core/tf_rm.c                |   2 +\n drivers/net/bnxt/tf_core/tf_rm.h                |   8 +\n drivers/net/bnxt/tf_core/tf_shadow_identifier.c | 190 ++++++++++++++++++++\n drivers/net/bnxt/tf_core/tf_shadow_identifier.h | 229 ++++++++++++++++++++++++\n 12 files changed, 777 insertions(+), 4 deletions(-)\n create mode 100644 drivers/net/bnxt/tf_core/tf_shadow_identifier.c\n create mode 100644 drivers/net/bnxt/tf_core/tf_shadow_identifier.h",
    "diff": "diff --git a/drivers/net/bnxt/meson.build b/drivers/net/bnxt/meson.build\nindex 0b93c31..8529b33 100644\n--- a/drivers/net/bnxt/meson.build\n+++ b/drivers/net/bnxt/meson.build\n@@ -46,7 +46,7 @@ sources = files('bnxt_cpr.c',\n \t'tf_core/ll.c',\n \t'tf_core/tf_global_cfg.c',\n \t'tf_core/tf_em_host.c',\n-\t'tf_ulp/ulp_fc_mgr.c',\n+\t'tf_core/tf_shadow_identifier.c',\n \n \t'hcapi/hcapi_cfa_p4.c',\n \n@@ -63,6 +63,7 @@ sources = files('bnxt_cpr.c',\n \t'tf_ulp/bnxt_ulp_flow.c',\n \t'tf_ulp/ulp_port_db.c',\n \t'tf_ulp/ulp_def_rules.c',\n+\t'tf_ulp/ulp_fc_mgr.c',\n \n \t'rte_pmd_bnxt.c')\n \ndiff --git a/drivers/net/bnxt/tf_core/Makefile b/drivers/net/bnxt/tf_core/Makefile\nindex 8064714..9c2735d 100644\n--- a/drivers/net/bnxt/tf_core/Makefile\n+++ b/drivers/net/bnxt/tf_core/Makefile\n@@ -31,3 +31,4 @@ SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_tcam.c\n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_util.c\n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_if_tbl.c\n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_global_cfg.c\n+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_shadow_identifier.c\ndiff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c\nindex a404cb8..97e7952 100644\n--- a/drivers/net/bnxt/tf_core/tf_core.c\n+++ b/drivers/net/bnxt/tf_core/tf_core.c\n@@ -534,6 +534,7 @@ tf_free_identifier(struct tf *tfp,\n \tfparms.dir = parms->dir;\n \tfparms.type = parms->ident_type;\n \tfparms.id = parms->id;\n+\tfparms.ref_cnt = &parms->ref_cnt;\n \trc = dev->ops->tf_dev_free_ident(tfp, &fparms);\n \tif (rc) {\n \t\tTFP_DRV_LOG(ERR,\n@@ -547,6 +548,66 @@ tf_free_identifier(struct tf *tfp,\n }\n \n int\n+tf_search_identifier(struct tf *tfp,\n+\t\t     struct tf_search_identifier_parms *parms)\n+{\n+\tint rc;\n+\tstruct tf_session *tfs;\n+\tstruct tf_dev_info *dev;\n+\tstruct tf_ident_search_parms sparms;\n+\n+\tTF_CHECK_PARMS2(tfp, parms);\n+\n+\t/* Can't do static initialization due to UT enum check */\n+\tmemset(&sparms, 0, sizeof(struct tf_ident_search_parms));\n+\n+\t/* Retrieve the session information */\n+\trc = tf_session_get_session(tfp, &tfs);\n+\tif (rc) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Failed to lookup session, rc:%s\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    strerror(-rc));\n+\t\treturn rc;\n+\t}\n+\n+\t/* Retrieve the device information */\n+\trc = tf_session_get_device(tfs, &dev);\n+\tif (rc) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Failed to lookup device, rc:%s\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    strerror(-rc));\n+\t\treturn rc;\n+\t}\n+\n+\tif (dev->ops->tf_dev_search_ident == NULL) {\n+\t\trc = -EOPNOTSUPP;\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Operation not supported, rc:%s\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    strerror(-rc));\n+\t\treturn rc;\n+\t}\n+\n+\tsparms.dir = parms->dir;\n+\tsparms.type = parms->ident_type;\n+\tsparms.search_id = parms->search_id;\n+\tsparms.hit = &parms->hit;\n+\tsparms.ref_cnt = &parms->ref_cnt;\n+\trc = dev->ops->tf_dev_search_ident(tfp, &sparms);\n+\tif (rc) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Identifier search failed, rc:%s\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    strerror(-rc));\n+\t\treturn rc;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n tf_alloc_tcam_entry(struct tf *tfp,\n \t\t    struct tf_alloc_tcam_entry_parms *parms)\n {\ndiff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h\nindex 9e80426..9a5e816 100644\n--- a/drivers/net/bnxt/tf_core/tf_core.h\n+++ b/drivers/net/bnxt/tf_core/tf_core.h\n@@ -695,9 +695,9 @@ struct tf_alloc_identifier_parms {\n \t */\n \tenum tf_identifier_type ident_type;\n \t/**\n-\t * [out] Identifier allocated\n+\t * [out] Allocated identifier\n \t */\n-\tuint16_t id;\n+\tuint32_t id;\n };\n \n /**\n@@ -715,7 +715,38 @@ struct tf_free_identifier_parms {\n \t/**\n \t * [in] ID to free\n \t */\n-\tuint16_t id;\n+\tuint32_t id;\n+\t/**\n+\t * (experimental)\n+\t * [out] Current refcnt after free\n+\t */\n+\tuint32_t ref_cnt;\n+};\n+\n+/**\n+ * tf_search_identifier parameter definition (experimental)\n+ */\n+struct tf_search_identifier_parms {\n+\t/**\n+\t * [in]\t receive or transmit direction\n+\t */\n+\tenum tf_dir dir;\n+\t/**\n+\t * [in] Identifier type\n+\t */\n+\tenum tf_identifier_type ident_type;\n+\t/**\n+\t * [in] Identifier data to search for\n+\t */\n+\tuint32_t search_id;\n+\t/**\n+\t * [out] Set if matching identifier found\n+\t */\n+\tbool hit;\n+\t/**\n+\t * [out] Current ref count after allocation\n+\t */\n+\tuint32_t ref_cnt;\n };\n \n /**\n@@ -724,6 +755,9 @@ struct tf_free_identifier_parms {\n  * TruFlow core will allocate a free id from the per identifier resource type\n  * pool reserved for the session during tf_open().  No firmware is involved.\n  *\n+ * If shadow copy is enabled, the internal ref_cnt is set to 1 in the\n+ * shadow table for a newly allocated resource.\n+ *\n  * Returns success or failure code.\n  */\n int tf_alloc_identifier(struct tf *tfp,\n@@ -736,12 +770,42 @@ int tf_alloc_identifier(struct tf *tfp,\n  * reserved for the session.  No firmware is involved.  During tf_close, the\n  * complete pool is returned to the firmware.\n  *\n+ * additional operation (experimental)\n+ * Decrement reference count.  Only release resource once refcnt goes to 0 if\n+ * shadow copy is enabled.\n+ *\n  * Returns success or failure code.\n  */\n int tf_free_identifier(struct tf *tfp,\n \t\t       struct tf_free_identifier_parms *parms);\n \n /**\n+ * Search identifier resource (experimental)\n+ *\n+ * If the shadow copy is enabled search_id is used to search for a matching\n+ * entry in the shadow table.  The shadow table consists of an array of\n+ * reference counts indexed by identifier.  If a matching entry is found hit is\n+ * set to TRUE, refcnt is increased by 1 and returned.  Otherwise, hit is\n+ * set to false and refcnt is set to 0.\n+ *\n+ * TODO: we may need a per table internal shadow copy enable flag to stage\n+ * the shadow table implementation.  We do not need the shadow table for other\n+ * tables at this time so we may only want to enable the identifier shadow.\n+ *\n+ * TODO: remove this pseudocode below added to show that if search fails\n+ * we shouldn't allocate a new entry but return.\n+ *\n+ * identifier alloc (search_en=1)\n+ * if (ident is allocated and ref_cnt >=1)\n+ *      return ident - hit is set, incr refcnt\n+ * else (not found)\n+ *      return\n+ *\n+ */\n+int tf_search_identifier(struct tf *tfp,\n+\t\t\t struct tf_search_identifier_parms *parms);\n+\n+/**\n  * @page dram_table DRAM Table Scope Interface\n  *\n  * @ref tf_alloc_tbl_scope\ndiff --git a/drivers/net/bnxt/tf_core/tf_device.h b/drivers/net/bnxt/tf_core/tf_device.h\nindex 0bc7090..fce7f25 100644\n--- a/drivers/net/bnxt/tf_core/tf_device.h\n+++ b/drivers/net/bnxt/tf_core/tf_device.h\n@@ -199,6 +199,26 @@ struct tf_dev_ops {\n \t\t\t\t struct tf_ident_free_parms *parms);\n \n \t/**\n+\t * Search of an identifier element.\n+\t *\n+\t * This API search the specified identifier element from a\n+\t * device specific identifier shadow DB. The allocated element\n+\t * is returned.\n+\t *\n+\t * [in] tfp\n+\t *   Pointer to TF handle\n+\t *\n+\t * [in] parms\n+\t *   Pointer to identifier search parameters\n+\t *\n+\t * Returns\n+\t *   - (0) if successful.\n+\t *   - (-EINVAL) on failure.\n+\t */\n+\tint (*tf_dev_search_ident)(struct tf *tfp,\n+\t\t\t\t   struct tf_ident_search_parms *parms);\n+\n+\t/**\n \t * Allocation of a table type element.\n \t *\n \t * This API allocates the specified table type element from a\ndiff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c\nindex dfe626c..f38c38e 100644\n--- a/drivers/net/bnxt/tf_core/tf_device_p4.c\n+++ b/drivers/net/bnxt/tf_core/tf_device_p4.c\n@@ -86,6 +86,7 @@ const struct tf_dev_ops tf_dev_ops_p4_init = {\n \t.tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info,\n \t.tf_dev_alloc_ident = NULL,\n \t.tf_dev_free_ident = NULL,\n+\t.tf_dev_search_ident = NULL,\n \t.tf_dev_alloc_ext_tbl = NULL,\n \t.tf_dev_alloc_tbl = NULL,\n \t.tf_dev_free_ext_tbl = NULL,\n@@ -120,6 +121,7 @@ const struct tf_dev_ops tf_dev_ops_p4 = {\n \t.tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info,\n \t.tf_dev_alloc_ident = tf_ident_alloc,\n \t.tf_dev_free_ident = tf_ident_free,\n+\t.tf_dev_search_ident = tf_ident_search,\n \t.tf_dev_alloc_tbl = tf_tbl_alloc,\n \t.tf_dev_alloc_ext_tbl = tf_tbl_ext_alloc,\n \t.tf_dev_free_tbl = tf_tbl_free,\ndiff --git a/drivers/net/bnxt/tf_core/tf_identifier.c b/drivers/net/bnxt/tf_core/tf_identifier.c\nindex 90aeaa4..273d629 100644\n--- a/drivers/net/bnxt/tf_core/tf_identifier.c\n+++ b/drivers/net/bnxt/tf_core/tf_identifier.c\n@@ -6,6 +6,7 @@\n #include <rte_common.h>\n \n #include \"tf_identifier.h\"\n+#include \"tf_shadow_identifier.h\"\n #include \"tf_common.h\"\n #include \"tf_rm.h\"\n #include \"tf_util.h\"\n@@ -23,6 +24,16 @@ static void *ident_db[TF_DIR_MAX];\n  */\n static uint8_t init;\n \n+/**\n+ * Identifier shadow DBs.\n+ */\n+static void *ident_shadow_db[TF_DIR_MAX];\n+\n+/**\n+ * Shadow DB Init flag, set on bind and cleared on unbind\n+ */\n+static uint8_t shadow_init;\n+\n int\n tf_ident_bind(struct tf *tfp,\n \t      struct tf_ident_cfg_parms *parms)\n@@ -30,6 +41,8 @@ tf_ident_bind(struct tf *tfp,\n \tint rc;\n \tint i;\n \tstruct tf_rm_create_db_parms db_cfg = { 0 };\n+\tstruct tf_shadow_ident_cfg_parms shadow_cfg = { 0 };\n+\tstruct tf_shadow_ident_create_db_parms shadow_cdb = { 0 };\n \n \tTF_CHECK_PARMS2(tfp, parms);\n \n@@ -55,6 +68,23 @@ tf_ident_bind(struct tf *tfp,\n \n \t\t\treturn rc;\n \t\t}\n+\n+\t\tif (parms->shadow_copy) {\n+\t\t\tshadow_cfg.alloc_cnt =\n+\t\t\t\tparms->resources->ident_cnt[i].cnt;\n+\t\t\tshadow_cdb.num_elements = parms->num_elements;\n+\t\t\tshadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i];\n+\t\t\tshadow_cdb.cfg = &shadow_cfg;\n+\t\t\trc = tf_shadow_ident_create_db(&shadow_cdb);\n+\t\t\tif (rc) {\n+\t\t\t\tTFP_DRV_LOG(ERR,\n+\t\t\t\t    \"%s: Ident shadow DB creation failed\\n\",\n+\t\t\t\t    tf_dir_2_str(i));\n+\n+\t\t\t\treturn rc;\n+\t\t\t}\n+\t\t\tshadow_init = 1;\n+\t\t}\n \t}\n \n \tinit = 1;\n@@ -71,6 +101,7 @@ tf_ident_unbind(struct tf *tfp)\n \tint rc = 0;\n \tint i;\n \tstruct tf_rm_free_db_parms fparms = { 0 };\n+\tstruct tf_shadow_ident_free_db_parms sparms = { 0 };\n \n \tTF_CHECK_PARMS1(tfp);\n \n@@ -89,10 +120,22 @@ tf_ident_unbind(struct tf *tfp)\n \t\t\tTFP_DRV_LOG(ERR,\n \t\t\t\t    \"rm free failed on unbind\\n\");\n \t\t}\n+\t\tif (shadow_init) {\n+\t\t\tsparms.tf_shadow_ident_db = ident_shadow_db[i];\n+\t\t\trc = tf_shadow_ident_free_db(&sparms);\n+\t\t\tif (rc) {\n+\t\t\t\t/* TODO: If there are failures on unbind we\n+\t\t\t\t * really just have to try until all DBs are\n+\t\t\t\t * attempted to be cleared.\n+\t\t\t\t */\n+\t\t\t}\n+\t\t\tident_shadow_db[i] = NULL;\n+\t\t}\n \t\tident_db[i] = NULL;\n \t}\n \n \tinit = 0;\n+\tshadow_init = 0;\n \n \treturn 0;\n }\n@@ -103,7 +146,9 @@ tf_ident_alloc(struct tf *tfp __rte_unused,\n {\n \tint rc;\n \tuint32_t id;\n+\tuint32_t base_id;\n \tstruct tf_rm_allocate_parms aparms = { 0 };\n+\tstruct tf_shadow_ident_insert_parms iparms = { 0 };\n \n \tTF_CHECK_PARMS2(tfp, parms);\n \n@@ -118,6 +163,7 @@ tf_ident_alloc(struct tf *tfp __rte_unused,\n \taparms.rm_db = ident_db[parms->dir];\n \taparms.db_index = parms->type;\n \taparms.index = &id;\n+\taparms.base_index = &base_id;\n \trc = tf_rm_allocate(&aparms);\n \tif (rc) {\n \t\tTFP_DRV_LOG(ERR,\n@@ -127,6 +173,21 @@ tf_ident_alloc(struct tf *tfp __rte_unused,\n \t\treturn rc;\n \t}\n \n+\tif (shadow_init) {\n+\t\tiparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];\n+\t\tiparms.type = parms->type;\n+\t\tiparms.id = base_id;\n+\n+\t\trc = tf_shadow_ident_insert(&iparms);\n+\t\tif (rc) {\n+\t\t\tTFP_DRV_LOG(ERR,\n+\t\t\t\t    \"%s: Failed insert shadow DB, type:%d\\n\",\n+\t\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t\t    parms->type);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n \t*parms->id = id;\n \n \treturn 0;\n@@ -139,7 +200,9 @@ tf_ident_free(struct tf *tfp __rte_unused,\n \tint rc;\n \tstruct tf_rm_is_allocated_parms aparms = { 0 };\n \tstruct tf_rm_free_parms fparms = { 0 };\n+\tstruct tf_shadow_ident_remove_parms rparms = { 0 };\n \tint allocated = 0;\n+\tuint32_t base_id;\n \n \tTF_CHECK_PARMS2(tfp, parms);\n \n@@ -154,6 +217,7 @@ tf_ident_free(struct tf *tfp __rte_unused,\n \taparms.rm_db = ident_db[parms->dir];\n \taparms.db_index = parms->type;\n \taparms.index = parms->id;\n+\taparms.base_index = &base_id;\n \taparms.allocated = &allocated;\n \trc = tf_rm_is_allocated(&aparms);\n \tif (rc)\n@@ -168,6 +232,27 @@ tf_ident_free(struct tf *tfp __rte_unused,\n \t\treturn -EINVAL;\n \t}\n \n+\tif (shadow_init) {\n+\t\trparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];\n+\t\trparms.type = parms->type;\n+\t\trparms.id = base_id;\n+\t\trparms.ref_cnt = parms->ref_cnt;\n+\n+\t\trc = tf_shadow_ident_remove(&rparms);\n+\t\tif (rc) {\n+\t\t\tTFP_DRV_LOG(ERR,\n+\t\t\t\t    \"%s: ref_cnt was 0 in shadow DB,\"\n+\t\t\t\t    \" type:%d, index:%d\\n\",\n+\t\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t\t    parms->type,\n+\t\t\t\t    parms->id);\n+\t\t\treturn rc;\n+\t\t}\n+\n+\t\tif (*rparms.ref_cnt > 0)\n+\t\t\treturn 0;\n+\t}\n+\n \t/* Free requested element */\n \tfparms.rm_db = ident_db[parms->dir];\n \tfparms.db_index = parms->type;\n@@ -184,3 +269,66 @@ tf_ident_free(struct tf *tfp __rte_unused,\n \n \treturn 0;\n }\n+\n+int\n+tf_ident_search(struct tf *tfp __rte_unused,\n+\t\tstruct tf_ident_search_parms *parms)\n+{\n+\tint rc;\n+\tstruct tf_rm_is_allocated_parms aparms = { 0 };\n+\tstruct tf_shadow_ident_search_parms sparms = { 0 };\n+\tint allocated = 0;\n+\tuint32_t base_id;\n+\n+\tTF_CHECK_PARMS2(tfp, parms);\n+\n+\tif (!init) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: No Identifier DBs created\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir));\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!shadow_init) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Identifier Shadow copy is not enabled\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir));\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Check if element is in use */\n+\taparms.rm_db = ident_db[parms->dir];\n+\taparms.db_index = parms->type;\n+\taparms.index = parms->search_id;\n+\taparms.base_index = &base_id;\n+\taparms.allocated = &allocated;\n+\trc = tf_rm_is_allocated(&aparms);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tif (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Entry not allocated, type:%d, index:%d\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    parms->type,\n+\t\t\t    parms->search_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsparms.tf_shadow_ident_db = ident_shadow_db[parms->dir];\n+\tsparms.type = parms->type;\n+\tsparms.search_id = base_id;\n+\tsparms.hit = parms->hit;\n+\tsparms.ref_cnt = parms->ref_cnt;\n+\n+\trc = tf_shadow_ident_search(&sparms);\n+\tif (rc) {\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"%s: Failed search shadow DB, type:%d\\n\",\n+\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t    parms->type);\n+\t\treturn rc;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/bnxt/tf_core/tf_identifier.h b/drivers/net/bnxt/tf_core/tf_identifier.h\nindex 6e36c52..6d9fa08 100644\n--- a/drivers/net/bnxt/tf_core/tf_identifier.h\n+++ b/drivers/net/bnxt/tf_core/tf_identifier.h\n@@ -66,6 +66,37 @@ struct tf_ident_free_parms {\n \t * [in] ID to free\n \t */\n \tuint16_t id;\n+\t/**\n+\t * (experimental)\n+\t * [out] Current refcnt after free\n+\t */\n+\tuint32_t *ref_cnt;\n+};\n+\n+/**\n+ * Identifier search parameter definition\n+ */\n+struct tf_ident_search_parms {\n+\t/**\n+\t * [in]  receive or transmit direction\n+\t */\n+\tenum tf_dir dir;\n+\t/**\n+\t * [in] Identifier type\n+\t */\n+\tenum tf_identifier_type type;\n+\t/**\n+\t * [in] Identifier data to search for\n+\t */\n+\tuint16_t search_id;\n+\t/**\n+\t * [out] Set if matching identifier found\n+\t */\n+\tbool *hit;\n+\t/**\n+\t * [out] Current ref count after allocation\n+\t */\n+\tuint32_t *ref_cnt;\n };\n \n /**\n@@ -144,4 +175,20 @@ int tf_ident_alloc(struct tf *tfp,\n int tf_ident_free(struct tf *tfp,\n \t\t  struct tf_ident_free_parms *parms);\n \n+/**\n+ * Search a single identifier type.\n+ *\n+ * [in] tfp\n+ *   Pointer to TF handle, used for HCAPI communication\n+ *\n+ * [in] parms\n+ *   Pointer to parameters\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_ident_search(struct tf *tfp,\n+\t\t    struct tf_ident_search_parms *parms);\n+\n #endif /* _TF_IDENTIFIER_H_ */\ndiff --git a/drivers/net/bnxt/tf_core/tf_rm.c b/drivers/net/bnxt/tf_core/tf_rm.c\nindex fdb87ec..78bc231 100644\n--- a/drivers/net/bnxt/tf_core/tf_rm.c\n+++ b/drivers/net/bnxt/tf_core/tf_rm.c\n@@ -755,6 +755,7 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms)\n \t}\n \n \t*parms->index = index;\n+\t*parms->base_index = id;\n \n \treturn rc;\n }\n@@ -841,6 +842,7 @@ tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)\n \tif (rc)\n \t\treturn rc;\n \n+\t*parms->base_index = adj_index;\n \t*parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,\n \t\t\t\t     adj_index);\n \ndiff --git a/drivers/net/bnxt/tf_core/tf_rm.h b/drivers/net/bnxt/tf_core/tf_rm.h\nindex 775f0aa..971120a 100644\n--- a/drivers/net/bnxt/tf_core/tf_rm.h\n+++ b/drivers/net/bnxt/tf_core/tf_rm.h\n@@ -204,6 +204,10 @@ struct tf_rm_allocate_parms {\n \t *              available index)\n \t */\n \tuint32_t priority;\n+\t/**\n+\t * [in] Pointer to the allocated index before adjusted.\n+\t */\n+\tuint32_t *base_index;\n };\n \n /**\n@@ -246,6 +250,10 @@ struct tf_rm_is_allocated_parms {\n \t * [in] Pointer to flag that indicates the state of the query\n \t */\n \tint *allocated;\n+\t/**\n+\t * [in] Pointer to the allocated index before adjusted.\n+\t */\n+\tuint32_t *base_index;\n };\n \n /**\ndiff --git a/drivers/net/bnxt/tf_core/tf_shadow_identifier.c b/drivers/net/bnxt/tf_core/tf_shadow_identifier.c\nnew file mode 100644\nindex 0000000..390d22f\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_core/tf_shadow_identifier.c\n@@ -0,0 +1,190 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#include <rte_common.h>\n+\n+#include \"tf_shadow_identifier.h\"\n+#include \"tf_common.h\"\n+#include \"tf_util.h\"\n+#include \"tfp.h\"\n+\n+/**\n+ * Shadow identifier DB element\n+ */\n+struct tf_shadow_ident_element {\n+\t/**\n+\t * Identifier\n+\t */\n+\tuint32_t *id;\n+\n+\t/**\n+\t * Reference count, array of number of identifier type entries\n+\t */\n+\tuint32_t *ref_count;\n+};\n+\n+/**\n+ * Shadow identifier DB definition\n+ */\n+struct tf_shadow_ident_db {\n+\t/**\n+\t * Number of elements in the DB\n+\t */\n+\tuint16_t num_entries;\n+\n+\t/**\n+\t * The DB consists of an array of elements\n+\t */\n+\tstruct tf_shadow_ident_element *db;\n+};\n+\n+int\n+tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms)\n+{\n+\tint rc;\n+\tint i;\n+\tstruct tfp_calloc_parms cparms;\n+\tstruct tf_shadow_ident_db *shadow_db;\n+\tstruct tf_shadow_ident_element *db;\n+\n+\tTF_CHECK_PARMS1(parms);\n+\n+\t/* Build the shadow DB per the request */\n+\tcparms.nitems = 1;\n+\tcparms.size = sizeof(struct tf_shadow_ident_db);\n+\tcparms.alignment = 0;\n+\trc = tfp_calloc(&cparms);\n+\tif (rc)\n+\t\treturn rc;\n+\tshadow_db = (void *)cparms.mem_va;\n+\n+\t/* Build the DB within shadow DB */\n+\tcparms.nitems = parms->num_elements;\n+\tcparms.size = sizeof(struct tf_shadow_ident_element);\n+\trc = tfp_calloc(&cparms);\n+\tif (rc)\n+\t\treturn rc;\n+\tshadow_db->db = (struct tf_shadow_ident_element *)cparms.mem_va;\n+\tshadow_db->num_entries = parms->num_elements;\n+\n+\tdb = shadow_db->db;\n+\tfor (i = 0; i < parms->num_elements; i++) {\n+\t\t/* If the element didn't request an allocation no need\n+\t\t * to create a pool nor verify if we got a reservation.\n+\t\t */\n+\t\tif (parms->cfg->alloc_cnt[i] == 0)\n+\t\t\tcontinue;\n+\n+\t\t/* Create array */\n+\t\tcparms.nitems = parms->cfg->alloc_cnt[i];\n+\t\tcparms.size = sizeof(uint32_t);\n+\t\trc = tfp_calloc(&cparms);\n+\t\tif (rc) {\n+\t\t\tTFP_DRV_LOG(ERR,\n+\t\t\t\t    \"%s: Array alloc failed, type:%d\\n\",\n+\t\t\t\t    tf_dir_2_str(parms->dir),\n+\t\t\t\t    i);\n+\t\t\tgoto fail;\n+\t\t}\n+\t\tdb[i].ref_count = (uint32_t *)cparms.mem_va;\n+\t}\n+\n+\t*parms->tf_shadow_ident_db = (void *)shadow_db;\n+\n+\treturn 0;\n+fail:\n+\ttfp_free((void *)db->ref_count);\n+\ttfp_free((void *)db);\n+\ttfp_free((void *)shadow_db);\n+\tparms->tf_shadow_ident_db = NULL;\n+\n+\treturn -EINVAL;\n+}\n+\n+int\n+tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms)\n+{\n+\tint i;\n+\tstruct tf_shadow_ident_db *shadow_db;\n+\n+\tTF_CHECK_PARMS1(parms);\n+\n+\tshadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;\n+\tfor (i = 0; i < shadow_db->num_entries; i++)\n+\t\ttfp_free((void *)shadow_db->db[i].ref_count);\n+\n+\ttfp_free((void *)shadow_db->db);\n+\ttfp_free((void *)parms->tf_shadow_ident_db);\n+\n+\treturn 0;\n+}\n+\n+int\n+tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms)\n+{\n+\tstruct tf_shadow_ident_db *shadow_db;\n+\tuint32_t ref_cnt = 0;\n+\n+\tTF_CHECK_PARMS1(parms);\n+\n+\tshadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;\n+\tref_cnt = shadow_db->db[parms->type].ref_count[parms->search_id];\n+\tif (ref_cnt > 0) {\n+\t\t*parms->hit = 1;\n+\t\t*parms->ref_cnt = ++ref_cnt;\n+\t\tshadow_db->db[parms->type].ref_count[parms->search_id] =\n+\t\t\t\t\t\t\t\tref_cnt;\n+\t} else {\n+\t\t*parms->hit = 0;\n+\t\t*parms->ref_cnt = 0;\n+\t}\n+\n+\n+\treturn 0;\n+}\n+\n+#define ID_REF_CNT_MAX 0xffffffff\n+int\n+tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms)\n+{\n+\tstruct tf_shadow_ident_db *shadow_db;\n+\n+\tTF_CHECK_PARMS1(parms);\n+\n+\tshadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;\n+\n+\t/* In case of overflow, ref count keeps the max value */\n+\tif (shadow_db->db[parms->type].ref_count[parms->id] < ID_REF_CNT_MAX)\n+\t\tshadow_db->db[parms->type].ref_count[parms->id]++;\n+\telse\n+\t\tTFP_DRV_LOG(ERR,\n+\t\t\t    \"Identifier %d in type %d reaches the max ref_cnt\\n\",\n+\t\t\t    parms->type,\n+\t\t\t    parms->id);\n+\n+\tparms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id];\n+\n+\treturn 0;\n+}\n+\n+int\n+tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms)\n+{\n+\tstruct tf_shadow_ident_db *shadow_db;\n+\tuint32_t ref_cnt = 0;\n+\n+\tTF_CHECK_PARMS1(parms);\n+\n+\tshadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db;\n+\tref_cnt = shadow_db->db[parms->type].ref_count[parms->id];\n+\tif (ref_cnt > 0)\n+\t\tshadow_db->db[parms->type].ref_count[parms->id]--;\n+\telse\n+\t\treturn -EINVAL;\n+\n+\t*parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id];\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/bnxt/tf_core/tf_shadow_identifier.h b/drivers/net/bnxt/tf_core/tf_shadow_identifier.h\nnew file mode 100644\nindex 0000000..dd633af\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_core/tf_shadow_identifier.h\n@@ -0,0 +1,229 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#ifndef _TF_SHADOW_IDENTIFIER_H_\n+#define _TF_SHADOW_IDENTIFIER_H_\n+\n+#include \"tf_core.h\"\n+\n+struct tf;\n+\n+/**\n+ * The Shadow Identifier module provides shadow DB handling for identifier based\n+ * TF types. A shadow DB provides the capability that allows for reuse\n+ * of TF resources.\n+ *\n+ * A Shadow identifier DB is intended to be used by the Identifier Type module\n+ * only.\n+ */\n+\n+/**\n+ * Shadow DB configuration information for a single identifier type.\n+ *\n+ * It is used in an array of identifier types. The array must be ordered\n+ * by the TF type is represents.\n+ */\n+struct tf_shadow_ident_cfg_parms {\n+\t/**\n+\t * TF Identifier type\n+\t */\n+\tenum tf_identifier_type type;\n+\n+\t/**\n+\t * Number of entries the Shadow DB needs to hold\n+\t */\n+\tint num_entries;\n+\n+\t/**\n+\t * Resource allocation count array. This array content\n+\t * originates from the tf_session_resources that is passed in\n+\t * on session open.\n+\t * Array size is num_elements.\n+\t */\n+\tuint16_t *alloc_cnt;\n+};\n+\n+/**\n+ * Shadow identifier DB creation parameters\n+ */\n+struct tf_shadow_ident_create_db_parms {\n+\t/**\n+\t * [in] Receive or transmit direction.\n+\t */\n+\tenum tf_dir dir;\n+\t/**\n+\t * [in] Configuration information for the shadow db\n+\t */\n+\tstruct tf_shadow_ident_cfg_parms *cfg;\n+\t/**\n+\t * [in] Number of elements in the parms structure\n+\t */\n+\tuint16_t num_elements;\n+\t/**\n+\t * [out] Shadow identifier DB handle\n+\t */\n+\tvoid **tf_shadow_ident_db;\n+};\n+\n+/**\n+ * Shadow identifier DB free parameters\n+ */\n+struct tf_shadow_ident_free_db_parms {\n+\t/**\n+\t * Shadow identifier DB handle\n+\t */\n+\tvoid *tf_shadow_ident_db;\n+};\n+\n+/**\n+ * Shadow identifier search parameters\n+ */\n+struct tf_shadow_ident_search_parms {\n+\t/**\n+\t * [in] Shadow identifier DB handle\n+\t */\n+\tvoid *tf_shadow_ident_db;\n+\t/**\n+\t * [in] Identifier type\n+\t */\n+\tenum tf_identifier_type type;\n+\t/**\n+\t * [in] id to search\n+\t */\n+\tuint16_t search_id;\n+\t/**\n+\t * [out] Index of the found element returned if hit\n+\t */\n+\tbool *hit;\n+\t/**\n+\t * [out] Reference count incremented if hit\n+\t */\n+\tuint32_t *ref_cnt;\n+};\n+\n+/**\n+ * Shadow identifier insert parameters\n+ */\n+struct tf_shadow_ident_insert_parms {\n+\t/**\n+\t * [in] Shadow identifier DB handle\n+\t */\n+\tvoid *tf_shadow_ident_db;\n+\t/**\n+\t * [in] Tbl type\n+\t */\n+\tenum tf_identifier_type type;\n+\t/**\n+\t * [in] Entry to update\n+\t */\n+\tuint16_t id;\n+\t/**\n+\t * [out] Reference count after insert\n+\t */\n+\tuint32_t ref_cnt;\n+};\n+\n+/**\n+ * Shadow identifier remove parameters\n+ */\n+struct tf_shadow_ident_remove_parms {\n+\t/**\n+\t * [in] Shadow identifier DB handle\n+\t */\n+\tvoid *tf_shadow_ident_db;\n+\t/**\n+\t * [in] Tbl type\n+\t */\n+\tenum tf_identifier_type type;\n+\t/**\n+\t * [in] Entry to update\n+\t */\n+\tuint16_t id;\n+\t/**\n+\t * [out] Reference count after removal\n+\t */\n+\tuint32_t *ref_cnt;\n+};\n+\n+/**\n+ * @page shadow_ident Shadow identifier DB\n+ *\n+ * @ref tf_shadow_ident_create_db\n+ *\n+ * @ref tf_shadow_ident_free_db\n+ *\n+ * @reg tf_shadow_ident_search\n+ *\n+ * @reg tf_shadow_ident_insert\n+ *\n+ * @reg tf_shadow_ident_remove\n+ */\n+\n+/**\n+ * Creates and fills a Shadow identifier DB. The DB is indexed per the\n+ * parms structure.\n+ *\n+ * [in] parms\n+ *   Pointer to create db parameters\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms);\n+\n+/**\n+ * Closes the Shadow identifier DB and frees all allocated\n+ * resources per the associated database.\n+ *\n+ * [in] parms\n+ *   Pointer to the free DB parameters\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms);\n+\n+/**\n+ * Search Shadow identifier db for matching result\n+ *\n+ * [in] parms\n+ *   Pointer to the search parameters\n+ *\n+ * Returns\n+ *   - (0) if successful, element was found.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms);\n+\n+/**\n+ * Inserts an element into the Shadow identifier DB. Ref_count after insert\n+ * will be incremented.\n+ *\n+ * [in] parms\n+ *   Pointer to insert parameters\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms);\n+\n+/**\n+ * Removes an element from the Shadow identifier DB. Will fail if the\n+ * elements ref_count is 0. Ref_count after removal will be\n+ * decremented.\n+ *\n+ * [in] parms\n+ *   Pointer to remove parameter\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms);\n+\n+#endif /* _TF_SHADOW_IDENTIFIER_H_ */\n",
    "prefixes": [
        "02/10"
    ]
}