net/bnxt: add initial TruFlow core session close
authorMichael Wildt <michael.wildt@broadcom.com>
Wed, 15 Apr 2020 08:18:42 +0000 (13:48 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:08 +0000 (13:57 +0200)
- Add TruFlow session and resource support functions
- Add Truflow session close API and related message support functions
  for both session and hw resources

Signed-off-by: Michael Wildt <michael.wildt@broadcom.com>
Reviewed-by: Randy Schacher <stuart.schacher@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
drivers/net/bnxt/Makefile
drivers/net/bnxt/tf_core/bitalloc.c [new file with mode: 0644]
drivers/net/bnxt/tf_core/bitalloc.h [new file with mode: 0644]
drivers/net/bnxt/tf_core/tf_core.c
drivers/net/bnxt/tf_core/tf_msg.c
drivers/net/bnxt/tf_core/tf_msg.h
drivers/net/bnxt/tf_core/tf_resources.h
drivers/net/bnxt/tf_core/tf_rm.h
drivers/net/bnxt/tf_core/tf_session.h

index 8a68059..8474673 100644 (file)
@@ -48,6 +48,7 @@ CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/tf_core
 endif
 
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_core.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/bitalloc.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_msg.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tfp.c
 
diff --git a/drivers/net/bnxt/tf_core/bitalloc.c b/drivers/net/bnxt/tf_core/bitalloc.c
new file mode 100644 (file)
index 0000000..fb4df9a
--- /dev/null
@@ -0,0 +1,364 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#include "bitalloc.h"
+
+#define BITALLOC_MAX_LEVELS 6
+
+/* Finds the first bit set plus 1, equivalent to gcc __builtin_ffs */
+static int
+ba_ffs(bitalloc_word_t v)
+{
+       int c; /* c will be the number of zero bits on the right plus 1 */
+
+       v &= -v;
+       c = v ? 32 : 0;
+
+       if (v & 0x0000FFFF)
+               c -= 16;
+       if (v & 0x00FF00FF)
+               c -= 8;
+       if (v & 0x0F0F0F0F)
+               c -= 4;
+       if (v & 0x33333333)
+               c -= 2;
+       if (v & 0x55555555)
+               c -= 1;
+
+       return c;
+}
+
+int
+ba_init(struct bitalloc *pool, int size)
+{
+       bitalloc_word_t *mem = (bitalloc_word_t *)pool;
+       int       i;
+
+       /* Initialize */
+       pool->size = 0;
+
+       if (size < 1 || size > BITALLOC_MAX_SIZE)
+               return -1;
+
+       /* Zero structure */
+       for (i = 0;
+            i < (int)(BITALLOC_SIZEOF(size) / sizeof(bitalloc_word_t));
+            i++)
+               mem[i] = 0;
+
+       /* Initialize */
+       pool->size = size;
+
+       /* Embed number of words of next level, after each level */
+       int words[BITALLOC_MAX_LEVELS];
+       int lev = 0;
+       int offset = 0;
+
+       words[0] = (size + 31) / 32;
+       while (words[lev] > 1) {
+               lev++;
+               words[lev] = (words[lev - 1] + 31) / 32;
+       }
+
+       while (lev) {
+               offset += words[lev];
+               pool->storage[offset++] = words[--lev];
+       }
+
+       /* Free the entire pool */
+       for (i = 0; i < size; i++)
+               ba_free(pool, i);
+
+       return 0;
+}
+
+static int
+ba_alloc_helper(struct bitalloc *pool,
+               int              offset,
+               int              words,
+               unsigned int     size,
+               int              index,
+               int             *clear)
+{
+       bitalloc_word_t *storage = &pool->storage[offset];
+       int       loc = ba_ffs(storage[index]);
+       int       r;
+
+       if (loc == 0)
+               return -1;
+
+       loc--;
+
+       if (pool->size > size) {
+               r = ba_alloc_helper(pool,
+                                   offset + words + 1,
+                                   storage[words],
+                                   size * 32,
+                                   index * 32 + loc,
+                                   clear);
+       } else {
+               r = index * 32 + loc;
+               *clear = 1;
+               pool->free_count--;
+       }
+
+       if (*clear) {
+               storage[index] &= ~(1 << loc);
+               *clear = (storage[index] == 0);
+       }
+
+       return r;
+}
+
+int
+ba_alloc(struct bitalloc *pool)
+{
+       int clear = 0;
+
+       return ba_alloc_helper(pool, 0, 1, 32, 0, &clear);
+}
+
+static int
+ba_alloc_index_helper(struct bitalloc *pool,
+                     int              offset,
+                     int              words,
+                     unsigned int     size,
+                     int             *index,
+                     int             *clear)
+{
+       bitalloc_word_t *storage = &pool->storage[offset];
+       int       loc;
+       int       r;
+
+       if (pool->size > size)
+               r = ba_alloc_index_helper(pool,
+                                         offset + words + 1,
+                                         storage[words],
+                                         size * 32,
+                                         index,
+                                         clear);
+       else
+               r = 1; /* Check if already allocated */
+
+       loc = (*index % 32);
+       *index = *index / 32;
+
+       if (r == 1) {
+               r = (storage[*index] & (1 << loc)) ? 0 : -1;
+               if (r == 0) {
+                       *clear = 1;
+                       pool->free_count--;
+               }
+       }
+
+       if (*clear) {
+               storage[*index] &= ~(1 << loc);
+               *clear = (storage[*index] == 0);
+       }
+
+       return r;
+}
+
+int
+ba_alloc_index(struct bitalloc *pool, int index)
+{
+       int clear = 0;
+       int index_copy = index;
+
+       if (index < 0 || index >= (int)pool->size)
+               return -1;
+
+       if (ba_alloc_index_helper(pool, 0, 1, 32, &index_copy, &clear) >= 0)
+               return index;
+       else
+               return -1;
+}
+
+static int
+ba_inuse_helper(struct bitalloc *pool,
+               int              offset,
+               int              words,
+               unsigned int     size,
+               int             *index)
+{
+       bitalloc_word_t *storage = &pool->storage[offset];
+       int       loc;
+       int       r;
+
+       if (pool->size > size)
+               r = ba_inuse_helper(pool,
+                                   offset + words + 1,
+                                   storage[words],
+                                   size * 32,
+                                   index);
+       else
+               r = 1; /* Check if in use */
+
+       loc = (*index % 32);
+       *index = *index / 32;
+
+       if (r == 1)
+               r = (storage[*index] & (1 << loc)) ? -1 : 0;
+
+       return r;
+}
+
+int
+ba_inuse(struct bitalloc *pool, int index)
+{
+       if (index < 0 || index >= (int)pool->size)
+               return -1;
+
+       return ba_inuse_helper(pool, 0, 1, 32, &index) == 0;
+}
+
+static int
+ba_free_helper(struct bitalloc *pool,
+              int              offset,
+              int              words,
+              unsigned int     size,
+              int             *index)
+{
+       bitalloc_word_t *storage = &pool->storage[offset];
+       int       loc;
+       int       r;
+
+       if (pool->size > size)
+               r = ba_free_helper(pool,
+                                  offset + words + 1,
+                                  storage[words],
+                                  size * 32,
+                                  index);
+       else
+               r = 1; /* Check if already free */
+
+       loc = (*index % 32);
+       *index = *index / 32;
+
+       if (r == 1) {
+               r = (storage[*index] & (1 << loc)) ? -1 : 0;
+               if (r == 0)
+                       pool->free_count++;
+       }
+
+       if (r == 0)
+               storage[*index] |= (1 << loc);
+
+       return r;
+}
+
+int
+ba_free(struct bitalloc *pool, int index)
+{
+       if (index < 0 || index >= (int)pool->size)
+               return -1;
+
+       return ba_free_helper(pool, 0, 1, 32, &index);
+}
+
+int
+ba_inuse_free(struct bitalloc *pool, int index)
+{
+       if (index < 0 || index >= (int)pool->size)
+               return -1;
+
+       return ba_free_helper(pool, 0, 1, 32, &index) + 1;
+}
+
+int
+ba_free_count(struct bitalloc *pool)
+{
+       return (int)pool->free_count;
+}
+
+int ba_inuse_count(struct bitalloc *pool)
+{
+       return (int)(pool->size) - (int)(pool->free_count);
+}
+
+static int
+ba_find_next_helper(struct bitalloc *pool,
+                   int              offset,
+                   int              words,
+                   unsigned int     size,
+                   int             *index,
+                   int              free)
+{
+       bitalloc_word_t *storage = &pool->storage[offset];
+       int       loc, r, bottom = 0;
+
+       if (pool->size > size)
+               r = ba_find_next_helper(pool,
+                                       offset + words + 1,
+                                       storage[words],
+                                       size * 32,
+                                       index,
+                                       free);
+       else
+               bottom = 1; /* Bottom of tree */
+
+       loc = (*index % 32);
+       *index = *index / 32;
+
+       if (bottom) {
+               int bit_index = *index * 32;
+
+               loc = ba_ffs(~storage[*index] & ((bitalloc_word_t)-1 << loc));
+               if (loc > 0) {
+                       loc--;
+                       r = (bit_index + loc);
+                       if (r >= (int)pool->size)
+                               r = -1;
+               } else {
+                       /* Loop over array at bottom of tree */
+                       r = -1;
+                       bit_index += 32;
+                       *index = *index + 1;
+                       while ((int)pool->size > bit_index) {
+                               loc = ba_ffs(~storage[*index]);
+
+                               if (loc > 0) {
+                                       loc--;
+                                       r = (bit_index + loc);
+                                       if (r >= (int)pool->size)
+                                               r = -1;
+                                       break;
+                               }
+                               bit_index += 32;
+                               *index = *index + 1;
+                       }
+               }
+       }
+
+       if (r >= 0 && (free)) {
+               if (bottom)
+                       pool->free_count++;
+               storage[*index] |= (1 << loc);
+       }
+
+       return r;
+}
+
+int
+ba_find_next_inuse(struct bitalloc *pool, int index)
+{
+       if (index < 0 ||
+           index >= (int)pool->size ||
+           pool->free_count == pool->size)
+               return -1;
+
+       return ba_find_next_helper(pool, 0, 1, 32, &index, 0);
+}
+
+int
+ba_find_next_inuse_free(struct bitalloc *pool, int index)
+{
+       if (index < 0 ||
+           index >= (int)pool->size ||
+           pool->free_count == pool->size)
+               return -1;
+
+       return ba_find_next_helper(pool, 0, 1, 32, &index, 1);
+}
diff --git a/drivers/net/bnxt/tf_core/bitalloc.h b/drivers/net/bnxt/tf_core/bitalloc.h
new file mode 100644 (file)
index 0000000..563c853
--- /dev/null
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _BITALLOC_H_
+#define _BITALLOC_H_
+
+#include <stdint.h>
+
+/* Bitalloc works on uint32_t as its word size */
+typedef uint32_t bitalloc_word_t;
+
+struct bitalloc {
+       bitalloc_word_t size;
+       bitalloc_word_t free_count;
+       bitalloc_word_t storage[1];
+};
+
+#define BA_L0(s) (((s) + 31) / 32)
+#define BA_L1(s) ((BA_L0(s) + 31) / 32)
+#define BA_L2(s) ((BA_L1(s) + 31) / 32)
+#define BA_L3(s) ((BA_L2(s) + 31) / 32)
+#define BA_L4(s) ((BA_L3(s) + 31) / 32)
+
+#define BITALLOC_SIZEOF(size)                                    \
+       (sizeof(struct bitalloc) *                               \
+        (((sizeof(struct bitalloc) +                            \
+           sizeof(struct bitalloc) - 1 +                        \
+           (sizeof(bitalloc_word_t) *                           \
+            ((BA_L0(size) - 1) +                                \
+             ((BA_L0(size) == 1) ? 0 : (BA_L1(size) + 1)) +     \
+             ((BA_L1(size) == 1) ? 0 : (BA_L2(size) + 1)) +     \
+             ((BA_L2(size) == 1) ? 0 : (BA_L3(size) + 1)) +     \
+             ((BA_L3(size) == 1) ? 0 : (BA_L4(size) + 1)))))) / \
+         sizeof(struct bitalloc)))
+
+#define BITALLOC_MAX_SIZE (32 * 32 * 32 * 32 * 32 * 32)
+
+/* The instantiation of a bitalloc looks a bit odd. Since a
+ * bit allocator has variable storage, we need a way to get a
+ * a pointer to a bitalloc structure that points to the correct
+ * amount of storage. We do this by creating an array of
+ * bitalloc where the first element in the array is the
+ * actual bitalloc base structure, and the remaining elements
+ * in the array provide the storage for it. This approach allows
+ * instances to be individual variables or members of larger
+ * structures.
+ */
+#define BITALLOC_INST(name, size)                      \
+       struct bitalloc name[(BITALLOC_SIZEOF(size) /  \
+                             sizeof(struct bitalloc))]
+
+/* Symbolic return codes */
+#define BA_SUCCESS           0
+#define BA_FAIL             -1
+#define BA_ENTRY_FREE        0
+#define BA_ENTRY_IN_USE      1
+#define BA_NO_ENTRY_FOUND   -1
+
+/**
+ * Initializates the bitallocator
+ *
+ * Returns 0 on success, -1 on failure.  Size is arbitrary up to
+ * BITALLOC_MAX_SIZE
+ */
+int ba_init(struct bitalloc *pool, int size);
+
+/**
+ * Returns -1 on failure, or index of allocated entry
+ */
+int ba_alloc(struct bitalloc *pool);
+int ba_alloc_index(struct bitalloc *pool, int index);
+
+/**
+ * Query a particular index in a pool to check if its in use.
+ *
+ * Returns -1 on invalid index, 1 if the index is allocated, 0 if it
+ * is free
+ */
+int ba_inuse(struct bitalloc *pool, int index);
+
+/**
+ * Variant of ba_inuse that frees the index if it is allocated, same
+ * return codes as ba_inuse
+ */
+int ba_inuse_free(struct bitalloc *pool, int index);
+
+/**
+ * Find next index that is in use, start checking at index 'idx'
+ *
+ * Returns next index that is in use on success, or
+ * -1 if no in use index is found
+ */
+int ba_find_next_inuse(struct bitalloc *pool, int idx);
+
+/**
+ * Variant of ba_find_next_inuse that also frees the next in use index,
+ * same return codes as ba_find_next_inuse
+ */
+int ba_find_next_inuse_free(struct bitalloc *pool, int idx);
+
+/**
+ * Multiple freeing of the same index has no negative side effects,
+ * but will return -1.  returns -1 on failure, 0 on success.
+ */
+int ba_free(struct bitalloc *pool, int index);
+
+/**
+ * Returns the pool's free count
+ */
+int ba_free_count(struct bitalloc *pool);
+
+/**
+ * Returns the pool's in use count
+ */
+int ba_inuse_count(struct bitalloc *pool);
+
+#endif /* _BITALLOC_H_ */
index 6bafae5..06753ad 100644 (file)
@@ -7,8 +7,10 @@
 
 #include "tf_core.h"
 #include "tf_session.h"
+#include "tf_rm.h"
 #include "tf_msg.h"
 #include "tfp.h"
+#include "bitalloc.h"
 #include "bnxt.h"
 
 int
@@ -141,5 +143,83 @@ tf_open_session(struct tf                    *tfp,
        return rc;
 
  cleanup_close:
+       tf_close_session(tfp);
        return -EINVAL;
 }
+
+int
+tf_attach_session(struct tf *tfp __rte_unused,
+                 struct tf_attach_session_parms *parms __rte_unused)
+{
+#if (TF_SHARED == 1)
+       int rc;
+
+       if (tfp == NULL)
+               return -EINVAL;
+
+       /* - Open the shared memory for the attach_chan_name
+        * - Point to the shared session for this Device instance
+        * - Check that session is valid
+        * - Attach to the firmware so it can record there is more
+        *   than one client of the session.
+        */
+
+       if (tfp->session) {
+               if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
+                       rc = tf_msg_session_attach(tfp,
+                                                  parms->ctrl_chan_name,
+                                                  parms->session_id);
+               }
+       }
+#endif /* TF_SHARED */
+       return -1;
+}
+
+int
+tf_close_session(struct tf *tfp)
+{
+       int rc;
+       int rc_close = 0;
+       struct tf_session *tfs;
+       union tf_session_id session_id;
+
+       if (tfp == NULL || tfp->session == NULL)
+               return -EINVAL;
+
+       tfs = (struct tf_session *)(tfp->session->core_data);
+
+       if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
+               rc = tf_msg_session_close(tfp);
+               if (rc) {
+                       /* Log error */
+                       PMD_DRV_LOG(ERR,
+                                   "Message send failed, rc:%d\n",
+                                   rc);
+               }
+
+               /* Update the ref_count */
+               tfs->ref_count--;
+       }
+
+       session_id = tfs->session_id;
+
+       /* Final cleanup as we're last user of the session */
+       if (tfs->ref_count == 0) {
+               tfp_free(tfp->session->core_data);
+               tfp_free(tfp->session);
+               tfp->session = NULL;
+       }
+
+       PMD_DRV_LOG(INFO,
+                   "Session closed, session_id:%d\n",
+                   session_id.id);
+
+       PMD_DRV_LOG(INFO,
+                   "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
+                   session_id.internal.domain,
+                   session_id.internal.bus,
+                   session_id.internal.device,
+                   session_id.internal.fw_session_id);
+
+       return rc_close;
+}
index 2b68681..e05aea7 100644 (file)
 #include "hsi_struct_def_dpdk.h"
 #include "hwrm_tf.h"
 
