diff --git a/drivers/net/bnxt/tf_core/ll.c b/drivers/net/bnxt/tf_core/ll.c
index cd168a7970..f2bdff6b9e 100644
--- a/drivers/net/bnxt/tf_core/ll.c
+++ b/drivers/net/bnxt/tf_core/ll.c
@@ -13,6 +13,7 @@ void ll_init(struct ll *ll)
 {
 	ll->head = NULL;
 	ll->tail = NULL;
+	ll->cnt = 0;
 }
 
 /* insert entry in linked list */
@@ -30,6 +31,7 @@ void ll_insert(struct ll *ll,
 		entry->next->prev = entry;
 		ll->head = entry->next->prev;
 	}
+	ll->cnt++;
 }
 
 /* delete entry from linked list */
@@ -49,4 +51,5 @@ void ll_delete(struct ll *ll,
 		entry->prev->next = entry->next;
 		entry->next->prev = entry->prev;
 	}
+	ll->cnt--;
 }
diff --git a/drivers/net/bnxt/tf_core/ll.h b/drivers/net/bnxt/tf_core/ll.h
index 239478b4f8..9cf8f64ec2 100644
--- a/drivers/net/bnxt/tf_core/ll.h
+++ b/drivers/net/bnxt/tf_core/ll.h
@@ -8,6 +8,8 @@
 #ifndef _LL_H_
 #define _LL_H_
 
+#include <stdint.h>
+
 /* linked list entry */
 struct ll_entry {
 	struct ll_entry *prev;
@@ -18,6 +20,7 @@ struct ll_entry {
 struct ll {
 	struct ll_entry *head;
 	struct ll_entry *tail;
+	uint32_t cnt;
 };
 
 /**
@@ -28,7 +31,7 @@ struct ll {
 void ll_init(struct ll *ll);
 
 /**
- * Linked list insert
+ * Linked list insert head
  *
  * [in] ll, linked list where element is inserted
  * [in] entry, entry to be added
@@ -43,4 +46,49 @@ void ll_insert(struct ll *ll, struct ll_entry *entry);
  */
 void ll_delete(struct ll *ll, struct ll_entry *entry);
 
+/**
+ * Linked list return next entry without deleting it
+ *
+ * Useful in performing search
+ *
+ * [in] Entry in the list
+ */
+static inline struct ll_entry *ll_next(struct ll_entry *entry)
+{
+	return entry->next;
+}
+
+/**
+ * Linked list return the head of the list without removing it
+ *
+ * Useful in performing search
+ *
+ * [in] ll, linked list
+ */
+static inline struct ll_entry *ll_head(struct ll *ll)
+{
+	return ll->head;
+}
+
+/**
+ * Linked list return the tail of the list without removing it
+ *
+ * Useful in performing search
+ *
+ * [in] ll, linked list
+ */
+static inline struct ll_entry *ll_tail(struct ll *ll)
+{
+	return ll->tail;
+}
+
+/**
+ * Linked list return the number of entries in the list
+ *
+ * [in] ll, linked list
+ */
+static inline uint32_t ll_cnt(struct ll *ll)
+{
+	return ll->cnt;
+}
 #endif /* _LL_H_ */
diff --git a/drivers/net/bnxt/tf_core/meson.build b/drivers/net/bnxt/tf_core/meson.build
index f28e77ec2e..b7333a431b 100644
--- a/drivers/net/bnxt/tf_core/meson.build
+++ b/drivers/net/bnxt/tf_core/meson.build
@@ -16,6 +16,8 @@ sources += files(
         'stack.c',
         'tf_rm.c',
         'tf_tbl.c',
+	'tf_tbl_sram.c',
+	'tf_sram_mgr.c',
         'tf_em_common.c',
         'tf_em_host.c',
         'tf_em_internal.c',
diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c
index 5458f76e2d..936102c804 100644
--- a/drivers/net/bnxt/tf_core/tf_core.c
+++ b/drivers/net/bnxt/tf_core/tf_core.c
@@ -1079,17 +1079,16 @@ tf_alloc_tbl_entry(struct tf *tfp,
 				    strerror(-rc));
 			return rc;
 		}
-
-	} else {
-		if (dev->ops->tf_dev_alloc_tbl == NULL) {
-			rc = -EOPNOTSUPP;
+	} else if (dev->ops->tf_dev_is_sram_managed(tfp, parms->type)) {
+		rc = dev->ops->tf_dev_alloc_sram_tbl(tfp, &aparms);
+		if (rc) {
 			TFP_DRV_LOG(ERR,
-				    "%s: Operation not supported, rc:%s\n",
+				    "%s: SRAM table allocation failed, rc:%s\n",
 				    tf_dir_2_str(parms->dir),
 				    strerror(-rc));
-			return -EOPNOTSUPP;
+			return rc;
 		}
-
+	} else {
 		rc = dev->ops->tf_dev_alloc_tbl(tfp, &aparms);
 		if (rc) {
 			TFP_DRV_LOG(ERR,
@@ -1162,15 +1161,16 @@ tf_free_tbl_entry(struct tf *tfp,
 				    strerror(-rc));
 			return rc;
 		}
-	} else {
-		if (dev->ops->tf_dev_free_tbl == NULL) {
-			rc = -EOPNOTSUPP;
+	} else if (dev->ops->tf_dev_is_sram_managed(tfp, parms->type)) {
+		rc = dev->ops->tf_dev_free_sram_tbl(tfp, &fparms);
+		if (rc) {
 			TFP_DRV_LOG(ERR,
-				    "%s: Operation not supported, rc:%s\n",
+				    "%s: SRAM table free failed, rc:%s\n",
 				    tf_dir_2_str(parms->dir),
 				    strerror(-rc));
-			return -EOPNOTSUPP;
+			return rc;
 		}
+	} else {
 
 		rc = dev->ops->tf_dev_free_tbl(tfp, &fparms);
 		if (rc) {
@@ -1181,7 +1181,6 @@ tf_free_tbl_entry(struct tf *tfp,
 			return rc;
 		}
 	}
-
 	return 0;
 }
 
@@ -1244,6 +1243,15 @@ tf_set_tbl_entry(struct tf *tfp,
 				    strerror(-rc));
 			return rc;
 		}
+	}  else if (dev->ops->tf_dev_is_sram_managed(tfp, parms->type)) {
+		rc = dev->ops->tf_dev_set_sram_tbl(tfp, &sparms);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s: SRAM table set failed, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    strerror(-rc));
+			return rc;
+		}
 	} else {
 		if (dev->ops->tf_dev_set_tbl == NULL) {
 			rc = -EOPNOTSUPP;
@@ -1300,28 +1308,39 @@ tf_get_tbl_entry(struct tf *tfp,
 			    strerror(-rc));
 		return rc;
 	}
-
-	if (dev->ops->tf_dev_get_tbl == NULL) {
-		rc = -EOPNOTSUPP;
-		TFP_DRV_LOG(ERR,
-			    "%s: Operation not supported, rc:%s\n",
-			    tf_dir_2_str(parms->dir),
-			    strerror(-rc));
-		return -EOPNOTSUPP;
-	}
-
 	gparms.dir = parms->dir;
 	gparms.type = parms->type;
 	gparms.data = parms->data;
 	gparms.data_sz_in_bytes = parms->data_sz_in_bytes;
 	gparms.idx = parms->idx;
-	rc = dev->ops->tf_dev_get_tbl(tfp, &gparms);
-	if (rc) {
-		TFP_DRV_LOG(ERR,
-			    "%s: Table get failed, rc:%s\n",
-			    tf_dir_2_str(parms->dir),
-			    strerror(-rc));
-		return rc;
+
+	if (dev->ops->tf_dev_is_sram_managed(tfp, parms->type)) {
+		rc = dev->ops->tf_dev_get_sram_tbl(tfp, &gparms);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s: SRAM table get failed, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    strerror(-rc));
+			return rc;
+		}
+	} else {
+		if (dev->ops->tf_dev_get_tbl == NULL) {
+			rc = -EOPNOTSUPP;
+			TFP_DRV_LOG(ERR,
+				    "%s: Operation not supported, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    strerror(-rc));
+			return -EOPNOTSUPP;
+		}
+
+		rc = dev->ops->tf_dev_get_tbl(tfp, &gparms);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s: Table get failed, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    strerror(-rc));
+			return rc;
+		}
 	}
 
 	return rc;
@@ -1361,6 +1380,13 @@ tf_bulk_get_tbl_entry(struct tf *tfp,
 		return rc;
 	}
 
+	bparms.dir = parms->dir;
+	bparms.type = parms->type;
+	bparms.starting_idx = parms->starting_idx;
+	bparms.num_entries = parms->num_entries;
+	bparms.entry_sz_in_bytes = parms->entry_sz_in_bytes;
+	bparms.physical_mem_addr = parms->physical_mem_addr;
+
 	if (parms->type == TF_TBL_TYPE_EXT) {
 		/* Not supported, yet */
 		rc = -EOPNOTSUPP;
@@ -1370,10 +1396,17 @@ tf_bulk_get_tbl_entry(struct tf *tfp,
 			    strerror(-rc));
 
 		return rc;
+	} else if (dev->ops->tf_dev_is_sram_managed(tfp, parms->type)) {
+		rc = dev->ops->tf_dev_get_bulk_sram_tbl(tfp, &bparms);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s: SRAM table bulk get failed, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    strerror(-rc));
+		}
+		return rc;
 	}
 
