diff --git a/drivers/net/bnxt/tf_core/meson.build b/drivers/net/bnxt/tf_core/meson.build
index d7e8f664fd..373ee0413b 100644
--- a/drivers/net/bnxt/tf_core/meson.build
+++ b/drivers/net/bnxt/tf_core/meson.build
@@ -30,5 +30,6 @@ sources += files(
         'll.c',
         'tf_global_cfg.c',
         'tf_em_host.c',
+        'tf_em_hash_internal.c',
         'tf_shadow_identifier.c',
         'tf_hash.c')
diff --git a/drivers/net/bnxt/tf_core/tf_device_p58.c b/drivers/net/bnxt/tf_core/tf_device_p58.c
index 7dd806000c..6cef1d5ba5 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p58.c
+++ b/drivers/net/bnxt/tf_core/tf_device_p58.c
@@ -256,14 +256,14 @@ const struct tf_dev_ops tf_dev_ops_p58 = {
 	.tf_dev_alloc_search_tcam = tf_tcam_alloc_search,
 	.tf_dev_set_tcam = tf_tcam_set,
 	.tf_dev_get_tcam = NULL,
-	.tf_dev_insert_int_em_entry = tf_em_insert_int_entry,
-	.tf_dev_delete_int_em_entry = tf_em_delete_int_entry,
-	.tf_dev_insert_ext_em_entry = tf_em_insert_ext_entry,
-	.tf_dev_delete_ext_em_entry = tf_em_delete_ext_entry,
-	.tf_dev_alloc_tbl_scope = tf_em_ext_common_alloc,
-	.tf_dev_map_tbl_scope = tf_em_ext_map_tbl_scope,
+	.tf_dev_insert_int_em_entry = tf_em_hash_insert_int_entry,
+	.tf_dev_delete_int_em_entry = tf_em_hash_delete_int_entry,
+	.tf_dev_insert_ext_em_entry = NULL,
+	.tf_dev_delete_ext_em_entry = NULL,
+	.tf_dev_alloc_tbl_scope = NULL,
+	.tf_dev_map_tbl_scope = NULL,
 	.tf_dev_map_parif = tf_dev_p58_map_parif,
-	.tf_dev_free_tbl_scope = tf_em_ext_common_free,
+	.tf_dev_free_tbl_scope = NULL,
 	.tf_dev_set_if_tbl = tf_if_tbl_set,
 	.tf_dev_get_if_tbl = tf_if_tbl_get,
 	.tf_dev_set_global_cfg = tf_global_cfg_set,
diff --git a/drivers/net/bnxt/tf_core/tf_em.h b/drivers/net/bnxt/tf_core/tf_em.h
index b5c3acb09a..5a67ca3509 100644
--- a/drivers/net/bnxt/tf_core/tf_em.h
+++ b/drivers/net/bnxt/tf_core/tf_em.h
@@ -197,6 +197,38 @@ int tf_em_insert_int_entry(struct tf *tfp,
 int tf_em_delete_int_entry(struct tf *tfp,
 			   struct tf_delete_em_entry_parms *parms);
 
+/**
+ * Insert record in to internal EM table
+ *
+ * [in] tfp
+ *   Pointer to TruFlow handle
+ *
+ * [in] parms
+ *   Pointer to input parameters
+ *
+ * Returns:
+ *   0       - Success
+ *   -EINVAL - Parameter error
+ */
+int tf_em_hash_insert_int_entry(struct tf *tfp,
+				struct tf_insert_em_entry_parms *parms);
+
+/**
+ * Delete record from internal EM table
+ *
+ * [in] tfp
+ *   Pointer to TruFlow handle
+ *
+ * [in] parms
+ *   Pointer to input parameters
+ *
+ * Returns:
+ *   0       - Success
+ *   -EINVAL - Parameter error
+ */
+int tf_em_hash_delete_int_entry(struct tf *tfp,
+				struct tf_delete_em_entry_parms *parms);
+
 /**
  * Insert record in to external EEM table
  *
diff --git a/drivers/net/bnxt/tf_core/tf_em_hash_internal.c b/drivers/net/bnxt/tf_core/tf_em_hash_internal.c
new file mode 100644
index 0000000000..09183b42f0
--- /dev/null
+++ b/drivers/net/bnxt/tf_core/tf_em_hash_internal.c
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2021 Broadcom
+ * All rights reserved.
+ */
+
+#include <string.h>
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+
+#include "tf_core.h"
+#include "tf_util.h"
+#include "tf_common.h"
+#include "tf_em.h"
+#include "tf_msg.h"
+#include "tfp.h"
+#include "tf_ext_flow_handle.h"
+
+#include "bnxt.h"
+
+/**
+ * EM Pool
+ */
+extern struct stack em_pool[TF_DIR_MAX];
+
+/**
+ * Insert EM internal entry API
+ *
+ *  returns:
+ *     0 - Success
+ */
+int
+tf_em_hash_insert_int_entry(struct tf *tfp,
+			    struct tf_insert_em_entry_parms *parms)
+{
+	int rc;
+	uint32_t gfid;
+	uint16_t rptr_index = 0;
+	uint8_t rptr_entry = 0;
+	uint8_t num_of_entries = 0;
+	struct stack *pool = &em_pool[parms->dir];
+	uint32_t index;
+	uint32_t key0_hash;
+	uint32_t key1_hash;
+	uint64_t big_hash;
+
+	rc = stack_pop(pool, &index);
+	if (rc) {
+		PMD_DRV_LOG(ERR,
+			    "%s, EM entry index allocation failed\n",
+			    tf_dir_2_str(parms->dir));
+		return rc;
+	}
+
+	big_hash = hcapi_cfa_key_hash((uint64_t *)parms->key,
+				      (TF_HW_EM_KEY_MAX_SIZE + 4) * 8);
+	key0_hash = (uint32_t)(big_hash >> 32);
+	key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
+
+	rptr_index = index;
+	rc = tf_msg_hash_insert_em_internal_entry(tfp,
+						  parms,
+						  key0_hash,
+						  key1_hash,
+						  &rptr_index,
+						  &rptr_entry,
+						  &num_of_entries);
+	if (rc) {
+		/* Free the allocated index before returning */
+		stack_push(pool, index);
+		return -1;
+	}
+
+	PMD_DRV_LOG
+		  (DEBUG,
+		   "%s, Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
+		   tf_dir_2_str(parms->dir),
+		   index,
+		   rptr_index,
+		   rptr_entry,
+		   num_of_entries);
+
+	TF_SET_GFID(gfid,
+		    ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
+		     rptr_entry),
+		    0); /* N/A for internal table */
+
+	TF_SET_FLOW_ID(parms->flow_id,
+		       gfid,
+		       TF_GFID_TABLE_INTERNAL,
+		       parms->dir);
+
+	TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
+				     (uint32_t)num_of_entries,
+				     0,
+				     0,
+				     rptr_index,
+				     rptr_entry,
+				     0);
+	return 0;
+}
+
+/** Delete EM internal entry API
+ *
+ * returns:
+ * 0
+ * -EINVAL
+ */
+int
+tf_em_hash_delete_int_entry(struct tf *tfp,
+			    struct tf_delete_em_entry_parms *parms)
+{
+	int rc = 0;
+	struct stack *pool = &em_pool[parms->dir];
+
+	rc = tf_msg_delete_em_entry(tfp, parms);
+
+	/* Return resource to pool */
+	if (rc == 0)
+		stack_push(pool, parms->index);
+
+	return rc;
+}
diff --git a/drivers/net/bnxt/tf_core/tf_em_internal.c b/drivers/net/bnxt/tf_core/tf_em_internal.c
index bdffd801b3..0864218469 100644
--- a/drivers/net/bnxt/tf_core/tf_em_internal.c
+++ b/drivers/net/bnxt/tf_core/tf_em_internal.c
@@ -30,11 +30,10 @@ static void *em_db[TF_DIR_MAX];
  */
 static uint8_t init;
 