+/**
+ * Endian converts min and max values from the HW response to the query
+ */
+#define TF_HW_RESP_TO_QUERY(query, index, response, element) do {            \
+       (query)->hw_query[index].min =                                       \
+               tfp_le_to_cpu_16(response. element ## _min);                 \
+       (query)->hw_query[index].max =                                       \
+               tfp_le_to_cpu_16(response. element ## _max);                 \
+} while (0)
+
+/**
+ * Endian converts the number of entries from the alloc to the request
+ */
+#define TF_HW_ALLOC_TO_REQ(alloc, index, request, element)                   \
+       (request. num_ ## element = tfp_cpu_to_le_16((alloc)->hw_num[index]))
+
+/**
+ * Endian converts the start and stride value from the free to the request
+ */
+#define TF_HW_FREE_TO_REQ(hw_entry, index, request, element) do {            \
+       request.element ## _start =                                          \
+               tfp_cpu_to_le_16(hw_entry[index].start);                     \
+       request.element ## _stride =                                         \
+               tfp_cpu_to_le_16(hw_entry[index].stride);                    \
+} while (0)
+
+/**
+ * Endian converts the start and stride from the HW response to the
+ * alloc
+ */
+#define TF_HW_RESP_TO_ALLOC(hw_entry, index, response, element) do {         \
+       hw_entry[index].start =                                              \
+               tfp_le_to_cpu_16(response.element ## _start);                \
+       hw_entry[index].stride =                                             \
+               tfp_le_to_cpu_16(response.element ## _stride);               \
+} while (0)
+
+/**
+ * Endian converts min and max values from the SRAM response to the
+ * query
+ */
+#define TF_SRAM_RESP_TO_QUERY(query, index, response, element) do {          \
+       (query)->sram_query[index].min =                                     \
+               tfp_le_to_cpu_16(response.element ## _min);                  \
+       (query)->sram_query[index].max =                                     \
+               tfp_le_to_cpu_16(response.element ## _max);                  \
+} while (0)
+
+/**
+ * Endian converts the number of entries from the action (alloc) to
+ * the request
+ */
+#define TF_SRAM_ALLOC_TO_REQ(action, index, request, element)                \
+       (request. num_ ## element = tfp_cpu_to_le_16((action)->sram_num[index]))
+
+/**
+ * Endian converts the start and stride value from the free to the request
+ */
+#define TF_SRAM_FREE_TO_REQ(sram_entry, index, request, element) do {        \
+       request.element ## _start =                                          \
+               tfp_cpu_to_le_16(sram_entry[index].start);                   \
+       request.element ## _stride =                                         \
+               tfp_cpu_to_le_16(sram_entry[index].stride);                  \
+} while (0)
+
+/**
+ * Endian converts the start and stride from the HW response to the
+ * alloc
+ */
+#define TF_SRAM_RESP_TO_ALLOC(sram_entry, index, response, element) do {     \
+       sram_entry[index].start =                                            \
+               tfp_le_to_cpu_16(response.element ## _start);                \
+       sram_entry[index].stride =                                           \
+               tfp_le_to_cpu_16(response.element ## _stride);               \
+} while (0)
+
 /**
  * Sends session open request to TF Firmware
  */
@@ -50,6 +126,45 @@ tf_msg_session_open(struct tf *tfp,
        return rc;
 }
 
+/**
+ * Sends session attach request to TF Firmware
+ */
+int
+tf_msg_session_attach(struct tf *tfp __rte_unused,
+                     char *ctrl_chan_name __rte_unused,
+                     uint8_t tf_fw_session_id __rte_unused)
+{
+       return -1;
+}
+
+/**
+ * Sends session close request to TF Firmware
+ */
+int
+tf_msg_session_close(struct tf *tfp)
+{
+       int rc;
+       struct hwrm_tf_session_close_input req = { 0 };
+       struct hwrm_tf_session_close_output resp = { 0 };
+       struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
+       struct tfp_send_msg_parms parms = { 0 };
+
+       /* Populate the request */
+       req.fw_session_id =
+               tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
+
+       parms.tf_type = HWRM_TF_SESSION_CLOSE;
+       parms.req_data = (uint32_t *)&req;
+       parms.req_size = sizeof(req);
+       parms.resp_data = (uint32_t *)&resp;
+       parms.resp_size = sizeof(resp);
+       parms.mailbox = TF_KONG_MB;
+
+       rc = tfp_send_msg_direct(tfp,
+                                &parms);
+       return rc;
+}
+
 /**
  * Sends session query config request to TF Firmware
  */
@@ -77,3 +192,289 @@ tf_msg_session_qcfg(struct tf *tfp)
                                 &parms);
        return rc;
 }
+
+/**
+ * Sends session HW resource query capability request to TF Firmware
+ */
+int
+tf_msg_session_hw_resc_qcaps(struct tf *tfp,
+                            enum tf_dir dir,
+                            struct tf_rm_hw_query *query)
+{
+       int rc;
+       struct tfp_send_msg_parms parms = { 0 };
+       struct tf_session_hw_resc_qcaps_input req = { 0 };
+       struct tf_session_hw_resc_qcaps_output resp = { 0 };
+       struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
+
+       memset(query, 0, sizeof(*query));
+
+       /* Populate the request */
+       req.fw_session_id =
+               tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
+       req.flags = tfp_cpu_to_le_16(dir);
+
+       MSG_PREP(parms,
+                TF_KONG_MB,
+                HWRM_TF,
+                HWRM_TFT_SESSION_HW_RESC_QCAPS,
+                req,
+                resp);
+
+       rc = tfp_send_msg_tunneled(tfp, &parms);
+       if (rc)
+               return rc;
+
+       /* Process the response */
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,
+                           l2_ctx_tcam_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_FUNC, resp,
+                           prof_func);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_TCAM, resp,
+                           prof_tcam_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_PROF_ID, resp,
+                           em_prof_id);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_REC, resp,
+                           em_record_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,
+                           wc_tcam_prof_id);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM, resp,
+                           wc_tcam_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_PROF, resp,
+                           meter_profiles);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_INST,
+                           resp, meter_inst);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_MIRROR, resp,
+                           mirrors);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_UPAR, resp,
+                           upar);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_SP_TCAM, resp,
+                           sp_tcam_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_FUNC, resp,
+                           l2_func);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_FKB, resp,
+                           flex_key_templ);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_TBL_SCOPE, resp,
+                           tbl_scope);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH0, resp,
+                           epoch0_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH1, resp,
+                           epoch1_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METADATA, resp,
+                           metadata);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_CT_STATE, resp,
+                           ct_state);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_PROF, resp,
+                           range_prof);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,
+                           range_entries);
+       TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_LAG_ENTRY, resp,
+                           lag_tbl_entries);
+
+       return tfp_le_to_cpu_32(parms.tf_resp_code);
+}
+
+/**
+ * Sends session HW resource allocation request to TF Firmware
+ */
+int
+tf_msg_session_hw_resc_alloc(struct tf *tfp __rte_unused,
+                            enum tf_dir dir,
+                            struct tf_rm_hw_alloc *hw_alloc __rte_unused,
+                            struct tf_rm_entry *hw_entry __rte_unused)
+{
+       int rc;
+       struct tfp_send_msg_parms parms = { 0 };
+       struct tf_session_hw_resc_alloc_input req = { 0 };
+       struct tf_session_hw_resc_alloc_output resp = { 0 };
+       struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
+
+       memset(hw_entry, 0, sizeof(*hw_entry));
+
+       /* Populate the request */
+       req.fw_session_id =
+               tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
+       req.flags = tfp_cpu_to_le_16(dir);
+
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,
+                          l2_ctx_tcam_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_FUNC, req,
+                          prof_func_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_TCAM, req,
+                          prof_tcam_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_PROF_ID, req,
+                          em_prof_id);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_REC, req,
+                          em_record_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,
+                          wc_tcam_prof_id);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM, req,
+                          wc_tcam_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_PROF, req,
+                          meter_profiles);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_INST, req,
+                          meter_inst);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_MIRROR, req,
+                          mirrors);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_UPAR, req,
+                          upar);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_SP_TCAM, req,
+                          sp_tcam_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_FUNC, req,
+                          l2_func);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_FKB, req,
+                          flex_key_templ);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_TBL_SCOPE, req,
+                          tbl_scope);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH0, req,
+                          epoch0_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH1, req,
+                          epoch1_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METADATA, req,
+                          metadata);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_CT_STATE, req,
+                          ct_state);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_PROF, req,
+                          range_prof);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_ENTRY, req,
+                          range_entries);
+       TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_LAG_ENTRY, req,
+                          lag_tbl_entries);
+
+       MSG_PREP(parms,
+                TF_KONG_MB,
+                HWRM_TF,
+                HWRM_TFT_SESSION_HW_RESC_ALLOC,
+                req,
+                resp);
+
+       rc = tfp_send_msg_tunneled(tfp, &parms);
+       if (rc)
+               return rc;
+
+       /* Process the response */
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,
+                           l2_ctx_tcam_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, resp,
+                           prof_func);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, resp,
+                           prof_tcam_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, resp,
+                           em_prof_id);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_REC, resp,
+                           em_record_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,
+                           wc_tcam_prof_id);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, resp,
+                           wc_tcam_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_PROF, resp,
+                           meter_profiles);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_INST, resp,
+                           meter_inst);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_MIRROR, resp,
+                           mirrors);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_UPAR, resp,
+                           upar);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, resp,
+                           sp_tcam_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, resp,
+                           l2_func);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_FKB, resp,
+                           flex_key_templ);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, resp,
+                           tbl_scope);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH0, resp,
+                           epoch0_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH1, resp,
+                           epoch1_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METADATA, resp,
+                           metadata);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_CT_STATE, resp,
+                           ct_state);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, resp,
+                           range_prof);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,
+                           range_entries);
+       TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, resp,
+                           lag_tbl_entries);
+
+       return tfp_le_to_cpu_32(parms.tf_resp_code);
+}
+
+/**
+ * Sends session HW resource free request to TF Firmware
+ */
+int
+tf_msg_session_hw_resc_free(struct tf *tfp,
+                           enum tf_dir dir,
+                           struct tf_rm_entry *hw_entry)
+{
+       int rc;
+       struct tfp_send_msg_parms parms = { 0 };
+       struct tf_session_hw_resc_free_input req = { 0 };
+       struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
+
+       memset(hw_entry, 0, sizeof(*hw_entry));
+
+       /* Populate the request */
+       req.fw_session_id =
+               tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
+       req.flags = tfp_cpu_to_le_16(dir);
+
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,
+                         l2_ctx_tcam_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, req,
+                         prof_func);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, req,
+                         prof_tcam_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, req,
+                         em_prof_id);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_REC, req,
+                         em_record_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,
+                         wc_tcam_prof_id);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, req,
+                         wc_tcam_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_PROF, req,
+                         meter_profiles);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_INST, req,
+                         meter_inst);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_MIRROR, req,
+                         mirrors);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_UPAR, req,
+                         upar);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, req,
+                         sp_tcam_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, req,
+                         l2_func);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_FKB, req,
+                         flex_key_templ);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, req,
+                         tbl_scope);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH0, req,
+                         epoch0_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH1, req,
+                         epoch1_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METADATA, req,
+                         metadata);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_CT_STATE, req,
+                         ct_state);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, req,
+                         range_prof);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, req,
+                         range_entries);
+       TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, req,
+                         lag_tbl_entries);
+
+       MSG_PREP_NO_RESP(parms,
+                        TF_KONG_MB,
+                        HWRM_TF,
+                        HWRM_TFT_SESSION_HW_RESC_FREE,
+                        req);
+
+       rc = tfp_send_msg_tunneled(tfp, &parms);
+       if (rc)
+               return rc;
+
+       return tfp_le_to_cpu_32(parms.tf_resp_code);
+}
index 20ebf2e..da5ccf3 100644 (file)
@@ -29,6 +29,34 @@ int tf_msg_session_open(struct tf *tfp,
                        char *ctrl_chan_name,
                        uint8_t *fw_session_id);
 
