eal: remove sys/queue.h from public headers
[dpdk.git] / drivers / net / bnxt / tf_core / tf_rm.c
index 30313e2..dd537aa 100644 (file)
@@ -1,11 +1,12 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019-2020 Broadcom
+ * Copyright(c) 2019-2021 Broadcom
  * All rights reserved.
  */
 
 #include <string.h>
 
 #include <rte_common.h>
+#include <rte_debug.h>
 
 #include <cfa_resource_types.h>
 
@@ -36,15 +37,29 @@ struct tf_rm_element {
         */
        uint16_t hcapi_type;
 
+       /**
+        * Resource slices.  How many slices will fit in the
+        * resource pool chunk size.
+        */
+       uint8_t slices;
+
        /**
         * HCAPI RM allocated range information for the element.
         */
        struct tf_rm_alloc_info alloc;
 
+       /**
+        * If cfg_type == HCAPI_BA_CHILD, this field indicates
+        * the parent module subtype for look up into the parent pool.
+        * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
+        * module subtype of TF_MODULE_TYPE_TABLE.
+        */
+       uint16_t parent_subtype;
+
        /**
         * Bit allocator pool for the element. Pool size is controlled
         * by the struct tf_session_resources at time of session creation.
-        * Null indicates that the element is not used for the device.
+        * Null indicates that the pool is not used for the element.
         */
        struct bitalloc *pool;
 };