-	/* Internal table type processing */
-
 	if (dev->ops->tf_dev_get_bulk_tbl == NULL) {
 		rc = -EOPNOTSUPP;
 		TFP_DRV_LOG(ERR,
@@ -1383,12 +1416,6 @@ tf_bulk_get_tbl_entry(struct tf *tfp,
 		return -EOPNOTSUPP;
 	}
 
-	bparms.dir = parms->dir;
-	bparms.type = parms->type;
-	bparms.starting_idx = parms->starting_idx;
-	bparms.num_entries = parms->num_entries;
-	bparms.entry_sz_in_bytes = parms->entry_sz_in_bytes;
-	bparms.physical_mem_addr = parms->physical_mem_addr;
 	rc = dev->ops->tf_dev_get_bulk_tbl(tfp, &bparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
@@ -1397,7 +1424,6 @@ tf_bulk_get_tbl_entry(struct tf *tfp,
 			    strerror(-rc));
 		return rc;
 	}
-
 	return rc;
 }
 
diff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h
index af8d13bd7e..fb02c2b161 100644
--- a/drivers/net/bnxt/tf_core/tf_core.h
+++ b/drivers/net/bnxt/tf_core/tf_core.h
@@ -65,6 +65,16 @@ enum tf_ext_mem_chan_type {
 	TF_EXT_MEM_CHAN_TYPE_MAX
 };
 
+/**
+ * WC TCAM number of slice per row that devices supported
+ */
+enum tf_wc_num_slice {
+	TF_WC_TCAM_1_SLICE_PER_ROW = 1,
+	TF_WC_TCAM_2_SLICE_PER_ROW = 2,
+	TF_WC_TCAM_4_SLICE_PER_ROW = 4,
+	TF_WC_TCAM_8_SLICE_PER_ROW = 8,
+};
+
 /**
  * EEM record AR helper
  *
@@ -670,6 +680,13 @@ struct tf_open_session_parms {
 	 */
 	void *bp;
 
+	/**
+	 * [in]
+	 *
+	 * The number of slices per row for WC TCAM entry.
+	 */
+	enum tf_wc_num_slice wc_num_slices;
+
 	/**
 	 * [out] shared_session_creator
 	 *
@@ -734,8 +751,6 @@ int tf_open_session(struct tf *tfp,
 /**
  * General internal resource info
  *
- * TODO: remove tf_rm_new_entry structure and use this structure
- * internally.
  */
 struct tf_resource_info {
 	uint16_t start;
@@ -1656,12 +1671,7 @@ struct tf_alloc_tbl_entry_parms {
  * entry of the indicated type for this TruFlow session.
  *
  * Allocates an index table record. This function will attempt to
- * allocate an entry or search an index table for a matching entry if
- * search is enabled (only the shadow copy of the table is accessed).
- *
- * If search is not enabled, the first available free entry is
- * returned. If search is enabled and a matching entry to entry_data
- * is found hit is set to TRUE and success is returned.
+ * allocate an index table entry.
  *
  * External types:
  *
@@ -1670,8 +1680,8 @@ struct tf_alloc_tbl_entry_parms {
  * Allocates an external index table action record.
  *
  * NOTE:
- * Implementation of the internals of this function will be a stack with push
- * and pop.
+ * Implementation of the internals of the external function will be a stack with
+ * push and pop.
  *
  * Returns success or failure code.
  */
@@ -1707,20 +1717,15 @@ struct tf_free_tbl_entry_parms {
  *
  * Internal types:
  *
- * If session has shadow_copy enabled the shadow DB is searched and if
- * found the element ref_cnt is decremented. If ref_cnt goes to
- * zero then the element is returned to the session pool.
- *
- * If the session does not have a shadow DB the element is free'ed and
- * given back to the session pool.
+ * The element is freed and given back to the session pool.
  *
  * External types:
  *
- * Free's an external index table action record.
+ * Frees an external index table action record.
  *
  * NOTE:
- * Implementation of the internals of this function will be a stack with push
- * and pop.
+ * Implementation of the internals of the external table will be a stack with
+ * push and pop.
  *
  * Returns success or failure code.
  */
@@ -1764,9 +1769,8 @@ struct tf_set_tbl_entry_parms {
 /**
  * set index table entry
  *
- * Used to insert an application programmed index table entry into a
- * previous allocated table location.  A shadow copy of the table
- * is maintained (if enabled) (only for internal objects)
+ * Used to set an application programmed index table entry into a
+ * previous allocated table location.
  *
  * Returns success or failure code.
  */
diff --git a/drivers/net/bnxt/tf_core/tf_device.c b/drivers/net/bnxt/tf_core/tf_device.c
index 498e668b16..25a7166bbb 100644
--- a/drivers/net/bnxt/tf_core/tf_device.c
+++ b/drivers/net/bnxt/tf_core/tf_device.c
@@ -11,10 +11,14 @@
 #include "tf_rm.h"
 #ifdef TF_TCAM_SHARED
 #include "tf_tcam_shared.h"
+#include "tf_tbl_sram.h"
 #endif /* TF_TCAM_SHARED */
 
 struct tf;
 
+/* Number of slices per row for WC TCAM */
+uint16_t g_wc_num_slices_per_row = TF_WC_TCAM_1_SLICE_PER_ROW;
+
 /* Forward declarations */
 static int tf_dev_unbind_p4(struct tf *tfp);
 static int tf_dev_unbind_p58(struct tf *tfp);
@@ -83,7 +87,8 @@ static int
 tf_dev_bind_p4(struct tf *tfp,
 	       bool shadow_copy,
 	       struct tf_session_resources *resources,
-	       struct tf_dev_info *dev_handle)
+	       struct tf_dev_info *dev_handle,
+	       enum tf_wc_num_slice wc_num_slices)
 {
 	int rc;
 	int frc;
@@ -131,7 +136,6 @@ tf_dev_bind_p4(struct tf *tfp,
 	if (rsv_cnt) {
 		tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
 		tbl_cfg.cfg = tf_tbl_p4;
-		tbl_cfg.shadow_copy = shadow_copy;
 		tbl_cfg.resources = resources;
 		rc = tf_tbl_bind(tfp, &tbl_cfg);
 		if (rc) {
@@ -151,6 +155,7 @@ tf_dev_bind_p4(struct tf *tfp,
 		tcam_cfg.cfg = tf_tcam_p4;
 		tcam_cfg.shadow_copy = shadow_copy;
 		tcam_cfg.resources = resources;
+		tcam_cfg.wc_num_slices = wc_num_slices;
 #ifdef TF_TCAM_SHARED
 		rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
 #else /* !TF_TCAM_SHARED */
@@ -369,7 +374,8 @@ static int
 tf_dev_bind_p58(struct tf *tfp,
 		bool shadow_copy,
 		struct tf_session_resources *resources,
-		struct tf_dev_info *dev_handle)
+		struct tf_dev_info *dev_handle,
+		enum tf_wc_num_slice wc_num_slices)
 {
 	int rc;
 	int frc;
@@ -414,7 +420,6 @@ tf_dev_bind_p58(struct tf *tfp,
 	if (rsv_cnt) {
 		tbl_cfg.num_elements = TF_TBL_TYPE_MAX;
 		tbl_cfg.cfg = tf_tbl_p58;
-		tbl_cfg.shadow_copy = shadow_copy;
 		tbl_cfg.resources = resources;
 		rc = tf_tbl_bind(tfp, &tbl_cfg);
 		if (rc) {
@@ -423,6 +428,13 @@ tf_dev_bind_p58(struct tf *tfp,
 			goto fail;
 		}
 		no_rsv_flag = false;
+
+		rc = tf_tbl_sram_bind(tfp);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "SRAM table initialization failure\n");
+			goto fail;
+		}
 	}
 
 	rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX,
@@ -433,6 +445,7 @@ tf_dev_bind_p58(struct tf *tfp,
 		tcam_cfg.cfg = tf_tcam_p58;
 		tcam_cfg.shadow_copy = shadow_copy;
 		tcam_cfg.resources = resources;
+		tcam_cfg.wc_num_slices = wc_num_slices;
 #ifdef TF_TCAM_SHARED
 		rc = tf_tcam_shared_bind(tfp, &tcam_cfg);
 #else /* !TF_TCAM_SHARED */
@@ -565,6 +578,18 @@ tf_dev_unbind_p58(struct tf *tfp)
 		fail = true;
 	}
 
+	/* Unbind the SRAM table prior to table as the table manager
+	 * owns and frees the table DB while the SRAM table manager owns
+	 * and manages it's internal data structures.  SRAM table manager
+	 * relies on the table rm_db to exist.
+	 */
+	rc = tf_tbl_sram_unbind(tfp);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Device unbind failed, SRAM table\n");
+		fail = true;
+	}
+
 	rc = tf_tbl_unbind(tfp);
 	if (rc) {
 		TFP_DRV_LOG(INFO,
@@ -606,6 +631,7 @@ tf_dev_bind(struct tf *tfp __rte_unused,
 	    enum tf_device_type type,
 	    bool shadow_copy,
 	    struct tf_session_resources *resources,
+	    uint16_t wc_num_slices,
 	    struct tf_dev_info *dev_handle)
 {
 	switch (type) {
@@ -615,13 +641,15 @@ tf_dev_bind(struct tf *tfp __rte_unused,
 		return tf_dev_bind_p4(tfp,
 				      shadow_copy,
 				      resources,
-				      dev_handle);
+				      dev_handle,
+				      wc_num_slices);
 	case TF_DEVICE_TYPE_THOR:
 		dev_handle->type = type;
 		return tf_dev_bind_p58(tfp,
 				       shadow_copy,
 				       resources,
-				       dev_handle);
+				       dev_handle,
+				       wc_num_slices);
 	default:
 		TFP_DRV_LOG(ERR,
 			    "No such device\n");
diff --git a/drivers/net/bnxt/tf_core/tf_device.h b/drivers/net/bnxt/tf_core/tf_device.h
index b43cfc6925..9b0c037db0 100644
--- a/drivers/net/bnxt/tf_core/tf_device.h
+++ b/drivers/net/bnxt/tf_core/tf_device.h
@@ -57,6 +57,9 @@ struct tf_dev_info {
  * [in] resources
  *   Pointer to resource allocation information
  *
+ * [in] wc_num_slices
+ *   Number of slices per row for WC
+ *
  * [out] dev_handle
  *   Device handle
  *
@@ -69,6 +72,7 @@ int tf_dev_bind(struct tf *tfp,
 		enum tf_device_type type,
 		bool shadow_copy,
 		struct tf_session_resources *resources,
+		uint16_t wc_num_slices,
 		struct tf_dev_info *dev_handle);
 
 /**
@@ -139,6 +143,23 @@ struct tf_dev_ops {
 				       uint16_t resource_id,
 				       const char **resource_str);
 
+	/**
+	 * Set the WC TCAM slice information that the device
+	 * supports.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] num_slices_per_row
+	 *   Number of slices per row the device supports
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_set_tcam_slice_info)(struct tf *tfp,
+					  enum tf_wc_num_slice num_slices_per_row);
+
 	/**
 	 * Retrieves the WC TCAM slice information that the device
 	 * supports.
@@ -241,6 +262,22 @@ struct tf_dev_ops {
 	int (*tf_dev_get_ident_resc_info)(struct tf *tfp,
 					  struct tf_identifier_resource_info *parms);
 
+	/**
+	 * Indicates whether the index table type is SRAM managed
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] type
+	 *   Truflow index table type, e.g. TF_TYPE_FULL_ACT_RECORD
+	 *
+	 * Returns
+	 *   - (0) if the table is not managed by the SRAM manager
+	 *   - (1) if the table is managed by the SRAM manager
+	 */
+	bool (*tf_dev_is_sram_managed)(struct tf *tfp,
+				       enum tf_tbl_type tbl_type);
+
 	/**
 	 * Get SRAM table information.
 	 *
@@ -289,6 +326,25 @@ struct tf_dev_ops {
 	int (*tf_dev_alloc_tbl)(struct tf *tfp,
 				struct tf_tbl_alloc_parms *parms);
 
+	/**
+	 * Allocation of an SRAM index table type element.
+	 *
+	 * This API allocates the specified table type element from a
+	 * device specific table type DB. The allocated element is
+	 * returned.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] parms
+	 *   Pointer to table allocation parameters
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_alloc_sram_tbl)(struct tf *tfp,
+				     struct tf_tbl_alloc_parms *parms);
 	/**
 	 * Allocation of a external table type element.
 	 *
@@ -327,7 +383,24 @@ struct tf_dev_ops {
 	 */
 	int (*tf_dev_free_tbl)(struct tf *tfp,
 			       struct tf_tbl_free_parms *parms);
-
+	/**
+	 * Free of an SRAM table type element.
+	 *
+	 * This API free's a previous allocated table type element from a
+	 * device specific table type DB.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] parms
+	 *   Pointer to table free parameters
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_free_sram_tbl)(struct tf *tfp,
+				    struct tf_tbl_free_parms *parms);
 	/**
 	 * Free of a external table type element.
 	 *
@@ -385,6 +458,25 @@ struct tf_dev_ops {
 	int (*tf_dev_set_ext_tbl)(struct tf *tfp,
 				  struct tf_tbl_set_parms *parms);
 
+	/**
+	 * Sets the specified SRAM table type element.
+	 *
+	 * This API sets the specified element data by invoking the
+	 * firmware.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] parms
+	 *   Pointer to table set parameters
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_set_sram_tbl)(struct tf *tfp,
+				   struct tf_tbl_set_parms *parms);
+
 	/**
 	 * Retrieves the specified table type element.
 	 *
@@ -404,6 +496,25 @@ struct tf_dev_ops {
 	int (*tf_dev_get_tbl)(struct tf *tfp,
 			      struct tf_tbl_get_parms *parms);
 
+	/**
+	 * Retrieves the specified SRAM table type element.
+	 *
+	 * This API retrieves the specified element data by invoking the
+	 * firmware.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] parms
+	 *   Pointer to table get parameters
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_get_sram_tbl)(struct tf *tfp,
+				   struct tf_tbl_get_parms *parms);
+
 	/**
 	 * Retrieves the specified table type element using 'bulk'
 	 * mechanism.
@@ -424,6 +535,26 @@ struct tf_dev_ops {
 	int (*tf_dev_get_bulk_tbl)(struct tf *tfp,
 				   struct tf_tbl_get_bulk_parms *parms);
 
+	/**
+	 * Retrieves the specified SRAM table type element using 'bulk'
+	 * mechanism.
+	 *
+	 * This API retrieves the specified element data by invoking the
+	 * firmware.
+	 *
+	 * [in] tfp
+	 *   Pointer to TF handle
+	 *
+	 * [in] parms
+	 *   Pointer to table get bulk parameters
+	 *
+	 * Returns
+	 *   - (0) if successful.
+	 *   - (-EINVAL) on failure.
+	 */
+	int (*tf_dev_get_bulk_sram_tbl)(struct tf *tfp,
+					struct tf_tbl_get_bulk_parms *parms);
+
 	/**
 	 * Gets the increment value to add to the shared session resource
 	 * start offset by for each count in the "stride"
diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c
index 2e7ccec123..826cd0cdbc 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p4.c
+++ b/drivers/net/bnxt/tf_core/tf_device_p4.c
@@ -118,14 +118,48 @@ tf_dev_p4_get_resource_str(struct tf *tfp __rte_unused,
 }
 
 /**
- * Device specific function that retrieves the WC TCAM slices the
+ * Device specific function that set the WC TCAM slices the
  * device supports.
  *
  * [in] tfp
  *   Pointer to TF handle
  *
- * [out] slice_size
- *   Pointer to the WC TCAM slice size
+ * [in] num_slices_per_row
+ *   The WC TCAM row slice configuration
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+static int
+tf_dev_p4_set_tcam_slice_info(struct tf *tfp __rte_unused,
+			      enum tf_wc_num_slice num_slices_per_row)
+{
+	switch (num_slices_per_row) {
+	case TF_WC_TCAM_1_SLICE_PER_ROW:
+	case TF_WC_TCAM_2_SLICE_PER_ROW:
+	case TF_WC_TCAM_4_SLICE_PER_ROW:
+		g_wc_num_slices_per_row = num_slices_per_row;
+	break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * Device specific function that retrieves the TCAM slices the
+ * device supports.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [in] type
+ *   TF TCAM type
+ *
+ * [in] key_sz
+ *   The key size
  *
  * [out] num_slices_per_row
  *   Pointer to the WC TCAM row slice configuration
@@ -141,11 +175,10 @@ tf_dev_p4_get_tcam_slice_info(struct tf *tfp __rte_unused,
 			      uint16_t *num_slices_per_row)
 {
 /* Single slice support */
-#define CFA_P4_WC_TCAM_SLICES_PER_ROW 1
 #define CFA_P4_WC_TCAM_SLICE_SIZE     12
 
 	if (type == TF_TCAM_TBL_TYPE_WC_TCAM) {
-		*num_slices_per_row = CFA_P4_WC_TCAM_SLICES_PER_ROW;
+		*num_slices_per_row = g_wc_num_slices_per_row;
 		if (key_sz > *num_slices_per_row * CFA_P4_WC_TCAM_SLICE_SIZE)
 			return -ENOTSUP;
 	} else { /* for other type of tcam */
@@ -220,26 +253,51 @@ static int tf_dev_p4_word_align(uint16_t size)
 	return ((((size) + 31) >> 5) * 4);
 }
 
+/**
+ * Indicates whether the index table type is SRAM managed
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [in] type
+ *   Truflow index table type, e.g. TF_TYPE_FULL_ACT_RECORD
+ *
+ * Returns
+ *   - (0) if the table is not managed by the SRAM manager
+ *   - (1) if the table is managed by the SRAM manager
+ */
+static bool tf_dev_p4_is_sram_managed(struct tf *tfp __rte_unused,
+				      enum tf_tbl_type type __rte_unused)
+{
+	return false;
+}
 /**
  * Truflow P4 device specific functions
  */
 const struct tf_dev_ops tf_dev_ops_p4_init = {
 	.tf_dev_get_max_types = tf_dev_p4_get_max_types,
 	.tf_dev_get_resource_str = tf_dev_p4_get_resource_str,
+	.tf_dev_set_tcam_slice_info = tf_dev_p4_set_tcam_slice_info,
 	.tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info,
 	.tf_dev_alloc_ident = NULL,
 	.tf_dev_free_ident = NULL,
 	.tf_dev_search_ident = NULL,
 	.tf_dev_get_ident_resc_info = NULL,
 	.tf_dev_get_tbl_info = NULL,
+	.tf_dev_is_sram_managed = tf_dev_p4_is_sram_managed,
 	.tf_dev_alloc_ext_tbl = NULL,
 	.tf_dev_alloc_tbl = NULL,
+	.tf_dev_alloc_sram_tbl = NULL,
 	.tf_dev_free_ext_tbl = NULL,
 	.tf_dev_free_tbl = NULL,
+	.tf_dev_free_sram_tbl = NULL,
 	.tf_dev_set_tbl = NULL,
 	.tf_dev_set_ext_tbl = NULL,
+	.tf_dev_set_sram_tbl = NULL,
 	.tf_dev_get_tbl = NULL,
+	.tf_dev_get_sram_tbl = NULL,
 	.tf_dev_get_bulk_tbl = NULL,
+	.tf_dev_get_bulk_sram_tbl = NULL,
 	.tf_dev_get_shared_tbl_increment = tf_dev_p4_get_shared_tbl_increment,
 	.tf_dev_get_tbl_resc_info = NULL,
 	.tf_dev_alloc_tcam = NULL,
@@ -271,20 +329,27 @@ const struct tf_dev_ops tf_dev_ops_p4_init = {
 const struct tf_dev_ops tf_dev_ops_p4 = {
 	.tf_dev_get_max_types = tf_dev_p4_get_max_types,
 	.tf_dev_get_resource_str = tf_dev_p4_get_resource_str,
+	.tf_dev_set_tcam_slice_info = tf_dev_p4_set_tcam_slice_info,
 	.tf_dev_get_tcam_slice_info = tf_dev_p4_get_tcam_slice_info,
 	.tf_dev_alloc_ident = tf_ident_alloc,
 	.tf_dev_free_ident = tf_ident_free,
 	.tf_dev_search_ident = tf_ident_search,
 	.tf_dev_get_ident_resc_info = tf_ident_get_resc_info,
 	.tf_dev_get_tbl_info = NULL,
+	.tf_dev_is_sram_managed = tf_dev_p4_is_sram_managed,
 	.tf_dev_alloc_tbl = tf_tbl_alloc,
 	.tf_dev_alloc_ext_tbl = tf_tbl_ext_alloc,
+	.tf_dev_alloc_sram_tbl = tf_tbl_alloc,
 	.tf_dev_free_tbl = tf_tbl_free,
 	.tf_dev_free_ext_tbl = tf_tbl_ext_free,
+	.tf_dev_free_sram_tbl = tf_tbl_free,
 	.tf_dev_set_tbl = tf_tbl_set,
 	.tf_dev_set_ext_tbl = tf_tbl_ext_common_set,
+	.tf_dev_set_sram_tbl = NULL,
 	.tf_dev_get_tbl = tf_tbl_get,
+	.tf_dev_get_sram_tbl = NULL,
 	.tf_dev_get_bulk_tbl = tf_tbl_bulk_get,
+	.tf_dev_get_bulk_sram_tbl = NULL,
 	.tf_dev_get_shared_tbl_increment = tf_dev_p4_get_shared_tbl_increment,
 	.tf_dev_get_tbl_resc_info = tf_tbl_get_resc_info,
 #ifdef TF_TCAM_SHARED
diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.h b/drivers/net/bnxt/tf_core/tf_device_p4.h
index a73ba3cd70..c1357913f1 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p4.h
+++ b/drivers/net/bnxt/tf_core/tf_device_p4.h
@@ -15,101 +15,101 @@
 struct tf_rm_element_cfg tf_ident_p4[TF_IDENT_TYPE_MAX] = {
 	[TF_IDENT_TYPE_L2_CTXT_HIGH] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_L2_CTXT_REMAP_HIGH,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_L2_CTXT_LOW] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_L2_CTXT_REMAP_LOW,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_PROF_FUNC] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_PROF_FUNC,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_WC_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_WC_TCAM_PROF_ID,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_EM_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_EM_PROF_ID,
-		0, 0, 0
+		0, 0
 	},
 };
 
 struct tf_rm_element_cfg tf_tcam_p4[TF_TCAM_TBL_TYPE_MAX] = {
 	[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_HIGH,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_L2_CTXT_TCAM_LOW,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_PROF_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_PROF_TCAM,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_WC_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_WC_TCAM,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_SP_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_SP_TCAM,
-		0, 0, 0
+		0, 0
 	},
 };
 
 struct tf_rm_element_cfg tf_tbl_p4[TF_TBL_TYPE_MAX] = {
 	[TF_TBL_TYPE_FULL_ACT_RECORD] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_FULL_ACTION,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_MCAST_GROUPS] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_MCG,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_8B] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_ENCAP_8B,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_16B] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_ENCAP_16B,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_64B] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_ENCAP_64B,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_SP_SMAC] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_SP_MAC,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_SP_MAC_IPV4,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_SP_MAC_IPV6,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_STATS_64] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_COUNTER_64B,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_ACT_MODIFY_IPV4] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_NAT_IPV4,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METER_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_METER_PROF,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METER_INST] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_METER,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_MIRROR_CONFIG] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_MIRROR,
-		0, 0, 0
+		0, 0
 	},
 
 };
@@ -117,14 +117,14 @@ struct tf_rm_element_cfg tf_tbl_p4[TF_TBL_TYPE_MAX] = {
 struct tf_rm_element_cfg tf_em_ext_p4[TF_EM_TBL_TYPE_MAX] = {
 	[TF_EM_TBL_TYPE_TBL_SCOPE] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P4_TBL_SCOPE,
-		0, 0, 0
+		0, 0
 	},
 };
 
 struct tf_rm_element_cfg tf_em_int_p4[TF_EM_TBL_TYPE_MAX] = {
 	[TF_EM_TBL_TYPE_EM_RECORD] = {
 		TF_RM_ELEM_CFG_HCAPI, CFA_RESOURCE_TYPE_P4_EM_REC,
-		0, 0, 0
+		0, 0
 	},
 };
 
diff --git a/drivers/net/bnxt/tf_core/tf_device_p58.c b/drivers/net/bnxt/tf_core/tf_device_p58.c
index a492c62bff..47d7836a58 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p58.c
+++ b/drivers/net/bnxt/tf_core/tf_device_p58.c
@@ -17,6 +17,7 @@
 #include "tf_if_tbl.h"
 #include "tfp.h"
 #include "tf_msg_common.h"
+#include "tf_tbl_sram.h"
 
 #define TF_DEV_P58_PARIF_MAX 16
 #define TF_DEV_P58_PF_MASK 0xfUL
@@ -105,14 +106,48 @@ tf_dev_p58_get_resource_str(struct tf *tfp __rte_unused,
 }
 
 /**
- * Device specific function that retrieves the WC TCAM slices the
+ * Device specific function that set the WC TCAM slices the
  * device supports.
  *
  * [in] tfp
  *   Pointer to TF handle
  *
- * [out] slice_size
- *   Pointer to the WC TCAM slice size
+ * [in] num_slices_per_row
+ *   The WC TCAM row slice configuration
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+static int
+tf_dev_p58_set_tcam_slice_info(struct tf *tfp __rte_unused,
+			       enum tf_wc_num_slice num_slices_per_row)
+{
+	switch (num_slices_per_row) {
+	case TF_WC_TCAM_1_SLICE_PER_ROW:
+	case TF_WC_TCAM_2_SLICE_PER_ROW:
+	case TF_WC_TCAM_4_SLICE_PER_ROW:
+		g_wc_num_slices_per_row = num_slices_per_row;
+	break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * Device specific function that retrieves the TCAM slices the
+ * device supports.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [in] type
+ *   TF TCAM type
+ *
+ * [in] key_sz
+ *   The key size
  *
  * [out] num_slices_per_row
  *   Pointer to the WC TCAM row slice configuration
@@ -123,16 +158,13 @@ tf_dev_p58_get_resource_str(struct tf *tfp __rte_unused,
  */
 static int
 tf_dev_p58_get_tcam_slice_info(struct tf *tfp __rte_unused,
-			      enum tf_tcam_tbl_type type,
-			      uint16_t key_sz,
-			      uint16_t *num_slices_per_row)
+			       enum tf_tcam_tbl_type type,
+			       uint16_t key_sz,
+			       uint16_t *num_slices_per_row)
 {
-#define CFA_P58_WC_TCAM_SLICES_PER_ROW 1
 #define CFA_P58_WC_TCAM_SLICE_SIZE     24
-
 	if (type == TF_TCAM_TBL_TYPE_WC_TCAM) {
-		/* only support single slice key size now */
-		*num_slices_per_row = CFA_P58_WC_TCAM_SLICES_PER_ROW;
+		*num_slices_per_row = g_wc_num_slices_per_row;
 		if (key_sz > *num_slices_per_row * CFA_P58_WC_TCAM_SLICE_SIZE)
 			return -ENOTSUP;
 	} else { /* for other type of tcam */
@@ -194,6 +226,44 @@ static int tf_dev_p58_get_shared_tbl_increment(struct tf *tfp __rte_unused,
 	return 0;
 }
 
+/**
+ * Indicates whether the index table type is SRAM managed
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [in] type
+ *   Truflow index table type, e.g. TF_TYPE_FULL_ACT_RECORD
+ *
+ * Returns
+ *   - (0) if the table is not managed by the SRAM manager
+ *   - (1) if the table is managed by the SRAM manager
+ */
+static bool tf_dev_p58_is_sram_managed(struct tf *tfp __rte_unused,
+				       enum tf_tbl_type type)
+{
+	switch (type) {
+	case TF_TBL_TYPE_FULL_ACT_RECORD:
+	case TF_TBL_TYPE_COMPACT_ACT_RECORD:
+	case TF_TBL_TYPE_ACT_ENCAP_8B:
+	case TF_TBL_TYPE_ACT_ENCAP_16B:
+	case TF_TBL_TYPE_ACT_ENCAP_32B:
+	case TF_TBL_TYPE_ACT_ENCAP_64B:
+	case TF_TBL_TYPE_ACT_SP_SMAC:
+	case TF_TBL_TYPE_ACT_SP_SMAC_IPV4:
+	case TF_TBL_TYPE_ACT_SP_SMAC_IPV6:
+	case TF_TBL_TYPE_ACT_STATS_64:
+	case TF_TBL_TYPE_ACT_MODIFY_IPV4:
+	case TF_TBL_TYPE_ACT_MODIFY_8B:
+	case TF_TBL_TYPE_ACT_MODIFY_16B:
+	case TF_TBL_TYPE_ACT_MODIFY_32B:
+	case TF_TBL_TYPE_ACT_MODIFY_64B:
+		return true;
+	default:
+		return false;
+	}
+}
+
 #define TF_DEV_P58_BANK_SZ_64B 2048
 /**
  * Get SRAM table information.
@@ -265,26 +335,34 @@ static int tf_dev_p58_get_sram_tbl_info(struct tf *tfp __rte_unused,
 	}
 	return 0;
 }
+
 /**
  * Truflow P58 device specific functions
  */
 const struct tf_dev_ops tf_dev_ops_p58_init = {
 	.tf_dev_get_max_types = tf_dev_p58_get_max_types,
 	.tf_dev_get_resource_str = tf_dev_p58_get_resource_str,
+	.tf_dev_set_tcam_slice_info = tf_dev_p58_set_tcam_slice_info,
 	.tf_dev_get_tcam_slice_info = tf_dev_p58_get_tcam_slice_info,
 	.tf_dev_alloc_ident = NULL,
 	.tf_dev_free_ident = NULL,
 	.tf_dev_search_ident = NULL,
 	.tf_dev_get_ident_resc_info = NULL,
 	.tf_dev_get_tbl_info = NULL,
+	.tf_dev_is_sram_managed = tf_dev_p58_is_sram_managed,
 	.tf_dev_alloc_ext_tbl = NULL,
 	.tf_dev_alloc_tbl = NULL,
+	.tf_dev_alloc_sram_tbl = NULL,
 	.tf_dev_free_ext_tbl = NULL,
 	.tf_dev_free_tbl = NULL,
+	.tf_dev_free_sram_tbl = NULL,
 	.tf_dev_set_tbl = NULL,
 	.tf_dev_set_ext_tbl = NULL,
+	.tf_dev_set_sram_tbl = NULL,
 	.tf_dev_get_tbl = NULL,
+	.tf_dev_get_sram_tbl = NULL,
 	.tf_dev_get_bulk_tbl = NULL,
+	.tf_dev_get_bulk_sram_tbl = NULL,
 	.tf_dev_get_shared_tbl_increment = tf_dev_p58_get_shared_tbl_increment,
 	.tf_dev_get_tbl_resc_info = NULL,
 	.tf_dev_alloc_tcam = NULL,
@@ -316,20 +394,27 @@ const struct tf_dev_ops tf_dev_ops_p58_init = {
 const struct tf_dev_ops tf_dev_ops_p58 = {
 	.tf_dev_get_max_types = tf_dev_p58_get_max_types,
 	.tf_dev_get_resource_str = tf_dev_p58_get_resource_str,
+	.tf_dev_set_tcam_slice_info = tf_dev_p58_set_tcam_slice_info,
 	.tf_dev_get_tcam_slice_info = tf_dev_p58_get_tcam_slice_info,
 	.tf_dev_alloc_ident = tf_ident_alloc,
 	.tf_dev_free_ident = tf_ident_free,
 	.tf_dev_search_ident = tf_ident_search,
 	.tf_dev_get_ident_resc_info = tf_ident_get_resc_info,
+	.tf_dev_is_sram_managed = tf_dev_p58_is_sram_managed,
 	.tf_dev_get_tbl_info = tf_dev_p58_get_sram_tbl_info,
 	.tf_dev_alloc_tbl = tf_tbl_alloc,
+	.tf_dev_alloc_sram_tbl = tf_tbl_sram_alloc,
 	.tf_dev_alloc_ext_tbl = tf_tbl_ext_alloc,
 	.tf_dev_free_tbl = tf_tbl_free,
 	.tf_dev_free_ext_tbl = tf_tbl_ext_free,
+	.tf_dev_free_sram_tbl = tf_tbl_sram_free,
 	.tf_dev_set_tbl = tf_tbl_set,
 	.tf_dev_set_ext_tbl = tf_tbl_ext_common_set,
+	.tf_dev_set_sram_tbl = tf_tbl_sram_set,
 	.tf_dev_get_tbl = tf_tbl_get,
+	.tf_dev_get_sram_tbl = tf_tbl_sram_get,
 	.tf_dev_get_bulk_tbl = tf_tbl_bulk_get,
+	.tf_dev_get_bulk_sram_tbl = tf_tbl_sram_bulk_get,
 	.tf_dev_get_shared_tbl_increment = tf_dev_p58_get_shared_tbl_increment,
 	.tf_dev_get_tbl_resc_info = tf_tbl_get_resc_info,
 #ifdef TF_TCAM_SHARED
diff --git a/drivers/net/bnxt/tf_core/tf_device_p58.h b/drivers/net/bnxt/tf_core/tf_device_p58.h
index 8c2e07aa34..3e8759f2df 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p58.h
+++ b/drivers/net/bnxt/tf_core/tf_device_p58.h
@@ -15,107 +15,107 @@
 struct tf_rm_element_cfg tf_ident_p58[TF_IDENT_TYPE_MAX] = {
 	[TF_IDENT_TYPE_L2_CTXT_HIGH] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_L2_CTXT_REMAP_HIGH,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_L2_CTXT_LOW] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_L2_CTXT_REMAP_LOW,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_PROF_FUNC] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_PROF_FUNC,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_WC_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_WC_TCAM_PROF_ID,
-		0, 0, 0
+		0, 0
 	},
 	[TF_IDENT_TYPE_EM_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_EM_PROF_ID,
-		0, 0, 0
+		0, 0
 	},
 };
 
 struct tf_rm_element_cfg tf_tcam_p58[TF_TCAM_TBL_TYPE_MAX] = {
 	[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_HIGH,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_L2_CTXT_TCAM_LOW,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_PROF_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_PROF_TCAM,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_WC_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_WC_TCAM,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TCAM_TBL_TYPE_VEB_TCAM] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_VEB_TCAM,
-		0, 0, 0
+		0, 0
 	},
 };
 
 struct tf_rm_element_cfg tf_tbl_p58[TF_TBL_TYPE_MAX] = {
 	[TF_TBL_TYPE_EM_FKB] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_EM_FKB,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_WC_FKB] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_WC_FKB,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METER_PROF] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_METER_PROF,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METER_INST] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_METER,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METER_DROP_CNT] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_METER_DROP_CNT,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_MIRROR_CONFIG] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_MIRROR,
