diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index 90dc413a04..d9a4613782 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -490,6 +490,16 @@ int __roc_api roc_nix_tm_node_name_get(struct roc_nix *roc_nix,
 				       uint32_t node_id, char *buf,
 				       size_t buflen);
 int __roc_api roc_nix_smq_flush(struct roc_nix *roc_nix);
+int __roc_api roc_nix_tm_max_prio(struct roc_nix *roc_nix, int lvl);
+int __roc_api roc_nix_tm_lvl_is_leaf(struct roc_nix *roc_nix, int lvl);
+void __roc_api
+roc_nix_tm_shaper_default_red_algo(struct roc_nix_tm_node *node,
+				   struct roc_nix_tm_shaper_profile *profile);
+int __roc_api roc_nix_tm_lvl_cnt_get(struct roc_nix *roc_nix);
+int __roc_api roc_nix_tm_lvl_have_link_access(struct roc_nix *roc_nix, int lvl);
+int __roc_api roc_nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix);
+bool __roc_api roc_nix_tm_is_user_hierarchy_enabled(struct roc_nix *nix);
+int __roc_api roc_nix_tm_tree_type_get(struct roc_nix *nix);
 
 /* MAC */
 int __roc_api roc_nix_mac_rxtx_start_stop(struct roc_nix *roc_nix, bool start);
diff --git a/drivers/common/cnxk/roc_nix_priv.h b/drivers/common/cnxk/roc_nix_priv.h
index 3412bf25e5..b67f648e5a 100644
--- a/drivers/common/cnxk/roc_nix_priv.h
+++ b/drivers/common/cnxk/roc_nix_priv.h
@@ -350,7 +350,6 @@ int nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree);
 int nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree);
 int nix_tm_sq_sched_conf(struct nix *nix, struct nix_tm_node *node,
 			 bool rr_quantum_only);
-int nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix);
 
 /*
  * TM priv utils.
diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c
index 947320ae63..08d6e866fe 100644
--- a/drivers/common/cnxk/roc_nix_tm.c
+++ b/drivers/common/cnxk/roc_nix_tm.c
@@ -155,6 +155,20 @@ nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree)
 	return 0;
 }
 
+static int
+nix_tm_root_node_get(struct nix *nix, int tree)
+{
+	struct nix_tm_node_list *list = nix_tm_node_list(nix, tree);
+	struct nix_tm_node *tm_node;
+
+	TAILQ_FOREACH(tm_node, list, node) {
+		if (tm_node->hw_lvl == nix->tm_root_lvl)
+			return 1;
+	}
+
+	return 0;
+}
+
 int
 nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node)
 {
@@ -207,6 +221,10 @@ nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node)
 	if (nix_tm_node_search(nix, node_id, tree))
 		return NIX_ERR_TM_NODE_EXISTS;
 
+	/* Check if root node exists */
+	if (hw_lvl == nix->tm_root_lvl && nix_tm_root_node_get(nix, tree))
+		return NIX_ERR_TM_NODE_EXISTS;
+
 	profile = nix_tm_shaper_profile_search(nix, profile_id);
 	if (!nix_tm_is_leaf(nix, lvl)) {
 		/* Check if shaper profile exists for non leaf node */
@@ -1157,7 +1175,7 @@ nix_tm_prepare_default_tree(struct roc_nix *roc_nix)
 }
 
 int
-nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix)
+roc_nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	uint32_t nonleaf_id = nix->nb_tx_queues;
@@ -1227,7 +1245,7 @@ nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix)
 			goto error;
 
 		node->id = i;
-		node->parent_id = parent;
+		node->parent_id = parent + i;
 		node->priority = 0;
 		node->weight = NIX_TM_DFLT_RR_WT;
 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c b/drivers/common/cnxk/roc_nix_tm_ops.c
index f956f8d8ed..eee80d5f00 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -934,13 +934,6 @@ roc_nix_tm_init(struct roc_nix *roc_nix)
 		return rc;
 	}
 
-	/* Prepare rlimit tree */
-	rc = nix_tm_prepare_rate_limited_tree(roc_nix);
-	if (rc) {
-		plt_err("failed to prepare rlimit tm tree, rc=%d", rc);
-		return rc;
-	}
-
 	return rc;
 }
 
@@ -958,11 +951,11 @@ roc_nix_tm_rlimit_sq(struct roc_nix *roc_nix, uint16_t qid, uint64_t rate)
 	uint8_t k = 0;
 	int rc;
 
