From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id D303AA0548;
	Thu,  1 Apr 2021 14:44:31 +0200 (CEST)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 256531412AF;
	Thu,  1 Apr 2021 14:40:37 +0200 (CEST)
Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com
 [67.231.156.173])
 by mails.dpdk.org (Postfix) with ESMTP id CAB2C1412AE
 for <dev@dpdk.org>; Thu,  1 Apr 2021 14:40:35 +0200 (CEST)
Received: from pps.filterd (m0045851.ppops.net [127.0.0.1])
 by mx0b-0016f401.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id
 131CPLSL019082 for <dev@dpdk.org>; Thu, 1 Apr 2021 05:40:35 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;
 h=from : to : cc :
 subject : date : message-id : in-reply-to : references : mime-version :
 content-type; s=pfpt0220; bh=+PviLjaEvymQVmJKggiHcYDGkGYXE4/zDMqPf8U/goQ=;
 b=bNXt230Z7KbOwQfwIfJGaPOitcXwKeIwB1OpRoh1663mKcXXlN9mZ8mAWeSP98VvF5lu
 pVq5u/yIXPe8SQU4SyasSHgnJhNwFQ9dTccFXQGpdbGO5Bblv0p/YNFEzAgB1t5kSIUZ
 uChKpVrTkZ7vczSlfF/OyrTqfNdWK/eUnE7O7ugmLJr55Xms+L3FDTHtsCvmarkbjnzj
 fEZrVNZGYVGDXCw1LiVE6Sr5VFOt4cPrLxWizQfI7O9kkezXzRn3mIaFOQOipRzkfKec
 KoyiBhESh7M9rLcOglA1cufY/ltYgAjNVy3ppll8XKOa9lXNrizvm0ohAYFT6FcDNoe7 vw== 