@@ -66,7 +81,7 @@ struct tf_rm_new_db {
        /**
         * Module type, used for logging purposes.
         */
-       enum tf_device_module_type type;
+       enum tf_module_type module;
 
        /**
         * The DB consists of an array of elements
@@ -99,7 +114,7 @@ struct tf_rm_new_db {
  */
 static void
 tf_rm_count_hcapi_reservations(enum tf_dir dir,
-                              enum tf_device_module_type type,
+                              enum tf_module_type module,
                               struct tf_rm_element_cfg *cfg,
                               uint16_t *reservations,
                               uint16_t count,
@@ -109,8 +124,7 @@ tf_rm_count_hcapi_reservations(enum tf_dir dir,
        uint16_t cnt = 0;
 
        for (i = 0; i < count; i++) {
-               if ((cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
-                    cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) &&
+               if (cfg[i].cfg_type != TF_RM_ELEM_CFG_NULL &&
                    reservations[i] > 0)
                        cnt++;
 
@@ -119,14 +133,14 @@ tf_rm_count_hcapi_reservations(enum tf_dir dir,
                 * split configuration array thus it would fail for
                 * this type of check.
                 */
-               if (type != TF_DEVICE_MODULE_TYPE_EM &&
+               if (module != TF_MODULE_TYPE_EM &&
                    cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL &&
                    reservations[i] > 0) {
                        TFP_DRV_LOG(ERR,
                                "%s, %s, %s allocation of %d not supported\n",
-                               tf_device_module_type_2_str(type),
+                               tf_module_2_str(module),
                                tf_dir_2_str(dir),
-                               tf_device_module_type_subtype_2_str(type, i),
+                               tf_module_subtype_2_str(module, i),
                                reservations[i]);
                }
        }
@@ -155,8 +169,10 @@ enum tf_rm_adjust_type {
  * [in] action
  *   Adjust action
  *
- * [in] db_index
- *   DB index for the element type
+ * [in] subtype
+ *   TF module subtype used as an index into the database.
+ *   An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
+ *   module subtype of TF_MODULE_TYPE_TABLE.
  *
  * [in] index
  *   Index to convert
@@ -171,14 +187,14 @@ enum tf_rm_adjust_type {
 static int
 tf_rm_adjust_index(struct tf_rm_element *db,
                   enum tf_rm_adjust_type action,
-                  uint32_t db_index,
+                  uint32_t subtype,
                   uint32_t index,
                   uint32_t *adj_index)
 {
        int rc = 0;
        uint32_t base_index;
 
-       base_index = db[db_index].alloc.entry.start;
+       base_index = db[subtype].alloc.entry.start;
 
        switch (action) {
        case TF_RM_ADJUST_RM_BASE:
@@ -200,7 +216,7 @@ tf_rm_adjust_index(struct tf_rm_element *db,
  * [in] dir
  *   Receive or transmit direction
  *
- * [in] type
+ * [in] module
  *   Type of Device Module
  *
  * [in] count
@@ -211,9 +227,10 @@ tf_rm_adjust_index(struct tf_rm_element *db,
  *   the DB in which this function is used. Each entry holds residual
  *   value for that entry.
  */
+#if (TF_RM_DEBUG == 1)
 static void
 tf_rm_log_residuals(enum tf_dir dir,
-                   enum tf_device_module_type type,
+                   enum tf_module_type module,
                    uint16_t count,
                    uint16_t *residuals)
 {
@@ -224,14 +241,14 @@ tf_rm_log_residuals(enum tf_dir dir,
         */
        for (i = 0; i < count; i++) {
                if (residuals[i] != 0)
-                       TFP_DRV_LOG(ERR,
+                       TFP_DRV_LOG(INFO,
                                "%s, %s was not cleaned up, %d outstanding\n",
                                tf_dir_2_str(dir),
-                               tf_device_module_type_subtype_2_str(type, i),
+                               tf_module_subtype_2_str(module, i),
                                residuals[i]);
        }
 }
-
+#endif /* TF_RM_DEBUG == 1 */
 /**
  * Performs a check of the passed in DB for any lingering elements. If
  * a resource type was found to not have been cleaned up by the caller
@@ -294,7 +311,7 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
        iparms.rm_db = rm_db;
        iparms.count = &count;
        for (i = 0, found = 0; i < rm_db->num_entries; i++) {
-               iparms.db_index = i;
+               iparms.subtype = i;
                rc = tf_rm_get_inuse_count(&iparms);
                /* Not a device supported entry, just skip */
                if (rc == -ENOTSUP)
@@ -328,13 +345,13 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
                for (i = 0, f = 0; i < rm_db->num_entries; i++) {
                        if (residuals[i] == 0)
                                continue;
-                       aparms.db_index = i;
+                       aparms.subtype = i;
                        aparms.info = &info;
                        rc = tf_rm_get_info(&aparms);
                        if (rc)
                                goto cleanup_all;
 
-                       hparms.db_index = i;
+                       hparms.subtype = i;
                        rc = tf_rm_get_hcapi_type(&hparms);
                        if (rc)
                                goto cleanup_all;
@@ -347,11 +364,12 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
                *resv_size = found;
        }
 
+#if (TF_RM_DEBUG == 1)
        tf_rm_log_residuals(rm_db->dir,
-                           rm_db->type,
+                           rm_db->module,
                            rm_db->num_entries,
                            residuals);
-
+#endif
        tfp_free((void *)residuals);
        *resv = local_resv;
 
@@ -366,16 +384,132 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
        return rc;
 }
 
+/**
+ * Some resources do not have a 1:1 mapping between the Truflow type and the cfa
+ * resource type (HCAPI RM).  These resources have multiple Truflow types which
+ * map to a single HCAPI RM type.  In order to support this, one Truflow type
+ * sharing the HCAPI resources is designated the parent.  All other Truflow
+ * types associated with that HCAPI RM type are designated the children.
+ *
+ * This function updates the resource counts of any HCAPI_BA_PARENT with the
+ * counts of the HCAPI_BA_CHILDREN.  These are read from the alloc_cnt and
+ * written back to the req_cnt.
+ *
+ * [in] cfg
+ *   Pointer to an array of module specific Truflow type indexed RM cfg items
+ *
+ * [in] alloc_cnt
+ *   Pointer to the tf_open_session() configured array of module specific
+ *   Truflow type indexed requested counts.
+ *
+ * [in/out] req_cnt
+ *   Pointer to the location to put the updated resource counts.
+ *
+ * Returns:
+ *     0          - Success
+ *     -          - Failure if negative
+ */
+static int
+tf_rm_update_parent_reservations(struct tf *tfp,
+                                struct tf_dev_info *dev,
+                                struct tf_rm_element_cfg *cfg,
+                                uint16_t *alloc_cnt,
+                                uint16_t num_elements,
+                                uint16_t *req_cnt,
+                                bool shared_session)
+{
+       int parent, child;
+       const char *type_str;
+
+       /* Search through all the elements */
+       for (parent = 0; parent < num_elements; parent++) {
+               uint16_t combined_cnt = 0;
+
+               /* If I am a parent */
+               if (cfg[parent].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
+                       uint8_t p_slices = 1;
+
+                       /* Shared session doesn't support slices */
+                       if (!shared_session)
+                               p_slices = cfg[parent].slices;
+
+                       RTE_ASSERT(p_slices);
+
+                       combined_cnt = alloc_cnt[parent] / p_slices;
+
+                       if (alloc_cnt[parent] % p_slices)
+                               combined_cnt++;
+
+                       if (alloc_cnt[parent]) {
+                               dev->ops->tf_dev_get_resource_str(tfp,
+                                                        cfg[parent].hcapi_type,
+                                                        &type_str);
+#if (TF_RM_DEBUG == 1)
+                               printf("%s:%s cnt(%d) slices(%d)\n",
+                                      type_str, tf_tbl_type_2_str(parent),
+                                      alloc_cnt[parent], p_slices);
+#endif /* (TF_RM_DEBUG == 1) */
+                       }
+
+                       /* Search again through all the elements */
+                       for (child = 0; child < num_elements; child++) {
+                               /* If this is one of my children */
+                               if (cfg[child].cfg_type ==
+                                   TF_RM_ELEM_CFG_HCAPI_BA_CHILD &&
+                                   cfg[child].parent_subtype == parent &&
+                                   alloc_cnt[child]) {
+                                       uint8_t c_slices = 1;
+                                       uint16_t cnt = 0;
+
+                                       if (!shared_session)
+                                               c_slices = cfg[child].slices;
+
+                                       RTE_ASSERT(c_slices);
+
+                                       dev->ops->tf_dev_get_resource_str(tfp,
+                                                         cfg[child].hcapi_type,
+                                                          &type_str);
+#if (TF_RM_DEBUG == 1)
+                                       printf("%s:%s cnt(%d) slices(%d)\n",
+                                              type_str,
+                                              tf_tbl_type_2_str(child),
+                                              alloc_cnt[child],
+                                              c_slices);
+#endif /* (TF_RM_DEBUG == 1) */
+                                       /* Increment the parents combined count
+                                        * with each child's count adjusted for
+                                        * number of slices per RM alloc item.
+                                        */
+                                       cnt = alloc_cnt[child] / c_slices;
+
+                                       if (alloc_cnt[child] % c_slices)
+                                               cnt++;
+
+                                       combined_cnt += cnt;
+                                       /* Clear the requested child count */
+                                       req_cnt[child] = 0;
+                               }
+                       }
+                       /* Save the parent count to be requested */
+                       req_cnt[parent] = combined_cnt;
+#if (TF_RM_DEBUG == 1)
+                       printf("%s calculated total:%d\n\n",
+                              type_str, req_cnt[parent]);
+#endif /* (TF_RM_DEBUG == 1) */
+               }
+       }
+       return 0;
+}
+
 int
 tf_rm_create_db(struct tf *tfp,
                struct tf_rm_create_db_parms *parms)
 {
        int rc;
-       int i;
-       int j;
        struct tf_session *tfs;
        struct tf_dev_info *dev;
-       uint16_t max_types;
+       int i, j;
+       uint16_t max_types, hcapi_items, *req_cnt;
        struct tfp_calloc_parms cparms;
        struct tf_rm_resc_req_entry *query;
        enum tf_rm_resc_resv_strategy resv_strategy;
@@ -384,12 +518,12 @@ tf_rm_create_db(struct tf *tfp,
        struct tf_rm_new_db *rm_db;
        struct tf_rm_element *db;
        uint32_t pool_size;
-       uint16_t hcapi_items;
+       bool shared_session = 0;
 
        TF_CHECK_PARMS2(tfp, parms);
 
        /* Retrieve the session information */
-       rc = tf_session_get_session(tfp, &tfs);
+       rc = tf_session_get_session_internal(tfp, &tfs);
        if (rc)
                return rc;
 
@@ -400,9 +534,8 @@ tf_rm_create_db(struct tf *tfp,
 
        /* Need device max number of elements for the RM QCAPS */
        rc = dev->ops->tf_dev_get_max_types(tfp, &max_types);
-       if (rc)
-               return rc;
 
+       /* Allocate memory for RM QCAPS request */
        cparms.nitems = max_types;
        cparms.size = sizeof(struct tf_rm_resc_req_entry);
        cparms.alignment = 0;
@@ -414,6 +547,7 @@ tf_rm_create_db(struct tf *tfp,
 
        /* Get Firmware Capabilities */
        rc = tf_msg_session_resc_qcaps(tfp,
+                                      dev,
                                       parms->dir,
                                       max_types,
                                       query,
@@ -421,6 +555,31 @@ tf_rm_create_db(struct tf *tfp,
        if (rc)
                return rc;
 
+       /* Copy requested counts (alloc_cnt) from tf_open_session() to local
+        * copy (req_cnt) so that it can be updated if required.
+        */
+
+       cparms.nitems = parms->num_elements;
+       cparms.size = sizeof(uint16_t);
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+
+       req_cnt = (uint16_t *)cparms.mem_va;
+
+       tfp_memcpy(req_cnt, parms->alloc_cnt,
+                  parms->num_elements * sizeof(uint16_t));
+
+       shared_session = tf_session_is_shared_session(tfs);
+
+       /* Update the req_cnt based upon the element configuration
+        */
+       tf_rm_update_parent_reservations(tfp, dev, parms->cfg,
+                                        parms->alloc_cnt,
+                                        parms->num_elements,
+                                        req_cnt,
+                                        shared_session);
+
        /* Process capabilities against DB requirements. However, as a
         * DB can hold elements that are not HCAPI we can reduce the
         * req msg content by removing those out of the request yet
@@ -428,22 +587,19 @@ tf_rm_create_db(struct tf *tfp,
         * remove entries where there are no request for elements.
         */
        tf_rm_count_hcapi_reservations(parms->dir,
-                                      parms->type,
+                                      parms->module,
                                       parms->cfg,
-                                      parms->alloc_cnt,
+                                      req_cnt,
                                       parms->num_elements,
                                       &hcapi_items);
 
-       /* Handle the case where a DB create request really ends up
-        * being empty. Unsupported (if not rare) case but possible
-        * that no resources are necessary for a 'direction'.
-        */
        if (hcapi_items == 0) {
-               TFP_DRV_LOG(ERR,
-                       "%s: DB create request for Zero elements, DB Type:%s\n",
+#if (TF_RM_DEBUG == 1)
+               TFP_DRV_LOG(INFO,
+                       "%s: module: %s Empty RM DB create request\n",
                        tf_dir_2_str(parms->dir),
-                       tf_device_module_type_2_str(parms->type));
-
+                       tf_module_2_str(parms->module));
+#endif
                parms->rm_db = NULL;
                return -ENOMEM;
        }
@@ -465,39 +621,47 @@ tf_rm_create_db(struct tf *tfp,
 
        /* Build the request */
        for (i = 0, j = 0; i < parms->num_elements; i++) {
-               /* Skip any non HCAPI cfg elements */
-               if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
-                   parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) {
-                       /* Only perform reservation for entries that
-                        * has been requested
-                        */
-                       if (parms->alloc_cnt[i] == 0)
-                               continue;
+               struct tf_rm_element_cfg *cfg = &parms->cfg[i];
+               uint16_t hcapi_type = cfg->hcapi_type;
 
-                       /* Verify that we can get the full amount
-                        * allocated per the qcaps availability.
+               /* Only perform reservation for requested entries
+                */
+               if (req_cnt[i] == 0)
+                       continue;
+
+               /* Skip any children in the request */
+               if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI ||
+                   cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
+                   cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
+
+                       /* Verify that we can get the full amount per qcaps.
                         */
-                       if (parms->alloc_cnt[i] <=
-                           query[parms->cfg[i].hcapi_type].max) {
-                               req[j].type = parms->cfg[i].hcapi_type;
-                               req[j].min = parms->alloc_cnt[i];
-                               req[j].max = parms->alloc_cnt[i];
+                       if (req_cnt[i] <= query[hcapi_type].max) {
+                               req[j].type = hcapi_type;
+                               req[j].min = req_cnt[i];
+                               req[j].max = req_cnt[i];
                                j++;
                        } else {
+                               const char *type_str;
+
+                               dev->ops->tf_dev_get_resource_str(tfp,
+                                                             hcapi_type,
+                                                             &type_str);
                                TFP_DRV_LOG(ERR,
-                                           "%s: Resource failure, type:%d\n",
-                                           tf_dir_2_str(parms->dir),
-                                           parms->cfg[i].hcapi_type);
-                               TFP_DRV_LOG(ERR,
-                                       "req:%d, avail:%d\n",
-                                       parms->alloc_cnt[i],
-                                       query[parms->cfg[i].hcapi_type].max);
+                                       "Failure, %s:%d:%s req:%d avail:%d\n",
+                                       tf_dir_2_str(parms->dir),
+                                       hcapi_type, type_str,
+                                       req_cnt[i],
+                                       query[hcapi_type].max);
                                return -EINVAL;
                        }
                }
        }
 
+       /* Allocate all resources for the module type
+        */
        rc = tf_msg_session_resc_alloc(tfp,
+                                      dev,
                                       parms->dir,
                                       hcapi_items,
                                       req,
@@ -523,32 +687,46 @@ tf_rm_create_db(struct tf *tfp,
 
        db = rm_db->db;
        for (i = 0, j = 0; i < parms->num_elements; i++) {
-               db[i].cfg_type = parms->cfg[i].cfg_type;
-               db[i].hcapi_type = parms->cfg[i].hcapi_type;
+               struct tf_rm_element_cfg *cfg = &parms->cfg[i];
+               const char *type_str;
+
+               dev->ops->tf_dev_get_resource_str(tfp,
+                                                 cfg->hcapi_type,
+                                                 &type_str);
 
-               /* Skip any non HCAPI types as we didn't include them
-                * in the reservation request.
+               db[i].cfg_type = cfg->cfg_type;
+               db[i].hcapi_type = cfg->hcapi_type;
+               db[i].slices = cfg->slices;
+
+               /* Save the parent subtype for later use to find the pool
                 */
-               if (parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI &&
-                   parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
-                       continue;
+               if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
+                       db[i].parent_subtype = cfg->parent_subtype;
 
                /* If the element didn't request an allocation no need
                 * to create a pool nor verify if we got a reservation.
                 */
-               if (parms->alloc_cnt[i] == 0)
+               if (req_cnt[i] == 0)
+                       continue;
+
+               /* Skip any children or invalid
+                */
+               if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI &&
+                   cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+                   cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT)
                        continue;
 
                /* If the element had requested an allocation and that
                 * allocation was a success (full amount) then
                 * allocate the pool.
                 */
-               if (parms->alloc_cnt[i] == resv[j].stride) {
+               if (req_cnt[i] == resv[j].stride) {
                        db[i].alloc.entry.start = resv[j].start;
                        db[i].alloc.entry.stride = resv[j].stride;
 
-                       /* Only allocate BA pool if so requested */
-                       if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) {
+                       /* Only allocate BA pool if a BA type not a child */
+                       if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
+                           cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
                                /* Create pool */
                                pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
                                             sizeof(struct bitalloc));
@@ -558,19 +736,21 @@ tf_rm_create_db(struct tf *tfp,
                                rc = tfp_calloc(&cparms);
                                if (rc) {
                                        TFP_DRV_LOG(ERR,
-                                            "%s: Pool alloc failed, type:%d\n",
-                                            tf_dir_2_str(parms->dir),
-                                            db[i].cfg_type);
+                                        "%s: Pool alloc failed, type:%d:%s\n",
+                                        tf_dir_2_str(parms->dir),
+                                        cfg->hcapi_type, type_str);
                                        goto fail;
                                }
                                db[i].pool = (struct bitalloc *)cparms.mem_va;
 
-                               rc = ba_init(db[i].pool, resv[j].stride);
+                               rc = ba_init(db[i].pool,
+                                            resv[j].stride,
+                                            !tf_session_is_shared_session(tfs));
                                if (rc) {
                                        TFP_DRV_LOG(ERR,
-                                            "%s: Pool init failed, type:%d\n",
-                                            tf_dir_2_str(parms->dir),
-                                            db[i].cfg_type);
+                                         "%s: Pool init failed, type:%d:%s\n",
+                                         tf_dir_2_str(parms->dir),
+                                         cfg->hcapi_type, type_str);
                                        goto fail;
                                }
                        }
@@ -580,32 +760,28 @@ tf_rm_create_db(struct tf *tfp,
                         * all elements, not any less.
                         */
                        TFP_DRV_LOG(ERR,
-                                   "%s: Alloc failed, type:%d\n",
-                                   tf_dir_2_str(parms->dir),
-                                   db[i].cfg_type);
-                       TFP_DRV_LOG(ERR,
-                                   "req:%d, alloc:%d\n",
-                                   parms->alloc_cnt[i],
-                                   resv[j].stride);
+                                   "%s: Alloc failed %d:%s req:%d, alloc:%d\n",
+                                   tf_dir_2_str(parms->dir), cfg->hcapi_type,
+                                   type_str, req_cnt[i], resv[j].stride);
                        goto fail;
                }
        }
 
        rm_db->num_entries = parms->num_elements;
        rm_db->dir = parms->dir;
-       rm_db->type = parms->type;
+       rm_db->module = parms->module;
        *parms->rm_db = (void *)rm_db;
 
 #if (TF_RM_DEBUG == 1)
-       printf("%s: type:%d num_entries:%d\n",
+
+       printf("%s: module:%s\n",
               tf_dir_2_str(parms->dir),
-              parms->type,
-              i);
+              tf_module_2_str(parms->module));
 #endif /* (TF_RM_DEBUG == 1) */
 
        tfp_free((void *)req);
        tfp_free((void *)resv);
-
+       tfp_free((void *)req_cnt);
        return 0;
 
  fail:
@@ -614,11 +790,251 @@ tf_rm_create_db(struct tf *tfp,
        tfp_free((void *)db->pool);
        tfp_free((void *)db);
        tfp_free((void *)rm_db);
+       tfp_free((void *)req_cnt);
        parms->rm_db = NULL;
 
        return -EINVAL;
 }
 
+int
+tf_rm_create_db_no_reservation(struct tf *tfp,
+                              struct tf_rm_create_db_parms *parms)
+{
+       int rc;
+       struct tf_session *tfs;
+       struct tf_dev_info *dev;
+       int i, j;
+       uint16_t hcapi_items, *req_cnt;
+       struct tfp_calloc_parms cparms;
+       struct tf_rm_resc_req_entry *req;
+       struct tf_rm_resc_entry *resv;
+       struct tf_rm_new_db *rm_db;
+       struct tf_rm_element *db;
+       uint32_t pool_size;
+
+       TF_CHECK_PARMS2(tfp, parms);
+
+       /* Retrieve the session information */
+       rc = tf_session_get_session_internal(tfp, &tfs);
+       if (rc)
+               return rc;
+
+       /* Retrieve device information */
+       rc = tf_session_get_device(tfs, &dev);
+       if (rc)
+               return rc;
+
+       /* Copy requested counts (alloc_cnt) from tf_open_session() to local
+        * copy (req_cnt) so that it can be updated if required.
+        */
+
+       cparms.nitems = parms->num_elements;
+       cparms.size = sizeof(uint16_t);
+       cparms.alignment = 0;
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+
+       req_cnt = (uint16_t *)cparms.mem_va;
+
+       tfp_memcpy(req_cnt, parms->alloc_cnt,
+                  parms->num_elements * sizeof(uint16_t));
+
+       /* Process capabilities against DB requirements. However, as a
+        * DB can hold elements that are not HCAPI we can reduce the
+        * req msg content by removing those out of the request yet
+        * the DB holds them all as to give a fast lookup. We can also
+        * remove entries where there are no request for elements.
+        */
+       tf_rm_count_hcapi_reservations(parms->dir,
+                                      parms->module,
+                                      parms->cfg,
+                                      req_cnt,
+                                      parms->num_elements,
+                                      &hcapi_items);
+
+       if (hcapi_items == 0) {
+               TFP_DRV_LOG(ERR,
+                       "%s: module:%s Empty RM DB create request\n",
+                       tf_dir_2_str(parms->dir),
+                       tf_module_2_str(parms->module));
+
+               parms->rm_db = NULL;
+               return -ENOMEM;
+       }
+
+       /* Alloc request, alignment already set */
+       cparms.nitems = (size_t)hcapi_items;
+       cparms.size = sizeof(struct tf_rm_resc_req_entry);
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+       req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
+
+       /* Alloc reservation, alignment and nitems already set */
+       cparms.size = sizeof(struct tf_rm_resc_entry);
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+       resv = (struct tf_rm_resc_entry *)cparms.mem_va;
+
+       /* Build the request */
+       for (i = 0, j = 0; i < parms->num_elements; i++) {
+               struct tf_rm_element_cfg *cfg = &parms->cfg[i];
+               uint16_t hcapi_type = cfg->hcapi_type;
+
+               /* Only perform reservation for requested entries
+                */
+               if (req_cnt[i] == 0)
+                       continue;
+
+               /* Skip any children in the request */
+               if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI ||
+                   cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
+                   cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
+                       req[j].type = hcapi_type;
+                       req[j].min = req_cnt[i];
+                       req[j].max = req_cnt[i];
+                       j++;
+               }
+       }
+
+       /* Get all resources info for the module type
+        */
+       rc = tf_msg_session_resc_info(tfp,
+                                     dev,
+                                     parms->dir,
+                                     hcapi_items,
+                                     req,
+                                     resv);
+       if (rc)
+               return rc;
+
+       /* Build the RM DB per the request */
+       cparms.nitems = 1;
+       cparms.size = sizeof(struct tf_rm_new_db);
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+       rm_db = (void *)cparms.mem_va;
+
+       /* Build the DB within RM DB */
+       cparms.nitems = parms->num_elements;
+       cparms.size = sizeof(struct tf_rm_element);
+       rc = tfp_calloc(&cparms);
+       if (rc)
+               return rc;
+       rm_db->db = (struct tf_rm_element *)cparms.mem_va;
+
+       db = rm_db->db;
+       for (i = 0, j = 0; i < parms->num_elements; i++) {
+               struct tf_rm_element_cfg *cfg = &parms->cfg[i];
+               const char *type_str;
+
+               dev->ops->tf_dev_get_resource_str(tfp,
+                                                 cfg->hcapi_type,
+                                                 &type_str);
+
+               db[i].cfg_type = cfg->cfg_type;
+               db[i].hcapi_type = cfg->hcapi_type;
+
+               /* Save the parent subtype for later use to find the pool
+                */
+               if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
+                       db[i].parent_subtype = cfg->parent_subtype;
+
+               /* If the element didn't request an allocation no need
+                * to create a pool nor verify if we got a reservation.
+                */
+               if (req_cnt[i] == 0)
+                       continue;
+
+               /* Skip any children or invalid
+                */
+               if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI &&
+                   cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+                   cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT)
+                       continue;
+
+               /* If the element had requested an allocation and that
+                * allocation was a success (full amount) then
+                * allocate the pool.
+                */
+               if (req_cnt[i] == resv[j].stride) {
+                       db[i].alloc.entry.start = resv[j].start;
+                       db[i].alloc.entry.stride = resv[j].stride;
+
+                       /* Only allocate BA pool if a BA type not a child */
+                       if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
+                           cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
+                               /* Create pool */
+                               pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
+                                            sizeof(struct bitalloc));
+                               /* Alloc request, alignment already set */
+                               cparms.nitems = pool_size;
+                               cparms.size = sizeof(struct bitalloc);
+                               rc = tfp_calloc(&cparms);
+                               if (rc) {
+                                       TFP_DRV_LOG(ERR,
+                                        "%s: Pool alloc failed, type:%d:%s\n",
+                                        tf_dir_2_str(parms->dir),
+                                        cfg->hcapi_type, type_str);
+                                       goto fail;
+                               }
+                               db[i].pool = (struct bitalloc *)cparms.mem_va;
+
+                               rc = ba_init(db[i].pool,
+                                            resv[j].stride,
+                                            !tf_session_is_shared_session(tfs));
+                               if (rc) {
+                                       TFP_DRV_LOG(ERR,
+                                         "%s: Pool init failed, type:%d:%s\n",
+                                         tf_dir_2_str(parms->dir),
+                                         cfg->hcapi_type, type_str);
+                                       goto fail;
+                               }
+                       }
+                       j++;
+               } else {
+                       /* Bail out as we want what we requested for
+                        * all elements, not any less.
+                        */
+                       TFP_DRV_LOG(ERR,
+                                   "%s: Alloc failed %d:%s req:%d, alloc:%d\n",
+                                   tf_dir_2_str(parms->dir), cfg->hcapi_type,
+                                   type_str, req_cnt[i], resv[j].stride);
+                       goto fail;
+               }
+       }
+
+       rm_db->num_entries = parms->num_elements;
+       rm_db->dir = parms->dir;
+       rm_db->module = parms->module;
+       *parms->rm_db = (void *)rm_db;
+
+#if (TF_RM_DEBUG == 1)
+
+       printf("%s: module:%s\n",
+              tf_dir_2_str(parms->dir),
+              tf_module_2_str(parms->module));
+#endif /* (TF_RM_DEBUG == 1) */
+
+       tfp_free((void *)req);
+       tfp_free((void *)resv);
+       tfp_free((void *)req_cnt);
+       return 0;
+
+ fail:
+       tfp_free((void *)req);
+       tfp_free((void *)resv);
+       tfp_free((void *)db->pool);
+       tfp_free((void *)db);
+       tfp_free((void *)rm_db);
+       tfp_free((void *)req_cnt);
+       parms->rm_db = NULL;
+
+       return -EINVAL;
+}
 int
 tf_rm_free_db(struct tf *tfp,
              struct tf_rm_free_db_parms *parms)
@@ -680,7 +1096,7 @@ tf_rm_free_db(struct tf *tfp,
                        TFP_DRV_LOG(ERR,
                                    "%s: Internal Flush error, module:%s\n",
                                    tf_dir_2_str(parms->dir),
-                                   tf_device_module_type_2_str(rm_db->type));
+                                   tf_module_2_str(rm_db->module));
        }
 
        /* No need to check for configuration type, even if we do not
@@ -693,6 +1109,54 @@ tf_rm_free_db(struct tf *tfp,
 
        return rc;
 }
+/**
+ * Get the bit allocator pool associated with the subtype and the db
+ *
+ * [in] rm_db
+ *   Pointer to the DB
+ *
+ * [in] subtype
+ *   Module subtype used to index into the module specific database.
+ *   An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
+ *   module subtype of TF_MODULE_TYPE_TABLE.
+ *
+ * [in/out] pool
+ *   Pointer to the bit allocator pool used
+ *
+ * [in/out] new_subtype
+ *   Pointer to the subtype of the actual pool used
+ * Returns:
+ *     0          - Success
+ *   - ENOTSUP    - Operation not supported
+ */
+static int
+tf_rm_get_pool(struct tf_rm_new_db *rm_db,
+              uint16_t subtype,
+              struct bitalloc **pool,
+              uint16_t *new_subtype)
+{
+       int rc = 0;
+       uint16_t tmp_subtype = subtype;
+
+       /* If we are a child, get the parent table index */
+       if (rm_db->db[subtype].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
+               tmp_subtype = rm_db->db[subtype].parent_subtype;
+
+       *pool = rm_db->db[tmp_subtype].pool;
+
+       /* Bail out if the pool is not valid, should never happen */
+       if (rm_db->db[tmp_subtype].pool == NULL) {
+               rc = -ENOTSUP;
+               TFP_DRV_LOG(ERR,
+                           "%s: Invalid pool for this type:%d, rc:%s\n",
+                           tf_dir_2_str(rm_db->dir),
+                           tmp_subtype,
+                           strerror(-rc));
+               return rc;
+       }
+       *new_subtype = tmp_subtype;
+       return rc;
+}
 
 int
 tf_rm_allocate(struct tf_rm_allocate_parms *parms)
@@ -702,35 +1166,33 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms)
        uint32_t index;
        struct tf_rm_new_db *rm_db;
        enum tf_rm_elem_cfg_type cfg_type;
+       struct bitalloc *pool;
+       uint16_t subtype;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
 
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
 
        /* Bail out if not controlled by RM */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
                return -ENOTSUP;
 
-       /* Bail out if the pool is not valid, should never happen */
-       if (rm_db->db[parms->db_index].pool == NULL) {
-               rc = -ENOTSUP;
-               TFP_DRV_LOG(ERR,
-                           "%s: Invalid pool for this type:%d, rc:%s\n",
-                           tf_dir_2_str(rm_db->dir),
-                           parms->db_index,
-                           strerror(-rc));
+       rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
+       if (rc)
                return rc;
-       }
-
        /*
         * priority  0: allocate from top of the tcam i.e. high
         * priority !0: allocate index from bottom i.e lowest
         */
        if (parms->priority)
-               id = ba_alloc_reverse(rm_db->db[parms->db_index].pool);
+               id = ba_alloc_reverse(pool);
        else
-               id = ba_alloc(rm_db->db[parms->db_index].pool);
+               id = ba_alloc(pool);
        if (id == BA_FAIL) {
                rc = -ENOMEM;
                TFP_DRV_LOG(ERR,
@@ -743,7 +1205,7 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms)
        /* Adjust for any non zero start value */
        rc = tf_rm_adjust_index(rm_db->db,
                                TF_RM_ADJUST_ADD_BASE,
-                               parms->db_index,
+                               subtype,
                                id,
                                &index);
        if (rc) {
@@ -755,6 +1217,8 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms)
        }
 
        *parms->index = index;
+       if (parms->base_index)
+               *parms->base_index = id;
 
        return rc;
 }
@@ -766,37 +1230,35 @@ tf_rm_free(struct tf_rm_free_parms *parms)
        uint32_t adj_index;
        struct tf_rm_new_db *rm_db;
        enum tf_rm_elem_cfg_type cfg_type;
+       struct bitalloc *pool;
+       uint16_t subtype;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
-
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
 
        /* Bail out if not controlled by RM */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
                return -ENOTSUP;
 
-       /* Bail out if the pool is not valid, should never happen */
-       if (rm_db->db[parms->db_index].pool == NULL) {
-               rc = -ENOTSUP;
-               TFP_DRV_LOG(ERR,
-                           "%s: Invalid pool for this type:%d, rc:%s\n",
-                           tf_dir_2_str(rm_db->dir),
-                           parms->db_index,
-                           strerror(-rc));
+       rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
+       if (rc)
                return rc;
-       }
 
        /* Adjust for any non zero start value */
        rc = tf_rm_adjust_index(rm_db->db,
                                TF_RM_ADJUST_RM_BASE,
-                               parms->db_index,
+                               subtype,
                                parms->index,
                                &adj_index);
        if (rc)
                return rc;
 
-       rc = ba_free(rm_db->db[parms->db_index].pool, adj_index);
+       rc = ba_free(pool, adj_index);
        /* No logging direction matters and that is not available here */
        if (rc)
                return rc;
@@ -811,38 +1273,37 @@ tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
        uint32_t adj_index;
        struct tf_rm_new_db *rm_db;
        enum tf_rm_elem_cfg_type cfg_type;
+       struct bitalloc *pool;
+       uint16_t subtype;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
-
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
 
        /* Bail out if not controlled by RM */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
                return -ENOTSUP;
 
-       /* Bail out if the pool is not valid, should never happen */
-       if (rm_db->db[parms->db_index].pool == NULL) {
-               rc = -ENOTSUP;
-               TFP_DRV_LOG(ERR,
-                           "%s: Invalid pool for this type:%d, rc:%s\n",
-                           tf_dir_2_str(rm_db->dir),
-                           parms->db_index,
-                           strerror(-rc));
+       rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
+       if (rc)
                return rc;
-       }
 
        /* Adjust for any non zero start value */
        rc = tf_rm_adjust_index(rm_db->db,
                                TF_RM_ADJUST_RM_BASE,
-                               parms->db_index,
+                               subtype,
                                parms->index,
                                &adj_index);
        if (rc)
                return rc;
 
-       *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
-                                    adj_index);
+       if (parms->base_index)
+               *parms->base_index = adj_index;
+       *parms->allocated = ba_inuse(pool, adj_index);
 
        return rc;
 }
@@ -854,22 +1315,58 @@ tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
        enum tf_rm_elem_cfg_type cfg_type;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
-
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
 
        /* Bail out if not controlled by HCAPI */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
-           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       if (cfg_type == TF_RM_ELEM_CFG_NULL)
                return -ENOTSUP;
 
        memcpy(parms->info,
-              &rm_db->db[parms->db_index].alloc,
+              &rm_db->db[parms->subtype].alloc,
               sizeof(struct tf_rm_alloc_info));
 
        return 0;
 }
 
+int
+tf_rm_get_all_info(struct tf_rm_get_alloc_info_parms *parms, int size)
+{
+       struct tf_rm_new_db *rm_db;
+       enum tf_rm_elem_cfg_type cfg_type;
+       struct tf_rm_alloc_info *info = parms->info;
+       int i;
+
+       TF_CHECK_PARMS1(parms);
+
+       /* No rm info available for this module type
+        */
+       if (!parms->rm_db)
+               return -ENOMEM;
+
+       rm_db = (struct tf_rm_new_db *)parms->rm_db;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       for (i = 0; i < size; i++) {
+               cfg_type = rm_db->db[i].cfg_type;
+
+               /* Bail out if not controlled by HCAPI */
+               if (cfg_type == TF_RM_ELEM_CFG_NULL) {
+                       info++;
+                       continue;
+               }
+
+               memcpy(info,
+                      &rm_db->db[i].alloc,
+                      sizeof(struct tf_rm_alloc_info));
+               info++;
+       }
+
+       return 0;
+}
+
 int
 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
 {
@@ -877,16 +1374,36 @@ tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
        enum tf_rm_elem_cfg_type cfg_type;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
+       rm_db = (struct tf_rm_new_db *)parms->rm_db;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
+
+       /* Bail out if not controlled by HCAPI */
+       if (cfg_type == TF_RM_ELEM_CFG_NULL)
+               return -ENOTSUP;
 
+       *parms->hcapi_type = rm_db->db[parms->subtype].hcapi_type;
+
+       return 0;
+}
+int
+tf_rm_get_slices(struct tf_rm_get_slices_parms *parms)
+{
+       struct tf_rm_new_db *rm_db;
+       enum tf_rm_elem_cfg_type cfg_type;
+
+       TF_CHECK_PARMS2(parms, parms->rm_db);
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
 
        /* Bail out if not controlled by HCAPI */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
-           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       if (cfg_type == TF_RM_ELEM_CFG_NULL)
                return -ENOTSUP;
 
-       *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
+       *parms->slices = rm_db->db[parms->subtype].slices;
 
        return 0;
 }
@@ -899,24 +1416,64 @@ tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
        enum tf_rm_elem_cfg_type cfg_type;
 
        TF_CHECK_PARMS2(parms, parms->rm_db);
-
        rm_db = (struct tf_rm_new_db *)parms->rm_db;
-       cfg_type = rm_db->db[parms->db_index].cfg_type;
+       TF_CHECK_PARMS1(rm_db->db);
 
-       /* Bail out if not controlled by RM */
-       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
+
+       /* Bail out if not a BA pool */
+       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
                return -ENOTSUP;
 
        /* Bail silently (no logging), if the pool is not valid there
         * was no elements allocated for it.
         */
-       if (rm_db->db[parms->db_index].pool == NULL) {
+       if (rm_db->db[parms->subtype].pool == NULL) {
                *parms->count = 0;
                return 0;
        }
 
-       *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
+       *parms->count = ba_inuse_count(rm_db->db[parms->subtype].pool);
 
        return rc;
+}
+/* Only used for table bulk get at this time
+ */
+int
+tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms)
+{
+       struct tf_rm_new_db *rm_db;
+       enum tf_rm_elem_cfg_type cfg_type;
+       uint32_t base_index;
+       uint32_t stride;
+       int rc = 0;
+       struct bitalloc *pool;
+       uint16_t subtype;
 
+       TF_CHECK_PARMS2(parms, parms->rm_db);
+       rm_db = (struct tf_rm_new_db *)parms->rm_db;
+       TF_CHECK_PARMS1(rm_db->db);
+
+       cfg_type = rm_db->db[parms->subtype].cfg_type;
+
+       /* Bail out if not a BA pool */
+       if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
+           cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
+               return -ENOTSUP;
+
+       rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
+       if (rc)
+               return rc;
+
+       base_index = rm_db->db[subtype].alloc.entry.start;
+       stride = rm_db->db[subtype].alloc.entry.stride;
+
+       if (parms->starting_index < base_index ||
+           parms->starting_index + parms->num_entries > base_index + stride)
+               return -EINVAL;
+
+       return rc;
 }