-		0, 0, 0
+		0, 0
 	},
 	[TF_TBL_TYPE_METADATA] = {
 		TF_RM_ELEM_CFG_HCAPI_BA, CFA_RESOURCE_TYPE_P58_METADATA,
-		0, 0, 0
+		0, 0
 	},
 	/* Policy - ARs in bank 1 */
 	[TF_TBL_TYPE_FULL_ACT_RECORD] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_PARENT,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1,
-		.slices          = 1,
+		.slices          = 4,
 	},
 	[TF_TBL_TYPE_COMPACT_ACT_RECORD] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_FULL_ACT_RECORD,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_1,
-		.slices          = 1,
+		.slices          = 8,
 	},
 	/* Policy - Encaps in bank 2 */
 	[TF_TBL_TYPE_ACT_ENCAP_8B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_PARENT,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 8,
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_16B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_ENCAP_8B,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 4,
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_32B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_ENCAP_8B,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 2,
 	},
 	[TF_TBL_TYPE_ACT_ENCAP_64B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
@@ -128,19 +128,19 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_TBL_TYPE_MAX] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_ENCAP_8B,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 8,
 	},
 	[TF_TBL_TYPE_ACT_MODIFY_16B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_ENCAP_8B,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 4,
 	},
 	[TF_TBL_TYPE_ACT_MODIFY_32B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_ENCAP_8B,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_2,
-		.slices          = 1,
+		.slices          = 2,
 	},
 	[TF_TBL_TYPE_ACT_MODIFY_64B] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
@@ -152,32 +152,32 @@ struct tf_rm_element_cfg tf_tbl_p58[TF_TBL_TYPE_MAX] = {
 	[TF_TBL_TYPE_ACT_SP_SMAC] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_PARENT,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0,
-		.slices          = 1,
+		.slices          = 8,
 	},
 	[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_SP_SMAC,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0,
-		.slices          = 1,
+		.slices          = 4,
 	},
 	[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_CHILD,
 		.parent_subtype  = TF_TBL_TYPE_ACT_SP_SMAC,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_0,
-		.slices          = 1,
+		.slices          = 2,
 	},
 	/* Policy - Stats in bank 3 */
 	[TF_TBL_TYPE_ACT_STATS_64] = {
 		.cfg_type        = TF_RM_ELEM_CFG_HCAPI_BA_PARENT,
 		.hcapi_type      = CFA_RESOURCE_TYPE_P58_SRAM_BANK_3,
-		.slices          = 1,
+		.slices          = 8,
 	},
 };
 
 struct tf_rm_element_cfg tf_em_int_p58[TF_EM_TBL_TYPE_MAX] = {
 	[TF_EM_TBL_TYPE_EM_RECORD] = {
 		TF_RM_ELEM_CFG_HCAPI, CFA_RESOURCE_TYPE_P58_EM_REC,
-		0, 0, 0
+		0, 0
 	},
 };
 
diff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c
index e07d9168be..0fbb2fe837 100644
--- a/drivers/net/bnxt/tf_core/tf_msg.c
+++ b/drivers/net/bnxt/tf_core/tf_msg.c
@@ -2231,7 +2231,7 @@ tf_msg_get_if_tbl_entry(struct tf *tfp,
 	if (rc != 0)
 		return rc;
 
-	tfp_memcpy(params->data, resp.data, req.size);
+	tfp_memcpy(&params->data[0], resp.data, req.size);
 
 	return 0;
 }
diff --git a/drivers/net/bnxt/tf_core/tf_rm.c b/drivers/net/bnxt/tf_core/tf_rm.c
index 0a46e2a343..03c958a7d6 100644
--- a/drivers/net/bnxt/tf_core/tf_rm.c
+++ b/drivers/net/bnxt/tf_core/tf_rm.c
@@ -34,6 +34,12 @@ 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.
 	 */
@@ -356,12 +362,15 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
  *     -          - Failure if negative
  */
 static int