Received: from dc5-exch02.marvell.com ([199.233.59.182])
 by mx0b-0016f401.pphosted.com with ESMTP id 37n28jje5m-1
 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)
 for <dev@dpdk.org>; Thu, 01 Apr 2021 05:40:35 -0700
Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com
 (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.2;
 Thu, 1 Apr 2021 05:40:32 -0700
Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com
 (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.2 via Frontend
 Transport; Thu, 1 Apr 2021 05:40:33 -0700
Received: from hyd1588t430.marvell.com (unknown [10.29.52.204])
 by maili.marvell.com (Postfix) with ESMTP id 43C1A3F704B;
 Thu,  1 Apr 2021 05:40:30 -0700 (PDT)
From: Nithin Dabilpuram <ndabilpuram@marvell.com>
To: <dev@dpdk.org>
CC: <jerinj@marvell.com>, <skori@marvell.com>, <skoteshwar@marvell.com>,
 <pbhagavatula@marvell.com>, <kirankumark@marvell.com>,
 <psatheesh@marvell.com>, <asekhar@marvell.com>, Nithin Dabilpuram
 <ndabilpuram@marvell.com>
Date: Thu, 1 Apr 2021 18:08:04 +0530
Message-ID: <20210401123817.14348-40-ndabilpuram@marvell.com>
X-Mailer: git-send-email 2.8.4
In-Reply-To: <20210401123817.14348-1-ndabilpuram@marvell.com>
References: <20210305133918.8005-1-ndabilpuram@marvell.com>
 <20210401123817.14348-1-ndabilpuram@marvell.com>
MIME-Version: 1.0
Content-Type: text/plain
X-Proofpoint-GUID: jxU1lXibmdF3nhlm0grm84Jnr-gPBvap
X-Proofpoint-ORIG-GUID: jxU1lXibmdF3nhlm0grm84Jnr-gPBvap
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369, 18.0.761
 definitions=2021-04-01_05:2021-03-31,
 2021-04-01 signatures=0
Subject: [dpdk-dev] [PATCH v3 39/52] common/cnxk: add nix tm debug support
 and misc utils
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>

Add support to dump TM HW registers and hierarchy on error.
This patch also adds support for misc utils such as API to
query TM HW resource availability, resource pre-allocation
and static priority support on root node.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
 drivers/common/cnxk/roc_nix.h          |   9 +
 drivers/common/cnxk/roc_nix_debug.c    | 330 +++++++++++++++++++++++++++++++++
 drivers/common/cnxk/roc_nix_tm.c       |   1 +
 drivers/common/cnxk/roc_nix_tm_ops.c   | 125 +++++++++++++
 drivers/common/cnxk/roc_nix_tm_utils.c |  18 ++
 drivers/common/cnxk/roc_utils.c        | 108 +++++++++++
 drivers/common/cnxk/version.map        |   6 +
 7 files changed, 597 insertions(+)

diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index ad00efe..b39f461 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -291,6 +291,7 @@ void __roc_api roc_nix_cqe_dump(const struct nix_cqe_hdr_s *cq);
 void __roc_api roc_nix_rq_dump(struct roc_nix_rq *rq);
 void __roc_api roc_nix_cq_dump(struct roc_nix_cq *cq);
 void __roc_api roc_nix_sq_dump(struct roc_nix_sq *sq);
+void __roc_api roc_nix_tm_dump(struct roc_nix *roc_nix);
 void __roc_api roc_nix_dump(struct roc_nix *roc_nix);
 
 /* IRQ */
@@ -394,6 +395,10 @@ int __roc_api roc_nix_tm_shaper_profile_update(
 int __roc_api roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix,
 					       uint32_t id);
 
+int __roc_api roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t lvl,
+				      uint16_t discontig, uint16_t contig);
+uint16_t __roc_api roc_nix_tm_leaf_cnt(struct roc_nix *roc_nix);
+
 struct roc_nix_tm_node *__roc_api roc_nix_tm_node_get(struct roc_nix *roc_nix,
 						      uint32_t node_id);
 struct roc_nix_tm_node *__roc_api
@@ -420,6 +425,10 @@ int __roc_api roc_nix_tm_hierarchy_enable(struct roc_nix *roc_nix,
  * TM utilities API.
  */
 int __roc_api roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id);
+bool __roc_api roc_nix_tm_root_has_sp(struct roc_nix *roc_nix);
+void __roc_api roc_nix_tm_rsrc_max(bool pf, uint16_t schq[ROC_TM_LVL_MAX]);
+int __roc_api roc_nix_tm_rsrc_count(struct roc_nix *roc_nix,
+				    uint16_t schq[ROC_TM_LVL_MAX]);
 int __roc_api roc_nix_tm_node_name_get(struct roc_nix *roc_nix,
 				       uint32_t node_id, char *buf,
 				       size_t buflen);
diff --git a/drivers/common/cnxk/roc_nix_debug.c b/drivers/common/cnxk/roc_nix_debug.c
index a0cf98e..6e56513 100644
--- a/drivers/common/cnxk/roc_nix_debug.c
+++ b/drivers/common/cnxk/roc_nix_debug.c
@@ -44,6 +44,33 @@ static const struct nix_lf_reg_info nix_lf_reg[] = {
 	NIX_REG_INFO(NIX_LF_SEND_ERR_DBG),
 };
 
+static void
+nix_bitmap_dump(struct plt_bitmap *bmp)
+{
+	uint32_t pos = 0, start_pos;
+	uint64_t slab = 0;
+	int i;
+
+	plt_bitmap_scan_init(bmp);
+	plt_bitmap_scan(bmp, &pos, &slab);
+	start_pos = pos;
+
+	nix_dump_no_nl("  \t\t[");
+	do {
+		if (!slab)
+			break;
+		i = 0;
+
+		for (i = 0; i < 64; i++)
+			if (slab & (1ULL << i))
+				nix_dump_no_nl("%d, ", i);
+
+		if (!plt_bitmap_scan(bmp, &pos, &slab))
+			break;
+	} while (start_pos != pos);
+	nix_dump_no_nl(" ]");
+}
+
 int
 roc_nix_lf_get_reg_count(struct roc_nix *roc_nix)
 {
@@ -761,6 +788,309 @@ roc_nix_sq_dump(struct roc_nix_sq *sq)
 	nix_dump("  fc = %p", sq->fc);
 };
 
+static uint8_t
+nix_tm_reg_dump_prep(uint16_t hw_lvl, uint16_t schq, uint16_t link,
+		     uint64_t *reg, char regstr[][NIX_REG_NAME_SZ])
+{
+	uint8_t k = 0;
+
+	switch (hw_lvl) {
+	case NIX_TXSCH_LVL_SMQ:
+		reg[k] = NIX_AF_SMQX_CFG(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_SMQ[%u]_CFG",
+			 schq);
+
+		reg[k] = NIX_AF_MDQX_PARENT(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_MDQ[%u]_PARENT",
+			 schq);
+
+		reg[k] = NIX_AF_MDQX_SCHEDULE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_MDQ[%u]_SCHEDULE", schq);
+
+		reg[k] = NIX_AF_MDQX_PIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_MDQ[%u]_PIR",
+			 schq);
+
+		reg[k] = NIX_AF_MDQX_CIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_MDQ[%u]_CIR",
+			 schq);
+
+		reg[k] = NIX_AF_MDQX_SHAPE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_MDQ[%u]_SHAPE",
+			 schq);
+
+		reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_MDQ[%u]_SW_XOFF",
+			 schq);
+		break;
+	case NIX_TXSCH_LVL_TL4:
+		reg[k] = NIX_AF_TL4X_PARENT(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL4[%u]_PARENT",
+			 schq);
+
+		reg[k] = NIX_AF_TL4X_TOPOLOGY(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL4[%u]_TOPOLOGY", schq);
+
+		reg[k] = NIX_AF_TL4X_SDP_LINK_CFG(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL4[%u]_SDP_LINK_CFG", schq);
+
+		reg[k] = NIX_AF_TL4X_SCHEDULE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL4[%u]_SCHEDULE", schq);
+
+		reg[k] = NIX_AF_TL4X_PIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL4[%u]_PIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL4X_CIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL4[%u]_CIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL4X_SHAPE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL4[%u]_SHAPE",
+			 schq);
+
+		reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL4[%u]_SW_XOFF",
+			 schq);
+		break;
+	case NIX_TXSCH_LVL_TL3:
+		reg[k] = NIX_AF_TL3X_PARENT(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL3[%u]_PARENT",
+			 schq);
+
+		reg[k] = NIX_AF_TL3X_TOPOLOGY(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL3[%u]_TOPOLOGY", schq);
+
+		reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL3_TL2[%u]_LINK[%u]_CFG", schq, link);
+
+		reg[k] = NIX_AF_TL3X_SCHEDULE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL3[%u]_SCHEDULE", schq);
+
+		reg[k] = NIX_AF_TL3X_PIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL3[%u]_PIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL3X_CIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL3[%u]_CIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL3X_SHAPE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL3[%u]_SHAPE",
+			 schq);
+
+		reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL3[%u]_SW_XOFF",
+			 schq);
+		break;
+	case NIX_TXSCH_LVL_TL2:
+		reg[k] = NIX_AF_TL2X_PARENT(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL2[%u]_PARENT",
+			 schq);
+
+		reg[k] = NIX_AF_TL2X_TOPOLOGY(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL2[%u]_TOPOLOGY", schq);
+
+		reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL3_TL2[%u]_LINK[%u]_CFG", schq, link);
+
+		reg[k] = NIX_AF_TL2X_SCHEDULE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL2[%u]_SCHEDULE", schq);
+
+		reg[k] = NIX_AF_TL2X_PIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL2[%u]_PIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL2X_CIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL2[%u]_CIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL2X_SHAPE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL2[%u]_SHAPE",
+			 schq);
+
+		reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL2[%u]_SW_XOFF",
+			 schq);
+		break;
+	case NIX_TXSCH_LVL_TL1:
+
+		reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL1[%u]_TOPOLOGY", schq);
+
+		reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL1[%u]_SCHEDULE", schq);
+
+		reg[k] = NIX_AF_TL1X_CIR(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL1[%u]_CIR",
+			 schq);
+
+		reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ, "NIX_AF_TL1[%u]_SW_XOFF",
+			 schq);
+
+		reg[k] = NIX_AF_TL1X_DROPPED_PACKETS(schq);
+		snprintf(regstr[k++], NIX_REG_NAME_SZ,
+			 "NIX_AF_TL1[%u]_DROPPED_PACKETS", schq);
+		break;
+	default:
+		break;
+	}
+
+	if (k > MAX_REGS_PER_MBOX_MSG) {
+		nix_dump("\t!!!NIX TM Registers request overflow!!!");
+		return 0;
+	}
+	return k;
+}
+
+static void
+nix_tm_dump_lvl(struct nix *nix, struct nix_tm_node_list *list, uint8_t hw_lvl)
+{
+	char regstr[MAX_REGS_PER_MBOX_MSG * 2][NIX_REG_NAME_SZ];
+	uint64_t reg[MAX_REGS_PER_MBOX_MSG * 2];
+	struct mbox *mbox = (&nix->dev)->mbox;
+	struct nix_txschq_config *req, *rsp;
+	const char *lvlstr, *parent_lvlstr;
+	struct nix_tm_node *node, *parent;
+	struct nix_tm_node *root = NULL;
+	uint32_t schq, parent_schq;
+	bool found = false;
+	uint8_t j, k, rc;
+
+	TAILQ_FOREACH(node, list, node) {
+		if (node->hw_lvl != hw_lvl)
+			continue;
+
+		found = true;
+		parent = node->parent;
+		if (hw_lvl == NIX_TXSCH_LVL_CNT) {
+			lvlstr = "SQ";
+			schq = node->id;
+		} else {
+			lvlstr = nix_tm_hwlvl2str(node->hw_lvl);
+			schq = node->hw_id;
+		}
+
+		if (parent) {
+			parent_schq = parent->hw_id;
+			parent_lvlstr = nix_tm_hwlvl2str(parent->hw_lvl);
+		} else if (node->hw_lvl == NIX_TXSCH_LVL_TL1) {
+			parent_schq = nix->tx_link;
+			parent_lvlstr = "LINK";
+		} else {
+			parent_schq = node->parent_hw_id;
+			parent_lvlstr = nix_tm_hwlvl2str(node->hw_lvl + 1);
+		}
+
+		nix_dump("\t(%p%s) %s_%d->%s_%d", node,
+			 node->child_realloc ? "[CR]" : "", lvlstr, schq,
+			 parent_lvlstr, parent_schq);
+
+		if (!(node->flags & NIX_TM_NODE_HWRES))
+			continue;
+
+		/* Need to dump TL1 when root is TL2 */
+		if (node->hw_lvl == nix->tm_root_lvl)
+			root = node;
+
+		/* Dump registers only when HWRES is present */
+		k = nix_tm_reg_dump_prep(node->hw_lvl, schq, nix->tx_link, reg,
+					 regstr);
+		if (!k)
+			continue;
+
+		req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+		req->read = 1;
+		req->lvl = node->hw_lvl;
+		req->num_regs = k;
+		mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k);
+		rc = mbox_process_msg(mbox, (void **)&rsp);
+		if (!rc) {
+			for (j = 0; j < k; j++)
+				nix_dump("\t\t%s=0x%016" PRIx64, regstr[j],
+					 rsp->regval[j]);
+		} else {
+			nix_dump("\t!!!Failed to dump registers!!!");
+		}
+	}
+
+	if (found)
+		nix_dump("\n");
+
+	/* Dump TL1 node data when root level is TL2 */
+	if (root && root->hw_lvl == NIX_TXSCH_LVL_TL2) {
+		k = nix_tm_reg_dump_prep(NIX_TXSCH_LVL_TL1, root->parent_hw_id,
+					 nix->tx_link, reg, regstr);
+		if (!k)
+			return;
+
+		req = mbox_alloc_msg_nix_txschq_cfg(mbox);
+		req->read = 1;
+		req->lvl = NIX_TXSCH_LVL_TL1;
+		req->num_regs = k;
+		mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k);
+		rc = mbox_process_msg(mbox, (void **)&rsp);
+		if (!rc) {
+			for (j = 0; j < k; j++)
+				nix_dump("\t\t%s=0x%016" PRIx64, regstr[j],
+					 rsp->regval[j]);
+		} else {
+			nix_dump("\t!!!Failed to dump registers!!!");
+		}
+		nix_dump("\n");
+	}
+}
+
+void
+roc_nix_tm_dump(struct roc_nix *roc_nix)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+	struct dev *dev = &nix->dev;
+	uint8_t hw_lvl, i;
+
+	nix_dump("===TM hierarchy and registers dump of %s (pf:vf) (%d:%d)===",
+		 nix->pci_dev->name, dev_get_pf(dev->pf_func),
+		 dev_get_vf(dev->pf_func));
+
+	/* Dump all trees */
+	for (i = 0; i < ROC_NIX_TM_TREE_MAX; i++) {
+		nix_dump("\tTM %s:", nix_tm_tree2str(i));
+		for (hw_lvl = 0; hw_lvl <= NIX_TXSCH_LVL_CNT; hw_lvl++)
+			nix_tm_dump_lvl(nix, &nix->trees[i], hw_lvl);
+	}
+
+	/* Dump unused resources */
+	nix_dump("\tTM unused resources:");
+	hw_lvl = NIX_TXSCH_LVL_SMQ;
+	for (; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
+		nix_dump("\t\ttxschq        %7s num = %d",
+			 nix_tm_hwlvl2str(hw_lvl),
+			 nix_tm_resource_avail(nix, hw_lvl, false));
+
+		nix_bitmap_dump(nix->schq_bmp[hw_lvl]);
+		nix_dump("\n");
+
+		nix_dump("\t\ttxschq_contig %7s num = %d",
+			 nix_tm_hwlvl2str(hw_lvl),
+			 nix_tm_resource_avail(nix, hw_lvl, true));
+		nix_bitmap_dump(nix->schq_contig_bmp[hw_lvl]);
+		nix_dump("\n");
+	}
+}
+
 void
 roc_nix_dump(struct roc_nix *roc_nix)
 {
diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c
index 9b328c9..ad54e17 100644
--- a/drivers/common/cnxk/roc_nix_tm.c
+++ b/drivers/common/cnxk/roc_nix_tm.c
@@ -393,6 +393,7 @@ roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq)
 
 	return 0;
 exit:
+	roc_nix_tm_dump(sq->roc_nix);
 	roc_nix_queues_ctx_dump(sq->roc_nix);
 	return -EFAULT;
 }
diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c b/drivers/common/cnxk/roc_nix_tm_ops.c
index e4463d1..ed244d4 100644
--- a/drivers/common/cnxk/roc_nix_tm_ops.c
+++ b/drivers/common/cnxk/roc_nix_tm_ops.c
@@ -579,6 +579,58 @@ roc_nix_tm_node_suspend_resume(struct roc_nix *roc_nix, uint32_t node_id,
 }
 
 int
+roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t lvl,
+			uint16_t discontig, uint16_t contig)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+	struct mbox *mbox = (&nix->dev)->mbox;
+	struct nix_txsch_alloc_req *req;
+	struct nix_txsch_alloc_rsp *rsp;
+	uint8_t hw_lvl;
+	int rc = -ENOSPC;
+
+	hw_lvl = nix_tm_lvl2nix(nix, lvl);
+	if (hw_lvl == NIX_TXSCH_LVL_CNT)
+		return -EINVAL;
+
+	/* Preallocate contiguous */
+	if (nix->contig_rsvd[hw_lvl] < contig) {
+		req = mbox_alloc_msg_nix_txsch_alloc(mbox);
+		if (req == NULL)
+			return rc;
+		req->schq_contig[hw_lvl] = contig - nix->contig_rsvd[hw_lvl];
+
+		rc = mbox_process_msg(mbox, (void *)&rsp);
+		if (rc)
+			return rc;
+
+		nix_tm_copy_rsp_to_nix(nix, rsp);
+	}
+
+	/* Preallocate contiguous */
+	if (nix->discontig_rsvd[hw_lvl] < discontig) {
+		req = mbox_alloc_msg_nix_txsch_alloc(mbox);
+		if (req == NULL)
+			return -ENOSPC;
+		req->schq[hw_lvl] = discontig - nix->discontig_rsvd[hw_lvl];
+
+		rc = mbox_process_msg(mbox, (void *)&rsp);
+		if (rc)
+			return rc;
+
+		nix_tm_copy_rsp_to_nix(nix, rsp);
+	}
+
+	/* Save thresholds */
+	nix->contig_rsvd[hw_lvl] = contig;
+	nix->discontig_rsvd[hw_lvl] = discontig;
+	/* Release anything present above thresholds */
+	nix_tm_release_resources(nix, hw_lvl, true, true);
+	nix_tm_release_resources(nix, hw_lvl, false, true);
+	return 0;
+}
+
+int
 roc_nix_tm_node_shaper_update(struct roc_nix *roc_nix, uint32_t node_id,
 			      uint32_t profile_id, bool force_update)
 {
@@ -904,3 +956,76 @@ roc_nix_tm_fini(struct roc_nix *roc_nix)
 	nix->tm_tree = 0;
 	nix->tm_flags &= ~NIX_TM_HIERARCHY_ENA;
 }