+/**
+ * Sends session close request to Firmware
+ *
+ * [in] session
+ *   Pointer to session handle
+ *
+ * [in] fw_session_id
+ *   Pointer to the fw_session_id that is assigned to the session at
+ *   time of session open
+ *
+ * Returns:
+ *
+ */
+int tf_msg_session_attach(struct tf *tfp,
+                         char *ctrl_channel_name,
+                         uint8_t tf_fw_session_id);
+
+/**
+ * Sends session close request to Firmware
+ *
+ * [in] session
+ *   Pointer to session handle
+ *
+ * Returns:
+ *
+ */
+int tf_msg_session_close(struct tf *tfp);
+
 /**
  * Sends session query config request to TF Firmware
  */
@@ -41,4 +69,18 @@ int tf_msg_session_hw_resc_qcaps(struct tf *tfp,
                                 enum tf_dir dir,
                                 struct tf_rm_hw_query *hw_query);
 
+/**
+ * Sends session HW resource allocation request to TF Firmware
+ */
+int tf_msg_session_hw_resc_alloc(struct tf *tfp,
+                                enum tf_dir dir,
+                                struct tf_rm_hw_alloc *hw_alloc,
+                                struct tf_rm_entry *hw_entry);
+
+/**
+ * Sends session HW resource free request to TF Firmware
+ */
+int tf_msg_session_hw_resc_free(struct tf *tfp,
+                               enum tf_dir dir,
+                               struct tf_rm_entry *hw_entry);
 #endif  /* _TF_MSG_H_ */
