pfc.c (40134B)
1 2 /* 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * Implementation for PFC SOC functions 9 */ 10 #if defined(BCM_TOMAHAWK3_SUPPORT) 11 #include <soc/pfc.h> 12 #include <soc/feature.h> 13 #include <soc/drv.h> 14 #include <soc/scache.h> 15 #include <soc/debug.h> 16 #include <soc/tomahawk.h> 17 #include <soc/dma.h> 18 #include <soc/mmu_config.h> 19 #include <soc/error.h> 20 21 #define _TH3_PFC_PRIORITY_GROUP_NUM 8 22 #define _TH3_PFC_EB_GROUP_NUM 9 23 24 #define _TH3_PFC_PRIORITY_MAX_INDEX 7 25 #define _TH3_PFC_INDEX_INVALID -1 26 27 #define _TH3_PFC_COS_NUM_MASK_OFFSET 12 /* total 12 cos using bits[11:0]*/ 28 29 typedef struct _soc_th3_pfc_eb_group_config_s { 30 int opt_group[TH3_PFC_COS_NUM]; /* PFC optimized COS */ 31 int eb_group[TH3_PFC_COS_NUM]; /* COS to EB mapping */ 32 uint8 eb_group_sp[_TH3_PFC_EB_GROUP_NUM]; /* EB group Scheduling Policy 33 * 1: Static Priority 34 * 0: Round Robin 35 */ 36 uint8 eb_group_opt[_TH3_PFC_EB_GROUP_NUM]; /* 1, EB group is optimized */ 37 int mmuq_eb_group[TH3_PFC_MMU_QUEUE_NUM]; /* MMU queue EB group mapping */ 38 } _soc_th3_pfc_eb_group_config_t; 39 40 typedef enum _soc_th3_pfc_port_speed_id_e { 41 42 _SOC_TH3_PFC_PORT_SPEED_50G = 0, 43 _SOC_TH3_PFC_PORT_SPEED_100G = 1, 44 _SOC_TH3_PFC_PORT_SPEED_200G = 2, 45 _SOC_TH3_PFC_PORT_SPEED_400G = 3, 46 _SOC_TH3_PFCPORT_SPEED_NUM = 4 47 48 } _SOC_th3_pfc_port_speed_id_t; 49 50 static const int opt_group_num_flexport[4][4] = { 51 {2, 3, 4, 4}, 52 {2, 3, 4, 4}, 53 {1, 2, 3, 3}, 54 {1, 2, 3, 3}, 55 }; 56 static const int magt_opt_group_num_flexport[4] = {4, 4, 3, 3}; 57 58 STATIC int 59 _soc_th3_pfc_mtu_encoding_get(int unit, int mtu_size) 60 { 61 int mtu_id; 62 63 if (mtu_size <= 1024) { /* < 1K */ 64 mtu_id = 0; 65 } 66 else if (mtu_size <= 2150) { /* < 2.1K */ 67 mtu_id = 1; 68 } 69 else if (mtu_size <= 4196) {/* < 4K */ 70 mtu_id = 2; 71 } 72 else if (mtu_size <= 9416) {/* < 9K */ 73 mtu_id = 3; 74 } 75 else { 76 mtu_id = _TH3_PFC_INDEX_INVALID; 77 } 78 return mtu_id; 79 } 80 81 STATIC int 82 _soc_th3_pfc_speed_encoding_get(int unit, int speed) 83 { 84 int speed_id; 85 86 if (speed < 50000) { 87 speed = 50000; 88 } 89 90 switch(speed) { 91 case 50000: 92 speed_id = _SOC_TH3_PFC_PORT_SPEED_50G; 93 break; 94 case 100000: 95 speed_id = _SOC_TH3_PFC_PORT_SPEED_100G; 96 break; 97 case 200000: 98 speed_id = _SOC_TH3_PFC_PORT_SPEED_200G; 99 break; 100 case 400000: 101 speed_id = _SOC_TH3_PFC_PORT_SPEED_400G; 102 break; 103 default: 104 speed_id = -1; 105 } 106 107 return speed_id; 108 } 109 110 STATIC void 111 _soc_th3_pfc_eb_group_config_t_init(_soc_th3_pfc_eb_group_config_t *config) 112 { 113 int i; 114 sal_memset(config, 0, sizeof(_soc_th3_pfc_eb_group_config_t)); 115 for (i = 0; i < TH3_PFC_COS_NUM; i++) { 116 config->eb_group[i] = _TH3_PFC_INDEX_INVALID; 117 } 118 } 119 120 STATIC void 121 _soc_th3_print_pfc_sched_profile_info (int unit, int profile_id, 122 _soc_th3_pfc_eb_group_config_t *eb_config) 123 { 124 int max_cos = 0; 125 int cos, idx, l0_idx = 0; 126 int mmuq0, mmuq1; 127 int fc_only_uc, sp; 128 int ebg_grp0, ebg_grp1, pfc_opt_grp, ebg_cos; 129 int sp0, sp1; 130 131 max_cos = soc_tomahawk3_get_sched_profile_max_cos(unit, profile_id); 132 133 LOG_VERBOSE(BSL_LS_SOC_MMU, (BSL_META_U(unit, 134 " Cos MMUQ0 MMUQ1 FC_UC SP PFC_opt " 135 "EB_grp(cos) EB_group0 EB_group1 SP(0) SP(1)\n"))); 136 137 for (cos = max_cos; cos >= 0; cos--) { 138 for (idx = 0; idx < SOC_TH3_NUM_GP_QUEUES; idx++) { 139 if (th3_sched_profile_info[unit][profile_id][idx].cos == cos) { 140 l0_idx = idx; 141 break; 142 } 143 } 144 mmuq0 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[0]; 145 mmuq1 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[1]; 146 fc_only_uc = th3_sched_profile_info[unit][profile_id][l0_idx].fc_is_uc_only; 147 sp = th3_sched_profile_info[unit][profile_id][l0_idx].strict_priority; 148 ebg_cos = eb_config->eb_group[cos]; 149 ebg_grp0 = eb_config->mmuq_eb_group[mmuq0]; 150 ebg_grp1 = eb_config->mmuq_eb_group[mmuq1]; 151 pfc_opt_grp = eb_config->opt_group[cos]; 152 sp0 = eb_config->eb_group_sp[ebg_grp0]; 153 sp1 = eb_config->eb_group_sp[ebg_grp1]; 154 LOG_VERBOSE(BSL_LS_SOC_MMU, (BSL_META_U(unit, 155 " %2d %2d %2d %d %d %d " 156 "%d %d %d %d %d\n"), 157 cos, mmuq0, mmuq1, fc_only_uc, sp, pfc_opt_grp, 158 ebg_cos, ebg_grp0, ebg_grp1, sp0, sp1)); 159 160 161 } 162 } 163 164 /* 165 * Function: 166 * _soc_th3_pfc_opt_bmp_validate 167 * Purpose: 168 * To check the validity of COS lists for all PFC priorities. 169 * Parameters: 170 * unit - (IN) unit number 171 * config_array - (IN) PFC class config array 172 * array_len - (IN) The array length 173 * Returns: 174 * SOC_E_XXX 175 */ 176 177 STATIC int 178 _soc_th3_pfc_opt_bmp_validate( 179 int unit, 180 soc_cosq_pfc_class_map_config_t *config_array, 181 int array_len) 182 { 183 int i, j; 184 uint32 opt_bmp_agg; 185 if (config_array == NULL) 186 return SOC_E_PARAM; 187 188 if (array_len > TH3_PFC_PRIORITY_NUM) 189 return SOC_E_PARAM; 190 /* 191 * two conditions have to be met 192 * 1. for any two optimized PFC priorities, the list of CoS must be either 193 * mutually exclusive or equal. 194 * 2. A priority p0 can be PFC optimized if there is no other priority p1 195 * that COS list of p1 is a subset of COS list of p0. 196 */ 197 for (i = 0; i< array_len; i++) { 198 if (!config_array[i].pfc_optimized || 199 !config_array[i].cos_list_bmp) { 200 continue; 201 } 202 203 for (j = 0; j < array_len; j++) { 204 if (j == i || !config_array[j].cos_list_bmp) { 205 continue; 206 } 207 opt_bmp_agg = config_array[i].cos_list_bmp & 208 config_array[j].cos_list_bmp; 209 if (config_array[j].pfc_optimized) { 210 /* contition 1 */ 211 if ((opt_bmp_agg != 0) && 212 (config_array[i].cos_list_bmp != config_array[j].cos_list_bmp)) { 213 return SOC_E_PARAM; 214 } 215 } else { 216 /* condition 2*/ 217 if (opt_bmp_agg == config_array[j].cos_list_bmp) { 218 return SOC_E_PARAM; 219 } 220 221 } 222 } 223 } 224 225 return SOC_E_NONE; 226 227 } 228 229 /* 230 * Function: 231 * _soc_th3_pfc_rx_config_validate 232 * Purpose: 233 * To check if the input Config array is valid 234 * Parameters: 235 * unit - (IN) unit number 236 * config_array - (IN) PFC class config array 237 * array_len - (IN) The array length 238 * Returns: 239 * SOC_E_XXX 240 */ 241 242 STATIC int 243 _soc_th3_pfc_rx_config_validate( 244 int unit, 245 soc_cosq_pfc_class_map_config_t *config_array, 246 int array_len) 247 { 248 249 int i; 250 if (config_array == NULL) { 251 return SOC_E_PARAM; 252 } 253 254 for (i = 0; i < array_len; i++) { 255 256 if ((config_array[i].cos_list_bmp >> _TH3_PFC_COS_NUM_MASK_OFFSET)) { 257 return SOC_E_PARAM; 258 } 259 } 260 261 SOC_IF_ERROR_RETURN(_soc_th3_pfc_opt_bmp_validate 262 (unit, config_array, TH3_PFC_PRIORITY_NUM)); 263 264 return SOC_E_NONE; 265 } 266 267 /* 268 * Function: 269 * _soc_th3_pfc_eb_group_allocate 270 * Purpose: 271 * First Assign EB groups to COS 272 * Then set EB scheduling based on 273 * 1. EB group assignment, 274 * 2. SP_P field from scheduler domain input. 275 * Parameters: 276 * unit - (IN) unit number 277 * eb_config - (IN/OUT) EB group config 278 * num_opt_group - (IN) the required number of optimized groups 279 * Returns: 280 * SOC_E_XXX 281 */ 282 283 STATIC int 284 _soc_th3_pfc_eb_group_allocate( 285 int unit, 286 int profile_id, 287 _soc_th3_pfc_eb_group_config_t *eb_config, 288 int num_opt_group) 289 { 290 291 int n_avail_eb, non_opt_num; 292 int i, cos_num, invalid_index = _TH3_PFC_INDEX_INVALID; 293 int rr_set = 0; 294 int max_cos = 0; 295 /*the maximum index of EB group */ 296 n_avail_eb = _TH3_PFC_EB_GROUP_NUM - 1; 297 /* maximum index of non-opt EB*/ 298 non_opt_num = n_avail_eb - num_opt_group; 299 300 max_cos = soc_tomahawk3_get_sched_profile_max_cos(unit, profile_id); 301 for (cos_num = max_cos; cos_num >= 0; cos_num--) { 302 int eb_sp = soc_tomahawk3_get_sp_for_cos(unit, profile_id, cos_num); 303 if (eb_config->opt_group[cos_num] !=0 && 304 eb_config->eb_group[cos_num] == invalid_index) { 305 306 eb_config->eb_group[cos_num] = n_avail_eb--; 307 308 for (i = cos_num -1; i >= 0; i--) { 309 if (eb_config->opt_group[i] 310 == eb_config->opt_group[cos_num]) { 311 eb_config->eb_group[i] = eb_config->eb_group[cos_num]; 312 313 /* the EB group is set to SP as long as there exists one of the 314 * COSs assigned to it is SP planned. 315 */ 316 eb_sp |= soc_tomahawk3_get_sp_for_cos(unit, profile_id, i); 317 } 318 } 319 eb_config->eb_group_opt[eb_config->eb_group[cos_num]] = 1; 320 321 } else if (eb_config->eb_group[cos_num] == invalid_index) { 322 if (non_opt_num > 0) { 323 /* if free EB_GRP is available, then set EB_GRP(cos_num) to 324 * the next available EB_GRP with largest index. 325 */ 326 eb_config->eb_group[cos_num] = n_avail_eb--; 327 non_opt_num--; 328 } else { 329 /* if free EB_GRP is not available, then set EB_GRP(current_cos) to 0 330 * and set scheduling policy to round robin 331 */ 332 eb_config->eb_group[cos_num] = 0; 333 rr_set = 1; 334 } 335 } 336 if (!rr_set) { 337 if (eb_sp == 1) { 338 eb_config->eb_group_sp[eb_config->eb_group[cos_num]] = 1; 339 } else { 340 rr_set = 1; 341 } 342 } 343 344 } 345 346 return SOC_E_NONE; 347 348 } 349 350 STATIC int 351 _soc_th3_pfc_mmuq_is_mc(int unit, int q_num) { 352 int mc_q_mode, num_ucq; 353 mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2); 354 num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 : 355 (mc_q_mode == 2) ? 8 : (mc_q_mode == 3) ? 6 : 8; 356 357 return (q_num >= 0 && q_num < num_ucq) ? 0 : 1; 358 } 359 360 /* 361 * Function: 362 * _soc_th3_pfc_mmu_to_eb_mapping 363 * Purpose: 364 * Map MMU queues to EB groups. 365 * Parameters: 366 * unit - (IN) unit number 367 * eb_config - (IN/OUT) EB group config 368 * profile_id - (IN) Profile index 369 * Returns: 370 * SOC_E_XXX 371 */ 372 STATIC int 373 _soc_th3_pfc_mmuq_to_eb_mapping( 374 int unit, 375 int profile_id, 376 _soc_th3_pfc_eb_group_config_t *eb_config) 377 { 378 379 int i, q_num, cos_f_q, eb_grp_n; 380 int fc_only_uc; 381 382 for (q_num = 0; q_num < TH3_PFC_MMU_QUEUE_NUM; q_num++) { 383 cos_f_q = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, q_num); 384 if (cos_f_q == -1) { 385 return SOC_E_PARAM; 386 } 387 eb_grp_n = eb_config->eb_group[cos_f_q]; 388 389 fc_only_uc = soc_tomahawk3_get_fc_only_uc_for_cos(unit, profile_id, 390 cos_f_q); 391 if (_soc_th3_pfc_mmuq_is_mc(unit, q_num) && fc_only_uc) { 392 for (i = eb_grp_n; i >= 0; i--) { 393 if (eb_config->eb_group_opt[i] != 1) { 394 break; 395 } 396 } 397 if (i >= 0) { 398 eb_config->mmuq_eb_group[q_num] = i; 399 } else { 400 return SOC_E_FAIL; 401 } 402 403 } else { 404 eb_config->mmuq_eb_group[q_num] = eb_grp_n; 405 406 } 407 } 408 return SOC_E_NONE; 409 } 410 411 /* 412 * Function: 413 * _soc_th3_pfc_rx_mapping_hw_write 414 * Purpose: 415 * Write PFC-rx realted HW tables/registers 416 * Parameters: 417 * unit - (IN) unit number 418 * config_arry - (IN) PFC rx config array 419 * len - (IN) array length 420 * eb_config - (IN) EB group config 421 * profile_id - (IN) Profile index 422 * Returns: 423 * SOC_E_XXX 424 */ 425 426 STATIC int 427 _soc_th3_pfc_rx_mapping_hw_write( 428 int unit, 429 int profile_id, 430 soc_cosq_pfc_class_map_config_t *config_array, 431 int len, 432 _soc_th3_pfc_eb_group_config_t *eb_config) 433 { 434 int i, pri, cos, pri_ebg, mmuq1 = -1, mmuq2 = -1; 435 uint32 cos_bmp, mmuq_bmp, ebg_bmp, sp_bmp, hp_bmp, reg_index, rval; 436 uint64 rval64; 437 int fc_only_uc = 0, cos_f_q = 0; 438 439 soc_reg_t pri_reg = MMU_INTFI_PFCPRI_PROFILEr, 440 mmuq_reg = MMU_EBCFP_MMUQ_EBGRP_PROFILEr, 441 sp_reg = MMU_EBQS_EBQ_PROFILEr, 442 hp_reg = MMU_OQS_AGER_Q_PROFILE_HP_MMUQr; 443 444 soc_field_t mmuq_field = PFCPRI_MMUQ_BMPf, 445 ebg_field = PFCPRI_EBGRP_BMPf, 446 sp_field = SP_ENABLE_BMPf, 447 hp_field = HP_MMUQ_BITMAPf; 448 449 soc_field_t mmuq_fields[] = { 450 MMUQ0_EBGRP_NUMf, MMUQ1_EBGRP_NUMf, MMUQ2_EBGRP_NUMf, 451 MMUQ3_EBGRP_NUMf, MMUQ4_EBGRP_NUMf, MMUQ5_EBGRP_NUMf, 452 MMUQ6_EBGRP_NUMf, MMUQ7_EBGRP_NUMf, MMUQ8_EBGRP_NUMf, 453 MMUQ9_EBGRP_NUMf, MMUQ10_EBGRP_NUMf, MMUQ11_EBGRP_NUMf 454 }; 455 456 /* write PFC-rx priority to MMUq(s) and EB group(s) Mapping profile */ 457 for (pri = 0; pri < TH3_PFC_PRIORITY_NUM && pri < len; pri++) { 458 mmuq_bmp = 0; 459 ebg_bmp = 0; 460 cos_bmp = config_array[pri].cos_list_bmp; 461 462 reg_index = profile_id + pri * TH3_PFC_RX_PROFILE_NUM_ENTRIES; 463 SOC_TH3_PFC_BMP_ITER(cos_bmp, TH3_PFC_COS_NUM, cos) { 464 int idx = -1; 465 int l0_idx = -1; 466 for (idx = 0; idx < SOC_TH3_NUM_GP_QUEUES; idx++) { 467 if (th3_sched_profile_info[unit][profile_id][idx].cos == cos) { 468 l0_idx = idx; 469 break; 470 } 471 } 472 if (l0_idx != -1) { 473 mmuq1 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[0]; 474 mmuq2 = th3_sched_profile_info[unit][profile_id][l0_idx].mmuq[1]; 475 } 476 477 /* flow control just the UC queue when FC_ONLY_UC=1. */ 478 if ((mmuq1 != -1) && (mmuq2 != -1)) { 479 cos_f_q = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, mmuq1); 480 if (cos_f_q == -1) { 481 return SOC_E_PARAM; 482 } 483 fc_only_uc = soc_tomahawk3_get_fc_only_uc_for_cos(unit, profile_id, 484 cos_f_q); 485 if (!(_soc_th3_pfc_mmuq_is_mc(unit, mmuq1) && (fc_only_uc))) { 486 mmuq_bmp |= 1U << mmuq1; 487 } 488 489 if (!(_soc_th3_pfc_mmuq_is_mc(unit, mmuq2) && (fc_only_uc))) { 490 mmuq_bmp |= 1U << mmuq2; 491 } 492 } else { 493 if (mmuq1 != -1) { 494 mmuq_bmp |= 1U << mmuq1; 495 } 496 if (mmuq2 != -1) { 497 mmuq_bmp |= 1U << mmuq2; 498 } 499 } 500 501 pri_ebg = eb_config->eb_group[cos]; 502 if (eb_config->eb_group_opt[pri_ebg] == 1) { 503 ebg_bmp |= 1U << pri_ebg; 504 } 505 } 506 507 SOC_TH3_PFC_BMP_ITER(cos_bmp, TH3_PFC_COS_NUM, cos) { 508 if (eb_config->eb_group_opt[eb_config->eb_group[cos]] == 0) { 509 ebg_bmp = 0; 510 break; 511 } 512 } 513 514 SOC_IF_ERROR_RETURN 515 (soc_reg32_get(unit, pri_reg, REG_PORT_ANY, reg_index, &rval)); 516 soc_reg_field_set(unit, pri_reg, &rval, mmuq_field, mmuq_bmp); 517 soc_reg_field_set(unit, pri_reg, &rval, ebg_field, ebg_bmp); 518 SOC_IF_ERROR_RETURN 519 (soc_reg32_set(unit, pri_reg, REG_PORT_ANY, reg_index, rval)); 520 521 } 522 523 /* write MMUq to EB group mapping profile */ 524 COMPILER_64_ZERO(rval64); 525 SOC_IF_ERROR_RETURN 526 (soc_reg64_get(unit, mmuq_reg, REG_PORT_ANY, profile_id, &rval64)); 527 528 for (i = 0; i < TH3_PFC_MMU_QUEUE_NUM; i++) { 529 soc_reg64_field32_set(unit, mmuq_reg, &rval64, mmuq_fields[i], 530 eb_config->mmuq_eb_group[i]); 531 } 532 SOC_IF_ERROR_RETURN 533 (soc_reg64_set(unit, mmuq_reg, REG_PORT_ANY, profile_id, rval64)); 534 535 sp_bmp = 0; 536 for (i = 0; i < _TH3_PFC_EB_GROUP_NUM; i++) { 537 if (eb_config->eb_group_sp[i] == 1) { 538 sp_bmp |= 1U << i; 539 } 540 } 541 /* static scheduling setting for EB groups */ 542 rval = 0; 543 SOC_IF_ERROR_RETURN 544 (soc_reg32_get(unit, sp_reg, REG_PORT_ANY, profile_id, &rval)); 545 soc_reg_field_set(unit, sp_reg, &rval, sp_field, sp_bmp); 546 SOC_IF_ERROR_RETURN 547 (soc_reg32_set(unit, sp_reg, REG_PORT_ANY, profile_id, rval)); 548 549 /* if MMUQ is mapped to a static-priority EB, then it is HP queue */ 550 hp_bmp = 0; 551 for (i = 0; i < TH3_PFC_MMU_QUEUE_NUM; i++) { 552 if(eb_config->eb_group_sp[eb_config->mmuq_eb_group[i]] == 1) { 553 hp_bmp |= 1U << i; 554 } 555 } 556 rval = 0; 557 SOC_IF_ERROR_RETURN 558 (soc_reg32_get(unit, hp_reg, REG_PORT_ANY, profile_id, &rval)); 559 soc_reg_field_set(unit, hp_reg, &rval, hp_field, hp_bmp); 560 561 SOC_IF_ERROR_RETURN 562 (soc_reg32_set(unit, hp_reg, REG_PORT_ANY, profile_id, rval)); 563 564 return SOC_E_NONE; 565 } 566 567 int 568 soc_th3_pfc_rx_priority_mapping_profile_get( 569 int unit, 570 int profile_id, 571 int max_count, 572 soc_cosq_pfc_class_map_config_t *config_array, 573 int *count) 574 { 575 int pri; 576 uint32 cos_bmp, mmuq_bmp, ebg_bmp, reg_index, rval, mmuq, cos_id; 577 578 soc_reg_t pri_reg = MMU_INTFI_PFCPRI_PROFILEr; 579 soc_field_t mmuq_field = PFCPRI_MMUQ_BMPf, 580 ebg_field = PFCPRI_EBGRP_BMPf; 581 582 /* if max_count = 0, config_array has to be NULL */ 583 if(max_count == 0) { 584 if((NULL != config_array)) 585 return SOC_E_PARAM; 586 } 587 588 if(profile_id < TH3_PFC_CLASS_PROFILE_ID_MIN || 589 profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) { 590 591 return SOC_E_PARAM; 592 } 593 594 for(pri = 0; pri < max_count && pri < TH3_PFC_PRIORITY_NUM; pri++) { 595 cos_bmp = 0; 596 597 rval = 0; 598 reg_index = profile_id + pri * TH3_PFC_RX_PROFILE_NUM_ENTRIES; 599 SOC_IF_ERROR_RETURN 600 (soc_reg32_get(unit, pri_reg, REG_PORT_ANY, reg_index, &rval)); 601 mmuq_bmp = soc_reg_field_get(unit, pri_reg, rval, mmuq_field); 602 ebg_bmp = soc_reg_field_get(unit, pri_reg, rval, ebg_field); 603 604 if(mmuq_bmp != 0) { 605 config_array[pri].pfc_enable = 1; 606 SOC_TH3_PFC_BMP_ITER(mmuq_bmp, TH3_PFC_MMU_QUEUE_NUM, mmuq) { 607 cos_id = soc_tomahawk3_get_cos_for_mmu_queue(unit, profile_id, mmuq); 608 cos_bmp |= 1U << cos_id; 609 } 610 config_array[pri].cos_list_bmp = cos_bmp; 611 } 612 613 if(ebg_bmp != 0) config_array[pri].pfc_optimized = 1; 614 615 } 616 617 *count = pri; 618 619 return SOC_E_NONE; 620 } 621 622 STATIC int 623 _soc_th3_pfc_check_higher_pri_cos_bmp(int unit, soc_cosq_pfc_class_map_config_t 624 *config_array, int pri_num) 625 { 626 int pri; 627 628 for (pri = (pri_num + 1); pri <= _TH3_PFC_PRIORITY_MAX_INDEX; pri++ ) { 629 if (config_array[pri_num].cos_list_bmp == 630 config_array[pri].cos_list_bmp) { 631 return 1; 632 } 633 } 634 635 return 0; 636 } 637 638 639 /* 640 * Function: 641 * soc_th3_pfc_rx_priority_mapping_profile_set 642 * Purpose: 643 * Set the PFC rx priority to MMU and EB group mapping. 644 * Parameters: 645 * unit - (IN) device id. 646 * port - (IN) logic port. 647 * config_array - (IN) PFC rx config array. 648 * count - (IN) The length of array 649 * It needs to be fixed at 8. All PFC priorities should 650 * be configured at once, and the config array must be 651 * arranged in ascending order of PFC priorities. 652 * 0, 1, ... , 7. 653 * Returns: 654 * SOC_E_XXX 655 */ 656 657 int 658 soc_th3_pfc_rx_priority_mapping_profile_set( 659 int unit, 660 int profile_id, 661 soc_cosq_pfc_class_map_config_t *config_array, 662 int count) 663 { 664 665 int pri_num, cos_num; 666 int opt_count = 0; 667 _soc_th3_pfc_eb_group_config_t eb_config; 668 669 670 671 if (profile_id < TH3_PFC_CLASS_PROFILE_ID_MIN || 672 profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) { 673 return SOC_E_PARAM; 674 } 675 676 if (config_array == NULL || count != TH3_PFC_PRIORITY_NUM) 677 return SOC_E_PARAM; 678 679 SOC_IF_ERROR_RETURN 680 (_soc_th3_pfc_rx_config_validate(unit, config_array, count)); 681 682 _soc_th3_pfc_eb_group_config_t_init(&eb_config); 683 684 /* Start from priority 7 and check every priority */ 685 for (pri_num = _TH3_PFC_PRIORITY_MAX_INDEX; pri_num >= 0; pri_num--) { 686 if (config_array[pri_num].pfc_optimized == 1 687 && config_array[pri_num].cos_list_bmp !=0) { 688 /* If PFC_Optimized(priority) is set and cos_list_bmp is not 0 && 689 * no other higher PFC optimized priority has same cos list */ 690 if (!_soc_th3_pfc_check_higher_pri_cos_bmp(unit, config_array, 691 pri_num)) { 692 opt_count++; 693 } 694 /* set PFC_Optimized_Group(cos) for every cos in the list 695 *to the same value opt_count 696 * opt_count is the number of PFC optimized groups used so far 697 */ 698 for (cos_num = 0; cos_num < TH3_PFC_COS_NUM; cos_num++) { 699 700 if (SOC_TH3_PFC_BMP_MEMBER( 701 config_array[pri_num].cos_list_bmp, cos_num)) { 702 eb_config.opt_group[cos_num] = opt_count; 703 } 704 } 705 706 } 707 } 708 709 SOC_IF_ERROR_RETURN 710 (_soc_th3_pfc_eb_group_allocate(unit, profile_id, &eb_config, opt_count)); 711 712 SOC_IF_ERROR_RETURN 713 (_soc_th3_pfc_mmuq_to_eb_mapping(unit, profile_id, &eb_config)); 714 715 /* Add function to print debug info for CoS-domain intermediary values */ 716 _soc_th3_print_pfc_sched_profile_info(unit, profile_id, &eb_config); 717 718 SOC_IF_ERROR_RETURN 719 (_soc_th3_pfc_rx_mapping_hw_write(unit, profile_id, config_array, count, 720 &eb_config)); 721 722 return SOC_E_NONE; 723 } 724 725 /* 726 * Function: 727 * soc_th3_pfc_tx_priority_mapping_profile_op 728 * Purpose: 729 * To set/get a PG-property profile. 730 * Parameters: 731 * unit - (IN) device id. 732 * profile_id - (IN) profile ID. 733 * max_count - (IN) max lenghth of PG array 734 * valid only for _get operation 735 * op - (IN) operation type, _get or _set 736 * array_count (IN/OUT) valid length of array 737 * IN for _set, OUT for _get 738 * pg_array (IN/OUT) PG array, index by PFC priority 739 IN for _set, OUT for _get 740 * Returns: 741 * SOC_E_XXX 742 */ 743 744 int 745 soc_th3_pfc_tx_priority_mapping_profile_op( 746 int unit, 747 int profile_id, 748 int max_count, 749 soc_th3_pfc_pfc_profile_op_t op, 750 int *array_count, 751 int *pg_array) 752 { 753 #define _TH3_PFC_PRIORITY_GROUP_ID_MAX 7 754 int i; 755 uint32 rval; 756 soc_reg_t reg = MMU_THDI_PFCPRI_PG_PROFILEr; 757 758 soc_field_t field_array[TH3_PFC_PRIORITY_NUM] = { 759 PFCPRI0_PGf, PFCPRI1_PGf, PFCPRI2_PGf, PFCPRI3_PGf, 760 PFCPRI4_PGf, PFCPRI5_PGf, PFCPRI6_PGf, PFCPRI7_PGf 761 }; 762 if (profile_id < TH3_PFC_PROPERTIES_PROFILE_ID_MIN || 763 profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) { 764 765 return SOC_E_PARAM; 766 } 767 768 769 SOC_IF_ERROR_RETURN 770 (soc_reg32_get(unit, reg, REG_PORT_ANY, profile_id, &rval)); 771 772 if (SOC_TH3_PFC_PROFILE_OP_SET == op) { 773 if (*array_count > TH3_PFC_PRIORITY_NUM || *array_count <= 0) { 774 return SOC_E_PARAM; 775 } 776 777 if (pg_array == NULL) { 778 return SOC_E_PARAM; 779 } 780 781 for (i = 0; i < *array_count; i++) { 782 if (pg_array[i] < 0 || pg_array[i] > _TH3_PFC_PRIORITY_GROUP_ID_MAX) { 783 return SOC_E_PARAM; 784 } 785 soc_reg_field_set(unit, reg, &rval, field_array[i], pg_array[i]); 786 } 787 SOC_IF_ERROR_RETURN 788 (soc_reg32_set(unit, reg, REG_PORT_ANY, profile_id, rval)); 789 } else if (SOC_TH3_PFC_PROFILE_OP_GET == op) { 790 791 if ((0 == max_count && pg_array != NULL) || 792 (0 != max_count && pg_array == NULL)) { 793 return SOC_E_PARAM; 794 } 795 796 for (i = 0; i < max_count && i < TH3_PFC_PRIORITY_NUM; i++) { 797 pg_array[i] = soc_reg_field_get(unit, reg, rval, field_array[i]); 798 } 799 *array_count = i; 800 } 801 802 return SOC_E_NONE; 803 } 804 805 /* 806 * Function: 807 * soc_th3_pfc_pg_profile_op 808 * Purpose: 809 * To set/get a PG-property profile. 810 * Parameters: 811 * unit - (IN) device id. 812 * profile_id - (IN) profile ID. 813 * max_count - (IN) max lenghth of PG-property config array 814 * valid only for _get operation 815 * op - (IN) operation type, _get or _set 816 * array_count (IN/OUT) valid length of array 817 * IN for _set, OUT for _get 818 * properties (IN/OUT) PG-property config array 819 IN for _set, OUT for _get 820 * Returns: 821 * SOC_E_XXX 822 */ 823 824 int 825 soc_th3_pfc_pg_profile_op( 826 int unit, 827 int profile_id, 828 int max_count, 829 soc_th3_pfc_pfc_profile_op_t op, 830 int* array_count, 831 soc_cosq_priority_group_properties_t *properties) 832 { 833 #define _TH3_PFC_SPID_MAX_INDEX 3 834 #define _TH3_PFC_HDRMID_MAX_INDEX 3 835 int i, pg_id; 836 uint64 rval; 837 soc_reg_t reg = MMU_THDI_PG_PROFILEr; 838 839 soc_field_t hdrm_farray[_TH3_PFC_PRIORITY_GROUP_NUM] = { 840 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf, 841 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf 842 }; 843 soc_field_t sp_farray[_TH3_PFC_PRIORITY_GROUP_NUM] = { 844 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 845 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf, 846 }; 847 848 if (profile_id < TH3_PFC_PROPERTIES_PROFILE_ID_MIN || 849 profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) { 850 return SOC_E_PARAM; 851 } 852 853 854 SOC_IF_ERROR_RETURN 855 (soc_reg64_get(unit, reg, REG_PORT_ANY, profile_id, &rval)); 856 857 if (SOC_TH3_PFC_PROFILE_OP_SET == op) { 858 if (*array_count < 0 || *array_count > _TH3_PFC_PRIORITY_GROUP_NUM) { 859 return SOC_E_PARAM; 860 } 861 if (properties == NULL) { 862 return SOC_E_PARAM; 863 } 864 865 for (i = 0; i < *array_count; i++) { 866 pg_id = properties[i].priority_group_id; 867 if (pg_id != -1) { 868 if(pg_id < 0 || pg_id >= _TH3_PFC_PRIORITY_GROUP_NUM) { 869 return SOC_E_PARAM; 870 } 871 } else { 872 continue; 873 } 874 if (properties[i].service_pool_id != -1) { 875 if(properties[i].service_pool_id < 0 || 876 properties[i].service_pool_id > _TH3_PFC_SPID_MAX_INDEX) { 877 return SOC_E_PARAM; 878 } 879 soc_reg64_field32_set(unit, reg, &rval, sp_farray[pg_id], 880 properties[i].service_pool_id); 881 } 882 if (properties[i].headroom_pool_id != -1) { 883 if(properties[i].headroom_pool_id < 0 || 884 properties[i].headroom_pool_id > _TH3_PFC_HDRMID_MAX_INDEX) { 885 return SOC_E_PARAM; 886 } 887 soc_reg64_field32_set(unit, reg, &rval, hdrm_farray[pg_id], 888 properties[i].headroom_pool_id); 889 } 890 } 891 SOC_IF_ERROR_RETURN 892 (soc_reg64_set(unit, reg, REG_PORT_ANY, profile_id, rval)); 893 894 } else if (SOC_TH3_PFC_PROFILE_OP_GET == op) { 895 if ((0 == max_count && properties != NULL) || 896 (0 != max_count && properties == NULL)) { 897 return SOC_E_PARAM; 898 } 899 for (i = 0; i < max_count && i < _TH3_PFC_PRIORITY_GROUP_NUM; i++) { 900 properties[i].priority_group_id = i; 901 902 properties[i].service_pool_id = 903 soc_reg64_field32_get(unit, reg, rval, sp_farray[i]); 904 properties[i].headroom_pool_id = 905 soc_reg64_field32_get(unit, reg, rval, hdrm_farray[i]); 906 } 907 *array_count = i; 908 } 909 #undef _TH3_PFC_SPID_MAX_INDEX 910 #undef _TH3_PFC_HDRMID_MAX_INDEX 911 return SOC_E_NONE; 912 } 913 914 /* 915 * Function: 916 * soc_th3_pfc_num_optimized_group_get 917 * Purpose: 918 * Get the maximum number of optimized PFC groups for a given port. 919 * Parameters: 920 * unit - (IN) device id. 921 * port - (IN) logic port number. 922 * num - (OUT) number of optimized PFC groups supported. 923 * Returns: 924 * SOC_E_XXX 925 */ 926 927 int 928 soc_th3_pfc_num_optimized_group_get( 929 int unit, 930 soc_port_t port, 931 int *num) 932 { 933 int speed, mtu_size; 934 uint32 speed_id, mtu_id; 935 soc_info_t *si = &SOC_INFO(unit); 936 937 /* PFC optimized group is not supported for LB port */ 938 if (SOC_PBMP_MEMBER(si->lb_pbm, port)) { 939 *num = 0; 940 return SOC_E_NONE; 941 } 942 943 if (IS_MANAGEMENT_PORT(unit,port)) { 944 speed = si->port_speed_max[port]; 945 } else if (si->flex_eligible) { 946 speed = 50000; 947 } else { 948 speed = si->port_init_speed[port]; 949 if (speed == 0) { 950 speed = si->port_speed_max[port]; 951 } 952 } 953 speed_id = _soc_th3_pfc_speed_encoding_get(unit, speed); 954 955 mtu_size = soc_property_get(unit, spn_MMU_PFC_GROUP_OPTIMIZED_MTU_SIZE, 9416); 956 mtu_id = _soc_th3_pfc_mtu_encoding_get(unit, mtu_size); 957 958 if (mtu_id == -1 || speed_id == -1) { 959 return SOC_E_PARAM; 960 } 961 if (IS_MANAGEMENT_PORT(unit,port)) { 962 *num = magt_opt_group_num_flexport[mtu_id]; 963 } else if (IS_LB_PORT(unit,port)) { 964 *num = 0; 965 } else { 966 *num = opt_group_num_flexport[mtu_id][speed_id]; 967 } 968 return SOC_E_NONE; 969 } 970 971 /* 972 * Function: 973 * soc_th3_pfc_config_profile_id_set 974 * Purpose: 975 * Set the PFC-related profile ID for a given port. 976 * Parameters: 977 * unit - (IN) device id. 978 * port - (IN) logic port number. 979 * type - (IN) profile type. 980 * profile_id - (IN) profile ID. 981 * Returns: 982 * SOC_E_XXX 983 */ 984 985 int 986 soc_th3_pfc_config_profile_id_set( 987 int unit, 988 soc_port_t port, 989 soc_th3_pfc_profile_t type, 990 uint32 profile_id) 991 { 992 993 soc_reg_t reg = INVALIDr; 994 soc_field_t field = INVALIDf; 995 uint32 rval; 996 int i, count = 0, opt_num = 0, max_opt_num = 0; 997 soc_cosq_pfc_class_map_config_t config_array[TH3_PFC_PRIORITY_NUM]; 998 sal_memset(config_array, 0, sizeof(soc_cosq_pfc_class_map_config_t) * TH3_PFC_PRIORITY_NUM); 999 if (type >= socTH3PFCProfileMax) { 1000 return SOC_E_PARAM; 1001 } 1002 1003 switch(type) { 1004 case socTH3PFCPGProperties: 1005 if (profile_id > TH3_PFC_PROPERTIES_PROFILE_ID_MAX) { 1006 return SOC_E_PARAM; 1007 } 1008 reg = MMU_THDI_ING_PORT_CONFIGr; 1009 field = PG_PROFILE_SELf; 1010 break; 1011 1012 1013 case socTH3PFCReceiveClass: 1014 if (profile_id > TH3_PFC_CLASS_PROFILE_ID_MAX) { 1015 return SOC_E_PARAM; 1016 } 1017 /* check if a port can have the required number of PFC optimized groups */ 1018 SOC_IF_ERROR_RETURN(soc_th3_pfc_num_optimized_group_get( 1019 unit, port, &max_opt_num)); 1020 SOC_IF_ERROR_RETURN( 1021 soc_th3_pfc_rx_priority_mapping_profile_get(unit, profile_id, 1022 TH3_PFC_PRIORITY_NUM, config_array, &count)); 1023 for (i =0; i < count; i++) { 1024 if (config_array[i].pfc_optimized) { 1025 opt_num++; 1026 if (opt_num > max_opt_num) { 1027 return SOC_E_PARAM; 1028 } 1029 } 1030 } 1031 reg = MMU_EBQS_PORT_CFGr; 1032 field = PROFILE_SELf; 1033 1034 SOC_IF_ERROR_RETURN( 1035 soc_reg32_get(unit, reg, port, 0, &rval)); 1036 soc_reg_field_set(unit, reg, &rval, field, profile_id); 1037 SOC_IF_ERROR_RETURN 1038 (soc_reg32_set(unit, reg, port, 0, rval)); 1039 1040 reg = MMU_EBCFP_EGR_PORT_CFGr; 1041 field = PROFILE_SELf; 1042 SOC_IF_ERROR_RETURN( 1043 soc_reg32_get(unit, reg, port, 0, &rval)); 1044 soc_reg_field_set(unit, reg, &rval, field, profile_id); 1045 SOC_IF_ERROR_RETURN 1046 (soc_reg32_set(unit, reg, port, 0, rval)); 1047 1048 reg = MMU_OQS_AGER_DST_PORT_MAPr; 1049 field = PROFILE_SELf; 1050 SOC_IF_ERROR_RETURN( 1051 soc_reg32_get(unit, reg, port, 0, &rval)); 1052 soc_reg_field_set(unit, reg, &rval, field, profile_id); 1053 SOC_IF_ERROR_RETURN 1054 (soc_reg32_set(unit, reg, port, 0, rval)); 1055 1056 reg = MMU_INTFI_EGR_PORT_CFGr; 1057 field = PROFILE_SELf; 1058 break; 1059 1060 default: 1061 return SOC_E_UNAVAIL; 1062 1063 } 1064 1065 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 1066 soc_reg_field_set(unit, reg, &rval, field, profile_id); 1067 SOC_IF_ERROR_RETURN 1068 (soc_reg32_set(unit, reg, port, 0, rval)); 1069 return SOC_E_NONE; 1070 1071 } 1072 1073 /* 1074 * Function: 1075 * soc_th3_pfc_config_profile_id_get 1076 * Purpose: 1077 * Get the PFC-related profile ID for a given port. 1078 * Parameters: 1079 * unit - (IN) device id. 1080 * port - (IN) logic port number. 1081 * type - (IN) profile type. 1082 * profile_id - (OUT) profile ID. 1083 * Returns: 1084 * SOC_E_XXX 1085 */ 1086 1087 int 1088 soc_th3_pfc_config_profile_id_get( 1089 int unit, 1090 soc_port_t port, 1091 soc_th3_pfc_profile_t type, 1092 uint32 *profile_id) 1093 { 1094 1095 soc_reg_t reg = INVALIDr; 1096 soc_field_t field = INVALIDf; 1097 uint32 rval, fval; 1098 1099 if (profile_id == NULL || type >= socTH3PFCProfileMax) { 1100 return SOC_E_PARAM; 1101 } 1102 1103 switch(type) { 1104 case socTH3PFCPGProperties: 1105 reg = MMU_THDI_ING_PORT_CONFIGr; 1106 field = PG_PROFILE_SELf; 1107 break; 1108 1109 case socTH3PFCReceiveClass: 1110 reg = MMU_INTFI_EGR_PORT_CFGr; 1111 field = PROFILE_SELf; 1112 break; 1113 1114 default: 1115 return SOC_E_UNAVAIL; 1116 1117 } 1118 1119 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 1120 fval = soc_reg_field_get(unit, reg, rval, field); 1121 *profile_id = fval; 1122 1123 return SOC_E_NONE; 1124 1125 } 1126 1127 /* 1128 * Function: 1129 * soc_th3_pfc_rx_init_from_cfg 1130 * Purpose: 1131 * To set PFC class profile from config variables 1132 * during init time. 1133 * config variables should follow the format below 1134 * 1. mmu_pfc_class_profile_<profile_id>.pfc_priority<priority number>. \ 1135 * cos_list=<Comma Seperated Values> 1136 * 2. mmu_pfc_class_profile_<profile_id>.pfc_priority. \ 1137 * optimized=<Comma Seperated Values>, the number of values should be equal 1138 * to the # of PFC priorities. 0: non-optimized, 1: optimized. 1139 * Parameters: 1140 * unit - (IN) device id. 1141 * Returns: 1142 * SOC_E_XXX 1143 */ 1144 1145 int 1146 soc_th3_pfc_rx_init_from_cfg(int unit) 1147 { 1148 int i, j, cos_idx, count, rv = SOC_E_NONE, set_profile = 0; 1149 char s_name[SOC_PROPERTY_NAME_MAX], s_opt[SOC_PROPERTY_NAME_MAX]; 1150 int cos_list[TH3_PFC_COS_NUM], opt_val[TH3_PFC_PRIORITY_NUM]; 1151 soc_cosq_pfc_class_map_config_t rx_config[TH3_PFC_PRIORITY_NUM]; 1152 int mtu_size; 1153 uint32 rval = 0; 1154 1155 for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) { 1156 set_profile = 0; 1157 sal_memset(rx_config, 0, TH3_PFC_PRIORITY_NUM * sizeof(rx_config[0])); 1158 sal_memset(opt_val, 0, TH3_PFC_PRIORITY_NUM * sizeof(opt_val[0])); 1159 1160 /* read pfc optimized config per profile */ 1161 sal_sprintf(s_opt, "%s_%d.%s.%s", 1162 spn_MMU_PFC_CLASS_PROFILE, i, 1163 spn_PFC_PRIORITY, spn_OPTIMIZED); 1164 (void) soc_property_get_csv 1165 (unit, s_opt, TH3_PFC_PRIORITY_NUM, opt_val); 1166 1167 /* read cos_list per PFC priority per Profile 1168 * , and fill structure soc_cosq_pfc_class_map_config_t 1169 */ 1170 for (j = 0; j < TH3_PFC_PRIORITY_NUM; j++) { 1171 1172 rx_config[j].pfc_optimized = opt_val[j]; 1173 1174 sal_sprintf(s_name, "%s_%d.%s%d.%s", 1175 spn_MMU_PFC_CLASS_PROFILE, i, 1176 spn_PFC_PRIORITY, j, spn_COS_LIST); 1177 count = soc_property_get_csv 1178 (unit, s_name, TH3_PFC_COS_NUM, cos_list); 1179 if (!count) { 1180 continue; 1181 } 1182 for (cos_idx = 0; cos_idx < count; cos_idx++) { 1183 rx_config[j].cos_list_bmp |= 1U << cos_list[cos_idx]; 1184 rx_config[j].pfc_enable = 1; 1185 } 1186 if (!set_profile) { 1187 set_profile = 1; 1188 } 1189 } 1190 1191 if (set_profile) { 1192 rv = soc_th3_pfc_rx_priority_mapping_profile_set 1193 (unit, i, rx_config, TH3_PFC_PRIORITY_NUM); 1194 if (rv != SOC_E_NONE) { 1195 /* Output error log */ 1196 } 1197 } 1198 } 1199 1200 mtu_size = soc_property_get(unit, spn_MMU_PFC_GROUP_OPTIMIZED_MTU_SIZE, 9416); 1201 1202 if (mtu_size < 9416) { 1203 mtu_size = (mtu_size + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL; 1204 rval = 0; 1205 SOC_IF_ERROR_RETURN 1206 (soc_reg32_get(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr, 1207 REG_PORT_ANY, 0, &rval)); 1208 1209 soc_reg_field_set(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr, &rval, 1210 REDUCED_MTUf, mtu_size); 1211 SOC_IF_ERROR_RETURN 1212 (soc_reg32_set(unit, MMU_EBCFP_OPT_EBGRP_REDUCED_MTUr, 1213 REG_PORT_ANY, 0, rval)); 1214 1215 /* specify to use this setting for all 8 profiles and 8 PFC priorities. */ 1216 for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) { 1217 SOC_IF_ERROR_RETURN 1218 (soc_reg32_get(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr, 1219 REG_PORT_ANY, i, &rval)); 1220 soc_reg_field_set(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr, 1221 &rval, OPT_EBGRP_MAX_MTU_BMPf, 0); 1222 SOC_IF_ERROR_RETURN 1223 (soc_reg32_set(unit, MMU_EBCFP_OPT_EBGRP_MTU_PROFILEr, 1224 REG_PORT_ANY, i, rval)); 1225 } 1226 } 1227 return SOC_E_NONE; 1228 } 1229 1230 /* PFC priority to PG mapping is also handled in THDI code*/ 1231 1232 /* 1233 * Function: 1234 * soc_th3_pfc_priority_to_pg_map_init_from_cfg 1235 * Purpose: 1236 * To set PFC-tx priority to PG mapping profile from config variables 1237 * during init time. 1238 * config variables should follow the format below: 1239 * buf.mapprofile<profile_id>.pfcclass_to_priority_group=<csv> 1240 * Parameters: 1241 * unit - (IN) device id. 1242 * Returns: 1243 * SOC_E_XXX 1244 */ 1245 1246 int 1247 soc_th3_pfc_priority_to_pg_map_init_from_cfg(int unit) 1248 { 1249 int i, count, rv = SOC_E_NONE; 1250 char s_name[SOC_PROPERTY_NAME_MAX]; 1251 int pg_list[TH3_PFC_PRIORITY_NUM]; 1252 1253 sal_memset(pg_list, 0, TH3_PFC_PRIORITY_NUM * sizeof(pg_list[0])); 1254 1255 for (i = 0; i <= TH3_PFC_CLASS_PROFILE_ID_MAX; i++) { 1256 1257 /* read PFC-tx to PG mapping per profile */ 1258 sal_sprintf(s_name, "%s.%s%d.%s", 1259 spn_BUF, spn_MAPPROFILE, i, spn_PFCCLASS_TO_PRIORITY_GROUP); 1260 count = soc_property_get_csv 1261 (unit, s_name, TH3_PFC_PRIORITY_NUM, pg_list); 1262 if (count > 0) { 1263 rv = soc_th3_pfc_tx_priority_mapping_profile_op( 1264 unit, i, TH3_PFC_PRIORITY_NUM, SOC_TH3_PFC_PROFILE_OP_SET, 1265 &count, pg_list); 1266 } 1267 1268 if (rv != SOC_E_NONE) { 1269 /* Output error log */ 1270 } 1271 1272 } 1273 return SOC_E_NONE; 1274 } 1275 1276 #endif