-tf_rm_update_parent_reservations(struct tf_rm_element_cfg *cfg,
+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)
 {
 	int parent, child;
+	const char *type_str;
 
 	/* Search through all the elements */
 	for (parent = 0; parent < num_elements; parent++) {
@@ -377,15 +386,25 @@ tf_rm_update_parent_reservations(struct tf_rm_element_cfg *cfg,
 			if (alloc_cnt[parent] % cfg[parent].slices)
 				combined_cnt++;
 
+			if (alloc_cnt[parent]) {
+				dev->ops->tf_dev_get_resource_str(tfp,
+							 cfg[parent].hcapi_type,
+							 &type_str);
+			}
+
 			/* 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) {
+				    cfg[child].parent_subtype == parent &&
+				    alloc_cnt[child]) {
 					uint16_t cnt = 0;
 					RTE_ASSERT(cfg[child].slices);
 
+					dev->ops->tf_dev_get_resource_str(tfp,
+							  cfg[child].hcapi_type,
+							   &type_str);
 					/* Increment the parents combined count
 					 * with each child's count adjusted for
 					 * number of slices per RM allocated item.
@@ -479,7 +498,7 @@ tf_rm_create_db(struct tf *tfp,
 
 	/* Update the req_cnt based upon the element configuration
 	 */
-	tf_rm_update_parent_reservations(parms->cfg,
+	tf_rm_update_parent_reservations(tfp, dev, parms->cfg,
 					 parms->alloc_cnt,
 					 parms->num_elements,
 					 req_cnt);
@@ -594,6 +613,7 @@ tf_rm_create_db(struct tf *tfp,
 
 		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
 		 */
@@ -1271,6 +1291,26 @@ tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
 
 	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;
+	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->slices = rm_db->db[parms->subtype].slices;
+
+	return 0;
+}
 
 int
 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
diff --git a/drivers/net/bnxt/tf_core/tf_rm.h b/drivers/net/bnxt/tf_core/tf_rm.h
index 8b984112e8..da7d0c7211 100644
--- a/drivers/net/bnxt/tf_core/tf_rm.h
+++ b/drivers/net/bnxt/tf_core/tf_rm.h
@@ -43,16 +43,6 @@ struct tf;
  * support module, not called directly.
  */
 
-/**
- * Resource reservation single entry result. Used when accessing HCAPI
- * RM on the firmware.
- */
-struct tf_rm_new_entry {
-	/** Starting index of the allocated resource */
-	uint16_t start;
-	/** Number of allocated elements */
-	uint16_t stride;
-};
 
 /**
  * RM Element configuration enumeration. Used by the Device to
@@ -114,10 +104,6 @@ struct tf_rm_element_cfg {
 	 */
 	enum tf_rm_elem_cfg_type cfg_type;
 
-	/* If a HCAPI to TF type conversion is required then TF type
-	 * can be added here.
-	 */
-
 	/**
 	 * HCAPI RM Type for the element. Used for TF to HCAPI type
 	 * conversion.
@@ -125,28 +111,19 @@ struct tf_rm_element_cfg {
 	uint16_t hcapi_type;
 
 	/**
-	 * if cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD
+	 * if cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD/PARENT
 	 *
 	 * Parent Truflow module subtype associated with this resource type.
 	 */
 	uint16_t parent_subtype;
 
 	/**
-	 * if cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD
+	 * if cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD/PARENT
 	 *
 	 * Resource slices.  How many slices will fit in the
 	 * resource pool chunk size.
 	 */
 	uint8_t slices;
-
-	/**
-	 * Pool element divider count
-	 * If 0 or 1, there is 1:1 correspondence between the RM
-	 * BA pool resource element and the HCAPI RM firmware
-	 * resource.  If > 1, the RM BA pool element has a 1:n
-	 * correspondence to the HCAPI RM firmware resource.
-	 */
-	uint8_t divider;
 };
 
 /**
@@ -160,7 +137,7 @@ struct tf_rm_alloc_info {
 	 * In case of dynamic allocation support this would have
 	 * to be changed to linked list of tf_rm_entry instead.
 	 */
-	struct tf_rm_new_entry entry;
+	struct tf_resource_info entry;
 };
 
 /**
@@ -331,6 +308,25 @@ struct tf_rm_get_hcapi_parms {
 	 */
 	uint16_t *hcapi_type;
 };
+/**
+ * Get Slices parameters for a single element
+ */
+struct tf_rm_get_slices_parms {
+	/**
+	 * [in] RM DB Handle
+	 */
+	void *rm_db;
+	/**
+	 * [in] TF subtype indicates which DB entry to perform the
+	 * action on. (e.g. TF_TBL_TYPE_FULL_ACTION subtype of module
+	 * TF_MODULE_TYPE_TABLE)
+	 */
+	uint16_t subtype;
+	/**
+	 * [in/out] Pointer to number of slices for the given type
+	 */
+	uint16_t *slices;
+};
 
 /**
  * Get InUse count parameters for single element
@@ -394,6 +390,8 @@ struct tf_rm_check_indexes_in_range_parms {
  * @ref tf_rm_get_hcapi_type
  *
  * @ref tf_rm_get_inuse_count
+ *
+ * @ref tf_rm_get_slice_size
  */
 
 /**
@@ -571,5 +569,17 @@ int tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms);
 int
 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms);
 
+/**
+ * Get the number of slices per resource bit allocator for the resource type
+ *
+ * [in] parms
+ *   Pointer to get inuse parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int
+tf_rm_get_slices(struct tf_rm_get_slices_parms *parms);
 
 #endif /* TF_RM_NEW_H_ */
diff --git a/drivers/net/bnxt/tf_core/tf_session.c b/drivers/net/bnxt/tf_core/tf_session.c
index 90b65c59e6..3e6664e9f2 100644
--- a/drivers/net/bnxt/tf_core/tf_session.c
+++ b/drivers/net/bnxt/tf_core/tf_session.c
@@ -202,6 +202,7 @@ tf_session_create(struct tf *tfp,
 			 parms->open_cfg->device_type,
 			 session->shadow_copy,
 			 &parms->open_cfg->resources,
+			 parms->open_cfg->wc_num_slices,
 			 &session->dev);
 
 	/* Logging handled by dev_bind */
@@ -705,6 +706,22 @@ tf_session_get_session(struct tf *tfp,
 	return rc;
 }
 
+int tf_session_get(struct tf *tfp,
+		   struct tf_session **tfs,
+		   struct tf_dev_info **tfd)
+{
+	int rc;
+	rc = tf_session_get_session_internal(tfp, tfs);
+
+	/* Logging done by tf_session_get_session_internal */
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_device(*tfs, tfd);
+
+	return rc;
+}
+
 struct tf_session_client *
 tf_session_get_session_client(struct tf_session *tfs,
 			      union tf_session_client_id session_client_id)
@@ -1012,4 +1029,43 @@ tf_session_set_tcam_shared_db(struct tf *tfp,
 	tfs->tcam_shared_db_handle = tcam_shared_db_handle;
 	return rc;
 }
+
+int
+tf_session_get_sram_db(struct tf *tfp,
+		       void **sram_handle)
+{
+	struct tf_session *tfs = NULL;
+	int rc = 0;
+
+	*sram_handle = NULL;
+
+	if (tfp == NULL)
+		return (-EINVAL);
+
+	rc = tf_session_get_session_internal(tfp, &tfs);
+	if (rc)
+		return rc;
+
+	*sram_handle = tfs->sram_handle;
+	return rc;
+}
+
+int
+tf_session_set_sram_db(struct tf *tfp,
+		       void *sram_handle)
+{
+	struct tf_session *tfs = NULL;
+	int rc = 0;
+
+	if (tfp == NULL)
+		return (-EINVAL);
+
+	rc = tf_session_get_session_internal(tfp, &tfs);
+	if (rc)
+		return rc;
+
+	tfs->sram_handle = sram_handle;
+	return rc;
+}
+
 #endif /* TF_TCAM_SHARED */
diff --git a/drivers/net/bnxt/tf_core/tf_session.h b/drivers/net/bnxt/tf_core/tf_session.h
index d68421cd13..c1d7f70060 100644
--- a/drivers/net/bnxt/tf_core/tf_session.h
+++ b/drivers/net/bnxt/tf_core/tf_session.h
@@ -166,6 +166,10 @@ struct tf_session {
 	 */
 	void *tcam_shared_db_handle;
 #endif /* TF_TCAM_SHARED */
+	/**
+	 * SRAM db reference for the session
+	 */
+	void *sram_handle;
 };
 
 /**
@@ -278,6 +282,10 @@ struct tf_session_close_session_parms {
  *
  * @ref tf_session_set_tcam_shared_db
  * #endif
+ *
+ * @ref tf_session_get_sram_db
+ *
+ * @ref tf_session_set_sram_db
  */
 
 /**
@@ -435,11 +443,11 @@ tf_session_find_session_client_by_fid(struct tf_session *tfs,
 /**
  * Looks up the device information from the TF Session.
  *
- * [in] tfp
- *   Pointer to TF handle
+ * [in] tfs
+ *   Pointer to session handle
  *
  * [out] tfd
- *   Pointer pointer to the device
+ *   Pointer to the device
  *
  * Returns
  *   - (0) if successful.
@@ -448,6 +456,26 @@ tf_session_find_session_client_by_fid(struct tf_session *tfs,
 int tf_session_get_device(struct tf_session *tfs,
 			  struct tf_dev_info **tfd);
 
+/**
+ * Returns the session and the device from the tfp.
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [out] tfs
+ *   Pointer to the session
+ *
+ * [out] tfd
+ *   Pointer to the device
+
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_session_get(struct tf *tfp,
+		   struct tf_session **tfs,
+		   struct tf_dev_info **tfd);
+
 /**
  * Looks up the FW Session id the requested TF handle.
  *
@@ -614,4 +642,28 @@ int
 tf_session_get_tcam_shared_db(struct tf *tfp,
 			      void **tcam_shared_db_handle);
 
+/**
+ * Set the pointer to the SRAM database
+ *
+ * [in] session, pointer to the session
+ *
+ * Returns:
+ *   - the pointer to the parent bnxt struct
+ */
+int
+tf_session_set_sram_db(struct tf *tfp,
+		       void *sram_handle);
+
+/**
+ * Get the pointer to the SRAM database
+ *
+ * [in] session, pointer to the session
+ *
+ * Returns:
+ *   - the pointer to the parent bnxt struct
+ */
+int
+tf_session_get_sram_db(struct tf *tfp,
+		       void **sram_handle);
+
 #endif /* _TF_SESSION_H_ */
diff --git a/drivers/net/bnxt/tf_core/tf_sram_mgr.c b/drivers/net/bnxt/tf_core/tf_sram_mgr.c
new file mode 100644
index 0000000000..f633a78b25
--- /dev/null
+++ b/drivers/net/bnxt/tf_core/tf_sram_mgr.c
@@ -0,0 +1,971 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2021 Broadcom
+ * All rights reserved.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "tf_sram_mgr.h"
+#include "tf_core.h"
+#include "tf_rm.h"
+#include "tf_common.h"
+#include "assert.h"
+#include "tf_util.h"
+#include "tfp.h"
+#if (STATS_CLEAR_ON_READ_SUPPORT == 0)
+#include "tf_msg.h"
+#endif
+/***************************
+ * Internal Data Structures
+ ***************************/
+
+/**
+ * TF SRAM block info
+ *
+ * Contains all the information about a particular 64B SRAM
+ * block and the slices within it.
+ */
+struct tf_sram_block {
+	/* Previous block
+	 */
+	struct tf_sram_block *prev;
+	/* Next block
+	 */
+	struct tf_sram_block *next;
+
+	/** Bitmap indicating which slices are in use
+	 *  If a bit is set, it indicates the slice
+	 *  in the row is in use.
+	 */
+	uint8_t in_use_mask;
+
+	/** Block id - this is a 64B offset
+	 */
+	uint16_t block_id;
+};
+
+/**
+ * TF SRAM block list
+ *
+ * List of 64B SRAM blocks used for fixed size slices (8, 16, 32, 64B)
+ */
+struct tf_sram_slice_list {
+	/** Pointer to head of linked list of blocks.
+	 */
+	struct tf_sram_block *head;
+
+	/** Pointer to tail of linked list of blocks.
+	 */
+	struct tf_sram_block *tail;
+
+	/** Total count of blocks
+	 */
+	uint32_t cnt;
+
+	/** First non-full block in the list
+	 */
+	struct tf_sram_block *first_not_full_block;
+
+	/** Entry slice size for this list
+	 */
+	enum tf_sram_slice_size size;
+};
+
+
+/**
+ * TF SRAM bank info consists of lists of different slice sizes per bank
+ */
+struct tf_sram_bank_info {
+	struct tf_sram_slice_list slice[TF_SRAM_SLICE_SIZE_MAX];
+};
+
+/**
+ * SRAM banks consist of SRAM bank information
+ */
+struct tf_sram_bank {
+	struct tf_sram_bank_info bank[TF_SRAM_BANK_ID_MAX];
+};
+
+/**
+ * SRAM banks consist of SRAM bank information
+ */
+struct tf_sram {
+	struct tf_sram_bank dir[TF_DIR_MAX];
+};
+
+/**********************
+ * Internal functions
+ **********************/
+
+/**
+ * Get slice size in string format
+ */
+const char
+*tf_sram_slice_2_str(enum tf_sram_slice_size slice_size)
+{
+	switch (slice_size) {
+	case TF_SRAM_SLICE_SIZE_8B:
+		return "8B slice";
+	case TF_SRAM_SLICE_SIZE_16B:
+		return "16B slice";
+	case TF_SRAM_SLICE_SIZE_32B:
+		return "32B slice";
+	case TF_SRAM_SLICE_SIZE_64B:
+		return "64B slice";
+	default:
+		return "Invalid slice size";
+	}
+}
+
+/**
+ * Get bank in string format
+ */
+const char
+*tf_sram_bank_2_str(enum tf_sram_bank_id bank_id)
+{
+	switch (bank_id) {
+	case TF_SRAM_BANK_ID_0:
+		return "bank_0";
+	case TF_SRAM_BANK_ID_1:
+		return "bank_1";
+	case TF_SRAM_BANK_ID_2:
+		return "bank_2";
+	case TF_SRAM_BANK_ID_3:
+		return "bank_3";
+	default:
+		return "Invalid bank_id";
+	}
+}
+
+/**
+ * TF SRAM get slice list
+ */
+static int
+tf_sram_get_slice_list(struct tf_sram *sram,
+		       struct tf_sram_slice_list **slice_list,
+		       enum tf_sram_slice_size slice_size,
+		       enum tf_dir dir,
+		       enum tf_sram_bank_id bank_id)
+{
+	int rc = 0;
+
+	TF_CHECK_PARMS2(sram, slice_list);
+
+	*slice_list = &sram->dir[dir].bank[bank_id].slice[slice_size];
+
+	return rc;
+}
+
+uint16_t tf_sram_bank_2_base_offset[TF_SRAM_BANK_ID_MAX] = {
+	0,
+	2048,
+	4096,
+	6144
+};
+
+/**
+ * Translate a block id and bank_id to an 8B offset
+ */
+static void
+tf_sram_block_id_2_offset(enum tf_sram_bank_id bank_id, uint16_t block_id,
+			  uint16_t *offset)
+{
+	*offset = (block_id + tf_sram_bank_2_base_offset[bank_id]) << 3;
+}
+
+/**
+ * Translates an 8B offset and bank_id to a block_id
+ */
+static void
+tf_sram_offset_2_block_id(enum tf_sram_bank_id bank_id, uint16_t offset,
+			  uint16_t *block_id, uint16_t *slice_offset)
+{
+	*slice_offset = offset & 0x7;
+	*block_id = ((offset & ~0x7) >> 3) -
+		    tf_sram_bank_2_base_offset[bank_id];
+}
+
+/**
+ * Find a matching block_id within the slice list
+ */
+static struct tf_sram_block
+*tf_sram_find_block(uint16_t block_id, struct tf_sram_slice_list *slice_list)
+{
+	uint32_t cnt;
+	struct tf_sram_block *block;
+
+	cnt = slice_list->cnt;
+	block = slice_list->head;
+
+	while (cnt > 0 && block) {
+		if (block->block_id == block_id)
+			return block;
+		block = block->next;
+		cnt--;
+	}
+	return NULL;
+}
+
+/**
+ * Given the current block get the next block within the slice list
+ *
+ * List is not changed.
+ */
+static struct tf_sram_block
+*tf_sram_get_next_block(struct tf_sram_block *block)
+{
+	struct tf_sram_block *nblock;
+
+	if (block != NULL)
+		nblock = block->next;
+	else
+		nblock = NULL;
+	return nblock;
+}
+
+/**
+ * Free an allocated slice from a block and if the block is empty,
+ * return an indication so that the block can be freed.
+ */
+static int
+tf_sram_free_slice(enum tf_sram_slice_size slice_size,
+		   uint16_t slice_offset, struct tf_sram_block *block,
+		   bool *block_is_empty)
+{
+	int rc = 0;
+	uint8_t shift;
+	uint8_t slice_mask = 0;
+
+	TF_CHECK_PARMS2(block, block_is_empty);
+
+	switch (slice_size) {
+	case TF_SRAM_SLICE_SIZE_8B:
+		shift = slice_offset >> 0;
+		assert(shift < 8);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_16B:
+		shift = slice_offset >> 1;
+		assert(shift < 4);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_32B:
+		shift = slice_offset >> 2;
+		assert(shift < 2);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_64B:
+	default:
+		shift = slice_offset >> 0;
+		assert(shift < 1);
+		slice_mask = 1 << shift;
+		break;
+	}
+
+	if ((block->in_use_mask & slice_mask) == 0) {
+		rc = -EINVAL;
+		TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
+			    block->block_id, slice_offset);
+		return rc;
+	}
+
+	block->in_use_mask &= ~slice_mask;
+
+	if (block->in_use_mask == 0)
+		*block_is_empty = true;
+	else
+		*block_is_empty = false;
+
+	return rc;
+}
+
+/**
+ * TF SRAM get next slice
+ *
+ * Gets the next slice_offset available in the block
+ * and updates the in_use_mask.
+ */
+static int
+tf_sram_get_next_slice_in_block(struct tf_sram_block *block,
+				enum tf_sram_slice_size slice_size,
+				uint16_t *slice_offset,
+				bool *block_is_full)
+{
+	int rc, free_id = -1;
+	uint8_t shift, max_slices, mask, i, full_mask;
+
+	TF_CHECK_PARMS3(block, slice_offset, block_is_full);
+
+	switch (slice_size) {
+	case TF_SRAM_SLICE_SIZE_8B:
+		shift      = 0;
+		max_slices = 8;
+		full_mask  = 0xff;
+		break;
+	case TF_SRAM_SLICE_SIZE_16B:
+		shift      = 1;
+		max_slices = 4;
+		full_mask  = 0xf;
+		break;
+	case TF_SRAM_SLICE_SIZE_32B:
+		shift      = 2;
+		max_slices = 2;
+		full_mask  = 0x3;
+		break;
+	case TF_SRAM_SLICE_SIZE_64B:
+	default:
+		shift      = 0;
+		max_slices = 1;
+		full_mask  = 1;
+		break;
+	}
+
+	mask = block->in_use_mask;
+
+	for (i = 0; i < max_slices; i++) {
+		if ((mask & 1) == 0) {
+			free_id = i;
+			block->in_use_mask |= 1 << free_id;
+			break;
+		}
+		mask = mask >> 1;
+	}
+
+	if (block->in_use_mask == full_mask)
+		*block_is_full = true;
+	else
+		*block_is_full = false;
+
+
+	if (free_id >= 0) {
+		*slice_offset = free_id << shift;
+		rc = 0;
+	} else {
+		*slice_offset = 0;
+		rc = -ENOMEM;
+	}
+
+	return rc;
+}
+
+/**
+ * TF SRAM get indication as to whether the slice offset is
+ * allocated in the block.
+ *
+ */
+static int
+tf_sram_is_slice_allocated_in_block(struct tf_sram_block *block,
+				    enum tf_sram_slice_size slice_size,
+				    uint16_t slice_offset,
+				    bool *is_allocated)
+{
+	int rc = 0;
+	uint8_t shift;
+	uint8_t slice_mask = 0;
+
+	TF_CHECK_PARMS2(block, is_allocated);
+
+	*is_allocated = false;
+
+	switch (slice_size) {
+	case TF_SRAM_SLICE_SIZE_8B:
+		shift = slice_offset >> 0;
+		assert(shift < 8);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_16B:
+		shift = slice_offset >> 1;
+		assert(shift < 4);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_32B:
+		shift = slice_offset >> 2;
+		assert(shift < 2);
+		slice_mask = 1 << shift;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_64B:
+	default:
+		shift = slice_offset >> 0;
+		assert(shift < 1);
+		slice_mask = 1 << shift;
+		break;
+	}
+
+	if ((block->in_use_mask & slice_mask) == 0) {
+		TFP_DRV_LOG(ERR, "block_id(0x%x) slice(%d) was not allocated\n",
+			    block->block_id, slice_offset);
+		*is_allocated = false;
+	} else {
+		*is_allocated = true;
+	}
+
+	return rc;
+}
+
+/**
+ * Initialize slice list
+ */
+static void
+tf_sram_init_slice_list(struct tf_sram_slice_list *slice_list,
+			enum tf_sram_slice_size slice_size)
+{
+	slice_list->head = NULL;
+	slice_list->tail = NULL;
+	slice_list->cnt = 0;
+	slice_list->size = slice_size;
+}
+
+/**
+ * Get the block count
+ */
+static uint32_t
+tf_sram_get_block_cnt(struct tf_sram_slice_list *slice_list)
+{
+	return slice_list->cnt;
+}
+
+
+/**
+ * Free a block data structure - does not free to the RM
+ */
+static void
+tf_sram_free_block(struct tf_sram_slice_list *slice_list,
+		   struct tf_sram_block *block)
+{
+	if (slice_list->head == block && slice_list->tail == block) {
+		slice_list->head = NULL;
+		slice_list->tail = NULL;
+	} else if (slice_list->head == block) {
+		slice_list->head = block->next;
+		slice_list->head->prev = NULL;
+	} else if (slice_list->tail == block) {
+		slice_list->tail = block->prev;
+		slice_list->tail->next = NULL;
+	} else {
+		block->prev->next = block->next;
+		block->next->prev = block->prev;
+	}
+	tfp_free(block);
+	slice_list->cnt--;
+}
+/**
+ * Free the entire slice_list
+ */
+static void
+tf_sram_free_slice_list(struct tf_sram_slice_list *slice_list)
+{
+	uint32_t i, block_cnt;
+	struct tf_sram_block *nblock, *block;
+
+	block_cnt = tf_sram_get_block_cnt(slice_list);
+	block = slice_list->head;
+
+	for (i = 0; i < block_cnt; i++) {
+		nblock = block->next;
+		tf_sram_free_block(slice_list, block);
+		block = nblock;
+	}
+}
+
+/**
+ * Allocate a single SRAM block from memory and add it to the slice list
+ */
+static struct tf_sram_block
+*tf_sram_alloc_block(struct tf_sram_slice_list *slice_list,
+		     uint16_t block_id)
+{
+	struct tf_sram_block *block;
+	struct tfp_calloc_parms cparms;
+	int rc;
+
+	cparms.nitems = 1;
+	cparms.size = sizeof(struct tf_sram_block);
+	cparms.alignment = 0;
+	rc = tfp_calloc(&cparms);
+	if (rc) {
+		/* Log error */
+		TFP_DRV_LOG(ERR,
+			    "Failed to allocate block, rc:%s\n",
+			    strerror(-rc));
+		return NULL;
+	}
+	block = (struct tf_sram_block *)cparms.mem_va;
+	block->block_id = block_id;
+
+	if (slice_list->head == NULL) {
+		slice_list->head = block;
+		slice_list->tail = block;
+		block->next = NULL;
+		block->prev = NULL;
+	} else {
+		block->next = slice_list->head;
+		block->prev = NULL;
+		block->next->prev = block;
+		slice_list->head = block->next->prev;
+	}
+	slice_list->cnt++;
+	return block;
+}
+
+/**
+ * Find the first not full block in the slice list
+ */
+static void
+tf_sram_find_first_not_full_block(struct tf_sram_slice_list *slice_list,
+				  enum tf_sram_slice_size slice_size,
+				  struct tf_sram_block **first_not_full_block)
+{
+	struct tf_sram_block *block = slice_list->head;
+	uint8_t slice_mask, mask;
+
+	switch (slice_size) {
+	case TF_SRAM_SLICE_SIZE_8B:
+		slice_mask = 0xff;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_16B:
+		slice_mask = 0xf;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_32B:
+		slice_mask = 0x3;
+		break;
+
+	case TF_SRAM_SLICE_SIZE_64B:
+	default:
+		slice_mask = 0x1;
+		break;
+	}
+
+	*first_not_full_block = NULL;
+
+	while (block) {
+		mask = block->in_use_mask & slice_mask;
+		if (mask != slice_mask) {
+			*first_not_full_block = block;
+			break;
+		}
+		block = block->next;
+	}
+}
+static void
+tf_sram_dump_block(struct tf_sram_block *block)
+{
+	TFP_DRV_LOG(INFO, "block_id(0x%x) in_use_mask(0x%02x)\n",
+		    block->block_id,
+		    block->in_use_mask);
+}
+
+/**********************
+ * External functions
+ **********************/
+int
+tf_sram_mgr_bind(void **sram_handle)
+{
+	int rc = 0;
+	enum tf_sram_bank_id bank_id;
+	enum tf_sram_slice_size slice_size;
+	struct tf_sram *sram;
+	struct tf_sram_slice_list *slice_list;
+	enum tf_dir dir;
+	struct tfp_calloc_parms cparms;
+
+	TF_CHECK_PARMS1(sram_handle);
+
+	cparms.nitems = 1;
+	cparms.size = sizeof(struct tf_sram);
+	cparms.alignment = 0;
+	rc = tfp_calloc(&cparms);
+	if (rc) {
+		/* Log error */
+		TFP_DRV_LOG(ERR,
+			    "Failed to allocate SRAM mgmt data, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	sram = (struct tf_sram *)cparms.mem_va;
+
+	/* For each direction
+	 */
+	for (dir = 0; dir < TF_DIR_MAX; dir++) {
+		/* For each bank
+		 */
+		for (bank_id = TF_SRAM_BANK_ID_0;
+		     bank_id < TF_SRAM_BANK_ID_MAX;
+		     bank_id++) {
+			/* Create each sized slice empty list
+			 */
+			for (slice_size = TF_SRAM_SLICE_SIZE_8B;
+			     slice_size < TF_SRAM_SLICE_SIZE_MAX;
+			     slice_size++) {
+				rc = tf_sram_get_slice_list(sram, &slice_list,
+							    slice_size, dir,
+							    bank_id);
+				if (rc) {
+					/* Log error */
+					TFP_DRV_LOG(ERR,
+						  "No SRAM slice list, rc:%s\n",
+						  strerror(-rc));
+					return rc;
+				}
+				tf_sram_init_slice_list(slice_list, slice_size);
+			}
+		}
+	}
+
+	*sram_handle = sram;
+
+	return rc;
+}
+
+int
+tf_sram_mgr_unbind(void *sram_handle)
+{
+	int rc = 0;
+	struct tf_sram *sram;
+	enum tf_sram_bank_id bank_id;
+	enum tf_sram_slice_size slice_size;
+	enum tf_dir dir;
+	struct tf_sram_slice_list *slice_list;
+
+	TF_CHECK_PARMS1(sram_handle);
+
+	sram = (struct tf_sram *)sram_handle;
+
+	for (dir = 0; dir < TF_DIR_MAX; dir++) {
+		/* For each bank
+		 */
+		for (bank_id = TF_SRAM_BANK_ID_0;
+		     bank_id < TF_SRAM_BANK_ID_MAX;
+		     bank_id++) {
+			/* For each slice size
+			 */
+			for (slice_size = TF_SRAM_SLICE_SIZE_8B;
+			     slice_size < TF_SRAM_SLICE_SIZE_MAX;
+			     slice_size++) {
+				rc = tf_sram_get_slice_list(sram, &slice_list,
+							    slice_size, dir,
+							    bank_id);
+				if (rc) {
+					/* Log error */
+					TFP_DRV_LOG(ERR,
+						  "No SRAM slice list, rc:%s\n",
+						  strerror(-rc));
+					return rc;
+				}
+				if (tf_sram_get_block_cnt(slice_list))
+					tf_sram_free_slice_list(slice_list);
+			}
+		}
+	}
+
+	tfp_free(sram);
+	sram_handle = NULL;
+
+	/* Freeing of the RM resources is handled by the table manager */
+	return rc;
+}
+
+int tf_sram_mgr_alloc(void *sram_handle,
+		      struct tf_sram_mgr_alloc_parms *parms)
+{
+	int rc = 0;
+	struct tf_sram *sram;
+	struct tf_sram_slice_list *slice_list;
+	uint16_t block_id, slice_offset = 0;
+	uint32_t index;
+	struct tf_sram_block *block;
+	struct tf_rm_allocate_parms aparms = { 0 };
+	bool block_is_full;
+	uint16_t block_offset;
+
+	TF_CHECK_PARMS3(sram_handle, parms, parms->sram_offset);
+
+	sram = (struct tf_sram *)sram_handle;
+
+	/* Check the current slice list
+	 */
+	rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
+				    parms->dir, parms->bank_id);
+	if (rc) {
+		/* Log error */
+		TFP_DRV_LOG(ERR,
+			    "No SRAM slice list, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* If the list is empty or all entries are full allocate a new block
+	 */
+	if (!slice_list->first_not_full_block) {
+		/* Allocate and insert a new block
+		 */
+		aparms.index = &index;
+		aparms.subtype = parms->tbl_type;
+		aparms.rm_db = parms->rm_db;
+		rc = tf_rm_allocate(&aparms);
+		if (rc)
+			return rc;
+
+		block_id = index;
+		block = tf_sram_alloc_block(slice_list, block_id);
+	} else {
+		/* Block exists
+		 */
+		block =
+		 (struct tf_sram_block *)(slice_list->first_not_full_block);
+	}
+	rc = tf_sram_get_next_slice_in_block(block,
+					     parms->slice_size,
+					     &slice_offset,
+					     &block_is_full);
+
+	/* Find the new first non-full block in the list
+	 */
+	tf_sram_find_first_not_full_block(slice_list,
+					  parms->slice_size,
+					  &slice_list->first_not_full_block);
+
+	tf_sram_block_id_2_offset(parms->bank_id, block->block_id,
+				  &block_offset);
+
+	*parms->sram_offset = block_offset + slice_offset;
+	return rc;
+}
+
+int
+tf_sram_mgr_free(void *sram_handle,
+		 struct tf_sram_mgr_free_parms *parms)
+{
+	int rc = 0;
+	struct tf_sram *sram;
+	struct tf_sram_slice_list *slice_list;
+	uint16_t block_id, slice_offset;
+	struct tf_sram_block *block;
+	bool block_is_empty;
+	struct tf_rm_free_parms fparms = { 0 };
+
+	TF_CHECK_PARMS2(sram_handle, parms);
+
+	sram = (struct tf_sram *)sram_handle;
+
+	/* Check the current slice list
+	 */
+	rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
+				    parms->dir, parms->bank_id);
+	if (rc) {
+		/* Log error */
+		TFP_DRV_LOG(ERR,
+			    "No SRAM slice list, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* Determine the block id and slice offset from the SRAM offset
+	 */
+	tf_sram_offset_2_block_id(parms->bank_id, parms->sram_offset, &block_id,
+				  &slice_offset);
+
+	/* Search the list of blocks for the matching block id
+	 */
+	block = tf_sram_find_block(block_id, slice_list);
+	if (block == NULL) {
+		TFP_DRV_LOG(ERR, "block not found 0x%x\n", block_id);
+		return rc;
+	}
+
+	/* If found, search for the matching SRAM slice in use.
+	 */
+	rc = tf_sram_free_slice(parms->slice_size, slice_offset,
+				block, &block_is_empty);
+	if (rc) {
+		TFP_DRV_LOG(ERR, "Error freeing slice (%s)\n", strerror(-rc));
+		return rc;
+	}
+#if (STATS_CLEAR_ON_READ_SUPPORT == 0)
+	/* If this is a counter, clear it.  In the future we need to switch to
+	 * using the special access registers on Thor to automatically clear on
+	 * read.
+	 */
+	/* If this is counter table, clear the entry on free */
+	if (parms->tbl_type == TF_TBL_TYPE_ACT_STATS_64) {
+		uint8_t data[8] = { 0 };
+		uint16_t hcapi_type = 0;
+		struct tf_rm_get_hcapi_parms hparms = { 0 };
+
+		/* Get the hcapi type */
+		hparms.rm_db = parms->rm_db;
+		hparms.subtype = parms->tbl_type;
+		hparms.hcapi_type = &hcapi_type;
+		rc = tf_rm_get_hcapi_type(&hparms);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s, Failed type lookup, type:%s, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    tf_tbl_type_2_str(parms->tbl_type),
+				    strerror(-rc));
+			return rc;
+		}
+		/* Clear the counter
+		 */
+		rc = tf_msg_set_tbl_entry(parms->tfp,
+					  parms->dir,
+					  hcapi_type,
+					  sizeof(data),
+					  data,
+					  parms->sram_offset);
+		if (rc) {
+			TFP_DRV_LOG(ERR,
+				    "%s, Set failed, type:%s, rc:%s\n",
+				    tf_dir_2_str(parms->dir),
+				    tf_tbl_type_2_str(parms->tbl_type),
+				    strerror(-rc));
+			return rc;
+		}
+	}
+#endif
+	/* If the block is empty, free the block to the RM
+	 */
+	if (block_is_empty) {
+		fparms.rm_db = parms->rm_db;
+		fparms.subtype = parms->tbl_type;
+		fparms.index = block_id;
+		rc = tf_rm_free(&fparms);
+
+		if (rc) {
+			TFP_DRV_LOG(ERR, "Free block_id(%d) failed error(%s)\n",
+				    block_id, strerror(-rc));
+		}
+		/* Free local entry regardless
+		 */
+		tf_sram_free_block(slice_list, block);
+
+		/* Find the next non-full block in the list
+		 */
+		tf_sram_find_first_not_full_block(slice_list,
+					     parms->slice_size,
+					     &slice_list->first_not_full_block);
+	}
+
+	return rc;
+}
+
+int
+tf_sram_mgr_dump(void *sram_handle,
+		 struct tf_sram_mgr_dump_parms *parms)
+{
+	int rc = 0;
+	struct tf_sram *sram;
+	struct tf_sram_slice_list *slice_list;
+	uint32_t block_cnt, i;
+	struct tf_sram_block *block;
+
+	TF_CHECK_PARMS2(sram_handle, parms);
+
+	sram = (struct tf_sram *)sram_handle;
+
+	rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
+				    parms->dir, parms->bank_id);
+	if (rc)
+		return rc;
+
+	if (slice_list->cnt || slice_list->first_not_full_block) {
+		TFP_DRV_LOG(INFO, "\n********** %s: %s: %s ***********\n",
+			    tf_sram_bank_2_str(parms->bank_id),
+			    tf_dir_2_str(parms->dir),
+			    tf_sram_slice_2_str(parms->slice_size));
+
+		block_cnt = tf_sram_get_block_cnt(slice_list);
+		TFP_DRV_LOG(INFO, "block_cnt(%d)\n", block_cnt);
+		if (slice_list->first_not_full_block)
+			TFP_DRV_LOG(INFO, "first_not_full_block(0x%x)\n",
+			    slice_list->first_not_full_block->block_id);
+		block = slice_list->head;
+		for (i = 0; i < block_cnt; i++) {
+			tf_sram_dump_block(block);
+			block = tf_sram_get_next_block(block);
+		}
+		TFP_DRV_LOG(INFO, "*********************************\n");
+	}
+	return rc;
+}
+/**
+ * Validate an SRAM Slice is allocated
+ *
+ * Validate whether the SRAM slice is allocated
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM alloc parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+int tf_sram_mgr_is_allocated(void *sram_handle,
+			     struct tf_sram_mgr_is_allocated_parms *parms)
+{
+	int rc = 0;
+	struct tf_sram *sram;
+	struct tf_sram_slice_list *slice_list;
+	uint16_t block_id, slice_offset;
+	struct tf_sram_block *block;
+
+	TF_CHECK_PARMS3(sram_handle, parms, parms->is_allocated);
+
+	sram = (struct tf_sram *)sram_handle;
+
+	/* Check the current slice list
+	 */
+	rc = tf_sram_get_slice_list(sram, &slice_list, parms->slice_size,
+				    parms->dir, parms->bank_id);
+	if (rc) {
+		/* Log error */
+		TFP_DRV_LOG(ERR,
+			    "No SRAM slice list, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* If the list is empty, then it cannot be allocated
+	 */
+	if (!slice_list->cnt) {
+		TFP_DRV_LOG(ERR, "List is empty for %s:%s:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_sram_slice_2_str(parms->slice_size),
+			    tf_sram_bank_2_str(parms->bank_id));
+
+		parms->is_allocated = false;
+		goto done;
+	}
+
+	/* Determine the block id and slice offset from the SRAM offset
+	 */
+	tf_sram_offset_2_block_id(parms->bank_id, parms->sram_offset, &block_id,
+				  &slice_offset);
+
+	/* Search the list of blocks for the matching block id
+	 */
+	block = tf_sram_find_block(block_id, slice_list);
+	if (block == NULL) {
+		TFP_DRV_LOG(ERR, "block not found in list 0x%x\n",
+			    parms->sram_offset);
+		parms->is_allocated = false;
+		goto done;
+	}
+
+	rc = tf_sram_is_slice_allocated_in_block(block,
+						 parms->slice_size,
+						 slice_offset,
+						 parms->is_allocated);
+done:
+	return rc;
+}
diff --git a/drivers/net/bnxt/tf_core/tf_sram_mgr.h b/drivers/net/bnxt/tf_core/tf_sram_mgr.h
new file mode 100644
index 0000000000..4abe3fb468
--- /dev/null
+++ b/drivers/net/bnxt/tf_core/tf_sram_mgr.h
@@ -0,0 +1,317 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2021 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _TF_SRAM_MGR_H_
+#define _TF_SRAM_MGR_H_
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include "tf_core.h"
+#include "tf_rm.h"
+
+/* When special access registers are used to access the SRAM, stats can be
+ * automatically cleared on read by the hardware.  This requires additional
+ * support to be added in the firmware to use these registers for statistics.
+ * The support entails using the special access registers to read the stats.
+ * These are stored in bank 3 currently but may move depending upon the
+ * policy defined in tf_device_p58.h
+ */
+#define STATS_CLEAR_ON_READ_SUPPORT 0
+
+#define TF_SRAM_MGR_BLOCK_SZ_BYTES 64
+#define TF_SRAM_MGR_MIN_SLICE_BYTES 8
+/**
+ * Bank identifier
+ */
+enum tf_sram_bank_id {
+	TF_SRAM_BANK_ID_0,		/**< SRAM Bank 0 id */
+	TF_SRAM_BANK_ID_1,		/**< SRAM Bank 1 id */
+	TF_SRAM_BANK_ID_2,		/**< SRAM Bank 2 id */
+	TF_SRAM_BANK_ID_3,		/**< SRAM Bank 3 id */
+	TF_SRAM_BANK_ID_MAX		/**< SRAM Bank index limit */
+};
+
+/**
+ * TF slice size.
+ *
+ * A slice is part of a 64B row
+ *
+ * Each slice is a multiple of 8B
+ */
+enum tf_sram_slice_size {
+	TF_SRAM_SLICE_SIZE_8B,	/**< 8 byte SRAM slice */
+	TF_SRAM_SLICE_SIZE_16B,	/**< 16 byte SRAM slice */
+	TF_SRAM_SLICE_SIZE_32B,	/**< 32 byte SRAM slice */
+	TF_SRAM_SLICE_SIZE_64B,	/**< 64 byte SRAM slice */
+	TF_SRAM_SLICE_SIZE_MAX  /**< slice limit */
+};
+
+
+/** Initialize the SRAM slice manager
+ *
+ *  The SRAM slice manager manages slices within 64B rows. Slices are of size
+ *  tf_sram_slice_size.  This function provides a handle to the SRAM manager
+ *  data.
+ *
+ *  SRAM manager data may dynamically allocate data upon initialization if
+ *  running on the host.
+ *
+ * [in/out] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ * Returns the handle for the SRAM slice manager
+ */
+int tf_sram_mgr_bind(void **sram_handle);
+
+/** Uninitialize the SRAM slice manager
+ *
+ * Frees any dynamically allocated data structures for SRAM slice management.
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ */
+int tf_sram_mgr_unbind(void *sram_handle);
+
+/**
+ * tf_sram_mgr_alloc_parms parameter definition
+ */
+struct tf_sram_mgr_alloc_parms {
+	/**
+	 * [in] dir
+	 */
+	enum tf_dir dir;
+	/**
+	 * [in] bank
+	 *
+	 *  the SRAM bank to allocate from
+	 */
+	enum tf_sram_bank_id bank_id;
+	/**
+	 * [in] slice_size
+	 *
+	 *  the slice size to allocate
+	 */
+	enum tf_sram_slice_size slice_size;
+	/**
+	 * [in/out] sram_slice
+	 *
+	 *  A pointer to be filled with an 8B sram slice offset
+	 */
+	uint16_t *sram_offset;
+	/**
+	 * [in] RM DB Handle required for RM allocation
+	 */
+	void *rm_db;
+	/**
+	 * [in] tf table type
+	 */
+	enum tf_tbl_type tbl_type;
+};
+
+/**
+ * Allocate an SRAM Slice
+ *
+ * Allocate an SRAM slice from the indicated bank.  If successful an 8B SRAM
+ * offset will be returned.  Slices are variable sized.  This may result in
+ * a row being allocated from the RM SRAM bank pool if required.
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM alloc parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+int tf_sram_mgr_alloc(void *sram_handle,
+		      struct tf_sram_mgr_alloc_parms *parms);
+/**
+ * tf_sram_mgr_free_parms parameter definition
+ */
+struct tf_sram_mgr_free_parms {
+	/**
+	 * [in] dir
+	 */
+	enum tf_dir dir;
+	/**
+	 * [in] bank
+	 *
+	 *  the SRAM bank to free to
+	 */
+	enum tf_sram_bank_id bank_id;
+	/**
+	 * [in] slice_size
+	 *
+	 *  the slice size to be returned
+	 */
+	enum tf_sram_slice_size slice_size;
+	/**
+	 * [in] sram_offset
+	 *
+	 *  the SRAM slice offset (8B) to be returned
+	 */
+	uint16_t sram_offset;
+	/**
+	 * [in] RM DB Handle required for RM free
+	 */
+	void *rm_db;
+	/**
+	 * [in] tf table type
+	 */
+	enum tf_tbl_type tbl_type;
+#if (STATS_CLEAR_ON_READ_SUPPORT == 0)
+	/**
+	 * [in] tfp
+	 *
+	 * A pointer to the tf handle
+	 */
+	void *tfp;
+#endif
+};
+
+/**
+ * Free an SRAM Slice
+ *
+ * Free an SRAM slice to the indicated bank.  This may result in a 64B row
+ * being returned to the RM SRAM bank pool.
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM free parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+int tf_sram_mgr_free(void *sram_handle,
+		     struct tf_sram_mgr_free_parms *parms);
+
+/**
+ * tf_sram_mgr_dump_parms parameter definition
+ */
+struct tf_sram_mgr_dump_parms {
+	/**
+	 * [in] dir
+	 */
+	enum tf_dir dir;
+	/**
+	 * [in] bank
+	 *
+	 *  the SRAM bank to dump
+	 */
+	enum tf_sram_bank_id bank_id;
+	/**
+	 * [in] slice_size
+	 *
+	 *  the slice size list to be dumped
+	 */
+	enum tf_sram_slice_size slice_size;
+};
+
+/**
+ * Dump a slice list
+ *
+ * Dump the slice list given the SRAM bank and the slice size
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM free parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+int tf_sram_mgr_dump(void *sram_handle,
+		     struct tf_sram_mgr_dump_parms *parms);
+
+/**
+ * tf_sram_mgr_is_allocated_parms parameter definition
+ */
+struct tf_sram_mgr_is_allocated_parms {
+	/**
+	 * [in] dir
+	 */
+	enum tf_dir dir;
+	/**
+	 * [in] bank
+	 *
+	 *  the SRAM bank to allocate from
+	 */
+	enum tf_sram_bank_id bank_id;
+	/**
+	 * [in] slice_size
+	 *
+	 *  the slice size which was allocated
+	 */
+	enum tf_sram_slice_size slice_size;
+	/**
+	 * [in] sram_offset
+	 *
+	 *  The sram slice offset to validate
+	 */
+	uint16_t sram_offset;
+	/**
+	 * [in/out] is_allocated
+	 *
+	 *  Pointer passed in to be filled with indication of allocation
+	 */
+	bool *is_allocated;
+};
+
+/**
+ * Validate an SRAM Slice is allocated
+ *
+ * Validate whether the SRAM slice is allocated
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM alloc parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+int tf_sram_mgr_is_allocated(void *sram_handle,
+			     struct tf_sram_mgr_is_allocated_parms *parms);
+
+/**
+ * Given the slice size, return a char string
+ */
+const char
+*tf_sram_slice_2_str(enum tf_sram_slice_size slice_size);
+
+/**
+ * Given the bank_id, return a char string
+ */
+const char
+*tf_sram_bank_2_str(enum tf_sram_bank_id bank_id);
+
+#endif /* _TF_SRAM_MGR_H_ */
diff --git a/drivers/net/bnxt/tf_core/tf_tbl.c b/drivers/net/bnxt/tf_core/tf_tbl.c
index 7011edcd78..0a8720e7b6 100644
--- a/drivers/net/bnxt/tf_core/tf_tbl.c
+++ b/drivers/net/bnxt/tf_core/tf_tbl.c
@@ -16,20 +16,11 @@
 #include "tf_session.h"
 #include "tf_device.h"
 
-#define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) {		\
-		*(new_idx) = (((idx) + (base)) << (shift));	\
-}
-
-#define TF_TBL_PTR_TO_RM(new_idx, idx, base, shift) {		\
-		*(new_idx) = (((idx) >> (shift)) - (base));	\
-}
-
 struct tf;
 