index 160abac..8dbb2f9 100644 (file)
@@ -6,11 +6,6 @@
 #ifndef _TF_RESOURCES_H_
 #define _TF_RESOURCES_H_
 
-/*
- * Hardware specific MAX values
- * NOTE: Should really come from the chip_cfg.h in some MAX form or HCAPI
- */
-
 /** HW Resource types
  */
 enum tf_resource_type_hw {
@@ -43,4 +38,23 @@ enum tf_resource_type_hw {
        TF_RESC_TYPE_HW_LAG_ENTRY,
        TF_RESC_TYPE_HW_MAX
 };
+
+/** HW Resource types
+ */
+enum tf_resource_type_sram {
+       TF_RESC_TYPE_SRAM_FULL_ACTION,
+       TF_RESC_TYPE_SRAM_MCG,
+       TF_RESC_TYPE_SRAM_ENCAP_8B,
+       TF_RESC_TYPE_SRAM_ENCAP_16B,
+       TF_RESC_TYPE_SRAM_ENCAP_64B,
+       TF_RESC_TYPE_SRAM_SP_SMAC,
+       TF_RESC_TYPE_SRAM_SP_SMAC_IPV4,
+       TF_RESC_TYPE_SRAM_SP_SMAC_IPV6,
+       TF_RESC_TYPE_SRAM_COUNTER_64B,
+       TF_RESC_TYPE_SRAM_NAT_SPORT,
+       TF_RESC_TYPE_SRAM_NAT_DPORT,
+       TF_RESC_TYPE_SRAM_NAT_S_IPV4,
+       TF_RESC_TYPE_SRAM_NAT_D_IPV4,
+       TF_RESC_TYPE_SRAM_MAX
+};
 #endif /* _TF_RESOURCES_H_ */
index 5164d6b..57ce19b 100644 (file)
@@ -8,10 +8,52 @@
 
 #include "tf_resources.h"
 #include "tf_core.h"
+#include "bitalloc.h"
 
 struct tf;
 struct tf_session;
 
+/* Internal macro to determine appropriate allocation pools based on
+ * DIRECTION parm, also performs error checking for DIRECTION parm. The
+ * SESSION_POOL and SESSION pointers are set appropriately upon
+ * successful return (the GLOBAL_POOL is used to globally manage
+ * resource allocation and the SESSION_POOL is used to track the
+ * resources that have been allocated to the session)
+ *
+ * parameters:
+ *   struct tfp        *tfp
+ *   enum tf_dir        direction
+ *   struct bitalloc  **session_pool
+ *   string             base_pool_name - used to form pointers to the
+ *                                      appropriate bit allocation
+ *                                      pools, both directions of the
+ *                                      session pools must have same
+ *                                      base name, for example if
+ *                                      POOL_NAME is feat_pool: - the
+ *                                      ptr's to the session pools
+ *                                      are feat_pool_rx feat_pool_tx
+ *
+ *  int                  rc - return code
+ *                           0 - Success
+ *                          -1 - invalid DIRECTION parm
+ */
+#define TF_RM_GET_POOLS(tfs, direction, session_pool, pool_name, rc) do { \
+               (rc) = 0;                                               \
+               if ((direction) == TF_DIR_RX) {                         \
+                       *(session_pool) = (tfs)->pool_name ## _RX;      \
+               } else if ((direction) == TF_DIR_TX) {                  \
+                       *(session_pool) = (tfs)->pool_name ## _TX;      \
+               } else {                                                \
+                       rc = -1;                                        \
+               }                                                       \
+       } while (0)
+
+#define TF_RM_GET_POOLS_RX(tfs, session_pool, pool_name)       \
+       (*(session_pool) = (tfs)->pool_name ## _RX)
+
+#define TF_RM_GET_POOLS_TX(tfs, session_pool, pool_name)       \
+       (*(session_pool) = (tfs)->pool_name ## _TX)
+
 /**
  * Resource query single entry
  */
@@ -22,6 +64,16 @@ struct tf_rm_query_entry {
        uint16_t max;
 };
 
+/**
+ * Resource single entry
+ */
+struct tf_rm_entry {
+       /** Starting index of the allocated resource */
+       uint16_t start;
+       /** Number of allocated elements */
+       uint16_t stride;
+};
+
 /**
  * Resource query array of HW entities
  */
@@ -30,4 +82,65 @@ struct tf_rm_hw_query {
        struct tf_rm_query_entry hw_query[TF_RESC_TYPE_HW_MAX];
 };
 
+/**
+ * Resource allocation array of HW entities
+ */
+struct tf_rm_hw_alloc {
+       /** array of HW resource entries */
+       uint16_t hw_num[TF_RESC_TYPE_HW_MAX];
+};
+
+/**
+ * Resource query array of SRAM entities
+ */
+struct tf_rm_sram_query {
+       /** array of SRAM resource entries */
+       struct tf_rm_query_entry sram_query[TF_RESC_TYPE_SRAM_MAX];
+};
+
+/**
+ * Resource allocation array of SRAM entities
+ */
+struct tf_rm_sram_alloc {
+       /** array of SRAM resource entries */
+       uint16_t sram_num[TF_RESC_TYPE_SRAM_MAX];
+};
+
+/**
+ * Initializes the Resource Manager and the associated database
+ * entries for HW and SRAM resources. Must be called before any other
+ * Resource Manager functions.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ */
+void tf_rm_init(struct tf *tfp);
+
+/**
+ * Allocates and validates both HW and SRAM resources per the NVM
+ * configuration. If any allocation fails all resources for the
+ * session is deallocated.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_rm_allocate_validate(struct tf *tfp);
+
+/**
+ * Closes the Resource Manager and frees all allocated resources per
+ * the associated database.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ *   - (-ENOTEMPTY) if resources are not cleaned up before close
+ */
+int tf_rm_close(struct tf *tfp);
 #endif /* TF_RM_H_ */
index 32e53c0..651d3ee 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include "bitalloc.h"
 #include "tf_core.h"
 #include "tf_rm.h"