get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 66789,
    "url": "http://patches.dpdk.org/api/patches/66789/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1584459511-5353-6-git-send-email-venkatkumar.duvvuru@broadcom.com/",
    "project": {
        "id": 1,
        "url": "http://patches.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": "<1584459511-5353-6-git-send-email-venkatkumar.duvvuru@broadcom.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1584459511-5353-6-git-send-email-venkatkumar.duvvuru@broadcom.com",
    "date": "2020-03-17T15:38:03",
    "name": "[05/33] net/bnxt: add initial tf core session close support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "3bc17bf54590d64e8a86492b790f991de67ca9d5",
    "submitter": {
        "id": 1635,
        "url": "http://patches.dpdk.org/api/people/1635/?format=api",
        "name": "Venkat Duvvuru",
        "email": "venkatkumar.duvvuru@broadcom.com"
    },
    "delegate": {
        "id": 1766,
        "url": "http://patches.dpdk.org/api/users/1766/?format=api",
        "username": "ajitkhaparde",
        "first_name": "Ajit",
        "last_name": "Khaparde",
        "email": "ajit.khaparde@broadcom.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1584459511-5353-6-git-send-email-venkatkumar.duvvuru@broadcom.com/mbox/",
    "series": [
        {
            "id": 8955,
            "url": "http://patches.dpdk.org/api/series/8955/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8955",
            "date": "2020-03-17T15:37:58",
            "name": "add support for host based flow table management",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8955/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/66789/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/66789/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 E973AA0565;\n\tTue, 17 Mar 2020 16:40:21 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7E2E11C0AD;\n\tTue, 17 Mar 2020 16:39:13 +0100 (CET)",
            "from mail-wr1-f67.google.com (mail-wr1-f67.google.com\n [209.85.221.67]) by dpdk.org (Postfix) with ESMTP id F14DC1C08D\n for <dev@dpdk.org>; Tue, 17 Mar 2020 16:39:10 +0100 (CET)",
            "by mail-wr1-f67.google.com with SMTP id w16so9880386wrv.13\n for <dev@dpdk.org>; Tue, 17 Mar 2020 08:39:10 -0700 (PDT)",
            "from S60.dhcp.broadcom.net ([192.19.234.250])\n by smtp.gmail.com with ESMTPSA id q4sm5052142wro.56.2020.03.17.08.39.07\n (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n Tue, 17 Mar 2020 08:39:09 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com;\n s=google;\n h=from:to:cc:subject:date:message-id:in-reply-to:references;\n bh=0xTPXGC2y1VkGFUdlixCsiKQQMaSY+RCGxR147dHnW8=;\n b=JOdti7S8sXkWXN6a9rL3zYSWUwiSHRzUUeggg462+WmGI8zUuUh77+xX8ZfhWQelPx\n WxIYXw+8Nm/5PXM7VwQOntSX0xaM//dSfUzhthhFvCnDGAKKmi3k0RFXA2/4hvWRHtAy\n 6ZEL9ObbtvnSMUQkxKLS5ZbsbOjdmiNOYNOj8=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references;\n bh=0xTPXGC2y1VkGFUdlixCsiKQQMaSY+RCGxR147dHnW8=;\n b=ap4hcQYPXch82V/WGP2ab9xwDYu1AmATzrFGuVoRIrgrqwdjSi0cFbc6PLC6x/rpDw\n M9aKp00OCxsZSCE+VIm5YVf8DF88KiMwLo6Vx4CX8LpKS8VACUVYItTZZ8mb8jauGML+\n OA2L9OLrCbB4nIqN2KKyqTxGOH4fFKcLZpbRodUdPexxHdQNbiUN18UpiuknPJsRJQO3\n Xl07hwV1Rz3bZp5GcKZjJy6/KCqDwlgjOT9yvpyfQImEv1XXz+JrLHyB0rOe/Cf7owPT\n 1IOUm0LI9CNwYX1tsV8BhkkPAQv0DS6bgv83DcKvE9QqNvx90Z5fg/Da82ldDXCzQvcV\n QmcA==",
        "X-Gm-Message-State": "ANhLgQ2hBGvLw/iTs/KMEZZq8UuegPjRkR4flS1DrPWGZgHf1WvSyv9V\n /nd6HaLwNtF9WxdWAa/nMUAoM/4QVbl29lu8fZaYA4GpldXxLbIP8ezVPb++DsmGUu9MTbgHzt4\n xsonZQeguC12sR2wDTh+Qx1c1NTHtaBTf5U9kQGUacrN0bwF2cghksGyGR2TTgARfN7QP",
        "X-Google-Smtp-Source": "\n ADFU+vukRnQMbY2Sa1M45kB1OwUPOgKsolg+3s8Q62cgImKOdTZBIj/KZWfp2mGN9/c2rMQnZGqH3g==",
        "X-Received": "by 2002:adf:ee10:: with SMTP id y16mr6621353wrn.162.1584459549471;\n Tue, 17 Mar 2020 08:39:09 -0700 (PDT)",
        "From": "Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>",
        "To": "dev@dpdk.org",
        "Cc": "Michael Wildt <michael.wildt@broadcom.com>",
        "Date": "Tue, 17 Mar 2020 21:08:03 +0530",
        "Message-Id": "\n <1584459511-5353-6-git-send-email-venkatkumar.duvvuru@broadcom.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "\n <1584459511-5353-1-git-send-email-venkatkumar.duvvuru@broadcom.com>",
        "References": "\n <1584459511-5353-1-git-send-email-venkatkumar.duvvuru@broadcom.com>",
        "Subject": "[dpdk-dev] [PATCH 05/33] net/bnxt: add initial tf core session\n\tclose support",
        "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: Michael Wildt <michael.wildt@broadcom.com>\n\n- Add TruFlow session and resource support functions\n- Add Truflow session close API and related message support functions\n  for both session and hw resources\n\nSigned-off-by: Michael Wildt <michael.wildt@broadcom.com>\nReviewed-by: Randy Schacher <stuart.schacher@broadcom.com>\nReviewed-by: Ajit Kumar Khaparde <ajit.khaparde@broadcom.com>\n---\n drivers/net/bnxt/Makefile               |   1 +\n drivers/net/bnxt/tf_core/bitalloc.c     | 364 +++++++++++++++++++++++++++++\n drivers/net/bnxt/tf_core/bitalloc.h     | 119 ++++++++++\n drivers/net/bnxt/tf_core/tf_core.c      |  86 +++++++\n drivers/net/bnxt/tf_core/tf_msg.c       | 401 ++++++++++++++++++++++++++++++++\n drivers/net/bnxt/tf_core/tf_msg.h       |  42 ++++\n drivers/net/bnxt/tf_core/tf_resources.h |  24 +-\n drivers/net/bnxt/tf_core/tf_rm.h        | 113 +++++++++\n drivers/net/bnxt/tf_core/tf_session.h   |   1 +\n 9 files changed, 1146 insertions(+), 5 deletions(-)\n create mode 100644 drivers/net/bnxt/tf_core/bitalloc.c\n create mode 100644 drivers/net/bnxt/tf_core/bitalloc.h",
    "diff": "diff --git a/drivers/net/bnxt/Makefile b/drivers/net/bnxt/Makefile\nindex 0686988..1b42c1f 100644\n--- a/drivers/net/bnxt/Makefile\n+++ b/drivers/net/bnxt/Makefile\n@@ -48,6 +48,7 @@ CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/tf_core\n endif\n \n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_TRUFLOW) += tf_core/tf_core.c\n+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_TRUFLOW) += tf_core/bitalloc.c\n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_TRUFLOW) += tf_core/tf_msg.c\n SRCS-$(CONFIG_RTE_LIBRTE_BNXT_TRUFLOW) += tf_core/tfp.c\n \ndiff --git a/drivers/net/bnxt/tf_core/bitalloc.c b/drivers/net/bnxt/tf_core/bitalloc.c\nnew file mode 100644\nindex 0000000..fb4df9a\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_core/bitalloc.c\n@@ -0,0 +1,364 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#include \"bitalloc.h\"\n+\n+#define BITALLOC_MAX_LEVELS 6\n+\n+/* Finds the first bit set plus 1, equivalent to gcc __builtin_ffs */\n+static int\n+ba_ffs(bitalloc_word_t v)\n+{\n+\tint c; /* c will be the number of zero bits on the right plus 1 */\n+\n+\tv &= -v;\n+\tc = v ? 32 : 0;\n+\n+\tif (v & 0x0000FFFF)\n+\t\tc -= 16;\n+\tif (v & 0x00FF00FF)\n+\t\tc -= 8;\n+\tif (v & 0x0F0F0F0F)\n+\t\tc -= 4;\n+\tif (v & 0x33333333)\n+\t\tc -= 2;\n+\tif (v & 0x55555555)\n+\t\tc -= 1;\n+\n+\treturn c;\n+}\n+\n+int\n+ba_init(struct bitalloc *pool, int size)\n+{\n+\tbitalloc_word_t *mem = (bitalloc_word_t *)pool;\n+\tint       i;\n+\n+\t/* Initialize */\n+\tpool->size = 0;\n+\n+\tif (size < 1 || size > BITALLOC_MAX_SIZE)\n+\t\treturn -1;\n+\n+\t/* Zero structure */\n+\tfor (i = 0;\n+\t     i < (int)(BITALLOC_SIZEOF(size) / sizeof(bitalloc_word_t));\n+\t     i++)\n+\t\tmem[i] = 0;\n+\n+\t/* Initialize */\n+\tpool->size = size;\n+\n+\t/* Embed number of words of next level, after each level */\n+\tint words[BITALLOC_MAX_LEVELS];\n+\tint lev = 0;\n+\tint offset = 0;\n+\n+\twords[0] = (size + 31) / 32;\n+\twhile (words[lev] > 1) {\n+\t\tlev++;\n+\t\twords[lev] = (words[lev - 1] + 31) / 32;\n+\t}\n+\n+\twhile (lev) {\n+\t\toffset += words[lev];\n+\t\tpool->storage[offset++] = words[--lev];\n+\t}\n+\n+\t/* Free the entire pool */\n+\tfor (i = 0; i < size; i++)\n+\t\tba_free(pool, i);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ba_alloc_helper(struct bitalloc *pool,\n+\t\tint              offset,\n+\t\tint              words,\n+\t\tunsigned int     size,\n+\t\tint              index,\n+\t\tint             *clear)\n+{\n+\tbitalloc_word_t *storage = &pool->storage[offset];\n+\tint       loc = ba_ffs(storage[index]);\n+\tint       r;\n+\n+\tif (loc == 0)\n+\t\treturn -1;\n+\n+\tloc--;\n+\n+\tif (pool->size > size) {\n+\t\tr = ba_alloc_helper(pool,\n+\t\t\t\t    offset + words + 1,\n+\t\t\t\t    storage[words],\n+\t\t\t\t    size * 32,\n+\t\t\t\t    index * 32 + loc,\n+\t\t\t\t    clear);\n+\t} else {\n+\t\tr = index * 32 + loc;\n+\t\t*clear = 1;\n+\t\tpool->free_count--;\n+\t}\n+\n+\tif (*clear) {\n+\t\tstorage[index] &= ~(1 << loc);\n+\t\t*clear = (storage[index] == 0);\n+\t}\n+\n+\treturn r;\n+}\n+\n+int\n+ba_alloc(struct bitalloc *pool)\n+{\n+\tint clear = 0;\n+\n+\treturn ba_alloc_helper(pool, 0, 1, 32, 0, &clear);\n+}\n+\n+static int\n+ba_alloc_index_helper(struct bitalloc *pool,\n+\t\t      int              offset,\n+\t\t      int              words,\n+\t\t      unsigned int     size,\n+\t\t      int             *index,\n+\t\t      int             *clear)\n+{\n+\tbitalloc_word_t *storage = &pool->storage[offset];\n+\tint       loc;\n+\tint       r;\n+\n+\tif (pool->size > size)\n+\t\tr = ba_alloc_index_helper(pool,\n+\t\t\t\t\t  offset + words + 1,\n+\t\t\t\t\t  storage[words],\n+\t\t\t\t\t  size * 32,\n+\t\t\t\t\t  index,\n+\t\t\t\t\t  clear);\n+\telse\n+\t\tr = 1; /* Check if already allocated */\n+\n+\tloc = (*index % 32);\n+\t*index = *index / 32;\n+\n+\tif (r == 1) {\n+\t\tr = (storage[*index] & (1 << loc)) ? 0 : -1;\n+\t\tif (r == 0) {\n+\t\t\t*clear = 1;\n+\t\t\tpool->free_count--;\n+\t\t}\n+\t}\n+\n+\tif (*clear) {\n+\t\tstorage[*index] &= ~(1 << loc);\n+\t\t*clear = (storage[*index] == 0);\n+\t}\n+\n+\treturn r;\n+}\n+\n+int\n+ba_alloc_index(struct bitalloc *pool, int index)\n+{\n+\tint clear = 0;\n+\tint index_copy = index;\n+\n+\tif (index < 0 || index >= (int)pool->size)\n+\t\treturn -1;\n+\n+\tif (ba_alloc_index_helper(pool, 0, 1, 32, &index_copy, &clear) >= 0)\n+\t\treturn index;\n+\telse\n+\t\treturn -1;\n+}\n+\n+static int\n+ba_inuse_helper(struct bitalloc *pool,\n+\t\tint              offset,\n+\t\tint              words,\n+\t\tunsigned int     size,\n+\t\tint             *index)\n+{\n+\tbitalloc_word_t *storage = &pool->storage[offset];\n+\tint       loc;\n+\tint       r;\n+\n+\tif (pool->size > size)\n+\t\tr = ba_inuse_helper(pool,\n+\t\t\t\t    offset + words + 1,\n+\t\t\t\t    storage[words],\n+\t\t\t\t    size * 32,\n+\t\t\t\t    index);\n+\telse\n+\t\tr = 1; /* Check if in use */\n+\n+\tloc = (*index % 32);\n+\t*index = *index / 32;\n+\n+\tif (r == 1)\n+\t\tr = (storage[*index] & (1 << loc)) ? -1 : 0;\n+\n+\treturn r;\n+}\n+\n+int\n+ba_inuse(struct bitalloc *pool, int index)\n+{\n+\tif (index < 0 || index >= (int)pool->size)\n+\t\treturn -1;\n+\n+\treturn ba_inuse_helper(pool, 0, 1, 32, &index) == 0;\n+}\n+\n+static int\n+ba_free_helper(struct bitalloc *pool,\n+\t       int              offset,\n+\t       int              words,\n+\t       unsigned int     size,\n+\t       int             *index)\n+{\n+\tbitalloc_word_t *storage = &pool->storage[offset];\n+\tint       loc;\n+\tint       r;\n+\n+\tif (pool->size > size)\n+\t\tr = ba_free_helper(pool,\n+\t\t\t\t   offset + words + 1,\n+\t\t\t\t   storage[words],\n+\t\t\t\t   size * 32,\n+\t\t\t\t   index);\n+\telse\n+\t\tr = 1; /* Check if already free */\n+\n+\tloc = (*index % 32);\n+\t*index = *index / 32;\n+\n+\tif (r == 1) {\n+\t\tr = (storage[*index] & (1 << loc)) ? -1 : 0;\n+\t\tif (r == 0)\n+\t\t\tpool->free_count++;\n+\t}\n+\n+\tif (r == 0)\n+\t\tstorage[*index] |= (1 << loc);\n+\n+\treturn r;\n+}\n+\n+int\n+ba_free(struct bitalloc *pool, int index)\n+{\n+\tif (index < 0 || index >= (int)pool->size)\n+\t\treturn -1;\n+\n+\treturn ba_free_helper(pool, 0, 1, 32, &index);\n+}\n+\n+int\n+ba_inuse_free(struct bitalloc *pool, int index)\n+{\n+\tif (index < 0 || index >= (int)pool->size)\n+\t\treturn -1;\n+\n+\treturn ba_free_helper(pool, 0, 1, 32, &index) + 1;\n+}\n+\n+int\n+ba_free_count(struct bitalloc *pool)\n+{\n+\treturn (int)pool->free_count;\n+}\n+\n+int ba_inuse_count(struct bitalloc *pool)\n+{\n+\treturn (int)(pool->size) - (int)(pool->free_count);\n+}\n+\n+static int\n+ba_find_next_helper(struct bitalloc *pool,\n+\t\t    int              offset,\n+\t\t    int              words,\n+\t\t    unsigned int     size,\n+\t\t    int             *index,\n+\t\t    int              free)\n+{\n+\tbitalloc_word_t *storage = &pool->storage[offset];\n+\tint       loc, r, bottom = 0;\n+\n+\tif (pool->size > size)\n+\t\tr = ba_find_next_helper(pool,\n+\t\t\t\t\toffset + words + 1,\n+\t\t\t\t\tstorage[words],\n+\t\t\t\t\tsize * 32,\n+\t\t\t\t\tindex,\n+\t\t\t\t\tfree);\n+\telse\n+\t\tbottom = 1; /* Bottom of tree */\n+\n+\tloc = (*index % 32);\n+\t*index = *index / 32;\n+\n+\tif (bottom) {\n+\t\tint bit_index = *index * 32;\n+\n+\t\tloc = ba_ffs(~storage[*index] & ((bitalloc_word_t)-1 << loc));\n+\t\tif (loc > 0) {\n+\t\t\tloc--;\n+\t\t\tr = (bit_index + loc);\n+\t\t\tif (r >= (int)pool->size)\n+\t\t\t\tr = -1;\n+\t\t} else {\n+\t\t\t/* Loop over array at bottom of tree */\n+\t\t\tr = -1;\n+\t\t\tbit_index += 32;\n+\t\t\t*index = *index + 1;\n+\t\t\twhile ((int)pool->size > bit_index) {\n+\t\t\t\tloc = ba_ffs(~storage[*index]);\n+\n+\t\t\t\tif (loc > 0) {\n+\t\t\t\t\tloc--;\n+\t\t\t\t\tr = (bit_index + loc);\n+\t\t\t\t\tif (r >= (int)pool->size)\n+\t\t\t\t\t\tr = -1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\tbit_index += 32;\n+\t\t\t\t*index = *index + 1;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (r >= 0 && (free)) {\n+\t\tif (bottom)\n+\t\t\tpool->free_count++;\n+\t\tstorage[*index] |= (1 << loc);\n+\t}\n+\n+\treturn r;\n+}\n+\n+int\n+ba_find_next_inuse(struct bitalloc *pool, int index)\n+{\n+\tif (index < 0 ||\n+\t    index >= (int)pool->size ||\n+\t    pool->free_count == pool->size)\n+\t\treturn -1;\n+\n+\treturn ba_find_next_helper(pool, 0, 1, 32, &index, 0);\n+}\n+\n+int\n+ba_find_next_inuse_free(struct bitalloc *pool, int index)\n+{\n+\tif (index < 0 ||\n+\t    index >= (int)pool->size ||\n+\t    pool->free_count == pool->size)\n+\t\treturn -1;\n+\n+\treturn ba_find_next_helper(pool, 0, 1, 32, &index, 1);\n+}\ndiff --git a/drivers/net/bnxt/tf_core/bitalloc.h b/drivers/net/bnxt/tf_core/bitalloc.h\nnew file mode 100644\nindex 0000000..563c853\n--- /dev/null\n+++ b/drivers/net/bnxt/tf_core/bitalloc.h\n@@ -0,0 +1,119 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019-2020 Broadcom\n+ * All rights reserved.\n+ */\n+\n+#ifndef _BITALLOC_H_\n+#define _BITALLOC_H_\n+\n+#include <stdint.h>\n+\n+/* Bitalloc works on uint32_t as its word size */\n+typedef uint32_t bitalloc_word_t;\n+\n+struct bitalloc {\n+\tbitalloc_word_t size;\n+\tbitalloc_word_t free_count;\n+\tbitalloc_word_t storage[1];\n+};\n+\n+#define BA_L0(s) (((s) + 31) / 32)\n+#define BA_L1(s) ((BA_L0(s) + 31) / 32)\n+#define BA_L2(s) ((BA_L1(s) + 31) / 32)\n+#define BA_L3(s) ((BA_L2(s) + 31) / 32)\n+#define BA_L4(s) ((BA_L3(s) + 31) / 32)\n+\n+#define BITALLOC_SIZEOF(size)                                    \\\n+\t(sizeof(struct bitalloc) *\t\t\t\t \\\n+\t (((sizeof(struct bitalloc) +\t\t\t\t \\\n+\t    sizeof(struct bitalloc) - 1 +\t\t\t \\\n+\t    (sizeof(bitalloc_word_t) *\t\t\t\t \\\n+\t     ((BA_L0(size) - 1) +\t\t\t\t \\\n+\t      ((BA_L0(size) == 1) ? 0 : (BA_L1(size) + 1)) +\t \\\n+\t      ((BA_L1(size) == 1) ? 0 : (BA_L2(size) + 1)) +\t \\\n+\t      ((BA_L2(size) == 1) ? 0 : (BA_L3(size) + 1)) +\t \\\n+\t      ((BA_L3(size) == 1) ? 0 : (BA_L4(size) + 1)))))) / \\\n+\t  sizeof(struct bitalloc)))\n+\n+#define BITALLOC_MAX_SIZE (32 * 32 * 32 * 32 * 32 * 32)\n+\n+/* The instantiation of a bitalloc looks a bit odd. Since a\n+ * bit allocator has variable storage, we need a way to get a\n+ * a pointer to a bitalloc structure that points to the correct\n+ * amount of storage. We do this by creating an array of\n+ * bitalloc where the first element in the array is the\n+ * actual bitalloc base structure, and the remaining elements\n+ * in the array provide the storage for it. This approach allows\n+ * instances to be individual variables or members of larger\n+ * structures.\n+ */\n+#define BITALLOC_INST(name, size)                      \\\n+\tstruct bitalloc name[(BITALLOC_SIZEOF(size) /  \\\n+\t\t\t      sizeof(struct bitalloc))]\n+\n+/* Symbolic return codes */\n+#define BA_SUCCESS           0\n+#define BA_FAIL             -1\n+#define BA_ENTRY_FREE        0\n+#define BA_ENTRY_IN_USE      1\n+#define BA_NO_ENTRY_FOUND   -1\n+\n+/**\n+ * Initializates the bitallocator\n+ *\n+ * Returns 0 on success, -1 on failure.  Size is arbitrary up to\n+ * BITALLOC_MAX_SIZE\n+ */\n+int ba_init(struct bitalloc *pool, int size);\n+\n+/**\n+ * Returns -1 on failure, or index of allocated entry\n+ */\n+int ba_alloc(struct bitalloc *pool);\n+int ba_alloc_index(struct bitalloc *pool, int index);\n+\n+/**\n+ * Query a particular index in a pool to check if its in use.\n+ *\n+ * Returns -1 on invalid index, 1 if the index is allocated, 0 if it\n+ * is free\n+ */\n+int ba_inuse(struct bitalloc *pool, int index);\n+\n+/**\n+ * Variant of ba_inuse that frees the index if it is allocated, same\n+ * return codes as ba_inuse\n+ */\n+int ba_inuse_free(struct bitalloc *pool, int index);\n+\n+/**\n+ * Find next index that is in use, start checking at index 'idx'\n+ *\n+ * Returns next index that is in use on success, or\n+ * -1 if no in use index is found\n+ */\n+int ba_find_next_inuse(struct bitalloc *pool, int idx);\n+\n+/**\n+ * Variant of ba_find_next_inuse that also frees the next in use index,\n+ * same return codes as ba_find_next_inuse\n+ */\n+int ba_find_next_inuse_free(struct bitalloc *pool, int idx);\n+\n+/**\n+ * Multiple freeing of the same index has no negative side effects,\n+ * but will return -1.  returns -1 on failure, 0 on success.\n+ */\n+int ba_free(struct bitalloc *pool, int index);\n+\n+/**\n+ * Returns the pool's free count\n+ */\n+int ba_free_count(struct bitalloc *pool);\n+\n+/**\n+ * Returns the pool's in use count\n+ */\n+int ba_inuse_count(struct bitalloc *pool);\n+\n+#endif /* _BITALLOC_H_ */\ndiff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c\nindex 6bafae5..3c5d55d 100644\n--- a/drivers/net/bnxt/tf_core/tf_core.c\n+++ b/drivers/net/bnxt/tf_core/tf_core.c\n@@ -7,10 +7,18 @@\n \n #include \"tf_core.h\"\n #include \"tf_session.h\"\n+#include \"tf_rm.h\"\n #include \"tf_msg.h\"\n #include \"tfp.h\"\n+#include \"bitalloc.h\"\n #include \"bnxt.h\"\n \n+static inline uint32_t SWAP_WORDS32(uint32_t val32)\n+{\n+\treturn (((val32 & 0x0000ffff) << 16) |\n+\t\t((val32 & 0xffff0000) >> 16));\n+}\n+\n int\n tf_open_session(struct tf                    *tfp,\n \t\tstruct tf_open_session_parms *parms)\n@@ -141,5 +149,83 @@ tf_open_session(struct tf                    *tfp,\n \treturn rc;\n \n  cleanup_close:\n+\ttf_close_session(tfp);\n \treturn -EINVAL;\n }\n+\n+int\n+tf_attach_session(struct tf *tfp __rte_unused,\n+\t\t  struct tf_attach_session_parms *parms __rte_unused)\n+{\n+#if (TF_SHARED == 1)\n+\tint rc;\n+\n+\tif (tfp == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* - Open the shared memory for the attach_chan_name\n+\t * - Point to the shared session for this Device instance\n+\t * - Check that session is valid\n+\t * - Attach to the firmware so it can record there is more\n+\t *   than one client of the session.\n+\t */\n+\n+\tif (tfp->session) {\n+\t\tif (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {\n+\t\t\trc = tf_msg_session_attach(tfp,\n+\t\t\t\t\t\t   parms->ctrl_chan_name,\n+\t\t\t\t\t\t   parms->session_id);\n+\t\t}\n+\t}\n+#endif /* TF_SHARED */\n+\treturn -1;\n+}\n+\n+int\n+tf_close_session(struct tf *tfp)\n+{\n+\tint rc;\n+\tint rc_close = 0;\n+\tstruct tf_session *tfs;\n+\tunion tf_session_id session_id;\n+\n+\tif (tfp == NULL || tfp->session == NULL)\n+\t\treturn -EINVAL;\n+\n+\ttfs = (struct tf_session *)(tfp->session->core_data);\n+\n+\tif (tfs->session_id.id != TF_SESSION_ID_INVALID) {\n+\t\trc = tf_msg_session_close(tfp);\n+\t\tif (rc) {\n+\t\t\t/* Log error */\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t    \"Message send failed, rc:%d\\n\",\n+\t\t\t\t    rc);\n+\t\t}\n+\n+\t\t/* Update the ref_count */\n+\t\ttfs->ref_count--;\n+\t}\n+\n+\tsession_id = tfs->session_id;\n+\n+\t/* Final cleanup as we're last user of the session */\n+\tif (tfs->ref_count == 0) {\n+\t\ttfp_free(tfp->session->core_data);\n+\t\ttfp_free(tfp->session);\n+\t\ttfp->session = NULL;\n+\t}\n+\n+\tPMD_DRV_LOG(INFO,\n+\t\t    \"Session closed, session_id:%d\\n\",\n+\t\t    session_id.id);\n+\n+\tPMD_DRV_LOG(INFO,\n+\t\t    \"domain:%d, bus:%d, device:%d, fw_session_id:%d\\n\",\n+\t\t    session_id.internal.domain,\n+\t\t    session_id.internal.bus,\n+\t\t    session_id.internal.device,\n+\t\t    session_id.internal.fw_session_id);\n+\n+\treturn rc_close;\n+}\ndiff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c\nindex 2b68681..e05aea7 100644\n--- a/drivers/net/bnxt/tf_core/tf_msg.c\n+++ b/drivers/net/bnxt/tf_core/tf_msg.c\n@@ -18,6 +18,82 @@\n #include \"hwrm_tf.h\"\n \n /**\n+ * Endian converts min and max values from the HW response to the query\n+ */\n+#define TF_HW_RESP_TO_QUERY(query, index, response, element) do {            \\\n+\t(query)->hw_query[index].min =                                       \\\n+\t\ttfp_le_to_cpu_16(response. element ## _min);                 \\\n+\t(query)->hw_query[index].max =                                       \\\n+\t\ttfp_le_to_cpu_16(response. element ## _max);                 \\\n+} while (0)\n+\n+/**\n+ * Endian converts the number of entries from the alloc to the request\n+ */\n+#define TF_HW_ALLOC_TO_REQ(alloc, index, request, element)                   \\\n+\t(request. num_ ## element = tfp_cpu_to_le_16((alloc)->hw_num[index]))\n+\n+/**\n+ * Endian converts the start and stride value from the free to the request\n+ */\n+#define TF_HW_FREE_TO_REQ(hw_entry, index, request, element) do {            \\\n+\trequest.element ## _start =                                          \\\n+\t\ttfp_cpu_to_le_16(hw_entry[index].start);                     \\\n+\trequest.element ## _stride =                                         \\\n+\t\ttfp_cpu_to_le_16(hw_entry[index].stride);                    \\\n+} while (0)\n+\n+/**\n+ * Endian converts the start and stride from the HW response to the\n+ * alloc\n+ */\n+#define TF_HW_RESP_TO_ALLOC(hw_entry, index, response, element) do {         \\\n+\thw_entry[index].start =                                              \\\n+\t\ttfp_le_to_cpu_16(response.element ## _start);                \\\n+\thw_entry[index].stride =                                             \\\n+\t\ttfp_le_to_cpu_16(response.element ## _stride);               \\\n+} while (0)\n+\n+/**\n+ * Endian converts min and max values from the SRAM response to the\n+ * query\n+ */\n+#define TF_SRAM_RESP_TO_QUERY(query, index, response, element) do {          \\\n+\t(query)->sram_query[index].min =                                     \\\n+\t\ttfp_le_to_cpu_16(response.element ## _min);                  \\\n+\t(query)->sram_query[index].max =                                     \\\n+\t\ttfp_le_to_cpu_16(response.element ## _max);                  \\\n+} while (0)\n+\n+/**\n+ * Endian converts the number of entries from the action (alloc) to\n+ * the request\n+ */\n+#define TF_SRAM_ALLOC_TO_REQ(action, index, request, element)                \\\n+\t(request. num_ ## element = tfp_cpu_to_le_16((action)->sram_num[index]))\n+\n+/**\n+ * Endian converts the start and stride value from the free to the request\n+ */\n+#define TF_SRAM_FREE_TO_REQ(sram_entry, index, request, element) do {        \\\n+\trequest.element ## _start =                                          \\\n+\t\ttfp_cpu_to_le_16(sram_entry[index].start);                   \\\n+\trequest.element ## _stride =                                         \\\n+\t\ttfp_cpu_to_le_16(sram_entry[index].stride);                  \\\n+} while (0)\n+\n+/**\n+ * Endian converts the start and stride from the HW response to the\n+ * alloc\n+ */\n+#define TF_SRAM_RESP_TO_ALLOC(sram_entry, index, response, element) do {     \\\n+\tsram_entry[index].start =                                            \\\n+\t\ttfp_le_to_cpu_16(response.element ## _start);                \\\n+\tsram_entry[index].stride =                                           \\\n+\t\ttfp_le_to_cpu_16(response.element ## _stride);               \\\n+} while (0)\n+\n+/**\n  * Sends session open request to TF Firmware\n  */\n int\n@@ -51,6 +127,45 @@ tf_msg_session_open(struct tf *tfp,\n }\n \n /**\n+ * Sends session attach request to TF Firmware\n+ */\n+int\n+tf_msg_session_attach(struct tf *tfp __rte_unused,\n+\t\t      char *ctrl_chan_name __rte_unused,\n+\t\t      uint8_t tf_fw_session_id __rte_unused)\n+{\n+\treturn -1;\n+}\n+\n+/**\n+ * Sends session close request to TF Firmware\n+ */\n+int\n+tf_msg_session_close(struct tf *tfp)\n+{\n+\tint rc;\n+\tstruct hwrm_tf_session_close_input req = { 0 };\n+\tstruct hwrm_tf_session_close_output resp = { 0 };\n+\tstruct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);\n+\tstruct tfp_send_msg_parms parms = { 0 };\n+\n+\t/* Populate the request */\n+\treq.fw_session_id =\n+\t\ttfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);\n+\n+\tparms.tf_type = HWRM_TF_SESSION_CLOSE;\n+\tparms.req_data = (uint32_t *)&req;\n+\tparms.req_size = sizeof(req);\n+\tparms.resp_data = (uint32_t *)&resp;\n+\tparms.resp_size = sizeof(resp);\n+\tparms.mailbox = TF_KONG_MB;\n+\n+\trc = tfp_send_msg_direct(tfp,\n+\t\t\t\t &parms);\n+\treturn rc;\n+}\n+\n+/**\n  * Sends session query config request to TF Firmware\n  */\n int\n@@ -77,3 +192,289 @@ tf_msg_session_qcfg(struct tf *tfp)\n \t\t\t\t &parms);\n \treturn rc;\n }\n+\n+/**\n+ * Sends session HW resource query capability request to TF Firmware\n+ */\n+int\n+tf_msg_session_hw_resc_qcaps(struct tf *tfp,\n+\t\t\t     enum tf_dir dir,\n+\t\t\t     struct tf_rm_hw_query *query)\n+{\n+\tint rc;\n+\tstruct tfp_send_msg_parms parms = { 0 };\n+\tstruct tf_session_hw_resc_qcaps_input req = { 0 };\n+\tstruct tf_session_hw_resc_qcaps_output resp = { 0 };\n+\tstruct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);\n+\n+\tmemset(query, 0, sizeof(*query));\n+\n+\t/* Populate the request */\n+\treq.fw_session_id =\n+\t\ttfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);\n+\treq.flags = tfp_cpu_to_le_16(dir);\n+\n+\tMSG_PREP(parms,\n+\t\t TF_KONG_MB,\n+\t\t HWRM_TF,\n+\t\t HWRM_TFT_SESSION_HW_RESC_QCAPS,\n+\t\t req,\n+\t\t resp);\n+\n+\trc = tfp_send_msg_tunneled(tfp, &parms);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\t/* Process the response */\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,\n+\t\t\t    l2_ctx_tcam_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_FUNC, resp,\n+\t\t\t    prof_func);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_TCAM, resp,\n+\t\t\t    prof_tcam_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_PROF_ID, resp,\n+\t\t\t    em_prof_id);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_REC, resp,\n+\t\t\t    em_record_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,\n+\t\t\t    wc_tcam_prof_id);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM, resp,\n+\t\t\t    wc_tcam_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_PROF, resp,\n+\t\t\t    meter_profiles);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_INST,\n+\t\t\t    resp, meter_inst);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_MIRROR, resp,\n+\t\t\t    mirrors);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_UPAR, resp,\n+\t\t\t    upar);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_SP_TCAM, resp,\n+\t\t\t    sp_tcam_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_FUNC, resp,\n+\t\t\t    l2_func);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_FKB, resp,\n+\t\t\t    flex_key_templ);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_TBL_SCOPE, resp,\n+\t\t\t    tbl_scope);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH0, resp,\n+\t\t\t    epoch0_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH1, resp,\n+\t\t\t    epoch1_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METADATA, resp,\n+\t\t\t    metadata);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_CT_STATE, resp,\n+\t\t\t    ct_state);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_PROF, resp,\n+\t\t\t    range_prof);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,\n+\t\t\t    range_entries);\n+\tTF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_LAG_ENTRY, resp,\n+\t\t\t    lag_tbl_entries);\n+\n+\treturn tfp_le_to_cpu_32(parms.tf_resp_code);\n+}\n+\n+/**\n+ * Sends session HW resource allocation request to TF Firmware\n+ */\n+int\n+tf_msg_session_hw_resc_alloc(struct tf *tfp __rte_unused,\n+\t\t\t     enum tf_dir dir,\n+\t\t\t     struct tf_rm_hw_alloc *hw_alloc __rte_unused,\n+\t\t\t     struct tf_rm_entry *hw_entry __rte_unused)\n+{\n+\tint rc;\n+\tstruct tfp_send_msg_parms parms = { 0 };\n+\tstruct tf_session_hw_resc_alloc_input req = { 0 };\n+\tstruct tf_session_hw_resc_alloc_output resp = { 0 };\n+\tstruct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);\n+\n+\tmemset(hw_entry, 0, sizeof(*hw_entry));\n+\n+\t/* Populate the request */\n+\treq.fw_session_id =\n+\t\ttfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);\n+\treq.flags = tfp_cpu_to_le_16(dir);\n+\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,\n+\t\t\t   l2_ctx_tcam_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_FUNC, req,\n+\t\t\t   prof_func_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_TCAM, req,\n+\t\t\t   prof_tcam_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_PROF_ID, req,\n+\t\t\t   em_prof_id);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_REC, req,\n+\t\t\t   em_record_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,\n+\t\t\t   wc_tcam_prof_id);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM, req,\n+\t\t\t   wc_tcam_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_PROF, req,\n+\t\t\t   meter_profiles);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_INST, req,\n+\t\t\t   meter_inst);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_MIRROR, req,\n+\t\t\t   mirrors);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_UPAR, req,\n+\t\t\t   upar);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_SP_TCAM, req,\n+\t\t\t   sp_tcam_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_FUNC, req,\n+\t\t\t   l2_func);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_FKB, req,\n+\t\t\t   flex_key_templ);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_TBL_SCOPE, req,\n+\t\t\t   tbl_scope);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH0, req,\n+\t\t\t   epoch0_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH1, req,\n+\t\t\t   epoch1_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METADATA, req,\n+\t\t\t   metadata);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_CT_STATE, req,\n+\t\t\t   ct_state);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_PROF, req,\n+\t\t\t   range_prof);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_ENTRY, req,\n+\t\t\t   range_entries);\n+\tTF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_LAG_ENTRY, req,\n+\t\t\t   lag_tbl_entries);\n+\n+\tMSG_PREP(parms,\n+\t\t TF_KONG_MB,\n+\t\t HWRM_TF,\n+\t\t HWRM_TFT_SESSION_HW_RESC_ALLOC,\n+\t\t req,\n+\t\t resp);\n+\n+\trc = tfp_send_msg_tunneled(tfp, &parms);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\t/* Process the response */\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,\n+\t\t\t    l2_ctx_tcam_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, resp,\n+\t\t\t    prof_func);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, resp,\n+\t\t\t    prof_tcam_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, resp,\n+\t\t\t    em_prof_id);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_REC, resp,\n+\t\t\t    em_record_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,\n+\t\t\t    wc_tcam_prof_id);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, resp,\n+\t\t\t    wc_tcam_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_PROF, resp,\n+\t\t\t    meter_profiles);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_INST, resp,\n+\t\t\t    meter_inst);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_MIRROR, resp,\n+\t\t\t    mirrors);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_UPAR, resp,\n+\t\t\t    upar);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, resp,\n+\t\t\t    sp_tcam_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, resp,\n+\t\t\t    l2_func);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_FKB, resp,\n+\t\t\t    flex_key_templ);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, resp,\n+\t\t\t    tbl_scope);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH0, resp,\n+\t\t\t    epoch0_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH1, resp,\n+\t\t\t    epoch1_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METADATA, resp,\n+\t\t\t    metadata);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_CT_STATE, resp,\n+\t\t\t    ct_state);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, resp,\n+\t\t\t    range_prof);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,\n+\t\t\t    range_entries);\n+\tTF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, resp,\n+\t\t\t    lag_tbl_entries);\n+\n+\treturn tfp_le_to_cpu_32(parms.tf_resp_code);\n+}\n+\n+/**\n+ * Sends session HW resource free request to TF Firmware\n+ */\n+int\n+tf_msg_session_hw_resc_free(struct tf *tfp,\n+\t\t\t    enum tf_dir dir,\n+\t\t\t    struct tf_rm_entry *hw_entry)\n+{\n+\tint rc;\n+\tstruct tfp_send_msg_parms parms = { 0 };\n+\tstruct tf_session_hw_resc_free_input req = { 0 };\n+\tstruct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);\n+\n+\tmemset(hw_entry, 0, sizeof(*hw_entry));\n+\n+\t/* Populate the request */\n+\treq.fw_session_id =\n+\t\ttfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);\n+\treq.flags = tfp_cpu_to_le_16(dir);\n+\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,\n+\t\t\t  l2_ctx_tcam_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, req,\n+\t\t\t  prof_func);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, req,\n+\t\t\t  prof_tcam_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, req,\n+\t\t\t  em_prof_id);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_REC, req,\n+\t\t\t  em_record_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,\n+\t\t\t  wc_tcam_prof_id);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, req,\n+\t\t\t  wc_tcam_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_PROF, req,\n+\t\t\t  meter_profiles);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_INST, req,\n+\t\t\t  meter_inst);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_MIRROR, req,\n+\t\t\t  mirrors);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_UPAR, req,\n+\t\t\t  upar);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, req,\n+\t\t\t  sp_tcam_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, req,\n+\t\t\t  l2_func);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_FKB, req,\n+\t\t\t  flex_key_templ);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, req,\n+\t\t\t  tbl_scope);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH0, req,\n+\t\t\t  epoch0_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH1, req,\n+\t\t\t  epoch1_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METADATA, req,\n+\t\t\t  metadata);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_CT_STATE, req,\n+\t\t\t  ct_state);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, req,\n+\t\t\t  range_prof);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, req,\n+\t\t\t  range_entries);\n+\tTF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, req,\n+\t\t\t  lag_tbl_entries);\n+\n+\tMSG_PREP_NO_RESP(parms,\n+\t\t\t TF_KONG_MB,\n+\t\t\t HWRM_TF,\n+\t\t\t HWRM_TFT_SESSION_HW_RESC_FREE,\n+\t\t\t req);\n+\n+\trc = tfp_send_msg_tunneled(tfp, &parms);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\treturn tfp_le_to_cpu_32(parms.tf_resp_code);\n+}\ndiff --git a/drivers/net/bnxt/tf_core/tf_msg.h b/drivers/net/bnxt/tf_core/tf_msg.h\nindex 20ebf2e..da5ccf3 100644\n--- a/drivers/net/bnxt/tf_core/tf_msg.h\n+++ b/drivers/net/bnxt/tf_core/tf_msg.h\n@@ -30,6 +30,34 @@ int tf_msg_session_open(struct tf *tfp,\n \t\t\tuint8_t *fw_session_id);\n \n /**\n+ * Sends session close request to Firmware\n+ *\n+ * [in] session\n+ *   Pointer to session handle\n+ *\n+ * [in] fw_session_id\n+ *   Pointer to the fw_session_id that is assigned to the session at\n+ *   time of session open\n+ *\n+ * Returns:\n+ *\n+ */\n+int tf_msg_session_attach(struct tf *tfp,\n+\t\t\t  char *ctrl_channel_name,\n+\t\t\t  uint8_t tf_fw_session_id);\n+\n+/**\n+ * Sends session close request to Firmware\n+ *\n+ * [in] session\n+ *   Pointer to session handle\n+ *\n+ * Returns:\n+ *\n+ */\n+int tf_msg_session_close(struct tf *tfp);\n+\n+/**\n  * Sends session query config request to TF Firmware\n  */\n int tf_msg_session_qcfg(struct tf *tfp);\n@@ -41,4 +69,18 @@ int tf_msg_session_hw_resc_qcaps(struct tf *tfp,\n \t\t\t\t enum tf_dir dir,\n \t\t\t\t struct tf_rm_hw_query *hw_query);\n \n+/**\n+ * Sends session HW resource allocation request to TF Firmware\n+ */\n+int tf_msg_session_hw_resc_alloc(struct tf *tfp,\n+\t\t\t\t enum tf_dir dir,\n+\t\t\t\t struct tf_rm_hw_alloc *hw_alloc,\n+\t\t\t\t struct tf_rm_entry *hw_entry);\n+\n+/**\n+ * Sends session HW resource free request to TF Firmware\n+ */\n+int tf_msg_session_hw_resc_free(struct tf *tfp,\n+\t\t\t\tenum tf_dir dir,\n+\t\t\t\tstruct tf_rm_entry *hw_entry);\n #endif  /* _TF_MSG_H_ */\ndiff --git a/drivers/net/bnxt/tf_core/tf_resources.h b/drivers/net/bnxt/tf_core/tf_resources.h\nindex 160abac..8dbb2f9 100644\n--- a/drivers/net/bnxt/tf_core/tf_resources.h\n+++ b/drivers/net/bnxt/tf_core/tf_resources.h\n@@ -6,11 +6,6 @@\n #ifndef _TF_RESOURCES_H_\n #define _TF_RESOURCES_H_\n \n-/*\n- * Hardware specific MAX values\n- * NOTE: Should really come from the chip_cfg.h in some MAX form or HCAPI\n- */\n-\n /** HW Resource types\n  */\n enum tf_resource_type_hw {\n@@ -43,4 +38,23 @@ enum tf_resource_type_hw {\n \tTF_RESC_TYPE_HW_LAG_ENTRY,\n \tTF_RESC_TYPE_HW_MAX\n };\n+\n+/** HW Resource types\n+ */\n+enum tf_resource_type_sram {\n+\tTF_RESC_TYPE_SRAM_FULL_ACTION,\n+\tTF_RESC_TYPE_SRAM_MCG,\n+\tTF_RESC_TYPE_SRAM_ENCAP_8B,\n+\tTF_RESC_TYPE_SRAM_ENCAP_16B,\n+\tTF_RESC_TYPE_SRAM_ENCAP_64B,\n+\tTF_RESC_TYPE_SRAM_SP_SMAC,\n+\tTF_RESC_TYPE_SRAM_SP_SMAC_IPV4,\n+\tTF_RESC_TYPE_SRAM_SP_SMAC_IPV6,\n+\tTF_RESC_TYPE_SRAM_COUNTER_64B,\n+\tTF_RESC_TYPE_SRAM_NAT_SPORT,\n+\tTF_RESC_TYPE_SRAM_NAT_DPORT,\n+\tTF_RESC_TYPE_SRAM_NAT_S_IPV4,\n+\tTF_RESC_TYPE_SRAM_NAT_D_IPV4,\n+\tTF_RESC_TYPE_SRAM_MAX\n+};\n #endif /* _TF_RESOURCES_H_ */\ndiff --git a/drivers/net/bnxt/tf_core/tf_rm.h b/drivers/net/bnxt/tf_core/tf_rm.h\nindex 5164d6b..57ce19b 100644\n--- a/drivers/net/bnxt/tf_core/tf_rm.h\n+++ b/drivers/net/bnxt/tf_core/tf_rm.h\n@@ -8,10 +8,52 @@\n \n #include \"tf_resources.h\"\n #include \"tf_core.h\"\n+#include \"bitalloc.h\"\n \n struct tf;\n struct tf_session;\n \n+/* Internal macro to determine appropriate allocation pools based on\n+ * DIRECTION parm, also performs error checking for DIRECTION parm. The\n+ * SESSION_POOL and SESSION pointers are set appropriately upon\n+ * successful return (the GLOBAL_POOL is used to globally manage\n+ * resource allocation and the SESSION_POOL is used to track the\n+ * resources that have been allocated to the session)\n+ *\n+ * parameters:\n+ *   struct tfp        *tfp\n+ *   enum tf_dir        direction\n+ *   struct bitalloc  **session_pool\n+ *   string             base_pool_name - used to form pointers to the\n+ *\t\t\t\t\t appropriate bit allocation\n+ *\t\t\t\t\t pools, both directions of the\n+ *\t\t\t\t\t session pools must have same\n+ *\t\t\t\t\t base name, for example if\n+ *\t\t\t\t\t POOL_NAME is feat_pool: - the\n+ *\t\t\t\t\t ptr's to the session pools\n+ *\t\t\t\t\t are feat_pool_rx feat_pool_tx\n+ *\n+ *  int                  rc - return code\n+ *\t\t\t      0 - Success\n+ *\t\t\t     -1 - invalid DIRECTION parm\n+ */\n+#define TF_RM_GET_POOLS(tfs, direction, session_pool, pool_name, rc) do { \\\n+\t\t(rc) = 0;\t\t\t\t\t\t\\\n+\t\tif ((direction) == TF_DIR_RX) {\t\t\t\t\\\n+\t\t\t*(session_pool) = (tfs)->pool_name ## _RX;\t\\\n+\t\t} else if ((direction) == TF_DIR_TX) {\t\t\t\\\n+\t\t\t*(session_pool) = (tfs)->pool_name ## _TX;\t\\\n+\t\t} else {\t\t\t\t\t\t\\\n+\t\t\trc = -1;\t\t\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t} while (0)\n+\n+#define TF_RM_GET_POOLS_RX(tfs, session_pool, pool_name)\t\\\n+\t(*(session_pool) = (tfs)->pool_name ## _RX)\n+\n+#define TF_RM_GET_POOLS_TX(tfs, session_pool, pool_name)\t\\\n+\t(*(session_pool) = (tfs)->pool_name ## _TX)\n+\n /**\n  * Resource query single entry\n  */\n@@ -23,6 +65,16 @@ struct tf_rm_query_entry {\n };\n \n /**\n+ * Resource single entry\n+ */\n+struct tf_rm_entry {\n+\t/** Starting index of the allocated resource */\n+\tuint16_t start;\n+\t/** Number of allocated elements */\n+\tuint16_t stride;\n+};\n+\n+/**\n  * Resource query array of HW entities\n  */\n struct tf_rm_hw_query {\n@@ -30,4 +82,65 @@ struct tf_rm_hw_query {\n \tstruct tf_rm_query_entry hw_query[TF_RESC_TYPE_HW_MAX];\n };\n \n+/**\n+ * Resource allocation array of HW entities\n+ */\n+struct tf_rm_hw_alloc {\n+\t/** array of HW resource entries */\n+\tuint16_t hw_num[TF_RESC_TYPE_HW_MAX];\n+};\n+\n+/**\n+ * Resource query array of SRAM entities\n+ */\n+struct tf_rm_sram_query {\n+\t/** array of SRAM resource entries */\n+\tstruct tf_rm_query_entry sram_query[TF_RESC_TYPE_SRAM_MAX];\n+};\n+\n+/**\n+ * Resource allocation array of SRAM entities\n+ */\n+struct tf_rm_sram_alloc {\n+\t/** array of SRAM resource entries */\n+\tuint16_t sram_num[TF_RESC_TYPE_SRAM_MAX];\n+};\n+\n+/**\n+ * Initializes the Resource Manager and the associated database\n+ * entries for HW and SRAM resources. Must be called before any other\n+ * Resource Manager functions.\n+ *\n+ * [in] tfp\n+ *   Pointer to TF handle\n+ */\n+void tf_rm_init(struct tf *tfp);\n+\n+/**\n+ * Allocates and validates both HW and SRAM resources per the NVM\n+ * configuration. If any allocation fails all resources for the\n+ * session is deallocated.\n+ *\n+ * [in] tfp\n+ *   Pointer to TF handle\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ */\n+int tf_rm_allocate_validate(struct tf *tfp);\n+\n+/**\n+ * Closes the Resource Manager and frees all allocated resources per\n+ * the associated database.\n+ *\n+ * [in] tfp\n+ *   Pointer to TF handle\n+ *\n+ * Returns\n+ *   - (0) if successful.\n+ *   - (-EINVAL) on failure.\n+ *   - (-ENOTEMPTY) if resources are not cleaned up before close\n+ */\n+int tf_rm_close(struct tf *tfp);\n #endif /* TF_RM_H_ */\ndiff --git a/drivers/net/bnxt/tf_core/tf_session.h b/drivers/net/bnxt/tf_core/tf_session.h\nindex c30ebbe..f845984 100644\n--- a/drivers/net/bnxt/tf_core/tf_session.h\n+++ b/drivers/net/bnxt/tf_core/tf_session.h\n@@ -9,6 +9,7 @@\n #include <stdint.h>\n #include <stdlib.h>\n \n+#include \"bitalloc.h\"\n #include \"tf_core.h\"\n #include \"tf_rm.h\"\n \n",
    "prefixes": [
        "05/33"
    ]
}