-/**
- * Shadow init flag, set on bind and cleared on unbind
- */
-static uint8_t shadow_init;
+#define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) {          \
+		*(new_idx) = (((idx) + (base)) << (shift));    \
+}
 
 int
 tf_tbl_bind(struct tf *tfp,
@@ -121,8 +112,6 @@ tf_tbl_unbind(struct tf *tfp)
 		tbl_db->tbl_db[i] = NULL;
 	}
 
-	shadow_init = 0;
-
 	return 0;
 }
 
@@ -135,7 +124,6 @@ tf_tbl_alloc(struct tf *tfp __rte_unused,
 	struct tf_rm_allocate_parms aparms = { 0 };
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
-	uint16_t base = 0, shift = 0;
 	struct tbl_rm_db *tbl_db;
 	void *tbl_db_ptr = NULL;
 
@@ -154,28 +142,12 @@ tf_tbl_alloc(struct tf *tfp __rte_unused,
 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "Failed to get em_ext_db from session, rc:%s\n",
+			    "Failed to get tbl_db from session, rc:%s\n",
 			    strerror(-rc));
 		return rc;
 	}
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* Only get table info if required for the device */
-	if (dev->ops->tf_dev_get_tbl_info) {
-		rc = dev->ops->tf_dev_get_tbl_info(tfp,
-						   tbl_db->tbl_db[parms->dir],
-						   parms->type,
-						   &base,
-						   &shift);
-		if (rc) {
-			TFP_DRV_LOG(ERR,
-				    "%s: Failed to get table info:%d\n",
-				    tf_dir_2_str(parms->dir),
-				    parms->type);
-			return rc;
-		}
-	}
-
 	/* Allocate requested element */
 	aparms.rm_db = tbl_db->tbl_db[parms->dir];
 	aparms.subtype = parms->type;
