xref: /dpdk/drivers/common/cnxk/roc_nix_tm_utils.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
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 
80885429cSNithin Dabilpuram static inline uint64_t
90885429cSNithin Dabilpuram nix_tm_shaper2regval(struct nix_tm_shaper_data *shaper)
100885429cSNithin Dabilpuram {
116fe49f10SNithin Dabilpuram 	uint64_t regval;
126fe49f10SNithin Dabilpuram 
136fe49f10SNithin Dabilpuram 	if (roc_model_is_cn9k()) {
146fe49f10SNithin Dabilpuram 		regval = (shaper->burst_exponent << 37);
156fe49f10SNithin Dabilpuram 		regval |= (shaper->burst_mantissa << 29);
166fe49f10SNithin Dabilpuram 		regval |= (shaper->div_exp << 13);
176fe49f10SNithin Dabilpuram 		regval |= (shaper->exponent << 9);
186fe49f10SNithin Dabilpuram 		regval |= (shaper->mantissa << 1);
196fe49f10SNithin Dabilpuram 		return regval;
206fe49f10SNithin Dabilpuram 	}
216fe49f10SNithin Dabilpuram 
226fe49f10SNithin Dabilpuram 	regval = (shaper->burst_exponent << 44);
236fe49f10SNithin Dabilpuram 	regval |= (shaper->burst_mantissa << 29);
246fe49f10SNithin Dabilpuram 	regval |= (shaper->div_exp << 13);
256fe49f10SNithin Dabilpuram 	regval |= (shaper->exponent << 9);
266fe49f10SNithin Dabilpuram 	regval |= (shaper->mantissa << 1);
276fe49f10SNithin Dabilpuram 	return regval;
280885429cSNithin Dabilpuram }
290885429cSNithin Dabilpuram 
30be3009e7SNithin Dabilpuram uint16_t
31be3009e7SNithin Dabilpuram nix_tm_lvl2nix_tl1_root(uint32_t lvl)
32be3009e7SNithin Dabilpuram {
33be3009e7SNithin Dabilpuram 	switch (lvl) {
34be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_ROOT:
35be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL1;
36be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH1:
37be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL2;
38be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH2:
39be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL3;
40be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH3:
41be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL4;
42be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH4:
43be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_SMQ;
44be3009e7SNithin Dabilpuram 	default:
45be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_CNT;
46be3009e7SNithin Dabilpuram 	}
47be3009e7SNithin Dabilpuram }
48be3009e7SNithin Dabilpuram 
49be3009e7SNithin Dabilpuram uint16_t
50be3009e7SNithin Dabilpuram nix_tm_lvl2nix_tl2_root(uint32_t lvl)
51be3009e7SNithin Dabilpuram {
52be3009e7SNithin Dabilpuram 	switch (lvl) {
53be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_ROOT:
54be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL2;
55be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH1:
56be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL3;
57be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH2:
58be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_TL4;
59be3009e7SNithin Dabilpuram 	case ROC_TM_LVL_SCH3:
60be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_SMQ;
61be3009e7SNithin Dabilpuram 	default:
62be3009e7SNithin Dabilpuram 		return NIX_TXSCH_LVL_CNT;
63be3009e7SNithin Dabilpuram 	}
64be3009e7SNithin Dabilpuram }
65be3009e7SNithin Dabilpuram 
66be3009e7SNithin Dabilpuram uint16_t
67be3009e7SNithin Dabilpuram nix_tm_lvl2nix(struct nix *nix, uint32_t lvl)
68be3009e7SNithin Dabilpuram {
69be3009e7SNithin Dabilpuram 	if (nix_tm_have_tl1_access(nix))
70be3009e7SNithin Dabilpuram 		return nix_tm_lvl2nix_tl1_root(lvl);
71be3009e7SNithin Dabilpuram 	else
72be3009e7SNithin Dabilpuram 		return nix_tm_lvl2nix_tl2_root(lvl);
73be3009e7SNithin Dabilpuram }
74be3009e7SNithin Dabilpuram 
7578fb5efeSNithin Dabilpuram uint8_t
7678fb5efeSNithin Dabilpuram nix_tm_lbk_relchan_get(struct nix *nix)
770885429cSNithin Dabilpuram {
780885429cSNithin Dabilpuram 	return nix->tx_chan_base & 0xff;
790885429cSNithin Dabilpuram }
800885429cSNithin Dabilpuram 
810885429cSNithin Dabilpuram static int
820885429cSNithin Dabilpuram nix_tm_find_prio_anchor(struct nix *nix, uint32_t node_id,
830885429cSNithin Dabilpuram 			enum roc_nix_tm_tree tree)
840885429cSNithin Dabilpuram {
850885429cSNithin Dabilpuram 	struct nix_tm_node *child_node;
860885429cSNithin Dabilpuram 	struct nix_tm_node_list *list;
870885429cSNithin Dabilpuram 
880885429cSNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
890885429cSNithin Dabilpuram 
900885429cSNithin Dabilpuram 	TAILQ_FOREACH(child_node, list, node) {
910885429cSNithin Dabilpuram 		if (!child_node->parent)
920885429cSNithin Dabilpuram 			continue;
930885429cSNithin Dabilpuram 		if (!(child_node->parent->id == node_id))
940885429cSNithin Dabilpuram 			continue;
950885429cSNithin Dabilpuram 		if (child_node->priority == child_node->parent->rr_prio)
960885429cSNithin Dabilpuram 			continue;
970885429cSNithin Dabilpuram 		return child_node->hw_id - child_node->priority;
980885429cSNithin Dabilpuram 	}
990885429cSNithin Dabilpuram 	return 0;
1000885429cSNithin Dabilpuram }
101be3009e7SNithin Dabilpuram 
102be3009e7SNithin Dabilpuram struct nix_tm_shaper_profile *
103be3009e7SNithin Dabilpuram nix_tm_shaper_profile_search(struct nix *nix, uint32_t id)
104be3009e7SNithin Dabilpuram {
105be3009e7SNithin Dabilpuram 	struct nix_tm_shaper_profile *profile;
106be3009e7SNithin Dabilpuram 
107be3009e7SNithin Dabilpuram 	TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
108be3009e7SNithin Dabilpuram 		if (profile->id == id)
109be3009e7SNithin Dabilpuram 			return profile;
110be3009e7SNithin Dabilpuram 	}
111be3009e7SNithin Dabilpuram 	return NULL;
112be3009e7SNithin Dabilpuram }
113be3009e7SNithin Dabilpuram 
11405d727e8SNithin Dabilpuram struct nix_tm_node *
11505d727e8SNithin Dabilpuram nix_tm_node_search(struct nix *nix, uint32_t node_id, enum roc_nix_tm_tree tree)
11605d727e8SNithin Dabilpuram {
11705d727e8SNithin Dabilpuram 	struct nix_tm_node_list *list;
11805d727e8SNithin Dabilpuram 	struct nix_tm_node *node;
11905d727e8SNithin Dabilpuram 
12005d727e8SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
12105d727e8SNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
12205d727e8SNithin Dabilpuram 		if (node->id == node_id)
12305d727e8SNithin Dabilpuram 			return node;
12405d727e8SNithin Dabilpuram 	}
12505d727e8SNithin Dabilpuram 	return NULL;
12605d727e8SNithin Dabilpuram }
12705d727e8SNithin Dabilpuram 
12802bf1662SSatha Rao static uint64_t
12902bf1662SSatha Rao nix_tm_shaper_rate_conv_floor(uint64_t value, uint64_t *exponent_p,
13002bf1662SSatha Rao 			      uint64_t *mantissa_p, uint64_t *div_exp_p)
13102bf1662SSatha Rao {
13202bf1662SSatha Rao 	uint64_t div_exp, exponent, mantissa;
13302bf1662SSatha Rao 
13402bf1662SSatha Rao 	/* Boundary checks */
13502bf1662SSatha Rao 	if (value < NIX_TM_MIN_SHAPER_RATE || value > NIX_TM_MAX_SHAPER_RATE)
13602bf1662SSatha Rao 		return 0;
13702bf1662SSatha Rao 
13802bf1662SSatha Rao 	if (value <= NIX_TM_SHAPER_RATE(0, 0, 0)) {
13902bf1662SSatha Rao 		/* Calculate rate div_exp and mantissa using
14002bf1662SSatha Rao 		 * the following formula:
14102bf1662SSatha Rao 		 *
14202bf1662SSatha Rao 		 * value = (2E6 * (256 + mantissa)
14302bf1662SSatha Rao 		 *              / ((1 << div_exp) * 256))
14402bf1662SSatha Rao 		 */
14502bf1662SSatha Rao 		div_exp = 0;
14602bf1662SSatha Rao 		exponent = 0;
14702bf1662SSatha Rao 		mantissa = NIX_TM_MAX_RATE_MANTISSA;
14802bf1662SSatha Rao 
14902bf1662SSatha Rao 		while (value <= (NIX_TM_SHAPER_RATE_CONST / (1 << div_exp)))
15002bf1662SSatha Rao 			div_exp += 1;
15102bf1662SSatha Rao 
15202bf1662SSatha Rao 		while (value <= ((NIX_TM_SHAPER_RATE_CONST * (256 + mantissa)) /
15302bf1662SSatha Rao 				 ((1 << div_exp) * 256)))
15402bf1662SSatha Rao 			mantissa -= 1;
15502bf1662SSatha Rao 	} else {
15602bf1662SSatha Rao 		/* Calculate rate exponent and mantissa using
15702bf1662SSatha Rao 		 * the following formula:
15802bf1662SSatha Rao 		 *
15902bf1662SSatha Rao 		 * value = (2E6 * ((256 + mantissa) << exponent)) / 256
16002bf1662SSatha Rao 		 *
16102bf1662SSatha Rao 		 */
16202bf1662SSatha Rao 		div_exp = 0;
16302bf1662SSatha Rao 		exponent = NIX_TM_MAX_RATE_EXPONENT;
16402bf1662SSatha Rao 		mantissa = NIX_TM_MAX_RATE_MANTISSA;
16502bf1662SSatha Rao 
16602bf1662SSatha Rao 		while (value <= (NIX_TM_SHAPER_RATE_CONST * (1 << exponent)))
16702bf1662SSatha Rao 			exponent -= 1;
16802bf1662SSatha Rao 
16902bf1662SSatha Rao 		while (value <= ((NIX_TM_SHAPER_RATE_CONST *
17002bf1662SSatha Rao 				  ((256 + mantissa) << exponent)) /
17102bf1662SSatha Rao 				 256))
17202bf1662SSatha Rao 			mantissa -= 1;
17302bf1662SSatha Rao 	}
17402bf1662SSatha Rao 
17502bf1662SSatha Rao 	if (div_exp > NIX_TM_MAX_RATE_DIV_EXP ||
17602bf1662SSatha Rao 	    exponent > NIX_TM_MAX_RATE_EXPONENT ||
17702bf1662SSatha Rao 	    mantissa > NIX_TM_MAX_RATE_MANTISSA)
17802bf1662SSatha Rao 		return 0;
17902bf1662SSatha Rao 
18002bf1662SSatha Rao 	if (div_exp_p)
18102bf1662SSatha Rao 		*div_exp_p = div_exp;
18202bf1662SSatha Rao 	if (exponent_p)
18302bf1662SSatha Rao 		*exponent_p = exponent;
18402bf1662SSatha Rao 	if (mantissa_p)
18502bf1662SSatha Rao 		*mantissa_p = mantissa;
18602bf1662SSatha Rao 
18702bf1662SSatha Rao 	/* Calculate real rate value */
18802bf1662SSatha Rao 	return NIX_TM_SHAPER_RATE(exponent, mantissa, div_exp);
18902bf1662SSatha Rao }
19002bf1662SSatha Rao 
19102bf1662SSatha Rao static uint64_t
19202bf1662SSatha Rao nix_tm_shaper_rate_conv_exact(uint64_t value, uint64_t *exponent_p,
193c2460d14SSatha Rao 			      uint64_t *mantissa_p, uint64_t *div_exp_p)
194c2460d14SSatha Rao {
195c2460d14SSatha Rao 	uint64_t div_exp, exponent, mantissa;
196c2460d14SSatha Rao 
197c2460d14SSatha Rao 	/* Boundary checks */
198c2460d14SSatha Rao 	if (value < NIX_TM_MIN_SHAPER_RATE || value > NIX_TM_MAX_SHAPER_RATE)
199c2460d14SSatha Rao 		return 0;
200c2460d14SSatha Rao 
201c2460d14SSatha Rao 	if (value <= NIX_TM_SHAPER_RATE(0, 0, 0)) {
202c2460d14SSatha Rao 		/* Calculate rate div_exp and mantissa using
203c2460d14SSatha Rao 		 * the following formula:
204c2460d14SSatha Rao 		 *
205c2460d14SSatha Rao 		 * value = (2E6 * (256 + mantissa)
206c2460d14SSatha Rao 		 *              / ((1 << div_exp) * 256))
207c2460d14SSatha Rao 		 */
208c2460d14SSatha Rao 		div_exp = 0;
209c2460d14SSatha Rao 		exponent = 0;
210c2460d14SSatha Rao 		mantissa = NIX_TM_MAX_RATE_MANTISSA;
211c2460d14SSatha Rao 
212c2460d14SSatha Rao 		while (value < (NIX_TM_SHAPER_RATE_CONST / (1 << div_exp)))
213c2460d14SSatha Rao 			div_exp += 1;
214c2460d14SSatha Rao 
215c2460d14SSatha Rao 		while (value < ((NIX_TM_SHAPER_RATE_CONST * (256 + mantissa)) /
216c2460d14SSatha Rao 				((1 << div_exp) * 256)))
217c2460d14SSatha Rao 			mantissa -= 1;
218c2460d14SSatha Rao 	} else {
219c2460d14SSatha Rao 		/* Calculate rate exponent and mantissa using
220c2460d14SSatha Rao 		 * the following formula:
221c2460d14SSatha Rao 		 *
222c2460d14SSatha Rao 		 * value = (2E6 * ((256 + mantissa) << exponent)) / 256
223c2460d14SSatha Rao 		 *
224c2460d14SSatha Rao 		 */
225c2460d14SSatha Rao 		div_exp = 0;
226c2460d14SSatha Rao 		exponent = NIX_TM_MAX_RATE_EXPONENT;
227c2460d14SSatha Rao 		mantissa = NIX_TM_MAX_RATE_MANTISSA;
228c2460d14SSatha Rao 
229c2460d14SSatha Rao 		while (value < (NIX_TM_SHAPER_RATE_CONST * (1 << exponent)))
230c2460d14SSatha Rao 			exponent -= 1;
231c2460d14SSatha Rao 
232c2460d14SSatha Rao 		while (value < ((NIX_TM_SHAPER_RATE_CONST *
233c2460d14SSatha Rao 				 ((256 + mantissa) << exponent)) /
234c2460d14SSatha Rao 				256))
235c2460d14SSatha Rao 			mantissa -= 1;
236c2460d14SSatha Rao 	}
237c2460d14SSatha Rao 
238c2460d14SSatha Rao 	if (div_exp > NIX_TM_MAX_RATE_DIV_EXP ||
239c2460d14SSatha Rao 	    exponent > NIX_TM_MAX_RATE_EXPONENT ||
240c2460d14SSatha Rao 	    mantissa > NIX_TM_MAX_RATE_MANTISSA)
241c2460d14SSatha Rao 		return 0;
242c2460d14SSatha Rao 
243c2460d14SSatha Rao 	if (div_exp_p)
244c2460d14SSatha Rao 		*div_exp_p = div_exp;
245c2460d14SSatha Rao 	if (exponent_p)
246c2460d14SSatha Rao 		*exponent_p = exponent;
247c2460d14SSatha Rao 	if (mantissa_p)
248c2460d14SSatha Rao 		*mantissa_p = mantissa;
249c2460d14SSatha Rao 
250c2460d14SSatha Rao 	/* Calculate real rate value */
251c2460d14SSatha Rao 	return NIX_TM_SHAPER_RATE(exponent, mantissa, div_exp);
252c2460d14SSatha Rao }
253c2460d14SSatha Rao 
25402bf1662SSatha Rao /* With zero accuracy we will tune parameters as defined by HW,
25502bf1662SSatha Rao  * non zero accuracy will keep the parameters close to lower values
25602bf1662SSatha Rao  * and make sure long-term shaper rate will not exceed the requested rate.
25702bf1662SSatha Rao  */
25802bf1662SSatha Rao uint64_t
25902bf1662SSatha Rao nix_tm_shaper_rate_conv(uint64_t value, uint64_t *exponent_p,
26002bf1662SSatha Rao 			uint64_t *mantissa_p, uint64_t *div_exp_p,
26102bf1662SSatha Rao 			int8_t accuracy)
26202bf1662SSatha Rao {
26302bf1662SSatha Rao 	if (!accuracy)
26402bf1662SSatha Rao 		return nix_tm_shaper_rate_conv_exact(value, exponent_p,
26502bf1662SSatha Rao 						     mantissa_p, div_exp_p);
26602bf1662SSatha Rao 
26702bf1662SSatha Rao 	return nix_tm_shaper_rate_conv_floor(value, exponent_p, mantissa_p,
26802bf1662SSatha Rao 					     div_exp_p);
26902bf1662SSatha Rao }
27002bf1662SSatha Rao 
271c2460d14SSatha Rao uint64_t
272c2460d14SSatha Rao nix_tm_shaper_burst_conv(uint64_t value, uint64_t *exponent_p,
273c2460d14SSatha Rao 			 uint64_t *mantissa_p)
274c2460d14SSatha Rao {
2756fe49f10SNithin Dabilpuram 	uint64_t min_burst, max_burst;
276c2460d14SSatha Rao 	uint64_t exponent, mantissa;
2776fe49f10SNithin Dabilpuram 	uint32_t max_mantissa;
278c2460d14SSatha Rao 
2796fe49f10SNithin Dabilpuram 	min_burst = NIX_TM_MIN_SHAPER_BURST;
2806fe49f10SNithin Dabilpuram 	max_burst = roc_nix_tm_max_shaper_burst_get();
2816fe49f10SNithin Dabilpuram 
2826fe49f10SNithin Dabilpuram 	if (value < min_burst || value > max_burst)
283c2460d14SSatha Rao 		return 0;
284c2460d14SSatha Rao 
2856fe49f10SNithin Dabilpuram 	max_mantissa = (roc_model_is_cn9k() ? NIX_CN9K_TM_MAX_BURST_MANTISSA :
2866fe49f10SNithin Dabilpuram 					      NIX_TM_MAX_BURST_MANTISSA);
287c2460d14SSatha Rao 	/* Calculate burst exponent and mantissa using
288c2460d14SSatha Rao 	 * the following formula:
289c2460d14SSatha Rao 	 *
2906fe49f10SNithin Dabilpuram 	 * value = (((256 + mantissa) << (exponent + 1) / 256)
291c2460d14SSatha Rao 	 *
292c2460d14SSatha Rao 	 */
293c2460d14SSatha Rao 	exponent = NIX_TM_MAX_BURST_EXPONENT;
2946fe49f10SNithin Dabilpuram 	mantissa = max_mantissa;
295c2460d14SSatha Rao 
296c2460d14SSatha Rao 	while (value < (1ull << (exponent + 1)))
297c2460d14SSatha Rao 		exponent -= 1;
298c2460d14SSatha Rao 
299c2460d14SSatha Rao 	while (value < ((256 + mantissa) << (exponent + 1)) / 256)
300c2460d14SSatha Rao 		mantissa -= 1;
301c2460d14SSatha Rao 
3026fe49f10SNithin Dabilpuram 	if (exponent > NIX_TM_MAX_BURST_EXPONENT || mantissa > max_mantissa)
303c2460d14SSatha Rao 		return 0;
304c2460d14SSatha Rao 
305c2460d14SSatha Rao 	if (exponent_p)
306c2460d14SSatha Rao 		*exponent_p = exponent;
307c2460d14SSatha Rao 	if (mantissa_p)
308c2460d14SSatha Rao 		*mantissa_p = mantissa;
309c2460d14SSatha Rao 
310c2460d14SSatha Rao 	return NIX_TM_SHAPER_BURST(exponent, mantissa);
311c2460d14SSatha Rao }
312c2460d14SSatha Rao 
3130885429cSNithin Dabilpuram static void
3140885429cSNithin Dabilpuram nix_tm_shaper_conf_get(struct nix_tm_shaper_profile *profile,
3150885429cSNithin Dabilpuram 		       struct nix_tm_shaper_data *cir,
3160885429cSNithin Dabilpuram 		       struct nix_tm_shaper_data *pir)
3170885429cSNithin Dabilpuram {
318f9dbd4a5SSatha Rao 	memset(cir, 0, sizeof(*cir));
319f9dbd4a5SSatha Rao 	memset(pir, 0, sizeof(*pir));
320f9dbd4a5SSatha Rao 
3210885429cSNithin Dabilpuram 	if (!profile)
3220885429cSNithin Dabilpuram 		return;
3230885429cSNithin Dabilpuram 
3240885429cSNithin Dabilpuram 	/* Calculate CIR exponent and mantissa */
3250885429cSNithin Dabilpuram 	if (profile->commit.rate)
3260885429cSNithin Dabilpuram 		cir->rate = nix_tm_shaper_rate_conv(
3270885429cSNithin Dabilpuram 			profile->commit.rate, &cir->exponent, &cir->mantissa,
32802bf1662SSatha Rao 			&cir->div_exp, profile->accuracy);
3290885429cSNithin Dabilpuram 
3300885429cSNithin Dabilpuram 	/* Calculate PIR exponent and mantissa */
3310885429cSNithin Dabilpuram 	if (profile->peak.rate)
3320885429cSNithin Dabilpuram 		pir->rate = nix_tm_shaper_rate_conv(
3330885429cSNithin Dabilpuram 			profile->peak.rate, &pir->exponent, &pir->mantissa,
33402bf1662SSatha Rao 			&pir->div_exp, profile->accuracy);
3350885429cSNithin Dabilpuram 
3360885429cSNithin Dabilpuram 	/* Calculate CIR burst exponent and mantissa */
3370885429cSNithin Dabilpuram 	if (profile->commit.size)
3380885429cSNithin Dabilpuram 		cir->burst = nix_tm_shaper_burst_conv(profile->commit.size,
3390885429cSNithin Dabilpuram 						      &cir->burst_exponent,
3400885429cSNithin Dabilpuram 						      &cir->burst_mantissa);
3410885429cSNithin Dabilpuram 
3420885429cSNithin Dabilpuram 	/* Calculate PIR burst exponent and mantissa */
3430885429cSNithin Dabilpuram 	if (profile->peak.size)
3440885429cSNithin Dabilpuram 		pir->burst = nix_tm_shaper_burst_conv(profile->peak.size,
3450885429cSNithin Dabilpuram 						      &pir->burst_exponent,
3460885429cSNithin Dabilpuram 						      &pir->burst_mantissa);
3470885429cSNithin Dabilpuram }
3480885429cSNithin Dabilpuram 
349df405df9SNithin Dabilpuram uint32_t
350df405df9SNithin Dabilpuram nix_tm_check_rr(struct nix *nix, uint32_t parent_id, enum roc_nix_tm_tree tree,
351df405df9SNithin Dabilpuram 		uint32_t *rr_prio, uint32_t *max_prio)
352df405df9SNithin Dabilpuram {
353df405df9SNithin Dabilpuram 	uint32_t node_cnt[NIX_TM_TLX_SP_PRIO_MAX];
354df405df9SNithin Dabilpuram 	struct nix_tm_node_list *list;
355df405df9SNithin Dabilpuram 	struct nix_tm_node *node;
356df405df9SNithin Dabilpuram 	uint32_t rr_num = 0, i;
357df405df9SNithin Dabilpuram 	uint32_t children = 0;
358df405df9SNithin Dabilpuram 	uint32_t priority;
359df405df9SNithin Dabilpuram 
360df405df9SNithin Dabilpuram 	memset(node_cnt, 0, sizeof(node_cnt));
361df405df9SNithin Dabilpuram 	*rr_prio = 0xF;
362df405df9SNithin Dabilpuram 	*max_prio = UINT32_MAX;
363df405df9SNithin Dabilpuram 
364df405df9SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
365df405df9SNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
366df405df9SNithin Dabilpuram 		if (!node->parent)
367df405df9SNithin Dabilpuram 			continue;
368df405df9SNithin Dabilpuram 
369df405df9SNithin Dabilpuram 		if (!(node->parent->id == parent_id))
370df405df9SNithin Dabilpuram 			continue;
371df405df9SNithin Dabilpuram 
372df405df9SNithin Dabilpuram 		priority = node->priority;
373df405df9SNithin Dabilpuram 		node_cnt[priority]++;
374df405df9SNithin Dabilpuram 		children++;
375df405df9SNithin Dabilpuram 	}
376df405df9SNithin Dabilpuram 
377df405df9SNithin Dabilpuram 	for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++) {
378df405df9SNithin Dabilpuram 		if (!node_cnt[i])
379df405df9SNithin Dabilpuram 			break;
380df405df9SNithin Dabilpuram 
381df405df9SNithin Dabilpuram 		if (node_cnt[i] > rr_num) {
382df405df9SNithin Dabilpuram 			*rr_prio = i;
383df405df9SNithin Dabilpuram 			rr_num = node_cnt[i];
384df405df9SNithin Dabilpuram 		}
385df405df9SNithin Dabilpuram 	}
386df405df9SNithin Dabilpuram 
387df405df9SNithin Dabilpuram 	/* RR group of single RR child is considered as SP */
388df405df9SNithin Dabilpuram 	if (rr_num == 1) {
389df405df9SNithin Dabilpuram 		*rr_prio = 0xF;
390df405df9SNithin Dabilpuram 		rr_num = 0;
391df405df9SNithin Dabilpuram 	}
392df405df9SNithin Dabilpuram 
393df405df9SNithin Dabilpuram 	/* Max prio will be returned only when we have non zero prio
394df405df9SNithin Dabilpuram 	 * or if a parent has single child.
395df405df9SNithin Dabilpuram 	 */
396df405df9SNithin Dabilpuram 	if (i > 1 || (children == 1))
397df405df9SNithin Dabilpuram 		*max_prio = i - 1;
398df405df9SNithin Dabilpuram 	return rr_num;
399df405df9SNithin Dabilpuram }
400df405df9SNithin Dabilpuram 
401be3009e7SNithin Dabilpuram static uint16_t
402be3009e7SNithin Dabilpuram nix_tm_max_prio(struct nix *nix, uint16_t hw_lvl)
403be3009e7SNithin Dabilpuram {
404be3009e7SNithin Dabilpuram 	if (hw_lvl >= NIX_TXSCH_LVL_CNT)
405be3009e7SNithin Dabilpuram 		return 0;
406be3009e7SNithin Dabilpuram 
407be3009e7SNithin Dabilpuram 	/* MDQ does not support SP */
408be3009e7SNithin Dabilpuram 	if (hw_lvl == NIX_TXSCH_LVL_MDQ)
409be3009e7SNithin Dabilpuram 		return 0;
410be3009e7SNithin Dabilpuram 
411be3009e7SNithin Dabilpuram 	/* PF's TL1 with VF's enabled does not support SP */
412be3009e7SNithin Dabilpuram 	if (hw_lvl == NIX_TXSCH_LVL_TL1 && (!nix_tm_have_tl1_access(nix) ||
413be3009e7SNithin Dabilpuram 					    (nix->tm_flags & NIX_TM_TL1_NO_SP)))
414be3009e7SNithin Dabilpuram 		return 0;
415be3009e7SNithin Dabilpuram 
416be3009e7SNithin Dabilpuram 	return NIX_TM_TLX_SP_PRIO_MAX - 1;
417be3009e7SNithin Dabilpuram }
418be3009e7SNithin Dabilpuram 
419be3009e7SNithin Dabilpuram int
420be3009e7SNithin Dabilpuram nix_tm_validate_prio(struct nix *nix, uint32_t lvl, uint32_t parent_id,
421be3009e7SNithin Dabilpuram 		     uint32_t priority, enum roc_nix_tm_tree tree)
422be3009e7SNithin Dabilpuram {
423be3009e7SNithin Dabilpuram 	uint8_t priorities[NIX_TM_TLX_SP_PRIO_MAX];
424be3009e7SNithin Dabilpuram 	struct nix_tm_node_list *list;
425be3009e7SNithin Dabilpuram 	struct nix_tm_node *node;
426be3009e7SNithin Dabilpuram 	uint32_t rr_num = 0;
427be3009e7SNithin Dabilpuram 	int i;
428be3009e7SNithin Dabilpuram 
429be3009e7SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
430be3009e7SNithin Dabilpuram 	/* Validate priority against max */
431be3009e7SNithin Dabilpuram 	if (priority > nix_tm_max_prio(nix, nix_tm_lvl2nix(nix, lvl - 1)))
432be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_PRIO_EXCEEDED;
433be3009e7SNithin Dabilpuram 
434be3009e7SNithin Dabilpuram 	if (parent_id == ROC_NIX_TM_NODE_ID_INVALID)
435be3009e7SNithin Dabilpuram 		return 0;
436be3009e7SNithin Dabilpuram 
437be3009e7SNithin Dabilpuram 	memset(priorities, 0, sizeof(priorities));
438be3009e7SNithin Dabilpuram 	priorities[priority] = 1;
439be3009e7SNithin Dabilpuram 
440be3009e7SNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
441be3009e7SNithin Dabilpuram 		if (!node->parent)
442be3009e7SNithin Dabilpuram 			continue;
443be3009e7SNithin Dabilpuram 
444be3009e7SNithin Dabilpuram 		if (node->parent->id != parent_id)
445be3009e7SNithin Dabilpuram 			continue;
446be3009e7SNithin Dabilpuram 
447be3009e7SNithin Dabilpuram 		priorities[node->priority]++;
448be3009e7SNithin Dabilpuram 	}
449be3009e7SNithin Dabilpuram 
450be3009e7SNithin Dabilpuram 	for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++)
451be3009e7SNithin Dabilpuram 		if (priorities[i] > 1)
452be3009e7SNithin Dabilpuram 			rr_num++;
453be3009e7SNithin Dabilpuram 
454be3009e7SNithin Dabilpuram 	/* At max, one rr groups per parent */
455be3009e7SNithin Dabilpuram 	if (rr_num > 1)
456be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_MULTIPLE_RR_GROUPS;
457be3009e7SNithin Dabilpuram 
458be3009e7SNithin Dabilpuram 	/* Check for previous priority to avoid holes in priorities */
459be3009e7SNithin Dabilpuram 	if (priority && !priorities[priority - 1])
460be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_PRIO_ORDER;
461be3009e7SNithin Dabilpuram 
462be3009e7SNithin Dabilpuram 	return 0;
463be3009e7SNithin Dabilpuram }
464be3009e7SNithin Dabilpuram 
465df405df9SNithin Dabilpuram bool
466df405df9SNithin Dabilpuram nix_tm_child_res_valid(struct nix_tm_node_list *list,
467df405df9SNithin Dabilpuram 		       struct nix_tm_node *parent)
468df405df9SNithin Dabilpuram {
469df405df9SNithin Dabilpuram 	struct nix_tm_node *child;
470df405df9SNithin Dabilpuram 
471df405df9SNithin Dabilpuram 	TAILQ_FOREACH(child, list, node) {
472df405df9SNithin Dabilpuram 		if (child->parent != parent)
473df405df9SNithin Dabilpuram 			continue;
474df405df9SNithin Dabilpuram 		if (!(child->flags & NIX_TM_NODE_HWRES))
475df405df9SNithin Dabilpuram 			return false;
476df405df9SNithin Dabilpuram 	}
477df405df9SNithin Dabilpuram 	return true;
478df405df9SNithin Dabilpuram }
479df405df9SNithin Dabilpuram 
48005d727e8SNithin Dabilpuram uint8_t
481f0b9158cSNithin Dabilpuram nix_tm_tl1_default_prep(struct nix *nix, uint32_t schq, volatile uint64_t *reg,
4820885429cSNithin Dabilpuram 			volatile uint64_t *regval)
4830885429cSNithin Dabilpuram {
4840885429cSNithin Dabilpuram 	uint8_t k = 0;
4850885429cSNithin Dabilpuram 
4860885429cSNithin Dabilpuram 	/*
4870885429cSNithin Dabilpuram 	 * Default config for TL1.
4880885429cSNithin Dabilpuram 	 * For VF this is always ignored.
4890885429cSNithin Dabilpuram 	 */
4900885429cSNithin Dabilpuram 	plt_tm_dbg("Default config for main root %s(%u)",
4910885429cSNithin Dabilpuram 		   nix_tm_hwlvl2str(NIX_TXSCH_LVL_TL1), schq);
4920885429cSNithin Dabilpuram 
4930885429cSNithin Dabilpuram 	/* Set DWRR quantum */
4940885429cSNithin Dabilpuram 	reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
4950885429cSNithin Dabilpuram 	regval[k] = NIX_TM_TL1_DFLT_RR_QTM;
4960885429cSNithin Dabilpuram 	k++;
4970885429cSNithin Dabilpuram 
4980885429cSNithin Dabilpuram 	reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
499f0b9158cSNithin Dabilpuram 	regval[k] = (nix->tm_aggr_lvl_rr_prio << 1);
5000885429cSNithin Dabilpuram 	k++;
5010885429cSNithin Dabilpuram 
5020885429cSNithin Dabilpuram 	reg[k] = NIX_AF_TL1X_CIR(schq);
5030885429cSNithin Dabilpuram 	regval[k] = 0;
5040885429cSNithin Dabilpuram 	k++;
5050885429cSNithin Dabilpuram 
5060885429cSNithin Dabilpuram 	return k;
5070885429cSNithin Dabilpuram }
5080885429cSNithin Dabilpuram 
5090885429cSNithin Dabilpuram uint8_t
5100885429cSNithin Dabilpuram nix_tm_topology_reg_prep(struct nix *nix, struct nix_tm_node *node,
5110885429cSNithin Dabilpuram 			 volatile uint64_t *reg, volatile uint64_t *regval,
5120885429cSNithin Dabilpuram 			 volatile uint64_t *regval_mask)
5130885429cSNithin Dabilpuram {
5146b7fcb7aSSatha Rao 	struct roc_nix *roc_nix = nix_priv_to_roc_nix(nix);
5150885429cSNithin Dabilpuram 	uint8_t k = 0, hw_lvl, parent_lvl;
5160885429cSNithin Dabilpuram 	uint64_t parent = 0, child = 0;
5170885429cSNithin Dabilpuram 	enum roc_nix_tm_tree tree;
5180885429cSNithin Dabilpuram 	uint32_t rr_prio, schq;
5190885429cSNithin Dabilpuram 	uint16_t link, relchan;
5200885429cSNithin Dabilpuram 
5210885429cSNithin Dabilpuram 	tree = node->tree;
5220885429cSNithin Dabilpuram 	schq = node->hw_id;
5230885429cSNithin Dabilpuram 	hw_lvl = node->hw_lvl;
5240885429cSNithin Dabilpuram 	parent_lvl = hw_lvl + 1;
5250885429cSNithin Dabilpuram 	rr_prio = node->rr_prio;
5260885429cSNithin Dabilpuram 
5270885429cSNithin Dabilpuram 	/* Root node will not have a parent node */
5280885429cSNithin Dabilpuram 	if (hw_lvl == nix->tm_root_lvl)
5290885429cSNithin Dabilpuram 		parent = node->parent_hw_id;
5300885429cSNithin Dabilpuram 	else
5310885429cSNithin Dabilpuram 		parent = node->parent->hw_id;
5320885429cSNithin Dabilpuram 
5330885429cSNithin Dabilpuram 	link = nix->tx_link;
53478fb5efeSNithin Dabilpuram 	relchan = roc_nix_is_lbk(roc_nix) ? nix_tm_lbk_relchan_get(nix) : 0;
5350885429cSNithin Dabilpuram 
5360885429cSNithin Dabilpuram 	if (hw_lvl != NIX_TXSCH_LVL_SMQ)
5370885429cSNithin Dabilpuram 		child = nix_tm_find_prio_anchor(nix, node->id, tree);
5380885429cSNithin Dabilpuram 
5390885429cSNithin Dabilpuram 	/* Override default rr_prio when TL1
5400885429cSNithin Dabilpuram 	 * Static Priority is disabled
5410885429cSNithin Dabilpuram 	 */
5420885429cSNithin Dabilpuram 	if (hw_lvl == NIX_TXSCH_LVL_TL1 && nix->tm_flags & NIX_TM_TL1_NO_SP) {
543f0b9158cSNithin Dabilpuram 		rr_prio = nix->tm_aggr_lvl_rr_prio;
5440885429cSNithin Dabilpuram 		child = 0;
5450885429cSNithin Dabilpuram 	}
5460885429cSNithin Dabilpuram 
5470885429cSNithin Dabilpuram 	plt_tm_dbg("Topology config node %s(%u)->%s(%" PRIu64 ") lvl %u, id %u"
5480885429cSNithin Dabilpuram 		   " prio_anchor %" PRIu64 " rr_prio %u (%p)",
5490885429cSNithin Dabilpuram 		   nix_tm_hwlvl2str(hw_lvl), schq, nix_tm_hwlvl2str(parent_lvl),
5500885429cSNithin Dabilpuram 		   parent, node->lvl, node->id, child, rr_prio, node);
5510885429cSNithin Dabilpuram 
5520885429cSNithin Dabilpuram 	/* Prepare Topology and Link config */
5530885429cSNithin Dabilpuram 	switch (hw_lvl) {
5540885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_SMQ:
5550885429cSNithin Dabilpuram 
5560885429cSNithin Dabilpuram 		/* Set xoff which will be cleared later */
5570885429cSNithin Dabilpuram 		reg[k] = NIX_AF_SMQX_CFG(schq);
5580885429cSNithin Dabilpuram 		regval[k] = (BIT_ULL(50) | NIX_MIN_HW_FRS |
5590885429cSNithin Dabilpuram 			     ((nix->mtu & 0xFFFF) << 8));
5606b7fcb7aSSatha Rao 		/* Maximum Vtag insertion size as a multiple of four bytes */
5616b7fcb7aSSatha Rao 		if (roc_nix->hw_vlan_ins)
5626b7fcb7aSSatha Rao 			regval[k] |= (0x2ULL << 36);
5636b7fcb7aSSatha Rao 		regval_mask[k] = ~(BIT_ULL(50) | GENMASK_ULL(6, 0) |
5646b7fcb7aSSatha Rao 				   GENMASK_ULL(23, 8) | GENMASK_ULL(38, 36));
5650885429cSNithin Dabilpuram 		k++;
5660885429cSNithin Dabilpuram 
5670885429cSNithin Dabilpuram 		/* Parent and schedule conf */
5680885429cSNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_PARENT(schq);
5690885429cSNithin Dabilpuram 		regval[k] = parent << 16;
5700885429cSNithin Dabilpuram 		k++;
5710885429cSNithin Dabilpuram 
5720885429cSNithin Dabilpuram 		break;
5730885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL4:
5740885429cSNithin Dabilpuram 		/* Parent and schedule conf */
5750885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_PARENT(schq);
5760885429cSNithin Dabilpuram 		regval[k] = parent << 16;
5770885429cSNithin Dabilpuram 		k++;
5780885429cSNithin Dabilpuram 
5790885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_TOPOLOGY(schq);
5800885429cSNithin Dabilpuram 		regval[k] = (child << 32) | (rr_prio << 1);
5810885429cSNithin Dabilpuram 		k++;
5820885429cSNithin Dabilpuram 
5830885429cSNithin Dabilpuram 		/* Configure TL4 to send to SDP channel instead of CGX/LBK */
5840885429cSNithin Dabilpuram 		if (nix->sdp_link) {
585b668d822SVeerasenareddy Burru 			relchan = nix->tx_chan_base & 0xff;
586*f665790aSDavid Marchand 			plt_tm_dbg("relchan=%u schq=%u tx_chan_cnt=%u", relchan, schq,
5878f867a87SVeerasenareddy Burru 				   nix->tx_chan_cnt);
5880885429cSNithin Dabilpuram 			reg[k] = NIX_AF_TL4X_SDP_LINK_CFG(schq);
5890885429cSNithin Dabilpuram 			regval[k] = BIT_ULL(12);
5908f867a87SVeerasenareddy Burru 			regval[k] |= BIT_ULL(13);
5912e9863fbSAkhil Goyal 			regval[k] |= (uint64_t)relchan;
5920885429cSNithin Dabilpuram 			k++;
5930885429cSNithin Dabilpuram 		}
5940885429cSNithin Dabilpuram 		break;
5950885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL3:
5960885429cSNithin Dabilpuram 		/* Parent and schedule conf */
5970885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_PARENT(schq);
5980885429cSNithin Dabilpuram 		regval[k] = parent << 16;
5990885429cSNithin Dabilpuram 		k++;
6000885429cSNithin Dabilpuram 
6010885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_TOPOLOGY(schq);
6020885429cSNithin Dabilpuram 		regval[k] = (child << 32) | (rr_prio << 1);
6030885429cSNithin Dabilpuram 		k++;
6040885429cSNithin Dabilpuram 
6050885429cSNithin Dabilpuram 		/* Link configuration */
6060885429cSNithin Dabilpuram 		if (!nix->sdp_link &&
6070885429cSNithin Dabilpuram 		    nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL3) {
6080885429cSNithin Dabilpuram 			reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
6092e9863fbSAkhil Goyal 			regval[k] = BIT_ULL(12) | (uint64_t)relchan;
6100885429cSNithin Dabilpuram 			k++;
6110885429cSNithin Dabilpuram 		}
6120885429cSNithin Dabilpuram 
6130885429cSNithin Dabilpuram 		break;
6140885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL2:
6150885429cSNithin Dabilpuram 		/* Parent and schedule conf */
6160885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_PARENT(schq);
6170885429cSNithin Dabilpuram 		regval[k] = parent << 16;
6180885429cSNithin Dabilpuram 		k++;
6190885429cSNithin Dabilpuram 
6200885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_TOPOLOGY(schq);
6210885429cSNithin Dabilpuram 		regval[k] = (child << 32) | (rr_prio << 1);
6220885429cSNithin Dabilpuram 		k++;
6230885429cSNithin Dabilpuram 
6240885429cSNithin Dabilpuram 		/* Link configuration */
6250885429cSNithin Dabilpuram 		if (!nix->sdp_link &&
6260885429cSNithin Dabilpuram 		    nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL2) {
6270885429cSNithin Dabilpuram 			reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
6282e9863fbSAkhil Goyal 			regval[k] = BIT_ULL(12) | (uint64_t)relchan;
6290885429cSNithin Dabilpuram 			k++;
6300885429cSNithin Dabilpuram 		}
6310885429cSNithin Dabilpuram 
6320885429cSNithin Dabilpuram 		break;
6330885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL1:
6340885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
6350885429cSNithin Dabilpuram 		regval[k] = (child << 32) | (rr_prio << 1 /*RR_PRIO*/);
6360885429cSNithin Dabilpuram 		k++;
6370885429cSNithin Dabilpuram 
6380885429cSNithin Dabilpuram 		break;
6390885429cSNithin Dabilpuram 	}
6400885429cSNithin Dabilpuram 
6410885429cSNithin Dabilpuram 	return k;
6420885429cSNithin Dabilpuram }
6430885429cSNithin Dabilpuram 
644902a4c02SSatha Rao static inline int
645902a4c02SSatha Rao nix_tm_default_rr_weight(struct nix *nix)
646902a4c02SSatha Rao {
647902a4c02SSatha Rao 	struct roc_nix *roc_nix = nix_priv_to_roc_nix(nix);
648902a4c02SSatha Rao 	uint32_t max_pktlen = roc_nix_max_pkt_len(roc_nix);
649902a4c02SSatha Rao 	uint32_t weight;
650902a4c02SSatha Rao 
651902a4c02SSatha Rao 	/* Reduce TX VTAG Insertions */
652902a4c02SSatha Rao 	max_pktlen -= 8;
653902a4c02SSatha Rao 	weight = max_pktlen / roc_nix->dwrr_mtu;
654902a4c02SSatha Rao 	if (max_pktlen % roc_nix->dwrr_mtu)
655902a4c02SSatha Rao 		weight += 1;
656902a4c02SSatha Rao 
657902a4c02SSatha Rao 	return weight;
658902a4c02SSatha Rao }
659902a4c02SSatha Rao 
6600885429cSNithin Dabilpuram uint8_t
661902a4c02SSatha Rao nix_tm_sched_reg_prep(struct nix *nix, struct nix_tm_node *node, volatile uint64_t *reg,
662902a4c02SSatha Rao 		      volatile uint64_t *regval)
6630885429cSNithin Dabilpuram {
6640885429cSNithin Dabilpuram 	uint64_t strict_prio = node->priority;
6650885429cSNithin Dabilpuram 	uint32_t hw_lvl = node->hw_lvl;
6660885429cSNithin Dabilpuram 	uint32_t schq = node->hw_id;
6670885429cSNithin Dabilpuram 	uint64_t rr_quantum;
6680885429cSNithin Dabilpuram 	uint8_t k = 0;
6690885429cSNithin Dabilpuram 
670902a4c02SSatha Rao 	/* If minimum weight not provided, then by default RR_QUANTUM
671902a4c02SSatha Rao 	 * should be in sync with kernel, i.e., single MTU value
672902a4c02SSatha Rao 	 */
673902a4c02SSatha Rao 	if (!node->weight)
674902a4c02SSatha Rao 		rr_quantum = nix_tm_default_rr_weight(nix);
675902a4c02SSatha Rao 	else
6766fe49f10SNithin Dabilpuram 		/* For CN9K, weight needs to be converted to quantum */
6770885429cSNithin Dabilpuram 		rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
6780885429cSNithin Dabilpuram 
6790885429cSNithin Dabilpuram 	/* For children to root, strict prio is default if either
6800885429cSNithin Dabilpuram 	 * device root is TL2 or TL1 Static Priority is disabled.
6810885429cSNithin Dabilpuram 	 */
6820885429cSNithin Dabilpuram 	if (hw_lvl == NIX_TXSCH_LVL_TL2 &&
6830885429cSNithin Dabilpuram 	    (!nix_tm_have_tl1_access(nix) || nix->tm_flags & NIX_TM_TL1_NO_SP))
684f0b9158cSNithin Dabilpuram 		strict_prio = nix->tm_aggr_lvl_rr_prio;
6850885429cSNithin Dabilpuram 
6860885429cSNithin Dabilpuram 	plt_tm_dbg("Schedule config node %s(%u) lvl %u id %u, "
6876fe49f10SNithin Dabilpuram 		   "prio 0x%" PRIx64 ", rr_quantum/rr_wt 0x%" PRIx64 " (%p)",
688902a4c02SSatha Rao 		   nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id, strict_prio,
689902a4c02SSatha Rao 		   rr_quantum, node);
6900885429cSNithin Dabilpuram 
6910885429cSNithin Dabilpuram 	switch (hw_lvl) {
6920885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_SMQ:
6930885429cSNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_SCHEDULE(schq);
6940885429cSNithin Dabilpuram 		regval[k] = (strict_prio << 24) | rr_quantum;
6950885429cSNithin Dabilpuram 		k++;
6960885429cSNithin Dabilpuram 
6970885429cSNithin Dabilpuram 		break;
6980885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL4:
6990885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_SCHEDULE(schq);
7000885429cSNithin Dabilpuram 		regval[k] = (strict_prio << 24) | rr_quantum;
7010885429cSNithin Dabilpuram 		k++;
7020885429cSNithin Dabilpuram 
7030885429cSNithin Dabilpuram 		break;
7040885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL3:
7050885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_SCHEDULE(schq);
7060885429cSNithin Dabilpuram 		regval[k] = (strict_prio << 24) | rr_quantum;
7070885429cSNithin Dabilpuram 		k++;
7080885429cSNithin Dabilpuram 
7090885429cSNithin Dabilpuram 		break;
7100885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL2:
7110885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_SCHEDULE(schq);
7120885429cSNithin Dabilpuram 		regval[k] = (strict_prio << 24) | rr_quantum;
7130885429cSNithin Dabilpuram 		k++;
7140885429cSNithin Dabilpuram 
7150885429cSNithin Dabilpuram 		break;
7160885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL1:
7170885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
7180885429cSNithin Dabilpuram 		regval[k] = rr_quantum;
7190885429cSNithin Dabilpuram 		k++;
7200885429cSNithin Dabilpuram 
7210885429cSNithin Dabilpuram 		break;
7220885429cSNithin Dabilpuram 	}
7230885429cSNithin Dabilpuram 
7240885429cSNithin Dabilpuram 	return k;
7250885429cSNithin Dabilpuram }
7260885429cSNithin Dabilpuram 
7270885429cSNithin Dabilpuram uint8_t
7280885429cSNithin Dabilpuram nix_tm_shaper_reg_prep(struct nix_tm_node *node,
7290885429cSNithin Dabilpuram 		       struct nix_tm_shaper_profile *profile,
7300885429cSNithin Dabilpuram 		       volatile uint64_t *reg, volatile uint64_t *regval)
7310885429cSNithin Dabilpuram {
7320885429cSNithin Dabilpuram 	struct nix_tm_shaper_data cir, pir;
7330885429cSNithin Dabilpuram 	uint32_t schq = node->hw_id;
7340885429cSNithin Dabilpuram 	uint64_t adjust = 0;
7350885429cSNithin Dabilpuram 	uint8_t k = 0;
7360885429cSNithin Dabilpuram 
7370885429cSNithin Dabilpuram 	nix_tm_shaper_conf_get(profile, &cir, &pir);
7380885429cSNithin Dabilpuram 
739680078faSSatha Rao 	if (profile && node->pkt_mode)
740680078faSSatha Rao 		adjust = profile->pkt_mode_adj;
7410885429cSNithin Dabilpuram 	else if (profile)
7420885429cSNithin Dabilpuram 		adjust = profile->pkt_len_adj;
7430885429cSNithin Dabilpuram 
744132dac75SNithin Dabilpuram 	adjust &= 0x1FF;
7450885429cSNithin Dabilpuram 	plt_tm_dbg("Shaper config node %s(%u) lvl %u id %u, "
7460885429cSNithin Dabilpuram 		   "pir %" PRIu64 "(%" PRIu64 "B),"
7470885429cSNithin Dabilpuram 		   " cir %" PRIu64 "(%" PRIu64 "B)"
7480885429cSNithin Dabilpuram 		   "adjust 0x%" PRIx64 "(pktmode %u) (%p)",
7490885429cSNithin Dabilpuram 		   nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id,
7500885429cSNithin Dabilpuram 		   pir.rate, pir.burst, cir.rate, cir.burst, adjust,
7510885429cSNithin Dabilpuram 		   node->pkt_mode, node);
7520885429cSNithin Dabilpuram 
7530885429cSNithin Dabilpuram 	switch (node->hw_lvl) {
7540885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_SMQ:
7550885429cSNithin Dabilpuram 		/* Configure PIR, CIR */
7560885429cSNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_PIR(schq);
7570885429cSNithin Dabilpuram 		regval[k] = (pir.rate && pir.burst) ?
7580885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&pir) | 1) :
7590885429cSNithin Dabilpuram 					  0;
7600885429cSNithin Dabilpuram 		k++;
7610885429cSNithin Dabilpuram 
7620885429cSNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_CIR(schq);
7630885429cSNithin Dabilpuram 		regval[k] = (cir.rate && cir.burst) ?
7640885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&cir) | 1) :
7650885429cSNithin Dabilpuram 					  0;
7660885429cSNithin Dabilpuram 		k++;
7670885429cSNithin Dabilpuram 
7680885429cSNithin Dabilpuram 		/* Configure RED ALG */
7690885429cSNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_SHAPE(schq);
7700885429cSNithin Dabilpuram 		regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
7710885429cSNithin Dabilpuram 			     (uint64_t)node->pkt_mode << 24);
7720885429cSNithin Dabilpuram 		k++;
7730885429cSNithin Dabilpuram 		break;
7740885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL4:
7750885429cSNithin Dabilpuram 		/* Configure PIR, CIR */
7760885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_PIR(schq);
7770885429cSNithin Dabilpuram 		regval[k] = (pir.rate && pir.burst) ?
7780885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&pir) | 1) :
7790885429cSNithin Dabilpuram 					  0;
7800885429cSNithin Dabilpuram 		k++;
7810885429cSNithin Dabilpuram 
7820885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_CIR(schq);
7830885429cSNithin Dabilpuram 		regval[k] = (cir.rate && cir.burst) ?
7840885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&cir) | 1) :
7850885429cSNithin Dabilpuram 					  0;
7860885429cSNithin Dabilpuram 		k++;
7870885429cSNithin Dabilpuram 
7880885429cSNithin Dabilpuram 		/* Configure RED algo */
7890885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_SHAPE(schq);
7900885429cSNithin Dabilpuram 		regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
7910885429cSNithin Dabilpuram 			     (uint64_t)node->pkt_mode << 24);
7920885429cSNithin Dabilpuram 		k++;
7930885429cSNithin Dabilpuram 		break;
7940885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL3:
7950885429cSNithin Dabilpuram 		/* Configure PIR, CIR */
7960885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_PIR(schq);
7970885429cSNithin Dabilpuram 		regval[k] = (pir.rate && pir.burst) ?
7980885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&pir) | 1) :
7990885429cSNithin Dabilpuram 					  0;
8000885429cSNithin Dabilpuram 		k++;
8010885429cSNithin Dabilpuram 
8020885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_CIR(schq);
8030885429cSNithin Dabilpuram 		regval[k] = (cir.rate && cir.burst) ?
8040885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&cir) | 1) :
8050885429cSNithin Dabilpuram 					  0;
8060885429cSNithin Dabilpuram 		k++;
8070885429cSNithin Dabilpuram 
8080885429cSNithin Dabilpuram 		/* Configure RED algo */
8090885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_SHAPE(schq);
8100885429cSNithin Dabilpuram 		regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
811132dac75SNithin Dabilpuram 			     (uint64_t)node->pkt_mode << 24);
8120885429cSNithin Dabilpuram 		k++;
8130885429cSNithin Dabilpuram 
8140885429cSNithin Dabilpuram 		break;
8150885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL2:
8160885429cSNithin Dabilpuram 		/* Configure PIR, CIR */
8170885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_PIR(schq);
8180885429cSNithin Dabilpuram 		regval[k] = (pir.rate && pir.burst) ?
8190885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&pir) | 1) :
8200885429cSNithin Dabilpuram 					  0;
8210885429cSNithin Dabilpuram 		k++;
8220885429cSNithin Dabilpuram 
8230885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_CIR(schq);
8240885429cSNithin Dabilpuram 		regval[k] = (cir.rate && cir.burst) ?
8250885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&cir) | 1) :
8260885429cSNithin Dabilpuram 					  0;
8270885429cSNithin Dabilpuram 		k++;
8280885429cSNithin Dabilpuram 
8290885429cSNithin Dabilpuram 		/* Configure RED algo */
8300885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_SHAPE(schq);
8310885429cSNithin Dabilpuram 		regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
8320885429cSNithin Dabilpuram 			     (uint64_t)node->pkt_mode << 24);
8330885429cSNithin Dabilpuram 		k++;
8340885429cSNithin Dabilpuram 
8350885429cSNithin Dabilpuram 		break;
8360885429cSNithin Dabilpuram 	case NIX_TXSCH_LVL_TL1:
8370885429cSNithin Dabilpuram 		/* Configure CIR */
8380885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL1X_CIR(schq);
8390885429cSNithin Dabilpuram 		regval[k] = (cir.rate && cir.burst) ?
8400885429cSNithin Dabilpuram 					  (nix_tm_shaper2regval(&cir) | 1) :
8410885429cSNithin Dabilpuram 					  0;
8420885429cSNithin Dabilpuram 		k++;
8430885429cSNithin Dabilpuram 
8440885429cSNithin Dabilpuram 		/* Configure length disable and adjust */
8450885429cSNithin Dabilpuram 		reg[k] = NIX_AF_TL1X_SHAPE(schq);
8460885429cSNithin Dabilpuram 		regval[k] = (adjust | (uint64_t)node->pkt_mode << 24);
8470885429cSNithin Dabilpuram 		k++;
8480885429cSNithin Dabilpuram 		break;
8490885429cSNithin Dabilpuram 	}
8500885429cSNithin Dabilpuram 
8510885429cSNithin Dabilpuram 	return k;
8520885429cSNithin Dabilpuram }
8530885429cSNithin Dabilpuram 
8540885429cSNithin Dabilpuram uint8_t
85505d727e8SNithin Dabilpuram nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
85605d727e8SNithin Dabilpuram 		    volatile uint64_t *reg, volatile uint64_t *regval)
85705d727e8SNithin Dabilpuram {
85805d727e8SNithin Dabilpuram 	uint32_t hw_lvl = node->hw_lvl;
85905d727e8SNithin Dabilpuram 	uint32_t schq = node->hw_id;
86005d727e8SNithin Dabilpuram 	uint8_t k = 0;
86105d727e8SNithin Dabilpuram 
86205d727e8SNithin Dabilpuram 	plt_tm_dbg("sw xoff config node %s(%u) lvl %u id %u, enable %u (%p)",
86305d727e8SNithin Dabilpuram 		   nix_tm_hwlvl2str(hw_lvl), schq, node->lvl, node->id, enable,
86405d727e8SNithin Dabilpuram 		   node);
86505d727e8SNithin Dabilpuram 
86605d727e8SNithin Dabilpuram 	regval[k] = enable;
86705d727e8SNithin Dabilpuram 
86805d727e8SNithin Dabilpuram 	switch (hw_lvl) {
86905d727e8SNithin Dabilpuram 	case NIX_TXSCH_LVL_MDQ:
87005d727e8SNithin Dabilpuram 		reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
87105d727e8SNithin Dabilpuram 		k++;
87205d727e8SNithin Dabilpuram 		break;
87305d727e8SNithin Dabilpuram 	case NIX_TXSCH_LVL_TL4:
87405d727e8SNithin Dabilpuram 		reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
87505d727e8SNithin Dabilpuram 		k++;
87605d727e8SNithin Dabilpuram 		break;
87705d727e8SNithin Dabilpuram 	case NIX_TXSCH_LVL_TL3:
87805d727e8SNithin Dabilpuram 		reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
87905d727e8SNithin Dabilpuram 		k++;
88005d727e8SNithin Dabilpuram 		break;
88105d727e8SNithin Dabilpuram 	case NIX_TXSCH_LVL_TL2:
88205d727e8SNithin Dabilpuram 		reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
88305d727e8SNithin Dabilpuram 		k++;
88405d727e8SNithin Dabilpuram 		break;
88505d727e8SNithin Dabilpuram 	case NIX_TXSCH_LVL_TL1:
88605d727e8SNithin Dabilpuram 		reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
88705d727e8SNithin Dabilpuram 		k++;
88805d727e8SNithin Dabilpuram 		break;
88905d727e8SNithin Dabilpuram 	default:
89005d727e8SNithin Dabilpuram 		break;
89105d727e8SNithin Dabilpuram 	}
89205d727e8SNithin Dabilpuram 
89305d727e8SNithin Dabilpuram 	return k;
89405d727e8SNithin Dabilpuram }
895be3009e7SNithin Dabilpuram 
896c2460d14SSatha Rao /* Search for min rate in topology */
897c2460d14SSatha Rao uint64_t
898c2460d14SSatha Rao nix_tm_shaper_profile_rate_min(struct nix *nix)
899c2460d14SSatha Rao {
900c2460d14SSatha Rao 	struct nix_tm_shaper_profile *profile;
901c2460d14SSatha Rao 	uint64_t rate_min = 1E9; /* 1 Gbps */
902c2460d14SSatha Rao 
903c2460d14SSatha Rao 	TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
904c2460d14SSatha Rao 		if (profile->peak.rate && profile->peak.rate < rate_min)
905c2460d14SSatha Rao 			rate_min = profile->peak.rate;
906c2460d14SSatha Rao 
907c2460d14SSatha Rao 		if (profile->commit.rate && profile->commit.rate < rate_min)
908c2460d14SSatha Rao 			rate_min = profile->commit.rate;
909c2460d14SSatha Rao 	}
910c2460d14SSatha Rao 	return rate_min;
911c2460d14SSatha Rao }
912c2460d14SSatha Rao 
913be3009e7SNithin Dabilpuram uint16_t
914be3009e7SNithin Dabilpuram nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
915be3009e7SNithin Dabilpuram {
916be3009e7SNithin Dabilpuram 	uint32_t pos = 0, start_pos = 0;
917be3009e7SNithin Dabilpuram 	struct plt_bitmap *bmp;
918be3009e7SNithin Dabilpuram 	uint16_t count = 0;
919be3009e7SNithin Dabilpuram 	uint64_t slab = 0;
920be3009e7SNithin Dabilpuram 
921be3009e7SNithin Dabilpuram 	bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
922be3009e7SNithin Dabilpuram 	plt_bitmap_scan_init(bmp);
923be3009e7SNithin Dabilpuram 
924be3009e7SNithin Dabilpuram 	if (!plt_bitmap_scan(bmp, &pos, &slab))
925be3009e7SNithin Dabilpuram 		return count;
926be3009e7SNithin Dabilpuram 
927be3009e7SNithin Dabilpuram 	/* Count bit set */
928be3009e7SNithin Dabilpuram 	start_pos = pos;
929be3009e7SNithin Dabilpuram 	do {
930354bf671SJerin Jacob 		count += plt_popcount64(slab);
931be3009e7SNithin Dabilpuram 		if (!plt_bitmap_scan(bmp, &pos, &slab))
932be3009e7SNithin Dabilpuram 			break;
933be3009e7SNithin Dabilpuram 	} while (pos != start_pos);
934be3009e7SNithin Dabilpuram 
935be3009e7SNithin Dabilpuram 	return count;
936be3009e7SNithin Dabilpuram }
937be3009e7SNithin Dabilpuram 
938df405df9SNithin Dabilpuram uint16_t
939df405df9SNithin Dabilpuram nix_tm_resource_estimate(struct nix *nix, uint16_t *schq_contig, uint16_t *schq,
940df405df9SNithin Dabilpuram 			 enum roc_nix_tm_tree tree)
941df405df9SNithin Dabilpuram {
942df405df9SNithin Dabilpuram 	struct nix_tm_node_list *list;
943df405df9SNithin Dabilpuram 	uint8_t contig_cnt, hw_lvl;
944df405df9SNithin Dabilpuram 	struct nix_tm_node *parent;
945df405df9SNithin Dabilpuram 	uint16_t cnt = 0, avail;
946df405df9SNithin Dabilpuram 
947df405df9SNithin Dabilpuram 	list = nix_tm_node_list(nix, tree);
948df405df9SNithin Dabilpuram 	/* Walk through parents from TL1..TL4 */
949df405df9SNithin Dabilpuram 	for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
950df405df9SNithin Dabilpuram 		TAILQ_FOREACH(parent, list, node) {
951df405df9SNithin Dabilpuram 			if (hw_lvl != parent->hw_lvl)
952df405df9SNithin Dabilpuram 				continue;
953df405df9SNithin Dabilpuram 
954df405df9SNithin Dabilpuram 			/* Skip accounting for children whose
955df405df9SNithin Dabilpuram 			 * parent does not indicate so.
956df405df9SNithin Dabilpuram 			 */
957df405df9SNithin Dabilpuram 			if (!parent->child_realloc)
958df405df9SNithin Dabilpuram 				continue;
959df405df9SNithin Dabilpuram 
960df405df9SNithin Dabilpuram 			/* Count children needed */
961df405df9SNithin Dabilpuram 			schq[hw_lvl - 1] += parent->rr_num;
962df405df9SNithin Dabilpuram 			if (parent->max_prio != UINT32_MAX) {
963df405df9SNithin Dabilpuram 				contig_cnt = parent->max_prio + 1;
964df405df9SNithin Dabilpuram 				schq_contig[hw_lvl - 1] += contig_cnt;
965df405df9SNithin Dabilpuram 				/* When we have SP + DWRR at a parent,
966df405df9SNithin Dabilpuram 				 * we will always have a spare schq at rr prio
967df405df9SNithin Dabilpuram 				 * location in contiguous queues. Hence reduce
968df405df9SNithin Dabilpuram 				 * discontiguous count by 1.
969df405df9SNithin Dabilpuram 				 */
970df405df9SNithin Dabilpuram 				if (parent->max_prio > 0 && parent->rr_num)
971df405df9SNithin Dabilpuram 					schq[hw_lvl - 1] -= 1;
972df405df9SNithin Dabilpuram 			}
973df405df9SNithin Dabilpuram 		}
974df405df9SNithin Dabilpuram 	}
975df405df9SNithin Dabilpuram 
976df405df9SNithin Dabilpuram 	schq[nix->tm_root_lvl] = 1;
977df405df9SNithin Dabilpuram 	if (!nix_tm_have_tl1_access(nix))
978df405df9SNithin Dabilpuram 		schq[NIX_TXSCH_LVL_TL1] = 1;
979df405df9SNithin Dabilpuram 
980df405df9SNithin Dabilpuram 	/* Now check for existing resources */
981df405df9SNithin Dabilpuram 	for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
982df405df9SNithin Dabilpuram 		avail = nix_tm_resource_avail(nix, hw_lvl, false);
983df405df9SNithin Dabilpuram 		if (schq[hw_lvl] <= avail)
984df405df9SNithin Dabilpuram 			schq[hw_lvl] = 0;
985df405df9SNithin Dabilpuram 		else
986df405df9SNithin Dabilpuram 			schq[hw_lvl] -= avail;
987df405df9SNithin Dabilpuram 
988df405df9SNithin Dabilpuram 		/* For contiguous queues, realloc everything */
989df405df9SNithin Dabilpuram 		avail = nix_tm_resource_avail(nix, hw_lvl, true);
990df405df9SNithin Dabilpuram 		if (schq_contig[hw_lvl] <= avail)
991df405df9SNithin Dabilpuram 			schq_contig[hw_lvl] = 0;
992df405df9SNithin Dabilpuram 
993df405df9SNithin Dabilpuram 		cnt += schq[hw_lvl];
994df405df9SNithin Dabilpuram 		cnt += schq_contig[hw_lvl];
995df405df9SNithin Dabilpuram 
996df405df9SNithin Dabilpuram 		plt_tm_dbg("Estimate resources needed for %s: dis %u cont %u",
997df405df9SNithin Dabilpuram 			   nix_tm_hwlvl2str(hw_lvl), schq[hw_lvl],
998df405df9SNithin Dabilpuram 			   schq_contig[hw_lvl]);
999df405df9SNithin Dabilpuram 	}
1000df405df9SNithin Dabilpuram 
1001df405df9SNithin Dabilpuram 	return cnt;
1002df405df9SNithin Dabilpuram }
1003df405df9SNithin Dabilpuram 
1004fcdef46bSNithin Dabilpuram uint16_t
1005fcdef46bSNithin Dabilpuram roc_nix_tm_leaf_cnt(struct roc_nix *roc_nix)
1006fcdef46bSNithin Dabilpuram {
1007fcdef46bSNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1008fcdef46bSNithin Dabilpuram 	struct nix_tm_node_list *list;
1009fcdef46bSNithin Dabilpuram 	struct nix_tm_node *node;
1010fcdef46bSNithin Dabilpuram 	uint16_t leaf_cnt = 0;
1011fcdef46bSNithin Dabilpuram 
1012fcdef46bSNithin Dabilpuram 	/* Count leafs only in user list */
1013fcdef46bSNithin Dabilpuram 	list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
1014fcdef46bSNithin Dabilpuram 	TAILQ_FOREACH(node, list, node) {
1015fcdef46bSNithin Dabilpuram 		if (node->id < nix->nb_tx_queues)
1016fcdef46bSNithin Dabilpuram 			leaf_cnt++;
1017fcdef46bSNithin Dabilpuram 	}
1018fcdef46bSNithin Dabilpuram 
1019fcdef46bSNithin Dabilpuram 	return leaf_cnt;
1020fcdef46bSNithin Dabilpuram }
1021fcdef46bSNithin Dabilpuram 
1022be3009e7SNithin Dabilpuram int
1023be3009e7SNithin Dabilpuram roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
1024be3009e7SNithin Dabilpuram {
1025be3009e7SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1026be3009e7SNithin Dabilpuram 	struct nix_tm_node *node;
1027be3009e7SNithin Dabilpuram 
1028be3009e7SNithin Dabilpuram 	node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
1029be3009e7SNithin Dabilpuram 	if (!node)
1030be3009e7SNithin Dabilpuram 		return NIX_ERR_TM_INVALID_NODE;
1031be3009e7SNithin Dabilpuram 
1032be3009e7SNithin Dabilpuram 	return node->lvl;
1033be3009e7SNithin Dabilpuram }
1034be3009e7SNithin Dabilpuram 
1035be3009e7SNithin Dabilpuram struct roc_nix_tm_node *
1036be3009e7SNithin Dabilpuram roc_nix_tm_node_get(struct roc_nix *roc_nix, uint32_t node_id)
1037be3009e7SNithin Dabilpuram {
1038be3009e7SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1039be3009e7SNithin Dabilpuram 	struct nix_tm_node *node;
1040be3009e7SNithin Dabilpuram 
1041be3009e7SNithin Dabilpuram 	node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
1042be3009e7SNithin Dabilpuram 	return (struct roc_nix_tm_node *)node;
1043be3009e7SNithin Dabilpuram }
1044be3009e7SNithin Dabilpuram 
1045be3009e7SNithin Dabilpuram struct roc_nix_tm_node *
1046be3009e7SNithin Dabilpuram roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev)
1047be3009e7SNithin Dabilpuram {
1048be3009e7SNithin Dabilpuram 	struct nix_tm_node *prev = (struct nix_tm_node *)__prev;
1049be3009e7SNithin Dabilpuram 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1050be3009e7SNithin Dabilpuram 	struct nix_tm_node_list *list;
1051be3009e7SNithin Dabilpuram 
1052be3009e7SNithin Dabilpuram 	list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
1053be3009e7SNithin Dabilpuram 
1054be3009e7SNithin Dabilpuram 	/* HEAD of the list */
1055be3009e7SNithin Dabilpuram 	if (!prev)
1056be3009e7SNithin Dabilpuram 		return (struct roc_nix_tm_node *)TAILQ_FIRST(list);
1057be3009e7SNithin Dabilpuram 
1058be3009e7SNithin Dabilpuram 	/* Next entry */
1059be3009e7SNithin Dabilpuram 	if (prev->tree != ROC_NIX_TM_USER)
1060be3009e7SNithin Dabilpuram 		return NULL;
1061be3009e7SNithin Dabilpuram 
1062be3009e7SNithin Dabilpuram 	return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
1063be3009e7SNithin Dabilpuram }
1064be3009e7SNithin Dabilpuram 
1065c2460d14SSatha Rao struct roc_nix_tm_shaper_profile *
1066c2460d14SSatha Rao roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id)
1067c2460d14SSatha Rao {
1068c2460d14SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1069c2460d14SSatha Rao 	struct nix_tm_shaper_profile *profile;
1070c2460d14SSatha Rao 
1071c2460d14SSatha Rao 	profile = nix_tm_shaper_profile_search(nix, profile_id);
1072c2460d14SSatha Rao 	return (struct roc_nix_tm_shaper_profile *)profile;
1073c2460d14SSatha Rao }
1074c2460d14SSatha Rao 
1075c2460d14SSatha Rao struct roc_nix_tm_shaper_profile *
1076c2460d14SSatha Rao roc_nix_tm_shaper_profile_next(struct roc_nix *roc_nix,
1077c2460d14SSatha Rao 			       struct roc_nix_tm_shaper_profile *__prev)
1078c2460d14SSatha Rao {
1079c2460d14SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1080c2460d14SSatha Rao 	struct nix_tm_shaper_profile_list *list;
1081c2460d14SSatha Rao 	struct nix_tm_shaper_profile *prev;
1082c2460d14SSatha Rao 
1083c2460d14SSatha Rao 	prev = (struct nix_tm_shaper_profile *)__prev;
1084c2460d14SSatha Rao 	list = &nix->shaper_profile_list;
1085c2460d14SSatha Rao 
1086c2460d14SSatha Rao 	/* HEAD of the list */
1087c2460d14SSatha Rao 	if (!prev)
1088c2460d14SSatha Rao 		return (struct roc_nix_tm_shaper_profile *)TAILQ_FIRST(list);
1089c2460d14SSatha Rao 
1090c2460d14SSatha Rao 	return (struct roc_nix_tm_shaper_profile *)TAILQ_NEXT(prev, shaper);
1091c2460d14SSatha Rao }
1092c2460d14SSatha Rao 
1093be3009e7SNithin Dabilpuram struct nix_tm_node *
1094be3009e7SNithin Dabilpuram nix_tm_node_alloc(void)
1095be3009e7SNithin Dabilpuram {
1096be3009e7SNithin Dabilpuram 	struct nix_tm_node *node;
1097be3009e7SNithin Dabilpuram 
1098be3009e7SNithin Dabilpuram 	node = plt_zmalloc(sizeof(struct nix_tm_node), 0);
1099be3009e7SNithin Dabilpuram 	if (!node)
1100be3009e7SNithin Dabilpuram 		return NULL;
1101be3009e7SNithin Dabilpuram 
1102be3009e7SNithin Dabilpuram 	node->free_fn = plt_free;
1103be3009e7SNithin Dabilpuram 	return node;
1104be3009e7SNithin Dabilpuram }
1105be3009e7SNithin Dabilpuram 
1106be3009e7SNithin Dabilpuram void
1107be3009e7SNithin Dabilpuram nix_tm_node_free(struct nix_tm_node *node)
1108be3009e7SNithin Dabilpuram {
1109be3009e7SNithin Dabilpuram 	if (!node || node->free_fn == NULL)
1110be3009e7SNithin Dabilpuram 		return;
1111be3009e7SNithin Dabilpuram 
1112be3009e7SNithin Dabilpuram 	(node->free_fn)(node);
1113be3009e7SNithin Dabilpuram }
1114c2460d14SSatha Rao 
1115c2460d14SSatha Rao struct nix_tm_shaper_profile *
1116c2460d14SSatha Rao nix_tm_shaper_profile_alloc(void)
1117c2460d14SSatha Rao {
1118c2460d14SSatha Rao 	struct nix_tm_shaper_profile *profile;
1119c2460d14SSatha Rao 
1120c2460d14SSatha Rao 	profile = plt_zmalloc(sizeof(struct nix_tm_shaper_profile), 0);
1121c2460d14SSatha Rao 	if (!profile)
1122c2460d14SSatha Rao 		return NULL;
1123c2460d14SSatha Rao 
1124c2460d14SSatha Rao 	profile->free_fn = plt_free;
1125c2460d14SSatha Rao 	return profile;
1126c2460d14SSatha Rao }
1127c2460d14SSatha Rao 
1128c2460d14SSatha Rao void
1129c2460d14SSatha Rao nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile)
1130c2460d14SSatha Rao {
1131c2460d14SSatha Rao 	if (!profile || !profile->free_fn)
1132c2460d14SSatha Rao 		return;
1133c2460d14SSatha Rao 
1134c2460d14SSatha Rao 	(profile->free_fn)(profile);
1135c2460d14SSatha Rao }
11366b7fcb7aSSatha Rao 
11376b7fcb7aSSatha Rao int
11386b7fcb7aSSatha Rao roc_nix_tm_node_stats_get(struct roc_nix *roc_nix, uint32_t node_id, bool clear,
11396b7fcb7aSSatha Rao 			  struct roc_nix_tm_node_stats *n_stats)
11406b7fcb7aSSatha Rao {
11416b7fcb7aSSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
11426b7fcb7aSSatha Rao 	struct mbox *mbox = (&nix->dev)->mbox;
11436b7fcb7aSSatha Rao 	struct nix_txschq_config *req, *rsp;
11446b7fcb7aSSatha Rao 	struct nix_tm_node *node;
11456b7fcb7aSSatha Rao 	uint32_t schq;
11466b7fcb7aSSatha Rao 	int rc, i;
11476b7fcb7aSSatha Rao 
11486b7fcb7aSSatha Rao 	node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
11496b7fcb7aSSatha Rao 	if (!node)
11506b7fcb7aSSatha Rao 		return NIX_ERR_TM_INVALID_NODE;
11516b7fcb7aSSatha Rao 
11526b7fcb7aSSatha Rao 	if (node->hw_lvl != NIX_TXSCH_LVL_TL1)
11536b7fcb7aSSatha Rao 		return NIX_ERR_OP_NOTSUP;
11546b7fcb7aSSatha Rao 
1155f9dbd4a5SSatha Rao 	/* Check if node has HW resource */
1156f9dbd4a5SSatha Rao 	if (!(node->flags & NIX_TM_NODE_HWRES))
1157f9dbd4a5SSatha Rao 		return 0;
1158f9dbd4a5SSatha Rao 
11596b7fcb7aSSatha Rao 	schq = node->hw_id;
11606b7fcb7aSSatha Rao 	/* Skip fetch if not requested */
11616b7fcb7aSSatha Rao 	if (!n_stats)
11626b7fcb7aSSatha Rao 		goto clear_stats;
11636b7fcb7aSSatha Rao 
11646b7fcb7aSSatha Rao 	memset(n_stats, 0, sizeof(struct roc_nix_tm_node_stats));
11656b7fcb7aSSatha Rao 
116644a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
11676b7fcb7aSSatha Rao 	req->read = 1;
11686b7fcb7aSSatha Rao 	req->lvl = NIX_TXSCH_LVL_TL1;
11696b7fcb7aSSatha Rao 
11706b7fcb7aSSatha Rao 	i = 0;
11716b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_DROPPED_PACKETS(schq);
11726b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_DROPPED_BYTES(schq);
11736b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_GREEN_PACKETS(schq);
11746b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_GREEN_BYTES(schq);
11756b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_YELLOW_PACKETS(schq);
11766b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_YELLOW_BYTES(schq);
11776b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_RED_PACKETS(schq);
11786b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_RED_BYTES(schq);
11796b7fcb7aSSatha Rao 	req->num_regs = i;
11806b7fcb7aSSatha Rao 
11816b7fcb7aSSatha Rao 	rc = mbox_process_msg(mbox, (void **)&rsp);
118244a9307cSRakesh Kudurumalla 	if (rc) {
118344a9307cSRakesh Kudurumalla 		mbox_put(mbox);
11846b7fcb7aSSatha Rao 		return rc;
118544a9307cSRakesh Kudurumalla 	}
11866b7fcb7aSSatha Rao 
11876b7fcb7aSSatha Rao 	/* Return stats */
11886b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_PKTS_DROPPED] = rsp->regval[0];
11896b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_BYTES_DROPPED] = rsp->regval[1];
11906b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_GREEN_PKTS] = rsp->regval[2];
11916b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_GREEN_BYTES] = rsp->regval[3];
11926b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_YELLOW_PKTS] = rsp->regval[4];
11936b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_YELLOW_BYTES] = rsp->regval[5];
11946b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_RED_PKTS] = rsp->regval[6];
11956b7fcb7aSSatha Rao 	n_stats->stats[ROC_NIX_TM_NODE_RED_BYTES] = rsp->regval[7];
119644a9307cSRakesh Kudurumalla 	mbox_put(mbox);
11976b7fcb7aSSatha Rao 
11986b7fcb7aSSatha Rao clear_stats:
11996b7fcb7aSSatha Rao 	if (!clear)
12006b7fcb7aSSatha Rao 		return 0;
12016b7fcb7aSSatha Rao 
12026b7fcb7aSSatha Rao 	/* Clear all the stats */
120344a9307cSRakesh Kudurumalla 	req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
12046b7fcb7aSSatha Rao 	req->lvl = NIX_TXSCH_LVL_TL1;
12056b7fcb7aSSatha Rao 	i = 0;
12066b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_DROPPED_PACKETS(schq);
12076b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_DROPPED_BYTES(schq);
12086b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_GREEN_PACKETS(schq);
12096b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_GREEN_BYTES(schq);
12106b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_YELLOW_PACKETS(schq);
12116b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_YELLOW_BYTES(schq);
12126b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_RED_PACKETS(schq);
12136b7fcb7aSSatha Rao 	req->reg[i++] = NIX_AF_TL1X_RED_BYTES(schq);
12146b7fcb7aSSatha Rao 	req->num_regs = i;
12156b7fcb7aSSatha Rao 
121644a9307cSRakesh Kudurumalla 	rc = mbox_process_msg(mbox, (void **)&rsp);
121744a9307cSRakesh Kudurumalla 	mbox_put(mbox);
121844a9307cSRakesh Kudurumalla 	return rc;
12196b7fcb7aSSatha Rao }
1220f9dbd4a5SSatha Rao 
1221f9dbd4a5SSatha Rao bool
1222f9dbd4a5SSatha Rao roc_nix_tm_is_user_hierarchy_enabled(struct roc_nix *roc_nix)
1223f9dbd4a5SSatha Rao {
1224f9dbd4a5SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1225f9dbd4a5SSatha Rao 
1226f9dbd4a5SSatha Rao 	if ((nix->tm_flags & NIX_TM_HIERARCHY_ENA) &&
1227f9dbd4a5SSatha Rao 	    (nix->tm_tree == ROC_NIX_TM_USER))
1228f9dbd4a5SSatha Rao 		return true;
1229f9dbd4a5SSatha Rao 	return false;
1230f9dbd4a5SSatha Rao }
1231f9dbd4a5SSatha Rao 
1232f9dbd4a5SSatha Rao int
1233f9dbd4a5SSatha Rao roc_nix_tm_tree_type_get(struct roc_nix *roc_nix)
1234f9dbd4a5SSatha Rao {
1235f9dbd4a5SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1236f9dbd4a5SSatha Rao 
1237f9dbd4a5SSatha Rao 	return nix->tm_tree;
1238f9dbd4a5SSatha Rao }
1239f9dbd4a5SSatha Rao 
1240f9dbd4a5SSatha Rao int
1241f9dbd4a5SSatha Rao roc_nix_tm_max_prio(struct roc_nix *roc_nix, int lvl)
1242f9dbd4a5SSatha Rao {
1243f9dbd4a5SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1244f9dbd4a5SSatha Rao 	int hw_lvl = nix_tm_lvl2nix(nix, lvl);
1245f9dbd4a5SSatha Rao 
1246f9dbd4a5SSatha Rao 	return nix_tm_max_prio(nix, hw_lvl);
1247f9dbd4a5SSatha Rao }
1248f9dbd4a5SSatha Rao 
1249f9dbd4a5SSatha Rao int
1250f9dbd4a5SSatha Rao roc_nix_tm_lvl_is_leaf(struct roc_nix *roc_nix, int lvl)
1251f9dbd4a5SSatha Rao {
1252f9dbd4a5SSatha Rao 	return nix_tm_is_leaf(roc_nix_to_nix_priv(roc_nix), lvl);
1253f9dbd4a5SSatha Rao }
1254f9dbd4a5SSatha Rao 
1255f9dbd4a5SSatha Rao void
1256f9dbd4a5SSatha Rao roc_nix_tm_shaper_default_red_algo(struct roc_nix_tm_node *node,
1257f9dbd4a5SSatha Rao 				   struct roc_nix_tm_shaper_profile *roc_prof)
1258f9dbd4a5SSatha Rao {
1259f9dbd4a5SSatha Rao 	struct nix_tm_node *tm_node = (struct nix_tm_node *)node;
1260f9dbd4a5SSatha Rao 	struct nix_tm_shaper_profile *profile;
1261f9dbd4a5SSatha Rao 	struct nix_tm_shaper_data cir, pir;
1262f9dbd4a5SSatha Rao 
126380053371SSatha Rao 	if (!roc_prof)
126480053371SSatha Rao 		return;
126580053371SSatha Rao 
1266f9dbd4a5SSatha Rao 	profile = (struct nix_tm_shaper_profile *)roc_prof->reserved;
126780053371SSatha Rao 	tm_node->red_algo = roc_prof->red_algo;
1268f9dbd4a5SSatha Rao 
1269f9dbd4a5SSatha Rao 	/* C0 doesn't support STALL when both PIR & CIR are enabled */
1270608f11e3SSatha Rao 	if (roc_model_is_cn96_cx() || roc_model_is_cnf95xxn_a0() || roc_model_is_cnf95xxo_a0() ||
1271608f11e3SSatha Rao 	    roc_model_is_cnf95xxn_a1() || roc_model_is_cnf95xxn_b0()) {
1272f9dbd4a5SSatha Rao 		nix_tm_shaper_conf_get(profile, &cir, &pir);
1273f9dbd4a5SSatha Rao 
1274f9dbd4a5SSatha Rao 		if (pir.rate && cir.rate)
1275f9dbd4a5SSatha Rao 			tm_node->red_algo = NIX_REDALG_DISCARD;
1276f9dbd4a5SSatha Rao 	}
1277f9dbd4a5SSatha Rao }
1278f9dbd4a5SSatha Rao 
1279f9dbd4a5SSatha Rao int
1280f9dbd4a5SSatha Rao roc_nix_tm_lvl_cnt_get(struct roc_nix *roc_nix)
1281f9dbd4a5SSatha Rao {
1282f9dbd4a5SSatha Rao 	if (nix_tm_have_tl1_access(roc_nix_to_nix_priv(roc_nix)))
1283f9dbd4a5SSatha Rao 		return NIX_TXSCH_LVL_CNT;
1284f9dbd4a5SSatha Rao 
1285f9dbd4a5SSatha Rao 	return (NIX_TXSCH_LVL_CNT - 1);
1286f9dbd4a5SSatha Rao }
1287f9dbd4a5SSatha Rao 
1288f9dbd4a5SSatha Rao int
1289f9dbd4a5SSatha Rao roc_nix_tm_lvl_have_link_access(struct roc_nix *roc_nix, int lvl)
1290f9dbd4a5SSatha Rao {
1291f9dbd4a5SSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1292f9dbd4a5SSatha Rao 
1293f9dbd4a5SSatha Rao 	if (nix_tm_lvl2nix(nix, lvl) == NIX_TXSCH_LVL_TL1)
1294f9dbd4a5SSatha Rao 		return 1;
1295f9dbd4a5SSatha Rao 
1296f9dbd4a5SSatha Rao 	return 0;
1297f9dbd4a5SSatha Rao }
1298