-
 /**
  * EM Pool
  */
-static struct stack em_pool[TF_DIR_MAX];
+struct stack em_pool[TF_DIR_MAX];
 
 /**
  * Create EM Tbl pool of memory indexes.
diff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c
index be30d4a09f..39d7e3eace 100644
--- a/drivers/net/bnxt/tf_core/tf_msg.c
+++ b/drivers/net/bnxt/tf_core/tf_msg.c
@@ -25,6 +25,7 @@
  */
 #define TF_MSG_SET_GLOBAL_CFG_DATA_SIZE  16
 #define TF_MSG_EM_INSERT_KEY_SIZE        64
+#define TF_MSG_EM_INSERT_RECORD_SIZE     80
 #define TF_MSG_TBL_TYPE_SET_DATA_SIZE    88
 
 /* Compile check - Catch any msg changes that we depend on, like the
@@ -706,6 +707,101 @@ tf_msg_insert_em_internal_entry(struct tf *tfp,
 	return 0;
 }
 
+int
+tf_msg_hash_insert_em_internal_entry(struct tf *tfp,
+				     struct tf_insert_em_entry_parms *em_parms,
+				     uint32_t key0_hash,
+				     uint32_t key1_hash,
+				     uint16_t *rptr_index,
+				     uint8_t *rptr_entry,
+				     uint8_t *num_of_entries)
+{
+	int rc;
+	struct tfp_send_msg_parms parms = { 0 };
+	struct hwrm_tf_em_hash_insert_input req = { 0 };
+	struct hwrm_tf_em_hash_insert_output resp = { 0 };
+	uint16_t flags;
+	uint8_t fw_session_id;
+	uint8_t msg_record_size;
+	struct tf_dev_info *dev;
+	struct tf_session *tfs;
+
+	/* Retrieve the session information */
+	rc = tf_session_get_session_internal(tfp, &tfs);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to lookup session, rc:%s\n",
+			    tf_dir_2_str(em_parms->dir),
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* Retrieve the device information */
+	rc = tf_session_get_device(tfs, &dev);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Failed to lookup device, rc:%s\n",
+			    tf_dir_2_str(em_parms->dir),
+			    strerror(-rc));
+		return rc;
+	}
+
+	rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+	if (rc) {
+		TFP_DRV_LOG(ERR,
+			    "%s: Unable to lookup FW id, rc:%s\n",
+			    tf_dir_2_str(em_parms->dir),
+			    strerror(-rc));
+		return rc;
+	}
+
+	/* Populate the request */
+	req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+
+	/* Check for key size conformity */
+	msg_record_size = (em_parms->em_record_sz_in_bits + 7) / 8;
+
+	if (msg_record_size > TF_MSG_EM_INSERT_RECORD_SIZE) {
+		rc = -EINVAL;
+		TFP_DRV_LOG(ERR,
+			    "%s: Record size to large, rc:%s\n",
+			    tf_dir_2_str(em_parms->dir),
+			    strerror(-rc));
+		return rc;
+	}
+
+	tfp_memcpy((char *)req.em_record,
+		   em_parms->em_record,
+		   msg_record_size);
+
+	flags = (em_parms->dir == TF_DIR_TX ?
+		 HWRM_TF_EM_INSERT_INPUT_FLAGS_DIR_TX :
+		 HWRM_TF_EM_INSERT_INPUT_FLAGS_DIR_RX);
+	req.flags = tfp_cpu_to_le_16(flags);
+	req.em_record_size_bits = em_parms->em_record_sz_in_bits;
+	req.em_record_idx = *rptr_index;
+	req.key0_hash = key0_hash;
+	req.key1_hash = key1_hash;
+
+	parms.tf_type = HWRM_TF_EM_HASH_INSERT;
+	parms.req_data = (uint32_t *)&req;
+	parms.req_size = sizeof(req);
+	parms.resp_data = (uint32_t *)&resp;
+	parms.resp_size = sizeof(resp);
+	parms.mailbox = dev->ops->tf_dev_get_mailbox();
+
+	rc = tfp_send_msg_direct(tfp,
+				 &parms);
+	if (rc)
+		return rc;
+
+	*rptr_entry = resp.rptr_entry;
+	*rptr_index = resp.rptr_index;
+	*num_of_entries = resp.num_of_entries;
+
+	return 0;
+}
+
 int
 tf_msg_delete_em_entry(struct tf *tfp,
 		       struct tf_delete_em_entry_parms *em_parms)