@@ -183,13 +155,12 @@ tf_tbl_alloc(struct tf *tfp __rte_unused,
 	rc = tf_rm_allocate(&aparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s: Failed allocate, type:%d\n",
+			    "%s: Failed allocate, type:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type);
+			    tf_tbl_type_2_str(parms->type));
 		return rc;
 	}
 
-	TF_TBL_RM_TO_PTR(&idx, idx, base, shift);
 	*parms->idx = idx;
 
 	return 0;
@@ -205,7 +176,6 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 	int allocated = 0;
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
-	uint16_t base = 0, shift = 0;
 	struct tbl_rm_db *tbl_db;
 	void *tbl_db_ptr = NULL;
 
@@ -230,28 +200,10 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 	}
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* Only get table info if required for the device */
-	if (dev->ops->tf_dev_get_tbl_info) {
-		rc = dev->ops->tf_dev_get_tbl_info(tfp,
-						   tbl_db->tbl_db[parms->dir],
-						   parms->type,
-						   &base,
-						   &shift);
-		if (rc) {
-			TFP_DRV_LOG(ERR,
-				    "%s: Failed to get table info:%d\n",
-				    tf_dir_2_str(parms->dir),
-				    parms->type);
-			return rc;
-		}
-	}
-
 	/* Check if element is in use */
 	aparms.rm_db = tbl_db->tbl_db[parms->dir];
 	aparms.subtype = parms->type;
-
-	TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
-
+	aparms.index = parms->idx;
 	aparms.allocated = &allocated;
 	rc = tf_rm_is_allocated(&aparms);
 	if (rc)
@@ -259,9 +211,9 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 
 	if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
 		TFP_DRV_LOG(ERR,
-			    "%s: Entry already free, type:%d, index:%d\n",
+			    "%s: Entry already free, type:%s, index:%d\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    parms->idx);
 		return -EINVAL;
 	}
@@ -279,9 +231,9 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 		rc = tf_rm_get_hcapi_type(&hparms);
 		if (rc) {
 			TFP_DRV_LOG(ERR,
-				    "%s, Failed type lookup, type:%d, rc:%s\n",
+				    "%s, Failed type lookup, type:%s, rc:%s\n",
 				    tf_dir_2_str(parms->dir),
-				    parms->type,
+				    tf_tbl_type_2_str(parms->type),
 				    strerror(-rc));
 			return rc;
 		}
@@ -295,9 +247,9 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 					  parms->idx);
 		if (rc) {
 			TFP_DRV_LOG(ERR,
-				    "%s, Set failed, type:%d, rc:%s\n",
+				    "%s, Set failed, type:%s, rc:%s\n",
 				    tf_dir_2_str(parms->dir),
-				    parms->type,
+				    tf_tbl_type_2_str(parms->type),
 				    strerror(-rc));
 			return rc;
 		}
@@ -306,15 +258,13 @@ tf_tbl_free(struct tf *tfp __rte_unused,
 	/* Free requested element */
 	fparms.rm_db = tbl_db->tbl_db[parms->dir];
 	fparms.subtype = parms->type;
-
-	TF_TBL_PTR_TO_RM(&fparms.index, parms->idx, base, shift);
-
+	fparms.index = parms->idx;
 	rc = tf_rm_free(&fparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s: Free failed, type:%d, index:%d\n",
+			    "%s: Free failed, type:%s, index:%d\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    parms->idx);
 		return rc;
 	}
@@ -333,7 +283,6 @@ tf_tbl_set(struct tf *tfp,
 	struct tf_rm_get_hcapi_parms hparms = { 0 };
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
-	uint16_t base = 0, shift = 0;
 	struct tbl_rm_db *tbl_db;
 	void *tbl_db_ptr = NULL;
 
@@ -358,21 +307,6 @@ tf_tbl_set(struct tf *tfp,
 	}
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* Only get table info if required for the device */
-	if (dev->ops->tf_dev_get_tbl_info) {
-		rc = dev->ops->tf_dev_get_tbl_info(tfp,
-						   tbl_db->tbl_db[parms->dir],
-						   parms->type,
-						   &base,
-						   &shift);
-		if (rc) {
-			TFP_DRV_LOG(ERR,
-				    "%s: Failed to get table info:%d\n",
-				    tf_dir_2_str(parms->dir),
-				    parms->type);
-			return rc;
-		}
-	}
 
 	/* Do not check meter drop counter because it is not allocated
 	 * resources
@@ -381,19 +315,18 @@ tf_tbl_set(struct tf *tfp,
 		/* Verify that the entry has been previously allocated */
 		aparms.rm_db = tbl_db->tbl_db[parms->dir];
 		aparms.subtype = parms->type;
-		TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
-
 		aparms.allocated = &allocated;
+		aparms.index = parms->idx;
 		rc = tf_rm_is_allocated(&aparms);
 		if (rc)
 			return rc;
 
 		if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
 			TFP_DRV_LOG(ERR,
-			   "%s, Invalid or not allocated index, type:%d, idx:%d\n",
-			   tf_dir_2_str(parms->dir),
-			   parms->type,
-			   parms->idx);
+			      "%s, Invalid or not allocated, type:%s, idx:%d\n",
+			      tf_dir_2_str(parms->dir),
+			      tf_tbl_type_2_str(parms->type),
+			      parms->idx);
 			return -EINVAL;
 		}
 	}
@@ -405,9 +338,9 @@ tf_tbl_set(struct tf *tfp,
 	rc = tf_rm_get_hcapi_type(&hparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Failed type lookup, type:%d, rc:%s\n",
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 		return rc;
 	}
@@ -420,9 +353,9 @@ tf_tbl_set(struct tf *tfp,
 				  parms->idx);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Set failed, type:%d, rc:%s\n",
+			    "%s, Set failed, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 		return rc;
 	}
