asf.c (49176B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: asf.c 8 * Purpose: ASF feature support for Tomahawk3 SKUs 9 * Requires: 10 */ 11 12 13 #if defined(BCM_TOMAHAWK3_SUPPORT) 14 #include <soc/tomahawk3.h> 15 #include <soc/init/tomahawk3_idb_init.h> 16 #include <soc/init/tomahawk3_ep_init.h> 17 #include <appl/diag/system.h> 18 #include <soc/drv.h> 19 #include <soc/ll.h> 20 #include <soc/property.h> 21 #include <shared/bsl.h> 22 #ifdef PORTMOD_SUPPORT 23 #include <soc/portmod/portmod.h> 24 #include <soc/esw/portctrl.h> 25 #endif 26 27 28 #ifdef BCM_WARM_BOOT_SUPPORT 29 #include <soc/scache.h> 30 #endif /* BCM_WARM_BOOT_SUPPORT */ 31 32 #define _SOC_TH3_ASF_QUERY 0xfe 33 #define _SOC_TH3_ASF_RETRV 0xff 34 35 #define _SOC_TH3_ASF_MAX_FACTOR 4 36 #define _SOC_TH3_ASF_MAX_SPEED 400000 37 38 #define _SOC_TH3_SAF_COMMIT_ID_NUM 16 39 40 #define _SOC_TH3_CT_CLASS_VALID_NUM 8 41 #define _SOC_TH3_CT_CLASS_TOTAL_NUM 16 42 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 43 #define _TH3_PORT_SPEED(si, port) (si)->port_init_speed[(port)] 44 45 #define _SOC_ASF_TH3_UNIT_VALIDATE(unit) \ 46 if ( !(((unit) >= 0) && ((unit) <= SOC_MAX_NUM_DEVICES)) ) \ 47 return SOC_E_UNIT; 48 49 #define _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(class) \ 50 if(!(((class) >= 0 && (class) < _SOC_TH3_CT_CLASS_VALID_NUM))) \ 51 return SOC_E_PARAM; 52 53 #define _SOC_TH3_CT_CLASS_TO_SPEED_MAP(ct_class) \ 54 soc_th3_asf_config_tbl[ct_class].speed 55 56 typedef enum _soc_th3_pipe_bandwidth_config_e { 57 58 _SOC_PIPE_BANDWIDTH_CONFIG_400G = 0, 59 _SOC_PIPE_BANDWIDTH_CONFIG_50G_400G = 1, 60 _SOC_PIPE_BADWIDTH_CONFIG_16x100G = 2, 61 _SOC_PIPE_BANDWIDTH_CONFIG_OTHER = 3, 62 _SOC_PIPE_BANDWIDTH_CONFIG_MAX = 4 63 64 } _soc_th3_pipe_bandwidth_config_t; 65 66 typedef struct _soc_th3_saf_commit_config_s { 67 68 uint16 saf_commit_id[_SOC_TH3_SAF_COMMIT_ID_NUM]; 69 70 } _soc_th3_saf_commit_config_t; 71 72 typedef enum _soc_th3_asf_speed_encoding_e { 73 _SOC_TH3_SPEED_ID_RESERVED = 0, 74 _SOC_TH3_SPEED_ID_10G, 75 _SOC_TH3_SPEED_ID_25G, 76 _SOC_TH3_SPEED_ID_40G, 77 _SOC_TH3_SPEED_ID_50G, 78 _SOC_TH3_SPEED_ID_100G, 79 _SOC_TH3_SPEED_ID_200G, 80 _SOC_TH3_SPEED_ID_400G, 81 _SOC_TH3_SPEED_ID_ERROR 82 } _soc_th3_asf_speed_encoding_t; 83 84 85 86 static const 87 _soc_th3_saf_commit_config_t 88 _soc_th3_saf_commit_tbl[_SOC_PIPE_BANDWIDTH_CONFIG_MAX] = { 89 {{0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 16}}, /* 4X400GE */ 90 {{1, 2, 3, 3, 4, 5, 6, 6, 7, 9, 11, 13, 15, 17, 19, 21}}, /* Mixed 50GE, 400GE */ 91 {{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20}}, /* 16x100GE */ 92 /*{{1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13}} others */ 93 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} /* others */ 94 }; 95 static const struct _soc_th3_bmop_settings_s { 96 int speed; 97 /*Bubble MOP disable.*/ 98 uint8 bmop_disable[3]; 99 } _soc_th3_bmop_settings_tbl[] = { 100 { -1, {0, 0, 0} }, /* SAF */ 101 { 10000, {1, 1, 1} }, /* 10GE */ 102 { 25000, {0, 0, 0} }, /* 25GE */ 103 { 40000, {0, 0, 0} }, /* 40GE */ 104 { 50000, {0, 0, 0} }, /* 50GE */ 105 {100000, {0, 0, 0} }, /* 100GE */ 106 {200000, {0, 0, 0} }, /* 200GE */ 107 {400000, {0, 0, 0} } /* 400GE */ 108 }; 109 110 /* ASF ctrl */ 111 typedef struct _soc_th3_asf_ctrl_s { 112 uint8 init; 113 pbmp_t asf_ports; 114 pbmp_t pause_restore; 115 } _soc_th3_asf_ctrl_t; 116 117 /* ASF Control */ 118 static _soc_th3_asf_ctrl_t* 119 _soc_th3_asf_ctrl[SOC_MAX_NUM_DEVICES] = {NULL}; 120 121 #ifdef BCM_WARM_BOOT_SUPPORT 122 /* ASF Warmboot */ 123 typedef struct _soc_th3_asf_wb_s { 124 int unit; 125 _soc_th3_asf_ctrl_t asf_ctrl; 126 } _soc_th3_asf_wb_t; 127 #endif /* BCM_WARM_BOOT_SUPPORT */ 128 129 /* 130 * Function: 131 * _soc_th3_asf_speed_encoding_get 132 * Purpose: 133 * Return speed encoding given a speed in MB/S 134 * Parameters: 135 * speed - (IN) speed in MB/s 136 * Returns: 137 * SOC_E_XXX 138 */ 139 140 STATIC int 141 _soc_th3_asf_speed_encoding_get(int speed) { 142 switch(speed) { 143 case 10000: 144 return _SOC_TH3_SPEED_ID_10G; 145 case 25000: 146 return _SOC_TH3_SPEED_ID_25G; 147 case 40000: 148 return _SOC_TH3_SPEED_ID_40G; 149 case 50000: 150 return _SOC_TH3_SPEED_ID_50G; 151 case 100000: 152 case 160000: 153 return _SOC_TH3_SPEED_ID_100G; 154 case 200000: 155 return _SOC_TH3_SPEED_ID_200G; 156 case 400000: 157 return _SOC_TH3_SPEED_ID_400G; 158 default: 159 return _SOC_TH3_SPEED_ID_ERROR; 160 } 161 } 162 163 STATIC int 164 _soc_th3_asf_speed_get (int speed_encode) { 165 switch(speed_encode) { 166 case _SOC_TH3_SPEED_ID_10G: 167 return 10000; 168 case _SOC_TH3_SPEED_ID_25G: 169 return 25000; 170 case _SOC_TH3_SPEED_ID_40G: 171 return 40000; 172 case _SOC_TH3_SPEED_ID_50G: 173 return 50000; 174 case _SOC_TH3_SPEED_ID_100G: 175 return 100000; 176 case _SOC_TH3_SPEED_ID_200G: 177 return 200000; 178 case _SOC_TH3_SPEED_ID_400G: 179 return 400000; 180 default: 181 return -1; 182 } 183 } 184 185 /* 186 * Function: 187 * _soc_th3_port_asf_speed_limits_get 188 * Purpose: 189 * Get the max and min src speed (encoding) 190 * given a dst port speed. 191 * Parameters: 192 * unit - (IN) unit number 193 * port_speed - (IN) dst port speed 194 * mode - (IN) forwarding mode 195 * min_sp (OUT) min src speed encoding 196 * max_sp (OUT) max src speed encoding 197 * Returns: 198 * SOC_E_XXX 199 */ 200 201 STATIC int 202 _soc_th3_port_asf_speed_limits_get( 203 int unit, 204 int port_speed, 205 int mode, 206 int *min_sp, 207 int *max_sp) 208 { 209 if(SOC_TH3_ASF_MODE_SAF != mode) { 210 *min_sp = _soc_th3_asf_speed_encoding_get(port_speed); 211 *max_sp = MIN(port_speed*_SOC_TH3_ASF_MAX_FACTOR, _SOC_TH3_ASF_MAX_SPEED); 212 *max_sp = _soc_th3_asf_speed_encoding_get(*max_sp); 213 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(*min_sp); 214 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(*max_sp); 215 } else { 216 *min_sp = -1; 217 *max_sp = -1; 218 } 219 220 return SOC_E_NONE; 221 222 } 223 224 /* 225 * Function: 226 * _soc_th3_port_asf_speed_limits_read 227 * Purpose: 228 * Get the max and min src speed (encoding) 229 * given a dst port speed. 230 * Parameters: 231 * unit - (IN) unit number 232 * port - (IN) dst port 233 * min_sp (OUT) min src speed encoding 234 * max_sp (OUT) max src speed encoding 235 * Returns: 236 * SOC_E_XXX 237 */ 238 239 STATIC int 240 _soc_th3_port_asf_speed_limits_read( 241 int unit, 242 soc_port_t port, 243 int *min_sp, 244 int *max_sp) 245 { 246 soc_reg_t asf_config_reg = MMU_EBCTM_EPORT_CT_CFGr; 247 uint32 rval = 0; 248 soc_field_t min_sp_fld = DST_PORT_SPEEDf; 249 soc_field_t max_sp_fld = MAX_SRC_PORT_SPEEDf; 250 251 SOC_IF_ERROR_RETURN 252 (soc_reg32_get(unit, asf_config_reg, port, 0, &rval)); 253 *min_sp = soc_reg_field_get(unit, asf_config_reg, rval, min_sp_fld); 254 *max_sp = soc_reg_field_get(unit, asf_config_reg, rval, max_sp_fld); 255 return SOC_E_NONE; 256 257 } 258 259 /* 260 * Function: 261 * _soc_th3_idb_ca_bmop_set 262 * Purpose: 263 * Config bubble MOP settings given a logic port. 264 * Parameters: 265 * unit - (IN) unit number 266 * port - (IN) logic port 267 * port_speed - (IN) port_speed. 268 * mode - (IN) ASF mode 269 * Returns: 270 * SOC_E_XXX 271 */ 272 273 STATIC int 274 _soc_th3_idb_ca_bmop_set(int unit, soc_port_t port, int port_speed, int mode) 275 { 276 soc_reg_t reg; 277 uint64 rval64, fldval64; 278 int phy_port; 279 int pm_num; 280 int subp; 281 int pipe_num; 282 uint32 bmop_disable; 283 int latency_mode; 284 int speed_encoding; 285 soc_info_t *si; 286 287 static const soc_reg_t th3_idb_ca_control_2[_TH3_PIPES_PER_DEV] = { 288 IDB_CA_CONTROL_2_PIPE0r, IDB_CA_CONTROL_2_PIPE1r, 289 IDB_CA_CONTROL_2_PIPE2r, IDB_CA_CONTROL_2_PIPE3r, 290 IDB_CA_CONTROL_2_PIPE4r, IDB_CA_CONTROL_2_PIPE5r, 291 IDB_CA_CONTROL_2_PIPE6r, IDB_CA_CONTROL_2_PIPE7r 292 }; 293 static const soc_field_t ca_bmop_disable_fields[] = { 294 PORT0_BUBBLE_MOP_DISABLEf, PORT1_BUBBLE_MOP_DISABLEf, 295 PORT2_BUBBLE_MOP_DISABLEf, PORT3_BUBBLE_MOP_DISABLEf, 296 PORT4_BUBBLE_MOP_DISABLEf, PORT5_BUBBLE_MOP_DISABLEf, 297 PORT6_BUBBLE_MOP_DISABLEf, PORT7_BUBBLE_MOP_DISABLEf 298 }; 299 si = &(SOC_INFO(unit)); 300 if(si == NULL) { 301 return SOC_E_INTERNAL; 302 } 303 phy_port = si->port_l2p_mapping[port]; 304 pipe_num = si->port_pipe[port]; 305 pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port); 306 subp = soc_tomahawk3_get_subp_from_phy_port(phy_port); 307 308 SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency_mode)); 309 310 speed_encoding = 311 (mode == SOC_TH3_ASF_MODE_SAF) ? 0 : 312 soc_tomahawk3_speed_to_e2e_settings_class_map(port_speed); 313 bmop_disable = _soc_th3_bmop_settings_tbl[speed_encoding]. 314 bmop_disable[latency_mode]; 315 reg = th3_idb_ca_control_2[pipe_num]; 316 SOC_IF_ERROR_RETURN(soc_reg_rawport_get(unit, reg, REG_PORT_ANY, 317 pm_num, &rval64)); 318 COMPILER_64_SET(fldval64, 0, bmop_disable); 319 soc_reg64_field_set(unit, reg, &rval64, ca_bmop_disable_fields[subp], 320 fldval64); 321 SOC_IF_ERROR_RETURN(soc_reg_rawport_set(unit, reg, REG_PORT_ANY, 322 pm_num, rval64)); 323 return SOC_E_NONE; 324 } 325 326 327 /* 328 * Function: 329 * _soc_th3_asf_pause_update 330 * Purpose: 331 * Update PAUSE settings for a port 332 * Parameters: 333 * unit - (IN) unit number 334 * port - (IN) logical port number 335 * mode - (IN) forwarding mode 336 * Returns: 337 * SOC_E_XXX 338 */ 339 340 STATIC int 341 _soc_th3_asf_pause_update( 342 int unit, 343 soc_port_t port, 344 soc_th3_asf_mode_t mode) 345 { 346 347 #ifdef PORTMOD_SUPPORT 348 int rv = SOC_E_NONE; 349 portmod_pause_control_t pause_control; 350 351 SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit)); 352 353 rv = portmod_port_pause_control_get(unit, port, &pause_control); 354 if (!rv) { 355 /* Retrieve current rx/tx pause enable for port */ 356 SOC_IF_ERROR_RETURN( 357 portmod_port_pause_control_get(unit, port, &pause_control)); 358 if(mode != SOC_TH3_ASF_MODE_SAF) { 359 if (pause_control.rx_enable == 1) { 360 SOC_PBMP_PORT_ADD((_soc_th3_asf_ctrl[unit])->pause_restore, port); 361 pause_control.rx_enable = 0; 362 SOC_IF_ERROR_RETURN( 363 portmod_port_pause_control_set(unit, port, 364 &pause_control)); 365 } 366 } else { 367 if (SOC_PBMP_MEMBER((_soc_th3_asf_ctrl[unit])->pause_restore, port)) { 368 pause_control.rx_enable = 1; 369 SOC_IF_ERROR_RETURN( 370 portmod_port_pause_control_set(unit, port, &pause_control)); 371 SOC_PBMP_PORT_REMOVE(_soc_th3_asf_ctrl[unit]->pause_restore, port); 372 } 373 } 374 375 SOC_IF_ERROR_RETURN( 376 portmod_port_pause_control_set(unit, port, &pause_control)); 377 } 378 379 380 return rv; 381 382 #else /* PORTMOD_SUPPORT */ 383 return SOC_E_UNAVAIL; 384 #endif /* PORTMOD_SUPPORT */ 385 } 386 387 /** 388 * Function: 389 * _soc_th3_asf_tct_config_set 390 * Purpose: 391 * Configure Transitional CT. 392 * Parameters: 393 * unit - (IN) Unit number. 394 * Returns: 395 * SOC_E_xxx 396 */ 397 STATIC int 398 _soc_th3_asf_tct_config_set(int unit) 399 { 400 #define _SOC_TH3_ASF_VALID_SPEED_NUM 7 401 int i; 402 soc_reg_t reg = INVALIDr; 403 uint64 rval; 404 static const struct _soc_th3_tct_config_s { 405 uint8 itm_pkt_th; 406 uint8 mmu_pkt_th; 407 uint8 itm_cell_th; 408 uint8 mmu_cell_th; 409 uint32 cell_reduction_cycle; 410 uint32 cell_reduction_num; 411 uint32 exit_tct_timer; 412 uint32 exit_cell_threshold; 413 } config_t[_SOC_TH3_ASF_VALID_SPEED_NUM] = { 414 {16, 16, 38, 38, 4096, 8, 32000, 76}, 415 {16, 16, 38, 38, 4096, 8, 32000, 76}, 416 {16, 16, 38, 38, 4096, 8, 32000, 76}, 417 {16, 16, 38, 38, 4096, 8, 32000, 76}, 418 {31, 31, 38, 38, 4096, 8, 32000, 76}, 419 {62, 62, 62, 62, 4096, 8, 16000, 100}, 420 {124, 124, 124, 124, 4096, 8, 8000, 162}, 421 }; 422 423 for(i = 0; i < _SOC_TH3_ASF_VALID_SPEED_NUM; i++){ 424 reg = MMU_EBCTM_TCT_ENTER_SPEED_CFGr; 425 SOC_IF_ERROR_RETURN 426 (soc_reg64_get(unit, reg, REG_PORT_ANY, i, &rval)); 427 428 soc_reg64_field32_set(unit, reg, &rval, ENTER_TCT_ITM_PKT_THRESHOLDf, 429 config_t[i].itm_pkt_th); 430 soc_reg64_field32_set(unit, reg, &rval, ENTER_TCT_MMU_PKT_THRESHOLDf, 431 config_t[i].mmu_pkt_th); 432 soc_reg64_field32_set(unit, reg, &rval, ENTER_TCT_ITM_CELL_THRESHOLDf, 433 config_t[i].itm_cell_th); 434 soc_reg64_field32_set(unit, reg, &rval, ENTER_TCT_MMU_CELL_THRESHOLDf, 435 config_t[i].mmu_cell_th); 436 437 SOC_IF_ERROR_RETURN 438 (soc_reg64_set(unit, reg, REG_PORT_ANY, i, rval)); 439 440 reg = MMU_EBCTM_TCT_EXIT_SPEED_CFGr; 441 SOC_IF_ERROR_RETURN 442 (soc_reg64_get(unit, reg, REG_PORT_ANY, i, &rval)); 443 444 soc_reg64_field32_set(unit, reg, &rval, TCT_BUFFER_CELL_REDUCTION_CYCLESf, 445 config_t[i].cell_reduction_cycle); 446 soc_reg64_field32_set(unit, reg, &rval, TCT_BUFFER_CELL_REDUCTION_NUMBERf, 447 config_t[i].cell_reduction_num); 448 soc_reg64_field32_set(unit, reg, &rval, EXIT_TCT_TIMERf, 449 config_t[i].exit_tct_timer); 450 soc_reg64_field32_set(unit, reg, &rval, EXIT_TCT_MMU_CELL_THRESHOLDf, 451 config_t[i].exit_cell_threshold); 452 453 SOC_IF_ERROR_RETURN 454 (soc_reg64_set(unit, reg, REG_PORT_ANY, i, rval)); 455 } 456 457 #undef _SOC_TH3_ASF_VALID_SPEED_NUM 458 459 return SOC_E_NONE; 460 } 461 462 #if 0 463 /** 464 * Function: 465 * _soc_th3_asf_port_enable 466 * Purpose: 467 * Enable/Disable a given port for CT in IDB. 468 * Parameters: 469 * unit - (IN) Unit number. 470 * port - (IN) Logical port number. 471 * enable - (IN) 0: disable, 1: enable. 472 * Returns: 473 * SOC_E_xxx 474 */ 475 STATIC int 476 _soc_th3_idb_ca_asf_enable(int unit, soc_port_t port, uint8 ct_enable) 477 { 478 soc_reg_t reg; 479 uint64 rval64; 480 uint32 fval; 481 int phy_port; 482 int pm_num; 483 int subp; 484 int pipe_num; 485 soc_info_t *si = &SOC_INFO(unit); 486 static const soc_reg_t ca_control_2[_TH3_PIPES_PER_DEV] = 487 { 488 IDB_CA_CONTROL_2_PIPE0r, IDB_CA_CONTROL_2_PIPE1r, 489 IDB_CA_CONTROL_2_PIPE2r, IDB_CA_CONTROL_2_PIPE3r, 490 IDB_CA_CONTROL_2_PIPE4r, IDB_CA_CONTROL_2_PIPE5r, 491 IDB_CA_CONTROL_2_PIPE6r, IDB_CA_CONTROL_2_PIPE7r 492 }; 493 static const soc_field_t ca_ct_disable_fields[] = { 494 PORT0_CT_DISABLEf, PORT1_CT_DISABLEf, 495 PORT2_CT_DISABLEf, PORT3_CT_DISABLEf, 496 PORT4_CT_DISABLEf, PORT5_CT_DISABLEf, 497 PORT6_CT_DISABLEf, PORT7_CT_DISABLEf 498 }; 499 500 if(si == NULL) { 501 return SOC_E_INTERNAL; 502 } 503 phy_port = si->port_l2p_mapping[port]; 504 pipe_num = si->port_pipe[port]; 505 pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port); 506 reg = ca_control_2[pipe_num]; 507 subp = soc_tomahawk3_get_subp_from_phy_port(phy_port); 508 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 509 pm_num, &rval64)); 510 fval = ct_enable ? 0: 1; 511 soc_reg64_field32_set(unit, reg, &rval64, ca_ct_disable_fields[subp], 512 fval); 513 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, REG_PORT_ANY, 514 pm_num, rval64)); 515 return SOC_E_NONE; 516 } 517 #endif 518 519 /** 520 * Function: 521 * _soc_th3_asf_port_enable 522 * Purpose: 523 * Enable/Disable a given port for CT. 524 * Parameters: 525 * unit - (IN) Unit number. 526 * port - (IN) Logical port number. 527 * port_speed (IN) port speed in MB/s. 528 * enable - (IN) 0: disable, 1: enable. 529 * Returns: 530 * SOC_E_xxx 531 */ 532 STATIC int 533 _soc_th3_asf_port_enable( 534 int unit, 535 soc_port_t port, 536 int port_speed, 537 uint8 enable) 538 { 539 540 int dst_speed_id, max_src_speed_id; 541 uint32 rval; 542 soc_reg_t reg = MMU_EBCTM_EPORT_CT_CFGr; 543 dst_speed_id = _soc_th3_asf_speed_encoding_get(port_speed); 544 max_src_speed_id = _soc_th3_asf_speed_encoding_get 545 (MIN((port_speed*_SOC_TH3_ASF_MAX_FACTOR), _SOC_TH3_ASF_MAX_SPEED)); 546 547 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(dst_speed_id); 548 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(max_src_speed_id); 549 550 SOC_IF_ERROR_RETURN 551 (soc_reg32_get(unit, reg, port, 0, &rval)); 552 if(enable) { 553 554 soc_reg_field_set(unit, reg, &rval, DST_PORT_SPEEDf, dst_speed_id); 555 soc_reg_field_set(unit, reg, &rval, MAX_SRC_PORT_SPEEDf, 556 max_src_speed_id); 557 558 } 559 560 soc_reg_field_set(unit, reg, &rval, CT_ENABLEf, enable); 561 SOC_IF_ERROR_RETURN 562 (soc_reg32_set(unit, reg, port, 0, rval)); 563 564 /* disable/enable per port TCT */ 565 reg = MMU_EBCTM_EPORT_TCT_CFGr; 566 SOC_IF_ERROR_RETURN 567 (soc_reg32_get(unit, reg, port, 0, &rval)); 568 soc_reg_field_set(unit, reg, &rval, TCT_ENABLEf, enable); 569 SOC_IF_ERROR_RETURN 570 (soc_reg32_set(unit, reg, port, 0, rval)); 571 572 #if 0 573 /*enable/diable CT in IDB */ 574 SOC_IF_ERROR_RETURN 575 (_soc_th3_idb_ca_asf_enable(unit, port, enable)); 576 #endif 577 return SOC_E_NONE; 578 } 579 580 /** 581 * Function: 582 * _soc_th3_mmu_rl_tile_config_set 583 * Purpose: 584 * Configure Read launcher. 585 * Parameters: 586 * unit - (IN) Unit number. 587 * Returns: 588 * SOC_E_xxx 589 */ 590 STATIC int 591 _soc_th3_mmu_rl_tile_config_set(int unit) 592 { 593 soc_reg_t reg = INVALIDr; 594 uint64 rval; 595 596 static const struct _soc_th3_mmu_rl_tile_config_s { 597 598 uint32 buffer_activity; 599 uint32 high_th; 600 uint16 ebq_backup_th; 601 uint32 ebq_backup; 602 uint32 stop_cooloff; 603 604 } rl_config = { 605 1024, 5120, 64, 512, 512 606 }; 607 608 609 reg = MMU_RL_CT_TILE_ACTIVITYr; 610 SOC_IF_ERROR_RETURN 611 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 612 613 soc_reg64_field32_set(unit, reg, &rval, 614 STOP_DUE_TO_EBQ_BACKUPf, rl_config.ebq_backup); 615 soc_reg64_field32_set(unit, reg, &rval, 616 STOP_DUE_TO_BUFFER_ACTIVITYf, rl_config.buffer_activity); 617 soc_reg64_field32_set(unit, reg, &rval, 618 EBQ_BACKUP_THRESHOLDf, rl_config.ebq_backup_th); 619 620 SOC_IF_ERROR_RETURN 621 (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval)); 622 623 reg = MMU_RL_CT_TILE_ACTIVITY2r; 624 COMPILER_64_ZERO(rval); 625 626 SOC_IF_ERROR_RETURN 627 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 628 629 soc_reg64_field32_set(unit, reg, &rval, 630 STOP_COOLOFFf, rl_config.stop_cooloff); 631 soc_reg64_field32_set(unit, reg, &rval, 632 HIGH_ACTIVITY_THf, rl_config.high_th); 633 634 SOC_IF_ERROR_RETURN 635 (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval)); 636 637 return SOC_E_NONE; 638 } 639 640 /** 641 * Function: 642 * _soc_th3_port_asf_fifo_threshold_set 643 * Purpose: 644 * Set CT FIFO threshold. 645 * Parameters: 646 * unit - (IN) Unit number. 647 * Returns: 648 * SOC_E_xxx 649 */ 650 STATIC int 651 _soc_th3_port_asf_fifo_threshold_set(int unit) 652 { 653 int i; 654 soc_reg_t reg; 655 soc_reg_t ct_cfg_regs[] = { 656 MMU_EBCTM_CT_SPEED_6_CFGr, MMU_EBCTM_CT_SPEED_5_CFGr, 657 MMU_EBCTM_CT_SPEED_4_CFGr, MMU_EBCTM_CT_SPEED_3_CFGr, 658 MMU_EBCTM_CT_SPEED_2_CFGr, MMU_EBCTM_CT_SPEED_1_CFGr, 659 MMU_EBCTM_CT_SPEED_0_CFGr}; 660 uint32 rval; 661 uint32 fval[] = {66, 38, 24, 16, 16, 16, 16}; 662 soc_field_t field = CT_FIFO_THRESHOLDf; 663 664 for(i = 0; i < sizeof(fval)/sizeof(uint32); i++){ 665 reg = ct_cfg_regs[i]; 666 SOC_IF_ERROR_RETURN 667 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 668 soc_reg_field_set(unit, reg, &rval, field, fval[i]); 669 SOC_IF_ERROR_RETURN 670 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 671 } 672 673 return SOC_E_NONE; 674 } 675 676 /** 677 * Function: 678 * _soc_th3_mmu_saf_commitment_config_set 679 * Purpose: 680 * Set SAF commitment register based on pipe configuration. 681 * Parameters: 682 * unit - (IN) Unit number. 683 * pipe - (IN) Pipe number. 684 * Returns: 685 * SOC_E_xxx 686 */ 687 STATIC int 688 _soc_th3_mmu_saf_commitment_config_set(int unit, int pipe) { 689 690 int i, pipe_cfg; 691 uint32 rval; 692 const _soc_th3_saf_commit_config_t *saf_commit_p; 693 soc_reg_t reg = MMU_EBCTM_CT_BUDGET_SAF_COMMITMENT_CFGr; 694 soc_field_t field = CTBUDGET_SAFCOMMITMENTf; 695 696 if (pipe < 0 || pipe >= SOC_MAX_NUM_PIPES) { 697 return SOC_E_PARAM; 698 } 699 700 pipe_cfg = _SOC_PIPE_BANDWIDTH_CONFIG_OTHER; 701 702 saf_commit_p = &(_soc_th3_saf_commit_tbl[pipe_cfg]); 703 704 for(i = 0; i < _SOC_TH3_SAF_COMMIT_ID_NUM; i++) { 705 rval = 0; 706 SOC_IF_ERROR_RETURN( 707 soc_tomahawk3_eb_reg32_get(unit, reg, pipe, pipe, i, &rval)); 708 soc_reg_field_set(unit, reg, &rval, field, saf_commit_p->saf_commit_id[i]); 709 SOC_IF_ERROR_RETURN 710 (soc_tomahawk3_eb_reg32_set(unit, reg, pipe, pipe, i, rval)); 711 } 712 return SOC_E_NONE; 713 } 714 715 STATIC int 716 _soc_th3_mmu_saf_speed_bucket_config_set(int unit) { 717 #define MOP_SPACE_200G_LOW_FREQ 4 718 soc_reg_t speed_cfg_reg = MMU_EBCTM_MIN_MOP_SPACING_SPEED_BUCKET_1_CFGr; 719 uint32 rval = 0; 720 SOC_IF_ERROR_RETURN( 721 soc_tomahawk3_eb_reg32_get(unit, speed_cfg_reg, REG_PORT_ANY, 0, 0, 722 &rval)); 723 soc_reg_field_set(unit, speed_cfg_reg, &rval, NUM_CLK_PER_MOP_CELLf, 724 MOP_SPACE_200G_LOW_FREQ); 725 SOC_IF_ERROR_RETURN 726 (soc_tomahawk3_eb_reg32_set(unit, speed_cfg_reg, REG_PORT_ANY, 0, 0, 727 rval)); 728 #undef MOP_SPACE_200G_LOW_FREQ 729 return SOC_E_NONE; 730 } 731 732 STATIC int 733 _soc_th3_ct_override_settings (int unit) { 734 uint32 rval = 0; 735 soc_reg_t reg; 736 soc_field_t field; 737 int fld_val, pipe; 738 soc_info_t *si = &SOC_INFO(unit); 739 static const soc_reg_t idb_min_port_pick_regs[] = { 740 IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE0r, IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE1r, 741 IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE2r, IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE3r, 742 IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE4r, IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE5r, 743 IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE6r, IS_MIN_PORT_PICK_SPACING_WITHIN_PKT_PIPE7r 744 }; 745 746 static const soc_reg_t idb_min_cell_spacing_regs[] = { 747 IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE0r, IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE1r, 748 IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE2r, IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE3r, 749 IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE4r, IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE5r, 750 IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE6r, IS_MIN_CELL_SPACING_EOP_TO_SOP_PIPE7r 751 }; 752 753 754 /* MMU_EBCTM_CT_BUDGET_CFG.CT_BUDGET = 'd16 */ 755 reg = MMU_EBCTM_CT_BUDGET_CFGr; 756 field = CT_BUDGETf; 757 fld_val = 16; 758 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 759 soc_reg_field_set(unit, reg, &rval, field, fld_val); 760 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 761 762 /* MMU_RL_EBP_OVRD.CT_BURST_TH = 'd12 */ 763 reg = MMU_RL_EBP_OVRDr; 764 field = CT_BURST_THf; 765 fld_val = 12; 766 rval = 0x0; 767 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 768 soc_reg_field_set(unit, reg, &rval, field, fld_val); 769 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 770 771 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 772 if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 773 774 /* MIN_PORT_PICK_SPACING_WITHIN_PKT.MID_PKT_400G_MIN_SPACING = 6 */ 775 reg = idb_min_port_pick_regs[pipe]; 776 field = MID_PKT_400G_MIN_SPACINGf; 777 fld_val = 6; 778 rval = 0x0; 779 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pipe, 0, &rval)); 780 soc_reg_field_set(unit, reg, &rval, field, fld_val); 781 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pipe, 0, rval)); 782 783 /* IS_MIN_CELL_SPACING_EOP_TO_SOP.INTER_PKT_400G_MIN_SPACING = 2 */ 784 reg = idb_min_cell_spacing_regs[pipe]; 785 field = INTER_PKT_400G_MIN_SPACINGf; 786 fld_val = 2; 787 rval = 0x0; 788 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pipe, 0, &rval)); 789 soc_reg_field_set(unit, reg, &rval, field, fld_val); 790 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pipe, 0, rval)); 791 } 792 } 793 794 /* For lower frequencies, 795 MIN_PORT_PICK_SPACING_WITHIN_PKT.MID_PKT_200G_MIN_SPACING = 6 */ 796 if (si->frequency < 1325) { 797 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 798 if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 799 reg = idb_min_port_pick_regs[pipe]; 800 field = MID_PKT_200G_MIN_SPACINGf; 801 fld_val = 6; 802 rval = 0x0; 803 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pipe, 0, &rval)); 804 soc_reg_field_set(unit, reg, &rval, field, fld_val); 805 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pipe, 0, rval)); 806 } 807 } 808 } 809 810 811 812 return SOC_E_NONE; 813 } 814 815 /************************************* 816 * Init Start Routine * 817 * - Allocates ASF Ctrl structure * 818 * for the given unit * 819 */ 820 STATIC int 821 _soc_th3_asf_init_start(int unit) 822 { 823 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 824 825 if (!(_soc_th3_asf_ctrl[unit] = 826 sal_alloc(sizeof(_soc_th3_asf_ctrl_t), "TH3 ASF Ctrl Area"))) { 827 return SOC_E_MEMORY; 828 } 829 sal_memset(_soc_th3_asf_ctrl[unit], 0, sizeof(_soc_th3_asf_ctrl_t)); 830 831 return SOC_E_NONE; 832 } 833 834 /** 835 * Function: 836 * soc_th3_port_asf_valid 837 * Purpose: 838 * Check if a port is eligible for CT. 839 * Parameters: 840 * unit - (IN) Unit number. 841 * port - (IN) Logical port number. 842 * Returns: 843 * SOC_E_xxx 844 */ 845 int 846 soc_th3_port_asf_valid( 847 int unit, 848 soc_port_t port) 849 { 850 if(IS_CPU_PORT(unit, port) || IS_MANAGEMENT_PORT(unit, port) 851 || IS_LB_PORT(unit, port)) { 852 return FALSE; 853 } 854 855 return TRUE; 856 } 857 858 /** 859 * Function: 860 * soc_th3_port_asf_mode_get 861 * Purpose: 862 * Get traffic forwarding mode for a specific port. 863 * Parameters: 864 * unit - (IN) Unit number. 865 * port - (IN) Logical port number. 866 * port_speed - (IN) Port speed in MB/s. 867 * mode - (OUT) ASF mode 868 * Returns: 869 * SOC_E_xxx 870 */ 871 int 872 soc_th3_port_asf_mode_get( 873 int unit, 874 soc_port_t port, 875 int port_speed, 876 soc_th3_asf_mode_t *mode) 877 { 878 uint32 rval, enable; 879 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 880 881 if(NULL == mode) { 882 return SOC_E_INTERNAL; 883 } 884 if(soc_th3_port_asf_valid(unit, port)) { 885 soc_reg_t reg = MMU_EBCTM_EPORT_CT_CFGr; 886 SOC_IF_ERROR_RETURN 887 (soc_reg32_get(unit, reg, port, 0, &rval)); 888 enable = soc_reg_field_get(unit, reg, rval, CT_ENABLEf); 889 if(enable) { 890 *mode = SOC_TH3_ASF_MODE_CT; 891 } 892 else { 893 *mode = SOC_TH3_ASF_MODE_SAF; 894 } 895 } else { 896 *mode = SOC_TH3_ASF_MODE_SAF; 897 } 898 899 return SOC_E_NONE; 900 } 901 /** 902 * Function: 903 * soc_th3_port_asf_mode_set 904 * Purpose: 905 * Set traffic forwarding mode for a specific port. 906 * Parameters: 907 * unit - (IN) Unit number. 908 * port - (IN) Logical port number. 909 * port_speed - (IN) Port speed in MB/s. 910 * mode - (IN) ASF mode 911 * Returns: 912 * SOC_E_xxx 913 */ 914 int 915 soc_th3_port_asf_mode_set( 916 int unit, 917 soc_port_t port, 918 int port_speed, 919 soc_th3_asf_mode_t mode) 920 { 921 int init = 0; 922 soc_info_t *si = &SOC_INFO(unit); 923 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 924 925 if(SOC_TH3_ASF_MODE_INIT == mode) { 926 init = 1; 927 mode = SOC_TH3_ASF_MODE_SAF; 928 } 929 if ((!init) && (!_soc_th3_asf_ctrl[unit] || 930 !_soc_th3_asf_ctrl[unit]->init || !si)) { 931 return SOC_E_INTERNAL; 932 } 933 if(!soc_th3_port_asf_valid(unit, port)) { 934 if(SOC_TH3_ASF_MODE_SAF != mode) { 935 return SOC_E_UNAVAIL; 936 } 937 return SOC_E_NONE; 938 } 939 940 if(SOC_TH3_ASF_MODE_SAF != mode) { 941 /* CT settings */ 942 /* Bubble Mop setting */ 943 SOC_IF_ERROR_RETURN 944 (_soc_th3_idb_ca_bmop_set(unit, port, port_speed, mode)); 945 946 947 /* Disable pause */ 948 SOC_IF_ERROR_RETURN 949 (_soc_th3_asf_pause_update(unit, port, mode)); 950 951 /*Enable CT */ 952 SOC_IF_ERROR_RETURN 953 (_soc_th3_asf_port_enable(unit, port, port_speed, 1)); 954 955 /*bookkeeping */ 956 SOC_PBMP_PORT_ADD(_soc_th3_asf_ctrl[unit]->asf_ports, port); 957 958 } else { 959 /* Bubble Mop setting */ 960 SOC_IF_ERROR_RETURN 961 (_soc_th3_idb_ca_bmop_set(unit, port, port_speed, mode)); 962 /* Disable CT */ 963 SOC_IF_ERROR_RETURN 964 (_soc_th3_asf_port_enable(unit, port, port_speed, 0)); 965 /* Restore Pause */ 966 SOC_IF_ERROR_RETURN 967 (_soc_th3_asf_pause_update(unit, port, mode)); 968 969 /*bookkeeping */ 970 SOC_PBMP_PORT_REMOVE(_soc_th3_asf_ctrl[unit]->asf_ports, port); 971 } 972 973 return SOC_E_NONE; 974 } 975 976 /************************ 977 * Init Complete Marker * 978 */ 979 STATIC int 980 _soc_th3_asf_init_done(int unit) 981 { 982 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 983 984 985 if (_soc_th3_asf_ctrl[unit]) { 986 _soc_th3_asf_ctrl[unit]->init = 1; 987 988 return SOC_E_NONE; 989 } else { 990 return SOC_E_INTERNAL; 991 } 992 } 993 994 /** 995 * Function: 996 * soc_th3_asf_init 997 * Purpose: 998 * Initialize ASF subsystem and configure all the applicable ports 999 * to the specified forwarding mode 1000 * Parameters: 1001 * unit - (IN) Unit number. 1002 * Returns: 1003 * SOC_E_xxx 1004 */ 1005 1006 int 1007 soc_th3_asf_init(int unit) 1008 { 1009 soc_port_t port; 1010 int speed, pipe; 1011 uint32 pipe_map; 1012 soc_info_t *si; 1013 int core_clock; 1014 if (!(si = &SOC_INFO(unit))) { 1015 return SOC_E_INTERNAL; 1016 } 1017 SOC_IF_ERROR_RETURN(_soc_th3_asf_init_start(unit)); 1018 /* 1. chip/pipe-level init */ 1019 1020 /* 1.1 RL config */ 1021 SOC_IF_ERROR_RETURN(_soc_th3_mmu_rl_tile_config_set(unit)); 1022 /* 1.2 CT FIFO threshold config */ 1023 SOC_IF_ERROR_RETURN(_soc_th3_port_asf_fifo_threshold_set(unit)); 1024 /* 1.3 TCT config */ 1025 SOC_IF_ERROR_RETURN 1026 (_soc_th3_asf_tct_config_set(unit)); 1027 /* 1.4 SAF commitment config */ 1028 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1029 for(pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 1030 if(pipe_map & (1 << pipe)) { 1031 SOC_IF_ERROR_RETURN( 1032 _soc_th3_mmu_saf_commitment_config_set(unit, pipe)); 1033 } 1034 } 1035 1036 /* 1.5 MOP min spacing config for lower frequencies */ 1037 core_clock = si->frequency; 1038 if (core_clock <= 1000) { 1039 _soc_th3_mmu_saf_speed_bucket_config_set(unit); 1040 } 1041 1042 /* Additional settings for SDK-166459 */ 1043 SOC_IF_ERROR_RETURN(_soc_th3_ct_override_settings(unit)); 1044 1045 /* Per-port config */ 1046 PBMP_PORT_ITER(unit, port) { 1047 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) 1048 || IS_MANAGEMENT_PORT(unit, port)) { 1049 continue; 1050 } 1051 speed = _TH3_PORT_SPEED(si, port); 1052 SOC_IF_ERROR_RETURN 1053 (soc_th3_port_asf_mode_set(unit, port, speed, SOC_TH3_ASF_MODE_INIT)); 1054 1055 } 1056 1057 SOC_IF_ERROR_RETURN(_soc_th3_asf_init_done(unit)); 1058 return SOC_E_NONE; 1059 } 1060 1061 /************************ 1062 * Deinit Routine * 1063 */ 1064 int 1065 soc_th3_asf_deinit(int unit) 1066 { 1067 #if 0 1068 /* Unregister linkscan callback routine */ 1069 bcm_esw_linkscan_unregister(unit, soc_th_asf_linkscan_callback); 1070 #endif 1071 1072 if (_soc_th3_asf_ctrl[unit]) { 1073 sal_free(_soc_th3_asf_ctrl[unit]); 1074 _soc_th3_asf_ctrl[unit] = NULL; 1075 } 1076 1077 return SOC_E_NONE; 1078 } 1079 1080 /****************************************************************************** 1081 * Name: soc_th3_port_asf_detach * 1082 * Description: * 1083 * Update ASF when port deleted during Flexport operation * 1084 * IN params: * 1085 * - Unit * 1086 * - Logical Port * 1087 * Returns: * 1088 * - SOC_E_NONE on success * 1089 * - SOC_E_PARAM on invalid parameter * 1090 */ 1091 int 1092 soc_th3_port_asf_detach(int unit, soc_port_t port) 1093 { 1094 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 1095 1096 if (_soc_th3_asf_ctrl[unit] == NULL) { 1097 return SOC_E_INIT; 1098 } 1099 1100 SOC_IF_ERROR_RETURN 1101 (soc_th3_port_asf_mode_set(unit, port, 1102 SOC_INFO(unit).port_init_speed[port], 1103 SOC_TH3_ASF_MODE_SAF)); 1104 1105 if (soc_th3_port_asf_valid(unit, port)) { 1106 SOC_PBMP_PORT_REMOVE(_soc_th3_asf_ctrl[unit]->asf_ports, port); 1107 SOC_PBMP_PORT_REMOVE(_soc_th3_asf_ctrl[unit]->pause_restore, port); 1108 } 1109 return SOC_E_NONE; 1110 } 1111 1112 int 1113 soc_th3_asf_config_dump(int unit) 1114 { 1115 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 1116 if (!_soc_th3_asf_ctrl[unit] || !_soc_th3_asf_ctrl[unit]->init) { 1117 return SOC_E_INTERNAL; 1118 } 1119 return SOC_E_NONE; 1120 } 1121 1122 /** 1123 * Function: 1124 * _soc_th3_port_asf_class_get 1125 * Purpose: 1126 * Return CT class of a given port. 1127 * Parameters: 1128 * unit - (IN) Unit number. 1129 * port - (IN) logical port number. 1130 * class - (OUT) CT class 1131 * Returns: 1132 * SOC_E_xxx 1133 */ 1134 1135 STATIC int 1136 _soc_th3_port_asf_class_get( 1137 int unit, 1138 soc_port_t port, 1139 int *class) 1140 { 1141 edb_ip_cut_thru_class_entry_t entry; 1142 1143 if (NULL == class) { 1144 return SOC_E_PARAM; 1145 } 1146 1147 sal_memset(&entry, 0, sizeof(edb_ip_cut_thru_class_entry_t)); 1148 SOC_IF_ERROR_RETURN 1149 (READ_EDB_IP_CUT_THRU_CLASSm(unit, MEM_BLOCK_ALL, port, &entry)); 1150 *class = soc_mem_field32_get(unit, EDB_IP_CUT_THRU_CLASSm, &entry, 1151 CUT_THRU_CLASSf); 1152 1153 return SOC_E_NONE; 1154 } 1155 1156 /** 1157 * Function: 1158 * _soc_th3_port_asf_fifo_threshold_get 1159 * Purpose: 1160 * Get MMU CT FIFO Threshold based on port speed. 1161 * Parameters: 1162 * unit - (IN) Unit number. 1163 * port_speed - (IN) Port speed in MB/s. 1164 * ct_thresh - (OUT) CT FIFO Threshold. 1165 * Returns: 1166 * SOC_E_xxx 1167 */ 1168 STATIC int 1169 _soc_th3_port_asf_fifo_threshold_get( 1170 int unit, 1171 int port_speed, 1172 int* ct_thresh) 1173 1174 { 1175 int speed_id; 1176 uint32 rval; 1177 soc_reg_t reg = INVALIDr; 1178 soc_reg_t ct_cfg_regs[] = { 1179 INVALIDr, MMU_EBCTM_CT_SPEED_6_CFGr, 1180 MMU_EBCTM_CT_SPEED_5_CFGr, MMU_EBCTM_CT_SPEED_4_CFGr, 1181 MMU_EBCTM_CT_SPEED_3_CFGr, MMU_EBCTM_CT_SPEED_2_CFGr, 1182 MMU_EBCTM_CT_SPEED_1_CFGr, MMU_EBCTM_CT_SPEED_0_CFGr}; 1183 1184 speed_id = _soc_th3_asf_speed_encoding_get(port_speed); 1185 reg = ct_cfg_regs[speed_id]; 1186 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(speed_id); 1187 if(SOC_REG_IS_VALID(unit, reg)) { 1188 SOC_IF_ERROR_RETURN 1189 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1190 *ct_thresh = soc_reg_field_get(unit, reg, rval, CT_FIFO_THRESHOLDf); 1191 } 1192 return SOC_E_NONE; 1193 } 1194 1195 /** 1196 * Function: 1197 * soc_th3_port_asf_config_dump 1198 * Purpose: 1199 * Dump per-port asf configurations to diag Shell. 1200 * Parameters: 1201 * unit - (IN) Unit number. 1202 * port - (IN) Logical port number. 1203 * port_speed - (IN) Port speed in MB/s. 1204 * Returns: 1205 * SOC_E_xxx 1206 */ 1207 int 1208 soc_th3_port_asf_config_dump(int unit, soc_port_t port, int port_speed) 1209 { 1210 int ct_class = 0; 1211 uint8 src_class = 0, dst_class = 0; 1212 int min_sp = 0, max_sp = 0, fifo_threshold = 0; 1213 uint8 xmit_start_cnt[_SOC_TH3_CT_CLASS_VALID_NUM] = {0}; 1214 uint32 egr_mmu_cell_credits = 0; 1215 portmod_pause_control_t pause_control; 1216 int rxp; 1217 soc_th3_asf_mode_t mode = SOC_TH3_ASF_MODE_SAF; 1218 egr_mmu_cell_credit_entry_t credit_entry; 1219 int phy_port; 1220 int min_speed, max_speed, dst_port_speed; 1221 soc_info_t *si = &SOC_INFO(unit); 1222 1223 if(si == NULL) { 1224 return SOC_E_INTERNAL; 1225 } 1226 phy_port = si->port_l2p_mapping[port]; 1227 1228 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 1229 SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(unit)); 1230 1231 if (!soc_th3_port_asf_valid(unit, port)) { 1232 return BCM_E_NONE; 1233 } 1234 1235 if (!_soc_th3_asf_ctrl[unit] || !_soc_th3_asf_ctrl[unit]->init) { 1236 return SOC_E_INTERNAL; 1237 } 1238 1239 SOC_IF_ERROR_RETURN( 1240 soc_th3_port_asf_mode_get(unit, port, port_speed, &mode)); 1241 1242 SOC_IF_ERROR_RETURN( 1243 _soc_th3_port_asf_speed_limits_read(unit, port, &min_sp, &max_sp)); 1244 1245 min_speed = _soc_th3_asf_speed_get(min_sp); 1246 max_speed = _soc_th3_asf_speed_get(max_sp); 1247 1248 if (mode != SOC_TH3_ASF_MODE_SAF) { 1249 dst_port_speed = min_speed; 1250 } else { 1251 dst_port_speed = port_speed; 1252 } 1253 1254 SOC_IF_ERROR_RETURN( 1255 _soc_th3_port_asf_class_get(unit, port, &ct_class)); 1256 1257 SOC_IF_ERROR_RETURN( 1258 _soc_th3_port_asf_fifo_threshold_get(unit, dst_port_speed, 1259 &fifo_threshold)); 1260 1261 dst_class = soc_tomahawk3_get_ct_class(dst_port_speed); 1262 for (src_class = 0; src_class < _SOC_TH3_CT_CLASS_VALID_NUM; src_class++) { 1263 xmit_start_cnt[src_class] = _SOC_TH3_ASF_RETRV; 1264 SOC_IF_ERROR_RETURN( 1265 soc_th3_port_asf_xmit_start_count_get(unit, port, src_class, 1266 dst_class, mode, 1267 &xmit_start_cnt[src_class])); 1268 } 1269 1270 LOG_CLI(("%-5s %-3d %-3d %-6d %-6d %-3d ", SOC_PORT_NAME(unit, port), 1271 mode, ct_class, min_speed, max_speed, fifo_threshold)); 1272 for (src_class = 0; src_class < _SOC_TH3_CT_CLASS_VALID_NUM; src_class++) { 1273 LOG_CLI(("%-3d ", xmit_start_cnt[src_class])); 1274 } 1275 1276 1277 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY, 1278 phy_port, &credit_entry)); 1279 egr_mmu_cell_credits = soc_EGR_MMU_CELL_CREDITm_field32_get(unit, 1280 &credit_entry, CREDITf); 1281 1282 SOC_IF_ERROR_RETURN( 1283 portmod_port_pause_control_get(unit, port, &pause_control)); 1284 rxp = pause_control.rx_enable; 1285 LOG_CLI((" %-3d %-3d \n", egr_mmu_cell_credits, rxp)); 1286 1287 return SOC_E_NONE; 1288 } 1289 1290 /** 1291 * Function: 1292 * soc_th3_port_asf_show 1293 * Purpose: 1294 * Print per-port traffic forwarding mode in diag Shell. 1295 * Parameters: 1296 * unit - (IN) Unit number. 1297 * port - (IN) Logical port number. 1298 * port_speed - (IN) Port speed in MB/s. 1299 * Returns: 1300 * SOC_E_xxx 1301 */ 1302 int 1303 soc_th3_port_asf_show( 1304 int unit, 1305 soc_port_t port, 1306 int port_speed) 1307 { 1308 #define _STRING_LEN 5 1309 #define _ASF_MODE_NUM 2 1310 1311 char mode_str[_ASF_MODE_NUM][_STRING_LEN] = {"SAF", "CT"}; 1312 char speed_str[_SOC_TH3_CT_CLASS_VALID_NUM][_STRING_LEN] = { 1313 "SAF", "10G", "25G", "40G", 1314 "50G", "100G", "200G", "400G"}; 1315 soc_th3_asf_mode_t mode = SOC_TH3_ASF_MODE_SAF; 1316 int min_speed, max_speed; 1317 1318 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 1319 return BCM_E_NONE; 1320 } 1321 1322 SOC_IF_ERROR_RETURN( 1323 soc_th3_port_asf_mode_get(unit, port, port_speed, &mode)); 1324 1325 1326 LOG_CLI(("%-5s %-11s ", SOC_PORT_NAME(unit, port), mode_str[mode])); 1327 1328 if (SOC_TH3_ASF_MODE_SAF == mode) { 1329 LOG_CLI((" .. NA ..\n")); 1330 } else if (SOC_TH3_ASF_MODE_CT == mode) { 1331 SOC_IF_ERROR_RETURN( 1332 _soc_th3_port_asf_speed_limits_get(unit, port_speed, mode, 1333 &min_speed, &max_speed)); 1334 LOG_CLI(("%s / %s\n", speed_str[max_speed], speed_str[min_speed])); 1335 } 1336 #undef _STRING_LEN 1337 #undef _ASF_MODE_NUM 1338 return SOC_E_NONE; 1339 } 1340 1341 /** 1342 * Function: 1343 * soc_th3_asf_class_init 1344 * Purpose: 1345 * Initialize CT class memory. 1346 * Parameters: 1347 * unit - (IN) Unit number. 1348 * port - (IN) Logical port number. 1349 * class_id (IN) CT class ID. 1350 * Returns: 1351 * SOC_E_xxx 1352 */ 1353 1354 int 1355 soc_th3_asf_class_init( 1356 int unit, 1357 soc_port_t port, 1358 uint32 class_id) 1359 { 1360 edb_ip_cut_thru_class_entry_t entry; 1361 sal_memset(&entry, 0, sizeof(edb_ip_cut_thru_class_entry_t)); 1362 soc_mem_field32_set(unit, EDB_IP_CUT_THRU_CLASSm, &entry, 1363 CUT_THRU_CLASSf, class_id); 1364 SOC_IF_ERROR_RETURN 1365 (WRITE_EDB_IP_CUT_THRU_CLASSm(unit, MEM_BLOCK_ALL, port, &entry)); 1366 1367 return SOC_E_NONE; 1368 } 1369 1370 1371 /****************************************************************************** 1372 * Name: soc_th3_port_asf_xmit_start_count_get * 1373 * Description: * 1374 * Query or retrieve the XMIT Start Count for the specified source class * 1375 * of the port depending on the magic number passed in xmit_cnt * 1376 * IN params: * 1377 * - Unit * 1378 * - Logical Port * 1379 * - Source Port's Class * 1380 * - Destination Port's CT Class * 1381 * - ASF Mode * 1382 * IN/OUT params: * 1383 * - xmit_cnt : IN: carries magic number for query / retrieve * 1384 * - xmit_cnt : OUT: contains a valid XMIT START COUNT for the * 1385 * source port class, on success * 1386 * Returns: * 1387 * - SOC_E_NONE on success * 1388 * - SOC_E_PARAM on invalid parameter * 1389 * - SOC_E_INTERNAL on init/soc errors * 1390 */ 1391 int 1392 soc_th3_port_asf_xmit_start_count_get( 1393 int unit, 1394 soc_port_t port, 1395 int sc, 1396 int dc, 1397 soc_th3_asf_mode_t mode, 1398 uint8 *xmit_cnt) 1399 { 1400 soc_info_t *si; 1401 edb_xmit_start_count_entry_t entry; 1402 int port_idx; 1403 int pipe; 1404 soc_mem_t config_mem = INVALIDm; 1405 1406 _SOC_ASF_TH3_UNIT_VALIDATE(unit); 1407 1408 if (!(si = &SOC_INFO(unit))) { 1409 return SOC_E_INTERNAL; 1410 } 1411 1412 pipe = si->port_pipe[port]; 1413 config_mem = SOC_MEM_UNIQUE_ACC(unit, EDB_XMIT_START_COUNTm)[pipe]; 1414 1415 if (!xmit_cnt || 1416 !((mode >= SOC_TH3_ASF_MODE_SAF) && 1417 (mode <= SOC_TH3_ASF_MODE_CT))) { 1418 return SOC_E_PARAM; 1419 } 1420 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(sc); 1421 _SOC_TH3_ASF_SPEED_CLASS_VALIDATE(dc); 1422 1423 1424 if (_SOC_TH3_ASF_RETRV == *xmit_cnt) { 1425 *xmit_cnt = 0; 1426 port_idx = ((port % SOC_TH3_MAX_DEV_PORTS_PER_PIPE) 1427 * _SOC_TH3_CT_CLASS_TOTAL_NUM) + sc; 1428 1429 sal_memset(&entry, 0, sizeof(edb_xmit_start_count_entry_t)); 1430 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 1431 port_idx, &entry)); 1432 *xmit_cnt = soc_mem_field32_get(unit, config_mem, 1433 &entry, THRESHOLDf); 1434 } else if (_SOC_TH3_ASF_QUERY == *xmit_cnt) { 1435 /* TH3: EDB_XMIT_START_COUNT is programmed by 1436 * soc_tomahawk3_ep_set_xmit_start_cnt. This function should not be used 1437 * to query and program the memory*/ 1438 return SOC_E_INTERNAL; 1439 1440 } 1441 1442 return SOC_E_NONE; 1443 } 1444 /****************************************************************************** 1445 * Name: soc_th3_port_asf_xmit_start_count_set * 1446 * Description: * 1447 * Initialize XMIT START COUNT memory for all the source class for the * 1448 * specified port * 1449 * IN params: * 1450 * - Unit * 1451 * - Logical Port * 1452 * - Port Speed * 1453 * - ASF Mode * 1454 * - Extra cells (if any, to be added to xmit start count) * 1455 * Returns: * 1456 * - SOC_E_NONE on success * 1457 * - SOC_E_PARAM on invalid parameter * 1458 */ 1459 int 1460 soc_th3_port_asf_xmit_start_count_set( 1461 int unit, 1462 soc_port_t port, 1463 int port_speed, 1464 soc_th3_asf_mode_t mode, 1465 uint8 extra_cells) 1466 { 1467 edb_xmit_start_count_entry_t entry; 1468 soc_info_t *si = &SOC_INFO(unit); 1469 uint8 xmit_cnt = 0; 1470 int src_class, dst_class = 0, port_idx; 1471 int pipe; 1472 soc_mem_t config_mem = INVALIDm; 1473 1474 if (!((mode >= SOC_TH3_ASF_MODE_SAF) && 1475 (mode <= SOC_TH3_ASF_MODE_CFG_UPDATE))) { 1476 return SOC_E_PARAM; 1477 } 1478 1479 if (SOC_TH3_ASF_MODE_CFG_UPDATE != mode) { 1480 if (SOC_E_PARAM == (dst_class = soc_tomahawk3_get_ct_class(port_speed))) { 1481 /* port on a speed unsupported by CT - will resort to SAF */ 1482 dst_class = 0; 1483 } 1484 } 1485 1486 sal_memset(&entry, 0, sizeof(edb_xmit_start_count_entry_t)); 1487 1488 pipe = si->port_pipe[port]; 1489 config_mem = SOC_MEM_UNIQUE_ACC(unit, EDB_XMIT_START_COUNTm)[pipe]; 1490 1491 for (src_class = 0; src_class < _SOC_TH3_CT_CLASS_VALID_NUM; src_class++) { 1492 if (SOC_TH3_ASF_MODE_CFG_UPDATE == mode) { 1493 xmit_cnt = _SOC_TH3_ASF_RETRV; 1494 } else { 1495 xmit_cnt = _SOC_TH3_ASF_QUERY; 1496 } 1497 SOC_IF_ERROR_RETURN( 1498 soc_th3_port_asf_xmit_start_count_get(unit, port, src_class, 1499 dst_class, mode, &xmit_cnt)); 1500 xmit_cnt += extra_cells; 1501 1502 port_idx = ((port % SOC_TH3_MAX_DEV_PORTS_PER_PIPE) 1503 * _SOC_TH3_CT_CLASS_TOTAL_NUM) + src_class; 1504 1505 soc_mem_field32_set(unit, config_mem, &entry, 1506 THRESHOLDf, xmit_cnt); 1507 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 1508 port_idx, &entry)); 1509 } 1510 1511 return SOC_E_NONE; 1512 } 1513 1514 /************************ 1515 * ASF Warmboot Support * 1516 */ 1517 #ifdef BCM_WARM_BOOT_SUPPORT 1518 1519 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 1520 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 1521 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 1522 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 1523 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 1524 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 1525 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 1526 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 1527 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 1528 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_8 1529 1530 int 1531 soc_th3_asf_wb_memsz_get( 1532 int unit, 1533 OUT uint32* const mem_sz, 1534 uint16 scache_ver) 1535 { 1536 if (!mem_sz) { 1537 return SOC_E_PARAM; 1538 } 1539 *mem_sz = 0; 1540 1541 if (!SOC_WARM_BOOT(unit)) { 1542 if (!_soc_th3_asf_ctrl[unit] ) { 1543 return SOC_E_UNAVAIL; 1544 } 1545 if (!_soc_th3_asf_ctrl[unit]->init) { 1546 return SOC_E_INTERNAL; 1547 } 1548 } 1549 1550 *mem_sz = sizeof(_soc_th3_asf_wb_t); 1551 1552 if (scache_ver < BCM_WB_VERSION_1_8) { 1553 /* adjust wb area sz for lower versions */ 1554 *mem_sz -= sizeof(int); 1555 } 1556 1557 return SOC_E_NONE; 1558 } 1559 1560 int 1561 soc_th3_asf_wb_sync( 1562 int unit, 1563 IN_OUT uint8* const wb_data) 1564 { 1565 _soc_th3_asf_wb_t *wbd; 1566 1567 if (!_soc_th3_asf_ctrl[unit]) { 1568 return SOC_E_UNAVAIL; 1569 } 1570 if (!_soc_th3_asf_ctrl[unit]->init) { 1571 return SOC_E_INTERNAL; 1572 } 1573 if (!wb_data) { 1574 return SOC_E_PARAM; 1575 } 1576 1577 wbd = (_soc_th3_asf_wb_t *) wb_data; 1578 wbd->unit = unit; 1579 sal_memcpy(&wbd->asf_ctrl, _soc_th3_asf_ctrl[unit], 1580 sizeof(_soc_th3_asf_ctrl_t)); 1581 1582 return SOC_E_NONE; 1583 } 1584 1585 int 1586 soc_th3_asf_wb_recover( 1587 int unit, 1588 uint8* const wb_data, 1589 uint16 scache_ver) 1590 { 1591 _soc_th3_asf_wb_t *wbd; 1592 int adj = 0; /*scache ver adjustment */ 1593 1594 if (!SOC_WARM_BOOT(unit)) { 1595 return SOC_E_INTERNAL; 1596 } 1597 if (!wb_data) { 1598 return SOC_E_PARAM; 1599 } 1600 1601 wbd = (_soc_th3_asf_wb_t *) wb_data; 1602 if (wbd->unit == unit) { 1603 if (!(_soc_th3_asf_ctrl[unit] = 1604 sal_alloc(sizeof(_soc_th3_asf_ctrl_t), "TH ASF Ctrl Area"))) { 1605 return SOC_E_MEMORY; 1606 } 1607 1608 sal_memcpy(_soc_th3_asf_ctrl[unit], &wbd->asf_ctrl, 1609 (sizeof(_soc_th3_asf_ctrl_t) - adj)); 1610 } 1611 1612 LOG_CLI((BSL_META_U(unit, "*** unit %d: MMU-ASF subsystem warmbooted: \n"), 1613 unit)); 1614 1615 return SOC_E_NONE; 1616 } 1617 #endif /* BCM_WARM_BOOT_SUPPORT */ 1618 1619 #endif