-	if (nix->tm_tree != ROC_NIX_TM_RLIMIT ||
+	if ((nix->tm_tree == ROC_NIX_TM_USER) ||
 	    !(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
 		return NIX_ERR_TM_INVALID_TREE;
 
-	node = nix_tm_node_search(nix, qid, ROC_NIX_TM_RLIMIT);
+	node = nix_tm_node_search(nix, qid, nix->tm_tree);
 
 	/* check if we found a valid leaf node */
 	if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
diff --git a/drivers/common/cnxk/roc_nix_tm_utils.c b/drivers/common/cnxk/roc_nix_tm_utils.c
index 83306248e8..a135454eeb 100644
--- a/drivers/common/cnxk/roc_nix_tm_utils.c
+++ b/drivers/common/cnxk/roc_nix_tm_utils.c
@@ -235,6 +235,9 @@ nix_tm_shaper_conf_get(struct nix_tm_shaper_profile *profile,
 		       struct nix_tm_shaper_data *cir,
 		       struct nix_tm_shaper_data *pir)
 {
+	memset(cir, 0, sizeof(*cir));
+	memset(pir, 0, sizeof(*pir));
+
 	if (!profile)
 		return;
 
@@ -624,8 +627,6 @@ nix_tm_shaper_reg_prep(struct nix_tm_node *node,
 	uint64_t adjust = 0;
 	uint8_t k = 0;
 
-	memset(&cir, 0, sizeof(cir));
-	memset(&pir, 0, sizeof(pir));
 	nix_tm_shaper_conf_get(profile, &cir, &pir);
 
 	if (profile && node->pkt_mode)
@@ -1043,15 +1044,16 @@ roc_nix_tm_node_stats_get(struct roc_nix *roc_nix, uint32_t node_id, bool clear,
 	if (node->hw_lvl != NIX_TXSCH_LVL_TL1)
 		return NIX_ERR_OP_NOTSUP;
 
+	/* Check if node has HW resource */
+	if (!(node->flags & NIX_TM_NODE_HWRES))
+		return 0;
+
 	schq = node->hw_id;
 	/* Skip fetch if not requested */
 	if (!n_stats)
 		goto clear_stats;
 
 	memset(n_stats, 0, sizeof(struct roc_nix_tm_node_stats));
-	/* Check if node has HW resource */
-	if (!(node->flags & NIX_TM_NODE_HWRES))
-		return 0;
 
 	req = mbox_alloc_msg_nix_txschq_cfg(mbox);
 	req->read = 1;
@@ -1102,3 +1104,77 @@ roc_nix_tm_node_stats_get(struct roc_nix *roc_nix, uint32_t node_id, bool clear,
 
 	return mbox_process_msg(mbox, (void **)&rsp);
 }
+
+bool
+roc_nix_tm_is_user_hierarchy_enabled(struct roc_nix *roc_nix)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+	if ((nix->tm_flags & NIX_TM_HIERARCHY_ENA) &&
+	    (nix->tm_tree == ROC_NIX_TM_USER))
+		return true;
+	return false;
+}
+
+int
+roc_nix_tm_tree_type_get(struct roc_nix *roc_nix)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+	return nix->tm_tree;
+}
+
+int
+roc_nix_tm_max_prio(struct roc_nix *roc_nix, int lvl)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+	int hw_lvl = nix_tm_lvl2nix(nix, lvl);
+
+	return nix_tm_max_prio(nix, hw_lvl);
+}
+
+int
+roc_nix_tm_lvl_is_leaf(struct roc_nix *roc_nix, int lvl)
+{
+	return nix_tm_is_leaf(roc_nix_to_nix_priv(roc_nix), lvl);
+}
+
+void
+roc_nix_tm_shaper_default_red_algo(struct roc_nix_tm_node *node,
+				   struct roc_nix_tm_shaper_profile *roc_prof)
+{
+	struct nix_tm_node *tm_node = (struct nix_tm_node *)node;
+	struct nix_tm_shaper_profile *profile;
+	struct nix_tm_shaper_data cir, pir;
+
+	profile = (struct nix_tm_shaper_profile *)roc_prof->reserved;
+	tm_node->red_algo = NIX_REDALG_STD;
+
+	/* C0 doesn't support STALL when both PIR & CIR are enabled */
+	if (profile && roc_model_is_cn96_cx()) {
+		nix_tm_shaper_conf_get(profile, &cir, &pir);
+
+		if (pir.rate && cir.rate)
+			tm_node->red_algo = NIX_REDALG_DISCARD;
+	}
+}
+
+int
+roc_nix_tm_lvl_cnt_get(struct roc_nix *roc_nix)
+{
+	if (nix_tm_have_tl1_access(roc_nix_to_nix_priv(roc_nix)))
+		return NIX_TXSCH_LVL_CNT;
+
+	return (NIX_TXSCH_LVL_CNT - 1);
+}
+
+int
+roc_nix_tm_lvl_have_link_access(struct roc_nix *roc_nix, int lvl)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+	if (nix_tm_lvl2nix(nix, lvl) == NIX_TXSCH_LVL_TL1)
+		return 1;
+
+	return 0;
+}
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 776cabbdef..9b7cbf69f0 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -175,10 +175,16 @@ INTERNAL {
 	roc_nix_tm_err_to_rte_err;
 	roc_nix_tm_fini;
 	roc_nix_tm_free_resources;
+	roc_nix_tm_lvl_cnt_get;
+	roc_nix_tm_tree_type_get;
 	roc_nix_tm_hierarchy_disable;
 	roc_nix_tm_hierarchy_enable;
 	roc_nix_tm_init;
+	roc_nix_tm_is_user_hierarchy_enabled;
 	roc_nix_tm_leaf_cnt;
+	roc_nix_tm_lvl_have_link_access;
+	roc_nix_tm_lvl_is_leaf;
+	roc_nix_tm_max_prio;
 	roc_nix_tm_node_add;
 	roc_nix_tm_node_delete;
 	roc_nix_tm_node_get;
@@ -191,10 +197,12 @@ INTERNAL {
 	roc_nix_tm_node_stats_get;
 	roc_nix_tm_node_suspend_resume;
 	roc_nix_tm_prealloc_res;
+	roc_nix_tm_prepare_rate_limited_tree;
 	roc_nix_tm_rlimit_sq;
 	roc_nix_tm_root_has_sp;
 	roc_nix_tm_rsrc_count;
 	roc_nix_tm_rsrc_max;
+	roc_nix_tm_shaper_default_red_algo;
 	roc_nix_tm_shaper_profile_add;
 	roc_nix_tm_shaper_profile_delete;
 	roc_nix_tm_shaper_profile_get;