@@ -441,7 +374,6 @@ tf_tbl_get(struct tf *tfp,
 	struct tf_rm_get_hcapi_parms hparms = { 0 };
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
-	uint16_t base = 0, shift = 0;
 	struct tbl_rm_db *tbl_db;
 	void *tbl_db_ptr = NULL;
 
@@ -466,22 +398,6 @@ tf_tbl_get(struct tf *tfp,
 	}
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* Only get table info if required for the device */
-	if (dev->ops->tf_dev_get_tbl_info) {
-		rc = dev->ops->tf_dev_get_tbl_info(tfp,
-						   tbl_db->tbl_db[parms->dir],
-						   parms->type,
-						   &base,
-						   &shift);
-		if (rc) {
-			TFP_DRV_LOG(ERR,
-				    "%s: Failed to get table info:%d\n",
-				    tf_dir_2_str(parms->dir),
-				    parms->type);
-			return rc;
-		}
-	}
-
 	/* Do not check meter drop counter because it is not allocated
 	 * resources.
 	 */
@@ -489,8 +405,7 @@ tf_tbl_get(struct tf *tfp,
 		/* Verify that the entry has been previously allocated */
 		aparms.rm_db = tbl_db->tbl_db[parms->dir];
 		aparms.subtype = parms->type;
-		TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
-
+		aparms.index = parms->idx;
 		aparms.allocated = &allocated;
 		rc = tf_rm_is_allocated(&aparms);
 		if (rc)
@@ -498,9 +413,9 @@ tf_tbl_get(struct tf *tfp,
 
 		if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
 			TFP_DRV_LOG(ERR,
-			   "%s, Invalid or not allocated index, type:%d, idx:%d\n",
+			   "%s, Invalid or not allocated index, type:%s, idx:%d\n",
 			   tf_dir_2_str(parms->dir),
-			   parms->type,
+			   tf_tbl_type_2_str(parms->type),
 			   parms->idx);
 			return -EINVAL;
 		}
@@ -513,9 +428,9 @@ tf_tbl_get(struct tf *tfp,
 	rc = tf_rm_get_hcapi_type(&hparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Failed type lookup, type:%d, rc:%s\n",
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 		return rc;
 	}
@@ -529,9 +444,9 @@ tf_tbl_get(struct tf *tfp,
 				  parms->idx);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Get failed, type:%d, rc:%s\n",
+			    "%s, Get failed, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 		return rc;
 	}
@@ -549,7 +464,6 @@ tf_tbl_bulk_get(struct tf *tfp,
 	struct tf_rm_check_indexes_in_range_parms cparms = { 0 };
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
-	uint16_t base = 0, shift = 0;
 	struct tbl_rm_db *tbl_db;
 	void *tbl_db_ptr = NULL;
 
@@ -574,40 +488,21 @@ tf_tbl_bulk_get(struct tf *tfp,
 	}
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* Only get table info if required for the device */
-	if (dev->ops->tf_dev_get_tbl_info) {
-		rc = dev->ops->tf_dev_get_tbl_info(tfp,
-						   tbl_db->tbl_db[parms->dir],
-						   parms->type,
-						   &base,
-						   &shift);
-		if (rc) {
-			TFP_DRV_LOG(ERR,
-				    "%s: Failed to get table info:%d\n",
-				    tf_dir_2_str(parms->dir),
-				    parms->type);
-			return rc;
-		}
-	}
-
 	/* Verify that the entries are in the range of reserved resources. */
 	cparms.rm_db = tbl_db->tbl_db[parms->dir];
 	cparms.subtype = parms->type;
-
-	TF_TBL_PTR_TO_RM(&cparms.starting_index, parms->starting_idx,
-			 base, shift);
-
 	cparms.num_entries = parms->num_entries;
+	cparms.starting_index = parms->starting_idx;
 
 	rc = tf_rm_check_indexes_in_range(&cparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
 			    "%s, Invalid or %d index starting from %d"
-			    " not in range, type:%d",
+			    " not in range, type:%s",
 			    tf_dir_2_str(parms->dir),
 			    parms->starting_idx,
 			    parms->num_entries,
-			    parms->type);
+			    tf_tbl_type_2_str(parms->type));
 		return rc;
 	}
 
@@ -617,9 +512,9 @@ tf_tbl_bulk_get(struct tf *tfp,
 	rc = tf_rm_get_hcapi_type(&hparms);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Failed type lookup, type:%d, rc:%s\n",
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 		return rc;
 	}
@@ -634,9 +529,9 @@ tf_tbl_bulk_get(struct tf *tfp,
 				       parms->physical_mem_addr);
 	if (rc) {
 		TFP_DRV_LOG(ERR,
-			    "%s, Bulk get failed, type:%d, rc:%s\n",
+			    "%s, Bulk get failed, type:%s, rc:%s\n",
 			    tf_dir_2_str(parms->dir),
-			    parms->type,
+			    tf_tbl_type_2_str(parms->type),
 			    strerror(-rc));
 	}
 
@@ -653,9 +548,9 @@ tf_tbl_get_resc_info(struct tf *tfp,
 	struct tf_rm_get_alloc_info_parms ainfo;
 	void *tbl_db_ptr = NULL;
 	struct tbl_rm_db *tbl_db;
-	uint16_t base = 0, shift = 0;
 	struct tf_dev_info *dev;
 	struct tf_session *tfs;
+	uint16_t base = 0, shift = 0;
 
 	TF_CHECK_PARMS2(tfp, tbl);
 
@@ -677,7 +572,6 @@ tf_tbl_get_resc_info(struct tf *tfp,
 
 	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
 
-	/* check if reserved resource for WC is multiple of num_slices */
 	for (d = 0; d < TF_DIR_MAX; d++) {
 		ainfo.rm_db = tbl_db->tbl_db[d];
 		dinfo = tbl[d].info;
diff --git a/drivers/net/bnxt/tf_core/tf_tbl.h b/drivers/net/bnxt/tf_core/tf_tbl.h
index 7e1107ffe7..2483718e5d 100644
--- a/drivers/net/bnxt/tf_core/tf_tbl.h
+++ b/drivers/net/bnxt/tf_core/tf_tbl.h
@@ -28,14 +28,6 @@ struct tf_tbl_cfg_parms {
 	 * Table Type element configuration array
 	 */
 	struct tf_rm_element_cfg *cfg;
-	/**
-	 * Shadow table type configuration array
-	 */
-	struct tf_shadow_tbl_cfg *shadow_cfg;
-	/**
-	 * Boolean controlling the request shadow copy.
-	 */
-	bool shadow_copy;
 	/**
 	 * Session resource allocations
 	 */
@@ -197,8 +189,6 @@ struct tbl_rm_db {
  *
  * @ref tf_tbl_free
  *
- * @ref tf_tbl_alloc_search
- *
  * @ref tf_tbl_set
  *
  * @ref tf_tbl_get
@@ -255,10 +245,7 @@ int tf_tbl_alloc(struct tf *tfp,
 		 struct tf_tbl_alloc_parms *parms);
 
 /**
- * Free's the requested table type and returns it to the DB. If shadow
- * DB is enabled its searched first and if found the element refcount
- * is decremented. If refcount goes to 0 then its returned to the
- * table type DB.
+ * Frees the requested table type and returns it to the DB.
  *
  * [in] tfp
  *   Pointer to TF handle, used for HCAPI communication
diff --git a/drivers/net/bnxt/tf_core/tf_tbl_sram.c b/drivers/net/bnxt/tf_core/tf_tbl_sram.c
new file mode 100644
index 0000000000..ea10afecb6
--- /dev/null
+++ b/drivers/net/bnxt/tf_core/tf_tbl_sram.c
@@ -0,0 +1,713 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2021 Broadcom
+ * All rights reserved.
+ */
+
+/* Truflow Table APIs and supporting code */
+
+#include <rte_common.h>
+
+#include "tf_tbl.h"
+#include "tf_tbl_sram.h"
+#include "tf_sram_mgr.h"
+#include "tf_common.h"
+#include "tf_rm.h"
+#include "tf_util.h"
+#include "tf_msg.h"
+#include "tfp.h"
+#include "tf_session.h"
+#include "tf_device.h"
+#include "cfa_resource_types.h"
+
+#define DBG_SRAM 0
+
+/**
+ * tf_sram_tbl_get_info_parms parameter definition
+ */
+struct tf_tbl_sram_get_info_parms {
+	/**
+	 * [in] table RM database
+	 */
+	void *rm_db;
+	/**
+	 * [in] Receive or transmit direction
+	 */
+	enum tf_dir dir;
+	/**
+	 * [in] table_type
+	 *
+	 *  the TF index table type
+	 */
+	enum tf_tbl_type tbl_type;
+	/**
+	 * [out] bank
+	 *
+	 *  The SRAM bank associated with the type
+	 */
+	enum tf_sram_bank_id bank_id;
+	/**
+	 * [out] slice_size
+	 *
+	 *  the slice size for the indicated table type
+	 */
+	enum tf_sram_slice_size slice_size;
+};
+
+/**
+ * Translate HCAPI type to SRAM Manager bank
+ */
+const uint16_t tf_tbl_sram_hcapi_2_bank[CFA_RESOURCE_TYPE_P58_LAST] = {
+	[CFA_RESOURCE_TYPE_P58_SRAM_BANK_0] = TF_SRAM_BANK_ID_0,
+	[CFA_RESOURCE_TYPE_P58_SRAM_BANK_1] = TF_SRAM_BANK_ID_1,
+	[CFA_RESOURCE_TYPE_P58_SRAM_BANK_2] = TF_SRAM_BANK_ID_2,
+	[CFA_RESOURCE_TYPE_P58_SRAM_BANK_3] = TF_SRAM_BANK_ID_3
+};
+
+#define TF_TBL_SRAM_SLICES_MAX  \
+	(TF_SRAM_MGR_BLOCK_SZ_BYTES / TF_SRAM_MGR_MIN_SLICE_BYTES)
+/**
+ * Translate HCAPI type to SRAM Manager bank
+ */
+const uint8_t tf_tbl_sram_slices_2_size[TF_TBL_SRAM_SLICES_MAX + 1] = {
+	[0] = TF_SRAM_SLICE_SIZE_64B, /* if 0 slices assume 1 64B block */
+	[1] = TF_SRAM_SLICE_SIZE_64B, /* 1 slice  per 64B block */
+	[2] = TF_SRAM_SLICE_SIZE_32B, /* 2 slices per 64B block */
+	[4] = TF_SRAM_SLICE_SIZE_16B, /* 4 slices per 64B block */
+	[8] = TF_SRAM_SLICE_SIZE_8B   /* 8 slices per 64B block */
+};
+
+/**
+ * Get SRAM Table Information for a given index table type
+ *
+ *
+ * [in] sram_handle
+ *   Pointer to SRAM handle
+ *
+ * [in] parms
+ *   Pointer to the SRAM get info parameters
+ *
+ * Returns
+ *   - (0) if successful
+ *   - (-EINVAL) on failure
+ *
+ */
+static int tf_tbl_sram_get_info(struct tf_tbl_sram_get_info_parms *parms)
+{
+	int rc = 0;
+	uint16_t hcapi_type;
+	uint16_t slices;
+	struct tf_rm_get_hcapi_parms hparms;
+	struct tf_rm_get_slices_parms sparms;
+
+	hparms.rm_db = parms->rm_db;
+	hparms.subtype = parms->tbl_type;
+	hparms.hcapi_type = &hcapi_type;
+
+	rc = tf_rm_get_hcapi_type(&hparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get hcapi_type %s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->tbl_type),
+			    strerror(-rc));
+		return rc;
+	}
+	parms->bank_id = tf_tbl_sram_hcapi_2_bank[hcapi_type];
+
+	sparms.rm_db = parms->rm_db;
+	sparms.subtype = parms->tbl_type;
+	sparms.slices = &slices;
+
+	rc = tf_rm_get_slices(&sparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get slice cnt %s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->tbl_type),
+			    strerror(-rc));
+		return rc;
+	}
+	if (slices)
+		parms->slice_size = tf_tbl_sram_slices_2_size[slices];
+
+	TFP_DRV_LOG(INFO,
+		    "(%s) bank(%s) slice_size(%s)\n",
+		    tf_tbl_type_2_str(parms->tbl_type),
+		    tf_sram_bank_2_str(parms->bank_id),
+		    tf_sram_slice_2_str(parms->slice_size));
+	return rc;
+}
+
+int
+tf_tbl_sram_bind(struct tf *tfp __rte_unused)
+{
+	int rc = 0;
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS1(tfp);
+
+	rc = tf_sram_mgr_bind(&sram_handle);
+
+	tf_session_set_sram_db(tfp, sram_handle);
+
+	TFP_DRV_LOG(INFO,
+		    "SRAM Table - initialized\n");
+
+	return rc;
+}
+
+int
+tf_tbl_sram_unbind(struct tf *tfp __rte_unused)
+{
+	int rc = 0;
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS1(tfp);
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	if (sram_handle)
+		rc = tf_sram_mgr_unbind(sram_handle);
+
+	TFP_DRV_LOG(INFO,
+		    "SRAM Table - deinitialized\n");
+	return rc;
+}
+
+int
+tf_tbl_sram_alloc(struct tf *tfp,
+		  struct tf_tbl_alloc_parms *parms)
+{
+	int rc;
+	uint16_t idx;
+	struct tf_session *tfs;
+	struct tf_dev_info *dev;
+	struct tf_tbl_sram_get_info_parms iparms = { 0 };
+	struct tf_sram_mgr_alloc_parms aparms = { 0 };
+	struct tbl_rm_db *tbl_db;
+	void *tbl_db_ptr = NULL;
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS2(tfp, parms);
+
+	/* Retrieve the session information */
+	rc = tf_session_get(tfp, &tfs, &dev);
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get tbl_db from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	iparms.rm_db = tbl_db->tbl_db[parms->dir];
+	iparms.dir = parms->dir;
+	iparms.tbl_type = parms->type;
+
+	rc = tf_tbl_sram_get_info(&iparms);
+
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get SRAM info %s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+
+	aparms.dir = parms->dir;
+	aparms.bank_id = iparms.bank_id;
+	aparms.slice_size = iparms.slice_size;
+	aparms.sram_offset = &idx;
+	aparms.tbl_type = parms->type;
+	aparms.rm_db = tbl_db->tbl_db[parms->dir];
+
+	rc = tf_sram_mgr_alloc(sram_handle, &aparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to allocate SRAM table:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+	*parms->idx = idx;
+
+#if (DBG_SRAM == 1)
+	{
+		struct tf_sram_mgr_dump_parms dparms;
+
+		dparms.dir = parms->dir;
+		dparms.bank_id = iparms.bank_id;
+		dparms.slice_size = iparms.slice_size;
+
+		rc = tf_sram_mgr_dump(sram_handle, &dparms);
+	}
+#endif
+
+	return rc;
+}
+
+int
+tf_tbl_sram_free(struct tf *tfp __rte_unused,
+		 struct tf_tbl_free_parms *parms)
+{
+	int rc;
+	struct tf_session *tfs;
+	struct tf_dev_info *dev;
+	struct tbl_rm_db *tbl_db;
+	void *tbl_db_ptr = NULL;
+	struct tf_tbl_sram_get_info_parms iparms = { 0 };
+	struct tf_sram_mgr_free_parms fparms = { 0 };
+	struct tf_sram_mgr_is_allocated_parms aparms = { 0 };
+	bool allocated = false;
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS2(tfp, parms);
+
+	/* Retrieve the session information */
+	rc = tf_session_get(tfp, &tfs, &dev);
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get em_ext_db from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	iparms.rm_db = tbl_db->tbl_db[parms->dir];
+	iparms.dir = parms->dir;
+	iparms.tbl_type = parms->type;
+
+	rc = tf_tbl_sram_get_info(&iparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get table info:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+
+#if (DBG_SRAM == 1)
+	{
+		struct tf_sram_mgr_dump_parms dparms;
+
+		printf("%s: %s: %s\n", tf_dir_2_str(parms->dir),
+		       tf_sram_slice_2_str(iparms.slice_size),
+		       tf_sram_bank_2_str(iparms.bank_id));
+
+		dparms.dir = parms->dir;
+		dparms.bank_id = iparms.bank_id;
+		dparms.slice_size = iparms.slice_size;
+
+		rc = tf_sram_mgr_dump(sram_handle, &dparms);
+	}
+#endif
+
+	aparms.sram_offset = parms->idx;
+	aparms.slice_size = iparms.slice_size;
+	aparms.bank_id = iparms.bank_id;
+	aparms.dir = parms->dir;
+	aparms.is_allocated = &allocated;
+
+	rc = tf_sram_mgr_is_allocated(sram_handle, &aparms);
+	if (rc || !allocated) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Free of invalid entry:%s idx(%d):(%s)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    parms->idx,
+			    strerror(-rc));
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	fparms.rm_db = tbl_db->tbl_db[parms->dir];
+	fparms.tbl_type = parms->type;
+	fparms.sram_offset = parms->idx;
+	fparms.slice_size = iparms.slice_size;
+	fparms.bank_id = iparms.bank_id;
+	fparms.dir = parms->dir;
+#if (STATS_CLEAR_ON_READ_SUPPORT == 0)
+	fparms.tfp = tfp;
+#endif
+	rc = tf_sram_mgr_free(sram_handle, &fparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to free entry:%s idx(%d)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    parms->idx);
+		return rc;
+	}
+
+
+#if (DBG_SRAM == 1)
+	{
+		struct tf_sram_mgr_dump_parms dparms;
+
+		printf("%s: %s: %s\n", tf_dir_2_str(parms->dir),
+		       tf_sram_slice_2_str(iparms.slice_size),
+		       tf_sram_bank_2_str(iparms.bank_id));
+
+		dparms.dir = parms->dir;
+		dparms.bank_id = iparms.bank_id;
+		dparms.slice_size = iparms.slice_size;
+
+		rc = tf_sram_mgr_dump(sram_handle, &dparms);
+	}
+#endif
+	return rc;
+}
+
+int
+tf_tbl_sram_set(struct tf *tfp,
+		struct tf_tbl_set_parms *parms)
+{
+	int rc;
+	bool allocated = 0;
+	uint16_t hcapi_type;
+	struct tf_rm_get_hcapi_parms hparms = { 0 };
+	struct tf_session *tfs;
+	struct tf_dev_info *dev;
+	struct tbl_rm_db *tbl_db;
+	void *tbl_db_ptr = NULL;
+	struct tf_tbl_sram_get_info_parms iparms = { 0 };
+	struct tf_sram_mgr_is_allocated_parms aparms = { 0 };
+	void *sram_handle = NULL;
+
+
+	TF_CHECK_PARMS3(tfp, parms, parms->data);
+
+	/* Retrieve the session information */
+	rc = tf_session_get(tfp, &tfs, &dev);
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get em_ext_db from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	iparms.rm_db = tbl_db->tbl_db[parms->dir];
+	iparms.dir = parms->dir;
+	iparms.tbl_type = parms->type;
+
+	rc = tf_tbl_sram_get_info(&iparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get table info:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+
+	aparms.sram_offset = parms->idx;
+	aparms.slice_size = iparms.slice_size;
+	aparms.bank_id = iparms.bank_id;
+	aparms.dir = parms->dir;
+	aparms.is_allocated = &allocated;
+	rc = tf_sram_mgr_is_allocated(sram_handle, &aparms);
+	if (rc || !allocated) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Entry not allocated:%s idx(%d):(%s)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    parms->idx,
+			    strerror(-rc));
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	/* Set the entry */
+	hparms.rm_db = tbl_db->tbl_db[parms->dir];
+	hparms.subtype = parms->type;
+	hparms.hcapi_type = &hcapi_type;
+	rc = tf_rm_get_hcapi_type(&hparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+		return rc;
+	}
+
+	rc = tf_msg_set_tbl_entry(tfp,
+				  parms->dir,
+				  hcapi_type,
+				  parms->data_sz_in_bytes,
+				  parms->data,
+				  parms->idx);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Set failed, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+		return rc;
+	}
+	return rc;
+}
+
+int
+tf_tbl_sram_get(struct tf *tfp,
+		struct tf_tbl_get_parms *parms)
+{
+	int rc;
+	uint16_t hcapi_type;
+	bool allocated = 0;
+	struct tf_rm_get_hcapi_parms hparms = { 0 };
+	struct tf_session *tfs;
+	struct tf_dev_info *dev;
+	struct tbl_rm_db *tbl_db;
+	void *tbl_db_ptr = NULL;
+	struct tf_tbl_sram_get_info_parms iparms = { 0 };
+	struct tf_sram_mgr_is_allocated_parms aparms = { 0 };
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS3(tfp, parms, parms->data);
+
+	/* Retrieve the session information */
+	rc = tf_session_get(tfp, &tfs, &dev);
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get em_ext_db from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	iparms.rm_db = tbl_db->tbl_db[parms->dir];
+	iparms.dir = parms->dir;
+	iparms.tbl_type = parms->type;
+
+	rc = tf_tbl_sram_get_info(&iparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get table info:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+
+	aparms.sram_offset = parms->idx;
+	aparms.slice_size = iparms.slice_size;
+	aparms.bank_id = iparms.bank_id;
+	aparms.dir = parms->dir;
+	aparms.is_allocated = &allocated;
+
+	rc = tf_sram_mgr_is_allocated(sram_handle, &aparms);
+	if (rc || !allocated) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Entry not allocated:%s idx(%d):(%s)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    parms->idx,
+			    strerror(-rc));
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	/* Get the entry */
+	hparms.rm_db = tbl_db->tbl_db[parms->dir];
+	hparms.subtype = parms->type;
+	hparms.hcapi_type = &hcapi_type;
+	rc = tf_rm_get_hcapi_type(&hparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* Get the entry */
+	rc = tf_msg_get_tbl_entry(tfp,
+				  parms->dir,
+				  hcapi_type,
+				  parms->data_sz_in_bytes,
+				  parms->data,
+				  parms->idx);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Get failed, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+		return rc;
+	}
+	return rc;
+}
+
+int
+tf_tbl_sram_bulk_get(struct tf *tfp,
+		     struct tf_tbl_get_bulk_parms *parms)
+{
+	int rc;
+	uint16_t hcapi_type;
+	struct tf_rm_get_hcapi_parms hparms = { 0 };
+	struct tf_tbl_sram_get_info_parms iparms = { 0 };
+	struct tf_session *tfs;
+	struct tf_dev_info *dev;
+	struct tbl_rm_db *tbl_db;
+	void *tbl_db_ptr = NULL;
+	uint16_t idx;
+	struct tf_sram_mgr_is_allocated_parms aparms = { 0 };
+	bool allocated = false;
+	void *sram_handle = NULL;
+
+	TF_CHECK_PARMS2(tfp, parms);
+
+	/* Retrieve the session information */
+	rc = tf_session_get(tfp, &tfs, &dev);
+	if (rc)
+		return rc;
+
+	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get em_ext_db from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+	tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
+
+	rc = tf_session_get_sram_db(tfp, &sram_handle);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "Failed to get sram_handle from session, rc:%s\n",
+			    strerror(-rc));
+		return rc;
+	}
+
+	iparms.rm_db = tbl_db->tbl_db[parms->dir];
+	iparms.dir = parms->dir;
+	iparms.tbl_type = parms->type;
+
+	rc = tf_tbl_sram_get_info(&iparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to get table info:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type));
+		return rc;
+	}
+
+	/* Validate the start offset and the end offset is allocated
+	 * This API is only used for statistics.  8 Byte entry allocation
+	 * is used to verify
+	 */
+	aparms.sram_offset = parms->starting_idx;
+	aparms.slice_size = iparms.slice_size;
+	aparms.bank_id = iparms.bank_id;
+	aparms.dir = parms->dir;
+	aparms.is_allocated = &allocated;
+	rc = tf_sram_mgr_is_allocated(sram_handle, &aparms);
+	if (rc || !allocated) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Entry not allocated:%s starting_idx(%d):(%s)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    parms->starting_idx,
+			    strerror(-rc));
+		rc = -ENOMEM;
+		return rc;
+	}
+	idx = parms->starting_idx + parms->num_entries - 1;
+	aparms.sram_offset = idx;
+	rc = tf_sram_mgr_is_allocated(sram_handle, &aparms);
+	if (rc || !allocated) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Entry not allocated:%s last_idx(%d):(%s)\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    idx,
+			    strerror(-rc));
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	hparms.rm_db = tbl_db->tbl_db[parms->dir];
+	hparms.subtype = parms->type;
+	hparms.hcapi_type = &hcapi_type;
+	rc = tf_rm_get_hcapi_type(&hparms);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Failed type lookup, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* Get the entries */
+	rc = tf_msg_bulk_get_tbl_entry(tfp,
+				       parms->dir,
+				       hcapi_type,
+				       parms->starting_idx,
+				       parms->num_entries,
+				       parms->entry_sz_in_bytes,
+				       parms->physical_mem_addr);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s, Bulk get failed, type:%s, rc:%s\n",
+			    tf_dir_2_str(parms->dir),
+			    tf_tbl_type_2_str(parms->type),
+			    strerror(-rc));
+	}
+	return rc;
+}
diff --git a/drivers/net/bnxt/tf_core/tf_tbl_sram.h b/drivers/net/bnxt/tf_core/tf_tbl_sram.h
new file mode 100644
index 0000000000..32001e34a9
--- /dev/null
+++ b/drivers/net/bnxt/tf_core/tf_tbl_sram.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2021 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef TF_TBL_SRAM_H_
+#define TF_TBL_SRAM_H_
+
+#include "tf_core.h"
+#include "stack.h"
+
+
+/**
+ * The SRAM Table module provides processing of managed SRAM types.
+ */
+
+
+/**
+ * @page  tblsram SRAM Table
+ *
+ * @ref tf_tbl_sram_bind
+ *
+ * @ref tf_tbl_sram_unbind
+ *
+ * @ref tf_tbl_sram_alloc
+ *
+ * @ref tf_tbl_sram_free
+ *
+ * @ref tf_tbl_sram_set
+ *
+ * @ref tf_tbl_sram_get
+ *
+ * @ref tf_tbl_sram_bulk_get
+ */
+
+/**
+ * Initializes the Table module with the requested DBs. Must be
+ * invoked as the first thing before any of the access functions.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table configuration parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_bind(struct tf *tfp);
+
+/**
+ * Cleans up the private DBs and releases all the data.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_unbind(struct tf *tfp);
+
+/**
+ * Allocates the requested table type from the internal RM DB.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table allocation parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_alloc(struct tf *tfp,
+		      struct tf_tbl_alloc_parms *parms);
+
+/**
+ * Free's the requested table type and returns it to the DB. If shadow
+ * DB is enabled its searched first and if found the element refcount
+ * is decremented. If refcount goes to 0 then its returned to the
+ * table type DB.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table free parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_free(struct tf *tfp,
+		     struct tf_tbl_free_parms *parms);
+
+
+/**
+ * Configures the requested element by sending a firmware request which
+ * then installs it into the device internal structures.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table set parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_set(struct tf *tfp,
+		    struct tf_tbl_set_parms *parms);
+
+/**
+ * Retrieves the requested element by sending a firmware request to get
+ * the element.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table get parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_get(struct tf *tfp,
+		    struct tf_tbl_get_parms *parms);
+
+/**
+ * Retrieves bulk block of elements by sending a firmware request to
+ * get the elements.
+ *
+ * [in] tfp
+ *   Pointer to TF handle, used for HCAPI communication
+ *
+ * [in] parms
+ *   Pointer to Table get bulk parameters
+ *
+ * Returns
+ *   - (0) if successful.
+ *   - (-EINVAL) on failure.
+ */
+int tf_tbl_sram_bulk_get(struct tf *tfp,
+			 struct tf_tbl_get_bulk_parms *parms);
+
+#endif /* TF_TBL_SRAM_H */
diff --git a/drivers/net/bnxt/tf_core/tf_tcam.c b/drivers/net/bnxt/tf_core/tf_tcam.c
index 45206c5992..806af3070a 100644
--- a/drivers/net/bnxt/tf_core/tf_tcam.c
+++ b/drivers/net/bnxt/tf_core/tf_tcam.c
@@ -43,7 +43,7 @@ tf_tcam_bind(struct tf *tfp,
 	struct tf_shadow_tcam_free_db_parms fshadow;
 	struct tf_shadow_tcam_cfg_parms shadow_cfg;
 	struct tf_shadow_tcam_create_db_parms shadow_cdb;
-	uint16_t num_slices = 1;
+	uint16_t num_slices = parms->wc_num_slices;
 	struct tf_session *tfs;
 	struct tf_dev_info *dev;
 	struct tcam_rm_db *tcam_db;
@@ -61,7 +61,7 @@ tf_tcam_bind(struct tf *tfp,
 	if (rc)
 		return rc;
 
-	if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
+	if (dev->ops->tf_dev_set_tcam_slice_info == NULL) {
 		rc = -EOPNOTSUPP;
 		TFP_DRV_LOG(ERR,
 			    "Operation not supported, rc:%s\n",
@@ -69,10 +69,8 @@ tf_tcam_bind(struct tf *tfp,
 		return rc;
 	}
 
-	rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
-						  TF_TCAM_TBL_TYPE_WC_TCAM,
-						  0,
-						  &num_slices);
+	rc = dev->ops->tf_dev_set_tcam_slice_info(tfp,
+						  num_slices);
 	if (rc)
 		return rc;
 
diff --git a/drivers/net/bnxt/tf_core/tf_tcam.h b/drivers/net/bnxt/tf_core/tf_tcam.h
index bed17af6ae..b1e7a92b0b 100644
--- a/drivers/net/bnxt/tf_core/tf_tcam.h
+++ b/drivers/net/bnxt/tf_core/tf_tcam.h
@@ -12,6 +12,9 @@
  * The TCAM module provides processing of Internal TCAM types.
  */
 
+/* Number of slices per row for WC TCAM */
+extern uint16_t g_wc_num_slices_per_row;
+
 /**
  * TCAM configuration parameters
  */
@@ -36,6 +39,10 @@ struct tf_tcam_cfg_parms {
 	 * Session resource allocations
 	 */
 	struct tf_session_resources *resources;
+	/**
+	 * WC number of slices per row.
+	 */
+	enum tf_wc_num_slice wc_num_slices;
 };
 
 /**
diff --git a/drivers/net/bnxt/tf_core/tf_tcam_shared.c b/drivers/net/bnxt/tf_core/tf_tcam_shared.c
index 83b6fbd5fb..c120c6f577 100644
--- a/drivers/net/bnxt/tf_core/tf_tcam_shared.c
+++ b/drivers/net/bnxt/tf_core/tf_tcam_shared.c
@@ -279,18 +279,6 @@ tf_tcam_shared_bind(struct tf *tfp,
 		if (rc)
 			return rc;
 
-		rc = tf_tcam_shared_get_slices(tfp,
-					       dev,
-					       &num_slices);
-		if (rc)
-			return rc;
-
-		if (num_slices > 1) {
-			TFP_DRV_LOG(ERR,
-				    "Only single slice supported\n");
-			return -EOPNOTSUPP;
-		}
-
 		tf_tcam_shared_create_db(&tcam_shared_wc);
 
 
@@ -330,6 +318,18 @@ tf_tcam_shared_bind(struct tf *tfp,
 
 			tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc);
 		}
+
+		rc = tf_tcam_shared_get_slices(tfp,
+					       dev,
+					       &num_slices);
+		if (rc)
+			return rc;
+
+		if (num_slices > 1) {
+			TFP_DRV_LOG(ERR,
+				    "Only single slice supported\n");
+			return -EOPNOTSUPP;
+		}
 	}
 done:
 	return rc;
@@ -972,9 +972,9 @@ tf_tcam_shared_move_entry(struct tf *tfp,
 	sparms.idx = dphy_idx;
 	sparms.key = gparms.key;
 	sparms.mask = gparms.mask;
-	sparms.key_size = gparms.key_size;
+	sparms.key_size = key_sz_bytes;
 	sparms.result = gparms.result;
-	sparms.result_size = gparms.result_size;
+	sparms.result_size = remap_sz_bytes;
 
 	rc = tf_msg_tcam_entry_set(tfp, dev, &sparms);
 	if (rc) {
diff --git a/drivers/net/bnxt/tf_core/tf_util.c b/drivers/net/bnxt/tf_core/tf_util.c
index d100399d0a..c1b9be0755 100644
--- a/drivers/net/bnxt/tf_core/tf_util.c
+++ b/drivers/net/bnxt/tf_core/tf_util.c
@@ -76,6 +76,8 @@ tf_tbl_type_2_str(enum tf_tbl_type tbl_type)
 	switch (tbl_type) {
 	case TF_TBL_TYPE_FULL_ACT_RECORD:
 		return "Full Action record";
+	case TF_TBL_TYPE_COMPACT_ACT_RECORD:
+		return "Compact Action record";
 	case TF_TBL_TYPE_MCAST_GROUPS:
 		return "Multicast Groups";
 	case TF_TBL_TYPE_ACT_ENCAP_8B:
@@ -96,6 +98,14 @@ tf_tbl_type_2_str(enum tf_tbl_type tbl_type)
 		return "Stats 64B";
 	case TF_TBL_TYPE_ACT_MODIFY_IPV4:
 		return "Modify IPv4";
+	case TF_TBL_TYPE_ACT_MODIFY_8B:
+		return "Modify 8B";
+	case TF_TBL_TYPE_ACT_MODIFY_16B:
+		return "Modify 16B";
+	case TF_TBL_TYPE_ACT_MODIFY_32B:
+		return "Modify 32B";
+	case TF_TBL_TYPE_ACT_MODIFY_64B:
+		return "Modify 64B";
 	case TF_TBL_TYPE_METER_PROF:
 		return "Meter Profile";
 	case TF_TBL_TYPE_METER_INST:
diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
index dbf85e4eda..183bae66c5 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp.c
@@ -384,6 +384,7 @@ ulp_ctx_shared_session_open(struct bnxt *bp,
 	size_t copy_nbytes;
 	uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
 	int32_t	rc = 0;
+	uint8_t app_id;
 
 	/* only perform this if shared session is enabled. */
 	if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
@@ -422,6 +423,12 @@ ulp_ctx_shared_session_open(struct bnxt *bp,
 	if (rc)
 		return rc;
 
+	rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
+	if (rc) {
+		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
+		return -EINVAL;
+	}
+
 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
@@ -445,6 +452,10 @@ ulp_ctx_shared_session_open(struct bnxt *bp,
 
 	parms.shadow_copy = true;
 	parms.bp = bp;
+	if (app_id == 0 || app_id == 3)
+		parms.wc_num_slices = TF_WC_TCAM_2_SLICE_PER_ROW;
+	else
+		parms.wc_num_slices = TF_WC_TCAM_1_SLICE_PER_ROW;
 
 	/*
 	 * Open the session here, but the collect the resources during the
@@ -516,6 +527,7 @@ ulp_ctx_session_open(struct bnxt *bp,
 	struct tf_open_session_parms	params;
 	struct tf_session_resources	*resources;
 	uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
+	uint8_t app_id;
 
 	memset(&params, 0, sizeof(params));
 
@@ -529,6 +541,12 @@ ulp_ctx_session_open(struct bnxt *bp,
 
 	params.shadow_copy = true;
 
+	rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
+	if (rc) {
+		BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
+		return -EINVAL;
+	}
+
 	rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
@@ -556,6 +574,11 @@ ulp_ctx_session_open(struct bnxt *bp,
 		return rc;
 
 	params.bp = bp;
+	if (app_id == 0 || app_id == 3)
+		params.wc_num_slices = TF_WC_TCAM_2_SLICE_PER_ROW;
+	else
+		params.wc_num_slices = TF_WC_TCAM_1_SLICE_PER_ROW;
+
 	rc = tf_open_session(&bp->tfp, &params);
 	if (rc) {
 		BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
diff --git a/meson_options.txt b/meson_options.txt
index 0e92734c49..f686e6d92a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -46,3 +46,5 @@ option('tests', type: 'boolean', value: true, description:
        'build unit tests')
 option('use_hpet', type: 'boolean', value: false, description:
        'use HPET timer in EAL')
+option('bnxt_tf_wc_slices', type: 'integer', min: 1, max: 4, value: 2,
+	description: 'Number of slices per WC TCAM entry')
