macutil.c (164350B)
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 * MAC driver support utilities. 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 14 #include <soc/drv.h> 15 #include <soc/ll.h> 16 #include <soc/error.h> 17 #include <soc/portmode.h> 18 #include <soc/macutil.h> 19 #include <soc/phyctrl.h> 20 #include <soc/mem.h> 21 #if defined(BCM_TRIDENT2_SUPPORT) 22 #include <soc/trident2.h> 23 #endif 24 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 25 #include <soc/td2_td2p.h> 26 #endif 27 #if defined(BCM_KATANA_SUPPORT) 28 #include <soc/katana.h> 29 #endif 30 #if defined(BCM_SABER2_SUPPORT) 31 #include <soc/saber2.h> 32 #endif 33 #if defined(BCM_MONTEREY_SUPPORT) 34 #include <soc/monterey.h> 35 #endif 36 37 #if defined(BCM_APACHE_SUPPORT) 38 #include <soc/apache.h> 39 #endif 40 41 #if defined(BCM_TOMAHAWK_SUPPORT) 42 #include <soc/tomahawk.h> 43 #endif /* BCM_TOMAHAWK_SUPPORT */ 44 #if defined(BCM_TOMAHAWK2_SUPPORT) 45 #include <soc/tomahawk2.h> 46 #endif /* BCM_TOMAHAWK2_SUPPORT */ 47 #if defined (BCM_TOMAHAWK3_SUPPORT) 48 #include <soc/tomahawk3.h> 49 #endif 50 #if defined(BCM_KATANA2_SUPPORT) 51 #include <soc/katana2.h> 52 #include <bcm/types.h> 53 #include <bcm/cosq.h> 54 #endif 55 #if defined(BCM_GREYHOUND_SUPPORT) 56 #include <soc/greyhound.h> 57 #endif 58 #if defined(BCM_TRIDENT3_SUPPORT) 59 #include <soc/trident3.h> 60 #endif /* BCM_TRIDENT3_SUPPORT */ 61 #if defined(BCM_HURRICANE3_SUPPORT) 62 #include <soc/hurricane3.h> 63 #endif 64 #if defined(BCM_GREYHOUND2_SUPPORT) 65 #include <soc/greyhound2.h> 66 #endif 67 #include <soc/debug.h> 68 69 #if defined(BCM_TRIUMPH3_SUPPORT) 70 int ibod_recovery_in_progress[SOC_MAX_NUM_DEVICES]; 71 int egress_drain_timeout_flag[SOC_MAX_NUM_DEVICES]; 72 #endif 73 74 #if defined(BCM_KATANA2_SUPPORT) 75 #define _SOC_KT2_COSQ_MAX_INDEX_S0 128 76 #define _SOC_KT2_COSQ_MAX_INDEX_S1 256 77 #endif 78 79 #if defined (BCM_SABER2_SUPPORT) 80 #define _SOC_SB2_COSQ_MAX_INDEX_S0 16 81 #endif 82 83 #if defined(BCM_ESW_SUPPORT) 84 85 /* 86 * Function: 87 * soc_egress_cell_count 88 * Purpose: 89 * Return the approximate number of cells of packets pending 90 * in the MMU destined for a specified egress. 91 */ 92 int 93 soc_egress_cell_count(int unit, soc_port_t port, uint32 *count) 94 { 95 uint32 val; 96 int cos; 97 #if defined(BCM_TRIDENT_SUPPORT) 98 int i; 99 #if defined(BCM_TRIDENT2_SUPPORT) 100 soc_mem_t mem; 101 int index; 102 uint32 entry[SOC_MAX_MEM_WORDS]; 103 #if defined(BCM_TOMAHAWK_SUPPORT) 104 soc_info_t *si = &SOC_INFO(unit); 105 soc_mem_t base_mem; 106 int pipe, xpe, base; 107 #endif /* BCM_TOMAHAWK_SUPPORT */ 108 #endif /* BCM_TRIDENT2_SUPPORT */ 109 #endif /* BCM_TRIDENT_SUPPORT */ 110 #if defined(BCM_TOMAHAWK3_SUPPORT) 111 int itm, num_ucq, num_mcq, uc_base, mc_base; 112 #endif 113 *count = 0; 114 115 switch (SOC_CHIP_GROUP(unit)) { 116 case SOC_CHIP_BCM56504: 117 case SOC_CHIP_BCM56102: 118 case SOC_CHIP_BCM56304: 119 case SOC_CHIP_BCM56218: 120 case SOC_CHIP_BCM56112: 121 case SOC_CHIP_BCM56314: 122 case SOC_CHIP_BCM56514: 123 case SOC_CHIP_BCM56224: 124 case SOC_CHIP_BCM53314: 125 case SOC_CHIP_BCM56142: 126 case SOC_CHIP_BCM56150: 127 case SOC_CHIP_BCM53400: 128 case SOC_CHIP_BCM56160: 129 case SOC_CHIP_BCM53540: 130 for (cos = 0; cos < NUM_COS(unit); cos++) { 131 SOC_IF_ERROR_RETURN(soc_reg_egress_cell_count_get(unit, port, cos, &val)); 132 *count += val; 133 } 134 #if defined(BCM_HURRICANE1_SUPPORT) 135 if (SOC_IS_HURRICANE(unit) && 136 (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port))) { 137 if (SOC_REG_PORT_VALID(unit, XP_XBODE_CELL_CNTr, port)) { 138 SOC_IF_ERROR_RETURN( 139 READ_XP_XBODE_CELL_CNTr(unit, port, &val)); 140 *count += soc_reg_field_get( 141 unit, XP_XBODE_CELL_CNTr, val, CELL_CNTf); 142 } 143 if (SOC_REG_PORT_VALID(unit, GE_GBODE_CELL_CNTr, port)) { 144 SOC_IF_ERROR_RETURN(READ_GE_GBODE_CELL_CNTr(unit, port, &val)); 145 *count += soc_reg_field_get( 146 unit, GE_GBODE_CELL_CNTr, val, CELL_CNTf); 147 } 148 } 149 #endif 150 break; 151 #if defined(BCM_GREYHOUND2_SUPPORT) 152 case SOC_CHIP_BCM53570: 153 for (cos = 0; cos < SOC_REG_NUMELS(unit, COSLCCOUNTr); cos++) { 154 SOC_IF_ERROR_RETURN(READ_COSLCCOUNTr(unit, port, cos, &val)); 155 *count += soc_reg_field_get(unit, COSLCCOUNTr, val, 156 LCCOUNTf); 157 } 158 for (cos = 0; cos < SOC_REG_NUMELS(unit, COSLCCOUNT_QGROUPr); cos++) { 159 SOC_IF_ERROR_RETURN(READ_COSLCCOUNT_QGROUPr(unit, port, cos, &val)); 160 *count += soc_reg_field_get(unit, COSLCCOUNT_QGROUPr, val, 161 LCCOUNTf); 162 } 163 break; 164 #endif /* BCM_GREYHOUND2_SUPPORT */ 165 #if defined(BCM_HERCULES_SUPPORT) 166 case SOC_CHIP_BCM5675: 167 168 break; 169 #endif /* BCM_HERCULES_SUPPORT */ 170 #if defined(BCM_BRADLEY_SUPPORT) 171 case SOC_CHIP_BCM56800: 172 case SOC_CHIP_BCM56820: 173 case SOC_CHIP_BCM56725: 174 case SOC_CHIP_BCM88732: 175 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNTr(unit, port, &val)); 176 *count += soc_reg_field_get(unit, OP_PORT_TOTAL_COUNTr, val, 177 OP_PORT_TOTAL_COUNTf); 178 if (IS_GX_PORT(unit, port) && !SOC_IS_SHADOW(unit)) { 179 SOC_IF_ERROR_RETURN(READ_XP_XBODE_CELL_CNTr(unit, port, &val)); 180 *count += soc_reg_field_get(unit, XP_XBODE_CELL_CNTr, val, 181 CELL_CNTf); 182 SOC_IF_ERROR_RETURN(READ_GE_GBODE_CELL_CNTr(unit, port, &val)); 183 *count += soc_reg_field_get(unit, GE_GBODE_CELL_CNTr, val, 184 CELL_CNTf); 185 } 186 break; 187 #endif /* BCM_BRADLEY_SUPPORT */ 188 #if defined(BCM_TRIUMPH_SUPPORT) 189 case SOC_CHIP_BCM56624: 190 case SOC_CHIP_BCM56680: 191 case SOC_CHIP_BCM56634: 192 case SOC_CHIP_BCM56524: 193 case SOC_CHIP_BCM56685: 194 case SOC_CHIP_BCM56334: 195 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &val)); 196 *count += soc_reg_field_get(unit, OP_PORT_TOTAL_COUNT_CELLr, val, 197 OP_PORT_TOTAL_COUNT_CELLf); 198 break; 199 case SOC_CHIP_BCM56640: 200 case SOC_CHIP_BCM56340: 201 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &val)); 202 *count += soc_reg_field_get(unit, OP_PORT_TOTAL_COUNT_CELLr, val, 203 TOTAL_COUNTf); 204 break; 205 #endif /* BCM_TRIUMPH_SUPPORT */ 206 #if defined(BCM_TRIDENT_SUPPORT) 207 case SOC_CHIP_BCM56840: 208 for (i = 0; i < SOC_INFO(unit).port_num_uc_cosq[port]; i++) { 209 SOC_IF_ERROR_RETURN 210 (READ_OP_UC_QUEUE_TOTAL_COUNT_CELLr(unit, port, i, &val)); 211 *count += soc_reg_field_get(unit, OP_UC_QUEUE_TOTAL_COUNT_CELLr, 212 val, Q_TOTAL_COUNT_CELLf); 213 } 214 for (i = 0; i < SOC_INFO(unit).port_num_cosq[port]; i++) { 215 SOC_IF_ERROR_RETURN 216 (READ_OP_QUEUE_TOTAL_COUNT_CELLr(unit, port, i, &val)); 217 *count += soc_reg_field_get(unit, OP_QUEUE_TOTAL_COUNT_CELLr, 218 val, Q_TOTAL_COUNT_CELLf); 219 } 220 if (SOC_INFO(unit).port_num_ext_cosq[port] > 0) { 221 for (i = 0; i < SOC_INFO(unit).port_num_uc_cosq[port] + 222 SOC_INFO(unit).port_num_ext_cosq[port]; i++) { 223 SOC_IF_ERROR_RETURN 224 (READ_OP_EX_QUEUE_TOTAL_COUNT_CELLr(unit, port, i, &val)); 225 *count += soc_reg_field_get(unit, 226 OP_EX_QUEUE_TOTAL_COUNT_CELLr, val, 227 Q_TOTAL_COUNT_CELLf); 228 } 229 } 230 break; 231 #endif /* BCM_TRIDENT_SUPPORT */ 232 case SOC_CHIP_BCM56440: 233 case SOC_CHIP_BCM56450: 234 case SOC_CHIP_BCM56260: 235 case SOC_CHIP_BCM56270: 236 237 *count = 0; 238 break; 239 #if defined (BCM_TRIDENT2_SUPPORT) 240 case SOC_CHIP_BCM56850: 241 case SOC_CHIP_BCM56860: 242 /* Unicast queues */ 243 index = SOC_INFO(unit).port_uc_cosq_base[port]; 244 if (index < 1480) { 245 mem = MMU_THDU_XPIPE_COUNTER_QUEUEm; 246 } else { 247 index -= 1480; 248 mem = MMU_THDU_YPIPE_COUNTER_QUEUEm; 249 } 250 for (i = 0; i < SOC_INFO(unit).port_num_uc_cosq[port]; i++) { 251 SOC_IF_ERROR_RETURN 252 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index + i, entry)); 253 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 254 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 255 } 256 257 /* Multicast queues */ 258 index = SOC_INFO(unit).port_cosq_base[port]; 259 if (index < 568) { 260 mem = MMU_THDM_DB_QUEUE_COUNT_0m; 261 } else { 262 index -= 568; 263 mem = MMU_THDM_DB_QUEUE_COUNT_1m; 264 } 265 for (i = 0; i < SOC_INFO(unit).port_num_cosq[port]; i++) { 266 SOC_IF_ERROR_RETURN 267 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index + i, entry)); 268 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 269 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 270 } 271 break; 272 #endif /* BCM_TRIDENT2_SUPPORT */ 273 #if defined(BCM_TOMAHAWK_SUPPORT) 274 #if defined(BCM_TRIDENT3_SUPPORT) 275 case SOC_CHIP_BCM56870: 276 case SOC_CHIP_BCM56770: 277 case SOC_CHIP_BCM56370: 278 #endif 279 case SOC_CHIP_BCM56960: 280 case SOC_CHIP_BCM56965: 281 case SOC_CHIP_BCM56970: 282 pipe = si->port_pipe[port]; 283 base = si->port_uc_cosq_base[port]; 284 285 /* Since TH has xpe architecture, go over all XPEs and pick the instance 286 * which is valid for the given Mem/XPE/Pipe combination. 287 */ 288 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 289 /* UC queue Count */ 290 base_mem = MMU_THDU_COUNTER_QUEUEm; 291 292 /* Get XPE/PIPE view from base mem */ 293 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 294 295 if (mem == INVALIDm) { 296 /* If given XPE/PIPE combination is not valid, continue */ 297 continue; 298 } 299 for (i = 0; i < SOC_INFO(unit).port_num_uc_cosq[port]; i++) { 300 SOC_IF_ERROR_RETURN 301 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + i, &entry)); 302 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 303 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 304 } 305 } 306 307 base = si->port_cosq_base[port]; 308 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 309 /* MC queue Count */ 310 base_mem = MMU_THDM_DB_QUEUE_COUNTm; 311 312 /* xpe/pipe/mem check not performed again as it is similar to UC 313 * queue layout. 314 */ 315 316 /* Get XPE/PIPE view from base mem */ 317 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 318 319 if (mem == INVALIDm) { 320 /* If given XPE/PIPE combination is not valid, continue */ 321 continue; 322 } 323 for (i = 0; i < SOC_INFO(unit).port_num_cosq[port]; i++) { 324 SOC_IF_ERROR_RETURN 325 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + i, &entry)); 326 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 327 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 328 } 329 } 330 331 break; 332 #endif /* BCM_TOMAHAWK_SUPPORT */ 333 #if defined (BCM_TOMAHAWK3_SUPPORT) 334 case SOC_CHIP_BCM56980: 335 num_ucq = _soc_th3_get_num_ucq(unit); 336 num_mcq = _soc_th3_get_num_mcq(unit); 337 SOC_IF_ERROR_RETURN( 338 soc_th3_chip_queue_num_get(unit, port, 0, 0, &uc_base)); 339 SOC_IF_ERROR_RETURN( 340 soc_th3_chip_queue_num_get(unit, port, 0, 1, &mc_base)); 341 for (itm = 0; itm < NUM_ITM(unit); itm++) { 342 if (!soc_tomahawk3_itm_valid(unit, itm)) { 343 continue; 344 } 345 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, MMU_THDO_COUNTER_QUEUEm, itm); 346 for (i = 0; i < num_ucq; i++) { 347 SOC_IF_ERROR_RETURN( 348 soc_mem_read(unit, mem, MEM_BLOCK_ALL, uc_base + i, &entry)); 349 *count += soc_mem_field32_get(unit, mem, entry, TOTALCOUNTf); 350 } 351 for (i = 0; i< num_mcq; i++) { 352 SOC_IF_ERROR_RETURN( 353 soc_mem_read(unit, mem, MEM_BLOCK_ALL, mc_base + i, &entry)); 354 *count += soc_mem_field32_get(unit, mem, entry, TOTALCOUNTf); 355 } 356 } 357 break; 358 #endif 359 #if defined (BCM_APACHE_SUPPORT) 360 case SOC_CHIP_BCM56560: 361 case SOC_CHIP_BCM56670: 362 /* Unicast queues */ 363 index = SOC_INFO(unit).port_uc_cosq_base[port]; 364 mem = MMU_THDU_XPIPE_COUNTER_QUEUEm; 365 for (i = 0; i < SOC_INFO(unit).port_num_uc_cosq[port]; i++) { 366 SOC_IF_ERROR_RETURN 367 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index + i, entry)); 368 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 369 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 370 } 371 372 /* Multicast queues */ 373 index = SOC_INFO(unit).port_cosq_base[port]; 374 mem = MMU_THDM_DB_QUEUE_COUNT_0m; 375 for (i = 0; i < SOC_INFO(unit).port_num_cosq[port]; i++) { 376 SOC_IF_ERROR_RETURN 377 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index + i, entry)); 378 *count += soc_mem_field32_get(unit, mem, entry, MIN_COUNTf); 379 *count += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 380 } 381 break; 382 #endif /* BCM_APACHE_SUPPORT */ 383 384 default: 385 return SOC_E_UNAVAIL; 386 } 387 388 return SOC_E_NONE; 389 } 390 391 #if defined(BCM_TRIDENT2_SUPPORT) 392 int 393 _soc_egress_cell_check(int unit, soc_port_t port, int *empty) 394 { 395 switch (SOC_CHIP_GROUP(unit)) { 396 case SOC_CHIP_BCM56850: 397 #if defined (BCM_TRIDENT2PLUS_SUPPORT) 398 case SOC_CHIP_BCM56860: 399 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 400 { 401 int bit_pos, phy_port, mmu_port; 402 uint64 rval64; 403 if (SAL_BOOT_SIMULATION && !SAL_BOOT_QUICKTURN) { 404 *empty = TRUE; 405 break; 406 } 407 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 408 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 409 410 if (mmu_port <= 63) { 411 SOC_IF_ERROR_RETURN(READ_MMU_ENQ_PORT_EMPTY_BMP0r(unit, &rval64)); 412 } else { 413 SOC_IF_ERROR_RETURN(READ_MMU_ENQ_PORT_EMPTY_BMP1r(unit, &rval64)); 414 mmu_port = mmu_port - 64; 415 } 416 bit_pos = mmu_port & 0x3f; 417 *empty = COMPILER_64_BITTEST(rval64, bit_pos); 418 break; 419 } 420 #if defined (BCM_APACHE_SUPPORT) 421 case SOC_CHIP_BCM56560: 422 case SOC_CHIP_BCM56670: 423 { 424 int bit_pos, phy_port, mmu_port; 425 uint64 rval64; 426 if (SAL_BOOT_SIMULATION && !SAL_BOOT_QUICKTURN) { 427 *empty = TRUE; 428 break; 429 } 430 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 431 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 432 433 if (mmu_port <= 63) { 434 SOC_IF_ERROR_RETURN(READ_MMU_ENQ_PORT_EMPTY_BMP0r(unit, &rval64)); 435 } else { 436 SOC_IF_ERROR_RETURN(READ_MMU_ENQ_PORT_EMPTY_BMP1r(unit, &rval64)); 437 mmu_port = mmu_port - 64; 438 } 439 bit_pos = mmu_port & 0x3f; 440 *empty = COMPILER_64_BITTEST(rval64, bit_pos); 441 break; 442 } 443 #endif /* BCM_APACHE_SUPPORT */ 444 445 default: 446 return SOC_E_UNAVAIL; 447 } 448 449 return SOC_E_NONE; 450 } 451 #endif /* BCM_TRIDENT2_SUPPORT */ 452 453 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 454 STATIC int 455 _soc_port_txfifo_cell_count(int unit, soc_port_t port, int *count) 456 { 457 uint32 rval; 458 459 switch (SOC_CHIP_GROUP(unit)) { 460 case SOC_CHIP_BCM56640: 461 case SOC_CHIP_BCM56340: 462 SOC_IF_ERROR_RETURN(READ_PORT_TXFIFO_CELL_CNTr(unit, port, &rval)); 463 *count = soc_reg_field_get(unit, PORT_TXFIFO_CELL_CNTr, rval, 464 CELL_CNTf); 465 break; 466 case SOC_CHIP_BCM56850: 467 case SOC_CHIP_BCM56860: 468 /* Should only be called by CMAC driver */ 469 SOC_IF_ERROR_RETURN(READ_CPORT_TXFIFO_CELL_CNTr(unit, port, &rval)); 470 *count = soc_reg_field_get(unit, CPORT_TXFIFO_CELL_CNTr, rval, 471 CELL_CNTf); 472 break; 473 default: 474 return SOC_E_UNAVAIL; 475 } 476 477 return SOC_E_NONE; 478 } 479 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */ 480 481 STATIC int 482 soc_mmu_backpressure_clear(int unit, soc_port_t port) { 483 uint64 rv; 484 485 COMPILER_64_SET(rv, 0, 0); 486 487 switch (SOC_CHIP_GROUP(unit)) { 488 case SOC_CHIP_BCM56840: 489 case SOC_CHIP_BCM56640: 490 case SOC_CHIP_BCM56850: 491 case SOC_CHIP_BCM56860: 492 case SOC_CHIP_BCM56340: 493 case SOC_CHIP_BCM56960: 494 case SOC_CHIP_BCM56870: 495 case SOC_CHIP_BCM56770: 496 case SOC_CHIP_BCM56965: 497 case SOC_CHIP_BCM56970: 498 SOC_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKPr(unit, port, 0)); 499 break; 500 case SOC_CHIP_BCM56370: 501 SOC_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKP_64r(unit, port, rv)); 502 break; 503 504 case SOC_CHIP_BCM56440: 505 if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) { 506 SOC_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKPr(unit, port, 0)); 507 } 508 break; 509 #if defined (BCM_APACHE_SUPPORT) 510 case SOC_CHIP_BCM56560: 511 { 512 soc_mem_t mem; 513 soc_field_t field; 514 static const soc_mem_t flowcontrol_mems[4] = { 515 MMU_INTFI_S1_ST_TBm, 516 MMU_INTFI_FC_ST_TBL0m, 517 MMU_INTFI_FC_ST_TBL1m, 518 MMU_INTFI_FC_ST_TBL2m 519 }; 520 521 static const soc_field_t flowcontrol_fields[4] = { 522 COEFCf, 523 FC_STf, 524 FC_STf, 525 FC_STf 526 }; 527 uint32 *bmap; 528 uint32 *bmap_list[SOC_APACHE_NODE_LVL_MAX - SOC_APACHE_NODE_LVL_S1]; 529 uint32 fval; 530 mmu_intfi_s1_st_tb_entry_t rval; /* Can be used with all mems */ 531 int lvl, index, word, bit, word_count, index_count, cindex; 532 int bit_val, rv; 533 bmap_list[0] = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 534 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 535 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 536 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 537 538 for (lvl = 0; 539 lvl < (SOC_APACHE_NODE_LVL_MAX - SOC_APACHE_NODE_LVL_S1); 540 lvl++) { 541 bmap = bmap_list[lvl]; 542 mem = flowcontrol_mems[lvl]; 543 field = flowcontrol_fields[lvl]; 544 index_count = soc_mem_index_count(unit, mem) * 4; 545 word_count = _SHR_BITDCLSIZE(index_count); 546 547 for (word = 0; word < word_count; word++) { 548 if (bmap[word] == 0) { 549 continue; 550 } 551 for (bit = 0; bit < SHR_BITWID; bit++) { 552 if (!(bmap[word] & (1 << bit))) { 553 continue; 554 } 555 index = (word * SHR_BITWID + bit) / 4; 556 cindex = (word * SHR_BITWID + bit) % 4; 557 bit_val = 1 << cindex; 558 /* Save the entry */ 559 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 560 &rval); 561 if (SOC_FAILURE(rv)) { 562 break; 563 } 564 fval = soc_mem_field32_get(unit, mem, &rval, field); 565 /* Disable the flowcontrol */ 566 fval = fval & (~bit_val); 567 568 soc_mem_field32_set(unit, mem, &rval, field, fval); 569 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 570 &rval); 571 if (SOC_FAILURE(rv)) { 572 break; 573 } 574 } 575 } 576 577 } 578 soc_mem_field32_set(unit, mem, &rval, field, 0); 579 rv = soc_mem_write(unit, MMU_INTFI_PORT_COEFC_TBm, MEM_BLOCK_ANY, port, 580 &rval); 581 if (SOC_FAILURE(rv)) { 582 break; 583 } 584 585 SOC_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKPr(unit, port, 0)); 586 break; 587 } 588 #endif /* BCM_APACHE_SUPPORT */ 589 default: 590 break; 591 } 592 593 return SOC_E_NONE; 594 } 595 596 int 597 _soc_egress_metering_freeze(int unit, soc_port_t port, void **setting) 598 { 599 int rv; 600 601 rv = SOC_E_NONE; 602 603 SOC_EGRESS_METERING_LOCK(unit); 604 605 switch (SOC_CHIP_GROUP(unit)) { 606 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 607 case SOC_CHIP_BCM56820: 608 case SOC_CHIP_BCM56725: 609 case SOC_CHIP_BCM56224: 610 case SOC_CHIP_BCM53314: 611 case SOC_CHIP_BCM56142: 612 { 613 uint32 *rval32; 614 615 rval32 = sal_alloc(sizeof(uint32), "shaper buffer"); 616 if (rval32 == NULL) { 617 rv = SOC_E_MEMORY; 618 break; 619 } 620 621 rv = READ_EGRMETERINGCONFIGr(unit, port, rval32); 622 if (SOC_SUCCESS(rv)) { 623 rv = WRITE_EGRMETERINGCONFIGr(unit, port, 0); 624 } 625 if (SOC_FAILURE(rv)) { 626 sal_free(rval32); 627 break; 628 } 629 *setting = rval32; 630 break; 631 } 632 #endif /* BCM_RAVEN_SUPPORT || BCM_SCORPION_SUPPORT || BCM_HURRICANE_SUPPORT */ 633 #if defined (BCM_HURRICANE2_SUPPORT) 634 case SOC_CHIP_BCM56150: 635 case SOC_CHIP_BCM53400: 636 case SOC_CHIP_BCM56160: 637 case SOC_CHIP_BCM53540: 638 { 639 int i; 640 uint32 regval; 641 uint32 *buffer; 642 int count; 643 644 /* buffer required = (X+1), for store original register setting. 645 * MAXBUCKETCONFIGr : X elements for a port 646 * EGRMETERINGCONFIG : 1 register value for a port 647 */ 648 count = SOC_REG_NUMELS(unit, MAXBUCKETCONFIGr) + 1; 649 buffer = sal_alloc(count * sizeof(uint32), "shaper buffer"); 650 if (buffer == NULL) { 651 rv = SOC_E_MEMORY; 652 goto _hu_freeze_abort; 653 } 654 sal_memset(buffer, 0, count); 655 656 /* save the original configuration : MAXBUCKETCONFIGr */ 657 count = 0; 658 for (i = 0; i < SOC_REG_NUMELS(unit, MAXBUCKETCONFIGr); i++) { 659 rv = READ_MAXBUCKETCONFIGr(unit, port, i, ®val); 660 if (SOC_FAILURE(rv)) { 661 sal_free(buffer); 662 goto _hu_freeze_abort; 663 } 664 buffer[count] = regval; 665 count ++; 666 /* Disable egress metering for this port */ 667 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, MAX_REFRESHf, 0); 668 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, MAX_THD_SELf, 0); 669 rv = WRITE_MAXBUCKETCONFIGr(unit, port, i, regval); 670 if (SOC_FAILURE(rv)) { 671 sal_free(buffer); 672 goto _hu_freeze_abort; 673 } 674 } 675 676 /* save the original configuration : EGRMETERINGCONFIGr */ 677 rv = READ_EGRMETERINGCONFIGr(unit, port, ®val); 678 if (SOC_SUCCESS(rv)) { 679 buffer[count] = regval; 680 count ++; 681 rv = WRITE_EGRMETERINGCONFIGr(unit, port, 0); 682 } 683 if (SOC_FAILURE(rv)) { 684 sal_free(buffer); 685 goto _hu_freeze_abort; 686 } 687 *setting = buffer; 688 _hu_freeze_abort: 689 break; 690 } 691 #endif /* BCM_HURRICANE2_SUPPORT */ 692 #if defined(BCM_GREYHOUND2_SUPPORT) 693 case SOC_CHIP_BCM53570: 694 { 695 int i; 696 uint32 value; 697 uint32 *buffer; 698 int count; 699 int qlayer_entry_count = 0; 700 int qgroup_entry_count = 0; 701 soc_mem_t config_mem = INVALIDm; 702 uint32 entry[SOC_MAX_MEM_WORDS]; 703 int memidx; 704 int is_64q_port; 705 706 rv = soc_gh2_64q_port_check(unit, port, &is_64q_port); 707 if (SOC_FAILURE(rv)) { 708 break; 709 } 710 711 if (is_64q_port) { 712 qlayer_entry_count = SOC_GH2_QLAYER_COSQ_PER_PORT_NUM; 713 qgroup_entry_count = SOC_GH2_QGROUP_PER_PORT_NUM; 714 } else { 715 qlayer_entry_count = SOC_GH2_LEGACY_QUEUE_NUM; 716 qgroup_entry_count = 0; 717 } 718 719 /* buffer required (X*2+Y*2+1) for store original setting. 720 * MMU port 0~57: X=8, Y=0 721 * MMU port 58-65 : X=64, Y=8 722 * MMU_MAX_BUCKET_QLAYERm : 723 * X entries for a port, 2 fields (REFRESHf, THD_SELf)stored 724 * MMU_MAX_BUCKET_QGROUPm : Y entries for a port 725 * Y entries for a port, 2 fields (REFRESHf, THD_SELf)stored 726 * EGRMETERINGCONFIG : 1 register value for a port 727 */ 728 count = (qlayer_entry_count * 2) + (qgroup_entry_count * 2) + 1; 729 buffer = sal_alloc(count * sizeof(uint32), "shaper buffer"); 730 if (buffer == NULL) { 731 rv = SOC_E_MEMORY; 732 break; 733 } 734 sal_memset(buffer, 0, count); 735 736 /* save the original configuration : MMU_MAX_BUCKET_QLAYERm */ 737 count = 0; 738 config_mem = MMU_MAX_BUCKET_QLAYERm; 739 rv = soc_gh2_mmu_bucket_qlayer_index(unit, port, 0, &memidx); 740 if (SOC_FAILURE(rv)) { 741 sal_free(buffer); 742 break; 743 } 744 for (i = memidx; i < qlayer_entry_count; i++) { 745 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 746 i, &entry); 747 if (SOC_FAILURE(rv)) { 748 sal_free(buffer); 749 break; 750 } 751 value = soc_mem_field32_get(unit, config_mem, 752 &entry, REFRESHf); 753 buffer[count] = value; 754 count ++; 755 value = soc_mem_field32_get(unit, config_mem, 756 &entry, THD_SELf); 757 buffer[count] = value; 758 count ++; 759 760 /* Disable egress metering for this port */ 761 soc_mem_field32_set(unit, config_mem, &entry, REFRESHf, 0); 762 soc_mem_field32_set(unit, config_mem, &entry, THD_SELf, 0); 763 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 764 i, &entry); 765 if (SOC_FAILURE(rv)) { 766 sal_free(buffer); 767 break; 768 } 769 } 770 771 /* save the original configuration : MMU_MAX_BUCKET_QGROUPm */ 772 if (qgroup_entry_count) { 773 config_mem = MMU_MAX_BUCKET_QGROUPm; 774 rv = soc_gh2_mmu_bucket_qgroup_index(unit, port, 0, &memidx); 775 if (SOC_FAILURE(rv)) { 776 sal_free(buffer); 777 break; 778 } 779 for (i = memidx; i < qgroup_entry_count; i++) { 780 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 781 i, &entry); 782 if (SOC_FAILURE(rv)) { 783 sal_free(buffer); 784 break; 785 } 786 value = soc_mem_field32_get(unit, config_mem, 787 &entry, REFRESHf); 788 buffer[count] = value; 789 count ++; 790 value = soc_mem_field32_get(unit, config_mem, 791 &entry, THD_SELf); 792 buffer[count] = value; 793 count ++; 794 795 /* Disable egress metering for this port */ 796 soc_mem_field32_set(unit, config_mem, &entry, REFRESHf, 0); 797 soc_mem_field32_set(unit, config_mem, &entry, THD_SELf, 0); 798 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 799 i, &entry); 800 if (SOC_FAILURE(rv)) { 801 sal_free(buffer); 802 break; 803 } 804 } 805 } 806 807 /* save the original configuration : EGRMETERINGCONFIGr */ 808 rv = READ_EGRMETERINGCONFIGr(unit, port, &value); 809 if (SOC_SUCCESS(rv)) { 810 buffer[count] = value; 811 count ++; 812 rv = WRITE_EGRMETERINGCONFIGr(unit, port, 0); 813 } 814 if (SOC_FAILURE(rv)) { 815 sal_free(buffer); 816 break; 817 } 818 *setting = buffer; 819 break; 820 } 821 #endif /* BCM_GREYHOUND2_SUPPORT */ 822 #if defined(BCM_TRIUMPH_SUPPORT) 823 case SOC_CHIP_BCM56624: 824 case SOC_CHIP_BCM56680: 825 case SOC_CHIP_BCM56634: 826 case SOC_CHIP_BCM56524: 827 case SOC_CHIP_BCM56685: 828 case SOC_CHIP_BCM56334: 829 { 830 uint64 *rval64, temp_rval64; 831 832 rval64 = sal_alloc(sizeof(uint64), "shaper buffer"); 833 if (rval64 == NULL) { 834 rv = SOC_E_MEMORY; 835 break; 836 } 837 838 rv = READ_EGRMETERINGCONFIG_64r(unit, port, rval64); 839 if (SOC_SUCCESS(rv)) { 840 COMPILER_64_ZERO(temp_rval64); 841 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, temp_rval64); 842 } 843 if (SOC_FAILURE(rv)) { 844 sal_free(rval64); 845 break; 846 } 847 *setting = rval64; 848 break; 849 } 850 case SOC_CHIP_BCM56840: 851 { 852 uint64 zero_rval64; 853 int count, index, queue_cnt; 854 soc_info_t *si; 855 uint64 *buffer; 856 857 si = &SOC_INFO(unit); 858 COMPILER_64_ZERO(zero_rval64); 859 queue_cnt = si->port_num_uc_cosq[port] + si->port_num_cosq[port] + 860 si->port_num_ext_cosq[port]; 861 /* Port level + S2 + S3 + UCQ + MCQ + EXT_UCQ. */ 862 count = 1 + 4 + 4 + queue_cnt; 863 864 buffer = sal_alloc(count * sizeof(mem_entry_t), 865 "shaper buffer"); 866 if (buffer == NULL) { 867 rv = SOC_E_MEMORY; 868 goto _trident_freeze_abort; 869 } 870 871 count = 0; 872 /* Port level meter. */ 873 rv = READ_EGRMETERINGCONFIG_64r(unit, port, &buffer[count]); 874 if (SOC_SUCCESS(rv)) { 875 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, zero_rval64); 876 } 877 if (SOC_FAILURE(rv)) { 878 sal_free(buffer); 879 goto _trident_freeze_abort; 880 } 881 count++; 882 883 if (!IS_CPU_PORT(unit, port)) { 884 /* S2 meter (including MC group). */ 885 for (index = 0; index < 4; index++) { 886 rv = READ_S2_MAXBUCKETCONFIG_64r(unit, port, index, 887 &buffer[count]); 888 if (SOC_SUCCESS(rv)) { 889 rv = WRITE_S2_MAXBUCKETCONFIG_64r(unit, port, index, 890 zero_rval64); 891 } 892 if (SOC_FAILURE(rv)) { 893 sal_free(buffer); 894 goto _trident_freeze_abort; 895 } 896 count++; 897 } 898 /* S3 meter. */ 899 for (index = 0; index < 4; index++) { 900 rv = READ_S3_MAXBUCKETCONFIG_64r(unit, port, index, 901 &buffer[count]); 902 if (SOC_SUCCESS(rv)) { 903 rv = WRITE_S3_MAXBUCKETCONFIG_64r(unit, port, index, 904 zero_rval64); 905 } 906 if (SOC_FAILURE(rv)) { 907 sal_free(buffer); 908 goto _trident_freeze_abort; 909 } 910 count++; 911 } 912 } 913 914 /* Queue meter. */ 915 for (index = 0; index < queue_cnt; index++) { 916 rv = READ_MAXBUCKETCONFIG_64r(unit, port, index, 917 &buffer[count]); 918 if (SOC_SUCCESS(rv)) { 919 rv = WRITE_MAXBUCKETCONFIG_64r(unit, port, index, 920 zero_rval64); 921 } 922 if (SOC_FAILURE(rv)) { 923 sal_free(buffer); 924 goto _trident_freeze_abort; 925 } 926 count++; 927 } 928 *setting = buffer; 929 _trident_freeze_abort: 930 break; 931 } 932 #endif /* BCM_TRIUMPH_SUPPORT */ 933 #ifdef BCM_TRIUMPH3_SUPPORT 934 case SOC_CHIP_BCM56640: 935 case SOC_CHIP_BCM56340: 936 { 937 uint64 rval64, temp_rval64; 938 soc_mem_t mem; 939 uint32 *bmap, *bmap_list[3]; 940 int lvl, index, word, bit, word_count, index_count, count; 941 mem_entry_t *buffer; 942 static const soc_mem_t shaper_mems[3] = { 943 MMU_MTRO_L0_MEMm, MMU_MTRO_L1_MEMm, MMU_MTRO_L2_MEMm 944 }; 945 946 bmap_list[0] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 947 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 948 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 949 950 SOC_LLS_SCHEDULER_LOCK(unit); 951 count = 1; /* One entry for port level */ 952 for (lvl = 0; lvl < 3; lvl++) { 953 bmap = bmap_list[lvl]; 954 mem = shaper_mems[lvl]; 955 index_count = soc_mem_index_count(unit, mem); 956 word_count = _SHR_BITDCLSIZE(index_count); 957 for (word = 0; word < word_count; word++) { 958 if (bmap[word] != 0) { 959 count += _shr_popcount(bmap[word]); 960 } 961 } 962 } 963 964 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 965 "shaper buffer"); 966 if (buffer == NULL) { 967 rv = SOC_E_MEMORY; 968 goto _tr_freeze_abort; 969 } 970 971 /* Port level meter */ 972 rv = READ_EGRMETERINGCONFIG_64r(unit, port, &rval64); 973 if (SOC_SUCCESS(rv)) { 974 COMPILER_64_ZERO(temp_rval64); 975 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, temp_rval64); 976 } 977 if (SOC_FAILURE(rv)) { 978 sal_free(buffer); 979 goto _tr_freeze_abort; 980 } 981 sal_memcpy(&buffer[0].entry[0], &rval64, sizeof(uint64)); 982 983 /* L0, L1, L2 meter */ 984 count = 1; 985 for (lvl = 0; lvl < 3; lvl++) { 986 bmap = bmap_list[lvl]; 987 mem = shaper_mems[lvl]; 988 index_count = soc_mem_index_count(unit, mem); 989 word_count = _SHR_BITDCLSIZE(index_count); 990 991 for (word = 0; word < word_count; word++) { 992 if (bmap[word] == 0) { 993 continue; 994 } 995 for (bit = 0; bit < SHR_BITWID; bit++) { 996 if (!(bmap[word] & (1 << bit))) { 997 continue; 998 } 999 index = word * SHR_BITWID + bit; 1000 /* Save the entry */ 1001 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1002 &buffer[count].entry); 1003 if (SOC_FAILURE(rv)) { 1004 sal_free(buffer); 1005 goto _tr_freeze_abort; 1006 } 1007 buffer[count].mem = mem; 1008 buffer[count].index = index; 1009 count++; 1010 /* Disable the entry */ 1011 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 1012 soc_mem_entry_null(unit, mem)); 1013 if (SOC_FAILURE(rv)) { 1014 sal_free(buffer); 1015 goto _tr_freeze_abort; 1016 } 1017 } 1018 } 1019 } 1020 1021 buffer[count].mem = INVALIDm; 1022 *setting = buffer; 1023 _tr_freeze_abort: 1024 SOC_LLS_SCHEDULER_UNLOCK(unit); 1025 break; 1026 } 1027 #endif /* BCM_TRIUMPH3_SUPPORT */ 1028 #ifdef BCM_APACHE_SUPPORT 1029 case SOC_CHIP_BCM56560: 1030 { 1031 soc_mem_t mem; 1032 uint32 *bmap, 1033 *bmap_list[SOC_APACHE_NODE_LVL_MAX - SOC_APACHE_NODE_LVL_S1]; 1034 int pipe, phy_port, mmu_port; 1035 int lvl, index, word, bit, word_count, index_count, count; 1036 mem_entry_t *buffer; 1037 static const int max_l1_table = 2; 1038 static const int max_l2_table = 8; 1039 static const soc_mem_t port_shaper_mems[1] = { 1040 MMU_MTRO_EGRMETERINGCONFIG_MEM_0m 1041 }; 1042 static const soc_mem_t shaper_mems[][1] = { 1043 { MMU_MTRO_S1_MEM_0m}, 1044 { MMU_MTRO_L0_MEM_0m}, 1045 { MMU_MTRO_L1_MEM_0m}, 1046 { MMU_MTRO_L2_MEM_0m} 1047 }; 1048 static const soc_mem_t l1_shaper_mems[] = { 1049 MMU_MTRO_L1_MEM_0m, 1050 MMU_MTRO_L1_MEM_1m 1051 }; 1052 static const soc_mem_t l2_shaper_mems[] = { 1053 MMU_MTRO_L2_MEM_0m, 1054 MMU_MTRO_L2_MEM_1m, 1055 MMU_MTRO_L2_MEM_2m, 1056 MMU_MTRO_L2_MEM_3m, 1057 MMU_MTRO_L2_MEM_4m, 1058 MMU_MTRO_L2_MEM_5m, 1059 MMU_MTRO_L2_MEM_6m, 1060 MMU_MTRO_L2_MEM_7m 1061 }; 1062 1063 pipe = 0; 1064 bmap_list[0] = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 1065 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 1066 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 1067 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 1068 1069 SOC_LLS_SCHEDULER_LOCK(unit); 1070 count = 1; /* One entry for port level */ 1071 for (lvl = 0; 1072 lvl < (SOC_APACHE_NODE_LVL_MAX - SOC_APACHE_NODE_LVL_S1); 1073 lvl++) { 1074 bmap = bmap_list[lvl]; 1075 mem = shaper_mems[lvl][pipe]; 1076 index_count = soc_mem_index_count(unit, mem); 1077 word_count = _SHR_BITDCLSIZE(index_count); 1078 for (word = 0; word < word_count; word++) { 1079 if (bmap[word] != 0) { 1080 count += _shr_popcount(bmap[word]); 1081 } 1082 } 1083 } 1084 1085 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 1086 "shaper buffer"); 1087 if (buffer == NULL) { 1088 rv = SOC_E_MEMORY; 1089 goto _ap_freeze_abort; 1090 } 1091 1092 count = 0; 1093 1094 /* Port level meter */ 1095 mem = port_shaper_mems[pipe]; 1096 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1097 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 1098 index = mmu_port & 0x7f; 1099 /* Save the entry */ 1100 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1101 &buffer[count].entry); 1102 if (SOC_FAILURE(rv)) { 1103 sal_free(buffer); 1104 goto _ap_freeze_abort; 1105 } 1106 buffer[count].mem = mem; 1107 buffer[count].index = index; 1108 count++; 1109 /* Disable the entry */ 1110 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 1111 soc_mem_entry_null(unit, mem)); 1112 if (SOC_FAILURE(rv)) { 1113 sal_free(buffer); 1114 goto _ap_freeze_abort; 1115 } 1116 1117 /*S1, L0, L1, L2 meter */ 1118 mem = shaper_mems[0][pipe]; 1119 for (lvl = 0; lvl < (SOC_APACHE_NODE_LVL_MAX - SOC_APACHE_NODE_LVL_S1); 1120 lvl++) { 1121 bmap = bmap_list[lvl]; 1122 mem = shaper_mems[lvl][pipe]; 1123 index_count = soc_mem_index_count(unit, mem); 1124 word_count = _SHR_BITDCLSIZE(index_count); 1125 1126 for (word = 0; word < word_count; word++) { 1127 if (bmap[word] == 0) { 1128 continue; 1129 } 1130 for (bit = 0; bit < SHR_BITWID; bit++) { 1131 if (!(bmap[word] & (1 << bit))) { 1132 continue; 1133 } 1134 index = word * SHR_BITWID + bit; 1135 if ((SOC_APACHE_NODE_LVL_L1 - SOC_APACHE_NODE_LVL_S1) == lvl) { 1136 mem = l1_shaper_mems[index % max_l1_table]; 1137 index /= max_l1_table; 1138 } else if ((SOC_APACHE_NODE_LVL_L2 - SOC_APACHE_NODE_LVL_S1) == lvl) { 1139 mem = l2_shaper_mems[index % max_l2_table]; 1140 index /= max_l2_table; 1141 } 1142 /* Save the entry */ 1143 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1144 &buffer[count].entry); 1145 if (SOC_FAILURE(rv)) { 1146 sal_free(buffer); 1147 goto _ap_freeze_abort; 1148 } 1149 buffer[count].mem = mem; 1150 buffer[count].index = index; 1151 count++; 1152 /* Disable the entry */ 1153 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 1154 soc_mem_entry_null(unit, mem)); 1155 if (SOC_FAILURE(rv)) { 1156 sal_free(buffer); 1157 goto _ap_freeze_abort; 1158 } 1159 } 1160 } 1161 } 1162 buffer[count].mem = INVALIDm; 1163 *setting = buffer; 1164 _ap_freeze_abort: 1165 SOC_LLS_SCHEDULER_UNLOCK(unit); 1166 break; 1167 } 1168 #endif /* BCM_APACHE_SUPPORT */ 1169 1170 #ifdef BCM_TRIDENT2_SUPPORT 1171 case SOC_CHIP_BCM56850: 1172 case SOC_CHIP_BCM56860: 1173 { 1174 soc_info_t *si; 1175 soc_mem_t mem; 1176 uint32 *bmap, *bmap_list[3]; 1177 int pipe, phy_port, mmu_port; 1178 int lvl, index, word, bit, word_count, index_count, count; 1179 mem_entry_t *buffer; 1180 static const soc_mem_t port_shaper_mems[2] = { 1181 MMU_MTRO_EGRMETERINGCONFIG_MEM_0m, 1182 MMU_MTRO_EGRMETERINGCONFIG_MEM_1m 1183 }; 1184 static const soc_mem_t shaper_mems[][2] = { 1185 { MMU_MTRO_L0_MEM_0m, MMU_MTRO_L0_MEM_1m }, 1186 { MMU_MTRO_L1_MEM_0m, MMU_MTRO_L1_MEM_1m }, 1187 { MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m } 1188 }; 1189 1190 si = &SOC_INFO(unit); 1191 pipe = SOC_PBMP_MEMBER(si->ypipe_pbm, port) ? 1 : 0; 1192 bmap_list[0] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 1193 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 1194 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 1195 if ((bmap_list[0] == NULL) || 1196 (bmap_list[1] == NULL) || 1197 (bmap_list[2] == NULL)) { 1198 rv = SOC_E_RESOURCE; 1199 goto _td_freeze_abort; 1200 } 1201 SOC_LLS_SCHEDULER_LOCK(unit); 1202 count = 1; /* One entry for port level */ 1203 for (lvl = 0; lvl < 3; lvl++) { 1204 bmap = bmap_list[lvl]; 1205 mem = shaper_mems[lvl][pipe]; 1206 index_count = soc_mem_index_count(unit, mem); 1207 word_count = _SHR_BITDCLSIZE(index_count); 1208 for (word = 0; word < word_count; word++) { 1209 if (bmap[word] != 0) { 1210 count += _shr_popcount(bmap[word]); 1211 } 1212 } 1213 } 1214 1215 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 1216 "shaper buffer"); 1217 if (buffer == NULL) { 1218 rv = SOC_E_MEMORY; 1219 goto _td_freeze_abort; 1220 } 1221 1222 count = 0; 1223 1224 /* Port level meter */ 1225 mem = port_shaper_mems[pipe]; 1226 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1227 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 1228 index = mmu_port & 0x3f; 1229 /* Save the entry */ 1230 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1231 &buffer[count].entry); 1232 if (SOC_FAILURE(rv)) { 1233 sal_free(buffer); 1234 goto _td_freeze_abort; 1235 } 1236 buffer[count].mem = mem; 1237 buffer[count].index = index; 1238 count++; 1239 /* Disable the entry */ 1240 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 1241 soc_mem_entry_null(unit, mem)); 1242 if (SOC_FAILURE(rv)) { 1243 sal_free(buffer); 1244 goto _td_freeze_abort; 1245 } 1246 1247 /* L0, L1, L2 meter */ 1248 mem = shaper_mems[0][pipe]; 1249 for (lvl = 0; lvl < 3; lvl++) { 1250 bmap = bmap_list[lvl]; 1251 mem = shaper_mems[lvl][pipe]; 1252 index_count = soc_mem_index_count(unit, mem); 1253 word_count = _SHR_BITDCLSIZE(index_count); 1254 1255 for (word = 0; word < word_count; word++) { 1256 if (bmap[word] == 0) { 1257 continue; 1258 } 1259 for (bit = 0; bit < SHR_BITWID; bit++) { 1260 if (!(bmap[word] & (1 << bit))) { 1261 continue; 1262 } 1263 index = word * SHR_BITWID + bit; 1264 /* Save the entry */ 1265 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1266 &buffer[count].entry); 1267 if (SOC_FAILURE(rv)) { 1268 sal_free(buffer); 1269 goto _td_freeze_abort; 1270 } 1271 buffer[count].mem = mem; 1272 buffer[count].index = index; 1273 count++; 1274 /* Disable the entry */ 1275 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, 1276 soc_mem_entry_null(unit, mem)); 1277 if (SOC_FAILURE(rv)) { 1278 sal_free(buffer); 1279 goto _td_freeze_abort; 1280 } 1281 } 1282 } 1283 } 1284 buffer[count].mem = INVALIDm; 1285 *setting = buffer; 1286 _td_freeze_abort: 1287 SOC_LLS_SCHEDULER_UNLOCK(unit); 1288 break; 1289 } 1290 #endif /* BCM_TRIDENT2_SUPPORT */ 1291 1292 #if defined(BCM_KATANA_SUPPORT) 1293 case SOC_CHIP_BCM56440: 1294 { 1295 soc_mem_t mem; 1296 uint32 *bmap, *bmap_list[3]; 1297 int word_count, wdc[3], blk_size=0; 1298 int lvl, j, index, word, bit, index_count, count; 1299 int idx, upper_flag = 0; 1300 int prev_idx, prev_upper_flag; 1301 mem_entry_t *buffer; 1302 uint32 mant, cycle, f_idx; 1303 uint32 entry[SOC_MAX_MEM_WORDS]; 1304 uint16 dev_id; 1305 uint8 rev_id; 1306 1307 static const soc_mem_t cfg_mems[][2] = { 1308 { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm }, 1309 { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm }, 1310 { LLS_L2_SHAPER_CONFIG_LOWERm, LLS_L2_MIN_CONFIG_LOWER_Cm }, 1311 { LLS_L2_SHAPER_CONFIG_UPPERm, LLS_L2_MIN_CONFIG_UPPER_Cm }, 1312 }; 1313 1314 1315 static const soc_field_t rate_mant_fields[] = { 1316 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1317 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 1318 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 1319 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 1320 }; 1321 1322 static const soc_field_t rate_exp_fields[] = { 1323 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1324 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 1325 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 1326 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 1327 }; 1328 static const soc_field_t burst_exp_fields[] = { 1329 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 1330 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 1331 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 1332 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 1333 }; 1334 static const soc_field_t burst_mant_fields[] = { 1335 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 1336 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 1337 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 1338 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 1339 }; 1340 1341 static const soc_field_t cycle_sel_fields[] = { 1342 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 1343 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 1344 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 1345 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 1346 }; 1347 1348 bmap_list[0] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 1349 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 1350 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 1351 1352 count = 0; /* One entry for port level */ 1353 for (lvl = 0; lvl < 3; lvl++) { 1354 bmap = bmap_list[lvl]; 1355 mem = cfg_mems[lvl][0]; 1356 index_count = soc_mem_index_count(unit, mem); 1357 1358 /* 1359 * Allocation done using LLS_LX_PARENT 1360 * reading also done using same memories 1361 */ 1362 if (lvl == 0) { 1363 index_count = soc_mem_index_count(unit, LLS_L0_PARENTm); 1364 } else if (lvl == 1) { 1365 index_count = soc_mem_index_count(unit, LLS_L1_PARENTm); 1366 } else if (lvl == 2) { 1367 index_count = soc_mem_index_count(unit, LLS_L2_PARENTm); 1368 } 1369 1370 wdc[lvl] = _SHR_BITDCLSIZE(index_count); 1371 word_count = wdc[lvl]; 1372 for (word = 0; word < word_count; word++) { 1373 if (bmap[word] != 0) { 1374 count += _shr_popcount(bmap[word]); 1375 } 1376 } 1377 } 1378 1379 count = (count * 8) + 1; 1380 1381 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 1382 "shaper buffer"); 1383 1384 if (buffer == NULL) { 1385 rv = SOC_E_MEMORY; 1386 goto _ka_freeze_abort; 1387 } 1388 1389 count = 0; 1390 /* port */ 1391 mem = LLS_PORT_SHAPER_CONFIG_Cm; 1392 index = port & 0x3f; 1393 1394 /* Save the entry */ 1395 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1396 &buffer[count].entry); 1397 1398 if (SOC_FAILURE(rv)) { 1399 sal_free(buffer); 1400 goto _ka_freeze_abort; 1401 } 1402 buffer[count].mem = mem; 1403 buffer[count].index = index; 1404 count++; 1405 /* Set the threshold for the port to max shaper rate */ 1406 rv = soc_kt_cosq_max_bucket_set(unit, port, index, 1407 _SOC_KT_COSQ_NODE_LEVEL_ROOT); 1408 if (SOC_FAILURE(rv)) { 1409 sal_free(buffer); 1410 goto _ka_freeze_abort; 1411 } 1412 1413 /* L0, L1, L2 meter */ 1414 for (lvl = 0; lvl < 3; lvl++) { 1415 idx = upper_flag = 0; 1416 prev_idx = prev_upper_flag = -1; 1417 blk_size = (lvl == 2) ? 8: ((lvl ==1)? 4:1); 1418 bmap = bmap_list[lvl]; 1419 word_count = wdc[lvl]; 1420 for (word = 0; word < word_count; word++) { 1421 if (bmap[word] == 0) { 1422 continue; 1423 } 1424 for (bit = 0; bit < SHR_BITWID; bit++) { 1425 if (!(bmap[word] & (1 << bit))) { 1426 continue; 1427 } 1428 index = word * SHR_BITWID + bit; 1429 idx = index / blk_size; 1430 1431 for (j = 0; j < 2; j++) { 1432 mem = cfg_mems[lvl][j]; 1433 if (lvl == 2) { 1434 if ((index % 8) >= 4) { 1435 mem = cfg_mems[lvl+1][j]; 1436 upper_flag = 1; 1437 } else { 1438 upper_flag = 0; 1439 } 1440 } 1441 1442 /* Store the Threshold MIN/MAX table entries only 1443 * once per table index as for the 1444 * next consecutive L1/L2 indices falling on 1445 * to the same table index need not be stored 1446 */ 1447 if ((prev_idx != idx) || 1448 ((lvl == 2) && (prev_upper_flag != upper_flag))) { 1449 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 1450 &buffer[count].entry); 1451 if (SOC_FAILURE(rv)) { 1452 sal_free(buffer); 1453 goto _ka_freeze_abort; 1454 } 1455 buffer[count].mem = mem; 1456 buffer[count].index = idx; 1457 count++; 1458 } 1459 1460 if (lvl == 2){ 1461 /* Set the MIN/MAX thresholds for L2 node 1462 * to 2 Kbps 1463 */ 1464 mant=1; 1465 /* For 56440_A0 minimum and maximum shapers 1466 * should be programmed to use a common value 1467 * for C_MIN_CYCLE_SEL and C_MAX_CYCLE_SEL 1468 * fields and the recommended value is 0x0. 1469 */ 1470 soc_cm_get_id(unit, &dev_id, &rev_id); 1471 cycle = (rev_id == BCM56440_A0_REV_ID) ? 0 : 4; 1472 f_idx = (j * 4) + (index % 4); 1473 sal_memset(entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 1474 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 1475 idx, &entry); 1476 if (SOC_FAILURE(rv)) { 1477 sal_free(buffer); 1478 goto _ka_freeze_abort; 1479 } 1480 1481 soc_mem_field32_set(unit, mem, &entry, 1482 rate_mant_fields[f_idx], mant); 1483 soc_mem_field32_set(unit, mem, &entry, 1484 rate_exp_fields[f_idx], 0); 1485 soc_mem_field32_set(unit, mem, &entry, 1486 burst_exp_fields[f_idx], 0); 1487 soc_mem_field32_set(unit, mem, &entry, 1488 burst_mant_fields[f_idx], 0); 1489 soc_mem_field32_set(unit, mem, &entry, 1490 cycle_sel_fields[f_idx], cycle); 1491 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 1492 idx, &entry); 1493 } else if ((lvl != 2) && (j == 1)) { 1494 /* Set the MIN/MAX thresholds for L0/L1 node 1495 * to max shaper rate 1496 */ 1497 rv = soc_kt_cosq_max_bucket_set(unit, port, 1498 index, (lvl + 1)); 1499 } 1500 if (SOC_FAILURE(rv)) { 1501 sal_free(buffer); 1502 goto _ka_freeze_abort; 1503 } 1504 }/*END of for j */ 1505 prev_idx = idx; 1506 prev_upper_flag = upper_flag; 1507 } /* END of the valid bit */ 1508 } /* END of the word */ 1509 } /* END of lvl */ 1510 1511 buffer[count].mem = INVALIDm; 1512 *setting = buffer; 1513 _ka_freeze_abort: 1514 break; 1515 } 1516 #endif /* BCM_KATANA_SUPPORT */ 1517 #ifdef BCM_KATANA2_SUPPORT 1518 case SOC_CHIP_BCM56450: 1519 { 1520 soc_mem_t mem; 1521 uint32 *bmap, *bmap_list[6]; 1522 int word_count, wdc[6], blk_size=0; 1523 int lvl, j, index, word, bit, index_count, count; 1524 int idx, upper_flag = 0; 1525 int prev_idx, prev_upper_flag; 1526 mem_entry_t *buffer; 1527 uint32 mant = 0, cycle = 0 , f_idx; 1528 uint32 entry[SOC_MAX_MEM_WORDS]; 1529 uint32 lvl_count = 0; 1530 uint32 min = 0; 1531 uint32 exp = 0 ; 1532 uint32 sched_mode = 0; 1533 int wt = 0 ; 1534 uint32 burst_mant = 0; 1535 uint32 burst_exp = 0; 1536 soc_info_t *si; 1537 static const soc_mem_t parent_mems[] = { 1538 0, 1539 LLS_L0_PARENTm, 1540 LLS_L0_PARENTm, 1541 LLS_L0_PARENTm, 1542 LLS_L1_PARENTm, 1543 LLS_L2_PARENTm 1544 }; 1545 1546 static const soc_mem_t cfg_mems[][2] = { 1547 { LLS_PORT_SHAPER_CONFIG_Cm, INVALIDm }, 1548 { LLS_S0_SHAPER_CONFIG_Cm, INVALIDm }, 1549 { LLS_S1_SHAPER_CONFIG_Cm, INVALIDm }, 1550 { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm }, 1551 { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm }, 1552 { LLS_L2_SHAPER_CONFIG_LOWERm, LLS_L2_MIN_CONFIG_LOWER_Cm }, 1553 { LLS_L2_SHAPER_CONFIG_UPPERm, LLS_L2_MIN_CONFIG_UPPER_Cm }, 1554 }; 1555 1556 static const soc_field_t rate_mant_fields[] = { 1557 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1558 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 1559 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 1560 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 1561 }; 1562 1563 static const soc_field_t rate_exp_fields[] = { 1564 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1565 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 1566 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 1567 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 1568 }; 1569 static const soc_field_t burst_exp_fields[] = { 1570 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 1571 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 1572 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 1573 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 1574 }; 1575 static const soc_field_t burst_mant_fields[] = { 1576 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 1577 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 1578 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 1579 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 1580 }; 1581 1582 static const soc_field_t cycle_sel_fields[] = { 1583 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 1584 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 1585 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 1586 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 1587 }; 1588 1589 bmap_list[0] = NULL; 1590 bmap_list[1] = SOC_CONTROL(unit)->port_lls_s0_bmap[port]; 1591 bmap_list[2] = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 1592 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 1593 bmap_list[4] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 1594 bmap_list[5] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 1595 1596 si = &SOC_INFO(unit); 1597 /* 1598 * On KTX we can have both s0 and s1 node or only 1599 * s1 node but can not have only s0 node 1600 */ 1601 bmap = bmap_list[2]; 1602 index_count = _SOC_KT2_COSQ_MAX_INDEX_S1; 1603 word_count = _SHR_BITDCLSIZE(index_count); 1604 for (word = 0; word < word_count; word++) { 1605 if (bmap[word] != 0) { 1606 break; 1607 } 1608 } 1609 if (word == word_count) { 1610 /* s1 list is zero */ 1611 bmap = bmap_list[1]; 1612 index_count = _SOC_KT2_COSQ_MAX_INDEX_S0; 1613 word_count = _SHR_BITDCLSIZE(index_count); 1614 for (word = 0; word < word_count; word++) { 1615 if (bmap[word] != 0) { 1616 break; 1617 } 1618 } 1619 if (word < word_count) { 1620 /* s0 list is non zero */ 1621 /* swap s0 ans s1 list */ 1622 bmap = bmap_list[2]; 1623 bmap_list[2] = bmap_list[1]; 1624 bmap_list[1] = bmap; 1625 } 1626 } 1627 count = 0; 1628 /* Count the number of the valid Root,S0,S1 1629 * L0/L1/L2 entries per port. 1630 * To allocate the buffer to store the Min, Max shaper 1631 * entries for the valid indices 1632 */ 1633 for (lvl = 0; lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 1634 lvl_count = 0; 1635 if (lvl == _SOC_KT2_COSQ_NODE_LVL_ROOT) { 1636 /* Port entry */ 1637 lvl_count = 1; 1638 wdc[lvl] = 0; 1639 } else { 1640 bmap = bmap_list[lvl]; 1641 mem = parent_mems[lvl]; 1642 index_count = soc_mem_index_count(unit, mem); 1643 1644 if (lvl == _SOC_KT2_COSQ_NODE_LVL_S0) { 1645 index_count = _SOC_KT2_COSQ_MAX_INDEX_S0; 1646 } else 1647 if (lvl == _SOC_KT2_COSQ_NODE_LVL_S1) { 1648 index_count =_SOC_KT2_COSQ_MAX_INDEX_S1; 1649 } 1650 wdc[lvl] = _SHR_BITDCLSIZE(index_count); 1651 word_count = wdc[lvl]; 1652 1653 for (word = 0; word < word_count; word++) { 1654 if (bmap[word] != 0) { 1655 lvl_count += _shr_popcount(bmap[word]); 1656 } 1657 } 1658 if (lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) { 1659 /* for MIN/MAX shaper config */ 1660 /* count allocation is based on worst case 1661 * estimate that entries might fall into different 1662 * table entries 1663 */ 1664 lvl_count = (lvl_count * 2); 1665 } 1666 } 1667 count += lvl_count; 1668 } 1669 count = count + 1; 1670 1671 1672 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 1673 "shaper buffer"); 1674 1675 if (buffer == NULL) { 1676 rv = SOC_E_MEMORY; 1677 goto _ka2_freeze_abort; 1678 } 1679 count = 0; 1680 /* port */ 1681 mem = LLS_PORT_SHAPER_CONFIG_Cm; 1682 index = port & 0x3f; 1683 1684 /* Save the entry */ 1685 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1686 &buffer[count].entry); 1687 if (SOC_FAILURE(rv)) { 1688 sal_free(buffer); 1689 goto _ka2_freeze_abort; 1690 } 1691 buffer[count].mem = mem; 1692 buffer[count].index = index; 1693 count++; 1694 1695 /* Set the threshold for the port to max shaper rate */ 1696 rv = soc_kt2_cosq_max_bucket_set(unit, port, index, 1697 _SOC_KT2_COSQ_NODE_LVL_ROOT); 1698 if (SOC_FAILURE(rv)) { 1699 sal_free(buffer); 1700 goto _ka2_freeze_abort; 1701 } 1702 1703 /* S0, S1, L0, L1, L2 meter */ 1704 for (lvl = _SOC_KT2_COSQ_NODE_LVL_S0; 1705 lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 1706 idx = upper_flag = 0; 1707 prev_idx = prev_upper_flag = -1; 1708 blk_size = ((lvl == _SOC_KT2_COSQ_NODE_LVL_L2) ? 8: 1709 ((lvl == _SOC_KT2_COSQ_NODE_LVL_L1)? 4: 1)); 1710 bmap = bmap_list[lvl]; 1711 word_count = wdc[lvl]; 1712 for (word = 0; word < word_count; word++) { 1713 if (bmap[word] == 0) { 1714 continue; 1715 } 1716 for (bit = 0; bit < SHR_BITWID; bit++) { 1717 if (!(bmap[word] & (1 << bit))) { 1718 continue; 1719 } 1720 index = word * SHR_BITWID + bit; 1721 idx = index / blk_size; 1722 1723 for (j = 0; j < 2; j++) { 1724 mem = cfg_mems[lvl][j]; 1725 1726 if (mem == INVALIDm) { 1727 continue; 1728 } 1729 1730 if (lvl == _SOC_KT2_COSQ_NODE_LVL_L2) { 1731 if ((index % 8) >= 4) { 1732 mem = cfg_mems[lvl+1][j]; 1733 upper_flag = 1; 1734 } else { 1735 upper_flag = 0; 1736 } 1737 } 1738 1739 /* Store the Threshold MIN/MAX table entries only 1740 * once per table index as for the 1741 * next consecutive L1/L2 indices falling on 1742 * to the same table index need not be stored 1743 */ 1744 if ((prev_idx != idx) || 1745 ((lvl == _SOC_KT2_COSQ_NODE_LVL_L2) && 1746 (prev_upper_flag != upper_flag))) { 1747 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 1748 &buffer[count].entry); 1749 if (SOC_FAILURE(rv)) { 1750 sal_free(buffer); 1751 goto _ka2_freeze_abort; 1752 } 1753 buffer[count].mem = mem; 1754 buffer[count].index = idx; 1755 count++; 1756 } 1757 1758 if (lvl == _SOC_KT2_COSQ_NODE_LVL_L2){ 1759 if (SOC_PBMP_MEMBER(si->linkphy_pbm, port)) { 1760 /* coverity[leaked_storage] */ 1761 rv = soc_kt2_cosq_get_sched_mode(unit, port, lvl, 1762 index, &sched_mode, &wt); 1763 } else { 1764 /* coverity[leaked_storage] */ 1765 /* coverity[resource_leak : FALSE] */ 1766 rv = soc_kt2_cosq_get_sched_mode(unit, port, lvl - 2, 1767 index, &sched_mode, &wt); 1768 } 1769 if (SOC_FAILURE(rv)) { 1770 sal_free(buffer); 1771 goto _ka2_freeze_abort; 1772 } 1773 1774 if ( sched_mode == BCM_COSQ_STRICT ) 1775 { 1776 rv = _soc_kt2_cosq_min_bucket_get(unit, port, 1777 index, lvl, 1778 &min, &mant, 1779 &exp, &cycle); 1780 if (SOC_FAILURE(rv)) { 1781 sal_free(buffer); 1782 goto _ka2_freeze_abort; 1783 } 1784 if (min) { 1785 if (exp != 0) { 1786 if (exp < 10) { 1787 burst_exp = 5; 1788 burst_mant = 0; 1789 } else { 1790 burst_exp = exp - 4; 1791 burst_mant = (mant >> 3); 1792 } 1793 } 1794 else { 1795 burst_mant = 0; 1796 burst_exp = 0; 1797 } 1798 } 1799 } 1800 if (!min) 1801 { 1802 /* Set the MIN/MAX thresholds for L2 node 1803 * to 2 Kbps 1804 */ 1805 mant = 1; 1806 cycle = 4; 1807 exp = 0; 1808 } 1809 f_idx = (j * 4) + (index % 4); 1810 sal_memset(entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 1811 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 1812 idx, &entry); 1813 if (SOC_FAILURE(rv)) { 1814 sal_free(buffer); 1815 goto _ka2_freeze_abort; 1816 } 1817 1818 soc_mem_field32_set(unit, mem, &entry, 1819 rate_mant_fields[f_idx], mant); 1820 soc_mem_field32_set(unit, mem, &entry, 1821 rate_exp_fields[f_idx], exp); 1822 soc_mem_field32_set(unit, mem, &entry, 1823 burst_exp_fields[f_idx], burst_exp); 1824 soc_mem_field32_set(unit, mem, &entry, 1825 burst_mant_fields[f_idx], burst_mant); 1826 soc_mem_field32_set(unit, mem, &entry, 1827 cycle_sel_fields[f_idx], cycle); 1828 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 1829 idx, &entry); 1830 min = 0; 1831 sched_mode = 0; 1832 cycle = 0; 1833 exp = 0; 1834 mant = 0; 1835 burst_exp = 0; 1836 burst_mant = 0; 1837 } else if (((lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) && (j == 1)) || 1838 (lvl < _SOC_KT2_COSQ_NODE_LVL_L0)) { 1839 /* Set the MIN/MAX thresholds for L0/L1 node 1840 * to max shaper rate 1841 */ 1842 rv = soc_kt2_cosq_max_bucket_set(unit, port, 1843 index, lvl); 1844 } 1845 if (SOC_FAILURE(rv)) { 1846 sal_free(buffer); 1847 goto _ka2_freeze_abort; 1848 } 1849 }/*END of for j */ 1850 prev_idx = idx; 1851 prev_upper_flag = upper_flag; 1852 } /* END of the valid bit */ 1853 } /* END of the word */ 1854 } /* END of lvl */ 1855 1856 buffer[count].mem = INVALIDm; 1857 *setting = buffer; 1858 _ka2_freeze_abort: 1859 break; 1860 } 1861 #endif /* BCM_KATANA2_SUPPORT */ 1862 #ifdef BCM_SABER2_SUPPORT 1863 case SOC_CHIP_BCM56260: 1864 case SOC_CHIP_BCM56270: 1865 { 1866 soc_mem_t mem; 1867 uint32 *bmap, *bmap_list[6]; 1868 int word_count, wdc[6], blk_size=0; 1869 int lvl, j, index, word, bit, index_count, count; 1870 int idx; 1871 int prev_idx; 1872 mem_entry_t *buffer; 1873 uint32 mant=0, cycle=0, f_idx; 1874 uint32 entry[SOC_MAX_MEM_WORDS]; 1875 uint32 lvl_count = 0; 1876 uint32 min = 0; 1877 uint32 exp = 0; 1878 uint32 sched_mode = 0; 1879 int wt = 0; 1880 uint32 burst_mant = 0; 1881 uint32 burst_exp = 0; 1882 soc_info_t *si; 1883 1884 static const soc_mem_t parent_mems[] = { 1885 0, 1886 LLS_L0_PARENTm, 1887 LLS_L0_PARENTm, 1888 LLS_L0_PARENTm, 1889 LLS_L1_PARENTm, 1890 LLS_L2_PARENTm 1891 }; 1892 1893 static const soc_mem_t cfg_mems[][2] = { 1894 { LLS_PORT_SHAPER_CONFIG_Cm, INVALIDm }, 1895 { LLS_S0_SHAPER_CONFIG_Cm, INVALIDm }, 1896 { LLS_S1_SHAPER_CONFIG_Cm, INVALIDm }, 1897 { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm }, 1898 { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm }, 1899 { LLS_L2_SHAPER_CONFIG_Cm, LLS_L2_MIN_CONFIG_Cm }, 1900 }; 1901 static const soc_field_t rate_mant_fields[] = { 1902 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1903 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 1904 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 1905 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 1906 }; 1907 1908 static const soc_field_t rate_exp_fields[] = { 1909 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1910 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 1911 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 1912 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 1913 }; 1914 static const soc_field_t burst_exp_fields[] = { 1915 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 1916 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 1917 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 1918 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 1919 }; 1920 static const soc_field_t burst_mant_fields[] = { 1921 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 1922 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 1923 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 1924 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 1925 }; 1926 1927 static const soc_field_t cycle_sel_fields[] = { 1928 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 1929 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 1930 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 1931 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 1932 }; 1933 1934 si = &SOC_INFO(unit); 1935 1936 bmap_list[0] = NULL; 1937 bmap_list[1] = SOC_CONTROL(unit)->port_lls_s0_bmap[port]; 1938 bmap_list[2] = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 1939 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 1940 bmap_list[4] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 1941 bmap_list[5] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 1942 /* 1943 * On KTX we can have both s0 and s1 node or only 1944 * s1 node but can not have only s0 node 1945 */ 1946 bmap = bmap_list[2]; 1947 index_count = soc_mem_index_count(unit, parent_mems[2]); 1948 word_count = _SHR_BITDCLSIZE(index_count); 1949 for (word = 0; word < word_count; word++) { 1950 if (bmap[word] != 0) { 1951 break; 1952 } 1953 } 1954 if (word == word_count) { 1955 /* s1 list is zero */ 1956 bmap = bmap_list[1]; 1957 for (word = 0; word < word_count; word++) { 1958 if (bmap[word] != 0) { 1959 break; 1960 } 1961 } 1962 if (word < word_count) { 1963 /* s0 list is non zero */ 1964 /* swap s0 ans s1 list */ 1965 bmap = bmap_list[2]; 1966 bmap_list[2] = bmap_list[1]; 1967 bmap_list[1] = bmap; 1968 } 1969 } 1970 count = 0; 1971 /* Count the number of the valid Root,S0,S1 1972 * L0/L1/L2 entries per port. 1973 * To allocate the buffer to store the Min, Max shaper 1974 * entries for the valid indices 1975 */ 1976 for (lvl = 0; lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 1977 lvl_count = 0; 1978 if (lvl == _SOC_KT2_COSQ_NODE_LVL_ROOT) { 1979 /* Port entry */ 1980 lvl_count = 1; 1981 wdc[lvl] = 0; 1982 } else { 1983 bmap = bmap_list[lvl]; 1984 mem = parent_mems[lvl]; 1985 index_count = soc_mem_index_count(unit, mem); 1986 if (lvl == _SOC_KT2_COSQ_NODE_LVL_S0) { 1987 index_count = _SOC_SB2_COSQ_MAX_INDEX_S0; 1988 } 1989 wdc[lvl] = _SHR_BITDCLSIZE(index_count); 1990 word_count = wdc[lvl]; 1991 1992 for (word = 0; word < word_count; word++) { 1993 if (bmap[word] != 0) { 1994 lvl_count += _shr_popcount(bmap[word]); 1995 } 1996 } 1997 if (lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) { 1998 /* for MIN/MAX shaper config */ 1999 /* count allocation is based on worst case 2000 * estimate that entries might fall into different 2001 * table entries 2002 */ 2003 lvl_count = (lvl_count * 2); 2004 } 2005 } 2006 count += lvl_count; 2007 } 2008 count = count + 1; 2009 2010 2011 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 2012 "shaper buffer"); 2013 2014 if (buffer == NULL) { 2015 rv = SOC_E_MEMORY; 2016 break; 2017 } 2018 count = 0; 2019 /* port */ 2020 mem = LLS_PORT_SHAPER_CONFIG_Cm; 2021 index = port & 0x1f; 2022 2023 /* Save the entry */ 2024 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 2025 &buffer[count].entry); 2026 if (SOC_FAILURE(rv)) { 2027 sal_free(buffer); 2028 break; 2029 } 2030 buffer[count].mem = mem; 2031 buffer[count].index = index; 2032 count++; 2033 2034 /* Set the threshold for the port to max shaper rate */ 2035 rv = soc_sb2_cosq_max_bucket_set(unit, port, index, 2036 _SOC_KT2_COSQ_NODE_LVL_ROOT); 2037 if (SOC_FAILURE(rv)) { 2038 sal_free(buffer); 2039 break; 2040 } 2041 2042 /* S0, S1, L0, L1, L2 meter */ 2043 for (lvl = _SOC_KT2_COSQ_NODE_LVL_S0; 2044 lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 2045 idx = 0; 2046 prev_idx = -1; 2047 blk_size = ((lvl == _SOC_KT2_COSQ_NODE_LVL_L2) ? 4: 1); 2048 bmap = bmap_list[lvl]; 2049 word_count = wdc[lvl]; 2050 for (word = 0; word < word_count; word++) { 2051 if (bmap[word] == 0) { 2052 continue; 2053 } 2054 for (bit = 0; bit < SHR_BITWID; bit++) { 2055 if (!(bmap[word] & (1 << bit))) { 2056 continue; 2057 } 2058 index = word * SHR_BITWID + bit; 2059 idx = index / blk_size; 2060 if ((lvl == _SOC_KT2_COSQ_NODE_LVL_S0) && 2061 (idx >= _SOC_SB2_COSQ_MAX_INDEX_S0)) { 2062 continue; 2063 } 2064 2065 for (j = 0; j < 2; j++) { 2066 mem = cfg_mems[lvl][j]; 2067 2068 if (mem == INVALIDm || (!SOC_MEM_IS_VALID(unit, mem))) { 2069 continue; 2070 } 2071 2072 /* Store the Threshold MIN/MAX table entries only 2073 * once per table index as for the 2074 * next consecutive L1/L2 indices falling on 2075 * to the same table index need not be stored 2076 */ 2077 if (prev_idx != idx) { 2078 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 2079 &buffer[count].entry); 2080 if (SOC_FAILURE(rv)) { 2081 sal_free(buffer); 2082 goto _sb2_freeze_abort; 2083 } 2084 buffer[count].mem = mem; 2085 buffer[count].index = idx; 2086 count++; 2087 } 2088 2089 if (lvl == _SOC_KT2_COSQ_NODE_LVL_L2){ 2090 /* Set the MIN/MAX thresholds for L2 node 2091 * to 2 Kbps 2092 */ 2093 if (SOC_PBMP_MEMBER(si->linkphy_pbm, port)) { 2094 rv = soc_kt2_cosq_get_sched_mode(unit, port, 2095 lvl, index, &sched_mode, &wt); 2096 } else { 2097 rv = soc_kt2_cosq_get_sched_mode(unit, port, 2098 lvl - 2, index, &sched_mode, &wt); 2099 } 2100 if (SOC_FAILURE(rv)) { 2101 sal_free(buffer); 2102 return rv; 2103 } 2104 if ( sched_mode == BCM_COSQ_STRICT ) 2105 { 2106 rv = soc_sb2_cosq_min_bucket_get(unit, port, 2107 index, lvl, 2108 &min, &mant, 2109 &exp, &cycle); 2110 if (SOC_FAILURE(rv)) { 2111 sal_free(buffer); 2112 goto _sb2_freeze_abort; 2113 } 2114 if (min) { 2115 if (exp != 0) { 2116 if (exp < 10) { 2117 burst_exp = 5; 2118 burst_mant = 0; 2119 } else { 2120 burst_exp = exp - 4; 2121 burst_mant = (mant >> 3); 2122 } 2123 } 2124 else { 2125 burst_mant = 0; 2126 burst_exp = 0; 2127 } 2128 } 2129 } 2130 if (!min) 2131 { 2132 /* Set the MIN/MAX thresholds for L2 node 2133 * to 2 Kbps 2134 */ 2135 mant = 1; 2136 cycle = 4; 2137 exp = 0; 2138 } 2139 f_idx = (j * 4) + index % 4; 2140 sal_memset(entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2141 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2142 idx, &entry); 2143 if (SOC_FAILURE(rv)) { 2144 sal_free(buffer); 2145 goto _sb2_freeze_abort; 2146 } 2147 soc_mem_field32_set(unit, mem, &entry, 2148 rate_mant_fields[f_idx], mant); 2149 soc_mem_field32_set(unit, mem, &entry, 2150 rate_exp_fields[f_idx], exp); 2151 soc_mem_field32_set(unit, mem, &entry, 2152 burst_exp_fields[f_idx], burst_exp); 2153 soc_mem_field32_set(unit, mem, &entry, 2154 burst_mant_fields[f_idx], burst_mant); 2155 soc_mem_field32_set(unit, mem, &entry, 2156 cycle_sel_fields[f_idx], cycle); 2157 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 2158 idx, &entry); 2159 min = 0; 2160 sched_mode = 0; 2161 cycle = 0; 2162 exp = 0; 2163 mant = 0; 2164 burst_exp = 0; 2165 burst_mant = 0; 2166 } else if (((lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) && (j == 1)) || 2167 (lvl < _SOC_KT2_COSQ_NODE_LVL_L0)) { 2168 /* Set the MIN/MAX thresholds for L0/L1 node 2169 * to max shaper rate 2170 */ 2171 rv = soc_sb2_cosq_max_bucket_set(unit, port, 2172 index, lvl); 2173 } 2174 if (SOC_FAILURE(rv)) { 2175 sal_free(buffer); 2176 goto _sb2_freeze_abort; 2177 } 2178 }/*END of for j */ 2179 prev_idx = idx; 2180 } /* END of the valid bit */ 2181 } /* END of the word */ 2182 } /* END of lvl */ 2183 2184 buffer[count].mem = INVALIDm; 2185 *setting = buffer; 2186 _sb2_freeze_abort: 2187 break; 2188 } 2189 #endif /* BCM_SABER2_SUPPORT */ 2190 #ifdef BCM_TRIDENT3_SUPPORT 2191 case SOC_CHIP_BCM56870: 2192 case SOC_CHIP_BCM56370: 2193 case SOC_CHIP_BCM56770: 2194 { 2195 uint64 rval64; 2196 uint64 *buffer; 2197 uint64 pbits64; 2198 int pipe; 2199 int split, pos; 2200 soc_reg_t mtro_reg; 2201 soc_reg_t reg_mtro[2] = {MTRO_PORT_ENTITY_DISABLE_SPLIT0r, 2202 MTRO_PORT_ENTITY_DISABLE_SPLIT1r}; 2203 2204 COMPILER_64_ZERO(rval64); 2205 COMPILER_64_ZERO(pbits64); 2206 2207 SOC_IF_ERROR_RETURN( 2208 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 2209 mtro_reg = reg_mtro[split]; 2210 2211 if (pos < 32) { 2212 COMPILER_64_SET(pbits64, 0, (1 << pos)); 2213 } else { 2214 COMPILER_64_SET(pbits64, (1 << (pos - 32)), 0); 2215 } 2216 2217 buffer = sal_alloc(sizeof(uint64), "MTRO status buffer"); 2218 if (buffer == NULL) { 2219 rv = SOC_E_MEMORY; 2220 break; 2221 } 2222 /* Disable Shaper Updates */ 2223 rv = soc_reg_get(unit, mtro_reg, pipe, 0, &rval64); 2224 if (SOC_FAILURE(rv)) { 2225 sal_free(buffer); 2226 break; 2227 } 2228 COMPILER_64_COPY(*buffer, rval64); 2229 COMPILER_64_AND(*buffer, pbits64); 2230 2231 COMPILER_64_OR(rval64, pbits64); 2232 2233 /* METERING_DISABLEf is the only field in reg. */ 2234 rv = soc_reg_set(unit, mtro_reg, pipe, 0, rval64); 2235 if (SOC_FAILURE(rv)) { 2236 sal_free(buffer); 2237 break; 2238 } 2239 2240 *setting = buffer; 2241 break; 2242 } 2243 #endif /* BCM_TRIDENT3_SUPPORT */ 2244 case SOC_CHIP_BCM56960: /* Use hardware flush */ 2245 case SOC_CHIP_BCM56965: 2246 default: 2247 break; 2248 } 2249 2250 if (SOC_FAILURE(rv)) { 2251 /* UNLOCK if fail */ 2252 SOC_EGRESS_METERING_UNLOCK(unit); 2253 } 2254 2255 return rv; 2256 } 2257 2258 int 2259 _soc_egress_metering_thaw(int unit, soc_port_t port, void *setting) 2260 { 2261 int rv; 2262 2263 if (setting == NULL) { 2264 SOC_EGRESS_METERING_UNLOCK(unit); 2265 return SOC_E_NONE; 2266 } 2267 2268 rv = SOC_E_NONE; 2269 2270 switch (SOC_CHIP_GROUP(unit)) { 2271 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 2272 case SOC_CHIP_BCM56224: 2273 case SOC_CHIP_BCM56820: 2274 case SOC_CHIP_BCM56725: 2275 case SOC_CHIP_BCM53314: 2276 case SOC_CHIP_BCM56142: 2277 { 2278 uint32 *rval32; 2279 2280 rval32 = setting; 2281 /* Restore egress metering configuration. */ 2282 rv = WRITE_EGRMETERINGCONFIGr(unit, port, *rval32); 2283 sal_free(setting); 2284 break; 2285 } 2286 #endif /* BCM_RAVEN_SUPPORT || BCM_SCORPION_SUPPORT || BCM_HURRICANE_SUPPORT */ 2287 #if defined (BCM_HURRICANE2_SUPPORT) 2288 case SOC_CHIP_BCM56150: 2289 case SOC_CHIP_BCM53400: 2290 case SOC_CHIP_BCM56160: 2291 case SOC_CHIP_BCM53540: 2292 { 2293 int i; 2294 uint32 *buffer = setting; 2295 int count; 2296 int err_flag = 0; 2297 2298 /* restore the original configuration : MAXBUCKETCONFIGr */ 2299 count = 0; 2300 for (i = 0; i < SOC_REG_NUMELS(unit, MAXBUCKETCONFIGr); i++) { 2301 rv = WRITE_MAXBUCKETCONFIGr(unit, port, i, buffer[count]); 2302 if (SOC_FAILURE(rv)) { 2303 err_flag = 1; 2304 break; 2305 } 2306 count ++; 2307 } 2308 if (!err_flag) { 2309 /* restore the original configuration : EGRMETERINGCONFIGr */ 2310 rv = WRITE_EGRMETERINGCONFIGr(unit, port, buffer[count]); 2311 } 2312 2313 sal_free(setting); 2314 break; 2315 } 2316 #endif /* BCM_HURRICANE2_SUPPORT */ 2317 #if defined(BCM_GREYHOUND2_SUPPORT) 2318 case SOC_CHIP_BCM53570: 2319 { 2320 int i; 2321 uint32 *buffer = setting; 2322 int err_flag = 0; 2323 int count; 2324 int qlayer_entry_count = 0; 2325 int qgroup_entry_count = 0; 2326 soc_mem_t config_mem = INVALIDm; 2327 uint32 entry[SOC_MAX_MEM_WORDS]; 2328 int memidx; 2329 int is_64q_port; 2330 2331 rv = soc_gh2_64q_port_check(unit, port, &is_64q_port); 2332 if (SOC_FAILURE(rv)) { 2333 sal_free(setting); 2334 break; 2335 } 2336 2337 if (is_64q_port) { 2338 qlayer_entry_count = SOC_GH2_QLAYER_COSQ_PER_PORT_NUM; 2339 qgroup_entry_count = SOC_GH2_QGROUP_PER_PORT_NUM; 2340 } else { 2341 qlayer_entry_count = SOC_GH2_LEGACY_QUEUE_NUM; 2342 qgroup_entry_count = 0; 2343 } 2344 2345 /* buffer required (X*2+Y*2+1) for store original setting. 2346 * MMU port 0~57: X=8, Y=0 2347 * MMU port 58-65 : X=64, Y=8 2348 * MMU_MAX_BUCKET_QLAYERm : 2349 * X entries for a port, two fields (REFRESHf, THD_SELf)stored 2350 * MMU_MAX_BUCKET_QGROUPm : Y entries for a port 2351 * Y entries for a port, two fields (REFRESHf, THD_SELf)stored 2352 * EGRMETERINGCONFIG : 1 register value for a port 2353 */ 2354 2355 /* restore the original configuration : MMU_MAX_BUCKET_QLAYERm */ 2356 count = 0; 2357 config_mem = MMU_MAX_BUCKET_QLAYERm; 2358 rv = soc_gh2_mmu_bucket_qlayer_index(unit, port, 0, &memidx); 2359 if (SOC_FAILURE(rv)) { 2360 err_flag = 1; 2361 } else { 2362 for (i = memidx; i < qlayer_entry_count; i++) { 2363 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 2364 i, &entry); 2365 if (SOC_FAILURE(rv)) { 2366 err_flag = 1; 2367 break; 2368 } 2369 soc_mem_field32_set(unit, config_mem, &entry, REFRESHf, 2370 buffer[count]); 2371 count ++; 2372 soc_mem_field32_set(unit, config_mem, &entry, THD_SELf, 2373 buffer[count]); 2374 count ++; 2375 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 2376 i, &entry); 2377 if (SOC_FAILURE(rv)) { 2378 err_flag = 1; 2379 break; 2380 } 2381 } 2382 } 2383 2384 /* restore the original configuration : MMU_MAX_BUCKET_QGROUPm */ 2385 if (!err_flag) { 2386 if (qgroup_entry_count) { 2387 config_mem = MMU_MAX_BUCKET_QGROUPm; 2388 rv = soc_gh2_mmu_bucket_qgroup_index(unit, port, 0, 2389 &memidx); 2390 if (SOC_FAILURE(rv)) { 2391 err_flag = 1; 2392 } else { 2393 for (i = memidx; i < qgroup_entry_count; i++) { 2394 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 2395 i, &entry); 2396 if (SOC_FAILURE(rv)) { 2397 err_flag = 1; 2398 break; 2399 } 2400 2401 soc_mem_field32_set(unit, config_mem, &entry, 2402 REFRESHf, buffer[count]); 2403 count ++; 2404 soc_mem_field32_set(unit, config_mem, &entry, 2405 THD_SELf, buffer[count]); 2406 count ++; 2407 rv = soc_mem_write(unit, config_mem, 2408 MEM_BLOCK_ALL, i, &entry); 2409 if (SOC_FAILURE(rv)) { 2410 err_flag = 1; 2411 break; 2412 } 2413 } 2414 } 2415 } 2416 } 2417 2418 if (!err_flag) { 2419 /* restore the original configuration : EGRMETERINGCONFIGr */ 2420 rv = WRITE_EGRMETERINGCONFIGr(unit, port, buffer[count]); 2421 } 2422 sal_free(setting); 2423 break; 2424 } 2425 #endif /* BCM_GREYHOUND2_SUPPORT */ 2426 #if defined(BCM_TRIUMPH_SUPPORT) 2427 case SOC_CHIP_BCM56624: 2428 case SOC_CHIP_BCM56680: 2429 case SOC_CHIP_BCM56634: 2430 case SOC_CHIP_BCM56524: 2431 case SOC_CHIP_BCM56334: 2432 case SOC_CHIP_BCM56685: 2433 { 2434 uint64 *rval64; 2435 2436 rval64 = setting; 2437 /* Restore egress metering configuration. */ 2438 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, *rval64); 2439 sal_free(setting); 2440 break; 2441 } 2442 case SOC_CHIP_BCM56840: 2443 { 2444 int count, index, queue_cnt, err_flag = 0; 2445 soc_info_t *si; 2446 uint64 *buffer = setting; 2447 2448 si = &SOC_INFO(unit); 2449 /* Port level + S2 + S3 + UCQ + MCQ + EXT_UCQ. */ 2450 queue_cnt = si->port_num_uc_cosq[port] + si->port_num_cosq[port] + 2451 si->port_num_ext_cosq[port]; 2452 2453 count = 0; 2454 /* Port level meter. */ 2455 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, buffer[count]); 2456 if (SOC_FAILURE(rv)) { 2457 err_flag = 1; 2458 } 2459 count++; 2460 2461 if (!IS_CPU_PORT(unit, port)) { 2462 /* S2 meter (including MC group). */ 2463 for (index = 0; (index < 4) && (err_flag == 0); index++) { 2464 rv = WRITE_S2_MAXBUCKETCONFIG_64r(unit, port, index, 2465 buffer[count]); 2466 if (SOC_FAILURE(rv)) { 2467 err_flag = 1; 2468 break; 2469 } 2470 count++; 2471 } 2472 /* S3 meter. */ 2473 for (index = 0; (index < 4) && (err_flag == 0); index++) { 2474 rv = WRITE_S3_MAXBUCKETCONFIG_64r(unit, port, index, 2475 buffer[count]); 2476 if (SOC_FAILURE(rv)) { 2477 err_flag = 1; 2478 break; 2479 } 2480 count++; 2481 } 2482 } 2483 2484 /* Queue meter. */ 2485 for (index = 0; (index < queue_cnt) && (err_flag == 0); index++) { 2486 rv = WRITE_MAXBUCKETCONFIG_64r(unit, port, index, 2487 buffer[count]); 2488 if (SOC_FAILURE(rv)) { 2489 break; 2490 } 2491 count++; 2492 } 2493 sal_free(setting); 2494 break; 2495 } 2496 case SOC_CHIP_BCM56640: 2497 case SOC_CHIP_BCM56340: 2498 { 2499 uint64 rval64; 2500 int index; 2501 mem_entry_t *buffer = setting; 2502 2503 /* Restore port level metering configuration. */ 2504 sal_memcpy(&rval64, &buffer[0].entry[0], sizeof(uint64)); 2505 rv = WRITE_EGRMETERINGCONFIG_64r(unit, port, rval64); 2506 2507 /* Restore L0,L1,L2 metering configuration. */ 2508 for (index = 1; buffer[index].mem != INVALIDm ;index++) { 2509 rv = soc_mem_write(unit, buffer[index].mem, MEM_BLOCK_ANY, 2510 buffer[index].index, &buffer[index].entry); 2511 if (SOC_FAILURE(rv)) { 2512 break; 2513 } 2514 } 2515 2516 sal_free(setting); 2517 break; 2518 } 2519 #endif /* BCM_TRIUMPH_SUPPORT */ 2520 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_KATANA_SUPPORT) 2521 case SOC_CHIP_BCM56440: 2522 case SOC_CHIP_BCM56450: 2523 case SOC_CHIP_BCM56260: 2524 case SOC_CHIP_BCM56850: 2525 case SOC_CHIP_BCM56860: 2526 case SOC_CHIP_BCM56560: 2527 case SOC_CHIP_BCM56270: 2528 { 2529 int index; 2530 mem_entry_t *buffer; 2531 2532 buffer = setting; 2533 for (index = 0; buffer[index].mem != INVALIDm ;index++) { 2534 rv = soc_mem_write(unit, buffer[index].mem, MEM_BLOCK_ANY, 2535 buffer[index].index, &buffer[index].entry); 2536 if (SOC_FAILURE(rv)) { 2537 break; 2538 } 2539 } 2540 sal_free(setting); 2541 break; 2542 } 2543 #endif /* BCM_TRIDENT2_SUPPORT || BCM_KATANA_SUPPORT */ 2544 #ifdef BCM_TRIDENT3_SUPPORT 2545 case SOC_CHIP_BCM56870: 2546 case SOC_CHIP_BCM56370: 2547 case SOC_CHIP_BCM56770: 2548 { 2549 uint64 rval64; 2550 uint64 *buffer; 2551 uint64 pbits64; 2552 int pipe; 2553 int split, pos; 2554 soc_reg_t mtro_reg; 2555 soc_reg_t reg_mtro[2] = {MTRO_PORT_ENTITY_DISABLE_SPLIT0r, 2556 MTRO_PORT_ENTITY_DISABLE_SPLIT1r}; 2557 2558 COMPILER_64_ZERO(rval64); 2559 COMPILER_64_ZERO(pbits64); 2560 2561 SOC_IF_ERROR_RETURN( 2562 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 2563 mtro_reg = reg_mtro[split]; 2564 2565 if (pos < 32) { 2566 COMPILER_64_SET(pbits64, 0, (1 << pos)); 2567 } else { 2568 COMPILER_64_SET(pbits64, (1 << (pos - 32)), 0); 2569 } 2570 2571 /* Restore Shaper Updates */ 2572 rv = soc_reg_get(unit, mtro_reg, pipe, 0, &rval64); 2573 if (SOC_FAILURE(rv)) { 2574 sal_free(setting); 2575 break; 2576 } 2577 buffer = setting; 2578 COMPILER_64_NOT(pbits64); 2579 COMPILER_64_AND(rval64, pbits64); 2580 COMPILER_64_OR(rval64, *buffer); 2581 2582 /* METERING_DISABLEf is the only field in reg. */ 2583 rv = soc_reg_set(unit, mtro_reg, pipe, 0, rval64); 2584 if (SOC_FAILURE(rv)) { 2585 sal_free(setting); 2586 break; 2587 } 2588 2589 sal_free(setting); 2590 break; 2591 } 2592 #endif /* BCM_TRIDENT3_SUPPORT */ 2593 case SOC_CHIP_BCM56960: /* Use hardware flush */ 2594 case SOC_CHIP_BCM56965: 2595 default: 2596 break; 2597 } 2598 2599 SOC_EGRESS_METERING_UNLOCK(unit); 2600 2601 return rv; 2602 } 2603 2604 int 2605 soc_mmu_flush_enable(int unit, soc_port_t port, int enable) 2606 { 2607 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 2608 uint32 flush_ctrl; 2609 #endif 2610 2611 #if defined(BCM_KATANA_SUPPORT) 2612 void *setting = NULL; 2613 int rv = SOC_E_NONE; 2614 int rv1 = SOC_E_NONE; 2615 #endif 2616 2617 switch (SOC_CHIP_GROUP(unit)) { 2618 #if defined(BCM_RAVEN_SUPPORT) 2619 case SOC_CHIP_BCM56224: 2620 case SOC_CHIP_BCM53314: 2621 SOC_IF_ERROR_RETURN 2622 (READ_MMUFLUSHCONTROLr(unit, &flush_ctrl)); 2623 flush_ctrl &= ~(0x1 << port); 2624 flush_ctrl |= enable ? (0x1 << port) : 0; 2625 SOC_IF_ERROR_RETURN 2626 (WRITE_MMUFLUSHCONTROLr(unit, flush_ctrl)); 2627 break; 2628 #endif /* BCM_RAVEN_SUPPORT */ 2629 2630 #if defined(BCM_HURRICANE2_SUPPORT) 2631 case SOC_CHIP_BCM56150: 2632 case SOC_CHIP_BCM53400: 2633 case SOC_CHIP_BCM56160: 2634 case SOC_CHIP_BCM53540: 2635 SOC_IF_ERROR_RETURN 2636 (READ_MMUFLUSHCONTROLr(unit, &flush_ctrl)); 2637 flush_ctrl &= ~(0x1 << port); 2638 flush_ctrl |= enable ? (0x1 << port) : 0; 2639 SOC_IF_ERROR_RETURN 2640 (WRITE_MMUFLUSHCONTROLr(unit, flush_ctrl)); 2641 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2642 (BSL_META_U(unit, 2643 "port %d MMUFLUSHCONTROl.FLUSH=0x%x\n"), port, flush_ctrl)); 2644 break; 2645 case SOC_CHIP_BCM53570: 2646 { 2647 int port_off; 2648 if (port < 32) { 2649 port_off = port; 2650 SOC_IF_ERROR_RETURN 2651 (READ_MMUFLUSHCONTROL_0r(unit, &flush_ctrl)); 2652 flush_ctrl &= ~(0x1 << port_off); 2653 flush_ctrl |= enable ? (0x1 << port_off) : 0; 2654 SOC_IF_ERROR_RETURN 2655 (WRITE_MMUFLUSHCONTROL_0r(unit, flush_ctrl)); 2656 } else if ((port >= 32) && (port < 64)) { 2657 port_off = port - 32; 2658 SOC_IF_ERROR_RETURN 2659 (READ_MMUFLUSHCONTROL_1r(unit, &flush_ctrl)); 2660 flush_ctrl &= ~(0x1 << port_off); 2661 flush_ctrl |= enable ? (0x1 << port_off) : 0; 2662 SOC_IF_ERROR_RETURN 2663 (WRITE_MMUFLUSHCONTROL_1r(unit, flush_ctrl)); 2664 } else { 2665 port_off = port - 64; 2666 SOC_IF_ERROR_RETURN 2667 (READ_MMUFLUSHCONTROL_1r(unit, &flush_ctrl)); 2668 flush_ctrl &= ~(0x1 << port_off); 2669 flush_ctrl |= enable ? (0x1 << port_off) : 0; 2670 SOC_IF_ERROR_RETURN 2671 (WRITE_MMUFLUSHCONTROL_1r(unit, flush_ctrl)); 2672 } 2673 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2674 (BSL_META_U(unit, 2675 "port %d MMUFLUSHCONTROl.FLUSH=0x%x\n"), port, flush_ctrl)); 2676 } 2677 break; 2678 #endif /* BCM_HURRICANE2_SUPPORT */ 2679 2680 #if defined(BCM_HURRICANE_SUPPORT) 2681 case SOC_CHIP_BCM56142: 2682 SOC_IF_ERROR_RETURN 2683 (READ_MMUFLUSHCONTROLr(unit, &flush_ctrl)); 2684 flush_ctrl &= ~(0x1 << port); 2685 flush_ctrl |= enable ? (0x1 << port) : 0; 2686 SOC_IF_ERROR_RETURN 2687 (WRITE_MMUFLUSHCONTROLr(unit, flush_ctrl)); 2688 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2689 (BSL_META_U(unit, 2690 "port %d MMUFLUSHCONTROl.FLUSH=0x%x\n"), port, flush_ctrl)); 2691 /* Fall through */ 2692 #endif /* BCM_HURRICANE_SUPPORT */ 2693 2694 #if defined(BCM_TRIUMPH2_SUPPORT) 2695 case SOC_CHIP_BCM56634: 2696 case SOC_CHIP_BCM56524: 2697 case SOC_CHIP_BCM56685: 2698 SOC_IF_ERROR_RETURN 2699 (READ_FAST_TX_FLUSHr(unit, port, &flush_ctrl)); 2700 soc_reg_field_set(unit, FAST_TX_FLUSHr, &flush_ctrl, IDf, 2701 (enable) ? 1 : 0); 2702 SOC_IF_ERROR_RETURN 2703 (WRITE_FAST_TX_FLUSHr(unit, port, flush_ctrl)); 2704 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2705 (BSL_META_U(unit, 2706 "port %d FAST_TX_FLUSH.ID=0x%x\n"), port, flush_ctrl)); 2707 /* Fall through */ 2708 #endif 2709 #if defined(BCM_TRIUMPH_SUPPORT) 2710 case SOC_CHIP_BCM56624: 2711 case SOC_CHIP_BCM56680: 2712 case SOC_CHIP_BCM56334: 2713 /*case SOC_CHIP_BCM88732:*/ 2714 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) { 2715 SOC_IF_ERROR_RETURN 2716 (READ_XP_EGR_PKT_DROP_CTLr(unit, port, &flush_ctrl)); 2717 soc_reg_field_set(unit, XP_EGR_PKT_DROP_CTLr, &flush_ctrl, FLUSHf, 2718 (enable) ? 1 : 0); 2719 SOC_IF_ERROR_RETURN 2720 (WRITE_XP_EGR_PKT_DROP_CTLr(unit, port, flush_ctrl)); 2721 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2722 (BSL_META_U(unit, 2723 "port %d XP_EGR_PKT_DROP_CTL.FLUSH=0x%x\n"), port, flush_ctrl)); 2724 } 2725 break; 2726 #endif /* BCM_TRIUMPH_SUPPORT */ 2727 2728 #if defined(BCM_SCORPION_SUPPORT) 2729 case SOC_CHIP_BCM56820: 2730 case SOC_CHIP_BCM56725: 2731 if (IS_GX_PORT(unit, port)) { 2732 SOC_IF_ERROR_RETURN 2733 (READ_XP_EGR_PKT_DROP_CTLr(unit, port, &flush_ctrl)); 2734 soc_reg_field_set(unit, XP_EGR_PKT_DROP_CTLr, &flush_ctrl, FLUSHf, 2735 (enable) ? 1 : 0); 2736 SOC_IF_ERROR_RETURN 2737 (WRITE_XP_EGR_PKT_DROP_CTLr(unit, port, flush_ctrl)); 2738 } 2739 break; 2740 #endif /* BCM_TRIUMPH_SUPPORT || BCM_SCORPION_SUPPORT */ 2741 2742 #if defined(BCM_TRIDENT_SUPPORT) 2743 case SOC_CHIP_BCM56840: 2744 SOC_IF_ERROR_RETURN 2745 (soc_reg_field32_modify(unit, XLP_TXFIFO_PKT_DROP_CTLr, port, 2746 DROP_ENf, enable ? 1 : 0)); 2747 break; 2748 #endif /* BCM_TRIDENT_SUPPORT */ 2749 2750 case SOC_CHIP_BCM56640: 2751 case SOC_CHIP_BCM56340: 2752 SOC_IF_ERROR_RETURN 2753 (soc_reg_field32_modify(unit, PORT_TXFIFO_PKT_DROP_CTLr, port, 2754 DROP_ENf, enable ? 1 : 0)); 2755 break; 2756 2757 #ifdef BCM_KATANA_SUPPORT 2758 case SOC_CHIP_BCM56440: 2759 case SOC_CHIP_BCM56450: 2760 case SOC_CHIP_BCM56260: 2761 case SOC_CHIP_BCM56270: 2762 if (!(SAL_BOOT_SIMULATION || SAL_BOOT_BCMSIM 2763 || SAL_BOOT_XGSSIM)) { 2764 soc_kt_port_flush_state_set(unit, port, TRUE); 2765 if (enable == 0) { 2766 rv = soc_kt_port_flush(unit, port, enable); 2767 } else { 2768 rv = soc_mmu_backpressure_clear(unit, port); 2769 if (SOC_FAILURE(rv)) { 2770 soc_kt_port_flush_state_set(unit, port, FALSE); 2771 return rv; 2772 } 2773 /* 2774 ***************************************************** 2775 * NOTE: Must not exit soc_kt_port_flush 2776 * without calling soc_egress_metering_thaw, 2777 * soc_egress_metering_freeze holds the lock. 2778 * soc_egress_metering_freeze releases the lock 2779 * on failure. 2780 */ 2781 rv = _soc_egress_metering_freeze(unit, 2782 port, &setting); 2783 if (SOC_FAILURE(rv)) { 2784 soc_kt_port_flush_state_set(unit, port, FALSE); 2785 return rv; 2786 } 2787 rv = soc_kt_port_flush(unit, port, enable); 2788 /* Restore egress metering configuration. */ 2789 rv1 = _soc_egress_metering_thaw(unit, port, setting); 2790 if (SOC_SUCCESS(rv)) { 2791 rv = rv1; 2792 } 2793 } 2794 soc_kt_port_flush_state_set(unit, port, FALSE); 2795 return rv; 2796 } 2797 break; 2798 #endif /* BCM_KATANA_SUPPORT */ 2799 2800 default: 2801 return SOC_E_NONE; 2802 } 2803 2804 return SOC_E_NONE; 2805 } 2806 2807 int 2808 soc_mmu_port_flush_hw(int unit, soc_port_t port, uint32 drain_timeout) 2809 { 2810 #if defined(BCM_TOMAHAWK2_SUPPORT) 2811 if (SOC_IS_TOMAHAWK2(unit)) { 2812 return SOC_E_NONE; 2813 } 2814 #endif 2815 #if defined(BCM_TOMAHAWK_SUPPORT) 2816 if (SOC_IS_TOMAHAWK(unit)) { 2817 return soc_tomahawk_mmu_port_flush_hw(unit, port, drain_timeout); 2818 } 2819 #endif 2820 #if defined(BCM_TRIDENT3_SUPPORT) 2821 if (SOC_IS_TRIDENT3X(unit)) { 2822 return SOC_E_NONE; 2823 } 2824 #endif 2825 return SOC_E_UNAVAIL; 2826 } 2827 2828 #if defined(BCM_TRIUMPH3_SUPPORT) 2829 /*#define IBOD_DEBUG*/ 2830 void soc_ibod_recovery_in_progress_set(int unit, int enable) 2831 { 2832 ibod_recovery_in_progress[unit] = enable; 2833 } 2834 int soc_ibod_recovery_in_progress_get(int unit) 2835 { 2836 return ibod_recovery_in_progress[unit]; 2837 } 2838 void _soc_egress_drain_timeout_flag_set(int unit, int flag) 2839 { 2840 egress_drain_timeout_flag[unit] = flag; 2841 } 2842 void _soc_egress_drain_timeout_flag_get(int unit, int *flag) 2843 { 2844 *flag = egress_drain_timeout_flag[unit]; 2845 } 2846 2847 #if defined(IBOD_DEBUG) || defined(TXERR_DEBUG) 2848 int _soc_egress_drain_debug(int unit, soc_port_t port, soc_reg_t reg) 2849 { 2850 uint32 credit, mmu_req, ep_level, total_count; 2851 egr_mmu_requests_entry_t mmu_entry; 2852 uint32 max_used_entry; 2853 int rv = SOC_E_NONE; 2854 uint32 rval; 2855 soc_info_t *si = &SOC_INFO(unit); 2856 2857 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &credit)); 2858 2859 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MMU_REQUESTSm, MEM_BLOCK_ANY, 2860 si->port_l2p_mapping[port], &mmu_entry)); 2861 mmu_req = soc_mem_field32_get(unit, EGR_MMU_REQUESTSm, &mmu_entry, OUTSTANDING_MMU_REQUESTSf); 2862 2863 SOC_IF_ERROR_RETURN(READ_EGR_EDB_MISC_CTRLr(unit, &rval)); 2864 soc_reg_field_set(unit, EGR_EDB_MISC_CTRLr, &rval, SELECT_CURRENT_USED_ENTRIESf, 1); 2865 SOC_IF_ERROR_RETURN(WRITE_EGR_EDB_MISC_CTRLr(unit, rval)); 2866 SOC_IF_ERROR_RETURN(READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL, 2867 si->port_l2p_mapping[port], &max_used_entry)); 2868 ep_level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm, &max_used_entry, LEVELf); 2869 2870 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &rval)); 2871 total_count = soc_reg_field_get(unit, OP_PORT_TOTAL_COUNT_CELLr,rval, TOTAL_COUNTf); 2872 2873 cli_out("Recovery: port %d mmu still has credit[total_count %d, level %d, credit %d mmu_req %d] \r\n", 2874 port, total_count, ep_level, credit, mmu_req); 2875 2876 return rv; 2877 } 2878 #endif /* IBOD_DEBUG || TXERR_DEBUG */ 2879 2880 int _soc_egress_drain_ep_max_level_get(int unit, soc_port_t port, uint32 *ep_max_level) 2881 { 2882 int rv = SOC_E_NONE; 2883 uint32 rval; 2884 uint32 max_used_entry; 2885 soc_info_t *si = &SOC_INFO(unit); 2886 2887 SOC_IF_ERROR_RETURN(READ_EGR_EDB_MISC_CTRLr(unit, &rval)); 2888 soc_reg_field_set(unit, EGR_EDB_MISC_CTRLr, &rval, SELECT_CURRENT_USED_ENTRIESf, 0); 2889 SOC_IF_ERROR_RETURN(WRITE_EGR_EDB_MISC_CTRLr(unit, rval)); 2890 2891 SOC_IF_ERROR_RETURN(READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL, si->port_l2p_mapping[port], &max_used_entry)); 2892 *ep_max_level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm, &max_used_entry, LEVELf); 2893 2894 return rv; 2895 } 2896 2897 int _soc_egress_drain_credit_calc(uint32 credit_current, uint32 credit_default, 2898 uint32 mmu_req, uint32 ep_level, uint32 *credit_set) 2899 { 2900 if (mmu_req > credit_default ) { 2901 if(ep_level < credit_default) { 2902 *credit_set = credit_default - ep_level; 2903 } 2904 else { 2905 *credit_set = credit_default; 2906 } 2907 } 2908 else if (mmu_req == 0) { 2909 if(ep_level < credit_default) { 2910 *credit_set = credit_default - ep_level; 2911 } 2912 else { 2913 *credit_set = credit_default; 2914 } 2915 } 2916 else if (mmu_req != credit_current) { 2917 *credit_set = mmu_req; 2918 } 2919 else { 2920 return 0; 2921 } 2922 2923 return 1; 2924 } 2925 #endif 2926 2927 int 2928 soc_egress_drain_cells(int unit, soc_port_t port, uint32 drain_timeout) 2929 { 2930 soc_timeout_t to; 2931 uint32 cur_cells, new_cells; 2932 int rv, rv1; 2933 void *setting = NULL; 2934 #if defined(BCM_TRIUMPH3_SUPPORT) 2935 uint32 max_used_entry, ep_level,rval, overflow0, overflow1, total_cell; 2936 uint32 credit, mmu_req, credit_set, mmu_cells; 2937 soc_info_t *si; 2938 egr_mmu_requests_entry_t mmu_entry; 2939 static const soc_reg_t lls_port_credit_reg[] = { 2940 LLS_PORT_0_CREDITr, LLS_PORT_1_CREDITr, LLS_PORT_2_CREDITr, 2941 LLS_PORT_3_CREDITr, LLS_PORT_4_CREDITr, LLS_PORT_5_CREDITr, 2942 LLS_PORT_6_CREDITr, LLS_PORT_7_CREDITr, LLS_PORT_8_CREDITr, 2943 LLS_PORT_9_CREDITr, LLS_PORT_10_CREDITr, LLS_PORT_11_CREDITr, 2944 LLS_PORT_12_CREDITr, LLS_PORT_13_CREDITr, LLS_PORT_14_CREDITr, 2945 LLS_PORT_15_CREDITr, LLS_PORT_16_CREDITr, LLS_PORT_17_CREDITr, 2946 LLS_PORT_18_CREDITr, LLS_PORT_19_CREDITr, LLS_PORT_20_CREDITr, 2947 LLS_PORT_21_CREDITr, LLS_PORT_22_CREDITr, LLS_PORT_23_CREDITr, 2948 LLS_PORT_24_CREDITr, LLS_PORT_25_CREDITr, LLS_PORT_26_CREDITr, 2949 LLS_PORT_27_CREDITr, LLS_PORT_28_CREDITr, LLS_PORT_29_CREDITr, 2950 LLS_PORT_30_CREDITr, LLS_PORT_31_CREDITr, LLS_PORT_32_CREDITr, 2951 LLS_PORT_33_CREDITr, LLS_PORT_34_CREDITr, LLS_PORT_35_CREDITr, 2952 LLS_PORT_36_CREDITr, LLS_PORT_37_CREDITr, LLS_PORT_38_CREDITr, 2953 LLS_PORT_39_CREDITr, LLS_PORT_40_CREDITr, LLS_PORT_41_CREDITr, 2954 LLS_PORT_42_CREDITr, LLS_PORT_43_CREDITr, LLS_PORT_44_CREDITr, 2955 LLS_PORT_45_CREDITr, LLS_PORT_46_CREDITr, LLS_PORT_47_CREDITr, 2956 LLS_PORT_48_CREDITr, LLS_PORT_49_CREDITr, LLS_PORT_50_CREDITr, 2957 LLS_PORT_51_CREDITr, LLS_PORT_52_CREDITr, LLS_PORT_53_CREDITr, 2958 LLS_PORT_54_CREDITr, LLS_PORT_55_CREDITr, LLS_PORT_56_CREDITr, 2959 LLS_PORT_57_CREDITr, LLS_PORT_58_CREDITr, LLS_PORT_59_CREDITr, 2960 LLS_PORT_60_CREDITr, LLS_PORT_61_CREDITr, LLS_PORT_62_CREDITr 2961 }; 2962 si = &SOC_INFO(unit); 2963 #endif 2964 if (soc_feature(unit, soc_feature_mmu_hw_flush)) { 2965 SOC_IF_ERROR_RETURN(soc_mmu_port_flush_hw(unit, port, drain_timeout)); 2966 rv = SOC_E_NONE; 2967 } else { 2968 if(!SOC_IS_KATANAX(unit)) { 2969 SOC_IF_ERROR_RETURN(soc_mmu_backpressure_clear(unit, port)); 2970 2971 /* 2972 ************************************************************** 2973 * NOTE: Must not exit this function without calling 2974 * soc_egress_metering_thaw(). soc_egress_metering_freeze 2975 * holds a lock. 2976 */ 2977 SOC_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, port, &setting)); 2978 } 2979 2980 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2981 if (SOC_IS_APACHE(unit) || 2982 SOC_IS_TRIDENT2PLUS(unit) || 2983 SOC_IS_TRIDENT2(unit)) { 2984 int empty = 0; 2985 if (SOC_IS_TRIDENT2PLUS(unit)) { 2986 /* Wait long enough to ensure CT FIFO of flushed ports are empty */ 2987 sal_usleep(4); 2988 } 2989 if (SOC_IS_MONTEREY(unit)) { 2990 /* extra delay added in monterey to drain the transit macsec packets for the port*/ 2991 sal_usleep(1000); 2992 } 2993 2994 soc_timeout_init(&to, drain_timeout, 0); 2995 for (;;) { 2996 rv = _soc_egress_cell_check(unit, port, &empty); 2997 if (empty == TRUE) { 2998 break; 2999 } 3000 if (soc_timeout_check(&to)) { 3001 rv = _soc_egress_cell_check(unit, port, &empty); 3002 if (empty == TRUE) { 3003 break; 3004 } 3005 /* Don't return error so that remaining port sequence is executed 3006 * and port is recovered successfully 3007 */ 3008 LOG_WARN(BSL_LS_SOC_COMMON, 3009 (BSL_META_U(unit, 3010 "MacDrainTimeOut:port %d,%s, " 3011 "timeout draining packets \n"), 3012 unit, SOC_PORT_NAME(unit, port))); 3013 break; 3014 } 3015 } 3016 } else 3017 #endif /* BCM_APACHE_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT || BCM_TRIDENT2_SUPPORT */ 3018 { 3019 3020 #if defined(BCM_TRIDENT2_SUPPORT) 3021 3022 #endif /* BCM_TRIDENT2_SUPPORT */ 3023 3024 cur_cells = 0xffffffff; 3025 3026 /* Probably not required to continuously check COSLCCOUNT if the fast 3027 * MMU flush feature is available - done just as an insurance */ 3028 rv = SOC_E_NONE; 3029 for (;;) { 3030 #if defined(BCM_TRIUMPH3_SUPPORT) 3031 /* only for TR3 MMU drain cells */ 3032 if(SOC_IS_TRIUMPH3(unit) && !SOC_IS_HELIX4(unit) && 3033 IS_CL_PORT(unit, port) && ibod_recovery_in_progress[unit]) { 3034 #ifdef IBOD_DEBUG 3035 uint32 ep_max_level = 0; 3036 uint32 mmu_req_1 = 0; 3037 /* check epc_link_bmap for debug */ 3038 pbmp_t pbm; 3039 epc_link_bmap_entry_t entry; 3040 READ_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0,&entry); 3041 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, &entry, PORT_BITMAPf, &pbm); 3042 if (SOC_PBMP_MEMBER(pbm, port)) { 3043 LOG_WARN(BSL_LS_BCM_PORT, 3044 (BSL_META_U(unit, 3045 "soc_egress_drain_cells:unit %d port %d still in epc link bitmap 0x%x\r\n"), 3046 unit, port, pbm.pbits[0])); 3047 } 3048 #endif 3049 new_cells=0; 3050 3051 /* check MMU cell */ 3052 if ((rv = soc_egress_cell_count(unit, port, &mmu_cells)) < 0) { 3053 break; 3054 } 3055 new_cells += mmu_cells; 3056 3057 /* read MMU credit */ 3058 rv = soc_reg32_get(unit,lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]], REG_PORT_ANY, 0, &credit); 3059 SOC_IF_ERROR_RETURN(rv); 3060 3061 rv = soc_mem_read(unit, EGR_MMU_REQUESTSm, MEM_BLOCK_ANY, si->port_l2p_mapping[port], &mmu_entry); 3062 SOC_IF_ERROR_RETURN(rv); 3063 mmu_req = soc_mem_field32_get(unit, EGR_MMU_REQUESTSm, &mmu_entry, OUTSTANDING_MMU_REQUESTSf); 3064 3065 /* read EP level */ 3066 rv = READ_EGR_EDB_MISC_CTRLr(unit, &rval); 3067 SOC_IF_ERROR_RETURN(rv); 3068 soc_reg_field_set(unit, EGR_EDB_MISC_CTRLr, &rval, SELECT_CURRENT_USED_ENTRIESf, 1); 3069 rv = WRITE_EGR_EDB_MISC_CTRLr(unit, rval); 3070 SOC_IF_ERROR_RETURN(rv); 3071 rv = READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL, si->port_l2p_mapping[port], &max_used_entry); 3072 SOC_IF_ERROR_RETURN(rv); 3073 ep_level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm, &max_used_entry, LEVELf); 3074 3075 /* Update cur_cells and give more time to drain packets. */ 3076 if (new_cells < cur_cells) { 3077 soc_timeout_init(&to, drain_timeout, 0); 3078 cur_cells = new_cells; 3079 } 3080 else { 3081 rv = soc_reg32_set(unit,lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]], REG_PORT_ANY, 0, si->port_credit[port]); 3082 SOC_IF_ERROR_RETURN(rv); 3083 #ifdef IBOD_DEBUG 3084 cli_out("soc_egress_drain_cells: port %d mmu cells not draining: %d cells remain,cur_cells %d, mmu_cells %d, level %d, credit %d mmu_req %d \r\n", 3085 port, new_cells, cur_cells, mmu_cells, ep_level, credit, mmu_req); 3086 #endif 3087 } 3088 if (soc_timeout_check(&to)) { 3089 if (ep_level == 0){ 3090 _soc_egress_drain_timeout_flag_set(unit, 1); 3091 #ifdef IBOD_DEBUG 3092 cli_out("soc_egress_drain_cells: Timeout Drain packets and ep_level is 0 (port %d, %d cells remain,cur_cells %d, mmu_cells %d, level %d, credit %d mmu_req %d) \r\n", 3093 port, new_cells, cur_cells, mmu_cells, ep_level, credit, mmu_req); 3094 #endif 3095 rv = SOC_E_NONE; 3096 break; 3097 } 3098 else { 3099 SOC_IF_ERROR_RETURN(READ_PQEFIFOOVERFLOW0r(unit, &overflow0)); 3100 SOC_IF_ERROR_RETURN(READ_PQEFIFOOVERFLOW1r(unit, &overflow1)); 3101 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &total_cell)); 3102 LOG_ERROR(BSL_LS_BCM_PORT, 3103 (BSL_META_U(unit, 3104 "\n soc_egress_drain_cells: Timeout Drain packets unit %d PORT: %s" 3105 "(%d cells remain,cur_cells %d, mmu_cells %d, level %d, credit %d " 3106 "mmu_req %d overflow0 %d overflow1 %d total_cell %d) \r\n"), 3107 unit, SOC_PORT_NAME(unit,port), 3108 new_cells,cur_cells, mmu_cells, ep_level, credit, 3109 mmu_req, overflow0, overflow1, total_cell)); 3110 rv = SOC_E_INTERNAL; 3111 break; 3112 } 3113 } 3114 3115 #ifdef IBOD_DEBUG 3116 /* for debug */ 3117 rv = soc_mem_read(unit, EGR_MMU_REQUESTSm, MEM_BLOCK_ANY, si->port_l2p_mapping[port], &mmu_entry); 3118 SOC_IF_ERROR_RETURN(rv); 3119 mmu_req_1 = soc_mem_field32_get(unit, EGR_MMU_REQUESTSm, &mmu_entry, OUTSTANDING_MMU_REQUESTSf); 3120 if(mmu_req_1 != mmu_req){ 3121 cli_out("soc_egress_drain_cells: port %d credit %d mmu_req %d is not equal mmu_req_1 %d !!!!!\r\n",port,credit, mmu_req, mmu_req_1); 3122 } 3123 #endif 3124 /* All packets were drained */ 3125 if (new_cells == 0) { 3126 /* default credit is not set */ 3127 if(si->port_credit[port] == 0) { 3128 si->port_credit[port] = mmu_req; 3129 } 3130 3131 if (_soc_egress_drain_credit_calc(credit, si->port_credit[port], mmu_req, ep_level, &credit_set)) { 3132 rv = soc_reg32_set(unit,lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]], REG_PORT_ANY, 0, credit_set); 3133 SOC_IF_ERROR_RETURN(rv); 3134 } 3135 #ifdef IBOD_DEBUG 3136 rv = _soc_egress_drain_ep_max_level_get(unit, port, &ep_max_level); 3137 if(rv == SOC_E_NONE) 3138 { 3139 cli_out("IBOD recovery: MacDrainOK max_level %d !!!!!\r\n", ep_max_level); 3140 } 3141 #endif 3142 break; 3143 } 3144 else if (mmu_cells){ /* some packets still stay in MMU */ 3145 if((credit == 0)) { 3146 rv = soc_reg32_get(unit,lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]], REG_PORT_ANY, 0, &credit); 3147 SOC_IF_ERROR_RETURN(rv); 3148 if(credit == 0) { 3149 rv = soc_mem_read(unit, EGR_MMU_REQUESTSm, MEM_BLOCK_ANY, si->port_l2p_mapping[port], &mmu_entry); 3150 SOC_IF_ERROR_RETURN(rv); 3151 mmu_req = soc_mem_field32_get(unit, EGR_MMU_REQUESTSm, &mmu_entry, OUTSTANDING_MMU_REQUESTSf); 3152 3153 /* default credit is not set */ 3154 if(si->port_credit[port] == 0) { 3155 si->port_credit[port] = mmu_req; 3156 } 3157 3158 if (_soc_egress_drain_credit_calc(credit, si->port_credit[port], mmu_req, ep_level, &credit_set)) { 3159 rv = soc_reg32_set(unit,lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]], REG_PORT_ANY, 0, credit_set); 3160 SOC_IF_ERROR_RETURN(rv); 3161 } 3162 } 3163 else { 3164 #ifdef IBOD_DEBUG 3165 _soc_egress_drain_debug(unit, port, lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]]); 3166 #endif 3167 } 3168 } 3169 else { 3170 #ifdef IBOD_DEBUG 3171 _soc_egress_drain_debug(unit, port, lls_port_credit_reg[si->port_p2m_mapping[si->port_l2p_mapping[port]]]); 3172 #endif 3173 } 3174 } 3175 } 3176 else 3177 #endif 3178 { 3179 if ((rv = soc_egress_cell_count(unit, port, &new_cells)) < 0) { 3180 break; 3181 } 3182 3183 if (new_cells == 0) { 3184 rv = SOC_E_NONE; 3185 break; 3186 } 3187 3188 if (new_cells < cur_cells) { /* Progress made */ 3189 /* Restart timeout */ 3190 soc_timeout_init(&to, drain_timeout, 0); 3191 cur_cells = new_cells; 3192 } 3193 3194 if (soc_timeout_check(&to)) { 3195 if ((rv = soc_egress_cell_count(unit, port, &new_cells)) < 0) { 3196 break; 3197 } 3198 #if defined(BCM_TRIUMPH3_SUPPORT) 3199 /*Drain timeout is not a real issue for triumph3 and Helix4, so need not return error code*/ 3200 if(SOC_IS_HELIX4(unit)){ 3201 SOC_IF_ERROR_RETURN(READ_EGR_EDB_MISC_CTRLr(unit, &rval)); 3202 soc_reg_field_set(unit, EGR_EDB_MISC_CTRLr, &rval, SELECT_CURRENT_USED_ENTRIESf, 1); 3203 SOC_IF_ERROR_RETURN(WRITE_EGR_EDB_MISC_CTRLr(unit, rval)); 3204 SOC_IF_ERROR_RETURN(READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL, 3205 si->port_l2p_mapping[port], &max_used_entry)); 3206 ep_level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm, &max_used_entry, LEVELf); 3207 SOC_IF_ERROR_RETURN(READ_PQEFIFOOVERFLOW0r(unit, &overflow0)); 3208 SOC_IF_ERROR_RETURN(READ_PQEFIFOOVERFLOW1r(unit, &overflow1)); 3209 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &total_cell)); 3210 if(ep_level == 0) { 3211 _soc_egress_drain_timeout_flag_set(unit, 1); 3212 } 3213 else { 3214 LOG_ERROR(BSL_LS_SOC_COMMON, 3215 (BSL_META_U(unit, 3216 "MacDrainTimeOut:port %d,%s, " 3217 "timeout draining packets (%d cells remain), ep_level:%d, overflow0:%d, overflow1:%d,total_cell:%d\n"), 3218 unit, SOC_PORT_NAME(unit, port), new_cells, ep_level, overflow0, overflow1,total_cell)); 3219 } 3220 } 3221 #else 3222 LOG_ERROR(BSL_LS_SOC_COMMON, 3223 (BSL_META_U(unit,"MacDrainTimeOut:port %d,%s, " 3224 "timeout draining packets (%d cells remain)\n"), 3225 unit, SOC_PORT_NAME(unit, port), new_cells)); 3226 rv = SOC_E_INTERNAL; 3227 #endif 3228 break; 3229 } 3230 } 3231 } 3232 } 3233 3234 if (!SOC_IS_KATANAX(unit)) { 3235 /* Restore egress metering configuration. */ 3236 rv1 = _soc_egress_metering_thaw(unit, port, setting); 3237 if (SOC_SUCCESS(rv)) { 3238 rv = rv1; 3239 } 3240 } 3241 } 3242 3243 return rv; 3244 } 3245 3246 int 3247 soc_txfifo_drain_cells(int unit, soc_port_t port, uint32 drain_timeout) 3248 { 3249 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 3250 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit)) { 3251 soc_timeout_t to; 3252 int count = 0; 3253 3254 soc_timeout_init(&to, drain_timeout, 0); 3255 for (;;) { 3256 SOC_IF_ERROR_RETURN 3257 (_soc_port_txfifo_cell_count(unit, port, &count)); 3258 if (!count) { 3259 break; 3260 } 3261 if (soc_timeout_check(&to)) { 3262 LOG_ERROR(BSL_LS_SOC_COMMON, 3263 (BSL_META_U(unit, 3264 "MacDrainTimeOut:port %d,%s, timeout draining TXFIFO " 3265 "(pending: %d)\n"), 3266 unit, SOC_PORT_NAME(unit, port), count)); 3267 return SOC_E_INTERNAL; 3268 } 3269 } 3270 } 3271 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */ 3272 3273 return SOC_E_NONE; 3274 } 3275 3276 int 3277 soc_port_credit_reset(int unit, soc_port_t port) 3278 { 3279 int phy_port; 3280 egr_port_credit_reset_entry_t entry; 3281 3282 switch (SOC_CHIP_GROUP(unit)) { 3283 case SOC_CHIP_BCM56850: 3284 case SOC_CHIP_BCM56860: 3285 case SOC_CHIP_BCM56560: 3286 case SOC_CHIP_BCM56870: 3287 case SOC_CHIP_BCM56770: 3288 case SOC_CHIP_BCM56370: 3289 case SOC_CHIP_BCM56970: 3290 case SOC_CHIP_BCM56670: 3291 /* Should be called by CLMAC and XLMAC driver */ 3292 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3293 sal_memset(&entry, 0, sizeof(entry)); 3294 soc_mem_field32_set(unit, EGR_PORT_CREDIT_RESETm, &entry, VALUEf, 1); 3295 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_CREDIT_RESETm(unit, MEM_BLOCK_ALL, 3296 phy_port, &entry)); 3297 soc_mem_field32_set(unit, EGR_PORT_CREDIT_RESETm, &entry, VALUEf, 0); 3298 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_CREDIT_RESETm(unit, MEM_BLOCK_ALL, 3299 phy_port, &entry)); 3300 break; 3301 case SOC_CHIP_BCM56150: 3302 case SOC_CHIP_BCM53400: 3303 case SOC_CHIP_BCM56160: 3304 case SOC_CHIP_BCM53570: 3305 case SOC_CHIP_BCM53540: 3306 { 3307 uint32 rval; 3308 int bindex; 3309 static const soc_field_t port_field[] = { 3310 PORT0f, PORT1f, PORT2f, PORT3f 3311 }; 3312 soc_reg_t txfifo_reg; 3313 3314 /* Should only be called by XLMAC/CLMAC driver */ 3315 if (!IS_XL_PORT(unit, port) && !IS_CL_PORT(unit, port)) { 3316 break; 3317 } 3318 3319 txfifo_reg = XLPORT_TXFIFO_CTRLr; 3320 3321 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3322 bindex = SOC_PORT_BINDEX(unit, phy_port); 3323 3324 #ifdef BCM_GREYHOUND_SUPPORT 3325 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 3326 SOC_IS_GREYHOUND2(unit)){ 3327 int blk, blktype; 3328 blk = SOC_PORT_BLOCK(unit, phy_port); 3329 blktype = SOC_BLOCK_INFO(unit, blk).type; 3330 if (blktype == SOC_BLK_GXPORT){ 3331 txfifo_reg = PGW_GX_TXFIFO_CTRLr; 3332 } else if (blktype == SOC_BLK_XLPORT) { 3333 txfifo_reg = PGW_XL_TXFIFO_CTRLr; 3334 } else if (blktype == SOC_BLK_CLPORT) { 3335 txfifo_reg = PGW_CL_TXFIFO_CTRLr; 3336 } 3337 } 3338 #endif 3339 3340 if (IS_CL_PORT(unit, port)) { 3341 if (SOC_REG_PORT_VALID(unit, CLPORT_ENABLE_REGr, port)) { 3342 SOC_IF_ERROR_RETURN 3343 (soc_reg_field32_modify(unit, CLPORT_ENABLE_REGr, port, 3344 port_field[bindex], 0)); 3345 } 3346 } else { 3347 if (SOC_REG_PORT_VALID(unit, XLPORT_ENABLE_REGr, port)) { 3348 SOC_IF_ERROR_RETURN 3349 (soc_reg_field32_modify(unit, XLPORT_ENABLE_REGr, port, 3350 port_field[bindex], 0)); 3351 } 3352 } 3353 3354 sal_memset(&entry, 0, sizeof(entry)); 3355 soc_mem_field32_set(unit, EGR_PORT_CREDIT_RESETm, &entry, VALUEf, 1); 3356 SOC_IF_ERROR_RETURN 3357 (WRITE_EGR_PORT_CREDIT_RESETm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3358 3359 SOC_IF_ERROR_RETURN 3360 (soc_reg32_get(unit, txfifo_reg, port, 0, &rval)); 3361 soc_reg_field_set(unit, txfifo_reg, &rval, MAC_CLR_COUNTf,1); 3362 soc_reg_field_set(unit, txfifo_reg, &rval, CORE_CLR_COUNTf,1); 3363 SOC_IF_ERROR_RETURN 3364 (soc_reg32_set(unit, txfifo_reg, port, 0, rval)); 3365 3366 sal_usleep(1000); 3367 3368 soc_mem_field32_set(unit, EGR_PORT_CREDIT_RESETm, &entry, VALUEf, 0); 3369 SOC_IF_ERROR_RETURN 3370 (WRITE_EGR_PORT_CREDIT_RESETm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3371 3372 SOC_IF_ERROR_RETURN 3373 (soc_reg32_get(unit, txfifo_reg, port, 0, &rval)); 3374 soc_reg_field_set(unit, txfifo_reg, &rval, MAC_CLR_COUNTf, 0); 3375 soc_reg_field_set(unit, txfifo_reg, &rval, CORE_CLR_COUNTf, 0); 3376 SOC_IF_ERROR_RETURN 3377 (soc_reg32_set(unit, txfifo_reg, port, 0, rval)); 3378 3379 if (IS_CL_PORT(unit, port)) { 3380 if (SOC_REG_PORT_VALID(unit, CLPORT_ENABLE_REGr, port)) { 3381 SOC_IF_ERROR_RETURN 3382 (soc_reg_field32_modify(unit, CLPORT_ENABLE_REGr, port, 3383 port_field[bindex], 1)); 3384 } 3385 } else { 3386 if (SOC_REG_PORT_VALID(unit, XLPORT_ENABLE_REGr, port)) { 3387 SOC_IF_ERROR_RETURN 3388 (soc_reg_field32_modify(unit, XLPORT_ENABLE_REGr, port, 3389 port_field[bindex], 1)); 3390 } 3391 } 3392 } 3393 break; 3394 #if defined(BCM_SABER2_SUPPORT) 3395 case SOC_CHIP_BCM56260: 3396 case SOC_CHIP_BCM56270: 3397 /* Bring the port down and back up to clear credits */ 3398 SOC_IF_ERROR_RETURN(soc_saber2_port_enable_set(unit, port, 0)); 3399 SOC_IF_ERROR_RETURN(soc_saber2_port_enable_set(unit, port, 1)); 3400 break; 3401 #endif 3402 default: 3403 break; 3404 } 3405 3406 return SOC_E_NONE; 3407 } 3408 3409 int 3410 soc_port_ingress_buffer_reset(int unit, soc_port_t port, int reset) 3411 { 3412 switch (SOC_CHIP_GROUP(unit)) { 3413 #if defined (BCM_TRIDENT2PLUS_SUPPORT) 3414 case SOC_CHIP_BCM56860: 3415 /* Poll until PGW buffers are empty */ 3416 SOC_IF_ERROR_RETURN(soc_td2p_idb_buf_reset(unit, port, reset)); 3417 break; 3418 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 3419 #if defined(BCM_TOMAHAWK_SUPPORT) 3420 case SOC_CHIP_BCM56960: 3421 case SOC_CHIP_BCM56965: 3422 SOC_IF_ERROR_RETURN(soc_tomahawk_idb_buf_reset(unit, port, reset)); 3423 break; 3424 #endif 3425 #if defined(BCM_TOMAHAWK2_SUPPORT) 3426 case SOC_CHIP_BCM56970: 3427 SOC_IF_ERROR_RETURN(soc_tomahawk2_idb_buf_reset(unit, port, reset)); 3428 break; 3429 #endif 3430 case SOC_CHIP_BCM56870: 3431 #if defined(BCM_TRIDENT3_SUPPORT) 3432 { 3433 SOC_IF_ERROR_RETURN(soc_trident3_idb_buf_reset(unit, port, reset)); 3434 } 3435 #endif 3436 break; 3437 case SOC_CHIP_BCM56560: 3438 #if defined(BCM_APACHE_SUPPORT) 3439 { 3440 SOC_IF_ERROR_RETURN(soc_apache_idb_buf_reset(unit, port, reset)); 3441 } 3442 #endif /* BCM_APACHE_SUPPORT */ 3443 break; 3444 case SOC_CHIP_BCM56670: 3445 #if defined(BCM_MONTEREY_SUPPORT) 3446 { 3447 SOC_IF_ERROR_RETURN(soc_monterey_idb_buf_reset(unit, port, reset)); 3448 } 3449 #endif /* BCM_APACHE_SUPPORT */ 3450 default: 3451 break; 3452 } 3453 return SOC_E_NONE; 3454 } 3455 3456 #if defined (BCM_TRIDENT2_SUPPORT) 3457 STATIC int 3458 soc_port_credit_init(int unit, soc_port_t port) 3459 { 3460 #ifdef BCM_XLMAC_SUPPORT 3461 soc_info_t *si = &SOC_INFO(unit); 3462 soc_reg_t reg; 3463 uint32 rval; 3464 int rv = SOC_E_NONE, mac_lb, speed; 3465 int phy_port, mmu_port, pipe; 3466 static soc_reg_t mmu_port_credit_regs[] = { 3467 ES_PIPE0_MMU_PORT_CREDITr, ES_PIPE1_MMU_PORT_CREDITr 3468 }; 3469 3470 rv = soc_mac_xl.md_lb_get(unit, port, &mac_lb); 3471 if (SOC_SUCCESS(rv) && mac_lb) { 3472 rv = soc_mac_xl.md_speed_get(unit, port, &speed); 3473 } else { 3474 rv = soc_phyctrl_speed_get(unit, port, &speed); 3475 if (SOC_E_UNAVAIL == rv) { 3476 /* PHY driver doesn't support speed_get. 3477 * Get the speed from MAC. 3478 */ 3479 rv = soc_mac_xl.md_speed_get(unit, port, &speed); 3480 } 3481 if ((IS_HG_PORT(unit, port) && speed < 5000) && 3482 !(IS_HL_PORT(unit,port))) { 3483 speed = 0; 3484 } 3485 } 3486 /* Set MMU port credit */ 3487 pipe = SOC_PBMP_MEMBER(si->ypipe_pbm, port) ? 1 : 0; 3488 reg = mmu_port_credit_regs[pipe]; 3489 phy_port = si->port_l2p_mapping[port]; 3490 mmu_port = si->port_p2m_mapping[phy_port]; 3491 3492 if (speed > 21000){ 3493 rval = 48; 3494 } else if (speed > 11000) { 3495 rval = 24; 3496 } else if (speed > 1000) { 3497 rval = 12; 3498 } else { 3499 rval = 3; 3500 } 3501 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 3502 mmu_port & 0x3f, rval)); 3503 #endif 3504 return SOC_E_NONE; 3505 } 3506 #endif 3507 3508 int 3509 soc_port_egress_buffer_sft_reset(int unit, soc_port_t port, int reset) 3510 { 3511 switch (SOC_CHIP_GROUP(unit)) { 3512 case SOC_CHIP_BCM56850: 3513 #if defined (BCM_TRIDENT2_SUPPORT) 3514 { 3515 soc_info_t *si = &SOC_INFO(unit); 3516 soc_reg_t reg; 3517 soc_field_t fields; 3518 int phy_port, block, bindex, lanemode, lanenum, i; 3519 uint32 xmrval, errval, value, entry; 3520 static soc_reg_t egr_reset_regs[] = { 3521 EGR_XLPORT_BUFFER_SFT_RESET_0_Xr, EGR_XLPORT_BUFFER_SFT_RESET_1_Xr, 3522 EGR_XLPORT_BUFFER_SFT_RESET_0_Yr, EGR_XLPORT_BUFFER_SFT_RESET_1_Yr 3523 }; 3524 static soc_field_t egr_reset_fields[] = { 3525 XLP0_RESETf, XLP1_RESETf, XLP2_RESETf, XLP3_RESETf, 3526 XLP4_RESETf, XLP5_RESETf, XLP6_RESETf, XLP7_RESETf, 3527 XLP8_RESETf, XLP9_RESETf, XLP10_RESETf, XLP11_RESETf, 3528 XLP12_RESETf, XLP13_RESETf, XLP14_RESETf, XLP15_RESETf 3529 }; 3530 3531 /* Find physical for the specified port */ 3532 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3533 3534 /* Find lane index for the specified port (base port) */ 3535 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 3536 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 3537 if (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) { 3538 break; 3539 } 3540 } 3541 3542 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 3543 3544 /* Get the current mode */ 3545 SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port, &xmrval)); 3546 lanemode = soc_reg_field_get(unit, XLPORT_MODE_REGr, xmrval, 3547 XPORT0_CORE_PORT_MODEf); 3548 3549 /* Figure out the current number of lanes */ 3550 switch (lanemode) { 3551 case SOC_TD2_PORT_MODE_QUAD: 3552 lanenum = 1; 3553 break; 3554 case SOC_TD2_PORT_MODE_TRI_012: 3555 lanenum = bindex == 0 ? 1 : 2; 3556 break; 3557 case SOC_TD2_PORT_MODE_TRI_023: 3558 lanenum = bindex == 0 ? 2 : 1; 3559 break; 3560 case SOC_TD2_PORT_MODE_DUAL: 3561 lanenum = 2; 3562 break; 3563 case SOC_TD2_PORT_MODE_SINGLE: 3564 lanenum = 4; 3565 break; 3566 default: 3567 return SOC_E_FAIL; 3568 } 3569 3570 if (lanenum == 1) { 3571 /* Don't reset egress buffer if port only take 1 lane */ 3572 return SOC_E_NONE; 3573 } 3574 3575 if (lanenum == 4) { /* reset all 4 lanes */ 3576 value = 4; 3577 } else if (bindex == 0) { /* reset lanes 0 and 1 */ 3578 value = 1; 3579 } else { /* reset lanes 2 and 3 */ 3580 value = 2; 3581 } 3582 3583 /* Reset egress hardware resource */ 3584 reg = egr_reset_regs[si->port_serdes[port] / 8]; 3585 fields = egr_reset_fields[si->port_serdes[port] % 16]; 3586 3587 SOC_IF_ERROR_RETURN 3588 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &errval)); 3589 3590 if (reset) { 3591 /* 3592 * Hold EDB port buffer in reset state and disable cell 3593 * request generation in EP. 3594 */ 3595 SOC_IF_ERROR_RETURN 3596 (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3597 soc_mem_field32_set(unit, EGR_ENABLEm, &entry, PRT_ENABLEf, 0); 3598 SOC_IF_ERROR_RETURN 3599 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3600 3601 soc_reg_field_set(unit, reg, &errval, fields, value); 3602 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 3603 errval)); 3604 } else { 3605 /* 3606 * Release EDB port buffer reset and enable cell request 3607 * generation in EP. 3608 */ 3609 soc_reg_field_set(unit, reg, &errval, fields, 0); 3610 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 3611 errval)); 3612 3613 SOC_IF_ERROR_RETURN 3614 (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3615 soc_mem_field32_set(unit, EGR_ENABLEm, &entry, PRT_ENABLEf, 1); 3616 SOC_IF_ERROR_RETURN 3617 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3618 /* 3619 * Config credit after EGR_ENABLE is set. 3620 */ 3621 SOC_IF_ERROR_RETURN(soc_port_credit_init(unit, port)); 3622 } 3623 } 3624 #endif 3625 break; 3626 3627 #if defined (BCM_TRIDENT2PLUS_SUPPORT) 3628 case SOC_CHIP_BCM56860: 3629 SOC_IF_ERROR_RETURN(soc_td2p_edb_buf_reset(unit, port, reset)); 3630 break; 3631 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 3632 3633 case SOC_CHIP_BCM56870: 3634 case SOC_CHIP_BCM56770: 3635 case SOC_CHIP_BCM56370: 3636 #if defined(BCM_TRIDENT3_SUPPORT) 3637 { 3638 SOC_IF_ERROR_RETURN(soc_trident3_edb_buf_reset(unit, port, reset)); 3639 } 3640 #endif 3641 break; 3642 3643 #if defined(BCM_TOMAHAWK_SUPPORT) 3644 case SOC_CHIP_BCM56960: 3645 case SOC_CHIP_BCM56965: 3646 SOC_IF_ERROR_RETURN(soc_tomahawk_edb_buf_reset(unit, port, reset)); 3647 break; 3648 #endif 3649 #if defined(BCM_TOMAHAWK2_SUPPORT) 3650 case SOC_CHIP_BCM56970: 3651 SOC_IF_ERROR_RETURN(soc_tomahawk2_edb_buf_reset(unit, port, reset)); 3652 break; 3653 #endif 3654 case SOC_CHIP_BCM56560: 3655 #if defined(BCM_APACHE_SUPPORT) 3656 { 3657 SOC_IF_ERROR_RETURN(soc_apache_edb_buf_reset(unit, port, reset)); 3658 } 3659 #endif /* BCM_APACHE_SUPPORT */ 3660 break; 3661 3662 case SOC_CHIP_BCM56670: 3663 3664 #if defined(BCM_MONTEREY_SUPPORT) 3665 if(SOC_IS_MONTEREY(unit)) 3666 { 3667 SOC_IF_ERROR_RETURN(soc_monterey_edb_buf_reset(unit, port, reset)); 3668 } 3669 #endif /* BCM_MONTEREY_SUPPORT */ 3670 default: 3671 break; 3672 } 3673 3674 return SOC_E_NONE; 3675 } 3676 3677 int 3678 soc_port_fifo_reset(int unit, soc_port_t port) 3679 { 3680 int phy_port, block, bindex, i; 3681 uint32 rval, orig_rval; 3682 static const soc_field_t fields[] = { 3683 PORT0f, PORT1f, PORT2f, PORT3f 3684 }; 3685 3686 switch (SOC_CHIP_GROUP(unit)) { 3687 case SOC_CHIP_BCM56850: 3688 case SOC_CHIP_BCM56860: 3689 #if defined(BCM_TRIDENT2_SUPPORT) 3690 /* OBM counters will be cleared by XLPORT_SOFT_RESET. 3691 * Clear in counter thread accordingly. 3692 */ 3693 SOC_IF_ERROR_RETURN(soc_td2_obm_counters_reset(unit, port)); 3694 #endif /* BCM_TRIDENT2_SUPPORT */ 3695 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3696 SOC_IF_ERROR_RETURN(READ_XLPORT_SOFT_RESETr(unit, port, &rval)); 3697 orig_rval = rval; 3698 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 3699 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 3700 if (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) { 3701 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 3702 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, 3703 fields[bindex], 1); 3704 break; 3705 } 3706 } 3707 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval)); 3708 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, orig_rval)); 3709 break; 3710 case SOC_CHIP_BCM56560: 3711 case SOC_CHIP_BCM56670: 3712 { 3713 soc_block_t port_blk; 3714 soc_reg_t port_reset_reg; 3715 3716 if (IS_CXX_PORT(unit, port) && 3717 (SOC_INFO(unit).port_speed_max[port] >= 100000)) { 3718 port_blk = SOC_BLK_CLPORT; 3719 port_reset_reg = CLPORT_SOFT_RESETr; 3720 } else if (IS_CL_PORT(unit, port) || IS_CLG2_PORT(unit, port)) { 3721 port_blk = SOC_BLK_CLPORT; 3722 port_reset_reg = CLPORT_SOFT_RESETr; 3723 } else if (IS_CLG2_PORT(unit, port)) { 3724 port_blk = SOC_BLK_CLG2PORT; 3725 port_reset_reg = CLPORT_SOFT_RESETr; 3726 } else { 3727 port_blk = SOC_BLK_XLPORT; 3728 port_reset_reg = XLPORT_SOFT_RESETr; 3729 } 3730 3731 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3732 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, port_reset_reg, port, 0, &rval)); 3733 orig_rval = rval; 3734 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 3735 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 3736 if (SOC_BLOCK_INFO(unit, block).type == port_blk) { 3737 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 3738 soc_reg_field_set(unit, port_reset_reg, &rval, 3739 fields[bindex], 1); 3740 break; 3741 } 3742 } 3743 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, port_reset_reg, port, 0, rval)); 3744 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, port_reset_reg, port, 0, orig_rval)); 3745 } 3746 break; 3747 case SOC_CHIP_BCM56260: 3748 case SOC_CHIP_BCM56270: 3749 if (SOC_REG_PORT_VALID(unit, XLPORT_SOFT_RESETr, port)) { 3750 bindex = ( port - 1 ) % 4; 3751 SOC_IF_ERROR_RETURN(READ_XLPORT_SOFT_RESETr(unit, port, &rval)); 3752 orig_rval = rval; 3753 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, 3754 fields[bindex], 1); 3755 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval)); 3756 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, orig_rval)); 3757 } 3758 break; 3759 default: 3760 break; 3761 } 3762 3763 return SOC_E_NONE; 3764 } 3765 3766 int 3767 soc_port_blk_init(int unit, soc_port_t port) 3768 { switch (SOC_CHIP_GROUP(unit)) { 3769 #if defined(BCM_RAVEN_SUPPORT) 3770 case SOC_CHIP_BCM56224: 3771 if (IS_S_PORT(unit, port)) { 3772 soc_pbmp_t pbmp_s0, pbmp_s1, pbmp_s3, pbmp_s4; 3773 uint32 val32; 3774 int higig_mode; 3775 3776 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &val32)); 3777 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, CLR_CNTf, 1); 3778 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, GPORT_ENf, 1); 3779 SOC_PBMP_WORD_SET(pbmp_s0, 0, 0x00000002); 3780 SOC_PBMP_WORD_SET(pbmp_s1, 0, 0x00000004); 3781 SOC_PBMP_WORD_SET(pbmp_s3, 0, 0x00000010); 3782 SOC_PBMP_WORD_SET(pbmp_s4, 0, 0x00000020); 3783 3784 higig_mode = IS_ST_PORT(unit, port) ? 1 : 0; 3785 if (SOC_PBMP_MEMBER(pbmp_s0, port)) { 3786 /* The "SOP check enables" are not gated with "HiGig2 enables" 3787 * and "bond_disable_stacking". 3788 * Thus software need to enable/disable the SOP drop check 3789 * in HiGig2 mode as desired. 3790 */ 3791 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3792 DROP_ON_WRONG_SOP_EN_S0f, 0); 3793 /* Enable HiGig 2 */ 3794 /* Assuming that always use stacking port in HiGig mode */ 3795 /* Actually, stacking port can also be used in ethernet mode */ 3796 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3797 HGIG2_EN_S0f, higig_mode); 3798 } else if (SOC_PBMP_MEMBER(pbmp_s1, port)) { 3799 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3800 DROP_ON_WRONG_SOP_EN_S1f, 0); 3801 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3802 HGIG2_EN_S1f, higig_mode); 3803 } else if (SOC_PBMP_MEMBER(pbmp_s3, port)) { 3804 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3805 DROP_ON_WRONG_SOP_EN_S3f, 0); 3806 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3807 HGIG2_EN_S3f, higig_mode); 3808 } else if (SOC_PBMP_MEMBER(pbmp_s4, port)) { 3809 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3810 DROP_ON_WRONG_SOP_EN_S4f, 0); 3811 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 3812 HGIG2_EN_S4f, higig_mode); 3813 } 3814 3815 SOC_IF_ERROR_RETURN 3816 (WRITE_GPORT_CONFIGr(unit, port, val32)); 3817 3818 /* Reset the clear-count bit after 64 clocks */ 3819 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, CLR_CNTf, 0); 3820 SOC_IF_ERROR_RETURN 3821 (WRITE_GPORT_CONFIGr(unit, port, val32)); 3822 } 3823 break; 3824 #endif /* BCM_RAVEN_SUPPORT */ 3825 default: 3826 return SOC_E_NONE; 3827 } 3828 return SOC_E_NONE; 3829 } 3830 3831 int 3832 soc_packet_purge_control_init(int unit, soc_port_t port) 3833 { 3834 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT) 3835 uint32 mask; 3836 mask = soc_property_port_get(unit, port, spn_GPORT_RSV_MASK, 0x070); 3837 #endif 3838 switch (SOC_CHIP_GROUP(unit)) { 3839 #if defined(BCM_RAVEN_SUPPORT) 3840 case SOC_CHIP_BCM56224: 3841 case SOC_CHIP_BCM53314: 3842 /* GPORT_RSV_MASK fields 3843 * bit 3844 * 0 frm_align_err_latch 3845 * 1 rx_frm_stack_vlan_latch 3846 * 2 rx_carrier_event_latch 3847 * 3 rx_frm_gmii_err_latch 3848 * 4 (frm_crc_err_latch | frm_crc_err) 3849 * 5 frm_length_err_latch & ~frm_truncate_latch 3850 * 6 frm_truncate_latch 3851 * 7 ~rx_frm_err_latch & ~frm_truncate_latch 3852 * 8 rx_frm_mltcast_latch 3853 * 9 rx_frm_broadcast_latch 3854 * 10 drbl_nbl_latch 3855 * 11 cmd_rcv_latch 3856 * 12 pause_rcv_latch 3857 * 13 rx_cmd_op_err_latch 3858 * 14 rx_frm_vlan_latch 3859 * 15 rx_frm_unicast_latch 3860 * 16 frm_truncate_latch 3861 */ 3862 SOC_IF_ERROR_RETURN 3863 (WRITE_GPORT_RSV_MASKr(unit, port, mask)); 3864 SOC_IF_ERROR_RETURN 3865 (WRITE_GPORT_STAT_UPDATE_MASKr(unit, port, mask)); 3866 break; 3867 #endif /* BCM_RAVEN_SUPPORT */ 3868 #ifdef BCM_TRX_SUPPORT 3869 case SOC_CHIP_BCM56624: 3870 case SOC_CHIP_BCM56680: 3871 case SOC_CHIP_BCM56634: 3872 case SOC_CHIP_BCM56524: 3873 case SOC_CHIP_BCM56685: 3874 case SOC_CHIP_BCM56820: 3875 case SOC_CHIP_BCM56725: 3876 SOC_IF_ERROR_RETURN 3877 (WRITE_GPORT_RSV_MASKr(unit, port, mask)); 3878 SOC_IF_ERROR_RETURN 3879 (WRITE_GPORT_STAT_UPDATE_MASKr(unit, port, mask)); 3880 break; 3881 case SOC_CHIP_BCM56334: 3882 case SOC_CHIP_BCM56142: 3883 case SOC_CHIP_BCM56150: 3884 case SOC_CHIP_BCM53400: 3885 case SOC_CHIP_BCM56160: 3886 case SOC_CHIP_BCM53570: 3887 case SOC_CHIP_BCM53540: 3888 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port) || 3889 IS_XQ_PORT(unit, port)) { 3890 SOC_IF_ERROR_RETURN 3891 (WRITE_QPORT_RSV_MASKr(unit, port, mask)); 3892 SOC_IF_ERROR_RETURN 3893 (WRITE_QPORT_STAT_UPDATE_MASKr(unit, port, mask)); 3894 } else { 3895 SOC_IF_ERROR_RETURN 3896 (WRITE_GPORT_RSV_MASKr(unit, port, mask)); 3897 SOC_IF_ERROR_RETURN 3898 (WRITE_GPORT_STAT_UPDATE_MASKr(unit, port, mask)); 3899 } 3900 break; 3901 #endif 3902 default: 3903 return SOC_E_NONE; 3904 } 3905 3906 return SOC_E_NONE; 3907 } 3908 3909 int 3910 soc_egress_enable(int unit, soc_port_t port, int enable) 3911 { 3912 #ifdef BCM_SHADOW_SUPPORT 3913 soc_info_t *si; 3914 #endif 3915 3916 #ifdef BCM_SHADOW_SUPPORT 3917 si = &SOC_INFO(unit); 3918 #endif 3919 3920 switch (SOC_CHIP_GROUP(unit)) { 3921 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 3922 case SOC_CHIP_BCM56820: 3923 case SOC_CHIP_BCM56224: 3924 case SOC_CHIP_BCM53314: 3925 case SOC_CHIP_BCM88732: 3926 { 3927 uint32 val32; 3928 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEr(unit, port, &val32)); 3929 #ifdef BCM_SHADOW_SUPPORT 3930 if (!SOC_PBMP_MEMBER(si->port.disabled_bitmap, port)) { 3931 soc_reg_field_set(unit, EGR_ENABLEr, &val32, PRT_ENABLEf, 1); 3932 } 3933 #else 3934 soc_reg_field_set(unit, EGR_ENABLEr, &val32, PRT_ENABLEf, 1); 3935 #endif 3936 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, val32)); 3937 break; 3938 } 3939 #endif /* BCM_RAVEN_SUPPORT || BCM_SCORPION_SUPPORT */ 3940 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 3941 case SOC_CHIP_BCM56860: 3942 { 3943 int phy_port; 3944 uint32 entry; 3945 3946 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3947 SOC_IF_ERROR_RETURN 3948 (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3949 soc_mem_field32_set(unit, EGR_ENABLEm, &entry, PRT_ENABLEf, enable); 3950 SOC_IF_ERROR_RETURN 3951 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, &entry)); 3952 break; 3953 } 3954 #endif 3955 default: 3956 return SOC_E_NONE; 3957 } 3958 return SOC_E_NONE; 3959 } 3960 3961 int 3962 soc_port_speed_update(int unit, soc_port_t port, int speed) 3963 { 3964 switch (SOC_CHIP_GROUP(unit)) { 3965 case SOC_CHIP_BCM56850: 3966 case SOC_CHIP_BCM56860: 3967 #ifdef BCM_TRIDENT2_SUPPORT 3968 SOC_IF_ERROR_RETURN(soc_trident2_port_speed_update(unit, port, speed)); 3969 #endif /* BCM_TRIDENT2_SUPPORT */ 3970 break; 3971 case SOC_CHIP_BCM56960: 3972 case SOC_CHIP_BCM56965: 3973 #ifdef BCM_TOMAHAWK_SUPPORT 3974 SOC_IF_ERROR_RETURN(soc_tomahawk_port_speed_update(unit, port, speed)); 3975 #endif /* BCM_TOMAHAWK_SUPPORT */ 3976 break; 3977 case SOC_CHIP_BCM56560: 3978 #ifdef BCM_APACHE_SUPPORT 3979 SOC_IF_ERROR_RETURN(soc_apache_port_speed_update(unit, port, speed)); 3980 #endif /* BCM_APACHE_SUPPORT */ 3981 break; 3982 case SOC_CHIP_BCM56670: 3983 #ifdef BCM_MONTEREY_SUPPORT 3984 SOC_IF_ERROR_RETURN(soc_monterey_port_speed_update(unit, port, speed)); 3985 #endif /* BCM_MONTEREY_SUPPORT */ 3986 break; 3987 case SOC_CHIP_BCM56870: 3988 #ifdef BCM_TRIDENT3_SUPPORT 3989 SOC_IF_ERROR_RETURN(soc_trident3_port_speed_update(unit, port, speed)); 3990 #endif /* BCM_TRIDENT3_SUPPORT */ 3991 break; 3992 case SOC_CHIP_BCM53570: 3993 #ifdef BCM_GREYHOUND2_SUPPORT 3994 SOC_IF_ERROR_RETURN( 3995 soc_greyhound2_port_speed_update(unit, port, speed)); 3996 #endif /* BCM_GREYHOUND2_SUPPORT */ 3997 break; 3998 default: 3999 break; 4000 } 4001 4002 return SOC_E_NONE; 4003 4004 } 4005 4006 int 4007 soc_port_hg_speed_get(int unit, soc_port_t port, int *speed) 4008 { 4009 switch (SOC_CHIP_GROUP(unit)) { 4010 case SOC_CHIP_BCM56960: 4011 case SOC_CHIP_BCM56965: 4012 #ifdef BCM_TOMAHAWK_SUPPORT 4013 SOC_IF_ERROR_RETURN(soc_th_port_hg_speed_get(unit, port, speed)); 4014 #endif /* BCM_TOMAHAWK_SUPPORT */ 4015 break; 4016 #ifdef BCM_GREYHOUND2_SUPPORT 4017 case SOC_CHIP_BCM53570: 4018 SOC_IF_ERROR_RETURN(soc_greyhound2_port_hg_speed_get(unit, port, speed)); 4019 break; 4020 #endif /* BCM_GREYHOUND2_SUPPORT */ 4021 #ifdef BCM_GREYHOUND_SUPPORT 4022 case SOC_CHIP_BCM53400: 4023 SOC_IF_ERROR_RETURN(soc_greyhound_port_hg_speed_get(unit, port, speed)); 4024 break; 4025 #endif /* BCM_GREYHOUND_SUPPORT */ 4026 default: 4027 break; 4028 } 4029 4030 return SOC_E_NONE; 4031 } 4032 4033 int 4034 soc_port_thdo_rx_enable_set(int unit, soc_port_t port, int enable) 4035 { 4036 switch (SOC_CHIP_GROUP(unit)) { 4037 case SOC_CHIP_BCM56850: 4038 case SOC_CHIP_BCM56860: 4039 #ifdef BCM_TRIDENT2_SUPPORT 4040 SOC_IF_ERROR_RETURN 4041 (soc_trident2_port_thdo_rx_enable_set(unit, port, enable)); 4042 #endif 4043 break; 4044 case SOC_CHIP_BCM56560: 4045 #ifdef BCM_APACHE_SUPPORT 4046 SOC_IF_ERROR_RETURN(soc_apache_port_thdo_rx_enable_set(unit, 4047 port, enable)); 4048 #endif 4049 break; 4050 case SOC_CHIP_BCM56670: 4051 #ifdef BCM_MONTEREY_SUPPORT 4052 SOC_IF_ERROR_RETURN(soc_monterey_port_thdo_rx_enable_set(unit, 4053 port, enable)); 4054 #endif 4055 break; 4056 default: 4057 break; 4058 } 4059 4060 return SOC_E_NONE; 4061 4062 } 4063 4064 #endif /* defined(BCM_ESW_SUPPORT) */ 4065 4066 int 4067 soc_llfc_xon_set(int unit, soc_port_t port, int enable) 4068 { 4069 if (enable) { 4070 /* no action required */ 4071 } else { 4072 #if defined(BCM_ESW_SUPPORT) 4073 if (soc_feature(unit, soc_feature_llfc_force_xon)) { 4074 SOC_IF_ERROR_RETURN(soc_mmu_backpressure_clear(unit, port)); 4075 } 4076 #endif /* defined(BCM_ESW_SUPPORT) */ 4077 } 4078 4079 return SOC_E_NONE; 4080 } 4081 4082 /* function to setup EEE Wake/LPI timers per speed */ 4083 int 4084 soc_port_eee_timers_setup(int unit, soc_port_t port, int speed) 4085 { 4086 switch (SOC_CHIP_GROUP(unit)) { 4087 #ifdef BCM_GREYHOUND_SUPPORT 4088 case SOC_CHIP_BCM53400: 4089 SOC_IF_ERROR_RETURN(soc_gh_port_eee_timers_setup(unit, port, speed)); 4090 break; 4091 #endif /* BCM_GREYHOUND_SUPPORT */ 4092 default : 4093 break; 4094 } 4095 return SOC_E_NONE; 4096 } 4097 4098 /* function to provide the ways to assigning EEE timers during MAC init. 4099 * 4100 * Note : 4101 * 1. MAC has it own EEE timer default value but these setting for some 4102 * specific chip might not proper for EEE operation. 4103 * 2. Once EEE timers at reset value=0 on a MAC, Packet lost will happen. 4104 */ 4105 int 4106 soc_port_eee_timers_init(int unit, soc_port_t port, int speed) 4107 { 4108 if (!soc_feature(unit, soc_feature_eee)) { 4109 return SOC_E_NONE; 4110 } 4111 4112 switch (SOC_CHIP_GROUP(unit)) { 4113 #ifdef BCM_GREYHOUND_SUPPORT 4114 case SOC_CHIP_BCM53400: 4115 SOC_IF_ERROR_RETURN(soc_gh_port_eee_ref_count_init(unit, port)); 4116 SOC_IF_ERROR_RETURN(soc_gh_port_eee_timers_setup(unit, port, speed)); 4117 break; 4118 #endif /* BCM_GREYHOUND_SUPPORT */ 4119 default : 4120 break; 4121 } 4122 return SOC_E_NONE; 4123 } 4124 4125 /* 4126 * Function: 4127 * soc_granular_speed_get 4128 * Purpose: 4129 * Map MMU_CELL_CREDIT to port speed 4130 * Parameters: 4131 * unit - (IN) unit number 4132 * port - (IN) port number 4133 * speed - (OUT) speed in Mbps 4134 * Returns: 4135 * N/A 4136 */ 4137 soc_error_t 4138 soc_granular_speed_get(int unit, soc_port_t port, int *speed) 4139 { 4140 soc_error_t rc; 4141 4142 switch (SOC_CHIP_GROUP(unit)) { 4143 #if defined (BCM_TRIDENT3_SUPPORT) 4144 case SOC_CHIP_BCM56870: 4145 rc = soc_td3_granular_speed_get(unit, port, speed); 4146 break; 4147 #endif 4148 #if defined (BCM_TOMAHAWK_SUPPORT) 4149 case SOC_CHIP_BCM56960: 4150 case SOC_CHIP_BCM56965: 4151 case SOC_CHIP_BCM56970: 4152 rc = soc_th_granular_speed_get(unit, port, speed); 4153 break; 4154 #endif 4155 #if defined (BCM_GREYHOUND2_SUPPORT) 4156 case SOC_CHIP_BCM53570: 4157 rc = soc_greyhound2_granular_speed_get(unit, port, speed); 4158 break; 4159 #endif /* BCM_GREYHOUND2_SUPPORT */ 4160 default: 4161 rc = SOC_E_PARAM; 4162 break; 4163 } 4164 return rc; 4165 } 4166 4167 /* 4168 * Function: 4169 * soc_mac_x_sync_fifo_reset 4170 * Purpose: 4171 * Reset a XMAC loopback syc fifo 4172 * Parameters: 4173 * unit - XGS unit #. 4174 * port - XGS unit # on unit. 4175 * Returns: 4176 * SOC_E_XXX 4177 */ 4178 int 4179 soc_mac_x_sync_fifo_reset(int unit, soc_port_t port) 4180 { 4181 #if defined(BCM_TRIUMPH3_SUPPORT) 4182 if (SOC_IS_TRIUMPH3(unit) && SOC_INFO(unit).port_num_lanes[port] == 4) { 4183 static const soc_field_t line_lb_field[] = { 4184 XMAC0_LINE_LPBK_RESETf, 4185 XMAC1_LINE_LPBK_RESETf, 4186 XMAC2_LINE_LPBK_RESETf 4187 }; 4188 int phy_port, bindex = -1; 4189 uint32 rval; 4190 4191 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 4192 if (phy_port != -1) { 4193 bindex = SOC_PORT_BINDEX(unit, phy_port) / 4; 4194 if (bindex != -1) { 4195 SOC_IF_ERROR_RETURN(READ_PORT_MAC_CONTROLr(unit, port, &rval)); 4196 soc_reg_field_set(unit, PORT_MAC_CONTROLr, &rval, 4197 line_lb_field[bindex], 1); 4198 SOC_IF_ERROR_RETURN(WRITE_PORT_MAC_CONTROLr(unit, port, rval)); 4199 sal_udelay(10); 4200 soc_reg_field_set(unit, PORT_MAC_CONTROLr, &rval, 4201 line_lb_field[bindex], 0); 4202 SOC_IF_ERROR_RETURN(WRITE_PORT_MAC_CONTROLr(unit, port, rval)); 4203 } 4204 } 4205 } 4206 #endif /* BCM_TRIUMPH3_SUPPORT */ 4207 return SOC_E_NONE; 4208 } 4209 4210 /* 4211 * Function: 4212 * soc_pgw_ge_rx_fifo_reset 4213 * Purpose: 4214 * Reset PGW Rx FIFO to prevent packets entering switch 4215 * Parameters: 4216 * unit - XGS unit #. 4217 * port - XGS unit # on unit. 4218 * reset - TRUE/FALSE 4219 * Returns: 4220 * SOC_E_XXX 4221 */ 4222 int soc_pgw_rx_fifo_reset(int unit, int port, int reset) 4223 { 4224 if (!soc_feature(unit, soc_feature_unimac_reset_wo_clock)) { 4225 return SOC_E_UNAVAIL; 4226 } 4227 4228 switch (SOC_CHIP_GROUP(unit)) { 4229 #ifdef BCM_HURRICANE3_SUPPORT 4230 case SOC_CHIP_BCM56160: 4231 case SOC_CHIP_BCM53540: 4232 SOC_IF_ERROR_RETURN 4233 (soc_hurricane3_pgw_rx_fifo_reset(unit, port, reset)); 4234 break; 4235 #endif /* BCM_HURRICANE3_SUPPORT */ 4236 default : 4237 break; 4238 } 4239 4240 return SOC_E_NONE; 4241 } 4242 4243 /* 4244 * Function: 4245 * soc_port_mmu_buffer_enable 4246 * Purpose: 4247 * MMU memory buffer enable configuration to specify which 4248 * egress ports are allowed to buffer packets. 4249 * Parameters: 4250 * unit - XGS unit #. 4251 * port - XGS unit # on unit. 4252 * enable - TRUE/FALSE 4253 * Returns: 4254 * SOC_E_XXX 4255 */ 4256 int 4257 soc_port_mmu_buffer_enable(int unit, int port, int enable) 4258 { 4259 switch (SOC_CHIP_GROUP(unit)) { 4260 #if defined (BCM_HURRICANE2_SUPPORT) 4261 case SOC_CHIP_BCM56150: 4262 case SOC_CHIP_BCM53400: 4263 case SOC_CHIP_BCM56160: 4264 { 4265 uint32 val, pbmp; 4266 pbmp_t mmu_pbmp; 4267 4268 SOC_PBMP_CLEAR(mmu_pbmp); 4269 SOC_IF_ERROR_RETURN(READ_MMUPORTENABLEr(unit, &val)); 4270 pbmp = soc_reg_field_get(unit, MMUPORTENABLEr, val, MMUPORTENABLEf); 4271 SOC_PBMP_WORD_SET(mmu_pbmp, 0, pbmp); 4272 if (enable) { 4273 SOC_PBMP_PORT_ADD(mmu_pbmp, port); 4274 } else { 4275 SOC_PBMP_PORT_REMOVE(mmu_pbmp, port); 4276 } 4277 soc_reg_field_set(unit, MMUPORTENABLEr, &val, MMUPORTENABLEf, 4278 SOC_PBMP_WORD_GET(mmu_pbmp, 0)); 4279 SOC_IF_ERROR_RETURN(WRITE_MMUPORTENABLEr(unit, val)); 4280 break; 4281 } 4282 #endif /* BCM_HURRICANE2_SUPPORT */ 4283 #if defined (BCM_GREYHOUND2_SUPPORT) 4284 case SOC_CHIP_BCM53570: 4285 { 4286 soc_info_t *si = &SOC_INFO(unit); 4287 pbmp_t mmu_pbmp; 4288 uint32 val, pbmp; 4289 int phy_port, mmu_port, word; 4290 static const soc_reg_t mmu_reg[] = {MMUPORTENABLE_0r, 4291 MMUPORTENABLE_1r, 4292 MMUPORTENABLE_2r}; 4293 4294 SOC_PBMP_CLEAR(mmu_pbmp); 4295 phy_port = si->port_l2p_mapping[port]; 4296 mmu_port = si->port_p2m_mapping[phy_port]; 4297 word = mmu_port / 32; 4298 SOC_IF_ERROR_RETURN( 4299 soc_reg32_get(unit, mmu_reg[word], REG_PORT_ANY, 0, &val)); 4300 pbmp = soc_reg_field_get(unit, mmu_reg[word], val, MMUPORTENABLEf); 4301 SOC_PBMP_WORD_SET(mmu_pbmp, word, pbmp); 4302 if (enable) { 4303 SOC_PBMP_PORT_ADD(mmu_pbmp, mmu_port); 4304 } else { 4305 SOC_PBMP_PORT_REMOVE(mmu_pbmp, mmu_port); 4306 } 4307 soc_reg_field_set(unit, mmu_reg[word], &val, MMUPORTENABLEf, 4308 SOC_PBMP_WORD_GET(mmu_pbmp, word)); 4309 SOC_IF_ERROR_RETURN( 4310 soc_reg32_set(unit, mmu_reg[word], REG_PORT_ANY, 0, val)); 4311 break; 4312 } 4313 #endif /* BCM_GREYHOUND2_SUPPORT */ 4314 default: 4315 break; 4316 } 4317 return SOC_E_NONE; 4318 }