bst.c (150054B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * BST - Buffer Statistics Tracking 7 * Purpose: API to set and manage various BST resources for TH3 8 */ 9 10 #include <shared/bsl.h> 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 #include <sal/core/boot.h> 16 17 #include <soc/drv.h> 18 #include <soc/error.h> 19 #include <soc/ll.h> 20 #include <soc/debug.h> 21 #include <soc/mem.h> 22 #include <soc/profile_mem.h> 23 #include <soc/tomahawk3.h> 24 #include <soc/pfc.h> 25 26 #include <bcm/switch.h> 27 #include <bcm/types.h> 28 #include <bcm/cosq.h> 29 #include <bcm_int/bst.h> 30 #include <bcm_int/esw/port.h> 31 #include <bcm_int/esw/tomahawk3.h> 32 #include <bcm_int/esw/pfc.h> 33 #if defined(BCM_TOMAHAWK3_SUPPORT) 34 35 #define _TH3_BST_THRESHOLD_CELL_MAX 0x3ffff 36 #define _TH3_BST_PROFILE_INIT_FLAG 2 37 #define _TH3_BST_QUEUE_TYPE_SHIFT 16 38 #define _TH3_BST_QUEUE_TYPE_SHIFT_MASK 0xffff 39 #define _BCM_TH3_BST_Q_TYPE_UC 0 40 #define _BCM_TH3_BST_Q_TYPE_MC 1 41 #define _BCM_TH3_BST_Q_TYPE_CPU 2 42 #define _BCM_TH3_BST_Q_TYPE_COUNT 3 43 44 typedef enum _bcm_th3_bst_config_e { 45 _bcm_th3_bst_config_tracking_mode = 0, 46 _bcm_th3_bst_config_snapshot = 1 47 } _bcm_th3_bst_config_t; 48 49 typedef enum _bcm_th3_bst_module_e { 50 _BCM_TH3_BST_MODULE_THDO = 0, 51 _BCM_TH3_BST_MODULE_THDI = 1, 52 _BCM_TH3_BST_MODULE_CFAP = 2, 53 _BCM_TH3_BST_MODULE_THDR = 3, 54 _BCM_TH3_BST_MODULE_COUNT =4 55 } _bcm_th3_bst_module_t; 56 57 typedef struct _bcm_th3_bst_resource_info_s { 58 bcm_bst_stat_id_t stat_id; 59 soc_reg_t stat_reg; 60 soc_mem_t stat_mem; 61 soc_field_t stat_field; 62 soc_reg_t thd_reg; 63 soc_mem_t thd_mem; 64 soc_field_t thd_field; 65 int idx_count; 66 int stat_count; 67 int thd_count; 68 } _bcm_th3_bst_resource_info_t; 69 70 extern int _bcm_bst_th3_sync_hw_snapshot(int unit, bcm_bst_stat_id_t bid, 71 int port, int index); 72 73 const static 74 soc_field_t sp_fields[] = {PORTSP0_SHARED_COUNTf, PORTSP1_SHARED_COUNTf, 75 PORTSP2_SHARED_COUNTf, PORTSP3_SHARED_COUNTf}; 76 const static 77 soc_field_t sp_sel_fields[] = {PORTSP0_BST_SHARED_PROFILE_SELf, 78 PORTSP1_BST_SHARED_PROFILE_SELf, 79 PORTSP2_BST_SHARED_PROFILE_SELf, 80 PORTSP3_BST_SHARED_PROFILE_SELf}; 81 82 const static 83 soc_field_t pg_fields[] = {PG0_SHARED_COUNTf, PG1_SHARED_COUNTf, 84 PG2_SHARED_COUNTf, PG3_SHARED_COUNTf, 85 PG4_SHARED_COUNTf, PG5_SHARED_COUNTf, 86 PG6_SHARED_COUNTf, PG7_SHARED_COUNTf}; 87 88 const static 89 soc_field_t pg_sel_fields[] = {PG0_BST_SHARED_PROFILE_SELf, 90 PG1_BST_SHARED_PROFILE_SELf, 91 PG2_BST_SHARED_PROFILE_SELf, 92 PG3_BST_SHARED_PROFILE_SELf, 93 PG4_BST_SHARED_PROFILE_SELf, 94 PG5_BST_SHARED_PROFILE_SELf, 95 PG6_BST_SHARED_PROFILE_SELf, 96 PG7_BST_SHARED_PROFILE_SELf}; 97 98 const static 99 soc_field_t pg_hdrm_fields[] = {PG0_BST_STAT_HDRMf, PG1_BST_STAT_HDRMf, 100 PG2_BST_STAT_HDRMf, PG3_BST_STAT_HDRMf, 101 PG4_BST_STAT_HDRMf, PG5_BST_STAT_HDRMf, 102 PG6_BST_STAT_HDRMf, PG7_BST_STAT_HDRMf}; 103 104 const static 105 soc_field_t pg_hdrm_sel_fields[] = {PG0_BST_HDRM_PROFILE_SELf, 106 PG1_BST_HDRM_PROFILE_SELf, 107 PG2_BST_HDRM_PROFILE_SELf, 108 PG3_BST_HDRM_PROFILE_SELf, 109 PG4_BST_HDRM_PROFILE_SELf, 110 PG5_BST_HDRM_PROFILE_SELf, 111 PG6_BST_HDRM_PROFILE_SELf, 112 PG7_BST_HDRM_PROFILE_SELf}; 113 114 const static 115 soc_field_t uc_portsp_fields[] = {SP0_BST_PORT_SHARED_COUNTf, 116 SP1_BST_PORT_SHARED_COUNTf, 117 SP2_BST_PORT_SHARED_COUNTf, 118 SP3_BST_PORT_SHARED_COUNTf}; 119 const static 120 soc_field_t uc_portsp_sel_fields[] = {BST_PORTSP0_WM_SHARED_THRESHOLD_SELf, 121 BST_PORTSP1_WM_SHARED_THRESHOLD_SELf, 122 BST_PORTSP2_WM_SHARED_THRESHOLD_SELf, 123 BST_PORTSP3_WM_SHARED_THRESHOLD_SELf}; 124 125 STATIC int _bcm_bst_th3_sbusdma_desc_sync(int unit); 126 STATIC int _bcm_bst_th3_sbusdma_desc_init(int unit); 127 STATIC int _bcm_bst_th3_sbusdma_desc_deinit(int unit); 128 129 130 STATIC int 131 _bcm_bst_th3_byte_to_cell(int unit, uint32 bytes) 132 { 133 return (bytes + (_TH3_MMU_BYTES_PER_CELL - 1))/_TH3_MMU_BYTES_PER_CELL; 134 } 135 136 STATIC int 137 _bcm_bst_th3_cell_to_byte(int unit, uint32 cells) 138 { 139 return cells * _TH3_MMU_BYTES_PER_CELL; 140 } 141 142 STATIC uint32 143 _bcm_bst_th3_profile_reg_id_get(int unit, bcm_bst_stat_id_t bid, int index) { 144 if(bcmBstStatIdQueueTotal == bid) { 145 return (index >> _TH3_BST_QUEUE_TYPE_SHIFT); 146 } 147 return 0; 148 } 149 150 STATIC int 151 _bcm_th3_bst_bid_gport_cosq_param_check(int unit, bcm_bst_stat_id_t bid, 152 bcm_gport_t gport, bcm_cos_queue_t cosq) { 153 soc_info_t *si = &SOC_INFO(unit); 154 int port_num_ucq, port; 155 156 if (bid == bcmBstStatIdDevice) { 157 /*port,queue based param checks invalid for Device*/ 158 return BCM_E_NONE; 159 } 160 if ((bid == bcmBstStatIdHeadroomPool) || 161 (bid == bcmBstStatIdIngPool) || 162 (bid == bcmBstStatIdPortPool) || 163 (bid == bcmBstStatIdPriGroupShared) || 164 (bid == bcmBstStatIdPriGroupHeadroom)) { 165 if (cosq >= _TH3_MMU_NUM_PG) { 166 return BCM_E_PARAM; 167 } 168 } 169 170 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 171 /* Passed cosq is multicast. Cannot be used for unicast Bids */ 172 if ((bid == bcmBstStatIdUcast) || 173 (bid == bcmBstStatIdEgrPool) || 174 (bid == bcmBstStatIdEgrPortPoolSharedUcast)) { 175 return BCM_E_PARAM; 176 } 177 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 178 /* Passed cosq is unicast. Cannot be used for multicast Bids */ 179 if ((bid == bcmBstStatIdMcast) || 180 (bid == bcmBstStatIdEgrMCastPool) || 181 (bid == bcmBstStatIdEgrPortPoolSharedMcast)) { 182 return BCM_E_PARAM; 183 } 184 } else { 185 if (gport == -1) { 186 return BCM_E_NONE; 187 } 188 /* GPORT is of local port type */ 189 BCM_IF_ERROR_RETURN( 190 _bcm_th3_cosq_localport_resolve(unit, gport, &port)); 191 if (cosq < BCM_COS_INVALID) { 192 return BCM_E_PARAM; 193 } 194 if (cosq == BCM_COS_INVALID) { 195 return BCM_E_NONE; 196 } 197 if (IS_CPU_PORT(unit, port)) { 198 port_num_ucq = 0; 199 if (cosq >= SOC_TH3_NUM_CPU_QUEUES) { 200 return BCM_E_PARAM; 201 } 202 } else { 203 port_num_ucq = si->port_num_uc_cosq[port]; 204 if (cosq >= SOC_TH3_NUM_GP_QUEUES) { 205 return BCM_E_PARAM; 206 } 207 } 208 if (cosq < port_num_ucq) { 209 /* Passed cosq is unicast. Cannot be used for multicast Bids */ 210 if ((bid == bcmBstStatIdMcast) || 211 (bid == bcmBstStatIdEgrMCastPool) || 212 (bid == bcmBstStatIdEgrPortPoolSharedMcast)) { 213 return BCM_E_PARAM; 214 } 215 } else { 216 /* Passed cosq is multicast. Cannot be used for unicast Bids */ 217 if ((bid == bcmBstStatIdUcast) || 218 (bid == bcmBstStatIdEgrPool) || 219 (bid == bcmBstStatIdEgrPortPoolSharedUcast)) { 220 return BCM_E_PARAM; 221 } 222 } 223 } 224 return BCM_E_NONE; 225 } 226 227 STATIC int _bcm_bst_field_ids_retrieve(int unit, bcm_bst_stat_id_t bid, 228 bcm_gport_t gport, bcm_cos_queue_t cosq, int *field_idx, int *num_fields) { 229 230 int idx, pool, local_port; 231 232 if ((field_idx == NULL) || (num_fields == NULL)) { 233 return BCM_E_PARAM; 234 } 235 BCM_IF_ERROR_RETURN( 236 _bcm_th3_cosq_localport_resolve(unit, gport, &local_port)); 237 switch (bid) { 238 case bcmBstStatIdPortPool: 239 if(cosq == BCM_COS_INVALID) { 240 *num_fields = _TH3_MMU_NUM_POOL; 241 for (idx = 0; idx < _TH3_MMU_NUM_POOL; idx ++) { 242 field_idx[idx] = idx; 243 } 244 } else { 245 BCM_IF_ERROR_RETURN( 246 _bcm_th3_cosq_ingress_sp_get_by_pg(unit, local_port, 247 cosq, &pool)); 248 field_idx[0] = pool; 249 *num_fields = 1; 250 } 251 break; 252 case bcmBstStatIdPriGroupShared: 253 case bcmBstStatIdPriGroupHeadroom: 254 if(cosq == BCM_COS_INVALID) { 255 *num_fields = _TH3_MMU_NUM_PG; 256 for (idx = 0; idx < _TH3_MMU_NUM_PG; idx ++) { 257 field_idx[idx] = idx; 258 } 259 } else { 260 field_idx[0] = cosq; 261 *num_fields = 1; 262 } 263 break; 264 case bcmBstStatIdEgrPortPoolSharedUcast: 265 if(cosq == BCM_COS_INVALID) { 266 *num_fields = _TH3_MMU_NUM_POOL; 267 for (idx = 0; idx < _TH3_MMU_NUM_POOL; idx ++) { 268 field_idx[idx] = idx; 269 } 270 } else { 271 BCM_IF_ERROR_RETURN( 272 _bcm_th3_cosq_egress_sp_get (unit, gport, cosq, &pool, NULL)); 273 field_idx[0] = pool; 274 *num_fields = 1; 275 } 276 break; 277 default: 278 return BCM_E_PARAM; 279 } 280 return BCM_E_NONE; 281 } 282 283 /* 284 * Function: 285 * _bcm_th3_bst_tracking_enable_set 286 * Purpose: 287 * Enable/Disable BST tracking. 288 * Parameters: 289 * unit - (IN) unit number 290 * arg - (IN) enable/disable config 291 * operation - (IN) operation type 292 * Returns: 293 * BCM_E_XXX 294 */ 295 296 STATIC int 297 _bcm_th3_bst_tracking_enable_set(int unit, int arg, 298 _bcm_bst_thread_oper_t operation) 299 { 300 #define _BCM_BST_TH3_GLB_TRACKING_EN 0xff 301 302 soc_reg_t reg; 303 uint32 rval; 304 _bcm_bst_cmn_unit_info_t *bst_info; 305 reg = MMU_GLBCFG_BST_TRACKING_ENABLEr; 306 307 bst_info = _BCM_UNIT_BST_INFO(unit); 308 if (!bst_info) { 309 return BCM_E_INIT; 310 } 311 312 rval = arg ? _BCM_BST_TH3_GLB_TRACKING_EN : 0; 313 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, REG_PORT_ANY, rval)); 314 315 if (operation == _bcmBstThreadOperExternal) { 316 bst_info->bst_tracking_enable = arg; 317 if (arg) { 318 BCM_IF_ERROR_RETURN(_bcm_bst_sync_thread_start(unit)); 319 } else { 320 BCM_IF_ERROR_RETURN(_bcm_bst_sync_thread_stop(unit)); 321 } 322 } else { 323 /* Set Enable Flag to True/False, to Run/Pause the Thread 324 * respectively. Wont Kill the thread. 325 */ 326 _BCM_BST_SYNC_THREAD_ENABLE_SET(unit, arg ? TRUE : FALSE); 327 } 328 #undef _BCM_BST_TH3_GLB_TRACKING_EN 329 return BCM_E_NONE; 330 } 331 332 /* 333 * Function: 334 * _bcm_th3_bst_config_set 335 * Purpose: 336 * Set BST config for different modules. 337 * Parameters: 338 * unit - (IN) unit number 339 * arg - (IN) tracking mode config 340 * bit[0]:THDO, bit[1]: THDI, bit[2]: CFAP 341 * type - (IN) bst config type 342 * Returns: 343 * BCM_E_XXX 344 */ 345 STATIC int 346 _bcm_th3_bst_config_set(int unit, int arg, _bcm_th3_bst_config_t type) 347 { 348 int i; 349 uint32 rval, mode, glb_rval; 350 _bcm_bst_cmn_unit_info_t *bst_info; 351 soc_reg_t reg, glb_reg; 352 soc_field_t field = INVALIDf; 353 soc_reg_t blk_regs[] = {MMU_THDO_BST_CONFIGr, MMU_THDI_BSTCONFIGr, 354 MMU_CFAP_BSTCONFIGr, MMU_THDR_QE_BST_CONFIGr}; 355 soc_field_t blk_fields[2][4] = { 356 {TRACKING_MODEf, TRACKING_MODEf, TRACKING_MODEf, TRACK_MODEf}, 357 {SNAPSHOT_ENf, SNAPSHOT_ENf, SNAPSHOT_ENf, HW_SNAPSHOT_ENf} }; 358 soc_field_t glb_fields[] = { 359 ACTION_EN_THDO0f, ACTION_EN_THDO1f, 360 ACTION_EN_THDI0f, ACTION_EN_THDI1f, 361 ACTION_EN_CFAP0f, ACTION_EN_CFAP1f, 362 ACTION_EN_THDR0f, ACTION_EN_THDR1f}; 363 soc_info_t *si = &SOC_INFO(unit); 364 uint32 itm_map = si->itm_map; 365 int itm, inst; 366 367 bst_info = _BCM_UNIT_BST_INFO(unit); 368 369 if (!bst_info) { 370 return BCM_E_INIT; 371 } 372 glb_reg = MMU_GLBCFG_BST_SNAPSHOT_ACTION_ENr; 373 switch (type) { 374 case _bcm_th3_bst_config_tracking_mode: 375 bst_info->track_mode = arg; 376 break; 377 case _bcm_th3_bst_config_snapshot: 378 bst_info->snapshot_mode = arg; 379 break; 380 default: 381 return BCM_E_PARAM; 382 } 383 for (i = _BCM_TH3_BST_MODULE_THDO; i < _BCM_TH3_BST_MODULE_COUNT; i++) { 384 field = blk_fields[type][i]; 385 mode = 0; 386 if (type == _bcm_th3_bst_config_snapshot) { 387 if (arg & (0x1 << i)) { 388 mode = 0x1; 389 } 390 } else { 391 if (arg) { 392 mode = 1; 393 } else { 394 mode = 0; 395 } 396 } 397 reg = blk_regs[i]; 398 for (itm = 0; itm < NUM_ITM(unit); itm++) { 399 if (itm_map & (1 << itm)) { 400 if ((itm == 1) && (i == _BCM_TH3_BST_MODULE_THDO)) { 401 continue; 402 } 403 inst = itm | SOC_REG_ADDR_INSTANCE_MASK; 404 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, 405 &rval)); 406 soc_reg_field_set(unit, reg, &rval, field, mode); 407 408 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, 409 rval)); 410 } 411 } 412 413 414 if(type == _bcm_th3_bst_config_snapshot) { 415 glb_rval = 0; 416 /* config GLOBAL snapshot action register */ 417 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_reg, 418 REG_PORT_ANY, 0, &glb_rval)); 419 soc_reg_field_set(unit, glb_reg, &glb_rval, 420 glb_fields[_TH3_ITMS_PER_DEV * i], mode); 421 soc_reg_field_set(unit, glb_reg, &glb_rval, 422 glb_fields[_TH3_ITMS_PER_DEV * i + 1], mode); 423 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_reg, 424 REG_PORT_ANY, 0, glb_rval)); 425 426 } 427 } 428 429 return BCM_E_NONE; 430 } 431 432 /* 433 * Function: 434 * _bcm_th3_bst_resource_init 435 * Purpose: 436 * BST Stat resouce init (initialize a SW structure) for a given Stat ID. 437 * Parameters: 438 * unit - (IN) unit number 439 * type - (IN) BST stat ID 440 * Returns: 441 * BCM_E_XXX 442 */ 443 STATIC int 444 _bcm_th3_bst_resource_init(int unit, bcm_bst_stat_id_t type) 445 { 446 447 _bcm_bst_resource_info_t *pres; 448 int idx_count, i; 449 /* stat count and thd count need not be same. 450 * stat_count - Acc Type of stat are Non Dup, hence stat is for all ACC type 451 * thd_count - Acc Type of Thd are Dup(except CFAP), hence 1 copy. 452 */ 453 int total_stat_count, total_thd_count; 454 soc_mem_t stat_mem = INVALIDm, child_mem = INVALIDm, 455 thd_sel_mem = INVALIDm; 456 457 soc_reg_t stat_reg = INVALIDr, thd_reg = INVALIDr, prof_reg = INVALIDr; 458 459 soc_reg_t q_thd_regs[_BCM_TH3_BST_Q_TYPE_COUNT] = { 460 MMU_THDO_QUE_TOT_BST_THRESHOLDr, 461 MMU_THDO_MC_QUEUE_TOT_BST_THRESHOLDr, 462 MMU_THDO_MC_CPU_QUEUE_TOT_BST_THRESHOLDr 463 }; 464 soc_field_t stat_field = INVALIDf, thd_field = INVALIDf, 465 thd_sel_field = INVALIDf, prof_field = INVALIDf; 466 467 int granularity = 1; 468 uint32 pipe_map; 469 /* get active pipe bitmap */ 470 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 471 472 switch (type) { 473 case bcmBstStatIdDevice: 474 /* bcmBstStatIdDevice */ 475 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdDevice); 476 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 477 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_DEV); 478 pres->num_instance = NUM_ITM(unit); 479 pres->num_field = 1; 480 idx_count = 1; 481 stat_mem = INVALIDm; 482 stat_reg = MMU_CFAP_BSTSTATr; 483 stat_field = CNTf; 484 485 /* Threshold info count and Resource allocation */ 486 granularity = 1; 487 total_thd_count = NUM_ITM(unit) * idx_count; 488 _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, MMU_CFAP_BSTTHRSr, 489 BST_THRESHOLDf, granularity); 490 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst cfap"); 491 /* Stat info count and Resource allocation */ 492 total_stat_count = total_thd_count; /* No per pipe copy */ 493 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 494 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst cfap"); 495 pres->index_min = 0; 496 pres->index_max = total_stat_count - 1; 497 break; 498 case bcmBstStatIdHeadroomPool: 499 /* bcmBstStatIdHeadroomPool */ 500 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdHeadroomPool); 501 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 502 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_ING); 503 pres->num_instance = NUM_ITM(unit); 504 pres->num_field = 1; 505 /* There are 4 HDRM POOL per ITM */ 506 idx_count = _TH3_MMU_NUM_POOL; 507 stat_mem = INVALIDm; 508 stat_reg = MMU_THDI_BST_HDRM_POOL_CNTr; 509 stat_field = HDRM_POOL_CNTf; 510 /* Threshold info count and Resource allocation */ 511 granularity = 1; 512 total_thd_count = idx_count; 513 _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, MMU_THDI_BST_HDRM_POOLr, 514 BST_HDRM_POOL_THRESHf, granularity); 515 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 516 "bst ing headroom pool"); 517 /* Stat info count and Resource allocation */ 518 total_stat_count = NUM_ITM(unit) * total_thd_count; 519 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 520 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 521 "bst ing headroom pool"); 522 pres->index_min = 0; 523 pres->index_max = total_stat_count - 1; 524 break; 525 case bcmBstStatIdIngPool: 526 /* bcmBstStatIdIngPool */ 527 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdIngPool); 528 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 529 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_ING); 530 pres->num_instance = NUM_ITM(unit); 531 pres->num_field = 1; 532 idx_count = _TH3_MMU_NUM_POOL; 533 stat_mem = INVALIDm; 534 stat_reg = MMU_THDI_BST_SP_SHARED_CNTr; 535 stat_field = SP_SHARED_CNTf; 536 537 /* Threshold info count and Resource allocation */ 538 granularity = 1; 539 total_thd_count = idx_count; 540 _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, 541 MMU_THDI_BST_SP_SHAREDr, 542 BST_SP_SHARED_THRESHf, granularity); 543 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst ing pool"); 544 /* Stat info count and Resource allocation */ 545 total_stat_count = NUM_ITM(unit) * total_thd_count; 546 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 547 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst ing pool"); 548 pres->index_min = 0; 549 pres->index_max = total_stat_count - 1; 550 break; 551 case bcmBstStatIdPortPool: 552 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPortPool); 553 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 554 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 555 _BCM_BST_CMN_RES_F_PIPED | 556 _BCM_BST_CMN_RES_F_RES_ING); 557 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit)); 558 pres->num_instance = NUM_PIPE(unit); 559 stat_mem = MMU_THDI_PORTSP_BSTm; 560 stat_reg = INVALIDr; 561 /* multiple fields are hanlded by _BCM_BST_STAT_FIELD_INFO */ 562 stat_field = INVALIDf; 563 564 565 /* Get the mem attributes(Max idx) from the first child, 566 * which could be used for other instances. 567 */ 568 child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0); 569 idx_count = soc_mem_index_max(unit, child_mem) + 1; 570 571 /* Threshold profile selection info count and Resource allocation */ 572 granularity = 1; 573 total_thd_count = NUM_PIPE(unit) * idx_count * _TH3_MMU_NUM_POOL; 574 thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm; 575 thd_sel_field = INVALIDf; 576 for (i = 0; i < NUM_PIPE(unit); i++) { 577 /* pipe is active */ 578 if (pipe_map & (1 << i)) { 579 _BCM_BST_THRESHOLD_INFO_N(pres, 580 SOC_MEM_UNIQUE_ACC_PIPE(unit, thd_sel_mem, i), 581 INVALIDr, thd_sel_field, granularity, i); 582 } 583 } 584 /* Threshold profile count and Resource allocation */ 585 prof_reg = MMU_THDI_BST_PORTSP_SHARED_PROFILEr; 586 prof_field = BST_PORTSP_SHARED_THRESHf; 587 _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field); 588 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst port pool"); 589 590 /* Stat info count and Resource allocation */ 591 total_stat_count = total_thd_count; 592 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 593 for(i = 0; i < _TH3_MMU_NUM_POOL; i++) { 594 _BCM_BST_STAT_FIELD_INFO(pres, sp_fields[i], i); 595 _BCM_BST_THD_FIELD_INFO(pres, sp_sel_fields[i], i); 596 } 597 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst port pool"); 598 pres->index_min = 0; 599 pres->index_max = total_stat_count - 1; 600 break; 601 case bcmBstStatIdPriGroupShared: 602 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPriGroupShared); 603 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 604 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 605 _BCM_BST_CMN_RES_F_PIPED | 606 _BCM_BST_CMN_RES_F_RES_ING); 607 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit)); 608 609 pres->num_instance = NUM_PIPE(unit); 610 stat_mem = MMU_THDI_PORT_PG_SHARED_BSTm; 611 stat_reg = INVALIDr; 612 stat_field = INVALIDf; 613 child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0); 614 idx_count = soc_mem_index_max(unit, child_mem) + 1; 615 616 /* Threshold sel info count and Resource allocation */ 617 granularity = 1; 618 total_thd_count = idx_count * NUM_PIPE(unit) * _TH3_MMU_NUM_PG; 619 thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm; 620 thd_sel_field = INVALIDf; 621 for (i = 0; i < NUM_PIPE(unit); i++) { 622 /* pipe is active */ 623 if (pipe_map & (1 << i)) { 624 _BCM_BST_THRESHOLD_INFO_N(pres, 625 SOC_MEM_UNIQUE_ACC(unit, thd_sel_mem)[i], 626 INVALIDr, thd_sel_field, granularity, i); 627 } 628 } 629 /* Threshold profile info count and Resource allocation*/ 630 prof_reg = MMU_THDI_BST_PG_SHARED_PROFILEr; 631 prof_field = BST_PG_SHARED_THRESHf; 632 _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field); 633 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst pg"); 634 for(i = 0; i < _TH3_MMU_NUM_PG; i++) { 635 _BCM_BST_STAT_FIELD_INFO(pres, pg_fields[i], i); 636 _BCM_BST_THD_FIELD_INFO(pres, pg_sel_fields[i], i); 637 } 638 /* Stat info count and Resource allocation */ 639 /* Stat res - THDI_PORT_PG_BST : (Num Ports (20/pipe) * 8 pipes) * 8(PGs) */ 640 total_stat_count = total_thd_count; 641 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 642 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst pg"); 643 pres->index_min = 0; 644 pres->index_max = total_stat_count - 1; 645 break; 646 case bcmBstStatIdPriGroupHeadroom: 647 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPriGroupHeadroom); 648 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 649 pres->num_instance = NUM_PIPE(unit); 650 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 651 _BCM_BST_CMN_RES_F_PIPED | 652 _BCM_BST_CMN_RES_F_RES_ING); 653 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit)); 654 stat_mem = MMU_THDI_PORT_PG_HDRM_BSTm; 655 stat_reg = INVALIDr; 656 stat_field = INVALIDf; 657 child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0); 658 idx_count = soc_mem_index_max(unit, child_mem) + 1; 659 660 /* Threshold sel info count and Resource allocation */ 661 granularity = 1; 662 total_thd_count = idx_count * NUM_PIPE(unit) * _TH3_MMU_NUM_PG; 663 thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm; 664 thd_field = INVALIDf; 665 for (i = 0; i < NUM_PIPE(unit); i++) { 666 /* pipe is active */ 667 if (pipe_map & (1 << i)) { 668 _BCM_BST_THRESHOLD_INFO_N(pres, 669 SOC_MEM_UNIQUE_ACC(unit, thd_sel_mem)[i], 670 INVALIDr, thd_sel_field, granularity, i); 671 } 672 } 673 674 /*Threshold profile info count and Resource allocation */ 675 prof_reg = MMU_THDI_BST_PG_HDRM_PROFILEr; 676 prof_field = BST_PG_HDRM_THRESHf; 677 _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field); 678 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst pg hdrm"); 679 for(i = 0; i < _TH3_MMU_NUM_PG; i++) { 680 _BCM_BST_STAT_FIELD_INFO(pres, pg_hdrm_fields[i], i); 681 _BCM_BST_THD_FIELD_INFO(pres, pg_hdrm_sel_fields[i], i); 682 } 683 /* Stat info count and Resource allocation */ 684 /* Stat res - THDI_PORT_PG_BST : (Num Ports (20/pipe) * 8 pipes) * 8(PGs) */ 685 total_stat_count = total_thd_count; 686 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 687 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst pg hdrm"); 688 pres->index_min = 0; 689 pres->index_max = total_stat_count - 1; 690 break; 691 case bcmBstStatIdEgrPool: 692 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPool); 693 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 694 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_EGR); 695 pres->num_instance = NUM_ITM(unit); 696 pres->num_field = 1; 697 idx_count = _TH3_MMU_NUM_POOL; 698 pres->threshold_adj = -1; 699 stat_mem = INVALIDm; 700 stat_reg = MMU_THDO_UC_POOL_BST_COUNTr; 701 stat_field = BST_COUNTf; 702 703 /* Threshold info count and Resource allocation */ 704 granularity = 1; 705 total_thd_count = idx_count; 706 thd_reg = MMU_THDO_SP_SHR_BST_THRESHOLDr; 707 thd_field = BST_STATf; 708 _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, thd_reg, 709 thd_field, granularity); 710 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 711 "bst egr pool"); 712 /* Stat info count and Resource allocation */ 713 total_stat_count = NUM_ITM(unit) * total_thd_count; 714 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 715 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 716 "bst egr pool"); 717 pres->index_min = 0; 718 pres->index_max = total_stat_count - 1; 719 720 break; 721 case bcmBstStatIdEgrMCastPool: 722 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrMCastPool); 723 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 724 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_EGR); 725 pres->num_instance = NUM_ITM(unit); 726 pres->num_field = 1; 727 idx_count = _TH3_MMU_NUM_POOL; 728 pres->threshold_adj = -1; 729 stat_mem = INVALIDm; 730 stat_reg = MMU_THDO_MC_POOL_BST_COUNTr; 731 stat_field = BST_COUNTf; 732 733 /* Threshold info count and Resource allocation */ 734 granularity = 1; 735 total_thd_count = idx_count; 736 thd_reg = MMU_THDO_MC_CQE_SP_BST_THRESHOLDr; 737 thd_field = BST_STATf; 738 _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, thd_reg, 739 thd_field, granularity); 740 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 741 "bst egr mcpool"); 742 /* Stat info count and Resource allocation */ 743 total_stat_count = NUM_ITM(unit) * total_thd_count; 744 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 745 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 746 "bst egr mcpool"); 747 pres->index_min = 0; 748 pres->index_max = total_stat_count - 1; 749 break; 750 case bcmBstStatIdEgrPortPoolSharedMcast: 751 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPortPoolSharedMcast); 752 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 753 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 754 _BCM_BST_CMN_RES_F_RES_EGR); 755 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit)); 756 pres->num_instance = NUM_ITM(unit); 757 pres->num_field = 1; 758 stat_mem = MMU_THDO_BST_SHARED_PORTSP_MCm; 759 stat_reg = INVALIDr; 760 stat_field = SHARED_COUNTf; 761 762 /* Get the mem attributes(Max idx) from the first child, 763 * which could be used for other instances. 764 * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr). 765 */ 766 child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0); 767 idx_count = soc_mem_index_max(unit, child_mem) + 1; 768 769 /* Threshold info count and Resource allocation */ 770 granularity = 1; 771 total_thd_count = idx_count; 772 thd_sel_mem = MMU_THDO_CONFIG_PORTSP_MCm; 773 thd_sel_field = BST_PORTSP_WM_MC_CQE_THRESHOLD_SELf; 774 775 _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem, 776 INVALIDr, thd_sel_field, granularity); 777 778 779 prof_reg = MMU_THDO_MC_CQE_PRT_SP_BST_THRESHOLDr; 780 prof_field = BST_STATf; 781 _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field); 782 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 783 "bst egr port pool shared mcast"); 784 /* Stat info count and Resource allocation */ 785 total_stat_count = NUM_ITM(unit) * total_thd_count; 786 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 787 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 788 "bst egr port pool shared mcast"); 789 pres->index_min = 0; 790 pres->index_max = total_stat_count - 1; 791 break; 792 case bcmBstStatIdEgrPortPoolSharedUcast: 793 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPortPoolSharedUcast); 794 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 795 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 796 _BCM_BST_CMN_RES_F_RES_EGR); 797 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_PORT_ALL(unit)); 798 pres->num_instance = NUM_ITM(unit); 799 stat_mem = MMU_THDO_BST_SHARED_PORTm; 800 stat_reg = INVALIDr; 801 stat_field = INVALIDf; 802 803 /* Get the mem attributes(Max idx) from the first child, 804 * which could be used for other instances. 805 * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr). 806 */ 807 child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0); 808 idx_count = soc_mem_index_max(unit, child_mem) + 1; 809 810 /* Threshold info count and Resource allocation */ 811 granularity = 1; 812 total_thd_count = idx_count * _TH3_MMU_NUM_POOL; 813 thd_sel_mem = MMU_THDO_CONFIG_PORT_UC0m; 814 thd_sel_field = INVALIDf; 815 _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem, 816 INVALIDr, thd_sel_field, granularity); 817 818 prof_reg = MMU_THDO_PRT_SP_SHR_BST_THRESHOLDr; 819 prof_field = BST_STATf; 820 for(i = 0; i < _TH3_MMU_NUM_POOL; i++) { 821 _BCM_BST_THD_FIELD_INFO(pres, uc_portsp_sel_fields[i], i); 822 _BCM_BST_STAT_FIELD_INFO(pres, uc_portsp_fields[i], i); 823 } 824 _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field); 825 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 826 "bst egr port pool shared ucast"); 827 /* Stat info count and Resource allocation */ 828 total_stat_count = NUM_ITM(unit) * total_thd_count; 829 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 830 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 831 "bst egr port pool shared ucast"); 832 pres->index_min = 0; 833 pres->index_max = total_stat_count - 1; 834 break; 835 case bcmBstStatIdQueueTotal: 836 pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdQueueTotal); 837 _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres); 838 _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID | 839 _BCM_BST_CMN_RES_F_RES_EGR); 840 _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_PORT_ALL(unit)); 841 pres->num_instance = NUM_ITM(unit); 842 pres->num_field = 1; 843 stat_mem = MMU_THDO_BST_TOTAL_QUEUEm; 844 stat_reg = INVALIDr; 845 stat_field = BST_QUEUE_TOTAL_COUNTf; 846 847 /* Get the mem attributes(Max idx) from the first child, 848 * which could be used for other instances. 849 * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr). 850 */ 851 child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0); 852 idx_count = soc_mem_index_max(unit, child_mem) + 1; 853 854 /* Threshold info count and Resource allocation */ 855 granularity = 1; 856 total_thd_count = idx_count; 857 thd_sel_mem = MMU_THDO_QUEUE_CONFIGm; 858 thd_sel_field = BST_Q_WM_TOTAL_THRESHOLD_SELf; 859 _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem, 860 INVALIDr, thd_sel_field, granularity); 861 862 863 prof_field = BST_STATf; 864 for(i = 0; i < _BCM_TH3_BST_Q_TYPE_COUNT; i++) { 865 prof_reg = q_thd_regs[i]; 866 _BCM_BST_PROFILE_INFO_N(pres, INVALIDm, prof_reg, 867 prof_field, i); 868 869 } 870 pres->num_profile_reg = i; 871 _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, 872 "bst queue total use count"); 873 /* Stat info count and Resource allocation */ 874 total_stat_count = NUM_ITM(unit) * total_thd_count; 875 _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field); 876 _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, 877 "bst egr port pool shared ucast"); 878 pres->index_min = 0; 879 pres->index_max = total_stat_count - 1; 880 break; 881 882 default: 883 return BCM_E_PARAM; 884 } 885 return BCM_E_NONE; 886 } 887 888 /* 889 * Function: 890 * _bcm_th3_bst_control_set 891 * Purpose: 892 * Set BST global control. 893 * Parameters: 894 * unit - (IN) unit number 895 * type - (IN) control type 896 * arg - (IN) control value 897 * operation - (IN) operation origin, i.e. internal or external 898 * Returns: 899 * BCM_E_XXX 900 */ 901 902 STATIC int 903 _bcm_th3_bst_control_set(int unit, bcm_switch_control_t type, int arg, 904 _bcm_bst_thread_oper_t operation) 905 { 906 if(arg < 0) { 907 return BCM_E_PARAM; 908 } 909 910 switch (type) { 911 case bcmSwitchBstEnable: 912 BCM_IF_ERROR_RETURN 913 (_bcm_th3_bst_tracking_enable_set(unit, arg, operation)); 914 break; 915 case bcmSwitchBstTrackingMode: 916 BCM_IF_ERROR_RETURN( 917 _bcm_th3_bst_config_set(unit, arg, 918 _bcm_th3_bst_config_tracking_mode)); 919 break; 920 case bcmSwitchBstSnapshotEnable: 921 BCM_IF_ERROR_RETURN( 922 _bcm_th3_bst_config_set(unit, arg, _bcm_th3_bst_config_snapshot)); 923 924 break; 925 926 default: 927 return BCM_E_PARAM; 928 } 929 return BCM_E_NONE; 930 } 931 932 /* 933 * Function: 934 * _bcm_th3_bst_control_get 935 * Purpose: 936 * Get BST global control configuration. 937 * Parameters: 938 * unit - (IN) unit number 939 * type - (IN) control type 940 * arg - (OUT) control value 941 * Returns: 942 * BCM_E_XXX 943 */ 944 945 STATIC int 946 _bcm_th3_bst_control_get(int unit, bcm_switch_control_t type, int *arg) 947 { 948 _bcm_bst_cmn_unit_info_t *bst_info; 949 bst_info = _BCM_UNIT_BST_INFO(unit); 950 if (!bst_info) { 951 return BCM_E_INIT; 952 } 953 954 switch (type) { 955 case bcmSwitchBstEnable: 956 /*HW register MMU_GLBCFG_BST_TRACKING_ENABLE cannot be used to 957 * retrieve this as the value can be modified by hardware when HW 958 * snapshot action enable is set*/ 959 *arg = bst_info->bst_tracking_enable; 960 break; 961 case bcmSwitchBstTrackingMode: 962 *arg = bst_info->track_mode; 963 break; 964 case bcmSwitchBstSnapshotEnable: 965 *arg = bst_info->snapshot_mode; 966 break; 967 default: 968 return BCM_E_PARAM; 969 } 970 return BCM_E_NONE; 971 } 972 973 974 /* 975 * Function: 976 * _bcm_th3_bst_control_get 977 * Purpose: 978 * Enable/disable BST HW interrupt. 979 * Parameters: 980 * unit - (IN) unit number 981 * enable - (IN) Enable config 982 * Returns: 983 * BCM_E_XXX 984 */ 985 986 STATIC int 987 _bcm_bst_th3_intr_enable_set(int unit, int enable) 988 { 989 int i; 990 uint32 rval; 991 uint64 rval64; 992 soc_reg_t reg = INVALIDr; 993 soc_reg_t regs_intr[_BCM_TH3_BST_MODULE_COUNT] = 994 {MMU_THDO_BST_CPU_INT_ENr, MMU_THDI_CPU_INT_ENr, 995 MMU_CFAP_INT_ENr, MMU_THDR_QE_CPU_INT_ENr}; 996 soc_field_t fields_intr[_BCM_TH3_BST_MODULE_COUNT] = 997 {BSTf, BST_TRIGf, BST_TRIGf, BSTf}; 998 999 if (!soc_property_get(unit, spn_POLLED_IRQ_MODE, 0)) { 1000 /* Enable interrupt at base level module THDI/THDO/THDR/CFAP */ 1001 for(i = _BCM_TH3_BST_MODULE_THDO; i < _BCM_TH3_BST_MODULE_COUNT; i++) { 1002 rval = 0; 1003 reg = regs_intr[i]; 1004 if(reg == MMU_CFAP_INT_ENr) { 1005 SOC_IF_ERROR_RETURN( 1006 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 1007 soc_reg64_field32_set(unit, reg, &rval64, 1008 fields_intr[i], enable); 1009 SOC_IF_ERROR_RETURN( 1010 soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64)); 1011 continue; 1012 }; 1013 SOC_IF_ERROR_RETURN( 1014 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1015 soc_reg_field_set(unit, reg, &rval, fields_intr[i], enable); 1016 SOC_IF_ERROR_RETURN( 1017 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1018 } 1019 } 1020 return BCM_E_NONE; 1021 } 1022 1023 STATIC int 1024 _bcm_th3_set_hw_intr_cb(int unit) 1025 { 1026 BCM_IF_ERROR_RETURN(soc_th3_set_bst_callback(unit, &_bcm_bst_hw_event_cb)); 1027 return BCM_E_NONE; 1028 } 1029 1030 1031 STATIC int 1032 _bcm_bst_th3_intr_to_resources(int unit, uint32 *flags) 1033 { 1034 uint32 flags_tr = 0; 1035 uint32 inst, itm_map, pipe_map; 1036 uint32 fval = 0; 1037 uint32 rval, rval32_type, rval32_status; 1038 int index[_bcmResourceMaxCount] = {-1}; 1039 int res[_bcmResourceMaxCount] = {-1}, res_ct = 0; 1040 int bid_detect[_bcmResourceMaxCount] = {0}; 1041 soc_field_t fld = INVALIDf; 1042 soc_reg_t reg_type = INVALIDr, reg_status = INVALIDr; 1043 int i, pipe, itm = 0; 1044 soc_info_t *si; 1045 1046 si = &SOC_INFO(unit); 1047 _bcm_bst_th3_intr_enable_set(unit, 0); 1048 LOG_VERBOSE(BSL_LS_BCM_COSQ, 1049 (BSL_META_U(unit, 1050 "BST interrupt handler: unit=%d flags=0x%x\n"), 1051 unit, *flags)); 1052 itm_map = si->itm_map; 1053 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1054 1055 /* _bcmResourceDevice */ 1056 BCM_IF_ERROR_RETURN(READ_MMU_CFAP_BSTSTATr(unit, &rval)); 1057 if (soc_reg_field_get(unit, MMU_CFAP_BSTSTATr, rval, CNTf)) { 1058 if (SOC_REG_IS_VALID(unit, MMU_CFAP_INT_STATr)) { 1059 /* For CFAP, it use MMU_CFAP_INT_STATr to indicate the bst 1060 * interruptbut not use a trigger status register. 1061 * MMU_CFAP_INT_STATr would be cleared in SER handler, so 1062 * we check _bcmResourceDevice every time here. */ 1063 index[res_ct] = 0; 1064 res[res_ct++] = _bcmResourceDevice; 1065 } 1066 } 1067 1068 /* THDI Status/Triggers per-pipe */ 1069 reg_type = MMU_THDI_BST_TRIGGER_STATUS_TYPEr; 1070 reg_status = THDI_BST_TRIGGER_STATUS_32r; 1071 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 1072 if (!(pipe_map & (1U << pipe))) { 1073 continue; 1074 } 1075 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 1076 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg_type, inst, 0, &rval32_type)); 1077 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg_status, inst, 0, &rval32_status)); 1078 1079 /* _bcmResourceIngPool */ 1080 fval = soc_reg_field_get(unit, reg_type, rval32_type, SP_SHARED_TRIGGERf); 1081 if (fval && !bid_detect[_bcmResourceIngPool]) { 1082 fld = SP_SHARED_TRIGGER_STATUSf; 1083 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1084 res[res_ct++] = _bcmResourceIngPool; 1085 bid_detect[_bcmResourceIngPool] = 1; 1086 } 1087 1088 /* _bcmResourcePortPool */ 1089 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1090 PORTSP_SHARED_TRIGGERf); 1091 if (fval && !bid_detect[_bcmResourcePortPool]) { 1092 fld = PORTSP_SHARED_TRIGGER_STATUSf; 1093 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1094 res[res_ct++] = _bcmResourcePortPool; 1095 bid_detect[_bcmResourcePortPool] = 1; 1096 } 1097 1098 /* _bcmResourcePriGroupShared */ 1099 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1100 PG_SHARED_TRIGGERf); 1101 if (fval && !bid_detect[_bcmResourcePriGroupShared]) { 1102 fld = PG_SHARED_TRIGGER_STATUSf; 1103 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1104 res[res_ct++] = _bcmResourcePriGroupShared; 1105 bid_detect[_bcmResourcePriGroupShared] = 1; 1106 } 1107 1108 /* _bcmResourcePriGroupHeadroom */ 1109 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1110 PG_HDRM_TRIGGERf); 1111 1112 if (fval && !bid_detect[_bcmResourcePriGroupHeadroom]) { 1113 fld = PG_HDRM_TRIGGER_STATUSf; 1114 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1115 res[res_ct++] = _bcmResourcePriGroupHeadroom; 1116 bid_detect[_bcmResourcePriGroupHeadroom] = 1; 1117 } 1118 1119 /* _bcmResourceHeadroomPool */ 1120 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1121 HEADROOM_POOL_TRIGGERf); 1122 1123 if (fval && !bid_detect[_bcmResourceHeadroomPool]) { 1124 fld = HEADROOM_POOL_TRIGGER_STATUSf; 1125 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1126 res[res_ct++] = _bcmResourceHeadroomPool; 1127 bid_detect[_bcmResourceHeadroomPool] = 1; 1128 } 1129 rval32_type = 0; 1130 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_type, inst, 0, rval32_type)); 1131 rval32_status = 0; 1132 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_status, inst, 0, rval32_status)); 1133 } 1134 1135 1136 /* THDO Status/Triggers */ 1137 /* MC egr pool and MC egr port-pool ID are stored in reg_status, 1138 * the rest of info is stored in reg_type 1139 */ 1140 reg_type = MMU_THDO_BST_STATr; 1141 reg_status = MMU_THDO_BST_STAT1r; 1142 rval = 0; 1143 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1144 if (!(itm_map & (1U << itm))) { 1145 continue; 1146 } 1147 inst = itm | SOC_REG_ADDR_INSTANCE_MASK; 1148 BCM_IF_ERROR_RETURN 1149 (soc_reg32_get(unit, reg_type, inst, 0, &rval32_type)); 1150 BCM_IF_ERROR_RETURN( 1151 soc_reg32_get(unit, reg_status, inst, 0, &rval32_status)); 1152 /* _bcmResourceEgrPool */ 1153 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1154 MMU_THDO_SP_SHR_BST_TRIGf); 1155 1156 if (fval && !bid_detect[_bcmResourceEgrPool]) { 1157 fld = MMU_THDO_SP_SHR_BST_IDf; 1158 index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld); 1159 res[res_ct++] = _bcmResourceEgrPool; 1160 bid_detect[_bcmResourceEgrPool] = 1; 1161 } 1162 1163 /* _bcmResourceEgrMCastPool */ 1164 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1165 MMU_THDO_MC_CQE_SP_BST_TRIGf); 1166 1167 if (fval && !bid_detect[_bcmResourceEgrMCastPool]) { 1168 fld = MMU_THDO_MC_CQE_SP_BST_IDf; 1169 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1170 res[res_ct++] = _bcmResourceEgrMCastPool; 1171 bid_detect[_bcmResourceEgrMCastPool] = 1; 1172 } 1173 1174 /* _bcmResourceBstStatIdQueueTotal */ 1175 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1176 MMU_THDO_QUE_TOT_BST_TRIGf); 1177 1178 if (fval && !bid_detect[_bcmResourceBstStatIdQueueTotal]) { 1179 fld = MMU_THDO_QUE_TOT_BST_IDf; 1180 index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld); 1181 res[res_ct++] = _bcmResourceBstStatIdQueueTotal; 1182 bid_detect[_bcmResourceBstStatIdQueueTotal] = 1; 1183 } 1184 1185 /* _bcmResourceEgrPortPoolSharedMcast*/ 1186 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1187 MMU_THDO_MC_CQE_PRT_SP_BST_TRIGf); 1188 1189 if (fval && !bid_detect[_bcmResourceEgrPortPoolSharedMcast]) { 1190 fld = MMU_THDO_MC_CQE_PRT_SP_BST_IDf; 1191 index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld); 1192 res[res_ct++] = _bcmResourceEgrPortPoolSharedMcast; 1193 bid_detect[_bcmResourceEgrPortPoolSharedMcast] = 1; 1194 } 1195 1196 /* _bcmResourceEgrPortPoolSharedUcast*/ 1197 fval = soc_reg_field_get(unit, reg_type, rval32_type, 1198 MMU_THDO_PRT_SP_SHR_BST_TRIGf); 1199 if (fval && !bid_detect[_bcmResourceEgrPortPoolSharedUcast]) { 1200 fld = MMU_THDO_PRT_SP_SHR_BST_IDf; 1201 index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld); 1202 res[res_ct++] = _bcmResourceEgrPortPoolSharedUcast; 1203 bid_detect[_bcmResourceEgrPortPoolSharedUcast] = 1; 1204 } 1205 rval32_type = 0; 1206 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_type, inst, 0, rval32_type)); 1207 rval32_status = 0; 1208 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_status, inst, 0, rval32_status)); 1209 } 1210 if (res_ct == 0) { 1211 _bcm_bst_th3_intr_enable_set(unit, 1); 1212 /* No resource to fetch */ 1213 return BCM_E_NONE; 1214 } 1215 1216 for (i = 0; i < res_ct; i++) { 1217 BCM_IF_ERROR_RETURN( 1218 _bcm_bst_th3_sync_hw_snapshot(unit, res[i], -1, index[i])); 1219 } 1220 1221 *flags = flags_tr; 1222 _bcm_bst_th3_intr_enable_set(unit, 1); 1223 return BCM_E_NONE; 1224 } 1225 1226 1227 /* 1228 * Function: 1229 * bcm_bst_th3_hw_stat_clear 1230 * Purpose: 1231 * Clear specified BST stat in HW. 1232 * Parameters: 1233 * unit - (IN) unit number 1234 * resInfo - (IN) resource info sturcture. 1235 * bid - (IN) BST stat ID. 1236 * buffer - (IN) buffer(ITM) id. 1237 * port - (IN) local port number. 1238 * index - (IN) stat index 1239 * Returns: 1240 * BCM_E_XXX 1241 */ 1242 1243 int 1244 bcm_bst_th3_hw_stat_clear(int unit, _bcm_bst_resource_info_t *resInfo, 1245 bcm_bst_stat_id_t bid, bcm_cosq_buffer_id_t buffer, 1246 int port, int index, 1247 int cosq) 1248 { 1249 _bcm_bst_cmn_unit_info_t *bst_info; 1250 int rv = BCM_E_NONE; 1251 uint32 rval; 1252 soc_mem_t base_mem = INVALIDm, mem = INVALIDm; 1253 soc_reg_t reg; 1254 int min_hw_idx, max_hw_idx, idx; 1255 int inst, stats_per_inst; 1256 int num_entries, mem_wsz; 1257 int num_field, field_idx; 1258 void *pentry; 1259 char *dmabuf; 1260 uint32 mmu_inst_map = 0; 1261 int field_ids[_TH3_MMU_NUM_PG]; 1262 int num, hw_idx; 1263 int enable = 0; 1264 1265 if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) { 1266 return BCM_E_PARAM; 1267 } 1268 1269 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 1270 return BCM_E_INIT; 1271 } 1272 if (bst_info->port_to_mmu_inst_map) { 1273 (void) bst_info->port_to_mmu_inst_map(unit, bid, port, 1274 &mmu_inst_map); 1275 } 1276 1277 if (bst_info->control_get) { 1278 bst_info->control_get(unit, bcmSwitchBstEnable, &enable); 1279 } 1280 if (enable && bst_info->control_set) { 1281 bst_info->control_set(unit, bcmSwitchBstEnable, 0, 1282 _bcmBstThreadOperInternal); 1283 } 1284 1285 if (!mmu_inst_map) { 1286 rv = BCM_E_PARAM; 1287 goto restore; 1288 } 1289 1290 if (index == -1) { 1291 min_hw_idx = resInfo->index_min; 1292 max_hw_idx = ((resInfo->index_max + 1) / resInfo->num_instance) - 1; 1293 } else { 1294 min_hw_idx = max_hw_idx = index; 1295 } 1296 1297 for (inst = 0; inst < resInfo->num_instance; inst++) { 1298 if (!(mmu_inst_map & (1 << inst))) { 1299 continue; 1300 } 1301 if ((base_mem = resInfo->stat_mem[0]) != INVALIDm) { 1302 /* All BST memories are either IPIPE based or ITM based in TH3*/ 1303 if((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) { 1304 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst); 1305 } else { 1306 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst); 1307 } 1308 if(mem == INVALIDm) { 1309 rv = BCM_E_INTERNAL; 1310 goto restore; 1311 } 1312 1313 if (index == -1) { 1314 /* clear all entries in the memory */ 1315 num_entries = soc_mem_index_count(unit, mem); 1316 mem_wsz = sizeof(uint32) * soc_mem_entry_words(unit, mem); 1317 1318 dmabuf = soc_cm_salloc(unit, num_entries * mem_wsz, "bst dmabuf"); 1319 if (dmabuf == NULL) { 1320 rv = BCM_E_MEMORY; 1321 goto restore; 1322 } 1323 1324 if (soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 1325 soc_mem_index_min(unit, mem), 1326 soc_mem_index_max(unit, mem), 1327 dmabuf)) { 1328 soc_cm_sfree(unit, dmabuf); 1329 rv = BCM_E_INTERNAL; 1330 goto restore; 1331 } 1332 1333 /* Clear stat counter if requested */ 1334 for (idx = min_hw_idx; idx <= max_hw_idx; idx++) { 1335 if (resInfo->stat_field != INVALIDf) { 1336 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 1337 dmabuf, idx); 1338 soc_mem_field32_set(unit, mem, pentry, 1339 resInfo->stat_field, 0); 1340 } else { 1341 /* Multiple fields case */ 1342 num_field = resInfo->num_field; 1343 hw_idx = idx / num_field; 1344 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 1345 dmabuf, hw_idx); 1346 for (field_idx = 0; field_idx < num_field; field_idx++) 1347 { 1348 soc_mem_field32_set(unit, mem, pentry, 1349 resInfo->stat_fields[field_idx], 0); 1350 } 1351 } 1352 } 1353 1354 if (soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 1355 soc_mem_index_min(unit, mem), 1356 soc_mem_index_max(unit, mem), 1357 dmabuf)) { 1358 soc_cm_sfree(unit, dmabuf); 1359 rv = BCM_E_INTERNAL; 1360 goto restore; 1361 } 1362 soc_cm_sfree(unit, dmabuf); 1363 } else { 1364 /* Clear a specific index */ 1365 uint32 entry[SOC_MAX_MEM_WORDS]; 1366 1367 if(resInfo->stat_field != INVALIDf) { 1368 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, entry); 1369 if (rv) { 1370 goto restore; 1371 } 1372 soc_mem_field32_set(unit, mem, entry, 1373 resInfo->stat_field, 0); 1374 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 1375 if (rv) { 1376 goto restore; 1377 } 1378 } else { 1379 /*multiple field case */ 1380 num_field = resInfo->num_field; 1381 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, entry); 1382 if (rv) { 1383 goto restore; 1384 } 1385 rv = _bcm_bst_field_ids_retrieve(unit, bid, port, cosq, 1386 field_ids, &num); 1387 if (rv) { 1388 goto restore; 1389 } 1390 if (num > num_field) { 1391 rv = BCM_E_INTERNAL; 1392 goto restore; 1393 } 1394 for (idx = 0; idx < num; idx++) { 1395 field_idx = field_ids[idx]; 1396 soc_mem_field32_set(unit, mem, entry, 1397 resInfo->stat_fields[field_idx], 0); 1398 } 1399 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 1400 if (rv) { 1401 goto restore; 1402 } 1403 1404 } 1405 } 1406 1407 } else if ((reg = resInfo->stat_reg[0]) != INVALIDr) { 1408 int stat_idx = 0; 1409 stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance; 1410 1411 /* Clear stat counters */ 1412 for (idx = min_hw_idx; idx <= max_hw_idx; idx++) { 1413 int l_inst; 1414 rval = 0; 1415 if (stats_per_inst) { 1416 l_inst = inst | SOC_REG_ADDR_INSTANCE_MASK; 1417 stat_idx = idx % stats_per_inst; 1418 } else { 1419 l_inst = REG_PORT_ANY; 1420 stat_idx = idx; 1421 } 1422 rv = soc_reg32_get(unit, reg, l_inst, stat_idx, &rval); 1423 if (rv) { 1424 goto restore; 1425 } 1426 /* no stat_reg has multiple fields in TH3*/ 1427 soc_reg_field_set(unit, reg, &rval, resInfo->stat_field, 0); 1428 rv = soc_reg32_set(unit, reg, l_inst, stat_idx, rval); 1429 if (rv) { 1430 goto restore; 1431 } 1432 } 1433 1434 } /* if valid reg */ 1435 } /* for each instance */ 1436 1437 restore: 1438 if (enable && bst_info->control_set) { 1439 bst_info->control_set(unit, bcmSwitchBstEnable, enable, 1440 _bcmBstThreadOperInternal); 1441 } 1442 1443 return rv; 1444 } 1445 1446 /* 1447 * Function: 1448 * _bcm_bst_th3_sync_resource_stat 1449 * Purpose: 1450 * Sync a stat count at a specific index. 1451 * Parameters: 1452 * unit - (IN) unit number. 1453 * resInfo - (IN) resource info sturcture. 1454 * idx - (IN) index of SW stat. 1455 * val - (IN) value to sync. 1456 * Returns: 1457 * BCM_E_XXX 1458 */ 1459 STATIC int 1460 _bcm_bst_th3_sync_resource_stat( 1461 int unit, 1462 _bcm_bst_resource_info_t *resInfo, 1463 uint32 idx, 1464 uint32 val) 1465 { 1466 _bcm_bst_cmn_unit_info_t *bst_info; 1467 int hwm_mode; 1468 if(resInfo == NULL) { 1469 return BCM_E_PARAM; 1470 } 1471 1472 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 1473 return BCM_E_INIT; 1474 } 1475 if (idx > resInfo->index_max) { 1476 return BCM_E_INTERNAL; 1477 } 1478 1479 hwm_mode = bst_info->track_mode; 1480 if (hwm_mode) { 1481 /* BST tracking is in Peak mode. 1482 * Hence store the watermark value only. 1483 */ 1484 if (resInfo->p_stat[idx] < val) { 1485 resInfo->p_stat[idx] = val; 1486 } 1487 } else { 1488 resInfo->p_stat[idx] = val; 1489 } 1490 1491 return BCM_E_NONE; 1492 } 1493 1494 /* 1495 * Function: 1496 * _bcm_bst_th3_sync_hw_snapshot 1497 * Purpose: 1498 * Sync all HW BST stat counts to SW copy for a given Stat ID. 1499 * Parameters: 1500 * unit - (IN) unit number. 1501 * bid - (IN) BST stat ID. 1502 * port, index - (IN) not used in the function, the function signature 1503 * is defined in a way such that it is consistent with the function 1504 * pointer required by bst_info->hw_stat_snapshot 1505 * Returns: 1506 * BCM_E_XXX 1507 */ 1508 1509 int 1510 _bcm_bst_th3_sync_hw_snapshot(int unit, bcm_bst_stat_id_t bid, 1511 int port, int index) 1512 { 1513 _bcm_bst_cmn_unit_info_t *bst_info; 1514 _bcm_bst_resource_info_t *resInfo; 1515 int num_entries, mem_wsz; 1516 int i, j, idx, idx_offset, thd_idx; 1517 int inst; 1518 int stats_per_inst = 0; /* stats per mem instance(itm) */ 1519 void *pentry; 1520 char *dmabuf; 1521 uint32 rval, temp_val; 1522 soc_mem_t mem, base_mem; 1523 soc_reg_t reg; 1524 bcm_gport_t gport; 1525 bcm_cos_queue_t cosq; 1526 uint32 pipe_map, itm_map; 1527 soc_info_t *si = &SOC_INFO(unit); 1528 int enable = 0; 1529 int rv = BCM_E_NONE; 1530 1531 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 1532 return BCM_E_INIT; 1533 } 1534 if (bst_info->control_get) { 1535 bst_info->control_get(unit, bcmSwitchBstEnable, &enable); 1536 } 1537 if (enable && bst_info->control_set) { 1538 bst_info->control_set(unit, bcmSwitchBstEnable, 0, 1539 _bcmBstThreadOperInternal); 1540 } 1541 1542 /* sync all the stats */ 1543 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 1544 bid = bcmBstStatIdQueueTotal; 1545 } 1546 resInfo = _BCM_BST_RESOURCE(unit, bid); 1547 if (resInfo == NULL) { 1548 rv = BCM_E_PARAM; 1549 goto restore; 1550 } 1551 1552 base_mem = resInfo->stat_mem[0]; 1553 reg = resInfo->stat_reg[0]; 1554 1555 /* get active pipe bitmap & itmbitmap */ 1556 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1557 itm_map = si->itm_map; 1558 1559 if (reg != INVALIDr) { 1560 int stat_idx = 0; 1561 stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance; 1562 1563 for (idx = 0; idx < resInfo->num_stat_pp; idx++) { 1564 rval = 0; 1565 if (stats_per_inst) { 1566 inst = idx / stats_per_inst; 1567 inst = inst | SOC_REG_ADDR_INSTANCE_MASK; 1568 stat_idx = idx % stats_per_inst; 1569 } else { 1570 inst = REG_PORT_ANY; 1571 stat_idx = idx; 1572 stats_per_inst = 1; 1573 } 1574 1575 idx_offset = idx; 1576 if(resInfo->stat_field != INVALIDf) { 1577 rv = soc_reg32_get(unit, reg, inst, stat_idx, &rval); 1578 if (rv) { 1579 goto restore; 1580 } 1581 temp_val = soc_reg_field_get(unit, reg, rval, 1582 resInfo->stat_field); 1583 rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo, 1584 idx_offset, temp_val); 1585 if (rv) { 1586 goto restore; 1587 } 1588 } else { 1589 /* register have multiple fields*/ 1590 rv = BCM_E_INTERNAL; 1591 goto restore; 1592 } 1593 1594 /* Check if there exists threshold for a resource 1595 * continue if we don't have one */ 1596 if (resInfo->p_threshold == NULL) { 1597 continue; 1598 } 1599 1600 thd_idx = idx; 1601 if ((bid != bcmBstStatIdDevice) && 1602 (!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED))) { 1603 /* Bids which have duplicate access */ 1604 thd_idx = stat_idx; 1605 } 1606 /* coverity[copy_paste_error : FALSE] */ 1607 if (resInfo->p_threshold[thd_idx] && 1608 (resInfo->p_stat[idx_offset] >= 1609 (resInfo->p_threshold[thd_idx] * resInfo->threshold_gran) 1610 )) { 1611 /* Generate SOC EVENT */ 1612 if (bst_info->handlers.reverse_resolve_index) { 1613 /* reverse map the inedx to port/cos pair */ 1614 bst_info->handlers.reverse_resolve_index(unit, bid, 1615 port, idx_offset, 1616 &gport, &cosq); 1617 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER, 1618 bid, gport, cosq); 1619 1620 } 1621 } 1622 1623 } 1624 } else if (base_mem != INVALIDm) { 1625 int min_idx = 0, max_idx = 0; 1626 int instance_offset = 0; /* offset per pipe or per (ITM) */ 1627 1628 /* Get the mem attributes(Max idx) from the first child, 1629 * which could be used for other instances. 1630 * Note: In TH3, ITM 0/Pipe 0 instance valid for all memories(Ing/Egr). 1631 */ 1632 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 1633 1634 mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, base_mem, 0, 0); 1635 }else { 1636 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0); 1637 } 1638 if (mem == INVALIDm) { 1639 rv = BCM_E_PARAM; 1640 goto restore; 1641 } 1642 stats_per_inst = (resInfo->index_max + 1) / resInfo->num_instance; 1643 min_idx = soc_mem_index_min(unit, mem); 1644 max_idx = soc_mem_index_max(unit, mem); 1645 num_entries = max_idx + 1; 1646 1647 mem_wsz = sizeof(uint32) * soc_mem_entry_words(unit, mem); 1648 1649 dmabuf = soc_cm_salloc(unit, num_entries * mem_wsz, "bst dmabuf"); 1650 if (dmabuf == NULL) { 1651 rv = BCM_E_MEMORY; 1652 goto restore; 1653 } 1654 /* num_instance is equal to the number of pipes if memory is per-pipe, 1655 * or the number of ITMs otherwise*/ 1656 for (i = 0; i < resInfo->num_instance; i++) { 1657 instance_offset = 0; 1658 gport = BCM_GPORT_INVALID; 1659 cosq = -1; 1660 instance_offset = stats_per_inst * i; 1661 if((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) { 1662 if (!(pipe_map & (1 << i))) { 1663 continue; 1664 } 1665 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, i); 1666 1667 } else { 1668 if (!(itm_map & (1 << i))) { 1669 continue; 1670 } 1671 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, i); 1672 } 1673 if(mem == INVALIDm) { 1674 rv = BCM_E_INTERNAL; 1675 goto restore; 1676 } 1677 1678 if (soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 1679 min_idx, max_idx, dmabuf)) { 1680 soc_cm_sfree(unit, dmabuf); 1681 rv = BCM_E_INTERNAL; 1682 goto restore; 1683 } 1684 1685 for (idx = 0; idx <= max_idx; idx++) { 1686 idx_offset = idx + instance_offset; 1687 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 1688 dmabuf, 1689 idx); 1690 if(resInfo->stat_field != INVALIDf) { 1691 idx_offset = idx + instance_offset; 1692 temp_val = soc_mem_field32_get(unit, mem, pentry, 1693 resInfo->stat_field); 1694 rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo, 1695 idx_offset, temp_val); 1696 if (rv) { 1697 soc_cm_sfree(unit, dmabuf); 1698 goto restore; 1699 } 1700 1701 /* In TH3, stat count and thd count need not be same as in 1702 * previous chips(check init). This is due to different 1703 * AccType for Stat and Threshold. 1704 * Stats - usually NON-DUP Acc Type 1705 * Threshold - usually DUP Acc Type 1706 * Hence threshold index might only exist for 1 instance 1707 * and applicable to all. 1708 */ 1709 thd_idx = idx_offset; 1710 if ((bid != bcmBstStatIdDevice) && 1711 ((!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)))) { 1712 /* Bids which have duplicate access across ITM */ 1713 thd_idx = idx_offset % stats_per_inst; 1714 } 1715 if (resInfo->p_threshold[thd_idx] && 1716 (resInfo->p_stat[idx_offset] >= 1717 (resInfo->p_threshold[thd_idx]) * resInfo->threshold_gran)) { 1718 /* Generate SOC EVENT */ 1719 if (bst_info->handlers.reverse_resolve_index) { 1720 /* reverse map the inedx to port/cos pair */ 1721 bst_info->handlers.reverse_resolve_index 1722 (unit, bid, port, thd_idx, 1723 &gport, &cosq); 1724 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER, 1725 bid, gport, cosq); 1726 1727 } 1728 } 1729 } else { 1730 for(j = 0; j < resInfo->num_field; j++) { 1731 idx_offset = (idx * (resInfo->num_field)) 1732 + instance_offset + j; 1733 temp_val = soc_mem_field32_get(unit, mem, 1734 pentry, resInfo->stat_fields[j]); 1735 rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo, 1736 idx_offset , temp_val); 1737 if (rv) { 1738 soc_cm_sfree(unit, dmabuf); 1739 goto restore; 1740 } 1741 /* In TH3, stat count and thd count need not be same as in 1742 * previous chips(check init). This is due to different 1743 * AccType for Stat and Threshold. 1744 * Stats - usually NON-DUP Acc Type 1745 * Threshold - usually DUP Acc Type 1746 * Hence threshold index might only exist for 1 instance 1747 * and applicable to all. 1748 */ 1749 if (!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) { 1750 thd_idx = (idx * resInfo->num_field) + j; 1751 } else { 1752 thd_idx = idx_offset; 1753 } 1754 if (resInfo->p_threshold[thd_idx] && 1755 (resInfo->p_stat[idx_offset] >= 1756 (resInfo->p_threshold[thd_idx]) * resInfo->threshold_gran)) { 1757 /* Generate SOC EVENT */ 1758 if (bst_info->handlers.reverse_resolve_index) { 1759 /* reverse map the inedx to port/cos pair */ 1760 bst_info->handlers.reverse_resolve_index 1761 (unit, bid, port, thd_idx, 1762 &gport, &cosq); 1763 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER, 1764 bid, gport, cosq); 1765 1766 } 1767 } 1768 1769 } 1770 1771 } 1772 1773 } 1774 1775 } 1776 soc_cm_sfree(unit, dmabuf); 1777 } 1778 restore: 1779 if (enable && bst_info->control_set) { 1780 bst_info->control_set(unit, bcmSwitchBstEnable, enable, 1781 _bcmBstThreadOperInternal); 1782 } 1783 1784 return rv; 1785 } 1786 1787 /* 1788 * Function: 1789 * _bst_th3_port_to_mmu_inst_map_get 1790 * Purpose: 1791 * Function to return the corresponding ITM instance for a given gport. 1792 * for per-pipe register/memory, instance -> pipe 1793 * otherwise, instance -> ITM 1794 * Parameters: 1795 * unit - (IN) unit number. 1796 * bid - (IN) BST stat ID. 1797 * gport - (IN) gport number. 1798 * mmu_inst_map (OUT) instance map. 1799 * Returns: 1800 * BCM_E_XXX 1801 */ 1802 1803 int _bst_th3_port_to_mmu_inst_map_get(int unit, bcm_bst_stat_id_t bid, 1804 bcm_gport_t gport, uint32 *mmu_inst_map) 1805 { 1806 soc_info_t *si = &SOC_INFO(unit); 1807 _bcm_bst_resource_info_t *resInfo; 1808 bcm_port_t local_port; 1809 int pipe; 1810 uint32 pipe_map; 1811 resInfo = _BCM_BST_RESOURCE(unit, bid); 1812 if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) { 1813 return BCM_E_PARAM; 1814 } 1815 1816 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1817 if(gport == -1) { 1818 if (resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 1819 *mmu_inst_map = pipe_map; 1820 } else { 1821 *mmu_inst_map = si->itm_map; 1822 } 1823 return BCM_E_NONE; 1824 } 1825 BCM_IF_ERROR_RETURN( 1826 _bcm_th3_cosq_localport_resolve(unit, gport, &local_port)); 1827 1828 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 1829 1830 if (resInfo->flags & _BCM_BST_CMN_RES_F_RES_ING) { 1831 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 1832 *mmu_inst_map = 1U << pipe; 1833 *mmu_inst_map &= pipe_map; 1834 } else { 1835 *mmu_inst_map = si->ipipe_itm_map[pipe]; 1836 *mmu_inst_map &= si->itm_map; 1837 } 1838 } else { 1839 /* For Global and EGR resource, return all instances (ITMs)*/ 1840 *mmu_inst_map = si->itm_map; 1841 } 1842 1843 return BCM_E_NONE; 1844 } 1845 1846 1847 /* 1848 * Function: 1849 * bcm_th3_cosq_bst_stat_clear 1850 * Purpose: 1851 * Clear speficied BST stat. 1852 * Parameters: 1853 * unit - (IN) unit number. 1854 * gport - (IN) gport number. 1855 * cosq - (IN) cosq number. 1856 * buffer - (IN) buffer(ITM) ID. 1857 * bid - (IN) BST stat ID. 1858 * Returns: 1859 * BCM_E_XXX 1860 */ 1861 int 1862 bcm_th3_cosq_bst_stat_clear(int unit, bcm_gport_t gport, 1863 bcm_cos_queue_t cosq, bcm_cosq_buffer_id_t buffer, 1864 bcm_bst_stat_id_t bid) 1865 1866 { 1867 _bcm_bst_cmn_unit_info_t *bst_info; 1868 _bcm_bst_resource_info_t *resInfo; 1869 int bcm_rv = BCM_E_NONE; 1870 _bcm_bst_cb_ret_t rv; 1871 void *cb_data = NULL; 1872 int rcb = 0; 1873 int start_hw_index = 0, end_hw_index = 0, pipe; 1874 int hw_index; 1875 1876 if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) { 1877 return BCM_E_PARAM; 1878 } 1879 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 1880 return BCM_E_INIT; 1881 } 1882 1883 if (bst_info->handlers.resolve_index == NULL) { 1884 return BCM_E_UNAVAIL; 1885 } 1886 1887 BCM_IF_ERROR_RETURN( 1888 _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq)); 1889 1890 if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) { 1891 bid = bcmBstStatIdQueueTotal; 1892 } 1893 resInfo = _BCM_BST_RESOURCE(unit, bid); 1894 if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) { 1895 return BCM_E_PARAM; 1896 } 1897 1898 sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER); 1899 if (gport == -1) { 1900 /* Clear all stat counters in the buffer*/ 1901 (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer, 1902 gport, -1, cosq); 1903 } else { 1904 /* Clear stat counter for given port, cos */ 1905 rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe, 1906 &start_hw_index, &end_hw_index, &rcb, 1907 &cb_data, &bcm_rv); 1908 if (rv != _BCM_BST_RV_ERROR) { 1909 for (hw_index = start_hw_index; hw_index <= end_hw_index; hw_index++) 1910 { 1911 (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer, 1912 gport, hw_index, 1913 cosq); 1914 } 1915 } 1916 } 1917 1918 if (gport == -1) { 1919 bcm_port_t local_port; 1920 PBMP_PORT_ITER(unit, local_port) { 1921 bcm_rv = bcm_bst_th3_sw_stat_clear(unit, local_port, 1922 cosq, buffer, bid); 1923 if (BCM_FAILURE(bcm_rv)) { 1924 break; 1925 } 1926 } 1927 } else { 1928 { 1929 bcm_rv = bcm_bst_th3_sw_stat_clear(unit, gport, cosq, buffer, bid); 1930 } 1931 } 1932 sal_mutex_give(bst_info->bst_reslock); 1933 1934 return bcm_rv; 1935 1936 } 1937 1938 /* 1939 * Function: 1940 * bcm_th3_cosq_bst_stat_multi_get 1941 * Purpose: 1942 * Get multiple BST stat counts. 1943 * Parameters: 1944 * unit - (IN) unit number. 1945 * gport - (IN) gport number. 1946 * cosq - (IN) cosq number. 1947 * options - (IN) BST stat read options, 1948 * used for setting clear-or-read FLAG. 1949 * max_values - (IN) size of BST stat ID array. 1950 * id_list - (IN) BST stat ID array. 1951 * pvalues - (OUT) BST stat count array. 1952 * Returns: 1953 * BCM_E_XXX 1954 */ 1955 int 1956 bcm_th3_cosq_bst_stat_multi_get(int unit, 1957 bcm_gport_t gport, 1958 bcm_cos_queue_t cosq, 1959 uint32 options, 1960 int max_values, 1961 bcm_bst_stat_id_t *id_list, 1962 uint64 *pvalues) 1963 { 1964 int i; 1965 1966 for (i = 0; i < max_values; i++) { 1967 1968 BCM_IF_ERROR_RETURN(bcm_th3_cosq_bst_stat_get(unit, gport, cosq, 1969 BCM_COSQ_BUFFER_ID_INVALID, id_list[i], 1970 options, &pvalues[i])); 1971 } 1972 return BCM_E_NONE; 1973 } 1974 1975 /* 1976 * Function: 1977 * _bcm_th3_bst_sw_index_get 1978 * Purpose: 1979 * Retrieve SW datastructure index corresponding to HW indes for a bid. 1980 * Parameters: 1981 * unit - (IN) unit number. 1982 * gport - (IN) gport number. 1983 * cosq - (IN) cosq number. 1984 * bid - (IN) BST ID. 1985 * hw_index - (IN) Hardware index. 1986 * num_sw_entries - (OUT) Number of software entries corresponding to the 1987 * hardware entry 1988 * sw_index_arr - (OUT) List of software indices corresponding to the HW 1989 * index 1990 * Returns: 1991 * BCM_E_XXX 1992 */ 1993 STATIC int 1994 _bcm_th3_bst_sw_index_get (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 1995 bcm_bst_stat_id_t bid, int hw_index, int *num_sw_entries, int *sw_index_arr) 1996 { 1997 1998 int cosq_loop_id; 1999 int local_port, pool = -1; 2000 int pool_start, pool_end; 2001 2002 if ((num_sw_entries == NULL) || (sw_index_arr == NULL)) { 2003 return BCM_E_PARAM; 2004 } 2005 2006 BCM_IF_ERROR_RETURN( 2007 _bcm_th3_cosq_localport_resolve(unit, gport, &local_port)); 2008 switch(bid) { 2009 case bcmBstStatIdEgrPortPoolSharedUcast: 2010 /* Retrieve the service pools mapped to given gport,cosq*/ 2011 BCM_IF_ERROR_RETURN( 2012 _bcm_th3_cosq_egress_sp_get (unit, gport, cosq, &pool_start, 2013 &pool_end)); 2014 *num_sw_entries = (pool_end - pool_start) + 1; 2015 cosq_loop_id = 0; 2016 for (pool = pool_start; pool <= pool_end; pool++) { 2017 sw_index_arr[cosq_loop_id] = 2018 (hw_index * _TH3_MMU_NUM_POOL) + pool; 2019 cosq_loop_id++; 2020 } 2021 break; 2022 case bcmBstStatIdPriGroupShared: 2023 case bcmBstStatIdPriGroupHeadroom: 2024 if (cosq == BCM_COS_INVALID) { 2025 *num_sw_entries = _TH3_MMU_NUM_PG; 2026 for (cosq_loop_id = 0; cosq_loop_id < _TH3_MMU_NUM_PG; 2027 cosq_loop_id++) { 2028 sw_index_arr[cosq_loop_id] = 2029 (hw_index * _TH3_MMU_NUM_PG) + cosq_loop_id; 2030 } 2031 } else { 2032 *num_sw_entries = 1; 2033 sw_index_arr[0] = (hw_index * _TH3_MMU_NUM_PG) + cosq; 2034 } 2035 break; 2036 case bcmBstStatIdPortPool: 2037 if (cosq == BCM_COS_INVALID) { 2038 *num_sw_entries = _TH3_MMU_NUM_POOL; 2039 for (pool = 0; pool < _TH3_MMU_NUM_POOL; 2040 pool++) { 2041 sw_index_arr[pool] = 2042 (hw_index * _TH3_MMU_NUM_POOL) + pool; 2043 } 2044 2045 } else { 2046 *num_sw_entries = 1; 2047 /* Retrieve Pool mapped to given PG of the port*/ 2048 BCM_IF_ERROR_RETURN( 2049 _bcm_th3_cosq_ingress_sp_get_by_pg(unit, local_port, 2050 cosq, &pool)); 2051 sw_index_arr[0] = (hw_index * _TH3_MMU_NUM_POOL) + pool; 2052 } 2053 break; 2054 default: 2055 *num_sw_entries = 1; 2056 sw_index_arr[0] = hw_index; 2057 break; 2058 } 2059 return BCM_E_NONE; 2060 } 2061 /* 2062 * Function: 2063 * bcm_bst_th3_sw_stat_clear 2064 * Purpose: 2065 * Clear specific BST stat counts in SW. 2066 * Parameters: 2067 * unit - (IN) unit number. 2068 * gport - (IN) gport number. 2069 * cosq - (IN) cosq number. 2070 * buffer - (IN) ITM id. 2071 * bid - (IN) BST stat ID. 2072 * Returns: 2073 * BCM_E_XXX 2074 */ 2075 2076 int 2077 bcm_bst_th3_sw_stat_clear(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2078 bcm_cosq_buffer_id_t buffer, bcm_bst_stat_id_t bid) 2079 { 2080 _bcm_bst_cmn_unit_info_t *bst_info; 2081 _bcm_bst_resource_info_t *resInfo; 2082 _bcm_bst_cb_ret_t rv; 2083 void *cb_data = NULL; 2084 int bcm_rv, rcb = 0, index; 2085 int start_hw_index = 0, end_hw_index = 0, pipe; 2086 uint32 mmu_inst_map = 0; 2087 int entries_per_inst, inst_offset, inst; 2088 int num_sw_entries, loop_idx, sw_index; 2089 /*max number of sw entries per hw index is 8 (number of PGS)*/ 2090 int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1}; 2091 2092 if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) { 2093 return BCM_E_PARAM; 2094 } 2095 2096 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 2097 return BCM_E_INIT; 2098 } 2099 2100 if (bst_info->handlers.resolve_index == NULL) { 2101 return BCM_E_UNAVAIL; 2102 } 2103 2104 do { 2105 rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe, 2106 &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv); 2107 if (bcm_rv) { 2108 return bcm_rv; 2109 } 2110 2111 if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) { 2112 bid = bcmBstStatIdQueueTotal; 2113 } 2114 resInfo = _BCM_BST_RESOURCE(unit, bid); 2115 if (resInfo == NULL) { 2116 return BCM_E_PARAM; 2117 } 2118 2119 entries_per_inst = (resInfo->index_max + 1) / resInfo->num_instance; 2120 if (bst_info->port_to_mmu_inst_map) { 2121 (void)bst_info->port_to_mmu_inst_map(unit, bid, gport, 2122 &mmu_inst_map); 2123 } 2124 if (!mmu_inst_map) { 2125 return BCM_E_PARAM; 2126 } 2127 2128 /* When a resource has more than one instance, clear all 2129 * applicable instances. 2130 */ 2131 for (index = start_hw_index; index <= end_hw_index; index++) { 2132 for (inst = 0; inst < resInfo->num_instance; inst++) { 2133 if (mmu_inst_map & (1 << inst)) { 2134 inst_offset = inst * entries_per_inst; 2135 /* retrieve the sw entries mapped to each hw index*/ 2136 BCM_IF_ERROR_RETURN( 2137 _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid, 2138 index, &num_sw_entries, sw_idx_arr)); 2139 if (num_sw_entries > resInfo->num_field) { 2140 return BCM_E_INTERNAL; 2141 } 2142 for (loop_idx = 0; loop_idx < num_sw_entries; loop_idx++) { 2143 if (sw_idx_arr[loop_idx] != -1) { 2144 sw_index = sw_idx_arr[loop_idx] + inst_offset; 2145 if (sw_index > resInfo->index_max) { 2146 return BCM_E_INTERNAL; 2147 } 2148 resInfo->p_stat[sw_index] = 0; 2149 } 2150 } 2151 } 2152 } 2153 } 2154 2155 } while (rv == _BCM_BST_RV_RETRY); 2156 return BCM_E_NONE; 2157 } 2158 2159 /* 2160 * Function: 2161 * bcm_th3_cosq_bst_stat_get 2162 * Purpose: 2163 * Get a specific BST stat count saved in SW. 2164 * Parameters: 2165 * unit - (IN) unit number. 2166 * gport - (IN) gport number. 2167 * cosq - (IN) cosq number. 2168 * buffer - (IN) ITM id. 2169 * bid - (IN) BST stat ID. 2170 * options - (IN) BST stat read options, 2171 * used for setting clear-or-read FLAG. 2172 * pvalue - (OUT) BST stat count. 2173 * Returns: 2174 * BCM_E_XXX 2175 */ 2176 int 2177 bcm_th3_cosq_bst_stat_get( 2178 int unit, 2179 bcm_gport_t gport, 2180 bcm_cos_queue_t cosq, 2181 bcm_cosq_buffer_id_t buffer, 2182 bcm_bst_stat_id_t bid, 2183 uint32 options, 2184 uint64 *pvalue) 2185 2186 { 2187 _bcm_bst_cmn_unit_info_t *bst_info; 2188 _bcm_bst_resource_info_t *resInfo; 2189 _bcm_bst_cb_ret_t rv; 2190 void *cb_data = NULL; 2191 int bcm_rv, rcb = 0, ii, inst, entries_per_inst; 2192 int start_hw_index = 0, end_hw_index = 0, pipe = 0; 2193 uint32 mmu_inst_map = 0; 2194 int temp_stat , max_stat; 2195 int num_sw_entries, loop_idx, sw_index; 2196 /*max number of sw entries per hw index is 8 (number of PGS)*/ 2197 int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1}; 2198 2199 2200 if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) { 2201 return BCM_E_PARAM; 2202 } 2203 2204 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 2205 return BCM_E_INIT; 2206 } 2207 2208 if (bst_info->handlers.resolve_index == NULL) { 2209 return BCM_E_UNAVAIL; 2210 } 2211 COMPILER_64_ZERO(*pvalue); 2212 2213 BCM_IF_ERROR_RETURN( 2214 _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq)); 2215 2216 do { 2217 rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe, 2218 &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv); 2219 if (bcm_rv) { 2220 return bcm_rv; 2221 } 2222 if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) { 2223 bid = bcmBstStatIdQueueTotal; 2224 } 2225 resInfo = _BCM_BST_RESOURCE(unit, bid); 2226 if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) { 2227 return BCM_E_PARAM; 2228 } 2229 2230 entries_per_inst = (resInfo->index_max + 1) / resInfo->num_instance; 2231 if (bst_info->port_to_mmu_inst_map) { 2232 (void) bst_info->port_to_mmu_inst_map(unit, bid, gport, 2233 &mmu_inst_map); 2234 } 2235 2236 if (!mmu_inst_map) { 2237 return BCM_E_PARAM; 2238 } 2239 /* When a resource has more than one instance, find the max value 2240 * of all applicable instances and return the Max value. 2241 */ 2242 for (ii = start_hw_index; ii <= end_hw_index; ii++) { 2243 temp_stat = 0; 2244 max_stat = 0; 2245 for (inst = 0; inst < resInfo->num_instance; inst++) { 2246 /* read only the specific buffer */ 2247 if (mmu_inst_map & (1 << inst)) { 2248 /* retrieve the sw entries mapped to each hw index*/ 2249 BCM_IF_ERROR_RETURN( 2250 _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid, 2251 ii, &num_sw_entries, sw_idx_arr)); 2252 if (num_sw_entries > resInfo->num_field) { 2253 return BCM_E_INTERNAL; 2254 } 2255 for (loop_idx = 0; loop_idx < num_sw_entries; loop_idx++) { 2256 if (sw_idx_arr[loop_idx] != -1) { 2257 sw_index = sw_idx_arr[loop_idx] + 2258 (inst * entries_per_inst); 2259 temp_stat = resInfo->p_stat[sw_index]; 2260 if (temp_stat > max_stat) { 2261 max_stat = temp_stat; 2262 } 2263 } 2264 } 2265 } 2266 } 2267 COMPILER_64_ADD_32(*pvalue, max_stat); 2268 } 2269 2270 } while (rv == _BCM_BST_RV_RETRY); 2271 2272 bcm_rv = BCM_E_NONE; 2273 2274 if (options & BCM_COSQ_STAT_CLEAR) { 2275 int need_hw_stat_clear = 1; 2276 int mode = bst_info->track_mode; 2277 2278 sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER); 2279 if ((mode == 1) && 2280 (bst_info->hw_cor_in_max_use_count == 1)) { 2281 /* no need hw stat clear */ 2282 need_hw_stat_clear = 0; 2283 } 2284 if(need_hw_stat_clear) { 2285 (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer, 2286 gport, start_hw_index, cosq); 2287 } 2288 bcm_rv = bcm_bst_th3_sw_stat_clear(unit, gport, cosq, buffer, bid); 2289 sal_mutex_give(bst_info->bst_reslock); 2290 } 2291 2292 2293 return bcm_rv; 2294 } 2295 2296 /* 2297 * Function: 2298 * bcm_bst_th3_index_resolve 2299 * Purpose: 2300 * Resolve the index range for a specific resource based on gport and cosq. 2301 * Parameters: 2302 * unit - (IN) unit number. 2303 * gport - (IN) gport number. 2304 * cosq - (IN) cosq number. 2305 * bid - (IN) BST stat ID. 2306 * pipe - (OUT) pipe number. 2307 * start_hw_index - (OUT) start of index range. 2308 * end_hw_index - (OUT) end of index range. 2309 * rcb_data, cb_data - (OUT) NOT used. 2310 * bcm_rv - (OUT) error status indicator. 2311 * Returns: 2312 * _BCM_BST_RV_* 2313 */ 2314 2315 _bcm_bst_cb_ret_t 2316 bcm_bst_th3_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2317 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 2318 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 2319 { 2320 int local_port, mmu_lport, mmu_chip_port; 2321 soc_info_t *si = &SOC_INFO(unit); 2322 2323 *bcm_rv = _bcm_th3_cosq_localport_resolve(unit, gport, &local_port); 2324 2325 if (BCM_E_NONE != (*bcm_rv)) { 2326 return _BCM_BST_RV_ERROR; 2327 } 2328 2329 mmu_lport = soc_th3_mmu_local_port_num(unit, local_port); 2330 mmu_chip_port = soc_th3_mmu_chip_port_num(unit, local_port); 2331 *pipe = si->port_pipe[local_port]; 2332 switch (bid) { 2333 case bcmBstStatIdDevice: 2334 *start_hw_index = *end_hw_index = 0; 2335 *bcm_rv = BCM_E_NONE; 2336 return _BCM_BST_RV_OK; 2337 case bcmBstStatIdHeadroomPool: 2338 if(cosq == BCM_COS_INVALID) { 2339 *start_hw_index = 0; 2340 *end_hw_index = _TH3_MMU_NUM_POOL - 1; 2341 *bcm_rv = BCM_E_NONE; 2342 return _BCM_BST_RV_OK; 2343 } 2344 *bcm_rv = _bcm_th3_cosq_ingress_hdrm_pool_get_by_pg(unit, gport, 2345 cosq, start_hw_index); 2346 *end_hw_index = *start_hw_index; 2347 if(*bcm_rv != BCM_E_NONE) { 2348 return _BCM_BST_RV_ERROR; 2349 } 2350 break; 2351 case bcmBstStatIdIngPool: 2352 if(cosq == BCM_COS_INVALID) { 2353 *start_hw_index = 0; 2354 *end_hw_index = _TH3_MMU_NUM_POOL - 1; 2355 *bcm_rv = BCM_E_NONE; 2356 return _BCM_BST_RV_OK; 2357 } 2358 *bcm_rv = _bcm_th3_cosq_ingress_sp_get_by_pg(unit, gport, 2359 cosq, start_hw_index); 2360 *end_hw_index = *start_hw_index; 2361 if(*bcm_rv != BCM_E_NONE) { 2362 return _BCM_BST_RV_ERROR; 2363 } 2364 break; 2365 case bcmBstStatIdPortPool: 2366 *start_hw_index = mmu_lport; 2367 *end_hw_index = mmu_lport; 2368 break; 2369 case bcmBstStatIdPriGroupShared: 2370 case bcmBstStatIdPriGroupHeadroom: 2371 *start_hw_index = mmu_lport; 2372 *end_hw_index = mmu_lport; 2373 break; 2374 case bcmBstStatIdEgrPool: 2375 case bcmBstStatIdEgrMCastPool: 2376 if(_bcm_th3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 2377 end_hw_index)) { 2378 *bcm_rv = BCM_E_PARAM; 2379 return _BCM_BST_RV_ERROR; 2380 } 2381 *bcm_rv = BCM_E_NONE; 2382 return _BCM_BST_RV_OK; 2383 case bcmBstStatIdEgrPortPoolSharedMcast: 2384 if(_bcm_th3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 2385 end_hw_index)) { 2386 *bcm_rv = BCM_E_PARAM; 2387 return _BCM_BST_RV_ERROR; 2388 } 2389 *start_hw_index = mmu_chip_port * _TH3_MMU_NUM_POOL + *start_hw_index; 2390 *end_hw_index = mmu_chip_port * _TH3_MMU_NUM_POOL + *end_hw_index; 2391 break; 2392 case bcmBstStatIdEgrPortPoolSharedUcast: 2393 *start_hw_index = mmu_chip_port; 2394 *end_hw_index = mmu_chip_port; 2395 break; 2396 case bcmBstStatIdUcast: 2397 if (IS_CPU_PORT(unit, local_port)) { 2398 *bcm_rv = BCM_E_PARAM; 2399 return _BCM_BST_RV_ERROR; 2400 } 2401 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2402 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq, 2403 _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE, 2404 &local_port, start_hw_index, NULL); 2405 if (cosq == -1) { 2406 *end_hw_index = *start_hw_index + 2407 si->port_num_uc_cosq[local_port] - 1; 2408 } else { 2409 *end_hw_index = *start_hw_index; 2410 } 2411 } else { 2412 /*cosq ibput passed in {port, cosq} format is treated as MMUQ 2413 * number*/ 2414 if (cosq == -1) { 2415 *start_hw_index = si->port_uc_cosq_base[local_port]; 2416 *end_hw_index = *start_hw_index + 2417 si->port_num_uc_cosq[local_port] - 1; 2418 } else { 2419 *start_hw_index = si->port_uc_cosq_base[local_port] + cosq; 2420 *end_hw_index = *start_hw_index; 2421 } 2422 } 2423 if (*bcm_rv != BCM_E_NONE) { 2424 return _BCM_BST_RV_ERROR; 2425 } 2426 break; 2427 case bcmBstStatIdMcast: 2428 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2429 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq, 2430 _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE, 2431 &local_port, start_hw_index, NULL); 2432 if (cosq == -1) { 2433 *end_hw_index = *start_hw_index + 2434 si->port_num_cosq[local_port] - 1; 2435 } else { 2436 *end_hw_index = *start_hw_index; 2437 } 2438 } else { 2439 /*cosq input passed in {port, cosq} format is treated as MMUQ 2440 * number*/ 2441 if (cosq == -1) { 2442 *start_hw_index = si->port_cosq_base[local_port]; 2443 *end_hw_index = *start_hw_index + 2444 si->port_num_cosq[local_port] - 1; 2445 } else { 2446 *start_hw_index = si->port_cosq_base[local_port] + 2447 (cosq - si->port_num_uc_cosq[local_port]); 2448 *end_hw_index = *start_hw_index; 2449 } 2450 } 2451 if (*bcm_rv != BCM_E_NONE) { 2452 return _BCM_BST_RV_ERROR; 2453 } 2454 break; 2455 case bcmBstStatIdQueueTotal: 2456 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2457 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq, 2458 _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE, 2459 &local_port, start_hw_index, NULL); 2460 if (cosq == -1) { 2461 *end_hw_index = *start_hw_index + _bcm_th3_get_num_ucq(unit) - 1; 2462 } else { 2463 *end_hw_index = *start_hw_index; 2464 } 2465 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2466 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq, 2467 _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE, 2468 &local_port, start_hw_index, NULL); 2469 if (cosq == -1) { 2470 *end_hw_index = *start_hw_index + _bcm_th3_get_num_mcq(unit) - 1; 2471 } else { 2472 *end_hw_index = *start_hw_index; 2473 } 2474 2475 } else { 2476 /*cosq ibput passed in {port, cosq} format is treated as MMUQ 2477 * number*/ 2478 if (cosq == -1) { 2479 if (!IS_CPU_PORT(unit, local_port)) { 2480 *start_hw_index = si->port_uc_cosq_base[local_port]; 2481 *end_hw_index = *start_hw_index + 2482 si->port_num_uc_cosq[local_port] + 2483 si->port_num_cosq[local_port] - 1; 2484 } else { 2485 *start_hw_index = si->port_cosq_base[local_port]; 2486 *end_hw_index = *start_hw_index + 2487 si->port_num_cosq[local_port] - 1; 2488 } 2489 } else { 2490 if (!IS_CPU_PORT(unit, local_port)) { 2491 *start_hw_index = si->port_uc_cosq_base[local_port] 2492 + cosq; 2493 } else { 2494 *start_hw_index = si->port_cosq_base[local_port] + cosq; 2495 } 2496 *end_hw_index = *start_hw_index; 2497 } 2498 } 2499 if (*bcm_rv != BCM_E_NONE) { 2500 return _BCM_BST_RV_ERROR; 2501 } 2502 break; 2503 default: 2504 *bcm_rv = BCM_E_PARAM; 2505 return _BCM_BST_RV_ERROR; 2506 } 2507 *bcm_rv = BCM_E_NONE; 2508 return _BCM_BST_RV_OK; 2509 } 2510 2511 /* 2512 * Function: 2513 * _bcm_th3_bst_profile_read_mem_range 2514 * Purpose: 2515 * Set/Get a specific threshold profile/value memory range in HW for a given resource. 2516 * Parameters: 2517 * unit - (IN) unit number. 2518 * flags - (IN) flags for read or write 2519 * bid - (IN) BST stat ID. 2520 * inst - (IN) inst number (pipe number or ITM number). 2521 * buffer - (OUT) memory buffer 2522 * Returns: 2523 * _BCM_BST_RV_* 2524 */ 2525 2526 STATIC int 2527 _bcm_th3_bst_profile_mem_range(int unit, int flags, bcm_bst_stat_id_t bid, 2528 int inst, uint8 **buffer) 2529 { 2530 _bcm_bst_resource_info_t *resInfo; 2531 soc_mem_t mem = INVALIDm; 2532 int idx_min, idx_max; 2533 2534 if (buffer == NULL) { 2535 return BCM_E_PARAM; 2536 } 2537 2538 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 2539 bid = bcmBstStatIdQueueTotal; 2540 } 2541 resInfo = _BCM_BST_RESOURCE(unit, bid); 2542 if(resInfo == NULL || !(resInfo->valid)) { 2543 return BCM_E_BADID; 2544 } 2545 if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) { 2546 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 2547 mem = resInfo->threshold_mem[inst]; 2548 } else { 2549 mem = resInfo->threshold_mem[0]; 2550 } 2551 } else { 2552 /* this function doesn't support registers. Only memory range */ 2553 return BCM_E_PARAM; 2554 } 2555 2556 if(mem != INVALIDm) { 2557 idx_min = soc_mem_index_min(unit, mem); 2558 idx_max = soc_mem_index_max(unit, mem); 2559 2560 if(flags & BST_OP_GET) { 2561 *buffer = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), 2562 "profile_read_mem_range"); 2563 if (*buffer == NULL) { 2564 return BCM_E_MEMORY; 2565 } 2566 /* Calling function will free up memory */ 2567 BCM_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 2568 idx_min, idx_max, *buffer)); 2569 } else if (flags & BST_OP_SET) { 2570 /* Calling function will free up memory */ 2571 BCM_IF_ERROR_RETURN(soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 2572 idx_min, idx_max, *buffer)); 2573 } 2574 } else { 2575 return BCM_E_PARAM; 2576 } 2577 return BCM_E_NONE; 2578 } 2579 2580 /* 2581 * Function: 2582 * _bcm_th3_bst_profile_op_mem_buffer 2583 * Purpose: 2584 * Set/Get a specific threshold profile/value in buffer for a given memory. 2585 * Parameters: 2586 * unit - (IN) unit number. 2587 * flags - (IN) operation type, i.e. GET or SET. 2588 * bid - (IN) BST stat ID. 2589 * inst - (IN) inst number (pipe number or ITM number). 2590 * sw_index - (IN) memory-entry index 2591 * buffer - (IN) RAM buffer to read/write from/to 2592 * resval - (IN) for SET, (OUT) for GET 2593 * Returns: 2594 * _BCM_BST_RV_* 2595 */ 2596 STATIC int 2597 _bcm_th3_bst_profile_op_mem_buffer(int unit, int flags, bcm_bst_stat_id_t bid, 2598 int inst, int sw_index, uint8 * buffer, uint32 *resval) 2599 { 2600 _bcm_bst_resource_info_t *resInfo; 2601 int num_field, idx_min, idx_max; 2602 soc_mem_t mem = INVALIDm; 2603 soc_field_t field; 2604 int hw_index = sw_index; 2605 uint32 *entry; 2606 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 2607 bid = bcmBstStatIdQueueTotal; 2608 } 2609 resInfo = _BCM_BST_RESOURCE(unit, bid); 2610 if(resInfo == NULL || !(resInfo->valid)) { 2611 return BCM_E_BADID; 2612 } 2613 if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) { 2614 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 2615 mem = resInfo->threshold_mem[inst]; 2616 } else { 2617 mem = resInfo->threshold_mem[0]; 2618 } 2619 } else { 2620 /* This function only supports memory, not registers */ 2621 return BCM_E_PARAM; 2622 } 2623 2624 if(mem != INVALIDm) { 2625 if((field = resInfo->threshold_field) == INVALIDf) { 2626 /* multiple sel field within one mem_entry */ 2627 num_field = resInfo->num_field; 2628 field = resInfo->thd_fields[sw_index % num_field]; 2629 hw_index = sw_index / num_field; 2630 } 2631 /* Sanity check */ 2632 idx_min = soc_mem_index_min(unit, mem); 2633 idx_max = soc_mem_index_max(unit, mem); 2634 if (hw_index < idx_min || hw_index > idx_max) { 2635 return BCM_E_PARAM; 2636 } 2637 2638 /* Get a pointer to the entry in the memory buffer */ 2639 entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, buffer, 2640 hw_index); 2641 if(flags & BST_OP_GET) { 2642 *resval = soc_mem_field32_get(unit, mem, entry, field); 2643 } else if (flags & BST_OP_SET){ 2644 soc_mem_field32_set(unit, mem, entry, field, *resval); 2645 } 2646 2647 } else { 2648 return BCM_E_PARAM; 2649 } 2650 return BCM_E_NONE; 2651 } 2652 2653 2654 /* 2655 * Function: 2656 * _bcm_th3_bst_profile_op 2657 * Purpose: 2658 * Set/Get a specific threshold profile/value in HW for a given resource. 2659 * Parameters: 2660 * unit - (IN) unit number. 2661 * flags - (IN) operation type, i.e. GET or SET. 2662 * bid - (IN) BST stat ID. 2663 * inst - (OUT) inst number (pipe number or ITM number). 2664 * sw_index - (IN) register/memory-entry index 2665 * resval - (IN) for SET, (OUT) for GET 2666 * Returns: 2667 * _BCM_BST_RV_* 2668 */ 2669 2670 STATIC int 2671 _bcm_th3_bst_profile_op(int unit, int flags, bcm_bst_stat_id_t bid, 2672 int inst, int sw_index, uint32 *resval) 2673 { 2674 _bcm_bst_resource_info_t *resInfo; 2675 int i, num_field; 2676 soc_mem_t mem = INVALIDm; 2677 soc_reg_t reg = INVALIDr; 2678 soc_field_t field = INVALIDf; 2679 int hw_index = sw_index; 2680 uint32 entry[SOC_MAX_MEM_WORDS], rval; 2681 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 2682 bid = bcmBstStatIdQueueTotal; 2683 } 2684 resInfo = _BCM_BST_RESOURCE(unit, bid); 2685 if(resInfo == NULL || !(resInfo->valid)) { 2686 return BCM_E_BADID; 2687 } 2688 if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) { 2689 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 2690 mem = resInfo->threshold_mem[inst]; 2691 } else { 2692 mem = resInfo->threshold_mem[0]; 2693 } 2694 } else { 2695 reg = resInfo->threshold_reg[0]; 2696 field = resInfo->threshold_field; 2697 } 2698 2699 if(mem != INVALIDm) { 2700 if((field = resInfo->threshold_field) == INVALIDf) { 2701 /* multiple sel field within one mem_entry */ 2702 num_field = resInfo->num_field; 2703 field = resInfo->thd_fields[sw_index % num_field]; 2704 hw_index = sw_index / num_field; 2705 } 2706 BCM_IF_ERROR_RETURN( 2707 soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, entry)); 2708 if(flags & BST_OP_GET) { 2709 *resval = soc_mem_field32_get(unit, mem, entry, field); 2710 } else if (flags & BST_OP_SET){ 2711 soc_mem_field32_set(unit, mem, entry, field, *resval); 2712 BCM_IF_ERROR_RETURN( 2713 soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, entry)); 2714 } 2715 2716 } else if (reg != INVALIDr) { 2717 2718 if(bid == bcmBstStatIdDevice) { 2719 if(inst == -1) { 2720 for(i = 0; i < NUM_ITM(unit); i++) { 2721 uint32 temp; 2722 inst = i | SOC_REG_ADDR_INSTANCE_MASK; 2723 SOC_IF_ERROR_RETURN( 2724 soc_reg32_get(unit, reg, inst, 2725 hw_index, &rval)); 2726 if(flags & BST_OP_GET) { 2727 temp = soc_reg_field_get(unit, reg, rval, field); 2728 if(temp > *resval) { 2729 *resval = temp; 2730 } 2731 2732 } else if (flags & BST_OP_SET) { 2733 2734 soc_reg_field_set(unit, reg, &rval, field, *resval); 2735 SOC_IF_ERROR_RETURN( 2736 soc_reg32_set(unit, reg, inst, hw_index, rval)); 2737 } 2738 } 2739 } 2740 else { 2741 inst = inst | SOC_REG_ADDR_INSTANCE_MASK; 2742 SOC_IF_ERROR_RETURN( 2743 soc_reg32_get(unit, reg, inst, hw_index, &rval)); 2744 if(flags & BST_OP_GET) { 2745 *resval = soc_reg_field_get(unit, reg, rval, field); 2746 } else if (flags & BST_OP_SET) { 2747 soc_reg_field_set(unit, reg, &rval, field, *resval); 2748 SOC_IF_ERROR_RETURN( 2749 soc_reg32_set(unit, reg, inst, hw_index, rval)); 2750 } 2751 } 2752 } else { 2753 SOC_IF_ERROR_RETURN( 2754 soc_reg32_get(unit, reg, REG_PORT_ANY, hw_index, &rval)); 2755 if(flags & BST_OP_GET) { 2756 *resval = soc_reg_field_get(unit, reg, rval, field); 2757 } else if(flags & BST_OP_SET){ 2758 soc_reg_field_set(unit, reg, &rval, field, *resval); 2759 SOC_IF_ERROR_RETURN( 2760 soc_reg32_set(unit, reg, REG_PORT_ANY, hw_index, rval)); 2761 } 2762 } 2763 } 2764 return BCM_E_NONE; 2765 } 2766 2767 2768 /* Function: 2769 * _bst_th3_cmn_profile_get_hw 2770 * Purpose: 2771 * Get threshold of specified bid from pipe and sw_index for profile_based 2772 * threshold, get threshold from itm and sw_index for non-profile based 2773 * threshold. 2774 * Parameters: 2775 * unit - (IN) unit number. 2776 * pipe - (IN) pipe number. 2777 * itm - (IN) ITM number. 2778 * sw_index - (IN) register/memory-entry index 2779 * bid - (IN) BST stat ID. 2780 * profile - (OUT) pointer to threshold struct. 2781 */ 2782 STATIC int 2783 _bst_th3_cmn_profile_get_hw(int unit, int pipe, int itm, int sw_index, 2784 bcm_bst_stat_id_t bid, 2785 bcm_cosq_bst_profile_t *profile) 2786 { 2787 _bcm_bst_cmn_unit_info_t *bst_info; 2788 _bcm_bst_resource_info_t *resInfo; 2789 uint32 val, rval, reg_id; 2790 soc_reg_t reg; 2791 soc_field_t field; 2792 2793 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 2794 return BCM_E_INIT; 2795 } 2796 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 2797 bid = bcmBstStatIdQueueTotal; 2798 } 2799 resInfo = _BCM_BST_RESOURCE(unit, bid); 2800 if (resInfo == NULL || !resInfo->valid) { 2801 return BCM_E_PARAM; 2802 } 2803 val = 0; 2804 if(!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) { 2805 /* non-profile based threshold, val is # of cells */ 2806 BCM_IF_ERROR_RETURN( 2807 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, itm, sw_index, 2808 &val)); 2809 profile->byte = bst_info->to_byte(unit, val); 2810 } else { 2811 /* profile-based threshold, val is the profile index */ 2812 reg_id = _bcm_bst_th3_profile_reg_id_get(unit, bid, sw_index); 2813 reg = resInfo->profile_reg[reg_id]; 2814 sw_index &= _TH3_BST_QUEUE_TYPE_SHIFT_MASK; 2815 BCM_IF_ERROR_RETURN( 2816 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, pipe, sw_index, 2817 &val)); 2818 field = resInfo->profile_field; 2819 if(reg != INVALIDr) { 2820 SOC_IF_ERROR_RETURN( 2821 soc_reg32_get(unit, reg, REG_PORT_ANY, val, &rval)); 2822 val = soc_reg_field_get(unit, reg, rval, field); 2823 profile->byte = bst_info->to_byte(unit, val); 2824 2825 } else { 2826 return BCM_E_INIT; 2827 } 2828 2829 } 2830 2831 return BCM_E_NONE; 2832 } 2833 2834 /* Function: 2835 * _bst_th3_cmn_profile_set_hw 2836 * Purpose: 2837 * Set threshold of specified bid from pipe and sw_index for profile_based 2838 * thresholds, set threshold from itm and sw_index for non-profile based 2839 * thresholds. 2840 * Parameters: 2841 * unit - (IN) unit number. 2842 * pipe - (IN) pipe number. 2843 * itm - (IN) ITM number. 2844 * sw_index - (IN) register/memory-entry index 2845 * bid - (IN) BST stat ID. 2846 * profile - (IN) pointer to threshold struct. 2847 * p_profile - (OUT) allocated profile index. 2848 */ 2849 2850 /* 2851 * Usage of itm (all BST threshold profile are duplicated except CFAP): 2852 * -1: all ITMs related to the pipe with same value, reg[i] = profile[0] 2853 * 0-1 : ITM num, applicable only for bid = bcmBstStatIdDevice 2854 * _TH3_BST_PROFILE_INIT_FLAG for BST profile init only 2855 */ 2856 2857 STATIC int 2858 _bst_th3_cmn_profile_set_hw(int unit, int pipe, int itm, int sw_index, 2859 bcm_bst_stat_id_t bid, 2860 bcm_cosq_bst_profile_t *profile, 2861 uint32 *p_profile) 2862 { 2863 uint32 cell; 2864 uint32 profile_index, old_profile_index, reg_id; 2865 int inst, inst_offset; 2866 uint64 rval; 2867 uint64 *prval[1]; 2868 _bcm_bst_cmn_unit_info_t *bst_info; 2869 _bcm_bst_resource_info_t *resInfo; 2870 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 2871 return BCM_E_INIT; 2872 } 2873 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 2874 bid = bcmBstStatIdQueueTotal; 2875 } 2876 resInfo = _BCM_BST_RESOURCE(unit, bid); 2877 if(resInfo == NULL || resInfo->valid == 0) { 2878 return BCM_E_INIT; 2879 } 2880 if (profile->byte > bst_info->max_bytes) { 2881 return BCM_E_PARAM; 2882 } 2883 cell = bst_info->to_cell(unit, profile->byte); 2884 inst_offset = (resInfo->index_max + 1) / (resInfo->num_instance); 2885 2886 reg_id = _bcm_bst_th3_profile_reg_id_get(unit, bid, sw_index); 2887 2888 sw_index &= _TH3_BST_QUEUE_TYPE_SHIFT_MASK; 2889 /*update sw thd */ 2890 if(sw_index >= 0) { 2891 if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) { 2892 /* for per-piped thresh, only update the specfic pipe */ 2893 resInfo->p_threshold[sw_index + pipe * inst_offset] = cell; 2894 } else { 2895 /* ITM based threshold */ 2896 if (bid == bcmBstStatIdDevice) { 2897 for(inst = 0; inst < resInfo->num_instance; inst++) { 2898 /*update both ITMs for threhsolds of unique access type */ 2899 resInfo->p_threshold[sw_index + inst * inst_offset] = cell; 2900 } 2901 } else { 2902 /*For trhehsolds in ITM with duplicate access type, upadate only 2903 * ITM 0*/ 2904 resInfo->p_threshold[sw_index] = cell; 2905 } 2906 } 2907 } 2908 if(!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) { 2909 /* non-profile based threshold */ 2910 BCM_IF_ERROR_RETURN( 2911 _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, itm, sw_index, 2912 &cell)); 2913 return BCM_E_NONE; 2914 } 2915 /* add new profile */ 2916 profile_index = old_profile_index = -1; 2917 2918 if (resInfo->profile_r[reg_id]) { 2919 COMPILER_64_ZERO(rval); 2920 soc_reg64_field32_set(unit, resInfo->profile_reg[reg_id], &rval, 2921 resInfo->profile_field, cell); 2922 prval[0] = &rval; 2923 SOC_IF_ERROR_RETURN(soc_profile_reg_add 2924 (unit, resInfo->profile_r[reg_id], 2925 prval, 1, &profile_index)); 2926 } 2927 if(profile_index != -1) 2928 { 2929 /* get old profile ID */ 2930 BCM_IF_ERROR_RETURN( 2931 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, pipe, sw_index, 2932 &old_profile_index)); 2933 2934 if(old_profile_index != profile_index) { 2935 /* attach new profile */ 2936 BCM_IF_ERROR_RETURN( 2937 _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, pipe, sw_index, 2938 &profile_index)); 2939 /* delete old profile */ 2940 if(itm != _TH3_BST_PROFILE_INIT_FLAG) { 2941 if(resInfo->profile_r[reg_id]) { 2942 SOC_IF_ERROR_RETURN 2943 (soc_profile_reg_delete(unit, resInfo->profile_r[reg_id], 2944 old_profile_index)); 2945 } 2946 } 2947 } 2948 if(p_profile) { 2949 *p_profile = profile_index; 2950 } 2951 } 2952 2953 return BCM_E_NONE; 2954 } 2955 2956 /* Function: 2957 * _bst_th3_cmn_profile_set 2958 * Purpose: 2959 * Set threshold of specified bid from gport/cosq/ITM 2960 * Parameters: 2961 * unit - (IN) unit number. 2962 * pipe - (IN) pipe number. 2963 * itm - (IN) ITM number. 2964 * sw_index - (IN) register/memory-entry index 2965 * bid - (IN) BST stat ID. 2966 * profile - (IN) pointer to threshold struct. 2967 */ 2968 /*BST threshold configuration is Unique only for bcmBstStatIdDevice in TH3*/ 2969 int 2970 _bcm_th3_bst_cmn_profile_set (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2971 int buffer, bcm_bst_stat_id_t bid, bcm_cosq_bst_profile_t *profile) 2972 { 2973 _bcm_bst_cmn_unit_info_t *bst_info; 2974 _bcm_bst_cb_ret_t rv; 2975 void *cb_data = NULL; 2976 int bcm_rv, ii, rcb = 0, pipe; 2977 int start_hw_index = 0, end_hw_index = 0; 2978 _bcm_bst_resource_info_t *resInfo; 2979 int sw_idx_loop, num_sw_entries, sw_index; 2980 int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1}; 2981 soc_info_t *si = &SOC_INFO(unit); 2982 int local_port, index; 2983 2984 /* Parameter check */ 2985 if (bid < bcmBstStatIdInvalid || bid >= bcmBstStatIdMaxCount) { 2986 return BCM_E_PARAM; 2987 } 2988 2989 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 2990 return BCM_E_INIT; 2991 } 2992 2993 BCM_IF_ERROR_RETURN( 2994 _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq)); 2995 2996 if (profile == NULL) { 2997 return BCM_E_PARAM; 2998 } 2999 3000 if (bst_info->handlers.resolve_index == NULL) { 3001 return BCM_E_UNAVAIL; 3002 } 3003 3004 do { 3005 rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe, 3006 &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv); 3007 if (bcm_rv) { 3008 return bcm_rv; 3009 } 3010 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 3011 bid = bcmBstStatIdQueueTotal; 3012 } 3013 resInfo = _BCM_BST_RESOURCE(unit, bid); 3014 if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) { 3015 return BCM_E_PARAM; 3016 } 3017 3018 for (ii = start_hw_index; ii <= end_hw_index; ii++) { 3019 BCM_IF_ERROR_RETURN( 3020 _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid, 3021 ii, &num_sw_entries, sw_idx_arr)); 3022 if (num_sw_entries > resInfo->num_field) { 3023 return BCM_E_INTERNAL; 3024 } 3025 for (sw_idx_loop = 0; sw_idx_loop < num_sw_entries; 3026 sw_idx_loop ++) { 3027 sw_index = sw_idx_arr[sw_idx_loop]; 3028 if (sw_index != -1) { 3029 if (bid == bcmBstStatIdQueueTotal) { 3030 BCM_IF_ERROR_RETURN( 3031 _bcm_th3_cosq_localport_resolve(unit, gport, 3032 &local_port)); 3033 if (IS_CPU_PORT(unit, local_port)) { 3034 index = sw_index | 3035 (_BCM_TH3_BST_Q_TYPE_CPU << 3036 _TH3_BST_QUEUE_TYPE_SHIFT); 3037 } else { 3038 if (sw_index < si->port_cosq_base[local_port]) { 3039 /*Unicast queue of port*/ 3040 index = sw_index | 3041 (_BCM_TH3_BST_Q_TYPE_UC << 3042 _TH3_BST_QUEUE_TYPE_SHIFT); 3043 } else { 3044 /*Multicast queue of port*/ 3045 index = sw_index | 3046 (_BCM_TH3_BST_Q_TYPE_MC << 3047 _TH3_BST_QUEUE_TYPE_SHIFT); 3048 } 3049 } 3050 BCM_IF_ERROR_RETURN( 3051 _bst_th3_cmn_profile_set_hw(unit, pipe, buffer, 3052 index, bid, profile, NULL)); 3053 } else { 3054 BCM_IF_ERROR_RETURN( 3055 _bst_th3_cmn_profile_set_hw(unit, pipe, buffer, 3056 sw_index, bid, profile, NULL)); 3057 } 3058 } 3059 } 3060 } 3061 3062 } while (rv == _BCM_BST_RV_RETRY); 3063 return BCM_E_NONE; 3064 } 3065 3066 /* Function: 3067 * _bst_th3_cmn_profile_get 3068 * Purpose: 3069 * Get threshold of specified bid from gport/cosq/ITM 3070 * Parameters: 3071 * unit - (IN) unit number. 3072 * pipe - (IN) pipe number. 3073 * itm - (IN) ITM number. 3074 * sw_index - (IN) register/memory-entry index 3075 * bid - (IN) BST stat ID. 3076 * profile - (OUT) pointer to threshold struct. 3077 */ 3078 int 3079 _bcm_th3_bst_cmn_profile_get (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 3080 int buffer, bcm_bst_stat_id_t bid, bcm_cosq_bst_profile_t *profile) 3081 { 3082 _bcm_bst_cmn_unit_info_t *bst_info; 3083 void *cb_data = NULL; 3084 int bcm_rv, rcb = 0, pipe; 3085 int start_hw_index = 0, end_hw_index = 0; 3086 _bcm_bst_resource_info_t *resInfo; 3087 int sw_idx_loop, num_sw_entries, sw_index; 3088 int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1}; 3089 soc_info_t *si = &SOC_INFO(unit); 3090 int local_port, index; 3091 3092 /* Parameter check */ 3093 if (bid < bcmBstStatIdInvalid || bid >= bcmBstStatIdMaxCount) { 3094 return BCM_E_PARAM; 3095 } 3096 3097 BCM_IF_ERROR_RETURN( 3098 _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq)); 3099 3100 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3101 return BCM_E_INIT; 3102 } 3103 3104 3105 if (profile == NULL) { 3106 return BCM_E_PARAM; 3107 } 3108 3109 if (bst_info->handlers.resolve_index == NULL) { 3110 return BCM_E_UNAVAIL; 3111 } 3112 3113 bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe, 3114 &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv); 3115 if (bcm_rv) { 3116 return bcm_rv; 3117 } 3118 3119 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 3120 bid = bcmBstStatIdQueueTotal; 3121 } 3122 3123 resInfo = _BCM_BST_RESOURCE(unit, bid); 3124 if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) { 3125 return BCM_E_PARAM; 3126 } 3127 BCM_IF_ERROR_RETURN( 3128 _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid, 3129 start_hw_index, &num_sw_entries, sw_idx_arr)); 3130 if (num_sw_entries > resInfo->num_field) { 3131 return BCM_E_INTERNAL; 3132 } 3133 for (sw_idx_loop = 0; sw_idx_loop < num_sw_entries; 3134 sw_idx_loop ++) { 3135 sw_index = sw_idx_arr[sw_idx_loop]; 3136 if (sw_index != -1) { 3137 if (bid == bcmBstStatIdQueueTotal) { 3138 BCM_IF_ERROR_RETURN( 3139 _bcm_th3_cosq_localport_resolve(unit, gport, 3140 &local_port)); 3141 if (IS_CPU_PORT(unit, local_port)) { 3142 index = sw_index | 3143 (_BCM_TH3_BST_Q_TYPE_CPU << 3144 _TH3_BST_QUEUE_TYPE_SHIFT); 3145 } else { 3146 if (sw_index < si->port_cosq_base[local_port]) { 3147 /*Unicast queue of port*/ 3148 index = sw_index | 3149 (_BCM_TH3_BST_Q_TYPE_UC << 3150 _TH3_BST_QUEUE_TYPE_SHIFT); 3151 } else { 3152 /*Multicast queue of port*/ 3153 index = sw_index | 3154 (_BCM_TH3_BST_Q_TYPE_MC << 3155 _TH3_BST_QUEUE_TYPE_SHIFT); 3156 } 3157 } 3158 BCM_IF_ERROR_RETURN( 3159 _bst_th3_cmn_profile_get_hw(unit, pipe, buffer, 3160 index, bid, profile)); 3161 } else { 3162 BCM_IF_ERROR_RETURN( 3163 _bst_th3_cmn_profile_get_hw(unit, pipe, buffer, 3164 sw_index, bid, profile)); 3165 } 3166 /* return after 1st valid get */ 3167 return BCM_E_NONE; 3168 } 3169 } 3170 3171 3172 return BCM_E_NONE; 3173 } 3174 3175 3176 /* Function: 3177 * _bst_th3_profile_init 3178 * Purpose: 3179 * Threshold Profile init. 3180 * unit - (IN) unit number. 3181 */ 3182 3183 STATIC int 3184 _bst_th3_profile_init(int unit) 3185 { 3186 3187 _bcm_bst_cmn_unit_info_t *bst_info; 3188 _bcm_bst_resource_info_t *resInfo; 3189 bcm_bst_stat_id_t bid; 3190 bcm_cosq_bst_profile_t profile; 3191 int i, ei, index_max, wb, inst; 3192 uint32 profile_index; 3193 soc_reg_t p_reg; 3194 int num_reg; 3195 3196 uint8 ** bid_inst_buffer = NULL; 3197 int rv = BCM_E_NONE; 3198 uint16 dev_id; 3199 uint8 rev_id; 3200 3201 soc_cm_get_id(unit, &dev_id, &rev_id); 3202 wb = SOC_WARM_BOOT(unit) ? 1 : 0; 3203 bst_info = _BCM_UNIT_BST_INFO(unit); 3204 profile.byte = bst_info->max_bytes; 3205 3206 _BCM_BST_RESOURCE_ITER(bst_info, bid) { 3207 resInfo = _BCM_BST_RESOURCE(unit, bid); 3208 3209 if (!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) { 3210 continue; 3211 } 3212 if ((bid == bcmBstStatIdUcast) || (bid == bcmBstStatIdMcast)) { 3213 continue; 3214 } 3215 3216 if (wb) { 3217 /* create an array of uint8 * to bring in each memory instance of resInfo 3218 * below */ 3219 bid_inst_buffer = (uint8 **)sal_alloc(resInfo->num_instance * sizeof(uint8 *), 3220 "bid_inst_buffer"); 3221 if (bid_inst_buffer == NULL) { 3222 rv = BCM_E_MEMORY; 3223 goto cleanup; 3224 } 3225 sal_memset(bid_inst_buffer, 0, resInfo->num_instance * sizeof(uint8 *)); 3226 } 3227 if(bid == bcmBstStatIdQueueTotal) { 3228 num_reg = resInfo->num_profile_reg; 3229 } else { 3230 num_reg = 1; 3231 } 3232 /* create profiles */ 3233 resInfo->profile_m = NULL; 3234 for (i = 0; i < _BCM_MAX_PROFILES; i ++) { 3235 resInfo->profile_r[i] = NULL; 3236 } 3237 for(i = 0; i < num_reg; i++) { 3238 p_reg = resInfo->profile_reg[i]; 3239 if (resInfo->profile_mem != INVALIDm) { 3240 /* currently no profile_mem for TH3 BST*/ 3241 rv = BCM_E_INTERNAL; 3242 goto cleanup; 3243 3244 } else if (p_reg != INVALIDr) { 3245 soc_profile_reg_t_init(&resInfo->iprofile_r[i]); 3246 rv = soc_profile_reg_create 3247 (unit, &p_reg, 1, &resInfo->iprofile_r[i]); 3248 if (BCM_FAILURE(rv)) { 3249 goto cleanup; 3250 } 3251 3252 resInfo->profile_r[i] = &resInfo->iprofile_r[i]; 3253 } 3254 3255 /* init profiles reference */ 3256 index_max = (resInfo->index_max + 1) / resInfo->num_instance; 3257 for(inst = 0; inst < resInfo->num_instance; inst++) { 3258 if (dev_id == BCM56983_DEVICE_ID) { 3259 /* For 56983 SKU, check if the bid is per itm or per pipe 3260 so if it is per pipe, skip the invalid pipes 2, 3, 4, 3261 5. For ITM, we skip ITM 1 3262 */ 3263 if (resInfo->num_instance == 8) { 3264 if (inst == 2 || inst == 3 || inst == 4 || inst == 5) { 3265 continue; 3266 } 3267 } else { 3268 if (inst == 1) { 3269 continue; 3270 } 3271 } 3272 } 3273 if (wb) { 3274 /* if the memory range is empty, read memory range to fill 3275 * it in */ 3276 if (bid_inst_buffer[inst] == NULL) { 3277 rv = _bcm_th3_bst_profile_mem_range(unit, BST_OP_GET, bid, inst, 3278 &bid_inst_buffer[inst]); 3279 if (BCM_FAILURE(rv)) { 3280 goto cleanup; 3281 } 3282 } 3283 } 3284 for (ei = 0; ei < index_max; ei ++) { 3285 /* get profile index */ 3286 if (wb) { 3287 /* retrieve profile_index from HW during warmboot*/ 3288 rv = _bcm_th3_bst_profile_op_mem_buffer(unit, BST_OP_GET | BST_OP_THD, 3289 bid, inst, ei, bid_inst_buffer[inst], &profile_index); 3290 3291 if (BCM_FAILURE(rv)) { 3292 goto cleanup; 3293 } 3294 } else if (ei == 0) { 3295 if(bid == bcmBstStatIdQueueTotal) { 3296 rv = _bst_th3_cmn_profile_set_hw 3297 (unit, inst, _TH3_BST_PROFILE_INIT_FLAG, 3298 ei | (i << _TH3_BST_QUEUE_TYPE_SHIFT), 3299 bid, &profile, &profile_index); 3300 if (BCM_FAILURE(rv)) { 3301 goto cleanup; 3302 } 3303 } else { 3304 3305 rv = _bst_th3_cmn_profile_set_hw 3306 (unit, inst, _TH3_BST_PROFILE_INIT_FLAG, 3307 ei, bid, &profile, &profile_index); 3308 if (BCM_FAILURE(rv)) { 3309 goto cleanup; 3310 } 3311 } 3312 /* Continue the above for loop, no cleanup necessary */ 3313 continue; 3314 } 3315 /* add reference */ 3316 if (resInfo->profile_r[i]) { 3317 rv = soc_profile_reg_reference(unit, 3318 resInfo->profile_r[i], profile_index, 1); 3319 if (BCM_FAILURE(rv)) { 3320 goto cleanup; 3321 } 3322 } 3323 /* update sw thd */ 3324 if(i == 0) { 3325 if ((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) || 3326 (bid == bcmBstStatIdDevice)) { 3327 resInfo->p_threshold[ei + inst * index_max] = 3328 bst_info->to_cell(unit, profile.byte); 3329 } else { 3330 resInfo->p_threshold[ei] = 3331 bst_info->to_cell(unit, profile.byte); 3332 } 3333 } 3334 if(profile_index != 0) { 3335 3336 /* attach reference, for performance issues, execute 3337 * only when it differs from HW default*/ 3338 if (wb) { 3339 rv = _bcm_th3_bst_profile_op_mem_buffer(unit, BST_OP_SET, 3340 bid, inst, ei, bid_inst_buffer[inst], &profile_index); 3341 } else { 3342 rv = _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, inst, ei, 3343 &profile_index); 3344 } 3345 if (BCM_FAILURE(rv)) { 3346 goto cleanup; 3347 } 3348 } 3349 } 3350 if (wb) { 3351 /* Write out the memeory buffer to hardware since we're done with 3352 * this instance of the profile */ 3353 if (bid_inst_buffer[inst]) { 3354 rv = _bcm_th3_bst_profile_mem_range(unit, BST_OP_SET, bid, inst, 3355 &bid_inst_buffer[inst]); 3356 if (BCM_FAILURE(rv)) { 3357 goto cleanup; 3358 } 3359 } 3360 } 3361 } 3362 } 3363 cleanup: 3364 if (bid_inst_buffer) { 3365 for (i = 0; i < resInfo->num_instance; ++i) { 3366 if (bid_inst_buffer[i]) { 3367 soc_cm_sfree(unit, bid_inst_buffer[i]); 3368 } 3369 } 3370 3371 sal_free (bid_inst_buffer); 3372 bid_inst_buffer = NULL; 3373 } 3374 if (BCM_FAILURE(rv)) { 3375 return rv; 3376 } 3377 } 3378 3379 return rv; 3380 } 3381 3382 int 3383 bcm_bst_th3_init(int unit) 3384 { 3385 _bcm_bst_cmn_unit_info_t *bst_info; 3386 int bid; 3387 uint32 mode; 3388 3389 bst_info = _BCM_UNIT_BST_INFO(unit); 3390 if (!bst_info) { 3391 return BCM_E_MEMORY; 3392 } 3393 3394 bst_info->to_cell = _bcm_bst_th3_byte_to_cell; 3395 bst_info->to_byte = _bcm_bst_th3_cell_to_byte; 3396 bst_info->control_set = _bcm_th3_bst_control_set; 3397 bst_info->control_get = _bcm_th3_bst_control_get; 3398 bst_info->intr_to_resources = _bcm_bst_th3_intr_to_resources; 3399 bst_info->hw_stat_snapshot = _bcm_bst_th3_sync_hw_snapshot; 3400 bst_info->hw_stat_clear = NULL; /* new function has one more parameter */ 3401 bst_info->intr_enable_set = _bcm_bst_th3_intr_enable_set; 3402 bst_info->pre_sync = NULL; 3403 bst_info->post_sync = NULL; 3404 bst_info->hw_intr_cb = _bcm_th3_set_hw_intr_cb; 3405 bst_info->port_to_mmu_inst_map = _bst_th3_port_to_mmu_inst_map_get; 3406 bst_info->thd_get = NULL; /* new function has one more parameter */ 3407 bst_info->thd_set = NULL; /* new function has one more parameter */ 3408 bst_info->profile_init = _bst_th3_profile_init; 3409 bst_info->hw_sbusdma_desc_init = _bcm_bst_th3_sbusdma_desc_init; 3410 bst_info->hw_sbusdma_desc_deinit = _bcm_bst_th3_sbusdma_desc_deinit; 3411 bst_info->hw_sbusdma_desc_sync = _bcm_bst_th3_sbusdma_desc_sync; 3412 bst_info->max_bytes = bst_info->to_byte(unit, _TH3_BST_THRESHOLD_CELL_MAX); 3413 3414 mode = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1); 3415 if (mode == 1) { 3416 /* bst */ 3417 for (bid = bcmBstStatIdDevice; bid < bcmBstStatIdMaxCount; bid++) { 3418 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast || 3419 ((bid >= bcmBstStatIdRQEQueue) && 3420 ((bid <= bcmBstStatIdUCQueueGroup)))) { 3421 continue; 3422 } 3423 BCM_IF_ERROR_RETURN 3424 (_bcm_th3_bst_resource_init(unit, bid)); 3425 } 3426 3427 } else if (mode == 2) { 3428 BCM_IF_ERROR_RETURN 3429 (_bcm_th3_bst_resource_init(unit, bcmBstStatIdEgrPool)); 3430 BCM_IF_ERROR_RETURN 3431 (_bcm_th3_bst_resource_init(unit, bcmBstStatIdIngPool)); 3432 } 3433 return BCM_E_NONE; 3434 } 3435 3436 3437 STATIC int 3438 _bst_th3_sbusdma_desc_setup(int unit) 3439 { 3440 _bcm_bst_cmn_unit_info_t *bst_info; 3441 _bcm_bst_resource_info_t *resInfo; 3442 _bcm_bst_tbl_ctrl_t *tbl_ctrl; 3443 int blk, bid, mi; 3444 uint8 acc_type; 3445 soc_mem_t mem, base_mem; 3446 soc_reg_t reg; 3447 uint32 size; 3448 uint8 *buff = NULL; 3449 _bcm_bst_tbl_desc_t *desc = NULL; 3450 int stats_per_inst = 0; 3451 int idx_count = 0; 3452 int xpe = 0; 3453 int stat_idx = 0; 3454 int inst = 0; 3455 3456 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3457 return BCM_E_INIT; 3458 } 3459 buff = bst_info->bst_tbl_buf; 3460 bst_tbl_ctrl[unit] = sal_alloc(bcmBstStatIdMaxCount * 3461 sizeof(_bcm_bst_tbl_ctrl_t *), 3462 "bst_tbl_ctrl_p"); 3463 if (bst_tbl_ctrl[unit] == NULL) { 3464 return BCM_E_MEMORY; 3465 } 3466 3467 bst_info->bst_tbl_desc = sal_alloc(bst_info->bst_tbl_num * sizeof(_bcm_bst_tbl_desc_t), 3468 "bst_tbl_desc_p"); 3469 if (bst_info->bst_tbl_desc == NULL) { 3470 return BCM_E_MEMORY; 3471 } 3472 sal_memset(bst_info->bst_tbl_desc, 0, bst_info->bst_tbl_num * sizeof(_bcm_bst_tbl_desc_t)); 3473 desc = bst_info->bst_tbl_desc; 3474 3475 mi = 0; 3476 for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) { 3477 resInfo = _BCM_BST_RESOURCE(unit, bid); 3478 if (resInfo == NULL) { 3479 return BCM_E_PARAM; 3480 } 3481 3482 if (!_BCM_BST_RESOURCE_VALID(resInfo)) { 3483 continue; 3484 } 3485 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 3486 continue; 3487 } 3488 3489 tbl_ctrl = sal_alloc(sizeof(_bcm_bst_tbl_ctrl_t), "bst_tbl_ctrl"); 3490 if (tbl_ctrl == NULL) { 3491 return BCM_E_MEMORY; 3492 } 3493 size = 0; 3494 tbl_ctrl->tindex = bid; 3495 /*BST tables are either per-pipe or per-ITM in TH3*/ 3496 tbl_ctrl->entries = resInfo->num_instance; 3497 tbl_ctrl->buff = buff; 3498 tbl_ctrl->size = 0; 3499 bst_tbl_ctrl[unit][bid] = tbl_ctrl; 3500 3501 base_mem = resInfo->stat_mem[0]; 3502 reg = resInfo->stat_reg[0]; 3503 if (reg != INVALIDr) { 3504 stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance; 3505 for (xpe = 0; xpe < resInfo->num_instance; xpe++) { 3506 if (stats_per_inst) { 3507 inst = xpe ; 3508 stat_idx = 0; 3509 } else { 3510 inst = REG_PORT_ANY; 3511 stat_idx = xpe; 3512 stats_per_inst = 1; 3513 } 3514 desc[mi].reg = reg; 3515 desc[mi].addr = soc_reg_addr_get(unit, reg, inst, stat_idx, 3516 SOC_REG_ADDR_OPTION_NONE, &blk, 3517 &acc_type); 3518 desc[mi].flags = 0; 3519 desc[mi].acc_type = acc_type; 3520 desc[mi].blk = blk; 3521 desc[mi].width = BYTES2WORDS(soc_reg_bytes(unit, reg)); 3522 desc[mi].entries= stats_per_inst; 3523 desc[mi].shift = 8; 3524 size += desc[mi].entries * desc[mi].width * 4; 3525 tbl_ctrl->blk = desc[mi].blk; 3526 mi++; 3527 } 3528 } else if (base_mem != INVALIDm) { 3529 idx_count = 0; 3530 for (inst = 0; inst < resInfo->num_instance; inst++) { 3531 if (resInfo->num_instance == NUM_ITM(unit)) { 3532 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst); 3533 } else { 3534 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst); 3535 } 3536 if (mem == INVALIDm) { 3537 continue; 3538 } 3539 idx_count = soc_mem_index_max(unit, mem) + 1; 3540 desc[mi].mem = mem; 3541 desc[mi].flags = SOC_SBUSDMA_CFG_COUNTER_IS_MEM | SOC_SBUSDMA_CFG_USE_FLAGS; 3542 desc[mi].blk = SOC_MEM_BLOCK_ANY(unit, mem); 3543 desc[mi].addr = soc_mem_addr_get(unit, mem, 3544 0, desc[mi].blk, 0, &acc_type); 3545 desc[mi].acc_type = acc_type; 3546 desc[mi].blk = SOC_BLOCK2SCH(unit, desc[mi].blk); 3547 desc[mi].width = soc_mem_entry_words(unit, mem); 3548 desc[mi].entries = idx_count; 3549 desc[mi].shift = 0; 3550 size += desc[mi].entries * desc[mi].width * 4; 3551 tbl_ctrl->blk = desc[mi].blk; 3552 mi++; 3553 } 3554 } 3555 buff += size; 3556 tbl_ctrl->size += size; 3557 } 3558 3559 return BCM_E_NONE; 3560 } 3561 3562 STATIC int 3563 _bcm_bst_th3_sbusdma_desc_init(int unit) 3564 { 3565 _bcm_bst_cmn_unit_info_t *bst_info; 3566 _bcm_bst_resource_info_t *resInfo; 3567 int bid, mi; 3568 soc_mem_t mem, base_mem; 3569 soc_reg_t reg; 3570 uint32 entries, width, size = 0; 3571 int inst = 0; 3572 int rv = BCM_E_INIT; 3573 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3574 return BCM_E_INIT; 3575 } 3576 mi = 0; 3577 for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) { 3578 resInfo = _BCM_BST_RESOURCE(unit, bid); 3579 if (resInfo == NULL) { 3580 return BCM_E_PARAM; 3581 } 3582 3583 if (!_BCM_BST_RESOURCE_VALID(resInfo)) { 3584 continue; 3585 } 3586 3587 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 3588 continue; 3589 } 3590 base_mem = resInfo->stat_mem[0]; 3591 reg = resInfo->stat_reg[0]; 3592 if (reg != INVALIDr) { 3593 for (inst = 0; inst < resInfo->num_instance; inst++) { 3594 entries = resInfo->num_stat_pp / resInfo->num_instance; 3595 width = BYTES2WORDS(soc_reg_bytes(unit, reg)); 3596 size += entries * width * 4; 3597 mi++; 3598 } 3599 } else if (base_mem != INVALIDm) { 3600 int idx_count = 0; 3601 if (resInfo->num_instance == NUM_ITM(unit)) { 3602 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0); 3603 } else { 3604 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0); 3605 } 3606 if (mem == INVALIDm) { 3607 return BCM_E_PARAM; 3608 } 3609 for (inst = 0; inst < resInfo->num_instance ; inst++) { 3610 if (resInfo->num_instance == NUM_ITM(unit)) { 3611 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0); 3612 } else { 3613 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0); 3614 } 3615 if (mem == INVALIDm) { 3616 continue; 3617 } 3618 idx_count = soc_mem_index_max(unit, mem) + 1; 3619 entries = idx_count; 3620 width = soc_mem_entry_words(unit, mem); 3621 size += entries * width * 4; 3622 mi++; 3623 } 3624 } 3625 } 3626 bst_info->bst_tbl_size = size; 3627 bst_info->bst_tbl_num = mi; 3628 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3629 (BSL_META_U(unit, 3630 "Total bst tbls: %d, Total size: %d\n"), 3631 mi, size)); 3632 bst_tbl_handles[unit] = 0; 3633 if (bst_info->bst_tbl_buf == NULL) { 3634 bst_info->bst_tbl_buf = soc_cm_salloc(unit, size, "bst_tbl_buf"); 3635 if (bst_info->bst_tbl_buf == NULL) { 3636 goto error; 3637 } 3638 } 3639 sal_memset(bst_info->bst_tbl_buf, 0, size); 3640 rv =_bst_th3_sbusdma_desc_setup(unit); 3641 if (rv != SOC_E_NONE) { 3642 goto error; 3643 } 3644 3645 rv = soc_bst_sbusdma_desc_setup(unit); 3646 if (rv != SOC_E_NONE) { 3647 goto error; 3648 } 3649 return BCM_E_NONE; 3650 error: 3651 if (bst_info->bst_tbl_buf) { 3652 soc_cm_sfree(unit, bst_info->bst_tbl_buf); 3653 bst_info->bst_tbl_buf = NULL; 3654 } 3655 if (bst_info->bst_tbl_desc) { 3656 sal_free(bst_info->bst_tbl_desc); 3657 bst_info->bst_tbl_desc = NULL; 3658 } 3659 rv = soc_bst_sbusdma_desc_free(unit); 3660 return rv; 3661 } 3662 3663 STATIC int 3664 _bst_th3_sw_sbusdma_desc_sync(int unit, int bid) 3665 { 3666 _bcm_bst_cmn_unit_info_t *bst_info; 3667 _bcm_bst_resource_info_t *resInfo; 3668 _bcm_bst_tbl_ctrl_t *tbl_ctrl; 3669 int idx, idx_offset = 0, inst_offset = 0; 3670 void *pentry; 3671 uint32 rval, temp_val = 0; 3672 uint8 *buff = NULL; 3673 soc_mem_t mem, base_mem; 3674 soc_reg_t reg; 3675 uint32 width = 0; 3676 bcm_gport_t gport = -1; 3677 bcm_cos_t cosq = -1; 3678 int port = -1; 3679 int j, inst; 3680 int max_idx = 0; 3681 int stats_per_inst = 0; 3682 3683 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3684 sal_mutex_give(bst_info->bst_reslock); 3685 return BCM_E_INIT; 3686 } 3687 if (!bst_tbl_ctrl[unit][bid]) { 3688 sal_mutex_give(bst_info->bst_reslock); 3689 return BCM_E_INIT; 3690 } 3691 tbl_ctrl = bst_tbl_ctrl[unit][bid]; 3692 buff = tbl_ctrl->buff; 3693 resInfo = _BCM_BST_RESOURCE(unit, bid); 3694 if (resInfo == NULL) { 3695 sal_mutex_give(bst_info->bst_reslock); 3696 return BCM_E_PARAM; 3697 } 3698 3699 base_mem = resInfo->stat_mem[0]; 3700 reg = resInfo->stat_reg[0]; 3701 if (reg != INVALIDr) { 3702 inst_offset = 0; 3703 for (idx = 0; idx < resInfo->num_stat_pp; idx++) { 3704 rval = 0; 3705 width = BYTES2WORDS(soc_reg_bytes(unit, reg)); 3706 idx_offset = idx + inst_offset; 3707 sal_memcpy(&rval, buff, width * 4); 3708 temp_val = soc_reg_field_get(unit, reg, rval, resInfo->stat_field); 3709 if (bst_info->track_mode) { 3710 /* BST tracking is in Peak mode. 3711 * Hence store the watermark value only. 3712 */ 3713 if (resInfo->p_stat[idx_offset] < temp_val) { 3714 resInfo->p_stat[idx_offset] = temp_val; 3715 } 3716 } else { 3717 resInfo->p_stat[idx_offset] = temp_val; 3718 } 3719 buff = buff + width * 4; 3720 3721 /* Check if there exists threshold for a resource 3722 * continue if we don't have one */ 3723 if (resInfo->p_threshold == NULL) { 3724 continue; 3725 } 3726 3727 /* coverity[copy_paste_error : FALSE] */ 3728 if (resInfo->p_threshold[idx_offset] && 3729 (resInfo->p_stat[idx_offset] >= 3730 (resInfo->p_threshold[idx_offset] * resInfo->threshold_gran) 3731 )) { 3732 /* Generate SOC EVENT */ 3733 if (bst_info->handlers.reverse_resolve_index) { 3734 /* reverse map the inedx to port/cos pair */ 3735 bst_info->handlers.reverse_resolve_index(unit, bid, 3736 port, idx_offset, 3737 &gport, &cosq); 3738 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER, 3739 bid, gport, cosq); 3740 } 3741 } 3742 3743 } 3744 } else if (base_mem != INVALIDm) { 3745 if (resInfo->num_instance == NUM_ITM(unit)) { 3746 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0); 3747 } else { 3748 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0); 3749 } 3750 3751 if (mem == INVALIDm) { 3752 sal_mutex_give(bst_info->bst_reslock); 3753 return BCM_E_PARAM; 3754 } 3755 stats_per_inst = (resInfo->index_max + 1) / resInfo->num_instance; 3756 max_idx = soc_mem_index_max(unit, mem); 3757 for (inst = 0; inst < resInfo->num_instance; inst++) { 3758 inst_offset = stats_per_inst * inst; 3759 gport = BCM_GPORT_INVALID; 3760 cosq = -1; 3761 if (resInfo->num_instance == NUM_ITM(unit)) { 3762 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst); 3763 } else { 3764 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst); 3765 } 3766 if (mem == INVALIDm) { 3767 continue; 3768 } 3769 3770 for (idx = 0; idx < max_idx; idx++) { 3771 if(resInfo->stat_field != INVALIDf) { 3772 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 3773 buff, idx); 3774 temp_val = soc_mem_field32_get(unit, mem, pentry, 3775 resInfo->stat_field); 3776 idx_offset = idx + inst_offset; 3777 3778 } else { 3779 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 3780 buff, idx); 3781 for(j = 0; j < resInfo->num_field; j++) { 3782 temp_val = soc_mem_field32_get(unit, mem, 3783 pentry, resInfo->stat_fields[j]); 3784 idx_offset = (idx * (resInfo->num_field)) 3785 + inst_offset + j; 3786 } 3787 3788 } 3789 if (bst_info->track_mode) { 3790 /* BST tracking is in Peak mode. 3791 * Hence store the watermark value only. 3792 */ 3793 if (resInfo->p_stat[idx_offset] < temp_val) { 3794 resInfo->p_stat[idx_offset] = temp_val; 3795 } 3796 } else { 3797 resInfo->p_stat[idx_offset] = temp_val; 3798 } 3799 3800 if (resInfo->p_threshold[idx] && 3801 (resInfo->p_stat[idx_offset] >= 3802 (resInfo->p_threshold[idx]) * resInfo->threshold_gran)) { 3803 /* Generate SOC EVENT */ 3804 if (bst_info->handlers.reverse_resolve_index) { 3805 /* reverse map the inedx to port/cos pair */ 3806 bst_info->handlers.reverse_resolve_index(unit, bid, 3807 port, idx, 3808 &gport, &cosq); 3809 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER, 3810 bid, gport, cosq); 3811 3812 } 3813 } 3814 } 3815 buff += tbl_ctrl->size / tbl_ctrl->entries; 3816 } 3817 } 3818 return BCM_E_NONE; 3819 } 3820 3821 3822 3823 STATIC int 3824 _bcm_bst_th3_sbusdma_desc_sync(int unit) 3825 { 3826 _bcm_bst_cmn_unit_info_t *bst_info; 3827 _bcm_bst_resource_info_t *resInfo; 3828 bcm_bst_stat_id_t bid; 3829 int enable = 0; 3830 3831 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3832 return BCM_E_INIT; 3833 } 3834 3835 if (!_BCM_BST_SYNC_THREAD_VALID(bst_info)) { 3836 return BCM_E_NONE; 3837 } 3838 3839 sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER); 3840 3841 if (bst_info->control_get) { 3842 bst_info->control_get(unit, bcmSwitchBstEnable, &enable); 3843 } 3844 3845 if (enable && bst_info->control_set) { 3846 bst_info->control_set(unit, bcmSwitchBstEnable, 0, 3847 _bcmBstThreadOperInternal); 3848 } 3849 3850 BCM_IF_ERROR_RETURN(soc_bst_hw_sbusdma_desc_sync(unit)); 3851 3852 for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) { 3853 resInfo = _BCM_BST_RESOURCE(unit, bid); 3854 if (resInfo == NULL) { 3855 return BCM_E_PARAM; 3856 } 3857 3858 if (!_BCM_BST_RESOURCE_VALID(resInfo)) { 3859 continue; 3860 } 3861 if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) { 3862 continue; 3863 } 3864 3865 BCM_IF_ERROR_RETURN(_bst_th3_sw_sbusdma_desc_sync(unit, bid)); 3866 } 3867 3868 if (enable && bst_info->control_set) { 3869 bst_info->control_set(unit, bcmSwitchBstEnable, enable, 3870 _bcmBstThreadOperInternal); 3871 } 3872 3873 sal_mutex_give(bst_info->bst_reslock); 3874 return BCM_E_NONE; 3875 } 3876 3877 STATIC int 3878 _bcm_bst_th3_sbusdma_desc_deinit(int unit) 3879 { 3880 _bcm_bst_cmn_unit_info_t *bst_info; 3881 int rv = BCM_E_INIT; 3882 3883 if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) { 3884 return BCM_E_INIT; 3885 } 3886 3887 if (bst_info->bst_tbl_buf) { 3888 soc_cm_sfree(unit, bst_info->bst_tbl_buf); 3889 bst_info->bst_tbl_buf = NULL; 3890 } 3891 if (bst_info->bst_tbl_desc) { 3892 sal_free(bst_info->bst_tbl_desc); 3893 bst_info->bst_tbl_desc = NULL; 3894 } 3895 3896 rv = soc_bst_sbusdma_desc_free(unit); 3897 if (rv != BCM_E_NONE) { 3898 return rv; 3899 } 3900 3901 return BCM_E_NONE; 3902 } 3903 3904 /* Function: 3905 * _bcm_bst_th3_retrive_port_cosq_from_voq 3906 * Purpose: 3907 * Retrieve gport/cosq from chip_queue_number. 3908 * Used for decoding BST trigger information for notifying users. 3909 * unit - (IN) unit number. 3910 * voq - (IN) Chip global VOQ number. 3911 * gport - (OUT) gport corresponding to input VOQ. 3912 * cosq - (OUT) cosq corresponding to input VOQ. 3913 */ 3914 STATIC int 3915 _bcm_bst_th3_retrive_port_cosq_from_voq (int unit, int voq, bcm_gport_t *gport, 3916 bcm_cos_t *cosq) 3917 { 3918 soc_info_t *si = &SOC_INFO(unit); 3919 int max_voq, port; 3920 int port_q_base, port_num_q; 3921 3922 if (gport == NULL || cosq == NULL) { 3923 return BCM_E_PARAM; 3924 } 3925 max_voq = si->port_uc_cosq_base[SOC_TH3_MAX_NUM_PORTS - 1] + 3926 SOC_TH3_NUM_GP_QUEUES; 3927 if (voq >= max_voq) { 3928 return BCM_E_INTERNAL; 3929 } 3930 /* Iterate through all ports to retrieve cosq_base and determine port, 3931 * cosq*/ 3932 PBMP_ALL_ITER(unit, port) { 3933 if (IS_CPU_PORT(unit, port)) { 3934 port_q_base = si->port_cosq_base[port]; 3935 } else { 3936 port_q_base = si->port_uc_cosq_base[port]; 3937 } 3938 port_num_q = si->port_num_uc_cosq[port] + si->port_num_cosq[port]; 3939 if ((voq >= port_q_base) && (voq < port_q_base + port_num_q)) { 3940 *gport = port; 3941 *cosq = voq - port_q_base; 3942 break; 3943 } 3944 } 3945 return BCM_E_NONE; 3946 } 3947 3948 /* Function: 3949 * _bcm_th3_cosq_bst_map_resource_to_gport_cos 3950 * Purpose: 3951 * Retrieve gport/cosq from BST SW index for a resource. 3952 * Used for decoding BST trigger information for notifying users. 3953 * unit - (IN) unit number. 3954 * bid - (IN) BST stat id. 3955 * port - (IN) Unused (retained to maintain consistency). 3956 * index - (IN) SW index for which stat > 0. 3957 * gport - (OUT) gport corresponding to input VOQ. 3958 * cosq - (OUT) cosq corresponding to input VOQ. 3959 */ 3960 3961 int 3962 _bcm_th3_cosq_bst_map_resource_to_gport_cos(int unit, 3963 bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport, 3964 bcm_cos_t *cosq) 3965 { 3966 soc_info_t *si = &SOC_INFO(unit); 3967 _bcm_bst_resource_info_t *pres = NULL; 3968 int phy_port = 0; 3969 int mmu_port = 0; 3970 int inst = 0; 3971 int mmu_port_base = 0; 3972 int stats_per_inst = 1; 3973 int pipe, mmu_chip_port, mmu_global_port; 3974 3975 if (bid >= bcmBstStatIdMaxCount) { 3976 LOG_INFO(BSL_LS_BCM_COSQ, 3977 (BSL_META_U(unit, 3978 "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"), 3979 unit, bid)); 3980 return BCM_E_NONE; 3981 } 3982 3983 pres = _BCM_BST_RESOURCE(unit, bid); 3984 stats_per_inst = (pres->num_stat_pp) / (pres->num_instance); 3985 inst = index / stats_per_inst; 3986 mmu_port_base = inst * SOC_TH3_MMU_PORT_STRIDE; 3987 index %= stats_per_inst; 3988 3989 switch (bid) { 3990 case bcmBstStatIdDevice: 3991 *gport = -1; 3992 *cosq = BCM_COS_INVALID; 3993 break; 3994 3995 case bcmBstStatIdIngPool: 3996 case bcmBstStatIdEgrPool: 3997 case bcmBstStatIdEgrMCastPool: 3998 *gport = -1; 3999 *cosq = index % _TH_MMU_NUM_POOL; 4000 break; 4001 4002 case bcmBstStatIdPortPool: 4003 /* Per pipe memory indexed by Local MMU port number*/ 4004 mmu_port= index/_TH_MMU_NUM_POOL; 4005 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 4006 *gport = si->port_p2l_mapping[phy_port]; 4007 *cosq = index % _TH_MMU_NUM_POOL; 4008 break; 4009 4010 case bcmBstStatIdPriGroupHeadroom: 4011 case bcmBstStatIdPriGroupShared: 4012 /* Per pipe memory indexed by Local MMU port number*/ 4013 mmu_port = index/_TH_MMU_NUM_PG; 4014 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 4015 *gport = si->port_p2l_mapping[phy_port]; 4016 *cosq = index % _TH_MMU_NUM_PG; 4017 break; 4018 4019 case bcmBstStatIdUcast: 4020 case bcmBstStatIdMcast: 4021 case bcmBstStatIdQueueTotal: 4022 /* Indexed based on chip_queue_number */ 4023 /* Iterate through all ports to retrieve cosq_base and determine port, 4024 * cosq*/ 4025 _bcm_bst_th3_retrive_port_cosq_from_voq(unit, index, gport, cosq); 4026 break; 4027 case bcmBstStatIdEgrPortPoolSharedUcast: 4028 case bcmBstStatIdEgrPortPoolSharedMcast: 4029 /* Per pipe memory indexed by MMU chip port number*/ 4030 mmu_chip_port = index/_TH_MMU_NUM_POOL; 4031 mmu_port = mmu_chip_port % 20; /*pipe offset for chip port number*/ 4032 pipe = index / (20 * _TH_MMU_NUM_POOL); 4033 mmu_global_port = mmu_port + (pipe * SOC_TH3_MMU_PORT_STRIDE); 4034 phy_port = si->port_m2p_mapping[mmu_global_port]; 4035 *gport = si->port_p2l_mapping[phy_port]; 4036 *cosq = index % _TH_MMU_NUM_POOL; 4037 break; 4038 default: 4039 break; 4040 } 4041 4042 return BCM_E_NONE; 4043 } 4044 4045 #endif 4046