+
+int
+roc_nix_tm_rsrc_count(struct roc_nix *roc_nix, uint16_t schq[ROC_TM_LVL_MAX])
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+	struct mbox *mbox = (&nix->dev)->mbox;
+	struct free_rsrcs_rsp *rsp;
+	uint8_t hw_lvl;
+	int rc, i;
+
+	/* Get the current free resources */
+	mbox_alloc_msg_free_rsrc_cnt(mbox);
+	rc = mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < ROC_TM_LVL_MAX; i++) {
+		hw_lvl = nix_tm_lvl2nix(nix, i);
+		if (hw_lvl == NIX_TXSCH_LVL_CNT)
+			continue;
+
+		schq[i] = (nix->is_nix1 ? rsp->schq_nix1[hw_lvl] :
+						rsp->schq[hw_lvl]);
+	}
+
+	return 0;
+}
+
+void
+roc_nix_tm_rsrc_max(bool pf, uint16_t schq[ROC_TM_LVL_MAX])
+{
+	uint8_t hw_lvl, i;
+	uint16_t max;
+
+	for (i = 0; i < ROC_TM_LVL_MAX; i++) {
+		hw_lvl = pf ? nix_tm_lvl2nix_tl1_root(i) :
+				    nix_tm_lvl2nix_tl2_root(i);
+
+		switch (hw_lvl) {
+		case NIX_TXSCH_LVL_SMQ:
+			max = (roc_model_is_cn9k() ?
+					     NIX_CN9K_TXSCH_LVL_SMQ_MAX :
+					     NIX_TXSCH_LVL_SMQ_MAX);
+			break;
+		case NIX_TXSCH_LVL_TL4:
+			max = NIX_TXSCH_LVL_TL4_MAX;
+			break;
+		case NIX_TXSCH_LVL_TL3:
+			max = NIX_TXSCH_LVL_TL3_MAX;
+			break;
+		case NIX_TXSCH_LVL_TL2:
+			max = pf ? NIX_TXSCH_LVL_TL2_MAX : 1;
+			break;
+		case NIX_TXSCH_LVL_TL1:
+			max = pf ? 1 : 0;
+			break;
+		default:
+			max = 0;
+			break;
+		}
+		schq[i] = max;
+	}
+}
+
+bool
+roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+	if (nix->tm_flags & NIX_TM_TL1_NO_SP)
+		return false;
+	return true;
+}
diff --git a/drivers/common/cnxk/roc_nix_tm_utils.c b/drivers/common/cnxk/roc_nix_tm_utils.c
index b644716..1d7dd68 100644
--- a/drivers/common/cnxk/roc_nix_tm_utils.c
+++ b/drivers/common/cnxk/roc_nix_tm_utils.c
@@ -868,6 +868,24 @@ nix_tm_resource_estimate(struct nix *nix, uint16_t *schq_contig, uint16_t *schq,
 	return cnt;
 }
 
