xref: /dpdk/drivers/common/cnxk/roc_nix_tm.c (revision 4785c406c26df4f8c29a84ea89712aa95acde44d)
105d727e8SNithin Dabilpuram /* SPDX-License-Identifier: BSD-3-Clause
205d727e8SNithin Dabilpuram  * Copyright(C) 2021 Marvell.
305d727e8SNithin Dabilpuram  */
405d727e8SNithin Dabilpuram 
505d727e8SNithin Dabilpuram #include "roc_api.h"
605d727e8SNithin Dabilpuram #include "roc_priv.h"
705d727e8SNithin Dabilpuram 
8df405df9SNithin Dabilpuram static inline int
9df405df9SNithin Dabilpuram bitmap_ctzll(uint64_t slab)
10df405df9SNithin Dabilpuram {
11df405df9SNithin Dabilpuram 	if (slab == 0)
12df405df9SNithin Dabilpuram 		return 0;
13df405df9SNithin Dabilpuram 
14354bf671SJerin Jacob 	return plt_ctz64(slab);
15df405df9SNithin Dabilpuram }
16df405df9SNithin Dabilpuram 
17c2460d14SSatha Rao void
18c2460d14SSatha Rao nix_tm_clear_shaper_profiles(struct nix *nix)
19c2460d14SSatha Rao {
206a78d41eSGowrishankar Muthukrishnan 	struct nix_tm_shaper_profile *shaper_profile, *tmp;
216a78d41eSGowrishankar Muthukrishnan 	struct nix_tm_shaper_profile_list *list;
22c2460d14SSatha Rao 
236a78d41eSGowrishankar Muthukrishnan 	list = &nix->shaper_profile_list;
246a78d41eSGowrishankar Muthukrishnan 	PLT_TAILQ_FOREACH_SAFE(shaper_profile, list, shaper, tmp) {
25c2460d14SSatha Rao 		if (shaper_profile->ref_cnt)
26c2460d14SSatha Rao 			plt_warn("Shaper profile %u has non zero references",
27c2460d14SSatha Rao 				 shaper_profile->id);
28c2460d14SSatha Rao 		TAILQ_REMOVE(&nix->shaper_profile_list, shaper_profile, shaper);
29c2460d14SSatha Rao 		nix_tm_shaper_profile_free(shaper_profile);
30c2460d14SSatha Rao 	}
31c2460d14SSatha Rao }
32c2460d14SSatha Rao 
330885429cSNithin Dabilpuram static int
340885429cSNithin Dabilpuram nix_tm_node_reg_conf(struct nix *nix, struct nix_tm_node *node)
350885429cSNithin Dabilpuram {
360885429cSNithin Dabilpuram 	uint64_t regval_mask[MAX_REGS_PER_MBOX_MSG];
370885429cSNithin Dabilpuram 	uint64_t regval[MAX_REGS_PER_MBOX_MSG];
380885429cSNithin Dabilpuram 	struct nix_tm_shaper_profile *profile;
390885429cSNithin Dabilpuram 	uint64_t reg[MAX_REGS_PER_MBOX_MSG];
400885429cSNithin Dabilpuram 	struct mbox *mbox = (&nix->dev)->mbox;
410885429cSNithin Dabilpuram 	struct nix_txschq_config *req;
420885429cSNithin Dabilpuram 	int rc = -EFAULT;
430885429cSNithin Dabilpuram 	uint32_t hw_lvl;
440885429cSNithin Dabilpuram 	uint8_t k = 0;
450885429cSNithin Dabilpuram 
460885429cSNithin Dabilpuram 	memset(regval, 0, sizeof(regval));
470885429cSNithin Dabilpuram 	memset(regval_mask, 0, sizeof(regval_mask));
480885429cSNithin Dabilpuram 
490885429cSNithin Dabilpuram 	profile = nix_tm_shaper_profile_search(nix, node->shaper_profile_id);
500885429cSNithin Dabilpuram 	hw_lvl = node->hw_lvl;
510885429cSNithin Dabilpuram 
520885429cSNithin Dabilpuram 	/* Need this trigger to configure TL1 */
530885429cSNithin Dabilpuram 	if (!nix_tm_have_tl1_access(nix) && hw_lvl == NIX_TXSCH_LVL_TL2) {
540885429cSNithin Dabilpuram 		/* Prepare default conf for TL1 */
5544a9307cSRakesh Kudurumalla 		req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
560885429cSNithin Dabilpuram 		req->lvl = NIX_TXSCH_LVL_TL1;
570885429cSNithin Dabilpuram 
58f0b9158cSNithin Dabilpuram 		k = nix_tm_tl1_default_prep(nix, node->parent_hw_id, req->reg,
590885429cSNithin Dabilpuram 					    req->regval);
600885429cSNithin Dabilpuram 		req->num_regs = k;
610885429cSNithin Dabilpuram 		rc = mbox_process(mbox);
6244a9307cSRakesh Kudurumalla 		mbox_put(mbox);
630885429cSNithin Dabilpuram 		if (rc)
640885429cSNithin Dabilpuram 			goto error;
650885429cSNithin Dabilpuram 	}
660885429cSNithin Dabilpuram 
670885429cSNithin Dabilpuram 	/* Prepare topology config */
680885429cSNithin Dabilpuram 	k = nix_tm_topology_reg_prep(nix, node, reg, regval, regval_mask);
690885429cSNithin Dabilpuram 
700885429cSNithin Dabilpuram 	/* Prepare schedule config */
710885429cSNithin Dabilpuram 	k += nix_tm_sched_reg_prep(nix, node, &reg[k], &regval[k]);
720885429cSNithin Dabilpuram 
730885429cSNithin Dabilpuram 	/* Prepare shaping config */
740885429cSNithin Dabilpuram 	k += nix_tm_shaper_reg_prep(node, profile, &reg[k], &regval[k]);
750885429cSNithin Dabilpuram 
760885429cSNithin Dabilpuram 	if (!k)
770885429cSNithin Dabilpuram 		return 0;
780885429cSNithin Dabilpuram 
790885429cSNithin Dabilpuram 	/* Copy and send config mbox */
8044a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
810885429cSNithin Dabilpuram 	req->lvl = hw_lvl;
820885429cSNithin Dabilpuram 	req->num_regs = k;
830885429cSNithin Dabilpuram 
840885429cSNithin Dabilpuram 	mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k);
850885429cSNithin Dabilpuram 	mbox_memcpy(req->regval, regval, sizeof(uint64_t) * k);
860885429cSNithin Dabilpuram 	mbox_memcpy(req->regval_mask, regval_mask, sizeof(uint64_t) * k);
870885429cSNithin Dabilpuram 
880885429cSNithin Dabilpuram 	rc = mbox_process(mbox);
8944a9307cSRakesh Kudurumalla 	mbox_put(mbox);
900885429cSNithin Dabilpuram 	if (rc)
910885429cSNithin Dabilpuram 		goto error;
920885429cSNithin Dabilpuram 
930885429cSNithin Dabilpuram 	return 0;
940885429cSNithin Dabilpuram error:
950885429cSNithin Dabilpuram 	plt_err("Txschq conf failed for node %p, rc=%d", node, rc);
960885429cSNithin Dabilpuram 	return rc;
970885429cSNithin Dabilpuram }
980885429cSNithin Dabilpuram 
990885429cSNithin Dabilpuram int
1000885429cSNithin Dabilpuram nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree)
1010885429cSNithin Dabilpuram {
1020885429cSNithin Dabilpuram 	struct nix_tm_node_list *list;
1030885429cSNithin Dabilpuram 	struct nix_tm_node *node;
1040885429cSNithin Dabilpuram 	uint32_t hw_lvl;
1050885429cSNithin Dabilpuram 	int rc = 0;
1060885429cSNithin Dabilpuram 
1070885429cSNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
1080885429cSNithin Dabilpuram 
1090885429cSNithin Dabilpuram 	for (hw_lvl = 0; hw_lvl <= nix->tm_root_lvl; hw_lvl++) {
1100885429cSNithin Dabilpuram 		TAILQ_FOREACH(node, list, node) {
1110885429cSNithin Dabilpuram 			if (node->hw_lvl != hw_lvl)
1120885429cSNithin Dabilpuram 				continue;
11358debb81SNithin Dabilpuram 
11458debb81SNithin Dabilpuram 			/* Only one TL3/TL2 Link config should have BP enable
11558debb81SNithin Dabilpuram 			 * set per channel only for PF or lbk vf.
11658debb81SNithin Dabilpuram 			 */
11758debb81SNithin Dabilpuram 			node->bp_capa = 0;
11878fb5efeSNithin Dabilpuram 			if (!nix->sdp_link && node->hw_lvl == nix->tm_link_cfg_lvl)
11958debb81SNithin Dabilpuram 				node->bp_capa = 1;
12058debb81SNithin Dabilpuram 
1210885429cSNithin Dabilpuram 			rc = nix_tm_node_reg_conf(nix, node);
1220885429cSNithin Dabilpuram 			if (rc)
1230885429cSNithin Dabilpuram 				goto exit;
1240885429cSNithin Dabilpuram 		}
1250885429cSNithin Dabilpuram 	}
1260885429cSNithin Dabilpuram exit:
1270885429cSNithin Dabilpuram 	return rc;
1280885429cSNithin Dabilpuram }
1290885429cSNithin Dabilpuram 
130be3009e7SNithin Dabilpuram int
131df405df9SNithin Dabilpuram nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree)
132df405df9SNithin Dabilpuram {
133df405df9SNithin Dabilpuram 	struct nix_tm_node *child, *parent;
134df405df9SNithin Dabilpuram 	struct nix_tm_node_list *list;
135df405df9SNithin Dabilpuram 	uint32_t rr_prio, max_prio;
136df405df9SNithin Dabilpuram 	uint32_t rr_num = 0;
137df405df9SNithin Dabilpuram 
138df405df9SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
139df405df9SNithin Dabilpuram 
140df405df9SNithin Dabilpuram 	/* Release all the node hw resources locally
141df405df9SNithin Dabilpuram 	 * if parent marked as dirty and resource exists.
142df405df9SNithin Dabilpuram 	 */
143df405df9SNithin Dabilpuram 	TAILQ_FOREACH(child, list, node) {
144df405df9SNithin Dabilpuram 		/* Release resource only if parent direct hierarchy changed */
145df405df9SNithin Dabilpuram 		if (child->flags & NIX_TM_NODE_HWRES && child->parent &&
146df405df9SNithin Dabilpuram 		    child->parent->child_realloc) {
147df405df9SNithin Dabilpuram 			nix_tm_free_node_resource(nix, child);
148df405df9SNithin Dabilpuram 		}
149df405df9SNithin Dabilpuram 		child->max_prio = UINT32_MAX;
150df405df9SNithin Dabilpuram 	}
151df405df9SNithin Dabilpuram 
152df405df9SNithin Dabilpuram 	TAILQ_FOREACH(parent, list, node) {
153df405df9SNithin Dabilpuram 		/* Count group of children of same priority i.e are RR */
154df405df9SNithin Dabilpuram 		rr_num = nix_tm_check_rr(nix, parent->id, tree, &rr_prio,
155df405df9SNithin Dabilpuram 					 &max_prio);
156df405df9SNithin Dabilpuram 
157df405df9SNithin Dabilpuram 		/* Assuming that multiple RR groups are
158df405df9SNithin Dabilpuram 		 * not configured based on capability.
159df405df9SNithin Dabilpuram 		 */
160df405df9SNithin Dabilpuram 		parent->rr_prio = rr_prio;
161df405df9SNithin Dabilpuram 		parent->rr_num = rr_num;
162df405df9SNithin Dabilpuram 		parent->max_prio = max_prio;
163df405df9SNithin Dabilpuram 	}
164df405df9SNithin Dabilpuram 
165df405df9SNithin Dabilpuram 	return 0;
166df405df9SNithin Dabilpuram }
167df405df9SNithin Dabilpuram 
168f9dbd4a5SSatha Rao static int
169f9dbd4a5SSatha Rao nix_tm_root_node_get(struct nix *nix, int tree)
170f9dbd4a5SSatha Rao {
171f9dbd4a5SSatha Rao 	struct nix_tm_node_list *list = nix_tm_node_list(nix, tree);
172f9dbd4a5SSatha Rao 	struct nix_tm_node *tm_node;
173f9dbd4a5SSatha Rao 
174f9dbd4a5SSatha Rao 	TAILQ_FOREACH(tm_node, list, node) {
175f9dbd4a5SSatha Rao 		if (tm_node->hw_lvl == nix->tm_root_lvl)
176f9dbd4a5SSatha Rao 			return 1;
177f9dbd4a5SSatha Rao 	}
178f9dbd4a5SSatha Rao 
179f9dbd4a5SSatha Rao 	return 0;
180f9dbd4a5SSatha Rao }
181f9dbd4a5SSatha Rao 
182df405df9SNithin Dabilpuram int
183be3009e7SNithin Dabilpuram nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node)
184be3009e7SNithin Dabilpuram {
185be3009e7SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
186be3009e7SNithin Dabilpuram 	struct nix_tm_shaper_profile *profile;
187be3009e7SNithin Dabilpuram 	uint32_t node_id, parent_id, lvl;
188be3009e7SNithin Dabilpuram 	struct nix_tm_node *parent_node;
189be3009e7SNithin Dabilpuram 	uint32_t priority, profile_id;
190be3009e7SNithin Dabilpuram 	uint8_t hw_lvl, exp_next_lvl;
191be3009e7SNithin Dabilpuram 	enum roc_nix_tm_tree tree;
192be3009e7SNithin Dabilpuram 	int rc;
193be3009e7SNithin Dabilpuram 
194be3009e7SNithin Dabilpuram 	node_id = node->id;
195be3009e7SNithin Dabilpuram 	priority = node->priority;
196be3009e7SNithin Dabilpuram 	parent_id = node->parent_id;
197be3009e7SNithin Dabilpuram 	profile_id = node->shaper_profile_id;
198be3009e7SNithin Dabilpuram 	lvl = node->lvl;
199be3009e7SNithin Dabilpuram 	tree = node->tree;
200be3009e7SNithin Dabilpuram 
201be3009e7SNithin Dabilpuram 	plt_tm_dbg("Add node %s lvl %u id %u, prio 0x%x weight 0x%x "
202be3009e7SNithin Dabilpuram 		   "parent %u profile 0x%x tree %u",
203be3009e7SNithin Dabilpuram 		   nix_tm_hwlvl2str(nix_tm_lvl2nix(nix, lvl)), lvl, node_id,
204be3009e7SNithin Dabilpuram 		   priority, node->weight, parent_id, profile_id, tree);
205be3009e7SNithin Dabilpuram 
206be3009e7SNithin Dabilpuram 	if (tree >= ROC_NIX_TM_TREE_MAX)
207be3009e7SNithin Dabilpuram 		return NIX_ERR_PARAM;
208be3009e7SNithin Dabilpuram 
209be3009e7SNithin Dabilpuram 	/* Translate sw level id's to nix hw level id's */
210be3009e7SNithin Dabilpuram 	hw_lvl = nix_tm_lvl2nix(nix, lvl);
211be3009e7SNithin Dabilpuram 	if (hw_lvl == NIX_TXSCH_LVL_CNT && !nix_tm_is_leaf(nix, lvl))
212be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_INVALID_LVL;
213be3009e7SNithin Dabilpuram 
214be3009e7SNithin Dabilpuram 	/* Leaf nodes have to be same priority */
215be3009e7SNithin Dabilpuram 	if (nix_tm_is_leaf(nix, lvl) && priority != 0)
216be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_INVALID_PRIO;
217be3009e7SNithin Dabilpuram 
218be3009e7SNithin Dabilpuram 	parent_node = nix_tm_node_search(nix, parent_id, tree);
219be3009e7SNithin Dabilpuram 
220be3009e7SNithin Dabilpuram 	if (node_id < nix->nb_tx_queues)
221be3009e7SNithin Dabilpuram 		exp_next_lvl = NIX_TXSCH_LVL_SMQ;
222be3009e7SNithin Dabilpuram 	else
223be3009e7SNithin Dabilpuram 		exp_next_lvl = hw_lvl + 1;
224be3009e7SNithin Dabilpuram 
225be3009e7SNithin Dabilpuram 	/* Check if there is no parent node yet */
226be3009e7SNithin Dabilpuram 	if (hw_lvl != nix->tm_root_lvl &&
227be3009e7SNithin Dabilpuram 	    (!parent_node || parent_node->hw_lvl != exp_next_lvl))
228be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_INVALID_PARENT;
229be3009e7SNithin Dabilpuram 
230be3009e7SNithin Dabilpuram 	/* Check if a node already exists */
231be3009e7SNithin Dabilpuram 	if (nix_tm_node_search(nix, node_id, tree))
232be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_NODE_EXISTS;
233be3009e7SNithin Dabilpuram 
234f9dbd4a5SSatha Rao 	/* Check if root node exists */
235f9dbd4a5SSatha Rao 	if (hw_lvl == nix->tm_root_lvl && nix_tm_root_node_get(nix, tree))
236f9dbd4a5SSatha Rao 		return NIX_ERR_TM_NODE_EXISTS;
237f9dbd4a5SSatha Rao 
238be3009e7SNithin Dabilpuram 	profile = nix_tm_shaper_profile_search(nix, profile_id);
239be3009e7SNithin Dabilpuram 	if (!nix_tm_is_leaf(nix, lvl)) {
240be3009e7SNithin Dabilpuram 		/* Check if shaper profile exists for non leaf node */
241be3009e7SNithin Dabilpuram 		if (!profile && profile_id != ROC_NIX_TM_SHAPER_PROFILE_NONE)
242be3009e7SNithin Dabilpuram 			return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
243be3009e7SNithin Dabilpuram 
244be3009e7SNithin Dabilpuram 		/* Packet mode in profile should match with that of tm node */
245be3009e7SNithin Dabilpuram 		if (profile && profile->pkt_mode != node->pkt_mode)
246be3009e7SNithin Dabilpuram 			return NIX_ERR_TM_PKT_MODE_MISMATCH;
247be3009e7SNithin Dabilpuram 	}
248be3009e7SNithin Dabilpuram 
249be3009e7SNithin Dabilpuram 	/* Check if there is second DWRR already in siblings or holes in prio */
250be3009e7SNithin Dabilpuram 	rc = nix_tm_validate_prio(nix, lvl, parent_id, priority, tree);
251be3009e7SNithin Dabilpuram 	if (rc)
252be3009e7SNithin Dabilpuram 		return rc;
253be3009e7SNithin Dabilpuram 
2546fe49f10SNithin Dabilpuram 	if (node->weight > roc_nix_tm_max_sched_wt_get())
255be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_WEIGHT_EXCEED;
256be3009e7SNithin Dabilpuram 
257be3009e7SNithin Dabilpuram 	node->hw_lvl = nix_tm_lvl2nix(nix, lvl);
258be3009e7SNithin Dabilpuram 	node->rr_prio = 0xF;
259be3009e7SNithin Dabilpuram 	node->max_prio = UINT32_MAX;
260be3009e7SNithin Dabilpuram 	node->hw_id = NIX_TM_HW_ID_INVALID;
261be3009e7SNithin Dabilpuram 	node->flags = 0;
262be3009e7SNithin Dabilpuram 
263be3009e7SNithin Dabilpuram 	if (profile)
264be3009e7SNithin Dabilpuram 		profile->ref_cnt++;
265be3009e7SNithin Dabilpuram 
266be3009e7SNithin Dabilpuram 	node->parent = parent_node;
267be3009e7SNithin Dabilpuram 	if (parent_node)
268be3009e7SNithin Dabilpuram 		parent_node->child_realloc = true;
269be3009e7SNithin Dabilpuram 	node->parent_hw_id = NIX_TM_HW_ID_INVALID;
270be3009e7SNithin Dabilpuram 
271be3009e7SNithin Dabilpuram 	TAILQ_INSERT_TAIL(&nix->trees[tree], node, node);
272be3009e7SNithin Dabilpuram 	plt_tm_dbg("Added node %s lvl %u id %u (%p)",
273be3009e7SNithin Dabilpuram 		   nix_tm_hwlvl2str(node->hw_lvl), lvl, node_id, node);
274be3009e7SNithin Dabilpuram 	return 0;
275be3009e7SNithin Dabilpuram }
27605d727e8SNithin Dabilpuram 
27705d727e8SNithin Dabilpuram int
27805d727e8SNithin Dabilpuram nix_tm_clear_path_xoff(struct nix *nix, struct nix_tm_node *node)
27905d727e8SNithin Dabilpuram {
28044a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
28105d727e8SNithin Dabilpuram 	struct nix_txschq_config *req;
28205d727e8SNithin Dabilpuram 	struct nix_tm_node *p;
28305d727e8SNithin Dabilpuram 	int rc;
28405d727e8SNithin Dabilpuram 
28505d727e8SNithin Dabilpuram 	/* Enable nodes in path for flush to succeed */
28605d727e8SNithin Dabilpuram 	if (!nix_tm_is_leaf(nix, node->lvl))
28705d727e8SNithin Dabilpuram 		p = node;
28805d727e8SNithin Dabilpuram 	else
28905d727e8SNithin Dabilpuram 		p = node->parent;
29005d727e8SNithin Dabilpuram 	while (p) {
29105d727e8SNithin Dabilpuram 		if (!(p->flags & NIX_TM_NODE_ENABLED) &&
29205d727e8SNithin Dabilpuram 		    (p->flags & NIX_TM_NODE_HWRES)) {
29305d727e8SNithin Dabilpuram 			req = mbox_alloc_msg_nix_txschq_cfg(mbox);
29405d727e8SNithin Dabilpuram 			req->lvl = p->hw_lvl;
29505d727e8SNithin Dabilpuram 			req->num_regs = nix_tm_sw_xoff_prep(p, false, req->reg,
29605d727e8SNithin Dabilpuram 							    req->regval);
29705d727e8SNithin Dabilpuram 			rc = mbox_process(mbox);
29805d727e8SNithin Dabilpuram 			if (rc)
29944a9307cSRakesh Kudurumalla 				goto exit;
30005d727e8SNithin Dabilpuram 
30105d727e8SNithin Dabilpuram 			p->flags |= NIX_TM_NODE_ENABLED;
30205d727e8SNithin Dabilpuram 		}
30305d727e8SNithin Dabilpuram 		p = p->parent;
30405d727e8SNithin Dabilpuram 	}
30505d727e8SNithin Dabilpuram 
30644a9307cSRakesh Kudurumalla 	rc = 0;
30744a9307cSRakesh Kudurumalla exit:
30844a9307cSRakesh Kudurumalla 	mbox_put(mbox);
30944a9307cSRakesh Kudurumalla 	return rc;
31005d727e8SNithin Dabilpuram }
31105d727e8SNithin Dabilpuram 
31205d727e8SNithin Dabilpuram int
31320d02329SSunil Kumar Kori nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
31478fb5efeSNithin Dabilpuram 		     bool enable)
31558debb81SNithin Dabilpuram {
31658debb81SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
31758debb81SNithin Dabilpuram 	enum roc_nix_tm_tree tree = nix->tm_tree;
31858debb81SNithin Dabilpuram 	struct mbox *mbox = (&nix->dev)->mbox;
31958debb81SNithin Dabilpuram 	struct nix_txschq_config *req = NULL;
32058debb81SNithin Dabilpuram 	struct nix_tm_node_list *list;
321d120c089SSatha Rao 	uint16_t link = nix->tx_link;
32220d02329SSunil Kumar Kori 	struct nix_tm_node *sq_node;
32320d02329SSunil Kumar Kori 	struct nix_tm_node *parent;
32458debb81SNithin Dabilpuram 	struct nix_tm_node *node;
325cc90e35bSHarman Kalra 	struct roc_nix_sq *sq_s;
32678fb5efeSNithin Dabilpuram 	uint16_t rel_chan = 0;
327174f2f35SSunil Kumar Kori 	uint8_t parent_lvl;
32858debb81SNithin Dabilpuram 	uint8_t k = 0;
32978fb5efeSNithin Dabilpuram 	int rc = 0, i;
33058debb81SNithin Dabilpuram 
33148054ca3SHarman Kalra 	if (roc_nix_is_sdp(roc_nix))
33248054ca3SHarman Kalra 		return 0;
33348054ca3SHarman Kalra 
334cc90e35bSHarman Kalra 	sq_s = nix->sqs[sq];
335cc90e35bSHarman Kalra 	if (!sq_s)
336cc90e35bSHarman Kalra 		return -ENOENT;
337cc90e35bSHarman Kalra 
33820d02329SSunil Kumar Kori 	sq_node = nix_tm_node_search(nix, sq, nix->tm_tree);
339d120c089SSatha Rao 	if (!sq_node)
340d120c089SSatha Rao 		return -ENOENT;
341d120c089SSatha Rao 
342174f2f35SSunil Kumar Kori 	parent_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH2 :
343174f2f35SSunil Kumar Kori 		      ROC_TM_LVL_SCH1);
344174f2f35SSunil Kumar Kori 
34520d02329SSunil Kumar Kori 	parent = sq_node->parent;
34620d02329SSunil Kumar Kori 	while (parent) {
347174f2f35SSunil Kumar Kori 		if (parent->lvl == parent_lvl)
34820d02329SSunil Kumar Kori 			break;
34920d02329SSunil Kumar Kori 
35020d02329SSunil Kumar Kori 		parent = parent->parent;
35120d02329SSunil Kumar Kori 	}
352d120c089SSatha Rao 	if (!parent)
353d120c089SSatha Rao 		return -ENOENT;
35420d02329SSunil Kumar Kori 
35558debb81SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
35658debb81SNithin Dabilpuram 
35778fb5efeSNithin Dabilpuram 	/* Get relative channel if loopback */
35878fb5efeSNithin Dabilpuram 	if (roc_nix_is_lbk(roc_nix))
35978fb5efeSNithin Dabilpuram 		rel_chan = nix_tm_lbk_relchan_get(nix);
36078fb5efeSNithin Dabilpuram 	else
36178fb5efeSNithin Dabilpuram 		rel_chan = tc;
36278fb5efeSNithin Dabilpuram 
363cc90e35bSHarman Kalra 	/* Enable request, parent rel chan already configured */
364cc90e35bSHarman Kalra 	if (enable && parent->rel_chan != NIX_TM_CHAN_INVALID &&
36578fb5efeSNithin Dabilpuram 	    parent->rel_chan != rel_chan) {
36678fb5efeSNithin Dabilpuram 		plt_err("SQ %d: parent node TL3 id %d already has rel_chan %d set",
36778fb5efeSNithin Dabilpuram 			sq, parent->hw_id, parent->rel_chan);
36820d02329SSunil Kumar Kori 		rc = -EINVAL;
36920d02329SSunil Kumar Kori 		goto err;
37020d02329SSunil Kumar Kori 	}
37120d02329SSunil Kumar Kori 
372cc90e35bSHarman Kalra 	/* No action if enable request for a non participating SQ. This case is
373cc90e35bSHarman Kalra 	 * required to handle post flush where TCs should be reconfigured after
374cc90e35bSHarman Kalra 	 * pre flush.
375cc90e35bSHarman Kalra 	 */
376cc90e35bSHarman Kalra 	if (enable && sq_s->tc == ROC_NIX_PFC_CLASS_INVALID &&
377cc90e35bSHarman Kalra 	    tc == ROC_NIX_PFC_CLASS_INVALID)
378cc90e35bSHarman Kalra 		return 0;
379cc90e35bSHarman Kalra 
380cc90e35bSHarman Kalra 	/* Find the parent TL3 */
38158debb81SNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
38258debb81SNithin Dabilpuram 		if (node->hw_lvl != nix->tm_link_cfg_lvl)
38358debb81SNithin Dabilpuram 			continue;
38458debb81SNithin Dabilpuram 
38558debb81SNithin Dabilpuram 		if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
38658debb81SNithin Dabilpuram 			continue;
38758debb81SNithin Dabilpuram 
388cc90e35bSHarman Kalra 		/* Restrict sharing of TL3 across the queues */
38978fb5efeSNithin Dabilpuram 		if (enable && node != parent && node->rel_chan == rel_chan) {
39078fb5efeSNithin Dabilpuram 			plt_warn("SQ %d: siblng node TL3 %d already has %d(%d) tc value set",
39178fb5efeSNithin Dabilpuram 				 sq, node->hw_id, tc, rel_chan);
39278fb5efeSNithin Dabilpuram 			return -EEXIST;
393cc90e35bSHarman Kalra 		}
394cc90e35bSHarman Kalra 	}
39520d02329SSunil Kumar Kori 
39678fb5efeSNithin Dabilpuram 	/* Allocating TL3 request */
39744a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
39858debb81SNithin Dabilpuram 	req->lvl = nix->tm_link_cfg_lvl;
39958debb81SNithin Dabilpuram 	k = 0;
40058debb81SNithin Dabilpuram 
40178fb5efeSNithin Dabilpuram 	/* Enable PFC/pause on the identified TL3 */
402cc90e35bSHarman Kalra 	req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(parent->hw_id, link);
40378fb5efeSNithin Dabilpuram 	req->regval[k] = enable ? rel_chan : 0;
40420d02329SSunil Kumar Kori 	req->regval[k] |= enable ? BIT_ULL(13) : 0;
40520d02329SSunil Kumar Kori 	req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0));
40658debb81SNithin Dabilpuram 	k++;
40758debb81SNithin Dabilpuram 
40858debb81SNithin Dabilpuram 	req->num_regs = k;
40958debb81SNithin Dabilpuram 	rc = mbox_process(mbox);
41058debb81SNithin Dabilpuram 	if (rc)
41158debb81SNithin Dabilpuram 		goto err;
41258debb81SNithin Dabilpuram 
41378fb5efeSNithin Dabilpuram 	parent->rel_chan = enable ? rel_chan : NIX_TM_CHAN_INVALID;
41478fb5efeSNithin Dabilpuram 	sq_s->tc = enable ? tc : ROC_NIX_PFC_CLASS_INVALID;
41578fb5efeSNithin Dabilpuram 	/* Clear other SQ's with same TC i.e same parent node */
41678fb5efeSNithin Dabilpuram 	for (i = 0; !enable && i < nix->nb_tx_queues; i++) {
41778fb5efeSNithin Dabilpuram 		if (nix->sqs[i] && nix->sqs[i]->tc == tc)
41878fb5efeSNithin Dabilpuram 			nix->sqs[i]->tc = ROC_NIX_PFC_CLASS_INVALID;
41978fb5efeSNithin Dabilpuram 	}
420cc90e35bSHarman Kalra 
42144a9307cSRakesh Kudurumalla 	rc = 0;
42278fb5efeSNithin Dabilpuram 	plt_tm_dbg("SQ %u: TL3 %d TC %u %s",
42378fb5efeSNithin Dabilpuram 		   sq, parent->hw_id, tc, enable ? "enabled" : "disabled");
42444a9307cSRakesh Kudurumalla 	goto exit;
42558debb81SNithin Dabilpuram err:
42658debb81SNithin Dabilpuram 	plt_err("Failed to %s bp on link %u, rc=%d(%s)",
42758debb81SNithin Dabilpuram 		enable ? "enable" : "disable", link, rc, roc_error_msg_get(rc));
42844a9307cSRakesh Kudurumalla exit:
42944a9307cSRakesh Kudurumalla 	mbox_put(mbox);
43058debb81SNithin Dabilpuram 	return rc;
43158debb81SNithin Dabilpuram }
43258debb81SNithin Dabilpuram 
43358debb81SNithin Dabilpuram int
43458debb81SNithin Dabilpuram nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled)
43558debb81SNithin Dabilpuram {
43658debb81SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
43758debb81SNithin Dabilpuram 	struct nix_txschq_config *req = NULL, *rsp;
43858debb81SNithin Dabilpuram 	enum roc_nix_tm_tree tree = nix->tm_tree;
43944a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
44058debb81SNithin Dabilpuram 	struct nix_tm_node_list *list;
44158debb81SNithin Dabilpuram 	struct nix_tm_node *node;
44258debb81SNithin Dabilpuram 	bool found = false;
44358debb81SNithin Dabilpuram 	uint8_t enable = 1;
44458debb81SNithin Dabilpuram 	uint8_t k = 0, i;
44558debb81SNithin Dabilpuram 	uint16_t link;
44658debb81SNithin Dabilpuram 	int rc = 0;
44758debb81SNithin Dabilpuram 
44858debb81SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
44958debb81SNithin Dabilpuram 	link = nix->tx_link;
45058debb81SNithin Dabilpuram 
45158debb81SNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
45258debb81SNithin Dabilpuram 		if (node->hw_lvl != nix->tm_link_cfg_lvl)
45358debb81SNithin Dabilpuram 			continue;
45458debb81SNithin Dabilpuram 
45558debb81SNithin Dabilpuram 		if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
45658debb81SNithin Dabilpuram 			continue;
45758debb81SNithin Dabilpuram 
45858debb81SNithin Dabilpuram 		found = true;
45958debb81SNithin Dabilpuram 		if (!req) {
46058debb81SNithin Dabilpuram 			req = mbox_alloc_msg_nix_txschq_cfg(mbox);
46158debb81SNithin Dabilpuram 			req->read = 1;
46258debb81SNithin Dabilpuram 			req->lvl = nix->tm_link_cfg_lvl;
46358debb81SNithin Dabilpuram 			k = 0;
46458debb81SNithin Dabilpuram 		}
46558debb81SNithin Dabilpuram 
46658debb81SNithin Dabilpuram 		req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link);
46758debb81SNithin Dabilpuram 		k++;
46858debb81SNithin Dabilpuram 
46958debb81SNithin Dabilpuram 		if (k >= MAX_REGS_PER_MBOX_MSG) {
47058debb81SNithin Dabilpuram 			req->num_regs = k;
47158debb81SNithin Dabilpuram 			rc = mbox_process_msg(mbox, (void **)&rsp);
47258debb81SNithin Dabilpuram 			if (rc || rsp->num_regs != k)
47358debb81SNithin Dabilpuram 				goto err;
47458debb81SNithin Dabilpuram 			req = NULL;
47558debb81SNithin Dabilpuram 
47658debb81SNithin Dabilpuram 			/* Report it as enabled only if enabled or all */
47758debb81SNithin Dabilpuram 			for (i = 0; i < k; i++)
47858debb81SNithin Dabilpuram 				enable &= !!(rsp->regval[i] & BIT_ULL(13));
47958debb81SNithin Dabilpuram 		}
48058debb81SNithin Dabilpuram 	}
48158debb81SNithin Dabilpuram 
48258debb81SNithin Dabilpuram 	if (req) {
48358debb81SNithin Dabilpuram 		req->num_regs = k;
484a3b48642SNithin Dabilpuram 		rc = mbox_process_msg(mbox, (void **)&rsp);
48558debb81SNithin Dabilpuram 		if (rc)
48658debb81SNithin Dabilpuram 			goto err;
48758debb81SNithin Dabilpuram 		/* Report it as enabled only if enabled or all */
48858debb81SNithin Dabilpuram 		for (i = 0; i < k; i++)
48958debb81SNithin Dabilpuram 			enable &= !!(rsp->regval[i] & BIT_ULL(13));
49058debb81SNithin Dabilpuram 	}
49158debb81SNithin Dabilpuram 
49258debb81SNithin Dabilpuram 	*is_enabled = found ? !!enable : false;
49344a9307cSRakesh Kudurumalla 	rc = 0;
49444a9307cSRakesh Kudurumalla 	goto exit;
49558debb81SNithin Dabilpuram err:
49658debb81SNithin Dabilpuram 	plt_err("Failed to get bp status on link %u, rc=%d(%s)", link, rc,
49758debb81SNithin Dabilpuram 		roc_error_msg_get(rc));
49844a9307cSRakesh Kudurumalla exit:
49944a9307cSRakesh Kudurumalla 	mbox_put(mbox);
50058debb81SNithin Dabilpuram 	return rc;
50158debb81SNithin Dabilpuram }
50258debb81SNithin Dabilpuram 
50358debb81SNithin Dabilpuram int
50405d727e8SNithin Dabilpuram nix_tm_smq_xoff(struct nix *nix, struct nix_tm_node *node, bool enable)
50505d727e8SNithin Dabilpuram {
50605d727e8SNithin Dabilpuram 	struct mbox *mbox = (&nix->dev)->mbox;
50705d727e8SNithin Dabilpuram 	struct nix_txschq_config *req;
50805d727e8SNithin Dabilpuram 	uint16_t smq;
50905d727e8SNithin Dabilpuram 	int rc;
51005d727e8SNithin Dabilpuram 
51105d727e8SNithin Dabilpuram 	smq = node->hw_id;
51205d727e8SNithin Dabilpuram 	plt_tm_dbg("Setting SMQ %u XOFF/FLUSH to %s", smq,
51305d727e8SNithin Dabilpuram 		   enable ? "enable" : "disable");
51405d727e8SNithin Dabilpuram 
51505d727e8SNithin Dabilpuram 	rc = nix_tm_clear_path_xoff(nix, node);
51605d727e8SNithin Dabilpuram 	if (rc)
51705d727e8SNithin Dabilpuram 		return rc;
51805d727e8SNithin Dabilpuram 
51944a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
52005d727e8SNithin Dabilpuram 	req->lvl = NIX_TXSCH_LVL_SMQ;
52105d727e8SNithin Dabilpuram 	req->num_regs = 1;
52205d727e8SNithin Dabilpuram 
52305d727e8SNithin Dabilpuram 	req->reg[0] = NIX_AF_SMQX_CFG(smq);
52405d727e8SNithin Dabilpuram 	req->regval[0] = enable ? (BIT_ULL(50) | BIT_ULL(49)) : 0;
52505d727e8SNithin Dabilpuram 	req->regval_mask[0] =
52605d727e8SNithin Dabilpuram 		enable ? ~(BIT_ULL(50) | BIT_ULL(49)) : ~BIT_ULL(50);
52705d727e8SNithin Dabilpuram 
52844a9307cSRakesh Kudurumalla 	rc = mbox_process(mbox);
52944a9307cSRakesh Kudurumalla 	mbox_put(mbox);
53044a9307cSRakesh Kudurumalla 	return rc;
53105d727e8SNithin Dabilpuram }
53205d727e8SNithin Dabilpuram 
53305d727e8SNithin Dabilpuram int
53405d727e8SNithin Dabilpuram nix_tm_leaf_data_get(struct nix *nix, uint16_t sq, uint32_t *rr_quantum,
53505d727e8SNithin Dabilpuram 		     uint16_t *smq)
53605d727e8SNithin Dabilpuram {
53705d727e8SNithin Dabilpuram 	struct nix_tm_node *node;
53805d727e8SNithin Dabilpuram 	int rc;
53905d727e8SNithin Dabilpuram 
54005d727e8SNithin Dabilpuram 	node = nix_tm_node_search(nix, sq, nix->tm_tree);
54105d727e8SNithin Dabilpuram 
54205d727e8SNithin Dabilpuram 	/* Check if we found a valid leaf node */
54305d727e8SNithin Dabilpuram 	if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
54405d727e8SNithin Dabilpuram 	    node->parent->hw_id == NIX_TM_HW_ID_INVALID) {
54505d727e8SNithin Dabilpuram 		return -EIO;
54605d727e8SNithin Dabilpuram 	}
54705d727e8SNithin Dabilpuram 
54805d727e8SNithin Dabilpuram 	/* Get SMQ Id of leaf node's parent */
54905d727e8SNithin Dabilpuram 	*smq = node->parent->hw_id;
55005d727e8SNithin Dabilpuram 	*rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
55105d727e8SNithin Dabilpuram 
55205d727e8SNithin Dabilpuram 	rc = nix_tm_smq_xoff(nix, node->parent, false);
55305d727e8SNithin Dabilpuram 	if (rc)
55405d727e8SNithin Dabilpuram 		return rc;
55505d727e8SNithin Dabilpuram 	node->flags |= NIX_TM_NODE_ENABLED;
55605d727e8SNithin Dabilpuram 	return 0;
55705d727e8SNithin Dabilpuram }
55805d727e8SNithin Dabilpuram 
55905d727e8SNithin Dabilpuram int
56005d727e8SNithin Dabilpuram roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq)
56105d727e8SNithin Dabilpuram {
56205d727e8SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(sq->roc_nix);
56305d727e8SNithin Dabilpuram 	uint16_t sqb_cnt, head_off, tail_off;
56405d727e8SNithin Dabilpuram 	uint64_t wdata, val, prev;
56505d727e8SNithin Dabilpuram 	uint16_t qid = sq->qid;
56605d727e8SNithin Dabilpuram 	int64_t *regaddr;
56705d727e8SNithin Dabilpuram 	uint64_t timeout; /* 10's of usec */
56805d727e8SNithin Dabilpuram 
56905d727e8SNithin Dabilpuram 	/* Wait for enough time based on shaper min rate */
57005d727e8SNithin Dabilpuram 	timeout = (sq->nb_desc * roc_nix_max_pkt_len(sq->roc_nix) * 8 * 1E5);
57105d727e8SNithin Dabilpuram 	/* Wait for worst case scenario of this SQ being last priority
57205d727e8SNithin Dabilpuram 	 * and so have to wait for all other SQ's drain out by their own.
57305d727e8SNithin Dabilpuram 	 */
57405d727e8SNithin Dabilpuram 	timeout = timeout * nix->nb_tx_queues;
57505d727e8SNithin Dabilpuram 	timeout = timeout / nix->tm_rate_min;
57605d727e8SNithin Dabilpuram 	if (!timeout)
57705d727e8SNithin Dabilpuram 		timeout = 10000;
57805d727e8SNithin Dabilpuram 
57905d727e8SNithin Dabilpuram 	wdata = ((uint64_t)qid << 32);
58005d727e8SNithin Dabilpuram 	regaddr = (int64_t *)(nix->base + NIX_LF_SQ_OP_STATUS);
58105d727e8SNithin Dabilpuram 	val = roc_atomic64_add_nosync(wdata, regaddr);
58205d727e8SNithin Dabilpuram 
58305d727e8SNithin Dabilpuram 	/* Spin multiple iterations as "sq->fc_cache_pkts" can still
58405d727e8SNithin Dabilpuram 	 * have space to send pkts even though fc_mem is disabled
58505d727e8SNithin Dabilpuram 	 */
58605d727e8SNithin Dabilpuram 
58705d727e8SNithin Dabilpuram 	while (true) {
58805d727e8SNithin Dabilpuram 		prev = val;
58905d727e8SNithin Dabilpuram 		plt_delay_us(10);
59005d727e8SNithin Dabilpuram 		val = roc_atomic64_add_nosync(wdata, regaddr);
59105d727e8SNithin Dabilpuram 		/* Continue on error */
59205d727e8SNithin Dabilpuram 		if (val & BIT_ULL(63))
59305d727e8SNithin Dabilpuram 			continue;
59405d727e8SNithin Dabilpuram 
59505d727e8SNithin Dabilpuram 		if (prev != val)
59605d727e8SNithin Dabilpuram 			continue;
59705d727e8SNithin Dabilpuram 
59805d727e8SNithin Dabilpuram 		sqb_cnt = val & 0xFFFF;
59905d727e8SNithin Dabilpuram 		head_off = (val >> 20) & 0x3F;
60005d727e8SNithin Dabilpuram 		tail_off = (val >> 28) & 0x3F;
60105d727e8SNithin Dabilpuram 
60205d727e8SNithin Dabilpuram 		/* SQ reached quiescent state */
60305d727e8SNithin Dabilpuram 		if (sqb_cnt <= 1 && head_off == tail_off &&
6041134d758SPavan Nikhilesh 		    (*(volatile uint64_t *)sq->fc == sq->aura_sqb_bufs)) {
60505d727e8SNithin Dabilpuram 			break;
60605d727e8SNithin Dabilpuram 		}
60705d727e8SNithin Dabilpuram 
60805d727e8SNithin Dabilpuram 		/* Timeout */
60905d727e8SNithin Dabilpuram 		if (!timeout)
61005d727e8SNithin Dabilpuram 			goto exit;
61105d727e8SNithin Dabilpuram 		timeout--;
61205d727e8SNithin Dabilpuram 	}
61305d727e8SNithin Dabilpuram 
61405d727e8SNithin Dabilpuram 	return 0;
61505d727e8SNithin Dabilpuram exit:
61605d727e8SNithin Dabilpuram 	return -EFAULT;
61705d727e8SNithin Dabilpuram }
61805d727e8SNithin Dabilpuram 
619b7c31b6dSSatha Rao void
620b7c31b6dSSatha Rao nix_tm_sq_free_sqe_buffer(uint64_t *sqe, int head_off, int end_off, int instr_sz)
621b7c31b6dSSatha Rao {
622b7c31b6dSSatha Rao 	int i, j, inc = (8 * (0x2 >> instr_sz)), segs;
623b7c31b6dSSatha Rao 	struct nix_send_hdr_s *send_hdr;
624b7c31b6dSSatha Rao 	uint64_t *ptr, aura_handle;
625b7c31b6dSSatha Rao 	struct idev_cfg *idev;
626b7c31b6dSSatha Rao 
627b7c31b6dSSatha Rao 	if (!sqe)
628b7c31b6dSSatha Rao 		return;
629b7c31b6dSSatha Rao 
630b7c31b6dSSatha Rao 	idev = idev_get_cfg();
631b7c31b6dSSatha Rao 	if (idev == NULL)
632b7c31b6dSSatha Rao 		return;
633b7c31b6dSSatha Rao 
634b7c31b6dSSatha Rao 	ptr = sqe + (head_off * inc);
635b7c31b6dSSatha Rao 	for (i = head_off; i < end_off; i++) {
636b7c31b6dSSatha Rao 		ptr = sqe + (i * inc);
637b7c31b6dSSatha Rao 		send_hdr = (struct nix_send_hdr_s *)(ptr);
638b7c31b6dSSatha Rao 		aura_handle = roc_npa_aura_handle_gen(send_hdr->w0.aura, idev->npa->base);
639b7c31b6dSSatha Rao 		ptr += 2;
640b7c31b6dSSatha Rao 		if (((*ptr >> 60) & 0xF) == NIX_SUBDC_EXT)
641b7c31b6dSSatha Rao 			ptr += 2;
642b7c31b6dSSatha Rao 		if (((*ptr >> 60) & 0xF) == NIX_SUBDC_AGE_AND_STATS)
643b7c31b6dSSatha Rao 			ptr += 2;
644b7c31b6dSSatha Rao 		if (((*ptr >> 60) & 0xF) == NIX_SUBDC_JUMP) {
645b7c31b6dSSatha Rao 			ptr += 1;
646b7c31b6dSSatha Rao 			ptr = (uint64_t *)*ptr;
647b7c31b6dSSatha Rao 		}
648b7c31b6dSSatha Rao 		if (((*ptr >> 60) & 0xF) == NIX_SUBDC_CRC)
649b7c31b6dSSatha Rao 			ptr += 2;
650b7c31b6dSSatha Rao 		/* We are not parsing immediate send descriptor */
651b7c31b6dSSatha Rao 		if (((*ptr >> 60) & 0xF) == NIX_SUBDC_IMM)
652b7c31b6dSSatha Rao 			continue;
653b7c31b6dSSatha Rao 		while (1) {
654b7c31b6dSSatha Rao 			if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG) {
655b7c31b6dSSatha Rao 				segs = (*ptr >> 48) & 0x3;
656b7c31b6dSSatha Rao 				ptr += 1;
657b7c31b6dSSatha Rao 				for (j = 0; j < segs; j++) {
658b7c31b6dSSatha Rao 					roc_npa_aura_op_free(aura_handle, 0, *ptr);
659b7c31b6dSSatha Rao 					ptr += 1;
660b7c31b6dSSatha Rao 				}
661b7c31b6dSSatha Rao 				if (segs == 2)
662b7c31b6dSSatha Rao 					ptr += 1;
663b7c31b6dSSatha Rao 			} else if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG2) {
664b7c31b6dSSatha Rao 				uint64_t aura = (*ptr >> 16) & 0xFFFFF;
665b7c31b6dSSatha Rao 
666b7c31b6dSSatha Rao 				aura = roc_npa_aura_handle_gen(aura, idev->npa->base);
667b7c31b6dSSatha Rao 				ptr += 1;
668b7c31b6dSSatha Rao 				roc_npa_aura_op_free(aura, 0, *ptr);
669b7c31b6dSSatha Rao 				ptr += 1;
670b7c31b6dSSatha Rao 			} else
671b7c31b6dSSatha Rao 				break;
672b7c31b6dSSatha Rao 		}
673b7c31b6dSSatha Rao 	}
674b7c31b6dSSatha Rao }
675b7c31b6dSSatha Rao 
676b7c31b6dSSatha Rao int
677b7c31b6dSSatha Rao roc_nix_tm_sq_free_pending_sqe(struct nix *nix, int q)
678b7c31b6dSSatha Rao {
679b7c31b6dSSatha Rao 	int head_off, count, rc = 0, tail_off;
680b7c31b6dSSatha Rao 	struct roc_nix_sq *sq = nix->sqs[q];
681b7c31b6dSSatha Rao 	void *sqb_buf, *dat, *tail_sqb;
682b7c31b6dSSatha Rao 	struct dev *dev = &nix->dev;
683b7c31b6dSSatha Rao 	struct ndc_sync_op *ndc_req;
684b7c31b6dSSatha Rao 	uint16_t sqes_per_sqb;
685b7c31b6dSSatha Rao 	struct mbox *mbox;
686b7c31b6dSSatha Rao 
687b7c31b6dSSatha Rao 	mbox = dev->mbox;
688b7c31b6dSSatha Rao 	/* Sync NDC-NIX-TX for LF */
68944a9307cSRakesh Kudurumalla 	ndc_req = mbox_alloc_msg_ndc_sync_op(mbox_get(mbox));
69044a9307cSRakesh Kudurumalla 	if (ndc_req == NULL) {
69144a9307cSRakesh Kudurumalla 		mbox_put(mbox);
692b7c31b6dSSatha Rao 		return -EFAULT;
69344a9307cSRakesh Kudurumalla 	}
694b7c31b6dSSatha Rao 
695b7c31b6dSSatha Rao 	ndc_req->nix_lf_tx_sync = 1;
696b7c31b6dSSatha Rao 	if (mbox_process(mbox))
697b7c31b6dSSatha Rao 		rc |= NIX_ERR_NDC_SYNC;
69844a9307cSRakesh Kudurumalla 	mbox_put(mbox);
699b7c31b6dSSatha Rao 
700b7c31b6dSSatha Rao 	if (rc)
701b7c31b6dSSatha Rao 		plt_err("NDC_SYNC failed rc %d", rc);
702b7c31b6dSSatha Rao 
703b7c31b6dSSatha Rao 	rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_SQ, q, (void *)&dat);
704b7c31b6dSSatha Rao 
705b7c31b6dSSatha Rao 	if (roc_model_is_cn9k()) {
706b7c31b6dSSatha Rao 		volatile struct nix_sq_ctx_s *ctx = (struct nix_sq_ctx_s *)dat;
707b7c31b6dSSatha Rao 
708b7c31b6dSSatha Rao 		/* We will cleanup SQE buffers only when we received MNQ interrupt */
709b7c31b6dSSatha Rao 		if (!ctx->mnq_dis)
710b7c31b6dSSatha Rao 			return -EFAULT;
711b7c31b6dSSatha Rao 
712b7c31b6dSSatha Rao 		count = ctx->sqb_count;
713b7c31b6dSSatha Rao 		sqb_buf = (void *)ctx->head_sqb;
714b7c31b6dSSatha Rao 		tail_sqb = (void *)ctx->tail_sqb;
715b7c31b6dSSatha Rao 		head_off = ctx->head_offset;
716b7c31b6dSSatha Rao 		tail_off = ctx->tail_offset;
717b7c31b6dSSatha Rao 	} else {
718b7c31b6dSSatha Rao 		volatile struct nix_cn10k_sq_ctx_s *ctx = (struct nix_cn10k_sq_ctx_s *)dat;
719b7c31b6dSSatha Rao 
720b7c31b6dSSatha Rao 		/* We will cleanup SQE buffers only when we received MNQ interrupt */
721b7c31b6dSSatha Rao 		if (!ctx->mnq_dis)
722b7c31b6dSSatha Rao 			return -EFAULT;
723b7c31b6dSSatha Rao 
724b7c31b6dSSatha Rao 		count = ctx->sqb_count;
725b7c31b6dSSatha Rao 		/* Free SQB's that are used */
726b7c31b6dSSatha Rao 		sqb_buf = (void *)ctx->head_sqb;
727b7c31b6dSSatha Rao 		tail_sqb = (void *)ctx->tail_sqb;
728b7c31b6dSSatha Rao 		head_off = ctx->head_offset;
729b7c31b6dSSatha Rao 		tail_off = ctx->tail_offset;
730b7c31b6dSSatha Rao 	}
731b7c31b6dSSatha Rao 	sqes_per_sqb = 1 << sq->sqes_per_sqb_log2;
732b7c31b6dSSatha Rao 	/* Free SQB's that are used */
733b7c31b6dSSatha Rao 	while (count) {
734b7c31b6dSSatha Rao 		void *next_sqb;
735b7c31b6dSSatha Rao 
736b7c31b6dSSatha Rao 		if (sqb_buf == tail_sqb)
737b7c31b6dSSatha Rao 			nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, tail_off, sq->max_sqe_sz);
738b7c31b6dSSatha Rao 		else
739b7c31b6dSSatha Rao 			nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, (sqes_per_sqb - 1),
740b7c31b6dSSatha Rao 						  sq->max_sqe_sz);
741b7c31b6dSSatha Rao 		next_sqb = *(void **)((uint64_t *)sqb_buf +
742b7c31b6dSSatha Rao 				      (uint32_t)((sqes_per_sqb - 1) * (0x2 >> sq->max_sqe_sz) * 8));
743b7c31b6dSSatha Rao 		roc_npa_aura_op_free(sq->aura_handle, 1, (uint64_t)sqb_buf);
744b7c31b6dSSatha Rao 		sqb_buf = next_sqb;
745b7c31b6dSSatha Rao 		head_off = 0;
746b7c31b6dSSatha Rao 		count--;
747b7c31b6dSSatha Rao 	}
748b7c31b6dSSatha Rao 
749b7c31b6dSSatha Rao 	return 0;
750b7c31b6dSSatha Rao }
751b7c31b6dSSatha Rao 
75209c3b99cSSatha Rao static inline int
75309c3b99cSSatha Rao nix_tm_sdp_sq_drop_pkts(struct roc_nix *roc_nix, struct roc_nix_sq *sq)
75409c3b99cSSatha Rao {
75509c3b99cSSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
75609c3b99cSSatha Rao 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
75709c3b99cSSatha Rao 	struct nix_txschq_config *req = NULL, *rsp;
75809c3b99cSSatha Rao 	enum roc_nix_tm_tree tree = nix->tm_tree;
75909c3b99cSSatha Rao 	int rc = 0, qid = sq->qid;
76009c3b99cSSatha Rao 	struct nix_tm_node *node;
76109c3b99cSSatha Rao 	uint64_t regval;
76209c3b99cSSatha Rao 
76309c3b99cSSatha Rao 	/* Find the node for this SQ */
76409c3b99cSSatha Rao 	node = nix_tm_node_search(nix, qid, tree);
76509c3b99cSSatha Rao 	while (node) {
76609c3b99cSSatha Rao 		if (node->hw_lvl != NIX_TXSCH_LVL_TL4) {
76709c3b99cSSatha Rao 			node = node->parent;
76809c3b99cSSatha Rao 			continue;
76909c3b99cSSatha Rao 		}
77009c3b99cSSatha Rao 		break;
77109c3b99cSSatha Rao 	}
77209c3b99cSSatha Rao 	if (!node) {
77309c3b99cSSatha Rao 		plt_err("Invalid node/state for sq %u", qid);
77409c3b99cSSatha Rao 		return -EFAULT;
77509c3b99cSSatha Rao 	}
77609c3b99cSSatha Rao 
77709c3b99cSSatha Rao 	/* Get present link config */
77809c3b99cSSatha Rao 	req = mbox_alloc_msg_nix_txschq_cfg(mbox);
77909c3b99cSSatha Rao 	req->read = 1;
78009c3b99cSSatha Rao 	req->lvl = NIX_TXSCH_LVL_TL4;
78109c3b99cSSatha Rao 	req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
78209c3b99cSSatha Rao 	req->num_regs = 1;
78309c3b99cSSatha Rao 	rc = mbox_process_msg(mbox, (void **)&rsp);
78409c3b99cSSatha Rao 	if (rc || rsp->num_regs != 1)
78509c3b99cSSatha Rao 		goto err;
78609c3b99cSSatha Rao 	regval = rsp->regval[0];
78709c3b99cSSatha Rao 	/* Disable BP_ENA in SDP link config */
78809c3b99cSSatha Rao 	req = mbox_alloc_msg_nix_txschq_cfg(mbox);
78909c3b99cSSatha Rao 	req->lvl = NIX_TXSCH_LVL_TL4;
79009c3b99cSSatha Rao 	req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
79109c3b99cSSatha Rao 	req->regval[0] = 0x0ull;
79209c3b99cSSatha Rao 	req->regval_mask[0] = ~(BIT_ULL(13));
79309c3b99cSSatha Rao 	req->num_regs = 1;
79409c3b99cSSatha Rao 	rc = mbox_process(mbox);
79509c3b99cSSatha Rao 	if (rc)
79609c3b99cSSatha Rao 		goto err;
79709c3b99cSSatha Rao 	mbox_put(mbox);
79809c3b99cSSatha Rao 	/* Flush SQ to drop all packets */
79909c3b99cSSatha Rao 	rc = roc_nix_tm_sq_flush_spin(sq);
80009c3b99cSSatha Rao 	if (rc)
80109c3b99cSSatha Rao 		plt_nix_dbg("SQ flush failed with link reset config rc %d", rc);
80209c3b99cSSatha Rao 	mbox = mbox_get((&nix->dev)->mbox);
80309c3b99cSSatha Rao 	/* Restore link config */
80409c3b99cSSatha Rao 	req = mbox_alloc_msg_nix_txschq_cfg(mbox);
80509c3b99cSSatha Rao 	req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
80609c3b99cSSatha Rao 	req->lvl = NIX_TXSCH_LVL_TL4;
80709c3b99cSSatha Rao 	req->regval[0] = regval;
80809c3b99cSSatha Rao 	req->regval_mask[0] = ~(BIT_ULL(13) | BIT_ULL(12) | GENMASK_ULL(7, 0));
80909c3b99cSSatha Rao 	req->num_regs = 1;
81009c3b99cSSatha Rao 	rc = mbox_process(mbox);
81109c3b99cSSatha Rao err:
81209c3b99cSSatha Rao 	mbox_put(mbox);
81309c3b99cSSatha Rao 	return rc;
81409c3b99cSSatha Rao }
81509c3b99cSSatha Rao 
81605d727e8SNithin Dabilpuram /* Flush and disable tx queue and its parent SMQ */
81705d727e8SNithin Dabilpuram int
81805d727e8SNithin Dabilpuram nix_tm_sq_flush_pre(struct roc_nix_sq *sq)
81905d727e8SNithin Dabilpuram {
82005d727e8SNithin Dabilpuram 	struct roc_nix *roc_nix = sq->roc_nix;
82105d727e8SNithin Dabilpuram 	struct nix_tm_node *node, *sibling;
82205d727e8SNithin Dabilpuram 	struct nix_tm_node_list *list;
82305d727e8SNithin Dabilpuram 	enum roc_nix_tm_tree tree;
824e746aec1SSatha Rao 	struct msg_req *req;
82505d727e8SNithin Dabilpuram 	struct mbox *mbox;
82605d727e8SNithin Dabilpuram 	struct nix *nix;
82705d727e8SNithin Dabilpuram 	uint16_t qid;
82805d727e8SNithin Dabilpuram 	int rc;
82905d727e8SNithin Dabilpuram 
83005d727e8SNithin Dabilpuram 	nix = roc_nix_to_nix_priv(roc_nix);
83105d727e8SNithin Dabilpuram 
83205d727e8SNithin Dabilpuram 	/* Need not do anything if tree is in disabled state */
83305d727e8SNithin Dabilpuram 	if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
83405d727e8SNithin Dabilpuram 		return 0;
83505d727e8SNithin Dabilpuram 
83605d727e8SNithin Dabilpuram 	mbox = (&nix->dev)->mbox;
83705d727e8SNithin Dabilpuram 	qid = sq->qid;
83805d727e8SNithin Dabilpuram 
83905d727e8SNithin Dabilpuram 	tree = nix->tm_tree;
84005d727e8SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
84105d727e8SNithin Dabilpuram 
84205d727e8SNithin Dabilpuram 	/* Find the node for this SQ */
84305d727e8SNithin Dabilpuram 	node = nix_tm_node_search(nix, qid, tree);
844b7c31b6dSSatha Rao 	if (!node) {
84505d727e8SNithin Dabilpuram 		plt_err("Invalid node/state for sq %u", qid);
84605d727e8SNithin Dabilpuram 		return -EFAULT;
84705d727e8SNithin Dabilpuram 	}
84805d727e8SNithin Dabilpuram 
84905d727e8SNithin Dabilpuram 	/* Enable CGX RXTX to drain pkts */
85005d727e8SNithin Dabilpuram 	if (!roc_nix->io_enabled) {
85105d727e8SNithin Dabilpuram 		/* Though it enables both RX MCAM Entries and CGX Link
85205d727e8SNithin Dabilpuram 		 * we assume all the rx queues are stopped way back.
85305d727e8SNithin Dabilpuram 		 */
85444a9307cSRakesh Kudurumalla 		mbox_alloc_msg_nix_lf_start_rx(mbox_get(mbox));
85505d727e8SNithin Dabilpuram 		rc = mbox_process(mbox);
85605d727e8SNithin Dabilpuram 		if (rc) {
85744a9307cSRakesh Kudurumalla 			mbox_put(mbox);
85805d727e8SNithin Dabilpuram 			plt_err("cgx start failed, rc=%d", rc);
85905d727e8SNithin Dabilpuram 			return rc;
86005d727e8SNithin Dabilpuram 		}
86144a9307cSRakesh Kudurumalla 		mbox_put(mbox);
86205d727e8SNithin Dabilpuram 	}
86305d727e8SNithin Dabilpuram 
86458debb81SNithin Dabilpuram 	/* Disable backpressure */
86578fb5efeSNithin Dabilpuram 	rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false);
86658debb81SNithin Dabilpuram 	if (rc) {
86758debb81SNithin Dabilpuram 		plt_err("Failed to disable backpressure for flush, rc=%d", rc);
86858debb81SNithin Dabilpuram 		return rc;
86958debb81SNithin Dabilpuram 	}
87058debb81SNithin Dabilpuram 
87105d727e8SNithin Dabilpuram 	/* Disable smq xoff for case it was enabled earlier */
87205d727e8SNithin Dabilpuram 	rc = nix_tm_smq_xoff(nix, node->parent, false);
87305d727e8SNithin Dabilpuram 	if (rc) {
87405d727e8SNithin Dabilpuram 		plt_err("Failed to enable smq %u, rc=%d", node->parent->hw_id,
87505d727e8SNithin Dabilpuram 			rc);
87605d727e8SNithin Dabilpuram 		return rc;
87705d727e8SNithin Dabilpuram 	}
87805d727e8SNithin Dabilpuram 
87905d727e8SNithin Dabilpuram 	/* As per HRM, to disable an SQ, all other SQ's
88005d727e8SNithin Dabilpuram 	 * that feed to same SMQ must be paused before SMQ flush.
88105d727e8SNithin Dabilpuram 	 */
88205d727e8SNithin Dabilpuram 	TAILQ_FOREACH(sibling, list, node) {
88305d727e8SNithin Dabilpuram 		if (sibling->parent != node->parent)
88405d727e8SNithin Dabilpuram 			continue;
88505d727e8SNithin Dabilpuram 		if (!(sibling->flags & NIX_TM_NODE_ENABLED))
88605d727e8SNithin Dabilpuram 			continue;
88705d727e8SNithin Dabilpuram 
88805d727e8SNithin Dabilpuram 		qid = sibling->id;
88905d727e8SNithin Dabilpuram 		sq = nix->sqs[qid];
89005d727e8SNithin Dabilpuram 		if (!sq)
89105d727e8SNithin Dabilpuram 			continue;
89205d727e8SNithin Dabilpuram 
893f6e0d835SRakesh Kudurumalla 		if (sq->enable) {
89405d727e8SNithin Dabilpuram 			rc = roc_nix_tm_sq_aura_fc(sq, false);
89505d727e8SNithin Dabilpuram 			if (rc) {
89605d727e8SNithin Dabilpuram 				plt_err("Failed to disable sqb aura fc, rc=%d", rc);
89705d727e8SNithin Dabilpuram 				goto cleanup;
89805d727e8SNithin Dabilpuram 			}
899f6e0d835SRakesh Kudurumalla 		}
90005d727e8SNithin Dabilpuram 
90105d727e8SNithin Dabilpuram 		/* Wait for sq entries to be flushed */
90205d727e8SNithin Dabilpuram 		rc = roc_nix_tm_sq_flush_spin(sq);
90305d727e8SNithin Dabilpuram 		if (rc) {
90409c3b99cSSatha Rao 			if (nix->sdp_link)
90509c3b99cSSatha Rao 				rc = nix_tm_sdp_sq_drop_pkts(roc_nix, sq);
90609c3b99cSSatha Rao 			else
907b7c31b6dSSatha Rao 				rc = roc_nix_tm_sq_free_pending_sqe(nix, sq->qid);
908b7c31b6dSSatha Rao 			if (rc) {
90909c3b99cSSatha Rao 				roc_nix_tm_dump(sq->roc_nix, NULL);
91009c3b99cSSatha Rao 				roc_nix_queues_ctx_dump(sq->roc_nix, NULL);
911f665790aSDavid Marchand 				plt_err("Failed to drain sq %u, rc=%d", sq->qid, rc);
91205d727e8SNithin Dabilpuram 				return rc;
91305d727e8SNithin Dabilpuram 			}
914b7c31b6dSSatha Rao 			/* Freed all pending SQEs for this SQ, so disable this node */
915b7c31b6dSSatha Rao 			sibling->flags &= ~NIX_TM_NODE_ENABLED;
916b7c31b6dSSatha Rao 		}
91705d727e8SNithin Dabilpuram 	}
91805d727e8SNithin Dabilpuram 
91905d727e8SNithin Dabilpuram 	node->flags &= ~NIX_TM_NODE_ENABLED;
92005d727e8SNithin Dabilpuram 
92105d727e8SNithin Dabilpuram 	/* Disable and flush */
92205d727e8SNithin Dabilpuram 	rc = nix_tm_smq_xoff(nix, node->parent, true);
92305d727e8SNithin Dabilpuram 	if (rc) {
92405d727e8SNithin Dabilpuram 		plt_err("Failed to disable smq %u, rc=%d", node->parent->hw_id,
92505d727e8SNithin Dabilpuram 			rc);
92605d727e8SNithin Dabilpuram 		goto cleanup;
92705d727e8SNithin Dabilpuram 	}
928e746aec1SSatha Rao 
92944a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_rx_sw_sync(mbox_get(mbox));
93044a9307cSRakesh Kudurumalla 	if (!req) {
93144a9307cSRakesh Kudurumalla 		mbox_put(mbox);
932e746aec1SSatha Rao 		return -ENOSPC;
93344a9307cSRakesh Kudurumalla 	}
934e746aec1SSatha Rao 
935e746aec1SSatha Rao 	rc = mbox_process(mbox);
93644a9307cSRakesh Kudurumalla 	mbox_put(mbox);
93705d727e8SNithin Dabilpuram cleanup:
93805d727e8SNithin Dabilpuram 	/* Restore cgx state */
93905d727e8SNithin Dabilpuram 	if (!roc_nix->io_enabled) {
94044a9307cSRakesh Kudurumalla 		mbox_alloc_msg_nix_lf_stop_rx(mbox_get(mbox));
94105d727e8SNithin Dabilpuram 		rc |= mbox_process(mbox);
94244a9307cSRakesh Kudurumalla 		mbox_put(mbox);
94305d727e8SNithin Dabilpuram 	}
94405d727e8SNithin Dabilpuram 
94505d727e8SNithin Dabilpuram 	return rc;
94605d727e8SNithin Dabilpuram }
94705d727e8SNithin Dabilpuram 
94805d727e8SNithin Dabilpuram int
94905d727e8SNithin Dabilpuram nix_tm_sq_flush_post(struct roc_nix_sq *sq)
95005d727e8SNithin Dabilpuram {
95105d727e8SNithin Dabilpuram 	struct roc_nix *roc_nix = sq->roc_nix;
95205d727e8SNithin Dabilpuram 	struct nix_tm_node *node, *sibling;
95305d727e8SNithin Dabilpuram 	struct nix_tm_node_list *list;
95405d727e8SNithin Dabilpuram 	enum roc_nix_tm_tree tree;
95505d727e8SNithin Dabilpuram 	struct roc_nix_sq *s_sq;
95605d727e8SNithin Dabilpuram 	bool once = false;
95705d727e8SNithin Dabilpuram 	uint16_t qid, s_qid;
95805d727e8SNithin Dabilpuram 	struct nix *nix;
95905d727e8SNithin Dabilpuram 	int rc;
96005d727e8SNithin Dabilpuram 
96105d727e8SNithin Dabilpuram 	nix = roc_nix_to_nix_priv(roc_nix);
96205d727e8SNithin Dabilpuram 
96305d727e8SNithin Dabilpuram 	/* Need not do anything if tree is in disabled state */
96405d727e8SNithin Dabilpuram 	if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
96505d727e8SNithin Dabilpuram 		return 0;
96605d727e8SNithin Dabilpuram 
96705d727e8SNithin Dabilpuram 	qid = sq->qid;
96805d727e8SNithin Dabilpuram 	tree = nix->tm_tree;
96905d727e8SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
97005d727e8SNithin Dabilpuram 
97105d727e8SNithin Dabilpuram 	/* Find the node for this SQ */
97205d727e8SNithin Dabilpuram 	node = nix_tm_node_search(nix, qid, tree);
97305d727e8SNithin Dabilpuram 	if (!node) {
97405d727e8SNithin Dabilpuram 		plt_err("Invalid node for sq %u", qid);
97505d727e8SNithin Dabilpuram 		return -EFAULT;
97605d727e8SNithin Dabilpuram 	}
97705d727e8SNithin Dabilpuram 
97805d727e8SNithin Dabilpuram 	/* Enable all the siblings back */
97905d727e8SNithin Dabilpuram 	TAILQ_FOREACH(sibling, list, node) {
98005d727e8SNithin Dabilpuram 		if (sibling->parent != node->parent)
98105d727e8SNithin Dabilpuram 			continue;
98205d727e8SNithin Dabilpuram 
98305d727e8SNithin Dabilpuram 		if (sibling->id == qid)
98405d727e8SNithin Dabilpuram 			continue;
98505d727e8SNithin Dabilpuram 
98605d727e8SNithin Dabilpuram 		if (!(sibling->flags & NIX_TM_NODE_ENABLED))
98705d727e8SNithin Dabilpuram 			continue;
98805d727e8SNithin Dabilpuram 
98905d727e8SNithin Dabilpuram 		s_qid = sibling->id;
99005d727e8SNithin Dabilpuram 		s_sq = nix->sqs[s_qid];
99105d727e8SNithin Dabilpuram 		if (!s_sq)
99205d727e8SNithin Dabilpuram 			continue;
99305d727e8SNithin Dabilpuram 
99405d727e8SNithin Dabilpuram 		if (!once) {
99505d727e8SNithin Dabilpuram 			/* Enable back if any SQ is still present */
99605d727e8SNithin Dabilpuram 			rc = nix_tm_smq_xoff(nix, node->parent, false);
99705d727e8SNithin Dabilpuram 			if (rc) {
99805d727e8SNithin Dabilpuram 				plt_err("Failed to enable smq %u, rc=%d",
99905d727e8SNithin Dabilpuram 					node->parent->hw_id, rc);
100005d727e8SNithin Dabilpuram 				return rc;
100105d727e8SNithin Dabilpuram 			}
100205d727e8SNithin Dabilpuram 			once = true;
100305d727e8SNithin Dabilpuram 		}
100405d727e8SNithin Dabilpuram 
1005f6e0d835SRakesh Kudurumalla 		if (s_sq->enable) {
100605d727e8SNithin Dabilpuram 			rc = roc_nix_tm_sq_aura_fc(s_sq, true);
100705d727e8SNithin Dabilpuram 			if (rc) {
100805d727e8SNithin Dabilpuram 				plt_err("Failed to enable sqb aura fc, rc=%d", rc);
100905d727e8SNithin Dabilpuram 				return rc;
101005d727e8SNithin Dabilpuram 			}
101105d727e8SNithin Dabilpuram 		}
1012f6e0d835SRakesh Kudurumalla 	}
101305d727e8SNithin Dabilpuram 
101405d727e8SNithin Dabilpuram 	return 0;
101505d727e8SNithin Dabilpuram }
101605d727e8SNithin Dabilpuram 
101705d727e8SNithin Dabilpuram int
10180885429cSNithin Dabilpuram nix_tm_sq_sched_conf(struct nix *nix, struct nix_tm_node *node,
10190885429cSNithin Dabilpuram 		     bool rr_quantum_only)
10200885429cSNithin Dabilpuram {
102144a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
10220885429cSNithin Dabilpuram 	uint16_t qid = node->id, smq;
10230885429cSNithin Dabilpuram 	uint64_t rr_quantum;
10240885429cSNithin Dabilpuram 	int rc;
10250885429cSNithin Dabilpuram 
10260885429cSNithin Dabilpuram 	smq = node->parent->hw_id;
10270885429cSNithin Dabilpuram 	rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
10280885429cSNithin Dabilpuram 
10290885429cSNithin Dabilpuram 	if (rr_quantum_only)
10300885429cSNithin Dabilpuram 		plt_tm_dbg("Update sq(%u) rr_quantum 0x%" PRIx64, qid,
10310885429cSNithin Dabilpuram 			   rr_quantum);
10320885429cSNithin Dabilpuram 	else
10330885429cSNithin Dabilpuram 		plt_tm_dbg("Enabling sq(%u)->smq(%u), rr_quantum 0x%" PRIx64,
10340885429cSNithin Dabilpuram 			   qid, smq, rr_quantum);
10350885429cSNithin Dabilpuram 
103644a9307cSRakesh Kudurumalla 	if (qid > nix->nb_tx_queues) {
103744a9307cSRakesh Kudurumalla 		rc = -EFAULT;
103844a9307cSRakesh Kudurumalla 		goto exit;
103944a9307cSRakesh Kudurumalla 	}
10400885429cSNithin Dabilpuram 
10410885429cSNithin Dabilpuram 	if (roc_model_is_cn9k()) {
10420885429cSNithin Dabilpuram 		struct nix_aq_enq_req *aq;
10430885429cSNithin Dabilpuram 
10440885429cSNithin Dabilpuram 		aq = mbox_alloc_msg_nix_aq_enq(mbox);
104544a9307cSRakesh Kudurumalla 		if (!aq) {
104644a9307cSRakesh Kudurumalla 			rc = -ENOSPC;
104744a9307cSRakesh Kudurumalla 			goto exit;
104844a9307cSRakesh Kudurumalla 		}
1049da718c19SNithin Dabilpuram 
10500885429cSNithin Dabilpuram 		aq->qidx = qid;
10510885429cSNithin Dabilpuram 		aq->ctype = NIX_AQ_CTYPE_SQ;
10520885429cSNithin Dabilpuram 		aq->op = NIX_AQ_INSTOP_WRITE;
10530885429cSNithin Dabilpuram 
10540885429cSNithin Dabilpuram 		/* smq update only when needed */
10550885429cSNithin Dabilpuram 		if (!rr_quantum_only) {
10560885429cSNithin Dabilpuram 			aq->sq.smq = smq;
10570885429cSNithin Dabilpuram 			aq->sq_mask.smq = ~aq->sq_mask.smq;
10580885429cSNithin Dabilpuram 		}
10590885429cSNithin Dabilpuram 		aq->sq.smq_rr_quantum = rr_quantum;
10600885429cSNithin Dabilpuram 		aq->sq_mask.smq_rr_quantum = ~aq->sq_mask.smq_rr_quantum;
1061*4785c406SSatha Rao 	} else if (roc_model_is_cn10k()) {
10620885429cSNithin Dabilpuram 		struct nix_cn10k_aq_enq_req *aq;
10630885429cSNithin Dabilpuram 
10640885429cSNithin Dabilpuram 		aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
106544a9307cSRakesh Kudurumalla 		if (!aq) {
106644a9307cSRakesh Kudurumalla 			rc = -ENOSPC;
106744a9307cSRakesh Kudurumalla 			goto exit;
106844a9307cSRakesh Kudurumalla 		}
1069da718c19SNithin Dabilpuram 
10700885429cSNithin Dabilpuram 		aq->qidx = qid;
10710885429cSNithin Dabilpuram 		aq->ctype = NIX_AQ_CTYPE_SQ;
10720885429cSNithin Dabilpuram 		aq->op = NIX_AQ_INSTOP_WRITE;
10730885429cSNithin Dabilpuram 
10740885429cSNithin Dabilpuram 		/* smq update only when needed */
10750885429cSNithin Dabilpuram 		if (!rr_quantum_only) {
10760885429cSNithin Dabilpuram 			aq->sq.smq = smq;
10770885429cSNithin Dabilpuram 			aq->sq_mask.smq = ~aq->sq_mask.smq;
10780885429cSNithin Dabilpuram 		}
10790885429cSNithin Dabilpuram 		aq->sq.smq_rr_weight = rr_quantum;
10800885429cSNithin Dabilpuram 		aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight;
1081*4785c406SSatha Rao 	} else {
1082*4785c406SSatha Rao 		struct nix_cn20k_aq_enq_req *aq;
1083*4785c406SSatha Rao 
1084*4785c406SSatha Rao 		aq = mbox_alloc_msg_nix_cn20k_aq_enq(mbox);
1085*4785c406SSatha Rao 		if (!aq) {
1086*4785c406SSatha Rao 			rc = -ENOSPC;
1087*4785c406SSatha Rao 			goto exit;
1088*4785c406SSatha Rao 		}
1089*4785c406SSatha Rao 
1090*4785c406SSatha Rao 		aq->qidx = qid;
1091*4785c406SSatha Rao 		aq->ctype = NIX_AQ_CTYPE_SQ;
1092*4785c406SSatha Rao 		aq->op = NIX_AQ_INSTOP_WRITE;
1093*4785c406SSatha Rao 
1094*4785c406SSatha Rao 		/* smq update only when needed */
1095*4785c406SSatha Rao 		if (!rr_quantum_only) {
1096*4785c406SSatha Rao 			aq->sq.smq = smq;
1097*4785c406SSatha Rao 			aq->sq_mask.smq = ~aq->sq_mask.smq;
1098*4785c406SSatha Rao 		}
1099*4785c406SSatha Rao 		aq->sq.smq_rr_weight = rr_quantum;
1100*4785c406SSatha Rao 		aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight;
11010885429cSNithin Dabilpuram 	}
11020885429cSNithin Dabilpuram 
11030885429cSNithin Dabilpuram 	rc = mbox_process(mbox);
11040885429cSNithin Dabilpuram 	if (rc)
11050885429cSNithin Dabilpuram 		plt_err("Failed to set smq, rc=%d", rc);
110644a9307cSRakesh Kudurumalla exit:
110744a9307cSRakesh Kudurumalla 	mbox_put(mbox);
11080885429cSNithin Dabilpuram 	return rc;
11090885429cSNithin Dabilpuram }
11100885429cSNithin Dabilpuram 
11110885429cSNithin Dabilpuram int
1112df405df9SNithin Dabilpuram nix_tm_release_resources(struct nix *nix, uint8_t hw_lvl, bool contig,
1113df405df9SNithin Dabilpuram 			 bool above_thresh)
1114df405df9SNithin Dabilpuram {
1115df405df9SNithin Dabilpuram 	uint16_t avail, thresh, to_free = 0, schq;
1116df405df9SNithin Dabilpuram 	struct mbox *mbox = (&nix->dev)->mbox;
1117df405df9SNithin Dabilpuram 	struct nix_txsch_free_req *req;
1118df405df9SNithin Dabilpuram 	struct plt_bitmap *bmp;
1119df405df9SNithin Dabilpuram 	uint64_t slab = 0;
1120df405df9SNithin Dabilpuram 	uint32_t pos = 0;
1121df405df9SNithin Dabilpuram 	int rc = -ENOSPC;
1122df405df9SNithin Dabilpuram 
1123df405df9SNithin Dabilpuram 	bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
1124df405df9SNithin Dabilpuram 	thresh =
1125df405df9SNithin Dabilpuram 		contig ? nix->contig_rsvd[hw_lvl] : nix->discontig_rsvd[hw_lvl];
1126df405df9SNithin Dabilpuram 	plt_bitmap_scan_init(bmp);
1127df405df9SNithin Dabilpuram 
1128df405df9SNithin Dabilpuram 	avail = nix_tm_resource_avail(nix, hw_lvl, contig);
1129df405df9SNithin Dabilpuram 
1130df405df9SNithin Dabilpuram 	if (above_thresh) {
1131df405df9SNithin Dabilpuram 		/* Release only above threshold */
1132df405df9SNithin Dabilpuram 		if (avail > thresh)
1133df405df9SNithin Dabilpuram 			to_free = avail - thresh;
1134df405df9SNithin Dabilpuram 	} else {
1135df405df9SNithin Dabilpuram 		/* Release everything */
1136df405df9SNithin Dabilpuram 		to_free = avail;
1137df405df9SNithin Dabilpuram 	}
1138df405df9SNithin Dabilpuram 
1139df405df9SNithin Dabilpuram 	/* Now release resources to AF */
1140df405df9SNithin Dabilpuram 	while (to_free) {
1141df405df9SNithin Dabilpuram 		if (!slab && !plt_bitmap_scan(bmp, &pos, &slab))
1142df405df9SNithin Dabilpuram 			break;
1143df405df9SNithin Dabilpuram 
1144df405df9SNithin Dabilpuram 		schq = bitmap_ctzll(slab);
1145df405df9SNithin Dabilpuram 		slab &= ~(1ULL << schq);
1146df405df9SNithin Dabilpuram 		schq += pos;
1147df405df9SNithin Dabilpuram 
1148df405df9SNithin Dabilpuram 		/* Free to AF */
114944a9307cSRakesh Kudurumalla 		req = mbox_alloc_msg_nix_txsch_free(mbox_get(mbox));
115044a9307cSRakesh Kudurumalla 		if (req == NULL) {
115144a9307cSRakesh Kudurumalla 			mbox_put(mbox);
1152df405df9SNithin Dabilpuram 			return rc;
115344a9307cSRakesh Kudurumalla 		}
1154df405df9SNithin Dabilpuram 		req->flags = 0;
1155df405df9SNithin Dabilpuram 		req->schq_lvl = hw_lvl;
1156df405df9SNithin Dabilpuram 		req->schq = schq;
1157df405df9SNithin Dabilpuram 		rc = mbox_process(mbox);
1158df405df9SNithin Dabilpuram 		if (rc) {
1159df405df9SNithin Dabilpuram 			plt_err("failed to release hwres %s(%u) rc %d",
1160df405df9SNithin Dabilpuram 				nix_tm_hwlvl2str(hw_lvl), schq, rc);
116144a9307cSRakesh Kudurumalla 			mbox_put(mbox);
1162df405df9SNithin Dabilpuram 			return rc;
1163df405df9SNithin Dabilpuram 		}
116444a9307cSRakesh Kudurumalla 		mbox_put(mbox);
1165df405df9SNithin Dabilpuram 		plt_tm_dbg("Released hwres %s(%u)", nix_tm_hwlvl2str(hw_lvl),
1166df405df9SNithin Dabilpuram 			   schq);
1167df405df9SNithin Dabilpuram 		plt_bitmap_clear(bmp, schq);
1168df405df9SNithin Dabilpuram 		to_free--;
1169df405df9SNithin Dabilpuram 	}
1170df405df9SNithin Dabilpuram 
1171df405df9SNithin Dabilpuram 	if (to_free) {
1172df405df9SNithin Dabilpuram 		plt_err("resource inconsistency for %s(%u)",
1173df405df9SNithin Dabilpuram 			nix_tm_hwlvl2str(hw_lvl), contig);
1174df405df9SNithin Dabilpuram 		return -EFAULT;
1175df405df9SNithin Dabilpuram 	}
1176df405df9SNithin Dabilpuram 	return 0;
1177df405df9SNithin Dabilpuram }
1178df405df9SNithin Dabilpuram 
1179df405df9SNithin Dabilpuram int
1180be3009e7SNithin Dabilpuram nix_tm_free_node_resource(struct nix *nix, struct nix_tm_node *node)
1181be3009e7SNithin Dabilpuram {
118244a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
1183be3009e7SNithin Dabilpuram 	struct nix_txsch_free_req *req;
1184be3009e7SNithin Dabilpuram 	struct plt_bitmap *bmp;
1185be3009e7SNithin Dabilpuram 	uint16_t avail, hw_id;
1186be3009e7SNithin Dabilpuram 	uint8_t hw_lvl;
1187be3009e7SNithin Dabilpuram 	int rc = -ENOSPC;
1188be3009e7SNithin Dabilpuram 
1189be3009e7SNithin Dabilpuram 	hw_lvl = node->hw_lvl;
1190be3009e7SNithin Dabilpuram 	hw_id = node->hw_id;
1191be3009e7SNithin Dabilpuram 	bmp = nix->schq_bmp[hw_lvl];
1192be3009e7SNithin Dabilpuram 	/* Free specific HW resource */
1193be3009e7SNithin Dabilpuram 	plt_tm_dbg("Free hwres %s(%u) lvl %u id %u (%p)",
1194be3009e7SNithin Dabilpuram 		   nix_tm_hwlvl2str(node->hw_lvl), hw_id, node->lvl, node->id,
1195be3009e7SNithin Dabilpuram 		   node);
1196be3009e7SNithin Dabilpuram 
1197be3009e7SNithin Dabilpuram 	avail = nix_tm_resource_avail(nix, hw_lvl, false);
1198be3009e7SNithin Dabilpuram 	/* Always for now free to discontiguous queue when avail
1199be3009e7SNithin Dabilpuram 	 * is not sufficient.
1200be3009e7SNithin Dabilpuram 	 */
1201be3009e7SNithin Dabilpuram 	if (nix->discontig_rsvd[hw_lvl] &&
1202be3009e7SNithin Dabilpuram 	    avail < nix->discontig_rsvd[hw_lvl]) {
1203be3009e7SNithin Dabilpuram 		PLT_ASSERT(hw_id < NIX_TM_MAX_HW_TXSCHQ);
1204be3009e7SNithin Dabilpuram 		PLT_ASSERT(plt_bitmap_get(bmp, hw_id) == 0);
1205be3009e7SNithin Dabilpuram 		plt_bitmap_set(bmp, hw_id);
1206be3009e7SNithin Dabilpuram 		node->hw_id = NIX_TM_HW_ID_INVALID;
1207be3009e7SNithin Dabilpuram 		node->flags &= ~NIX_TM_NODE_HWRES;
120844a9307cSRakesh Kudurumalla 		rc = 0;
120944a9307cSRakesh Kudurumalla 		goto exit;
1210be3009e7SNithin Dabilpuram 	}
1211be3009e7SNithin Dabilpuram 
1212be3009e7SNithin Dabilpuram 	/* Free to AF */
1213be3009e7SNithin Dabilpuram 	req = mbox_alloc_msg_nix_txsch_free(mbox);
1214be3009e7SNithin Dabilpuram 	if (req == NULL)
121544a9307cSRakesh Kudurumalla 		goto exit;
1216be3009e7SNithin Dabilpuram 	req->flags = 0;
1217be3009e7SNithin Dabilpuram 	req->schq_lvl = node->hw_lvl;
1218be3009e7SNithin Dabilpuram 	req->schq = hw_id;
1219be3009e7SNithin Dabilpuram 	rc = mbox_process(mbox);
1220be3009e7SNithin Dabilpuram 	if (rc) {
1221be3009e7SNithin Dabilpuram 		plt_err("failed to release hwres %s(%u) rc %d",
1222be3009e7SNithin Dabilpuram 			nix_tm_hwlvl2str(node->hw_lvl), hw_id, rc);
122344a9307cSRakesh Kudurumalla 		goto exit;
1224be3009e7SNithin Dabilpuram 	}
1225be3009e7SNithin Dabilpuram 
1226be3009e7SNithin Dabilpuram 	/* Mark parent as dirty for reallocing it's children */
1227be3009e7SNithin Dabilpuram 	if (node->parent)
1228be3009e7SNithin Dabilpuram 		node->parent->child_realloc = true;
1229be3009e7SNithin Dabilpuram 
1230be3009e7SNithin Dabilpuram 	node->hw_id = NIX_TM_HW_ID_INVALID;
1231be3009e7SNithin Dabilpuram 	node->flags &= ~NIX_TM_NODE_HWRES;
1232be3009e7SNithin Dabilpuram 	plt_tm_dbg("Released hwres %s(%u) to af",
1233be3009e7SNithin Dabilpuram 		   nix_tm_hwlvl2str(node->hw_lvl), hw_id);
123444a9307cSRakesh Kudurumalla 	rc = 0;
123544a9307cSRakesh Kudurumalla exit:
123644a9307cSRakesh Kudurumalla 	mbox_put(mbox);
123744a9307cSRakesh Kudurumalla 	return rc;
1238be3009e7SNithin Dabilpuram }
1239be3009e7SNithin Dabilpuram 
1240be3009e7SNithin Dabilpuram int
1241be3009e7SNithin Dabilpuram nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id,
1242be3009e7SNithin Dabilpuram 		   enum roc_nix_tm_tree tree, bool free)
1243be3009e7SNithin Dabilpuram {
1244be3009e7SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1245be3009e7SNithin Dabilpuram 	struct nix_tm_shaper_profile *profile;
1246be3009e7SNithin Dabilpuram 	struct nix_tm_node *node, *child;
1247be3009e7SNithin Dabilpuram 	struct nix_tm_node_list *list;
1248be3009e7SNithin Dabilpuram 	uint32_t profile_id;
1249be3009e7SNithin Dabilpuram 	int rc;
1250be3009e7SNithin Dabilpuram 
1251be3009e7SNithin Dabilpuram 	plt_tm_dbg("Delete node id %u tree %u", node_id, tree);
1252be3009e7SNithin Dabilpuram 
1253be3009e7SNithin Dabilpuram 	node = nix_tm_node_search(nix, node_id, tree);
1254be3009e7SNithin Dabilpuram 	if (!node)
1255be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_INVALID_NODE;
1256be3009e7SNithin Dabilpuram 
1257be3009e7SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
1258be3009e7SNithin Dabilpuram 	/* Check for any existing children */
1259be3009e7SNithin Dabilpuram 	TAILQ_FOREACH(child, list, node) {
1260be3009e7SNithin Dabilpuram 		if (child->parent == node)
1261be3009e7SNithin Dabilpuram 			return NIX_ERR_TM_CHILD_EXISTS;
1262be3009e7SNithin Dabilpuram 	}
1263be3009e7SNithin Dabilpuram 
1264be3009e7SNithin Dabilpuram 	/* Remove shaper profile reference */
1265be3009e7SNithin Dabilpuram 	profile_id = node->shaper_profile_id;
1266be3009e7SNithin Dabilpuram 	profile = nix_tm_shaper_profile_search(nix, profile_id);
1267be3009e7SNithin Dabilpuram 
1268be3009e7SNithin Dabilpuram 	/* Free hw resource locally */
1269be3009e7SNithin Dabilpuram 	if (node->flags & NIX_TM_NODE_HWRES) {
1270be3009e7SNithin Dabilpuram 		rc = nix_tm_free_node_resource(nix, node);
1271be3009e7SNithin Dabilpuram 		if (rc)
1272be3009e7SNithin Dabilpuram 			return rc;
1273be3009e7SNithin Dabilpuram 	}
1274be3009e7SNithin Dabilpuram 
1275be3009e7SNithin Dabilpuram 	if (profile)
1276be3009e7SNithin Dabilpuram 		profile->ref_cnt--;
1277be3009e7SNithin Dabilpuram 
1278be3009e7SNithin Dabilpuram 	TAILQ_REMOVE(list, node, node);
1279be3009e7SNithin Dabilpuram 
1280be3009e7SNithin Dabilpuram 	plt_tm_dbg("Deleted node %s lvl %u id %u, prio 0x%x weight 0x%x "
1281be3009e7SNithin Dabilpuram 		   "parent %u profile 0x%x tree %u (%p)",
1282be3009e7SNithin Dabilpuram 		   nix_tm_hwlvl2str(node->hw_lvl), node->lvl, node->id,
1283be3009e7SNithin Dabilpuram 		   node->priority, node->weight,
1284be3009e7SNithin Dabilpuram 		   node->parent ? node->parent->id : UINT32_MAX,
1285be3009e7SNithin Dabilpuram 		   node->shaper_profile_id, tree, node);
1286be3009e7SNithin Dabilpuram 	/* Free only if requested */
1287be3009e7SNithin Dabilpuram 	if (free)
1288be3009e7SNithin Dabilpuram 		nix_tm_node_free(node);
1289be3009e7SNithin Dabilpuram 	return 0;
1290be3009e7SNithin Dabilpuram }
1291be3009e7SNithin Dabilpuram 
1292df405df9SNithin Dabilpuram static int
1293df405df9SNithin Dabilpuram nix_tm_assign_hw_id(struct nix *nix, struct nix_tm_node *parent,
1294df405df9SNithin Dabilpuram 		    uint16_t *contig_id, int *contig_cnt,
1295df405df9SNithin Dabilpuram 		    struct nix_tm_node_list *list)
1296df405df9SNithin Dabilpuram {
1297df405df9SNithin Dabilpuram 	struct nix_tm_node *child;
1298df405df9SNithin Dabilpuram 	struct plt_bitmap *bmp;
1299df405df9SNithin Dabilpuram 	uint8_t child_hw_lvl;
1300df405df9SNithin Dabilpuram 	int spare_schq = -1;
1301df405df9SNithin Dabilpuram 	uint32_t pos = 0;
1302df405df9SNithin Dabilpuram 	uint64_t slab;
1303df405df9SNithin Dabilpuram 	uint16_t schq;
1304df405df9SNithin Dabilpuram 
1305df405df9SNithin Dabilpuram 	child_hw_lvl = parent->hw_lvl - 1;
1306df405df9SNithin Dabilpuram 	bmp = nix->schq_bmp[child_hw_lvl];
1307df405df9SNithin Dabilpuram 	plt_bitmap_scan_init(bmp);
1308df405df9SNithin Dabilpuram 	slab = 0;
1309df405df9SNithin Dabilpuram 
1310df405df9SNithin Dabilpuram 	/* Save spare schq if it is case of RR + SP */
1311df405df9SNithin Dabilpuram 	if (parent->rr_prio != 0xf && *contig_cnt > 1)
1312df405df9SNithin Dabilpuram 		spare_schq = *contig_id + parent->rr_prio;
1313df405df9SNithin Dabilpuram 
1314df405df9SNithin Dabilpuram 	TAILQ_FOREACH(child, list, node) {
1315df405df9SNithin Dabilpuram 		if (!child->parent)
1316df405df9SNithin Dabilpuram 			continue;
1317df405df9SNithin Dabilpuram 		if (child->parent->id != parent->id)
1318df405df9SNithin Dabilpuram 			continue;
1319df405df9SNithin Dabilpuram 
1320df405df9SNithin Dabilpuram 		/* Resource never expected to be present */
1321df405df9SNithin Dabilpuram 		if (child->flags & NIX_TM_NODE_HWRES) {
1322df405df9SNithin Dabilpuram 			plt_err("Resource exists for child (%s)%u, id %u (%p)",
1323df405df9SNithin Dabilpuram 				nix_tm_hwlvl2str(child->hw_lvl), child->hw_id,
1324df405df9SNithin Dabilpuram 				child->id, child);
1325df405df9SNithin Dabilpuram 			return -EFAULT;
1326df405df9SNithin Dabilpuram 		}
1327df405df9SNithin Dabilpuram 
132866d485fbSNithin Dabilpuram 		if (!slab)
132966d485fbSNithin Dabilpuram 			plt_bitmap_scan(bmp, &pos, &slab);
1330df405df9SNithin Dabilpuram 
1331df405df9SNithin Dabilpuram 		if (child->priority == parent->rr_prio && spare_schq != -1) {
1332df405df9SNithin Dabilpuram 			/* Use spare schq first if present */
1333df405df9SNithin Dabilpuram 			schq = spare_schq;
1334df405df9SNithin Dabilpuram 			spare_schq = -1;
1335df405df9SNithin Dabilpuram 			*contig_cnt = *contig_cnt - 1;
1336df405df9SNithin Dabilpuram 
1337df405df9SNithin Dabilpuram 		} else if (child->priority == parent->rr_prio) {
1338df405df9SNithin Dabilpuram 			/* Assign a discontiguous queue */
1339df405df9SNithin Dabilpuram 			if (!slab) {
1340df405df9SNithin Dabilpuram 				plt_err("Schq not found for Child %u "
1341df405df9SNithin Dabilpuram 					"lvl %u (%p)",
1342df405df9SNithin Dabilpuram 					child->id, child->lvl, child);
1343df405df9SNithin Dabilpuram 				return -ENOENT;
1344df405df9SNithin Dabilpuram 			}
1345df405df9SNithin Dabilpuram 
1346df405df9SNithin Dabilpuram 			schq = bitmap_ctzll(slab);
1347df405df9SNithin Dabilpuram 			slab &= ~(1ULL << schq);
1348df405df9SNithin Dabilpuram 			schq += pos;
1349df405df9SNithin Dabilpuram 			plt_bitmap_clear(bmp, schq);
1350df405df9SNithin Dabilpuram 		} else {
1351df405df9SNithin Dabilpuram 			/* Assign a contiguous queue */
1352df405df9SNithin Dabilpuram 			schq = *contig_id + child->priority;
1353df405df9SNithin Dabilpuram 			*contig_cnt = *contig_cnt - 1;
1354df405df9SNithin Dabilpuram 		}
1355df405df9SNithin Dabilpuram 
1356df405df9SNithin Dabilpuram 		plt_tm_dbg("Resource %s(%u), for lvl %u id %u(%p)",
1357df405df9SNithin Dabilpuram 			   nix_tm_hwlvl2str(child->hw_lvl), schq, child->lvl,
1358df405df9SNithin Dabilpuram 			   child->id, child);
1359df405df9SNithin Dabilpuram 
1360df405df9SNithin Dabilpuram 		child->hw_id = schq;
1361df405df9SNithin Dabilpuram 		child->parent_hw_id = parent->hw_id;
1362df405df9SNithin Dabilpuram 		child->flags |= NIX_TM_NODE_HWRES;
1363df405df9SNithin Dabilpuram 	}
1364df405df9SNithin Dabilpuram 
1365df405df9SNithin Dabilpuram 	return 0;
1366df405df9SNithin Dabilpuram }
1367df405df9SNithin Dabilpuram 
1368df405df9SNithin Dabilpuram int
1369df405df9SNithin Dabilpuram nix_tm_assign_resources(struct nix *nix, enum roc_nix_tm_tree tree)
1370df405df9SNithin Dabilpuram {
1371df405df9SNithin Dabilpuram 	struct nix_tm_node *parent, *root = NULL;
1372df405df9SNithin Dabilpuram 	struct plt_bitmap *bmp, *bmp_contig;
1373df405df9SNithin Dabilpuram 	struct nix_tm_node_list *list;
1374df405df9SNithin Dabilpuram 	uint8_t child_hw_lvl, hw_lvl;
1375df405df9SNithin Dabilpuram 	uint16_t contig_id, j;
1376df405df9SNithin Dabilpuram 	uint64_t slab = 0;
1377df405df9SNithin Dabilpuram 	uint32_t pos = 0;
1378df405df9SNithin Dabilpuram 	int cnt, rc;
1379df405df9SNithin Dabilpuram 
1380df405df9SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
1381df405df9SNithin Dabilpuram 	/* Walk from TL1 to TL4 parents */
1382df405df9SNithin Dabilpuram 	for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
1383df405df9SNithin Dabilpuram 		TAILQ_FOREACH(parent, list, node) {
1384df405df9SNithin Dabilpuram 			child_hw_lvl = parent->hw_lvl - 1;
1385df405df9SNithin Dabilpuram 			if (parent->hw_lvl != hw_lvl)
1386df405df9SNithin Dabilpuram 				continue;
1387df405df9SNithin Dabilpuram 
1388df405df9SNithin Dabilpuram 			/* Remember root for future */
1389df405df9SNithin Dabilpuram 			if (parent->hw_lvl == nix->tm_root_lvl)
1390df405df9SNithin Dabilpuram 				root = parent;
1391df405df9SNithin Dabilpuram 
1392df405df9SNithin Dabilpuram 			if (!parent->child_realloc) {
1393df405df9SNithin Dabilpuram 				/* Skip when parent is not dirty */
1394df405df9SNithin Dabilpuram 				if (nix_tm_child_res_valid(list, parent))
1395df405df9SNithin Dabilpuram 					continue;
1396df405df9SNithin Dabilpuram 				plt_err("Parent not dirty but invalid "
1397df405df9SNithin Dabilpuram 					"child res parent id %u(lvl %u)",
1398df405df9SNithin Dabilpuram 					parent->id, parent->lvl);
1399df405df9SNithin Dabilpuram 				return -EFAULT;
1400df405df9SNithin Dabilpuram 			}
1401df405df9SNithin Dabilpuram 
1402df405df9SNithin Dabilpuram 			bmp_contig = nix->schq_contig_bmp[child_hw_lvl];
1403df405df9SNithin Dabilpuram 
1404df405df9SNithin Dabilpuram 			/* Prealloc contiguous indices for a parent */
1405df405df9SNithin Dabilpuram 			contig_id = NIX_TM_MAX_HW_TXSCHQ;
1406df405df9SNithin Dabilpuram 			cnt = (int)parent->max_prio + 1;
1407df405df9SNithin Dabilpuram 			if (cnt > 0) {
1408df405df9SNithin Dabilpuram 				plt_bitmap_scan_init(bmp_contig);
1409df405df9SNithin Dabilpuram 				if (!plt_bitmap_scan(bmp_contig, &pos, &slab)) {
1410df405df9SNithin Dabilpuram 					plt_err("Contig schq not found");
1411df405df9SNithin Dabilpuram 					return -ENOENT;
1412df405df9SNithin Dabilpuram 				}
1413df405df9SNithin Dabilpuram 				contig_id = pos + bitmap_ctzll(slab);
1414df405df9SNithin Dabilpuram 
1415df405df9SNithin Dabilpuram 				/* Check if we have enough */
1416df405df9SNithin Dabilpuram 				for (j = contig_id; j < contig_id + cnt; j++) {
1417df405df9SNithin Dabilpuram 					if (!plt_bitmap_get(bmp_contig, j))
1418df405df9SNithin Dabilpuram 						break;
1419df405df9SNithin Dabilpuram 				}
1420df405df9SNithin Dabilpuram 
1421df405df9SNithin Dabilpuram 				if (j != contig_id + cnt) {
1422df405df9SNithin Dabilpuram 					plt_err("Contig schq not sufficient");
1423df405df9SNithin Dabilpuram 					return -ENOENT;
1424df405df9SNithin Dabilpuram 				}
1425df405df9SNithin Dabilpuram 
1426df405df9SNithin Dabilpuram 				for (j = contig_id; j < contig_id + cnt; j++)
1427df405df9SNithin Dabilpuram 					plt_bitmap_clear(bmp_contig, j);
1428df405df9SNithin Dabilpuram 			}
1429df405df9SNithin Dabilpuram 
1430df405df9SNithin Dabilpuram 			/* Assign hw id to all children */
1431df405df9SNithin Dabilpuram 			rc = nix_tm_assign_hw_id(nix, parent, &contig_id, &cnt,
1432df405df9SNithin Dabilpuram 						 list);
1433df405df9SNithin Dabilpuram 			if (cnt || rc) {
1434df405df9SNithin Dabilpuram 				plt_err("Unexpected err, contig res alloc, "
1435df405df9SNithin Dabilpuram 					"parent %u, of %s, rc=%d, cnt=%d",
1436df405df9SNithin Dabilpuram 					parent->id, nix_tm_hwlvl2str(hw_lvl),
1437df405df9SNithin Dabilpuram 					rc, cnt);
1438df405df9SNithin Dabilpuram 				return -EFAULT;
1439df405df9SNithin Dabilpuram 			}
1440df405df9SNithin Dabilpuram 
1441df405df9SNithin Dabilpuram 			/* Clear the dirty bit as children's
1442df405df9SNithin Dabilpuram 			 * resources are reallocated.
1443df405df9SNithin Dabilpuram 			 */
1444df405df9SNithin Dabilpuram 			parent->child_realloc = false;
1445df405df9SNithin Dabilpuram 		}
1446df405df9SNithin Dabilpuram 	}
1447df405df9SNithin Dabilpuram 
1448df405df9SNithin Dabilpuram 	/* Root is always expected to be there */
1449df405df9SNithin Dabilpuram 	if (!root)
1450df405df9SNithin Dabilpuram 		return -EFAULT;
1451df405df9SNithin Dabilpuram 
1452df405df9SNithin Dabilpuram 	if (root->flags & NIX_TM_NODE_HWRES)
1453df405df9SNithin Dabilpuram 		return 0;
1454df405df9SNithin Dabilpuram 
1455df405df9SNithin Dabilpuram 	/* Process root node */
1456df405df9SNithin Dabilpuram 	bmp = nix->schq_bmp[nix->tm_root_lvl];
1457df405df9SNithin Dabilpuram 	plt_bitmap_scan_init(bmp);
1458df405df9SNithin Dabilpuram 	if (!plt_bitmap_scan(bmp, &pos, &slab)) {
1459df405df9SNithin Dabilpuram 		plt_err("Resource not allocated for root");
1460df405df9SNithin Dabilpuram 		return -EIO;
1461df405df9SNithin Dabilpuram 	}
1462df405df9SNithin Dabilpuram 
1463df405df9SNithin Dabilpuram 	root->hw_id = pos + bitmap_ctzll(slab);
1464df405df9SNithin Dabilpuram 	root->flags |= NIX_TM_NODE_HWRES;
1465df405df9SNithin Dabilpuram 	plt_bitmap_clear(bmp, root->hw_id);
1466df405df9SNithin Dabilpuram 
1467df405df9SNithin Dabilpuram 	/* Get TL1 id as well when root is not TL1 */
1468df405df9SNithin Dabilpuram 	if (!nix_tm_have_tl1_access(nix)) {
1469df405df9SNithin Dabilpuram 		bmp = nix->schq_bmp[NIX_TXSCH_LVL_TL1];
1470df405df9SNithin Dabilpuram 
1471df405df9SNithin Dabilpuram 		plt_bitmap_scan_init(bmp);
1472df405df9SNithin Dabilpuram 		if (!plt_bitmap_scan(bmp, &pos, &slab)) {
1473df405df9SNithin Dabilpuram 			plt_err("Resource not found for TL1");
1474df405df9SNithin Dabilpuram 			return -EIO;
1475df405df9SNithin Dabilpuram 		}
1476df405df9SNithin Dabilpuram 		root->parent_hw_id = pos + bitmap_ctzll(slab);
1477df405df9SNithin Dabilpuram 		plt_bitmap_clear(bmp, root->parent_hw_id);
1478df405df9SNithin Dabilpuram 	}
1479df405df9SNithin Dabilpuram 
1480df405df9SNithin Dabilpuram 	plt_tm_dbg("Resource %s(%u) for root(id %u) (%p)",
1481df405df9SNithin Dabilpuram 		   nix_tm_hwlvl2str(root->hw_lvl), root->hw_id, root->id, root);
1482df405df9SNithin Dabilpuram 
1483df405df9SNithin Dabilpuram 	return 0;
1484df405df9SNithin Dabilpuram }
1485df405df9SNithin Dabilpuram 
1486df405df9SNithin Dabilpuram void
1487df405df9SNithin Dabilpuram nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp)
1488df405df9SNithin Dabilpuram {
1489df405df9SNithin Dabilpuram 	uint8_t lvl;
1490df405df9SNithin Dabilpuram 	uint16_t i;
1491df405df9SNithin Dabilpuram 
1492df405df9SNithin Dabilpuram 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
1493df405df9SNithin Dabilpuram 		for (i = 0; i < rsp->schq[lvl]; i++)
1494df405df9SNithin Dabilpuram 			plt_bitmap_set(nix->schq_bmp[lvl],
1495df405df9SNithin Dabilpuram 				       rsp->schq_list[lvl][i]);
1496df405df9SNithin Dabilpuram 
1497df405df9SNithin Dabilpuram 		for (i = 0; i < rsp->schq_contig[lvl]; i++)
1498df405df9SNithin Dabilpuram 			plt_bitmap_set(nix->schq_contig_bmp[lvl],
1499df405df9SNithin Dabilpuram 				       rsp->schq_contig_list[lvl][i]);
1500df405df9SNithin Dabilpuram 	}
1501df405df9SNithin Dabilpuram }
1502df405df9SNithin Dabilpuram 
1503df405df9SNithin Dabilpuram int
1504df405df9SNithin Dabilpuram nix_tm_alloc_txschq(struct nix *nix, enum roc_nix_tm_tree tree)
1505df405df9SNithin Dabilpuram {
1506df405df9SNithin Dabilpuram 	uint16_t schq_contig[NIX_TXSCH_LVL_CNT];
1507df405df9SNithin Dabilpuram 	struct mbox *mbox = (&nix->dev)->mbox;
1508df405df9SNithin Dabilpuram 	uint16_t schq[NIX_TXSCH_LVL_CNT];
1509df405df9SNithin Dabilpuram 	struct nix_txsch_alloc_req *req;
1510df405df9SNithin Dabilpuram 	struct nix_txsch_alloc_rsp *rsp;
1511df405df9SNithin Dabilpuram 	uint8_t hw_lvl, i;
1512df405df9SNithin Dabilpuram 	bool pend;
1513df405df9SNithin Dabilpuram 	int rc;
1514df405df9SNithin Dabilpuram 
1515df405df9SNithin Dabilpuram 	memset(schq, 0, sizeof(schq));
1516df405df9SNithin Dabilpuram 	memset(schq_contig, 0, sizeof(schq_contig));
1517df405df9SNithin Dabilpuram 
1518df405df9SNithin Dabilpuram 	/* Estimate requirement */
1519df405df9SNithin Dabilpuram 	rc = nix_tm_resource_estimate(nix, schq_contig, schq, tree);
1520df405df9SNithin Dabilpuram 	if (!rc)
1521df405df9SNithin Dabilpuram 		return 0;
1522df405df9SNithin Dabilpuram 
1523df405df9SNithin Dabilpuram 	/* Release existing contiguous resources when realloc requested
1524df405df9SNithin Dabilpuram 	 * as there is no way to guarantee continuity of old with new.
1525df405df9SNithin Dabilpuram 	 */
1526df405df9SNithin Dabilpuram 	for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1527df405df9SNithin Dabilpuram 		if (schq_contig[hw_lvl])
1528df405df9SNithin Dabilpuram 			nix_tm_release_resources(nix, hw_lvl, true, false);
1529df405df9SNithin Dabilpuram 	}
1530df405df9SNithin Dabilpuram 
1531df405df9SNithin Dabilpuram 	/* Alloc as needed */
1532df405df9SNithin Dabilpuram 	do {
1533df405df9SNithin Dabilpuram 		pend = false;
153444a9307cSRakesh Kudurumalla 		req = mbox_alloc_msg_nix_txsch_alloc(mbox_get(mbox));
1535df405df9SNithin Dabilpuram 		if (!req) {
153644a9307cSRakesh Kudurumalla 			mbox_put(mbox);
1537df405df9SNithin Dabilpuram 			rc = -ENOMEM;
1538df405df9SNithin Dabilpuram 			goto alloc_err;
1539df405df9SNithin Dabilpuram 		}
1540df405df9SNithin Dabilpuram 		mbox_memcpy(req->schq, schq, sizeof(req->schq));
1541df405df9SNithin Dabilpuram 		mbox_memcpy(req->schq_contig, schq_contig,
1542df405df9SNithin Dabilpuram 			    sizeof(req->schq_contig));
1543df405df9SNithin Dabilpuram 
1544df405df9SNithin Dabilpuram 		/* Each alloc can be at max of MAX_TXSCHQ_PER_FUNC per level.
1545df405df9SNithin Dabilpuram 		 * So split alloc to multiple requests.
1546df405df9SNithin Dabilpuram 		 */
1547df405df9SNithin Dabilpuram 		for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) {
1548df405df9SNithin Dabilpuram 			if (req->schq[i] > MAX_TXSCHQ_PER_FUNC)
1549df405df9SNithin Dabilpuram 				req->schq[i] = MAX_TXSCHQ_PER_FUNC;
1550df405df9SNithin Dabilpuram 			schq[i] -= req->schq[i];
1551df405df9SNithin Dabilpuram 
1552df405df9SNithin Dabilpuram 			if (req->schq_contig[i] > MAX_TXSCHQ_PER_FUNC)
1553df405df9SNithin Dabilpuram 				req->schq_contig[i] = MAX_TXSCHQ_PER_FUNC;
1554df405df9SNithin Dabilpuram 			schq_contig[i] -= req->schq_contig[i];
1555df405df9SNithin Dabilpuram 
1556df405df9SNithin Dabilpuram 			if (schq[i] || schq_contig[i])
1557df405df9SNithin Dabilpuram 				pend = true;
1558df405df9SNithin Dabilpuram 		}
1559df405df9SNithin Dabilpuram 
1560df405df9SNithin Dabilpuram 		rc = mbox_process_msg(mbox, (void *)&rsp);
156144a9307cSRakesh Kudurumalla 		if (rc) {
156244a9307cSRakesh Kudurumalla 			mbox_put(mbox);
1563df405df9SNithin Dabilpuram 			goto alloc_err;
156444a9307cSRakesh Kudurumalla 		}
1565df405df9SNithin Dabilpuram 
1566df405df9SNithin Dabilpuram 		nix_tm_copy_rsp_to_nix(nix, rsp);
156744a9307cSRakesh Kudurumalla 		mbox_put(mbox);
1568df405df9SNithin Dabilpuram 	} while (pend);
1569df405df9SNithin Dabilpuram 
1570df405df9SNithin Dabilpuram 	nix->tm_link_cfg_lvl = rsp->link_cfg_lvl;
1571f0b9158cSNithin Dabilpuram 	nix->tm_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio;
1572df405df9SNithin Dabilpuram 	return 0;
1573df405df9SNithin Dabilpuram alloc_err:
1574df405df9SNithin Dabilpuram 	for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) {
1575df405df9SNithin Dabilpuram 		if (nix_tm_release_resources(nix, i, true, false))
1576df405df9SNithin Dabilpuram 			plt_err("Failed to release contig resources of "
1577df405df9SNithin Dabilpuram 				"lvl %d on error",
1578df405df9SNithin Dabilpuram 				i);
1579df405df9SNithin Dabilpuram 		if (nix_tm_release_resources(nix, i, false, false))
1580df405df9SNithin Dabilpuram 			plt_err("Failed to release discontig resources of "
1581df405df9SNithin Dabilpuram 				"lvl %d on error",
1582df405df9SNithin Dabilpuram 				i);
1583df405df9SNithin Dabilpuram 	}
1584df405df9SNithin Dabilpuram 	return rc;
1585df405df9SNithin Dabilpuram }
1586df405df9SNithin Dabilpuram 
1587df405df9SNithin Dabilpuram int
15885a960e26SNithin Dabilpuram nix_tm_prepare_default_tree(struct roc_nix *roc_nix)
15895a960e26SNithin Dabilpuram {
15905a960e26SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
15915a960e26SNithin Dabilpuram 	uint32_t nonleaf_id = nix->nb_tx_queues;
15925a960e26SNithin Dabilpuram 	struct nix_tm_node *node = NULL;
15935a960e26SNithin Dabilpuram 	uint8_t leaf_lvl, lvl, lvl_end;
15945a960e26SNithin Dabilpuram 	uint32_t parent, i;
15955a960e26SNithin Dabilpuram 	int rc = 0;
15965a960e26SNithin Dabilpuram 
15975a960e26SNithin Dabilpuram 	/* Add ROOT, SCH1, SCH2, SCH3, [SCH4]  nodes */
15985a960e26SNithin Dabilpuram 	parent = ROC_NIX_TM_NODE_ID_INVALID;
15995a960e26SNithin Dabilpuram 	/* With TL1 access we have an extra level */
16005a960e26SNithin Dabilpuram 	lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 :
16015a960e26SNithin Dabilpuram 						       ROC_TM_LVL_SCH3);
16025a960e26SNithin Dabilpuram 
16035a960e26SNithin Dabilpuram 	for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) {
16045a960e26SNithin Dabilpuram 		rc = -ENOMEM;
16055a960e26SNithin Dabilpuram 		node = nix_tm_node_alloc();
16065a960e26SNithin Dabilpuram 		if (!node)
16075a960e26SNithin Dabilpuram 			goto error;
16085a960e26SNithin Dabilpuram 
16095a960e26SNithin Dabilpuram 		node->id = nonleaf_id;
16105a960e26SNithin Dabilpuram 		node->parent_id = parent;
16115a960e26SNithin Dabilpuram 		node->priority = 0;
1612eac95048SSatha Rao 		/* Default VF root RR_QUANTUM is in sync with kernel */
1613eac95048SSatha Rao 		if (lvl == ROC_TM_LVL_ROOT && !nix_tm_have_tl1_access(nix))
1614eac95048SSatha Rao 			node->weight = roc_nix->root_sched_weight;
1615eac95048SSatha Rao 		else
16165a960e26SNithin Dabilpuram 			node->weight = NIX_TM_DFLT_RR_WT;
16175a960e26SNithin Dabilpuram 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
16185a960e26SNithin Dabilpuram 		node->lvl = lvl;
16195a960e26SNithin Dabilpuram 		node->tree = ROC_NIX_TM_DEFAULT;
162020d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
16215a960e26SNithin Dabilpuram 
16225a960e26SNithin Dabilpuram 		rc = nix_tm_node_add(roc_nix, node);
16235a960e26SNithin Dabilpuram 		if (rc)
16245a960e26SNithin Dabilpuram 			goto error;
16255a960e26SNithin Dabilpuram 		parent = nonleaf_id;
16265a960e26SNithin Dabilpuram 		nonleaf_id++;
16275a960e26SNithin Dabilpuram 	}
16285a960e26SNithin Dabilpuram 
16295a960e26SNithin Dabilpuram 	parent = nonleaf_id - 1;
16305a960e26SNithin Dabilpuram 	leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
16315a960e26SNithin Dabilpuram 							ROC_TM_LVL_SCH4);
16325a960e26SNithin Dabilpuram 
16335a960e26SNithin Dabilpuram 	/* Add leaf nodes */
16345a960e26SNithin Dabilpuram 	for (i = 0; i < nix->nb_tx_queues; i++) {
16355a960e26SNithin Dabilpuram 		rc = -ENOMEM;
16365a960e26SNithin Dabilpuram 		node = nix_tm_node_alloc();
16375a960e26SNithin Dabilpuram 		if (!node)
16385a960e26SNithin Dabilpuram 			goto error;
16395a960e26SNithin Dabilpuram 
16405a960e26SNithin Dabilpuram 		node->id = i;
16415a960e26SNithin Dabilpuram 		node->parent_id = parent;
16425a960e26SNithin Dabilpuram 		node->priority = 0;
16435a960e26SNithin Dabilpuram 		node->weight = NIX_TM_DFLT_RR_WT;
16445a960e26SNithin Dabilpuram 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
16455a960e26SNithin Dabilpuram 		node->lvl = leaf_lvl;
16465a960e26SNithin Dabilpuram 		node->tree = ROC_NIX_TM_DEFAULT;
164720d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
16485a960e26SNithin Dabilpuram 
16495a960e26SNithin Dabilpuram 		rc = nix_tm_node_add(roc_nix, node);
16505a960e26SNithin Dabilpuram 		if (rc)
16515a960e26SNithin Dabilpuram 			goto error;
16525a960e26SNithin Dabilpuram 	}
16535a960e26SNithin Dabilpuram 
16545a960e26SNithin Dabilpuram 	return 0;
16555a960e26SNithin Dabilpuram error:
16565a960e26SNithin Dabilpuram 	nix_tm_node_free(node);
16575a960e26SNithin Dabilpuram 	return rc;
16585a960e26SNithin Dabilpuram }
16595a960e26SNithin Dabilpuram 
16605a960e26SNithin Dabilpuram int
1661f9dbd4a5SSatha Rao roc_nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix)
16625a960e26SNithin Dabilpuram {
16635a960e26SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
16645a960e26SNithin Dabilpuram 	uint32_t nonleaf_id = nix->nb_tx_queues;
16655a960e26SNithin Dabilpuram 	struct nix_tm_node *node = NULL;
16665a960e26SNithin Dabilpuram 	uint8_t leaf_lvl, lvl, lvl_end;
16675a960e26SNithin Dabilpuram 	uint32_t parent, i;
16685a960e26SNithin Dabilpuram 	int rc = 0;
16695a960e26SNithin Dabilpuram 
16705a960e26SNithin Dabilpuram 	/* Add ROOT, SCH1, SCH2 nodes */
16715a960e26SNithin Dabilpuram 	parent = ROC_NIX_TM_NODE_ID_INVALID;
16725a960e26SNithin Dabilpuram 	lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 :
16735a960e26SNithin Dabilpuram 						       ROC_TM_LVL_SCH2);
16745a960e26SNithin Dabilpuram 
16755a960e26SNithin Dabilpuram 	for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) {
16765a960e26SNithin Dabilpuram 		rc = -ENOMEM;
16775a960e26SNithin Dabilpuram 		node = nix_tm_node_alloc();
16785a960e26SNithin Dabilpuram 		if (!node)
16795a960e26SNithin Dabilpuram 			goto error;
16805a960e26SNithin Dabilpuram 
16815a960e26SNithin Dabilpuram 		node->id = nonleaf_id;
16825a960e26SNithin Dabilpuram 		node->parent_id = parent;
16835a960e26SNithin Dabilpuram 		node->priority = 0;
16845a960e26SNithin Dabilpuram 		node->weight = NIX_TM_DFLT_RR_WT;
16855a960e26SNithin Dabilpuram 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
16865a960e26SNithin Dabilpuram 		node->lvl = lvl;
16875a960e26SNithin Dabilpuram 		node->tree = ROC_NIX_TM_RLIMIT;
168820d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
16895a960e26SNithin Dabilpuram 
16905a960e26SNithin Dabilpuram 		rc = nix_tm_node_add(roc_nix, node);
16915a960e26SNithin Dabilpuram 		if (rc)
16925a960e26SNithin Dabilpuram 			goto error;
16935a960e26SNithin Dabilpuram 		parent = nonleaf_id;
16945a960e26SNithin Dabilpuram 		nonleaf_id++;
16955a960e26SNithin Dabilpuram 	}
16965a960e26SNithin Dabilpuram 
16975a960e26SNithin Dabilpuram 	/* SMQ is mapped to SCH4 when we have TL1 access and SCH3 otherwise */
16985a960e26SNithin Dabilpuram 	lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : ROC_TM_LVL_SCH3);
16995a960e26SNithin Dabilpuram 
17005a960e26SNithin Dabilpuram 	/* Add per queue SMQ nodes i.e SCH4 / SCH3 */
17015a960e26SNithin Dabilpuram 	for (i = 0; i < nix->nb_tx_queues; i++) {
17025a960e26SNithin Dabilpuram 		rc = -ENOMEM;
17035a960e26SNithin Dabilpuram 		node = nix_tm_node_alloc();
17045a960e26SNithin Dabilpuram 		if (!node)
17055a960e26SNithin Dabilpuram 			goto error;
17065a960e26SNithin Dabilpuram 
17075a960e26SNithin Dabilpuram 		node->id = nonleaf_id + i;
17085a960e26SNithin Dabilpuram 		node->parent_id = parent;
17095a960e26SNithin Dabilpuram 		node->priority = 0;
17105a960e26SNithin Dabilpuram 		node->weight = NIX_TM_DFLT_RR_WT;
17115a960e26SNithin Dabilpuram 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
17125a960e26SNithin Dabilpuram 		node->lvl = lvl;
17135a960e26SNithin Dabilpuram 		node->tree = ROC_NIX_TM_RLIMIT;
171420d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
17155a960e26SNithin Dabilpuram 
17165a960e26SNithin Dabilpuram 		rc = nix_tm_node_add(roc_nix, node);
17175a960e26SNithin Dabilpuram 		if (rc)
17185a960e26SNithin Dabilpuram 			goto error;
17195a960e26SNithin Dabilpuram 	}
17205a960e26SNithin Dabilpuram 
17215a960e26SNithin Dabilpuram 	parent = nonleaf_id;
17225a960e26SNithin Dabilpuram 	leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
17235a960e26SNithin Dabilpuram 							ROC_TM_LVL_SCH4);
17245a960e26SNithin Dabilpuram 
17255a960e26SNithin Dabilpuram 	/* Add leaf nodes */
17265a960e26SNithin Dabilpuram 	for (i = 0; i < nix->nb_tx_queues; i++) {
17275a960e26SNithin Dabilpuram 		rc = -ENOMEM;
17285a960e26SNithin Dabilpuram 		node = nix_tm_node_alloc();
17295a960e26SNithin Dabilpuram 		if (!node)
17305a960e26SNithin Dabilpuram 			goto error;
17315a960e26SNithin Dabilpuram 
17325a960e26SNithin Dabilpuram 		node->id = i;
1733f9dbd4a5SSatha Rao 		node->parent_id = parent + i;
17345a960e26SNithin Dabilpuram 		node->priority = 0;
17355a960e26SNithin Dabilpuram 		node->weight = NIX_TM_DFLT_RR_WT;
17365a960e26SNithin Dabilpuram 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
17375a960e26SNithin Dabilpuram 		node->lvl = leaf_lvl;
17385a960e26SNithin Dabilpuram 		node->tree = ROC_NIX_TM_RLIMIT;
173920d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
174020d02329SSunil Kumar Kori 
174120d02329SSunil Kumar Kori 		rc = nix_tm_node_add(roc_nix, node);
174220d02329SSunil Kumar Kori 		if (rc)
174320d02329SSunil Kumar Kori 			goto error;
174420d02329SSunil Kumar Kori 	}
174520d02329SSunil Kumar Kori 
174620d02329SSunil Kumar Kori 	return 0;
174720d02329SSunil Kumar Kori error:
174820d02329SSunil Kumar Kori 	nix_tm_node_free(node);
174920d02329SSunil Kumar Kori 	return rc;
175020d02329SSunil Kumar Kori }
175120d02329SSunil Kumar Kori 
175220d02329SSunil Kumar Kori int
175320d02329SSunil Kumar Kori roc_nix_tm_pfc_prepare_tree(struct roc_nix *roc_nix)
175420d02329SSunil Kumar Kori {
175520d02329SSunil Kumar Kori 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1756174f2f35SSunil Kumar Kori 	uint8_t leaf_lvl, lvl, lvl_start, lvl_end;
175720d02329SSunil Kumar Kori 	uint32_t nonleaf_id = nix->nb_tx_queues;
175820d02329SSunil Kumar Kori 	struct nix_tm_node *node = NULL;
175920d02329SSunil Kumar Kori 	uint32_t tl2_node_id;
176020d02329SSunil Kumar Kori 	uint32_t parent, i;
176120d02329SSunil Kumar Kori 	int rc = -ENOMEM;
176220d02329SSunil Kumar Kori 
176320d02329SSunil Kumar Kori 	parent = ROC_NIX_TM_NODE_ID_INVALID;
1764174f2f35SSunil Kumar Kori 	lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 :
1765174f2f35SSunil Kumar Kori 		   ROC_TM_LVL_SCH2);
1766174f2f35SSunil Kumar Kori 	leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
1767174f2f35SSunil Kumar Kori 		    ROC_TM_LVL_SCH4);
176820d02329SSunil Kumar Kori 
176920d02329SSunil Kumar Kori 	/* TL1 node */
177020d02329SSunil Kumar Kori 	node = nix_tm_node_alloc();
177120d02329SSunil Kumar Kori 	if (!node)
177220d02329SSunil Kumar Kori 		goto error;
177320d02329SSunil Kumar Kori 
177420d02329SSunil Kumar Kori 	node->id = nonleaf_id;
177520d02329SSunil Kumar Kori 	node->parent_id = parent;
177620d02329SSunil Kumar Kori 	node->priority = 0;
177720d02329SSunil Kumar Kori 	node->weight = NIX_TM_DFLT_RR_WT;
177820d02329SSunil Kumar Kori 	node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
177920d02329SSunil Kumar Kori 	node->lvl = ROC_TM_LVL_ROOT;
178020d02329SSunil Kumar Kori 	node->tree = ROC_NIX_TM_PFC;
178120d02329SSunil Kumar Kori 	node->rel_chan = NIX_TM_CHAN_INVALID;
178220d02329SSunil Kumar Kori 
178320d02329SSunil Kumar Kori 	rc = nix_tm_node_add(roc_nix, node);
178420d02329SSunil Kumar Kori 	if (rc)
178520d02329SSunil Kumar Kori 		goto error;
178620d02329SSunil Kumar Kori 
178720d02329SSunil Kumar Kori 	parent = nonleaf_id;
178820d02329SSunil Kumar Kori 	nonleaf_id++;
178920d02329SSunil Kumar Kori 
1790174f2f35SSunil Kumar Kori 	lvl_start = ROC_TM_LVL_SCH1;
1791174f2f35SSunil Kumar Kori 	if (roc_nix_is_pf(roc_nix)) {
179220d02329SSunil Kumar Kori 		/* TL2 node */
179320d02329SSunil Kumar Kori 		rc = -ENOMEM;
179420d02329SSunil Kumar Kori 		node = nix_tm_node_alloc();
179520d02329SSunil Kumar Kori 		if (!node)
179620d02329SSunil Kumar Kori 			goto error;
179720d02329SSunil Kumar Kori 
179820d02329SSunil Kumar Kori 		node->id = nonleaf_id;
179920d02329SSunil Kumar Kori 		node->parent_id = parent;
180020d02329SSunil Kumar Kori 		node->priority = 0;
180120d02329SSunil Kumar Kori 		node->weight = NIX_TM_DFLT_RR_WT;
180220d02329SSunil Kumar Kori 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
180320d02329SSunil Kumar Kori 		node->lvl = ROC_TM_LVL_SCH1;
180420d02329SSunil Kumar Kori 		node->tree = ROC_NIX_TM_PFC;
180520d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
180620d02329SSunil Kumar Kori 
180720d02329SSunil Kumar Kori 		rc = nix_tm_node_add(roc_nix, node);
180820d02329SSunil Kumar Kori 		if (rc)
180920d02329SSunil Kumar Kori 			goto error;
181020d02329SSunil Kumar Kori 
1811174f2f35SSunil Kumar Kori 		lvl_start = ROC_TM_LVL_SCH2;
181220d02329SSunil Kumar Kori 		tl2_node_id = nonleaf_id;
181320d02329SSunil Kumar Kori 		nonleaf_id++;
1814174f2f35SSunil Kumar Kori 	} else {
1815174f2f35SSunil Kumar Kori 		tl2_node_id = parent;
1816174f2f35SSunil Kumar Kori 	}
181720d02329SSunil Kumar Kori 
181820d02329SSunil Kumar Kori 	for (i = 0; i < nix->nb_tx_queues; i++) {
181920d02329SSunil Kumar Kori 		parent = tl2_node_id;
1820174f2f35SSunil Kumar Kori 		for (lvl = lvl_start; lvl <= lvl_end; lvl++) {
182120d02329SSunil Kumar Kori 			rc = -ENOMEM;
182220d02329SSunil Kumar Kori 			node = nix_tm_node_alloc();
182320d02329SSunil Kumar Kori 			if (!node)
182420d02329SSunil Kumar Kori 				goto error;
182520d02329SSunil Kumar Kori 
182620d02329SSunil Kumar Kori 			node->id = nonleaf_id;
182720d02329SSunil Kumar Kori 			node->parent_id = parent;
182820d02329SSunil Kumar Kori 			node->priority = 0;
182920d02329SSunil Kumar Kori 			node->weight = NIX_TM_DFLT_RR_WT;
183020d02329SSunil Kumar Kori 			node->shaper_profile_id =
183120d02329SSunil Kumar Kori 				ROC_NIX_TM_SHAPER_PROFILE_NONE;
183220d02329SSunil Kumar Kori 			node->lvl = lvl;
183320d02329SSunil Kumar Kori 			node->tree = ROC_NIX_TM_PFC;
183420d02329SSunil Kumar Kori 			node->rel_chan = NIX_TM_CHAN_INVALID;
183520d02329SSunil Kumar Kori 
183620d02329SSunil Kumar Kori 			rc = nix_tm_node_add(roc_nix, node);
183720d02329SSunil Kumar Kori 			if (rc)
183820d02329SSunil Kumar Kori 				goto error;
183920d02329SSunil Kumar Kori 
184020d02329SSunil Kumar Kori 			parent = nonleaf_id;
184120d02329SSunil Kumar Kori 			nonleaf_id++;
184220d02329SSunil Kumar Kori 		}
184320d02329SSunil Kumar Kori 
1844174f2f35SSunil Kumar Kori 		lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 :
1845174f2f35SSunil Kumar Kori 		       ROC_TM_LVL_SCH3);
184620d02329SSunil Kumar Kori 
184720d02329SSunil Kumar Kori 		rc = -ENOMEM;
184820d02329SSunil Kumar Kori 		node = nix_tm_node_alloc();
184920d02329SSunil Kumar Kori 		if (!node)
185020d02329SSunil Kumar Kori 			goto error;
185120d02329SSunil Kumar Kori 
185220d02329SSunil Kumar Kori 		node->id = nonleaf_id;
185320d02329SSunil Kumar Kori 		node->parent_id = parent;
185420d02329SSunil Kumar Kori 		node->priority = 0;
185520d02329SSunil Kumar Kori 		node->weight = NIX_TM_DFLT_RR_WT;
185620d02329SSunil Kumar Kori 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
185720d02329SSunil Kumar Kori 		node->lvl = lvl;
185820d02329SSunil Kumar Kori 		node->tree = ROC_NIX_TM_PFC;
185920d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
186020d02329SSunil Kumar Kori 
186120d02329SSunil Kumar Kori 		rc = nix_tm_node_add(roc_nix, node);
186220d02329SSunil Kumar Kori 		if (rc)
186320d02329SSunil Kumar Kori 			goto error;
186420d02329SSunil Kumar Kori 
186520d02329SSunil Kumar Kori 		parent = nonleaf_id;
186620d02329SSunil Kumar Kori 		nonleaf_id++;
186720d02329SSunil Kumar Kori 
186820d02329SSunil Kumar Kori 		rc = -ENOMEM;
186920d02329SSunil Kumar Kori 		node = nix_tm_node_alloc();
187020d02329SSunil Kumar Kori 		if (!node)
187120d02329SSunil Kumar Kori 			goto error;
187220d02329SSunil Kumar Kori 
187320d02329SSunil Kumar Kori 		node->id = i;
187420d02329SSunil Kumar Kori 		node->parent_id = parent;
187520d02329SSunil Kumar Kori 		node->priority = 0;
187620d02329SSunil Kumar Kori 		node->weight = NIX_TM_DFLT_RR_WT;
187720d02329SSunil Kumar Kori 		node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
187820d02329SSunil Kumar Kori 		node->lvl = leaf_lvl;
187920d02329SSunil Kumar Kori 		node->tree = ROC_NIX_TM_PFC;
188020d02329SSunil Kumar Kori 		node->rel_chan = NIX_TM_CHAN_INVALID;
18815a960e26SNithin Dabilpuram 
18825a960e26SNithin Dabilpuram 		rc = nix_tm_node_add(roc_nix, node);
18835a960e26SNithin Dabilpuram 		if (rc)
18845a960e26SNithin Dabilpuram 			goto error;
18855a960e26SNithin Dabilpuram 	}
18865a960e26SNithin Dabilpuram 
18875a960e26SNithin Dabilpuram 	return 0;
18885a960e26SNithin Dabilpuram error:
18895a960e26SNithin Dabilpuram 	nix_tm_node_free(node);
18905a960e26SNithin Dabilpuram 	return rc;
18915a960e26SNithin Dabilpuram }
18925a960e26SNithin Dabilpuram 
18935a960e26SNithin Dabilpuram int
1894df405df9SNithin Dabilpuram nix_tm_free_resources(struct roc_nix *roc_nix, uint32_t tree_mask, bool hw_only)
1895df405df9SNithin Dabilpuram {
1896df405df9SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1897df405df9SNithin Dabilpuram 	struct nix_tm_shaper_profile *profile;
1898df405df9SNithin Dabilpuram 	struct nix_tm_node *node, *next_node;
1899df405df9SNithin Dabilpuram 	struct nix_tm_node_list *list;
1900df405df9SNithin Dabilpuram 	enum roc_nix_tm_tree tree;
1901df405df9SNithin Dabilpuram 	uint32_t profile_id;
1902df405df9SNithin Dabilpuram 	int rc = 0;
1903a5abf68cSNithin Dabilpuram 	int hw_lvl;
1904df405df9SNithin Dabilpuram 
1905df405df9SNithin Dabilpuram 	for (tree = 0; tree < ROC_NIX_TM_TREE_MAX; tree++) {
1906df405df9SNithin Dabilpuram 		if (!(tree_mask & BIT(tree)))
1907df405df9SNithin Dabilpuram 			continue;
1908df405df9SNithin Dabilpuram 
1909df405df9SNithin Dabilpuram 		plt_tm_dbg("Freeing resources of tree %u", tree);
1910df405df9SNithin Dabilpuram 
1911df405df9SNithin Dabilpuram 		list = nix_tm_node_list(nix, tree);
1912a5abf68cSNithin Dabilpuram 		/* Flush and free resources from leaf */
1913a5abf68cSNithin Dabilpuram 		for (hw_lvl = NIX_TXSCH_LVL_SMQ; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1914df405df9SNithin Dabilpuram 			next_node = TAILQ_FIRST(list);
1915df405df9SNithin Dabilpuram 			while (next_node) {
1916df405df9SNithin Dabilpuram 				node = next_node;
1917df405df9SNithin Dabilpuram 				next_node = TAILQ_NEXT(node, node);
1918a5abf68cSNithin Dabilpuram 				if (node->hw_lvl != hw_lvl)
1919a5abf68cSNithin Dabilpuram 					continue;
1920df405df9SNithin Dabilpuram 
1921df405df9SNithin Dabilpuram 				if (!nix_tm_is_leaf(nix, node->lvl) &&
1922df405df9SNithin Dabilpuram 				    node->flags & NIX_TM_NODE_HWRES) {
1923df405df9SNithin Dabilpuram 					/* Clear xoff in path for flush to succeed */
1924df405df9SNithin Dabilpuram 					rc = nix_tm_clear_path_xoff(nix, node);
1925df405df9SNithin Dabilpuram 					if (rc)
1926df405df9SNithin Dabilpuram 						return rc;
1927df405df9SNithin Dabilpuram 					rc = nix_tm_free_node_resource(nix, node);
1928df405df9SNithin Dabilpuram 					if (rc)
1929df405df9SNithin Dabilpuram 						return rc;
1930df405df9SNithin Dabilpuram 				}
1931df405df9SNithin Dabilpuram 			}
1932a5abf68cSNithin Dabilpuram 		}
1933df405df9SNithin Dabilpuram 
1934df405df9SNithin Dabilpuram 		/* Leave software elements if needed */
1935df405df9SNithin Dabilpuram 		if (hw_only)
1936df405df9SNithin Dabilpuram 			continue;
1937df405df9SNithin Dabilpuram 
1938df405df9SNithin Dabilpuram 		next_node = TAILQ_FIRST(list);
1939df405df9SNithin Dabilpuram 		while (next_node) {
1940df405df9SNithin Dabilpuram 			node = next_node;
1941df405df9SNithin Dabilpuram 			next_node = TAILQ_NEXT(node, node);
1942df405df9SNithin Dabilpuram 
1943df405df9SNithin Dabilpuram 			plt_tm_dbg("Free node lvl %u id %u (%p)", node->lvl,
1944df405df9SNithin Dabilpuram 				   node->id, node);
1945df405df9SNithin Dabilpuram 
1946df405df9SNithin Dabilpuram 			profile_id = node->shaper_profile_id;
1947df405df9SNithin Dabilpuram 			profile = nix_tm_shaper_profile_search(nix, profile_id);
1948df405df9SNithin Dabilpuram 			if (profile)
1949df405df9SNithin Dabilpuram 				profile->ref_cnt--;
1950df405df9SNithin Dabilpuram 
1951df405df9SNithin Dabilpuram 			TAILQ_REMOVE(list, node, node);
1952df405df9SNithin Dabilpuram 			nix_tm_node_free(node);
1953df405df9SNithin Dabilpuram 		}
1954df405df9SNithin Dabilpuram 	}
1955df405df9SNithin Dabilpuram 	return rc;
1956df405df9SNithin Dabilpuram }
1957df405df9SNithin Dabilpuram 
1958be3009e7SNithin Dabilpuram int
195905d727e8SNithin Dabilpuram nix_tm_conf_init(struct roc_nix *roc_nix)
196005d727e8SNithin Dabilpuram {
196105d727e8SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
196205d727e8SNithin Dabilpuram 	uint32_t bmp_sz, hw_lvl;
196305d727e8SNithin Dabilpuram 	void *bmp_mem;
196405d727e8SNithin Dabilpuram 	int rc, i;
196505d727e8SNithin Dabilpuram 
1966be3009e7SNithin Dabilpuram 	PLT_STATIC_ASSERT(sizeof(struct nix_tm_node) <= ROC_NIX_TM_NODE_SZ);
1967c2460d14SSatha Rao 	PLT_STATIC_ASSERT(sizeof(struct nix_tm_shaper_profile) <=
1968c2460d14SSatha Rao 			  ROC_NIX_TM_SHAPER_PROFILE_SZ);
1969be3009e7SNithin Dabilpuram 
197005d727e8SNithin Dabilpuram 	nix->tm_flags = 0;
197105d727e8SNithin Dabilpuram 	for (i = 0; i < ROC_NIX_TM_TREE_MAX; i++)
197205d727e8SNithin Dabilpuram 		TAILQ_INIT(&nix->trees[i]);
197305d727e8SNithin Dabilpuram 
197405d727e8SNithin Dabilpuram 	TAILQ_INIT(&nix->shaper_profile_list);
197505d727e8SNithin Dabilpuram 	nix->tm_rate_min = 1E9; /* 1Gbps */
197605d727e8SNithin Dabilpuram 
197705d727e8SNithin Dabilpuram 	rc = -ENOMEM;
197805d727e8SNithin Dabilpuram 	bmp_sz = plt_bitmap_get_memory_footprint(NIX_TM_MAX_HW_TXSCHQ);
197905d727e8SNithin Dabilpuram 	bmp_mem = plt_zmalloc(bmp_sz * NIX_TXSCH_LVL_CNT * 2, 0);
198005d727e8SNithin Dabilpuram 	if (!bmp_mem)
198105d727e8SNithin Dabilpuram 		return rc;
198205d727e8SNithin Dabilpuram 	nix->schq_bmp_mem = bmp_mem;
198305d727e8SNithin Dabilpuram 
198405d727e8SNithin Dabilpuram 	/* Init contiguous and discontiguous bitmap per lvl */
198505d727e8SNithin Dabilpuram 	rc = -EIO;
198605d727e8SNithin Dabilpuram 	for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
198705d727e8SNithin Dabilpuram 		/* Bitmap for discontiguous resource */
198805d727e8SNithin Dabilpuram 		nix->schq_bmp[hw_lvl] =
198905d727e8SNithin Dabilpuram 			plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz);
199005d727e8SNithin Dabilpuram 		if (!nix->schq_bmp[hw_lvl])
199105d727e8SNithin Dabilpuram 			goto exit;
199205d727e8SNithin Dabilpuram 
199305d727e8SNithin Dabilpuram 		bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz);
199405d727e8SNithin Dabilpuram 
199505d727e8SNithin Dabilpuram 		/* Bitmap for contiguous resource */
199605d727e8SNithin Dabilpuram 		nix->schq_contig_bmp[hw_lvl] =
199705d727e8SNithin Dabilpuram 			plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz);
199805d727e8SNithin Dabilpuram 		if (!nix->schq_contig_bmp[hw_lvl])
199905d727e8SNithin Dabilpuram 			goto exit;
200005d727e8SNithin Dabilpuram 
200105d727e8SNithin Dabilpuram 		bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz);
200205d727e8SNithin Dabilpuram 	}
200305d727e8SNithin Dabilpuram 
20040b7e667eSSatha Rao 	rc = nix_tm_mark_init(nix);
20050b7e667eSSatha Rao 	if (rc)
20060b7e667eSSatha Rao 		goto exit;
20070b7e667eSSatha Rao 
200805d727e8SNithin Dabilpuram 	/* Disable TL1 Static Priority when VF's are enabled
200905d727e8SNithin Dabilpuram 	 * as otherwise VF's TL2 reallocation will be needed
201005d727e8SNithin Dabilpuram 	 * runtime to support a specific topology of PF.
201105d727e8SNithin Dabilpuram 	 */
201205d727e8SNithin Dabilpuram 	if (nix->pci_dev->max_vfs)
201305d727e8SNithin Dabilpuram 		nix->tm_flags |= NIX_TM_TL1_NO_SP;
201405d727e8SNithin Dabilpuram 
201505d727e8SNithin Dabilpuram 	/* TL1 access is only for PF's */
201605d727e8SNithin Dabilpuram 	if (roc_nix_is_pf(roc_nix)) {
201705d727e8SNithin Dabilpuram 		nix->tm_flags |= NIX_TM_TL1_ACCESS;
201805d727e8SNithin Dabilpuram 		nix->tm_root_lvl = NIX_TXSCH_LVL_TL1;
201905d727e8SNithin Dabilpuram 	} else {
202005d727e8SNithin Dabilpuram 		nix->tm_root_lvl = NIX_TXSCH_LVL_TL2;
202105d727e8SNithin Dabilpuram 	}
202205d727e8SNithin Dabilpuram 
202305d727e8SNithin Dabilpuram 	return 0;
202405d727e8SNithin Dabilpuram exit:
202505d727e8SNithin Dabilpuram 	nix_tm_conf_fini(roc_nix);
202605d727e8SNithin Dabilpuram 	return rc;
202705d727e8SNithin Dabilpuram }
202805d727e8SNithin Dabilpuram 
202905d727e8SNithin Dabilpuram void
203005d727e8SNithin Dabilpuram nix_tm_conf_fini(struct roc_nix *roc_nix)
203105d727e8SNithin Dabilpuram {
203205d727e8SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
203305d727e8SNithin Dabilpuram 	uint16_t hw_lvl;
203405d727e8SNithin Dabilpuram 
203505d727e8SNithin Dabilpuram 	for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
203605d727e8SNithin Dabilpuram 		plt_bitmap_free(nix->schq_bmp[hw_lvl]);
203705d727e8SNithin Dabilpuram 		plt_bitmap_free(nix->schq_contig_bmp[hw_lvl]);
203805d727e8SNithin Dabilpuram 	}
203905d727e8SNithin Dabilpuram 	plt_free(nix->schq_bmp_mem);
204005d727e8SNithin Dabilpuram }
2041