diff --git a/drivers/net/bnxt/tf_core/tf_msg.h b/drivers/net/bnxt/tf_core/tf_msg.h
index 25e29a554f..1d82ce5049 100644
--- a/drivers/net/bnxt/tf_core/tf_msg.h
+++ b/drivers/net/bnxt/tf_core/tf_msg.h
@@ -225,6 +225,41 @@ int tf_msg_insert_em_internal_entry(struct tf *tfp,
 				    uint16_t *rptr_index,
 				    uint8_t *rptr_entry,
 				    uint8_t *num_of_entries);
+/**
+ * Sends EM hash internal insert request to Firmware
+ *
+ * [in] tfp
+ *   Pointer to TF handle
+ *
+ * [in] params
+ *   Pointer to em insert parameter list
+ *
+ * [in] key0_hash
+ *      CRC32 hash of key
+ *
+ * [in] key1_hash
+ *      Lookup3 hash of key
+ *
+ * [in] rptr_index
+ *   Record ptr index
+ *
+ * [in] rptr_entry
+ *   Record ptr entry
+ *
+ * [in] num_of_entries
+ *   Number of entries to insert
+ *
+ * Returns:
+ *   0 on Success else internal Truflow error
+ */
+int
+tf_msg_hash_insert_em_internal_entry(struct tf *tfp,
+				struct tf_insert_em_entry_parms *em_parms,
+				uint32_t key0_hash,
+				uint32_t key1_hash,
+				uint16_t *rptr_index,
+				uint8_t *rptr_entry,
+				uint8_t *num_of_entries);
 /**
  * Sends EM internal delete request to Firmware
  *
