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