+uint16_t
+roc_nix_tm_leaf_cnt(struct roc_nix *roc_nix)
+{
+	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+	struct nix_tm_node_list *list;
+	struct nix_tm_node *node;
+	uint16_t leaf_cnt = 0;
+
+	/* Count leafs only in user list */
+	list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
+	TAILQ_FOREACH(node, list, node) {
+		if (node->id < nix->nb_tx_queues)
+			leaf_cnt++;
+	}
+
+	return leaf_cnt;
+}
+
 int
 roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
 {
diff --git a/drivers/common/cnxk/roc_utils.c b/drivers/common/cnxk/roc_utils.c
index 2b157a3..6cfa28d 100644
--- a/drivers/common/cnxk/roc_utils.c
+++ b/drivers/common/cnxk/roc_utils.c
@@ -38,6 +38,69 @@ roc_error_msg_get(int errorcode)
 	case NIX_ERR_AQ_WRITE_FAILED:
 		err_msg = "AQ write failed";
 		break;
+	case NIX_ERR_TM_LEAF_NODE_GET:
+		err_msg = "TM leaf node get failed";
+		break;
+	case NIX_ERR_TM_INVALID_LVL:
+		err_msg = "TM node level invalid";
+		break;
+	case NIX_ERR_TM_INVALID_PRIO:
+		err_msg = "TM node priority invalid";
+		break;
+	case NIX_ERR_TM_INVALID_PARENT:
+		err_msg = "TM parent id invalid";
+		break;
+	case NIX_ERR_TM_NODE_EXISTS:
+		err_msg = "TM Node Exists";
+		break;
+	case NIX_ERR_TM_INVALID_NODE:
+		err_msg = "TM node id invalid";
+		break;
+	case NIX_ERR_TM_INVALID_SHAPER_PROFILE:
+		err_msg = "TM shaper profile invalid";
+		break;
+	case NIX_ERR_TM_WEIGHT_EXCEED:
+		err_msg = "TM DWRR weight exceeded";
+		break;
+	case NIX_ERR_TM_CHILD_EXISTS:
+		err_msg = "TM node children exists";
+		break;
+	case NIX_ERR_TM_INVALID_PEAK_SZ:
+		err_msg = "TM peak size invalid";
+		break;
+	case NIX_ERR_TM_INVALID_PEAK_RATE:
+		err_msg = "TM peak rate invalid";
+		break;
+	case NIX_ERR_TM_INVALID_COMMIT_SZ:
+		err_msg = "TM commit size invalid";
+		break;
+	case NIX_ERR_TM_INVALID_COMMIT_RATE:
+		err_msg = "TM commit rate invalid";
+		break;
+	case NIX_ERR_TM_SHAPER_PROFILE_IN_USE:
+		err_msg = "TM shaper profile in use";
+		break;
+	case NIX_ERR_TM_SHAPER_PROFILE_EXISTS:
+		err_msg = "TM shaper profile exists";
+		break;
+	case NIX_ERR_TM_INVALID_TREE:
+		err_msg = "TM tree invalid";
+		break;
+	case NIX_ERR_TM_PARENT_PRIO_UPDATE:
+		err_msg = "TM node parent and prio update failed";
+		break;
+	case NIX_ERR_TM_PRIO_EXCEEDED:
+		err_msg = "TM node priority exceeded";
+		break;
+	case NIX_ERR_TM_PRIO_ORDER:
+		err_msg = "TM node priority not in order";
+		break;
+	case NIX_ERR_TM_MULTIPLE_RR_GROUPS:
+		err_msg = "TM multiple rr groups";
+		break;
+	case NIX_ERR_TM_SQ_UPDATE_FAIL:
+		err_msg = "TM SQ update failed";
+		break;
 	case NIX_ERR_NDC_SYNC:
 		err_msg = "NDC Sync failed";
 		break;
@@ -75,9 +138,54 @@ roc_error_msg_get(int errorcode)
 	case NIX_AF_ERR_AF_LF_ALLOC:
 		err_msg = "NIX LF alloc failed";
 		break;
+	case NIX_AF_ERR_TLX_INVALID:
+		err_msg = "Invalid NIX TLX";
+		break;
+	case NIX_AF_ERR_TLX_ALLOC_FAIL:
+		err_msg = "NIX TLX alloc failed";
+		break;
+	case NIX_AF_ERR_RSS_SIZE_INVALID:
+		err_msg = "Invalid RSS size";
+		break;
+	case NIX_AF_ERR_RSS_GRPS_INVALID:
+		err_msg = "Invalid RSS groups";
+		break;
+	case NIX_AF_ERR_FRS_INVALID:
+		err_msg = "Invalid frame size";
+		break;
+	case NIX_AF_ERR_RX_LINK_INVALID:
+		err_msg = "Invalid Rx link";
+		break;
+	case NIX_AF_INVAL_TXSCHQ_CFG:
+		err_msg = "Invalid Tx scheduling config";
+		break;
+	case NIX_AF_SMQ_FLUSH_FAILED:
+		err_msg = "SMQ flush failed";
+		break;
 	case NIX_AF_ERR_LF_RESET:
 		err_msg = "NIX LF reset failed";
 		break;
+	case NIX_AF_ERR_MARK_CFG_FAIL:
+		err_msg = "Marking config failed";
+		break;
+	case NIX_AF_ERR_LSO_CFG_FAIL:
+		err_msg = "LSO config failed";
+		break;
+	case NIX_AF_INVAL_NPA_PF_FUNC:
+		err_msg = "Invalid NPA pf_func";
+		break;
+	case NIX_AF_INVAL_SSO_PF_FUNC:
+		err_msg = "Invalid SSO pf_func";
+		break;
+	case NIX_AF_ERR_TX_VTAG_NOSPC:
+		err_msg = "No space for Tx VTAG";
+		break;
+	case NIX_AF_ERR_RX_VTAG_INUSE:
+		err_msg = "Rx VTAG is in use";
+		break;
+	case NIX_AF_ERR_PTP_CONFIG_FAIL:
+		err_msg = "PTP config failed";
+		break;
 	case UTIL_ERR_FS:
 		err_msg = "file operation failed";
 		break;
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index a5efbea..21f1d5a 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -104,11 +104,13 @@ INTERNAL {
 	roc_nix_xstats_names_get;
 	roc_nix_switch_hdr_set;
 	roc_nix_eeprom_info_get;
+	roc_nix_tm_dump;
 	roc_nix_tm_fini;
 	roc_nix_tm_free_resources;
 	roc_nix_tm_hierarchy_disable;
 	roc_nix_tm_hierarchy_enable;
 	roc_nix_tm_init;
+	roc_nix_tm_leaf_cnt;
 	roc_nix_tm_node_add;
 	roc_nix_tm_node_delete;
 	roc_nix_tm_node_get;
@@ -119,7 +121,11 @@ INTERNAL {
 	roc_nix_tm_node_pkt_mode_update;
 	roc_nix_tm_node_shaper_update;
 	roc_nix_tm_node_suspend_resume;
+	roc_nix_tm_prealloc_res;
 	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_profile_add;
 	roc_nix_tm_shaper_profile_delete;
 	roc_nix_tm_shaper_profile_get;
-- 
2.8.4