tcb.c (90263B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: tcb.c 8 * Purpose: Handle TH2 specific tcb APIs 9 */ 10 11 #include <shared/bsl.h> 12 #include <bcm/error.h> 13 #include <soc/drv.h> 14 #include <bcm/cosq.h> 15 #include <soc/profile_mem.h> 16 #include <soc/tomahawk.h> 17 #include <soc/tomahawk2.h> 18 19 #include <bcm_int/esw_dispatch.h> 20 #include <bcm_int/esw/virtual.h> 21 #include <bcm_int/esw/tomahawk.h> 22 23 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 24 #include <bcm_int/esw/tcb.h> 25 #endif 26 27 28 #define _BCM_TH2_NUM_UCAST_QUEUE_PER_PORT 10 29 30 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 31 32 STATIC soc_field_t _bcm_cosq_tcb_threshold_profile_map_fields[] = { 33 QUEUE_0f, 34 QUEUE_1f, 35 QUEUE_2f, 36 QUEUE_3f, 37 QUEUE_4f, 38 QUEUE_5f, 39 QUEUE_6f, 40 QUEUE_7f, 41 QUEUE_8f, 42 QUEUE_9f 43 }; 44 45 STATIC soc_field_t _bcm_th2_cosq_tcb_freeze_fields[] = { 46 TCB_FREEZE_XPE_RAf, 47 TCB_FREEZE_XPE_RBf, 48 TCB_FREEZE_XPE_SAf, 49 TCB_FREEZE_XPE_SBf 50 }; 51 52 STATIC int _bcm_th2_cosq_tcb_ucq_offset[] = {0, 708, 0, 708}; 53 STATIC int _bcm_th2_cosq_tcb_ing_port_offset[] = {0, 0, 64, 64}; 54 STATIC int _bcm_th2_cosq_tcb_egr_port_offset[] = {0, 64, 0, 64}; 55 STATIC int _bcm_th2_cosq_tcb_egr_mmu_port_offset[] = {0, 34, 0, 34}; 56 57 58 STATIC _bcm_cosq_tcb_pipe_port_tab_t _bcm_th2_cosq_tcb_pipe_table[] = { 59 /* tcb 0*/ 60 {_TCB_PIPE0 | _TCB_PIPE3, {0, 3}, _TCB_PIPE0 | _TCB_PIPE1, {0, 1}, 61 "0,3", "0,1", "1-33,102-134", "1-33,34-66", ""}, 62 /* tcb 1*/ 63 {_TCB_PIPE0 | _TCB_PIPE3, {0, 3}, _TCB_PIPE2 | _TCB_PIPE3, {2, 3}, 64 "0,3", "2,3", "1-33,102-134", "68-100,102-134", ""}, 65 /* tcb 2*/ 66 {_TCB_PIPE1 | _TCB_PIPE2, {1, 2}, _TCB_PIPE0 | _TCB_PIPE1, {0, 1}, 67 "1,2", "0,1", "34-66,68-100", "1-33,34-66", ""}, 68 /* tcb 3*/ 69 {_TCB_PIPE1 | _TCB_PIPE2, {1, 2}, _TCB_PIPE2 | _TCB_PIPE3, {2, 3}, 70 "1,2", "2,3", "34-66,68-100", "68-100,102-134", ""} 71 }; 72 73 STATIC int _bcm_th2_cosq_tcb_ext_frz_offset[] = {0, 2, 1, 3}; 74 75 /* Number of COSQs configured for this unit */ 76 #define _TH2_NUM_PROFILE_COS 10 77 78 #define _BCM_TH2_TCB_MAX_NUM 4 79 #define _BCM_TH2_TCB_PROFILE_MAX_NUM 8 80 81 #define _BCM_TH2_TCB_THRESHOLD_MAX 0xffff 82 83 #define _MMU_CELLS_TO_BYTES(cells, cell_bytes) cells * cell_bytes 84 #define _MMU_BYTES_TO_CELLS(bytes, cell_bytes) (bytes + (cell_bytes - 1)) \ 85 / cell_bytes 86 87 /* 88 * timer = (pre_freeze_capture_time * frequency) /10; 89 * The algorithm above would cause a max deviation of 9 (10-1) 90 */ 91 #define _TCB_PRE_FREEZE_CAP_TIME_TO_TIMER(u, _pre_freeze_capture_time) \ 92 (((_pre_freeze_capture_time) * (SOC_INFO(u).frequency)) / _TCB_CAP_TIM_FACTOR) 93 /* 94 * pre_freeze_capture_time = (timer * 10) /frequency; 95 * Adding a max deviation of 9 (10-1), while calculating the pre-freeze capture time 96 */ 97 #define _TCB_TIMER_TO_PRE_FREEZE_CAP_TIME(u, _timer) \ 98 (((_timer) * _TCB_CAP_TIM_FACTOR + _TCB_CAP_TIM_MAX_DEVIATION) / (SOC_INFO(u).frequency)) 99 100 /* 101 * timer = (pre_freeze_capture_time * frequency) /10; 102 * The algorithm above would cause a max deviation of 9 (10-1) 103 */ 104 #define _TCB_PRE_FREEZE_CAP_TIME_TO_TIMER(u, _pre_freeze_capture_time) \ 105 (((_pre_freeze_capture_time) * (SOC_INFO(u).frequency)) / _TCB_CAP_TIM_FACTOR) 106 /* 107 * pre_freeze_capture_time = (timer * 10) /frequency; 108 * Adding a max deviation of 9 (10-1), while calculating the pre-freeze capture time 109 */ 110 #define _TCB_TIMER_TO_PRE_FREEZE_CAP_TIME(u, _timer) \ 111 (((_timer) * _TCB_CAP_TIM_FACTOR + _TCB_CAP_TIM_MAX_DEVIATION) / (SOC_INFO(u).frequency)) 112 113 #ifdef BCM_WARM_BOOT_SUPPORT 114 int 115 bcm_th2_cosq_tcb_reinit(int unit) 116 { 117 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 118 _bcm_cosq_tcb_info_t *tcb_config; 119 int i, j, k, n, enable, index, start_threshold, stop_threshold; 120 uint64 rval64; 121 soc_mem_t profile_mem; 122 soc_field_t field; 123 124 tcb_unit_info = TCB_UNIT_CONTROL(unit); 125 TCB_INIT(unit); 126 127 for (i = 0; i < _BCM_TH2_TCB_MAX_NUM; i++) { 128 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_CONFIGr, i, 0, &rval64)); 129 enable = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, TCB_ENABLEf); 130 if (enable) { 131 tcb_unit_info->tcb_enabled_bmp |= 1 << i; 132 } 133 134 profile_mem = SOC_MEM_UNIQUE_ACC(unit, TCB_THRESHOLD_PROFILE_MAPm)[i]; 135 tcb_config = tcb_unit_info->tcb_info[i]; 136 SHR_BITSET(tcb_config->profile_bmp, 0); 137 138 for (n = 1; n < _BCM_TH2_TCB_PROFILE_MAX_NUM; n++) { 139 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_THRESHOLD_PROFILEr, i, 140 n, &rval64)); 141 start_threshold = soc_reg_field_get(unit, TCB_THRESHOLD_PROFILEr, 142 rval64, CAPTURE_START_THRESHOLDf); 143 stop_threshold = soc_reg_field_get(unit, TCB_THRESHOLD_PROFILEr, 144 rval64, CAPTURE_END_THRESHOLDf); 145 if (start_threshold != 0 || stop_threshold != 0) { 146 SHR_BITSET(tcb_config->profile_bmp, n); 147 } 148 149 } 150 for (j = 0; j < soc_mem_index_count(unit, profile_mem); j++) { 151 BCM_IF_ERROR_RETURN (soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, 152 j, &rval64)); 153 for (k = 0; k < _TH2_NUM_PROFILE_COS; k++) { 154 field = _bcm_cosq_tcb_threshold_profile_map_fields[k]; 155 index = soc_mem_field32_get(unit,TCB_THRESHOLD_PROFILE_MAPm, 156 &rval64, field); 157 for (n = 0; n < _BCM_TH2_TCB_PROFILE_MAX_NUM; n++) { 158 if (index == n) { 159 if(SHR_BITGET(tcb_config->profile_bmp, n)) { 160 tcb_config->profile_ref_count[n]++; 161 } 162 } 163 } 164 } 165 } 166 } 167 168 return BCM_E_NONE; 169 } 170 #endif 171 172 /* 173 * Function: 174 * _bcm_th2_cosq_tcb_current_phase_get 175 * Purpose: 176 * Get tcb buffer running status. 177 * Parameters: 178 * unit - (IN) BCM device number. 179 * buffer_id - (IN) TCB buffer id. 180 * status - (OUT) TCB buffer status. 181 * Returns: 182 * BCM_E_XXX 183 */ 184 STATIC int 185 _bcm_th2_cosq_tcb_current_phase_get(int unit, 186 bcm_cosq_buffer_id_t buffer_id, int *status) 187 { 188 uint32 rval; 189 190 LOG_INFO(BSL_LS_BCM_COSQ, 191 (BSL_META_U(unit, 192 "tcb_current_phase_get: unit %d, buffer_id %d\n"), 193 unit, buffer_id)); 194 195 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, TCB_CURRENT_PHASEr, buffer_id, 0, &rval)); 196 *status = soc_reg_field_get(unit,TCB_CURRENT_PHASEr, rval, CURRENT_PHASEf); 197 198 return BCM_E_NONE; 199 } 200 201 STATIC int 202 _bcm_th2_cosq_tcb_intr_enable_set(int unit, int enable) 203 { 204 uint32 rval; 205 206 if (SOC_REG_IS_VALID(unit, MMU_XCFG_XPE_CPU_INT_ENr)) { 207 BCM_IF_ERROR_RETURN(READ_MMU_XCFG_XPE_CPU_INT_ENr(unit, &rval)); 208 soc_reg_field_set(unit, MMU_XCFG_XPE_CPU_INT_ENr, &rval, 209 TCB_FREEZE_INT_ENf, enable); 210 BCM_IF_ERROR_RETURN(WRITE_MMU_XCFG_XPE_CPU_INT_ENr(unit, rval)); 211 } 212 return BCM_E_NONE; 213 } 214 215 STATIC int 216 _bcm_th2_cosq_tcb_intr_status_reset(int unit) 217 { 218 uint32 rval; 219 220 BCM_IF_ERROR_RETURN(READ_MMU_XCFG_XPE_CPU_INT_CLEARr(unit, &rval)); 221 soc_reg_field_set(unit, MMU_XCFG_XPE_CPU_INT_CLEARr, &rval, 222 TCB_FREEZE_INT_CLRf, 0); 223 BCM_IF_ERROR_RETURN(WRITE_MMU_XCFG_XPE_CPU_INT_CLEARr(unit, rval)); 224 225 return BCM_E_NONE; 226 } 227 228 STATIC int 229 _bcm_th2_cosq_tcb_hw_event_cb(int unit) 230 { 231 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 232 bcm_cosq_buffer_id_t buffer_id; 233 int status; 234 235 tcb_unit_info = TCB_UNIT_CONTROL(unit); 236 if (!tcb_unit_info) { 237 return 0; 238 } 239 240 _bcm_th2_cosq_tcb_intr_enable_set(unit, 0); 241 _bcm_th2_cosq_tcb_intr_status_reset(unit); 242 243 for (buffer_id = 0; buffer_id < _BCM_TH2_TCB_MAX_NUM; buffer_id++) 244 { 245 /* Go over the enabled TCB to see which is freezed */ 246 if(tcb_unit_info->tcb_enabled_bmp & (1 << buffer_id)) { 247 BCM_IF_ERROR_RETURN( 248 _bcm_th2_cosq_tcb_current_phase_get(unit, buffer_id, &status)); 249 if (_TCB_FROZEN_PHASE == status) { 250 if (tcb_unit_info->tcb_evt_cb) { 251 tcb_unit_info->tcb_evt_cb(unit, buffer_id, 252 tcb_unit_info->tcb_evt_user_data); 253 } 254 } 255 } 256 } 257 258 _bcm_th2_cosq_tcb_intr_enable_set(unit, 1); 259 return BCM_E_NONE; 260 } 261 262 int 263 soc_th2_tcb_set_hw_intr_cb(int unit) 264 { 265 #ifdef BCM_TOMAHAWK2_SUPPORT 266 BCM_IF_ERROR_RETURN( 267 soc_th2_set_tcb_callback(unit, &_bcm_th2_cosq_tcb_hw_event_cb)); 268 #endif 269 return SOC_E_NONE; 270 } 271 272 STATIC int 273 _bcm_th2_cosq_tcb_ext_freeze_set(int unit, 274 bcm_cosq_buffer_id_t buffer_id, int enable) 275 { 276 uint32 rval; 277 soc_field_t field; 278 int idx; 279 280 LOG_INFO(BSL_LS_BCM_COSQ, 281 (BSL_META_U(unit, 282 "tcb_ext_freeze_set: unit %d, buffer_id %d, enable %d\n"), 283 unit, buffer_id, enable)); 284 285 BCM_IF_ERROR_RETURN(READ_MMU_GCFG_TCB_FREEZEr(unit, &rval)); 286 287 if (-1 == buffer_id) { 288 if (enable) { 289 for (idx = 0; idx < _BCM_TH2_TCB_MAX_NUM; idx++) { 290 field = _bcm_th2_cosq_tcb_freeze_fields[idx]; 291 soc_reg_field_set(unit, MMU_GCFG_TCB_FREEZEr, &rval, field, 1); 292 } 293 } else { 294 for (idx = 0; idx < _BCM_TH2_TCB_MAX_NUM; idx++) { 295 field = _bcm_th2_cosq_tcb_freeze_fields[idx]; 296 soc_reg_field_set(unit, MMU_GCFG_TCB_FREEZEr, &rval, field, 0); 297 } 298 } 299 } else { 300 idx = _bcm_th2_cosq_tcb_ext_frz_offset[buffer_id]; 301 field = _bcm_th2_cosq_tcb_freeze_fields[idx]; 302 303 if(enable) { 304 soc_reg_field_set(unit,MMU_GCFG_TCB_FREEZEr, &rval, field, 1); 305 } else { 306 soc_reg_field_set(unit,MMU_GCFG_TCB_FREEZEr, &rval, field, 0); 307 } 308 } 309 BCM_IF_ERROR_RETURN(WRITE_MMU_GCFG_TCB_FREEZEr(unit, rval)); 310 311 return BCM_E_NONE; 312 } 313 314 315 STATIC int 316 _bcm_th2_cosq_tcb_buffer_ready_clear(int unit, bcm_cosq_buffer_id_t buffer_id) 317 { 318 uint32 rval; 319 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, TCB_BUFFER_READYr, buffer_id, 0, &rval)); 320 soc_reg_field_set(unit, TCB_BUFFER_READYr, &rval, BUFFER_READYf, 0); 321 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, TCB_BUFFER_READYr, buffer_id, 0, rval)); 322 323 return BCM_E_NONE; 324 } 325 326 STATIC int 327 _bcm_cosq_tcb_is_enabled(int unit, bcm_cosq_buffer_id_t buffer_id) 328 { 329 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 330 int enabled; 331 332 tcb_unit_info = TCB_UNIT_CONTROL(unit); 333 enabled = tcb_unit_info->tcb_enabled_bmp & (1 << buffer_id); 334 if (0 == enabled) { 335 return FALSE; 336 } else { 337 return TRUE; 338 } 339 } 340 341 342 STATIC int 343 _bcm_th2_cosq_tcb_profile_id_alloc(int unit, 344 bcm_cosq_buffer_id_t buffer_id, int *index) 345 { 346 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 347 int i, profile_count; 348 SHR_BITDCL *bitmap; 349 _bcm_cosq_tcb_info_t *tcb_info; 350 351 tcb_unit_info = TCB_UNIT_CONTROL(unit); 352 353 tcb_info = tcb_unit_info->tcb_info[buffer_id]; 354 bitmap = tcb_info->profile_bmp; 355 profile_count = _BCM_TH2_TCB_PROFILE_MAX_NUM; 356 357 for(i = 0; i < profile_count; i++) { 358 if(!SHR_BITGET(bitmap, i)) { 359 SHR_BITSET(bitmap, i); 360 *index = i; 361 return BCM_E_NONE; 362 } 363 } 364 365 LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 366 "No free profile in TCB %d\n"), 367 buffer_id)); 368 369 return BCM_E_RESOURCE; 370 } 371 372 373 374 STATIC int 375 _bcm_th2_cosq_tcb_buffer_info_get(int unit, 376 bcm_cosq_buffer_id_t buffer_id, 377 int type, int *arg) 378 { 379 uint32 rval; 380 381 LOG_INFO(BSL_LS_BCM_COSQ, 382 (BSL_META_U(unit, 383 "tcb_buffer_info_get: unit %d, buffer_id %d, type %d\n"), 384 unit, buffer_id, type)); 385 386 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, TCB_BUFFER_STATUSr, buffer_id, 0, &rval)); 387 388 switch(type) { 389 case _TCB_BUF_STATUS_WRAPPED: 390 *arg = soc_reg_field_get(unit, TCB_BUFFER_STATUSr, rval, 391 TCB_BUFFER_WRAP_AROUND_FLAGf); 392 break; 393 case _TCB_BUF_STATUS_PTR: 394 *arg = soc_reg_field_get(unit, TCB_BUFFER_STATUSr, rval, 395 TCB_BUFFER_END_PTRf); 396 break; 397 case _TCB_BUF_STATUS_EVT_NUM: 398 *arg = soc_reg_field_get(unit, TCB_BUFFER_STATUSr, rval, 399 EVENT_BUFFER_SIZEf); 400 break; 401 case _TCB_BUF_STATUS_0_USED: 402 *arg = soc_reg_field_get(unit, TCB_BUFFER_STATUSr, rval, 403 TCB_BUFFER_ADDRESS_0_USEDf); 404 break; 405 default: 406 break; 407 } 408 409 return BCM_E_NONE; 410 } 411 412 STATIC int 413 _bcm_th2_cosq_tcb_evt_overflow_count_get(int unit, 414 bcm_cosq_buffer_id_t buffer_id, 415 int *num) 416 { 417 uint32 rval; 418 419 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, TCB_EVENT_BUFFER_OVERFLOW_COUNTERr, 420 buffer_id, 0, &rval)); 421 *num = soc_reg_field_get(unit, TCB_EVENT_BUFFER_OVERFLOW_COUNTERr, 422 rval, OVERFLOW_COUNTERf); 423 424 return BCM_E_NONE; 425 } 426 427 428 STATIC int 429 _bcm_th2_cosq_tcb_buffer_get_rd_num(int unit, 430 bcm_cosq_buffer_id_t buffer_id, int *num) 431 { 432 int wrap_flag, end_idx, add_0_used; 433 434 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 435 _TCB_BUF_STATUS_WRAPPED, &wrap_flag)); 436 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 437 _TCB_BUF_STATUS_PTR, &end_idx)); 438 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 439 _TCB_BUF_STATUS_0_USED, &add_0_used)); 440 441 if (0 == add_0_used) { 442 *num = 0; 443 } else if (0 == wrap_flag) { 444 *num = end_idx + 1; 445 } else { 446 *num = 1024; 447 } 448 449 return BCM_E_NONE; 450 } 451 452 STATIC void 453 _bcm_th2_cosq_tcb_pkt_order_fix(uint8 *pkt_data) 454 { 455 uint32 temp32; 456 int i; 457 458 for (i = 36; i >= 20; i -= 4) { 459 temp32 = *(uint32*)(&pkt_data[i]); 460 *(uint32*)(&pkt_data[i]) = soc_ntohl(*(uint32*)(&pkt_data[36 - i])); 461 *(uint32*)(&pkt_data[36 - i]) = soc_ntohl(temp32); 462 } 463 464 return; 465 } 466 467 int 468 bcm_th2_cosq_tcb_uc_queue_resolve(int unit, bcm_cosq_buffer_id_t buffer_id, int qnum, 469 bcm_gport_t *uc_gport) 470 { 471 int index, pipe, id; 472 bcm_port_t mmu_port, local_port, phy_port, local_mmu_port; 473 soc_info_t *si; 474 475 si = &SOC_INFO(unit); 476 477 index = (qnum) < 708 ? 0 : 1; 478 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_member[index]; 479 id = (qnum - _bcm_th2_cosq_tcb_ucq_offset[pipe]) % 480 _BCM_TH2_NUM_UCAST_QUEUE_PER_PORT; 481 local_mmu_port = (qnum - _bcm_th2_cosq_tcb_ucq_offset[pipe]) / 482 _BCM_TH2_NUM_UCAST_QUEUE_PER_PORT; 483 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + local_mmu_port; 484 phy_port = si->port_m2p_mapping[mmu_port]; 485 local_port = si->port_p2l_mapping[phy_port]; 486 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*uc_gport, local_port, id); 487 488 return BCM_E_NONE; 489 } 490 491 STATIC int 492 _bcm_th2_cosq_tcb_celldata_read(int unit, bcm_cosq_buffer_id_t buffer_id, 493 int num, bcm_cosq_tcb_buffer_t *record_entries) 494 { 495 uint32 mem_wid; 496 soc_mem_t mem; 497 mmu_tcb_buffer_cell_data_upper_entry_t *pud; 498 mmu_tcb_buffer_cell_data_lower_entry_t *pld; 499 uint8 *tcb_md_buf = NULL; 500 int i, j = 0, idx, wrapped; 501 502 LOG_INFO(BSL_LS_BCM_COSQ, 503 (BSL_META_U(unit, 504 "tcb_celldata_read: unit %d, buffer_id %d, num %d\n"), 505 unit, buffer_id, num)); 506 507 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 508 _TCB_BUF_STATUS_PTR, &idx)); 509 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 510 _TCB_BUF_STATUS_WRAPPED, 511 &wrapped)); 512 513 mem_wid = sizeof(uint32) * soc_mem_entry_words(unit, 514 MMU_TCB_BUFFER_CELL_DATA_UPPERm); 515 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_TCB_BUFFER_CELL_DATA_UPPERm)[buffer_id]; 516 517 if (wrapped) { 518 tcb_md_buf = soc_cm_salloc(unit, mem_wid * _BCM_TCB_RD_MAX_NUM, 519 "tcb cell data upper"); 520 if (tcb_md_buf == NULL) { 521 return BCM_E_MEMORY; 522 } 523 524 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, 525 _BCM_TCB_RD_MAX_NUM - 1, tcb_md_buf)); 526 527 for (i = idx + 1, j = 0; j < num; i++, j++) { 528 pud = soc_mem_table_idx_to_pointer(unit, MMU_TCB_BUFFER_CELL_DATA_UPPERm, 529 mmu_tcb_buffer_cell_data_upper_entry_t *, tcb_md_buf, 530 i % _BCM_TCB_RD_MAX_NUM); 531 soc_MMU_TCB_BUFFER_CELL_DATA_UPPERm_field_get(unit, (uint32*)pud, 532 CBIDATAf, (uint32*)(record_entries[j].buf_data)); 533 _bcm_th2_cosq_tcb_pkt_order_fix(record_entries[j].buf_data); 534 } 535 } else { 536 tcb_md_buf = soc_cm_salloc(unit, mem_wid * num, "tcb cell data upper"); 537 if (tcb_md_buf == NULL) { 538 return BCM_E_MEMORY; 539 } 540 541 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, num - 1, 542 tcb_md_buf)); 543 for(i = 0; i < num; i++) { 544 pud = soc_mem_table_idx_to_pointer(unit, MMU_TCB_BUFFER_CELL_DATA_UPPERm, 545 mmu_tcb_buffer_cell_data_upper_entry_t *, tcb_md_buf, i); 546 soc_MMU_TCB_BUFFER_CELL_DATA_UPPERm_field_get(unit, pud, 547 CBIDATAf, (uint32*)(record_entries[i].buf_data)); 548 _bcm_th2_cosq_tcb_pkt_order_fix(record_entries[i].buf_data); 549 } 550 } 551 552 soc_cm_sfree(unit, tcb_md_buf); 553 554 mem_wid = sizeof(uint32) * soc_mem_entry_words(unit, 555 MMU_TCB_BUFFER_CELL_DATA_LOWERm); 556 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_TCB_BUFFER_CELL_DATA_LOWERm)[buffer_id]; 557 558 if (wrapped) { 559 tcb_md_buf = soc_cm_salloc(unit, mem_wid * _BCM_TCB_RD_MAX_NUM, 560 "tcb metadata"); 561 if (tcb_md_buf == NULL) { 562 return BCM_E_MEMORY; 563 } 564 565 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, 566 _BCM_TCB_RD_MAX_NUM - 1, tcb_md_buf)); 567 568 for (i = idx + 1, j = 0; j < num; i++, j++) { 569 pld = soc_mem_table_idx_to_pointer(unit, MMU_TCB_BUFFER_CELL_DATA_LOWERm, 570 mmu_tcb_buffer_cell_data_lower_entry_t *, tcb_md_buf, 571 i % _BCM_TCB_RD_MAX_NUM); 572 soc_MMU_TCB_BUFFER_CELL_DATA_LOWERm_field_get(unit, pld, 573 CBIDATAf, (uint32*)(&(record_entries[j].buf_data[40]))); 574 _bcm_th2_cosq_tcb_pkt_order_fix((uint8*)(&(record_entries[j].buf_data[40]))); 575 } 576 } else { 577 tcb_md_buf = soc_cm_salloc(unit, mem_wid * num, "tcb cell data lower"); 578 if (tcb_md_buf == NULL) { 579 return BCM_E_MEMORY; 580 } 581 582 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, num - 1, 583 tcb_md_buf)); 584 for(i = 0; i < num; i++) { 585 pld = soc_mem_table_idx_to_pointer(unit, MMU_TCB_BUFFER_CELL_DATA_LOWERm, 586 mmu_tcb_buffer_cell_data_lower_entry_t *, tcb_md_buf, i); 587 588 soc_MMU_TCB_BUFFER_CELL_DATA_LOWERm_field_get(unit, pld, 589 CBIDATAf, (uint32*)(&(record_entries[i].buf_data[40]))); 590 _bcm_th2_cosq_tcb_pkt_order_fix((uint8*)(&(record_entries[i].buf_data[40]))); 591 } 592 } 593 594 soc_cm_sfree(unit, tcb_md_buf); 595 return BCM_E_NONE; 596 } 597 598 STATIC int 599 _bcm_th2_cosq_tcb_modport_set(int unit, int gpp, bcm_gport_t *modport) 600 { 601 bcm_module_t mod_in, mod_out; 602 bcm_port_t port_in, port_out; 603 604 port_in = gpp & SOC_MEM_FIF_DGPP_PORT_MASK; 605 mod_in = (gpp & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 606 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 607 BCM_IF_ERROR_RETURN 608 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 609 mod_in, port_in, &mod_out, &port_out)); 610 BCM_GPORT_MODPORT_SET(*modport, mod_out, port_out); 611 612 return BCM_E_NONE; 613 } 614 615 STATIC int 616 _bcm_th2_cosq_tcb_metadata_read(int unit, bcm_cosq_buffer_id_t buffer_id, 617 int num, bcm_cosq_tcb_buffer_t *record_entries) 618 { 619 uint32 mem_wid; 620 soc_mem_t mem; 621 tcb_buffer_metadata_entry_t *pmd; 622 uint8 *tcb_md_buf = NULL; 623 int i, j, idx, wrapped; 624 int dvp, dgpp, sgpp, src_port, dst_port, qnum, depth, cell_bytes; 625 bcm_port_t mmu_port, local_port, phy_port; 626 soc_info_t *si; 627 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 628 bcm_gport_t ingress_gport, egress_gport, dvp_gport; 629 630 LOG_INFO(BSL_LS_BCM_COSQ, 631 (BSL_META_U(unit, 632 "tcb_metadata_read: unit %d, buffer_id %d, num %d\n"), 633 unit, buffer_id, num)); 634 635 si = &SOC_INFO(unit); 636 tcb_unit_info = TCB_UNIT_CONTROL(unit); 637 cell_bytes = tcb_unit_info->cell_bytes; 638 639 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 640 _TCB_BUF_STATUS_PTR, &idx)); 641 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 642 _TCB_BUF_STATUS_WRAPPED, 643 &wrapped)); 644 645 mem_wid = sizeof(uint32) * soc_mem_entry_words(unit, TCB_BUFFER_METADATAm); 646 mem = SOC_MEM_UNIQUE_ACC(unit, TCB_BUFFER_METADATAm)[buffer_id]; 647 648 if (wrapped) { 649 tcb_md_buf = soc_cm_salloc(unit, mem_wid * _BCM_TCB_RD_MAX_NUM, 650 "tcb metadata"); 651 if (tcb_md_buf == NULL) { 652 return BCM_E_MEMORY; 653 } 654 655 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, 656 _BCM_TCB_RD_MAX_NUM - 1, tcb_md_buf)); 657 658 for (i = idx + 1, j = 0; j < num; i++, j++) { 659 pmd = soc_mem_table_idx_to_pointer(unit, TCB_BUFFER_METADATAm, 660 tcb_buffer_metadata_entry_t *, tcb_md_buf, 661 i % _BCM_TCB_RD_MAX_NUM); 662 663 soc_TCB_BUFFER_METADATAm_field_get(unit, pmd, TIMESTAMPf, 664 (uint32*)(&(record_entries[j].timestamp))); 665 666 dvp = soc_TCB_EVENT_BUFFERm_field32_get(unit, pmd, DVPf); 667 _bcm_vp_encode_gport(unit, dvp, &dvp_gport); 668 669 dgpp = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, DGPPf); 670 _bcm_th2_cosq_tcb_modport_set(unit, dgpp, &egress_gport); 671 672 sgpp = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SGPP_SVPf); 673 if (sgpp & _TCB_SGPP_TYPE_MASK) { 674 sgpp &= _TCB_SGPP_MASK; 675 _bcm_th2_cosq_tcb_modport_set(unit, sgpp, &ingress_gport); 676 } else { 677 sgpp &= _TCB_SGPP_MASK; 678 _bcm_vp_encode_gport(unit, sgpp, &ingress_gport); 679 } 680 681 src_port = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SRC_PORTf); 682 if (SOC_IS_TRIDENT3(unit)) { 683 mmu_port = src_port; 684 } else { 685 int index, pipe; 686 687 index = (src_port) < 64 ? 0 : 1; 688 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_member[index]; 689 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + 690 (src_port - _bcm_th2_cosq_tcb_ing_port_offset[pipe]); 691 } 692 phy_port = si->port_m2p_mapping[mmu_port]; 693 local_port = si->port_p2l_mapping[phy_port]; 694 BCM_GPORT_LOCAL_SET(record_entries[j].ingress_gport, local_port); 695 696 qnum = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, QNUMf); 697 BCM_IF_ERROR_RETURN 698 (_bcm_cosq_tcb_uc_queue_resolve(unit, buffer_id, qnum, 699 &record_entries[j].queue)); 700 701 dst_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(record_entries[j].queue); 702 BCM_GPORT_LOCAL_SET(record_entries[j].egress_gport, dst_port); 703 704 depth = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, Q_DEPTHf); 705 record_entries[j].queue_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 706 707 depth = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SRVPOOL_DEPTHf); 708 record_entries[j].service_pool_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 709 } 710 } else { 711 tcb_md_buf = soc_cm_salloc(unit, mem_wid * num, "tcb metadata"); 712 if (tcb_md_buf == NULL) { 713 return BCM_E_MEMORY; 714 } 715 716 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, 717 num - 1, tcb_md_buf)); 718 for(i = 0; i < num; i++) { 719 pmd = soc_mem_table_idx_to_pointer(unit, TCB_BUFFER_METADATAm, 720 tcb_buffer_metadata_entry_t *, tcb_md_buf, i); 721 722 soc_TCB_BUFFER_METADATAm_field_get(unit, pmd, TIMESTAMPf, 723 (uint32*)(&(record_entries[i].timestamp))); 724 725 dvp = soc_TCB_EVENT_BUFFERm_field32_get(unit, pmd, DVPf); 726 _bcm_vp_encode_gport(unit, dvp, &dvp_gport); 727 728 dgpp = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, DGPPf); 729 _bcm_th2_cosq_tcb_modport_set(unit, dgpp, &egress_gport); 730 731 sgpp = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SGPP_SVPf); 732 if (sgpp & _TCB_SGPP_TYPE_MASK) { 733 sgpp &= _TCB_SGPP_MASK; 734 _bcm_th2_cosq_tcb_modport_set(unit, sgpp, &ingress_gport); 735 } else { 736 sgpp &= _TCB_SGPP_MASK; 737 _bcm_vp_encode_gport(unit, sgpp, &ingress_gport); 738 } 739 740 src_port = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SRC_PORTf); 741 if (SOC_IS_TRIDENT3(unit)) { 742 mmu_port = src_port; 743 } else { 744 int index, pipe; 745 746 index = (src_port) < 64 ? 0 : 1; 747 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_member[index]; 748 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + 749 (src_port - _bcm_th2_cosq_tcb_ing_port_offset[pipe]); 750 } 751 phy_port = si->port_m2p_mapping[mmu_port]; 752 local_port = si->port_p2l_mapping[phy_port]; 753 BCM_GPORT_LOCAL_SET(record_entries[i].ingress_gport, local_port); 754 755 qnum = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, QNUMf); 756 BCM_IF_ERROR_RETURN 757 (_bcm_cosq_tcb_uc_queue_resolve(unit, buffer_id, qnum, 758 &record_entries[i].queue)); 759 760 dst_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(record_entries[i].queue); 761 BCM_GPORT_LOCAL_SET(record_entries[i].egress_gport, dst_port); 762 763 depth = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, Q_DEPTHf); 764 record_entries[i].queue_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 765 766 depth = soc_TCB_BUFFER_METADATAm_field32_get(unit, pmd, SRVPOOL_DEPTHf); 767 record_entries[i].service_pool_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 768 } 769 } 770 771 soc_cm_sfree(unit, tcb_md_buf); 772 return BCM_E_NONE; 773 } 774 775 STATIC int 776 _bcm_th2_cosq_tcb_event_buffer_read(int unit, bcm_cosq_buffer_id_t buffer_id, 777 int num, bcm_cosq_tcb_event_t *record_entries) 778 { 779 uint32 mem_wid; 780 tcb_event_buffer_entry_t *ped; 781 uint8 *tcb_evt_buf = NULL; 782 soc_mem_t mem; 783 int idx; 784 int dvp, dgpp, sgpp, src_port, dst_port, qnum; 785 int drop_reason = 0, drop_vector, depth, cell_bytes; 786 bcm_port_t mmu_port, local_port, phy_port; 787 soc_info_t *si; 788 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 789 bcm_gport_t ingress_gport, egress_gport, dvp_gport; 790 791 LOG_INFO(BSL_LS_BCM_COSQ, 792 (BSL_META_U(unit, 793 "tcb_event_buffer_read: unit %d, buffer_id %d, num %d\n"), 794 unit, buffer_id, num)); 795 796 si = &SOC_INFO(unit); 797 tcb_unit_info = TCB_UNIT_CONTROL(unit); 798 cell_bytes = tcb_unit_info->cell_bytes; 799 800 mem_wid = sizeof(uint32) * soc_mem_entry_words(unit, TCB_EVENT_BUFFERm); 801 802 tcb_evt_buf = soc_cm_salloc(unit, num * mem_wid, "tcb event"); 803 804 if (tcb_evt_buf == NULL) { 805 return BCM_E_MEMORY; 806 } 807 808 mem = SOC_MEM_UNIQUE_ACC(unit, TCB_EVENT_BUFFERm)[buffer_id]; 809 SOC_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 0, num - 1, 810 tcb_evt_buf)); 811 812 for (idx = 0; idx < num; idx++) { 813 ped = soc_mem_table_idx_to_pointer 814 (unit, TCB_EVENT_BUFFERm, tcb_event_buffer_entry_t *, 815 tcb_evt_buf, idx); 816 817 soc_TCB_EVENT_BUFFERm_field_get(unit, ped, TIMESTAMPf, 818 (uint32*)(&(record_entries[idx].timestamp))); 819 820 dvp = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, DVPf); 821 _bcm_vp_encode_gport(unit, dvp, &dvp_gport); 822 823 dgpp = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, DGPPf); 824 _bcm_th2_cosq_tcb_modport_set(unit, dgpp, &egress_gport); 825 826 sgpp = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, SGPP_SVPf); 827 if (sgpp & _TCB_SGPP_TYPE_MASK) { 828 sgpp &= _TCB_SGPP_MASK; 829 _bcm_th2_cosq_tcb_modport_set(unit, sgpp, &ingress_gport); 830 } else { 831 sgpp &= _TCB_SGPP_MASK; 832 _bcm_vp_encode_gport(unit, sgpp, &ingress_gport); 833 } 834 835 src_port = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, SRC_PORTf); 836 if (SOC_IS_TRIDENT3(unit)) { 837 mmu_port = src_port; 838 } else { 839 int index, pipe; 840 841 index = (src_port) < 64 ? 0 : 1; 842 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_member[index]; 843 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + 844 (src_port - _bcm_th2_cosq_tcb_ing_port_offset[pipe]); 845 } 846 phy_port = si->port_m2p_mapping[mmu_port]; 847 local_port = si->port_p2l_mapping[phy_port]; 848 BCM_GPORT_LOCAL_SET(record_entries[idx].ingress_gport, local_port); 849 850 qnum = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, QNUMf); 851 BCM_IF_ERROR_RETURN 852 (_bcm_cosq_tcb_uc_queue_resolve(unit, buffer_id, qnum, 853 &record_entries[idx].queue)); 854 855 dst_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(record_entries[idx].queue); 856 BCM_GPORT_LOCAL_SET(record_entries[idx].egress_gport, dst_port); 857 858 depth = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, Q_DEPTHf); 859 record_entries[idx].queue_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 860 861 depth = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, SRVPOOL_DEPTHf); 862 record_entries[idx].service_pool_size = _MMU_CELLS_TO_BYTES(depth, cell_bytes); 863 864 record_entries[idx].color = 865 soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, CNGf); 866 867 drop_vector = soc_TCB_EVENT_BUFFERm_field32_get(unit, ped, 868 DROP_RSN_VECTORf); 869 if (drop_vector & _TCB_EVENT_DROP_REASON_IADMN_MASK || 870 drop_vector & _TCB_EVENT_DROP_REASON_PURGE_MASK) { 871 drop_reason = 1 << _SHR_TCB_TRACK_IADMN_DROP_SHIFT; 872 } 873 if (drop_vector & _TCB_EVENT_DROP_REASON_EADMN_MASK) { 874 drop_reason |= 1 << _SHR_TCB_TRACK_EADMN_DROP_SHIFT; 875 } 876 if (drop_vector & _TCB_EVENT_DROP_REASON_WRED_MASK) { 877 drop_reason |= 1 << _SHR_TCB_TRACK_WRED_DROP_SHIFT; 878 } 879 if (drop_vector & _TCB_EVENT_DROP_REASON_CFAP_MASK) { 880 drop_reason |= 1 << _SHR_TCB_TRACK_CFAP_DROP_SHIFT; 881 } 882 record_entries[idx].drop_reason = drop_reason; 883 } 884 885 soc_cm_sfree(unit, tcb_evt_buf); 886 887 return BCM_E_NONE; 888 889 } 890 891 892 STATIC void 893 _bcm_th2_cosq_tcb_scope_help(int unit) { 894 895 int i; 896 _bcm_cosq_tcb_pipe_port_tab_t tab; 897 898 LOG_INFO(BSL_LS_BCM_COSQ,(BSL_META_U(unit, 899 "=== Scope Parameter is Invalid ===\n"))); 900 LOG_INFO(BSL_LS_BCM_COSQ,(BSL_META_U(unit, 901 "buffer_id\tIng_Port_Range\tEgr_Port_Range\tUcq_Range\n"))); 902 903 for (i = 0; i < _BCM_TH2_TCB_MAX_NUM; i++) { 904 tab = _bcm_th2_cosq_tcb_pipe_table[i]; 905 LOG_INFO(BSL_LS_BCM_COSQ,(BSL_META_U(unit, 906 "%d\t%s\t%s\t%s\n"), 907 i, tab.iport_range, tab.eport_range, 908 tab.ucq_range)); 909 } 910 911 return; 912 } 913 914 /* 915 * Function: 916 * _bcm_th2_cosq_tcb_deinit 917 * Purpose: 918 * Deinitialize all TCB internal structure. 919 * Parameters: 920 * unit - (IN) BCM device number. 921 * Returns: 922 * BCM_E_XXX 923 */ 924 int 925 _bcm_th2_cosq_tcb_deinit(int unit) 926 { 927 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 928 _bcm_cosq_tcb_info_t *tcb_info; 929 int i; 930 931 tcb_unit_info = TCB_UNIT_CONTROL(unit); 932 if (tcb_unit_info == NULL) { 933 return BCM_E_NONE; 934 } 935 936 for (i = 0; i < _BCM_TH2_TCB_MAX_NUM; i++) { 937 if (NULL != tcb_unit_info->tcb_info[i]) { 938 tcb_info = tcb_unit_info->tcb_info[i]; 939 if (NULL != tcb_info->profile_bmp) { 940 sal_free(tcb_info->profile_bmp); 941 tcb_info->profile_bmp = NULL; 942 } 943 sal_free(tcb_unit_info->tcb_info[i]); 944 tcb_unit_info->tcb_info[i] = NULL; 945 } 946 } 947 948 if (NULL != tcb_unit_info->tcb_evt_cb) { 949 tcb_unit_info->tcb_evt_cb = NULL; 950 } 951 952 if (NULL != tcb_unit_info->tcb_evt_user_data) { 953 tcb_unit_info->tcb_evt_user_data = NULL; 954 } 955 956 if (NULL != tcb_unit_info->tcb_reslock) { 957 sal_mutex_destroy(tcb_unit_info->tcb_reslock); 958 tcb_unit_info->tcb_reslock = NULL; 959 } 960 961 sal_free(tcb_unit_info); 962 963 TCB_UNIT_CONTROL(unit) = NULL; 964 965 return BCM_E_NONE; 966 } 967 968 /* 969 * Function: 970 * bcm_th2_cosq_tcb_control_get 971 * Purpose: 972 * Get TCB instance control status. 973 * Parameters: 974 * unit - (IN) BCM device number. 975 * buffer_id - (IN) TCB buffer id. 976 * type - (IN) Control type 977 * arg - (OUT) argument. 978 * Returns: 979 * BCM_E_XXX 980 */ 981 int 982 bcm_th2_cosq_tcb_control_get(int unit, bcm_cosq_buffer_id_t buffer_id, 983 bcm_cosq_tcb_control_t type, int *arg) 984 { 985 int status; 986 987 LOG_INFO(BSL_LS_BCM_COSQ, 988 (BSL_META_U(unit, 989 "tcb_control_get: unit %d, buffer_id %d, type %d\n"), 990 unit, buffer_id, type)); 991 992 TCB_ID_CHECK(buffer_id); 993 if (NULL == arg) { 994 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, "arg is null!\n"))); 995 return BCM_E_PARAM; 996 } 997 998 if (type == bcmCosqTcbControlEnable) { 999 if (_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1000 *arg = 1; 1001 } else { 1002 *arg = 0; 1003 } 1004 } else if (type == bcmCosqTcbControlFreeze) { 1005 if (!_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1006 LOG_INFO(BSL_LS_BCM_COSQ, 1007 (BSL_META_U(unit, 1008 "tcb buffer %d is not enabled\n"), 1009 buffer_id)); 1010 return BCM_E_DISABLED; 1011 } 1012 BCM_IF_ERROR_RETURN( 1013 _bcm_th2_cosq_tcb_current_phase_get(unit, buffer_id, &status)); 1014 if (status == _TCB_FROZEN_PHASE) { 1015 *arg = 1; 1016 } else { 1017 *arg = 0; 1018 } 1019 } else { 1020 LOG_ERROR(BSL_LS_BCM_COSQ, 1021 (BSL_META_U(unit, 1022 "unknown tcb control type %d\n"), 1023 type)); 1024 return BCM_E_PARAM; 1025 } 1026 1027 return BCM_E_NONE; 1028 } 1029 1030 /* 1031 * Function: 1032 * bcm_th2_cosq_tcb_enable 1033 * Purpose: 1034 * Enable or disable a TCB buffer. 1035 * Parameters: 1036 * unit - (IN) BCM device number. 1037 * buffer_id - (IN) TCB buffer id. 1038 * enable - (IN) enable or disable. 1039 * Returns: 1040 * BCM_E_XXX 1041 */ 1042 int 1043 bcm_th2_cosq_tcb_enable(int unit, bcm_cosq_buffer_id_t buffer_id, int enable) 1044 { 1045 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1046 int mask, rv = BCM_E_NONE; 1047 uint64 rval64; 1048 1049 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1050 TCB_ID_CHECK(buffer_id); 1051 mask = 1 << buffer_id; 1052 1053 LOG_INFO(BSL_LS_BCM_COSQ, 1054 (BSL_META_U(unit, 1055 "tcb_enable: unit %d, buffer_id %d, enable %d\n"), 1056 unit, buffer_id, enable)); 1057 1058 if (!(tcb_unit_info->tcb_config_init_bmp & (1 << buffer_id))) { 1059 LOG_INFO(BSL_LS_BCM_COSQ, 1060 (BSL_META_U(unit, 1061 "tcb config of buffer %d is not initialized\n"), 1062 buffer_id)); 1063 return BCM_E_DISABLED; 1064 } 1065 1066 if (enable) { 1067 if (tcb_unit_info->tcb_enabled_bmp & mask) { 1068 /* tcb is already enabled */ 1069 rv = BCM_E_BUSY; 1070 } else { /* enable tcb */ 1071 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_CONFIGr, buffer_id, 0, 1072 &rval64)); 1073 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TCB_ENABLEf, 1); 1074 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, TCB_CONFIGr, buffer_id, 0, 1075 rval64)); 1076 1077 if (tcb_unit_info->tcb_enabled_bmp == 0) { 1078 /* Enable interrupt */ 1079 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_intr_enable_set(unit, 1)); 1080 } 1081 tcb_unit_info->tcb_enabled_bmp |= mask; 1082 } 1083 } else { 1084 if (!(tcb_unit_info->tcb_enabled_bmp & mask)) { 1085 /* tcb is already disabled */ 1086 rv = BCM_E_PARAM; 1087 } else { /* disable tcb */ 1088 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_ext_freeze_set(unit, buffer_id, 0)); 1089 1090 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_CONFIGr, buffer_id, 0, 1091 &rval64)); 1092 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TCB_ENABLEf, 0); 1093 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, TCB_CONFIGr, buffer_id, 0, 1094 rval64)); 1095 1096 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_ready_clear(unit, buffer_id)); 1097 1098 tcb_unit_info->tcb_enabled_bmp &= ~mask; 1099 if (tcb_unit_info->tcb_enabled_bmp == 0) { 1100 /* Disable interrupt */ 1101 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_intr_enable_set(unit, 0)); 1102 } 1103 } 1104 } 1105 1106 return rv; 1107 1108 } 1109 1110 /* 1111 * Function: 1112 * bcm_th2_cosq_tcb_freeze 1113 * Purpose: 1114 * External freeze a TCB buffer. 1115 * Parameters: 1116 * unit - (IN) BCM device number. 1117 * buffer_id - (IN) TCB buffer id. 1118 * enable - (IN) enable or disable. 1119 * Returns: 1120 * BCM_E_XXX 1121 * Notes: 1122 * When buffer_id is -1, this API will freeze all TCB instance at a once. 1123 */ 1124 int 1125 bcm_th2_cosq_tcb_freeze(int unit, bcm_cosq_buffer_id_t buffer_id, int enable) 1126 { 1127 int i; 1128 1129 LOG_INFO(BSL_LS_BCM_COSQ, 1130 (BSL_META_U(unit, 1131 "tcb_freeze: unit %d, buffer_id %d, enable %d\n"), 1132 unit, buffer_id, enable)); 1133 1134 if(-1 == buffer_id) { 1135 int tcb_disable_all = TRUE; 1136 /* freeze all TCB instance */ 1137 for (i = 0; i < _BCM_TH2_TCB_MAX_NUM; i++) { 1138 if (!_bcm_cosq_tcb_is_enabled(unit, i)) { 1139 continue; 1140 } 1141 1142 if (enable) { 1143 BCM_IF_ERROR_RETURN( 1144 _bcm_th2_cosq_tcb_ext_freeze_set(unit, i, 1)); 1145 } else { 1146 BCM_IF_ERROR_RETURN( 1147 _bcm_th2_cosq_tcb_ext_freeze_set(unit, i, 0)); 1148 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_ready_clear(unit, i)); 1149 } 1150 tcb_disable_all = FALSE; 1151 } 1152 1153 if (tcb_disable_all) { 1154 LOG_INFO(BSL_LS_BCM_COSQ, 1155 (BSL_META_U(unit, 1156 "all tcb buffer is disabled, can not freeze\n"))); 1157 return BCM_E_DISABLED; 1158 } 1159 1160 } else { 1161 TCB_ID_CHECK(buffer_id); 1162 1163 if (!_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1164 LOG_INFO(BSL_LS_BCM_COSQ, 1165 (BSL_META_U(unit, 1166 "tcb buffer %d is disabled, can not freeze\n"), 1167 buffer_id)); 1168 return BCM_E_DISABLED; 1169 } 1170 1171 if (0 != enable) { 1172 BCM_IF_ERROR_RETURN( 1173 _bcm_th2_cosq_tcb_ext_freeze_set(unit, buffer_id, 1)); 1174 } else { 1175 BCM_IF_ERROR_RETURN( 1176 _bcm_th2_cosq_tcb_ext_freeze_set(unit, buffer_id, 0)); 1177 BCM_IF_ERROR_RETURN( 1178 _bcm_th2_cosq_tcb_buffer_ready_clear(unit, buffer_id)); 1179 } 1180 } 1181 1182 return BCM_E_NONE; 1183 } 1184 1185 /* 1186 * Function: 1187 * bcm_th2_cosq_tcb_config_set 1188 * Purpose: 1189 * Set TCB instance config attributes. 1190 * Parameters: 1191 * unit - (IN) BCM device number. 1192 * buffer_id - (IN) TCB buffer id. 1193 * config - (IN) TCB config information 1194 * Returns: 1195 * BCM_E_XXX 1196 */ 1197 int 1198 bcm_th2_cosq_tcb_config_set(int unit, bcm_cosq_buffer_id_t buffer_id, 1199 bcm_cosq_tcb_config_t *config) 1200 { 1201 uint64 rval64 = COMPILER_64_INIT(0,0); 1202 int timer; 1203 bcm_port_t local_port; 1204 bcm_gport_t gport; 1205 int mmu_port, phy_port, q_num, pipe, arg = 0, cosq, modid, trunk_id; 1206 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1207 soc_info_t *si; 1208 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1209 1210 LOG_INFO(BSL_LS_BCM_COSQ, 1211 (BSL_META_U(unit, 1212 "tcb_config_set: unit %d, buffer_id %d\n"), 1213 unit, buffer_id)); 1214 1215 TCB_ID_CHECK(buffer_id); 1216 if (NULL == config) { 1217 LOG_ERROR(BSL_LS_BCM_COSQ, 1218 (BSL_META_U(unit, "config is null!\n"))); 1219 return BCM_E_PARAM; 1220 } 1221 1222 if (_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1223 /* tcb can only be configured in idle state */ 1224 LOG_INFO(BSL_LS_BCM_COSQ, 1225 (BSL_META_U(unit, 1226 "tcb buffer %d is enabled\n"), 1227 buffer_id)); 1228 return BCM_E_BUSY; 1229 } 1230 1231 gport = config->gport; 1232 si = &SOC_INFO(unit); 1233 1234 /* Reset default value */ 1235 if ((config->scope_type == bcmCosqTcbScopeMaxCount) && 1236 (config->gport == BCM_GPORT_INVALID) && 1237 (config->cosq == -1) && 1238 (config->trigger_reason == (BCM_COSQ_TCB_INGRESS_ADMIN_DROP | 1239 BCM_COSQ_TCB_EGRESS_ADMIN_DROP | 1240 BCM_COSQ_TCB_CFAP_DROP | 1241 BCM_COSQ_TCB_WRED_DROP)) && 1242 (config->pre_freeze_capture_num == _TCB_CAP_NUM_DEFAULT) && 1243 (config->pre_freeze_capture_time == 1244 _TCB_TIMER_TO_PRE_FREEZE_CAP_TIME(unit, _TCB_CAP_TIM_DEFAULT)) && 1245 (config->pre_sample_probability == _TCB_PRE_SAMP_RATE_DEFAULT + 1) && 1246 (config->post_sample_probability == _TCB_POST_SAMP_RATE_DEFAULT + 1)) { 1247 1248 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, TCB_CONFIGr, buffer_id, 0, rval64)); 1249 /* update TCB instance status */ 1250 if ((tcb_unit_info->tcb_config_init_bmp & (1 << buffer_id))) { 1251 tcb_unit_info->tcb_config_init_bmp &= ~(1 << buffer_id); 1252 } 1253 return BCM_E_NONE; 1254 } 1255 1256 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_CONFIGr, buffer_id, 0, &rval64)); 1257 1258 switch(config->scope_type) { 1259 case bcmCosqTcbScopeUcastQueue: 1260 if (!BCM_GPORT_IS_SET(gport)) { 1261 LOG_INFO(BSL_LS_BCM_COSQ, 1262 (BSL_META_U(unit, 1263 "tcb config set, gport 0x%x is illegal\n"), 1264 gport)); 1265 return BCM_E_PARAM; 1266 } 1267 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1268 LOG_INFO(BSL_LS_BCM_COSQ, 1269 (BSL_META_U(unit, 1270 "tcb config set, gport 0x%x is illegal\n"), 1271 gport)); 1272 return BCM_E_PARAM; 1273 } 1274 1275 BCM_IF_ERROR_RETURN(_bcm_th_cosq_index_resolve(unit, gport, 0, 1276 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, 1277 &cosq, NULL)); 1278 BCM_IF_ERROR_RETURN(_bcm_th_cosq_port_resolve(unit, gport, &modid, 1279 &local_port, &trunk_id, NULL, NULL)); 1280 1281 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 1282 if(!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_bmp), 1283 pipe)) { 1284 _bcm_th2_cosq_tcb_scope_help(unit); 1285 return BCM_E_PARAM; 1286 } 1287 1288 q_num = cosq + _bcm_th2_cosq_tcb_ucq_offset[pipe]; 1289 1290 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITY_TYPEf, 1291 _TCB_SCOPE_UCQ); 1292 arg = q_num; 1293 break; 1294 case bcmCosqTcbScopeIngressPort: 1295 if (BCM_GPORT_IS_SET(gport)){ 1296 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, 1297 &local_port)); 1298 } else if (SOC_PORT_VALID(unit, gport)) { 1299 local_port = gport; 1300 } else { 1301 LOG_INFO(BSL_LS_BCM_COSQ, 1302 (BSL_META_U(unit, 1303 "tcb config set, gport 0x%x is illegal\n"), 1304 gport)); 1305 return BCM_E_PORT; 1306 } 1307 1308 if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port)) { 1309 LOG_INFO(BSL_LS_BCM_COSQ, 1310 (BSL_META_U(unit, 1311 "tcb config set, gport 0x%x is illegal\n"), 1312 gport)); 1313 return BCM_E_PORT; 1314 } 1315 1316 phy_port = si->port_l2p_mapping[local_port]; 1317 mmu_port = si->port_p2m_mapping[phy_port]; 1318 pipe = si->port_pipe[local_port]; 1319 if(!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_bmp), pipe)) { 1320 _bcm_th2_cosq_tcb_scope_help(unit); 1321 return BCM_E_PARAM; 1322 } 1323 1324 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITY_TYPEf, 1325 _TCB_SCOPE_ING_PORT); 1326 arg = mmu_port % SOC_TH_MMU_PORT_STRIDE + 1327 _bcm_th2_cosq_tcb_ing_port_offset[pipe]; 1328 break; 1329 case bcmCosqTcbScopeEgressPort: 1330 if (BCM_GPORT_IS_SET(gport)){ 1331 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, 1332 &local_port)); 1333 } else if (SOC_PORT_VALID(unit, gport)) { 1334 local_port = gport; 1335 } else { 1336 LOG_INFO(BSL_LS_BCM_COSQ, 1337 (BSL_META_U(unit, 1338 "tcb config set, gport 0x%x is illegal\n"), 1339 gport)); 1340 return BCM_E_PORT; 1341 } 1342 1343 if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port)) { 1344 LOG_INFO(BSL_LS_BCM_COSQ, 1345 (BSL_META_U(unit, 1346 "tcb config set, gport 0x%x is illegal\n"), 1347 gport)); 1348 return BCM_E_PORT; 1349 } 1350 1351 phy_port = si->port_l2p_mapping[local_port]; 1352 mmu_port = si->port_p2m_mapping[phy_port]; 1353 pipe = si->port_pipe[local_port]; 1354 if(!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_bmp), pipe)) { 1355 _bcm_th2_cosq_tcb_scope_help(unit); 1356 return BCM_E_PARAM; 1357 } 1358 1359 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITY_TYPEf, 1360 _TCB_SCOPE_EGR_PORT); 1361 arg = mmu_port % SOC_TH_MMU_PORT_STRIDE + _bcm_th2_cosq_tcb_egr_port_offset[pipe]; 1362 break; 1363 case bcmCosqTcbScopeIngressPipe: 1364 if (!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_bmp), config->pipe_id)) { 1365 _bcm_th2_cosq_tcb_scope_help(unit); 1366 return BCM_E_PARAM; 1367 } 1368 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITY_TYPEf, 1369 _TCB_SCOPE_ING_PIPE); 1370 arg = config->pipe_id; 1371 break; 1372 case bcmCosqTcbScopeEgressPipe: 1373 if (!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_bmp), config->pipe_id)) { 1374 _bcm_th2_cosq_tcb_scope_help(unit); 1375 return BCM_E_PARAM; 1376 } 1377 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITY_TYPEf, 1378 _TCB_SCOPE_EGR_PIPE); 1379 arg = config->pipe_id; 1380 break; 1381 default: 1382 LOG_INFO(BSL_LS_BCM_COSQ, 1383 (BSL_META_U(unit, 1384 "tcb config set, scope type %d is illegal\n"), 1385 config->scope_type)); 1386 return BCM_E_PARAM; 1387 } 1388 1389 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, SCOPE_ENTITYf, arg); 1390 1391 if (config->trigger_reason > _TCB_TRIGGER_MAX) { 1392 LOG_INFO(BSL_LS_BCM_COSQ, 1393 (BSL_META_U(unit, 1394 "tcb config set, trigger reason %d is illegal\n"), 1395 config->trigger_reason)); 1396 return BCM_E_PARAM; 1397 } 1398 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TRACK_IADMN_DROPf, 1399 (config->trigger_reason & BCM_COSQ_TCB_INGRESS_ADMIN_DROP) ? 1:0); 1400 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TRACK_EADMN_DROPf, 1401 (config->trigger_reason & BCM_COSQ_TCB_EGRESS_ADMIN_DROP) ? 1:0); 1402 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TRACK_CFAP_DROPf, 1403 (config->trigger_reason & BCM_COSQ_TCB_CFAP_DROP) ? 1:0); 1404 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, TRACK_WRED_DROPf, 1405 (config->trigger_reason & BCM_COSQ_TCB_WRED_DROP) ? 1:0); 1406 1407 /* rev_counter valid range is 2 - 1024 */ 1408 if ((config->pre_freeze_capture_num < _TCB_CAP_NUM_MIN) || 1409 (config->pre_freeze_capture_num > _TCB_CAP_NUM_MAX)) { 1410 LOG_INFO(BSL_LS_BCM_COSQ, 1411 (BSL_META_U(unit, 1412 "tcb config set, pre freeze capture %d is illegal\n"), 1413 config->pre_freeze_capture_num)); 1414 return BCM_E_PARAM; 1415 } 1416 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, REV_COUNTERf, 1417 config->pre_freeze_capture_num); 1418 1419 /* WD_TIMER_PRESET is a counter of clock cycles * 10, a value 1 means 10 clock cycles */ 1420 timer = _TCB_PRE_FREEZE_CAP_TIME_TO_TIMER(unit, config->pre_freeze_capture_time); 1421 if (timer > _TCB_CAP_TIM_MAX) { 1422 LOG_INFO(BSL_LS_BCM_COSQ, 1423 (BSL_META_U(unit, 1424 "tcb config set, pre freeze capture time %d is illegal\n"), 1425 config->pre_freeze_capture_time)); 1426 return BCM_E_PARAM; 1427 } 1428 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, WD_TIMER_PRESETf, 1429 timer); 1430 1431 if (config->post_sample_probability > _TCB_POST_SAMP_RATE_MAX || 1432 config->post_sample_probability <= 0) { 1433 LOG_INFO(BSL_LS_BCM_COSQ, 1434 (BSL_META_U(unit, 1435 "tcb config set, post sample probability %d is illegal\n"), 1436 config->post_sample_probability)); 1437 return BCM_E_PARAM; 1438 } 1439 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, POST_TRIGGER_SAMPLE_RATEf, 1440 config->post_sample_probability - 1); 1441 1442 if (config->pre_sample_probability > _TCB_PRE_SAMP_RATE_MAX || 1443 config->pre_sample_probability <= 0) { 1444 LOG_INFO(BSL_LS_BCM_COSQ, 1445 (BSL_META_U(unit, 1446 "tcb config set, pre sample probability %d is illegal\n"), 1447 config->pre_sample_probability)); 1448 return BCM_E_PARAM; 1449 } 1450 soc_reg64_field32_set(unit, TCB_CONFIGr, &rval64, PRE_TRIGGER_SAMPLE_RATEf, 1451 config->pre_sample_probability - 1); 1452 1453 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, TCB_CONFIGr, buffer_id, 0, rval64)); 1454 1455 /* update TCB instance status */ 1456 if (!(tcb_unit_info->tcb_config_init_bmp & (1 << buffer_id))) { 1457 tcb_unit_info->tcb_config_init_bmp |= (1 << buffer_id); 1458 } 1459 return BCM_E_NONE; 1460 } 1461 1462 /* 1463 * Function: 1464 * bcm_th2_cosq_tcb_config_get 1465 * Purpose: 1466 * Get TCB instance control status. 1467 * Parameters: 1468 * unit - (IN) BCM device number. 1469 * buffer_id - (IN) TCB buffer id. 1470 * config - (OUT) TCB config information 1471 * Returns: 1472 * BCM_E_XXX 1473 */ 1474 int 1475 bcm_th2_cosq_tcb_config_get(int unit, bcm_cosq_buffer_id_t buffer_id, 1476 bcm_cosq_tcb_config_t *config) 1477 { 1478 uint64 rval64; 1479 uint32 trigger, timer; 1480 int type, entity_num, index, pipe, propability; 1481 bcm_port_t mmu_port, phy_port, local_port; 1482 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1483 soc_info_t *si; 1484 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1485 1486 LOG_INFO(BSL_LS_BCM_COSQ, 1487 (BSL_META_U(unit, 1488 "tcb_config_get: unit %d, buffer_id %d\n"), 1489 unit, buffer_id)); 1490 1491 TCB_ID_CHECK(buffer_id); 1492 if (NULL == config) { 1493 LOG_ERROR(BSL_LS_BCM_COSQ, 1494 (BSL_META_U(unit, "config is null!\n"))); 1495 return BCM_E_PARAM; 1496 } 1497 1498 si = &SOC_INFO(unit); 1499 1500 /* check TCB instance status */ 1501 if (!(tcb_unit_info->tcb_config_init_bmp & (1 << buffer_id))) { 1502 config->scope_type = bcmCosqTcbScopeMaxCount; 1503 config->gport = BCM_GPORT_INVALID; 1504 config->cosq = -1; 1505 config->trigger_reason = BCM_COSQ_TCB_INGRESS_ADMIN_DROP | 1506 BCM_COSQ_TCB_EGRESS_ADMIN_DROP | 1507 BCM_COSQ_TCB_CFAP_DROP | 1508 BCM_COSQ_TCB_WRED_DROP; 1509 config->pre_freeze_capture_num = _TCB_CAP_NUM_DEFAULT; 1510 config->pre_freeze_capture_time = 1511 _TCB_TIMER_TO_PRE_FREEZE_CAP_TIME(unit, _TCB_CAP_TIM_DEFAULT); 1512 config->pre_sample_probability = _TCB_PRE_SAMP_RATE_DEFAULT + 1; 1513 config->post_sample_probability = _TCB_POST_SAMP_RATE_DEFAULT + 1; 1514 1515 return BCM_E_NONE; 1516 } 1517 1518 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_CONFIGr, buffer_id, 0, &rval64)); 1519 1520 type = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, SCOPE_ENTITY_TYPEf); 1521 1522 switch(type) { 1523 case _TCB_SCOPE_UCQ: 1524 config->scope_type = bcmCosqTcbScopeUcastQueue; 1525 entity_num = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1526 SCOPE_ENTITYf); 1527 BCM_IF_ERROR_RETURN 1528 (_bcm_cosq_tcb_uc_queue_resolve(unit, buffer_id, entity_num, 1529 &config->gport)); 1530 break; 1531 case _TCB_SCOPE_ING_PORT: 1532 config->scope_type = bcmCosqTcbScopeIngressPort; 1533 entity_num = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1534 SCOPE_ENTITYf); 1535 index = (entity_num) < 64 ? 0 : 1; 1536 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].ipipe_member[index]; 1537 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + 1538 (entity_num - _bcm_th2_cosq_tcb_ing_port_offset[pipe]); 1539 phy_port = si->port_m2p_mapping[mmu_port]; 1540 local_port = si->port_p2l_mapping[phy_port]; 1541 BCM_GPORT_LOCAL_SET(config->gport, local_port); 1542 break; 1543 case _TCB_SCOPE_EGR_PORT: 1544 config->scope_type = bcmCosqTcbScopeEgressPort; 1545 entity_num = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1546 SCOPE_ENTITYf); 1547 index = (entity_num < 64) ? 0 : 1; 1548 pipe = _bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_member[index]; 1549 mmu_port = pipe * SOC_TH_MMU_PORT_STRIDE + 1550 (entity_num - _bcm_th2_cosq_tcb_egr_port_offset[pipe]); 1551 phy_port = si->port_m2p_mapping[mmu_port]; 1552 local_port = si->port_p2l_mapping[phy_port]; 1553 BCM_GPORT_LOCAL_SET(config->gport, local_port); 1554 break; 1555 case _TCB_SCOPE_ING_PIPE: 1556 config->scope_type = bcmCosqTcbScopeIngressPipe; 1557 config->pipe_id = soc_reg64_field32_get( 1558 unit, TCB_CONFIGr, rval64, SCOPE_ENTITYf); 1559 break; 1560 case _TCB_SCOPE_EGR_PIPE: 1561 config->scope_type = bcmCosqTcbScopeEgressPipe; 1562 config->pipe_id = soc_reg64_field32_get( 1563 unit, TCB_CONFIGr, rval64, SCOPE_ENTITYf); 1564 break; 1565 default: 1566 LOG_ERROR(BSL_LS_BCM_COSQ, 1567 (BSL_META_U(unit, 1568 "scope type %d is illegal\n"), 1569 type)); 1570 return BCM_E_PARAM; 1571 } 1572 1573 trigger = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, TRACK_IADMN_DROPf); 1574 config->trigger_reason = trigger << _SHR_TCB_TRACK_IADMN_DROP_SHIFT; 1575 trigger = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, TRACK_EADMN_DROPf); 1576 config->trigger_reason |= trigger << _SHR_TCB_TRACK_EADMN_DROP_SHIFT; 1577 trigger = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, TRACK_CFAP_DROPf); 1578 config->trigger_reason |= trigger << _SHR_TCB_TRACK_CFAP_DROP_SHIFT; 1579 trigger = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, TRACK_WRED_DROPf); 1580 config->trigger_reason |= trigger << _SHR_TCB_TRACK_WRED_DROP_SHIFT; 1581 1582 config->pre_freeze_capture_num = soc_reg64_field32_get(unit, TCB_CONFIGr, 1583 rval64, REV_COUNTERf); 1584 timer = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1585 WD_TIMER_PRESETf); 1586 config->pre_freeze_capture_time = 1587 _TCB_TIMER_TO_PRE_FREEZE_CAP_TIME(unit, timer); 1588 propability = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1589 PRE_TRIGGER_SAMPLE_RATEf); 1590 config->pre_sample_probability = propability + 1; 1591 propability = soc_reg64_field32_get(unit, TCB_CONFIGr, rval64, 1592 POST_TRIGGER_SAMPLE_RATEf); 1593 config->post_sample_probability = propability + 1; 1594 1595 return BCM_E_NONE; 1596 1597 } 1598 1599 /* 1600 * Function: 1601 * bcm_th2_cosq_tcb_gport_threshold_mapping_set 1602 * Purpose: 1603 * Set threshold profile for a UCQ or a port. 1604 * Parameters: 1605 * unit - (IN) unit number 1606 * gport - (IN) Ucq or a port 1607 * cosq - (IN) Reserved field 1608 * buffer_id - (IN) TCB buffer id. 1609 * index - (IN) Threshold profile index 1610 * Returns: 1611 * BCM_E_XXX 1612 * Notes: 1613 * When gport is a port, SDK will attach all Ucqs in this port to one threshold profile. 1614 */ 1615 int 1616 bcm_th2_cosq_tcb_gport_threshold_mapping_set(int unit, 1617 bcm_gport_t gport, bcm_cos_queue_t cosq, 1618 bcm_cosq_buffer_id_t buffer_id, 1619 int index) 1620 { 1621 soc_mem_t profile_mem; 1622 soc_field_t field; 1623 bcm_port_t local_port; 1624 int mmu_port, phy_port, pipe, i, port_index, old_profile; 1625 bcm_cos_t cos; 1626 soc_info_t *si; 1627 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1628 _bcm_cosq_tcb_info_t *tcb_config; 1629 uint32 entry[SOC_MAX_MEM_WORDS]; 1630 1631 si = &SOC_INFO(unit); 1632 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1633 TCB_ID_CHECK(buffer_id); 1634 1635 LOG_INFO(BSL_LS_BCM_COSQ, 1636 (BSL_META_U(unit, 1637 "tcb_threshold_mapping_set: unit %d, gport 0x%x, " 1638 "cosq %d, buffer_id %d, index %d\n"), 1639 unit, gport, cosq, buffer_id, index)); 1640 1641 if (_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1642 /* tcb can only be configured in idle state */ 1643 LOG_INFO(BSL_LS_BCM_COSQ, 1644 (BSL_META_U(unit, 1645 "tcb buffer %d is enabled\n"), 1646 buffer_id)); 1647 return BCM_E_BUSY; 1648 } 1649 1650 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 1651 profile_mem = SOC_MEM_UNIQUE_ACC(unit, TCB_THRESHOLD_PROFILE_MAPm)[buffer_id]; 1652 1653 if (BCM_GPORT_IS_SET(gport)) { 1654 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1655 BCM_IF_ERROR_RETURN(_bcm_th_cosq_index_resolve(unit, gport, 0, 1656 _BCM_TH_COSQ_INDEX_STYLE_COS, &local_port, 1657 &cos, NULL)); 1658 } else if (BCM_GPORT_IS_LOCAL(gport) || BCM_GPORT_IS_MODPORT(gport)) { 1659 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port)); 1660 cos = -1; 1661 } else { 1662 LOG_INFO(BSL_LS_BCM_COSQ, 1663 (BSL_META_U(unit, 1664 "tcb_threshold_mapping_set, gport 0x%x is illegal\n"), 1665 gport)); 1666 return BCM_E_PARAM; 1667 } 1668 } else { 1669 local_port = gport; 1670 cos = -1; 1671 } 1672 1673 if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port) || 1674 IS_LB_PORT(unit, local_port)) { 1675 LOG_INFO(BSL_LS_BCM_COSQ, 1676 (BSL_META_U(unit, 1677 "tcb_threshold_mapping_set, gport 0x%x is illegal\n"), 1678 gport)); 1679 return BCM_E_PORT; 1680 } 1681 1682 phy_port = si->port_l2p_mapping[local_port]; 1683 mmu_port = si->port_p2m_mapping[phy_port]; 1684 pipe = si->port_pipe[local_port]; 1685 port_index = mmu_port % SOC_TH_MMU_PORT_STRIDE + 1686 _bcm_th2_cosq_tcb_egr_mmu_port_offset[pipe]; 1687 1688 if(!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_bmp), pipe)) { 1689 _bcm_th2_cosq_tcb_scope_help(unit); 1690 return BCM_E_PARAM; 1691 } 1692 1693 if (!SHR_BITGET(tcb_config->profile_bmp, index)) { 1694 LOG_ERROR(BSL_LS_BCM_COSQ, 1695 (BSL_META_U(unit, 1696 "profile %d is illegal\n"), 1697 index)); 1698 return BCM_E_NOT_FOUND; 1699 } 1700 1701 if (-1 == cos) { 1702 BCM_IF_ERROR_RETURN (soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, 1703 port_index, entry)); 1704 for (i = 0; i < _TH2_NUM_PROFILE_COS; i++) { 1705 field = _bcm_cosq_tcb_threshold_profile_map_fields[i]; 1706 old_profile = soc_mem_field32_get(unit, TCB_THRESHOLD_PROFILE_MAPm, 1707 entry, field); 1708 tcb_config->profile_ref_count[old_profile]--; 1709 soc_mem_field32_set(unit, TCB_THRESHOLD_PROFILE_MAPm, entry, field, 1710 index); 1711 tcb_config->profile_ref_count[index]++; 1712 } 1713 BCM_IF_ERROR_RETURN (soc_mem_write(unit, profile_mem, MEM_BLOCK_ALL, 1714 port_index, entry)); 1715 } else { 1716 field = _bcm_cosq_tcb_threshold_profile_map_fields[cos]; 1717 BCM_IF_ERROR_RETURN (soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, 1718 port_index, entry)); 1719 old_profile = soc_mem_field32_get(unit, TCB_THRESHOLD_PROFILE_MAPm, 1720 entry, field); 1721 tcb_config->profile_ref_count[old_profile]--; 1722 1723 soc_mem_field32_set(unit, TCB_THRESHOLD_PROFILE_MAPm, entry, 1724 field, index); 1725 tcb_config->profile_ref_count[index]++; 1726 BCM_IF_ERROR_RETURN (soc_mem_write(unit, profile_mem, MEM_BLOCK_ALL, 1727 port_index, entry)); 1728 } 1729 1730 return BCM_E_NONE; 1731 } 1732 1733 /* 1734 * Function: 1735 * bcm_th2_cosq_tcb_gport_threshold_mapping_get 1736 * Purpose: 1737 * Set threshold profile for a UCQ or a port. 1738 * Parameters: 1739 * unit - (IN) unit number 1740 * gport - (IN) Ucq or a port 1741 * cosq - (IN) Reserved field 1742 * buffer_id - (IN) TCB buffer id. 1743 * index - (OUT) Threshold profile index 1744 * Returns: 1745 * BCM_E_XXX 1746 * Notes: 1747 * When gport is a port, SDK will return the threshold profile index of the first Ucq in this 1748 * port. 1749 */ 1750 int 1751 bcm_th2_cosq_tcb_gport_threshold_mapping_get(int unit, 1752 bcm_gport_t gport, bcm_cos_queue_t cosq, 1753 bcm_cosq_buffer_id_t buffer_id, int *index) 1754 { 1755 soc_mem_t profile_mem; 1756 soc_field_t field; 1757 bcm_port_t local_port; 1758 int mmu_port, phy_port, pipe, port_index, cos; 1759 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1760 _bcm_cosq_tcb_info_t *tcb_config; 1761 soc_info_t *si; 1762 uint32 entry[SOC_MAX_MEM_WORDS]; 1763 1764 LOG_INFO(BSL_LS_BCM_COSQ, 1765 (BSL_META_U(unit, 1766 "tcb_threshold_mapping_get: unit %d, gport 0x%x, " 1767 "cosq %d, buffer_id %d\n"), 1768 unit, gport, cosq, buffer_id)); 1769 1770 TCB_ID_CHECK(buffer_id); 1771 if (NULL == index) { 1772 LOG_ERROR(BSL_LS_BCM_COSQ, 1773 (BSL_META_U(unit, "index is null!\n"))); 1774 return BCM_E_PARAM; 1775 } 1776 1777 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1778 si = &SOC_INFO(unit); 1779 1780 profile_mem = SOC_MEM_UNIQUE_ACC(unit, TCB_THRESHOLD_PROFILE_MAPm)[buffer_id]; 1781 1782 if (BCM_GPORT_IS_SET(gport)) { 1783 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1784 BCM_IF_ERROR_RETURN(_bcm_th_cosq_index_resolve(unit, gport, 0, 1785 _BCM_TH_COSQ_INDEX_STYLE_COS, &local_port, 1786 &cos, NULL)); 1787 } else if (BCM_GPORT_IS_LOCAL(gport) || BCM_GPORT_IS_MODPORT(gport)) { 1788 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port)); 1789 cos = 0; 1790 } else { 1791 LOG_INFO(BSL_LS_BCM_COSQ, 1792 (BSL_META_U(unit, 1793 "tcb_threshold_mapping_get, gport 0x%x is illegal\n"), 1794 gport)); 1795 return BCM_E_PARAM; 1796 } 1797 } else { 1798 local_port = gport; 1799 cos = 0; 1800 } 1801 1802 if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port) || 1803 IS_LB_PORT(unit, local_port)) { 1804 LOG_INFO(BSL_LS_BCM_COSQ, 1805 (BSL_META_U(unit, 1806 "tcb_threshold_mapping_get, gport 0x%x is illegal\n"), 1807 gport)); 1808 return BCM_E_PORT; 1809 } 1810 1811 phy_port = si->port_l2p_mapping[local_port]; 1812 mmu_port = si->port_p2m_mapping[phy_port]; 1813 pipe = si->port_pipe[local_port]; 1814 port_index = mmu_port % SOC_TH_MMU_PORT_STRIDE + 1815 _bcm_th2_cosq_tcb_egr_mmu_port_offset[pipe]; 1816 1817 if(!SHR_BITGET(&(_bcm_th2_cosq_tcb_pipe_table[buffer_id].epipe_bmp), pipe)) { 1818 _bcm_th2_cosq_tcb_scope_help(unit); 1819 return BCM_E_PARAM; 1820 } 1821 1822 BCM_IF_ERROR_RETURN(soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, 1823 port_index, entry)); 1824 1825 field = _bcm_cosq_tcb_threshold_profile_map_fields[cos]; 1826 *index = soc_mem_field32_get(unit,TCB_THRESHOLD_PROFILE_MAPm, entry, field); 1827 1828 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 1829 if (!SHR_BITGET(tcb_config->profile_bmp, *index)) { 1830 LOG_ERROR(BSL_LS_BCM_COSQ, 1831 (BSL_META_U(unit, 1832 "profile %d is illegal\n"), 1833 *index)); 1834 return BCM_E_NOT_FOUND; 1835 } 1836 1837 return BCM_E_NONE; 1838 1839 } 1840 1841 /* 1842 * Function: 1843 * bcm_th2_cosq_tcb_threshold_profile_create 1844 * Purpose: 1845 * Create a threshold profile for a specified TCB buffer. 1846 * Parameters: 1847 * unit - (IN) BCM device number. 1848 * flags - (IN) BCM_COSQ_TCB_THRESHOLD_PROFILE_WITH_ID: Index arg is given 1849 * BCM_COSQ_TCB_THRESHOLD_PROFILE_REPLACE: Replace existing profile 1850 * buffer_id - (IN) TCB buffer id. 1851 * threshold - (IN) Threshold profile 1852 * index - (INOUT) profile index 1853 * Returns: 1854 * BCM_E_XXX 1855 * Notes: 1856 * If user do not specify index, SDK will alloc a profile index and return to user. 1857 * With BCM_COSQ_TCB_THRESHOLD_PROFILE_REPLACE flag user could directly update a 1858 * existing threshold profile to new values. 1859 */ 1860 int 1861 bcm_th2_cosq_tcb_threshold_profile_create(int unit, int flags, 1862 bcm_cosq_buffer_id_t buffer_id, 1863 bcm_cosq_tcb_threshold_profile_t *threshold, 1864 int *index) 1865 { 1866 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 1867 _bcm_cosq_tcb_info_t *tcb_config; 1868 1869 uint64 rval64; 1870 int start_threshold, stop_threshold, i, start_cell, stop_cell, cell_bytes, threshold_max; 1871 1872 tcb_unit_info = TCB_UNIT_CONTROL(unit); 1873 TCB_ID_CHECK(buffer_id); 1874 cell_bytes = tcb_unit_info->cell_bytes; 1875 threshold_max = tcb_unit_info->threshold_max; 1876 1877 LOG_INFO(BSL_LS_BCM_COSQ, 1878 (BSL_META_U(unit, 1879 "tcb_threshold_profile_create: unit %d, " 1880 "flags %d, buffer_id %d\n"), 1881 unit, flags, buffer_id)); 1882 1883 if (_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 1884 /* tcb can only be configured in idle state */ 1885 LOG_INFO(BSL_LS_BCM_COSQ, 1886 (BSL_META_U(unit, 1887 "tcb buffer %d is enabled\n"), 1888 buffer_id)); 1889 return BCM_E_BUSY; 1890 } 1891 1892 if (NULL == threshold || NULL == index) { 1893 LOG_ERROR(BSL_LS_BCM_COSQ, 1894 (BSL_META_U(unit, "threshold or index is null!\n"))); 1895 return BCM_E_PARAM; 1896 } 1897 1898 start_threshold = _MMU_BYTES_TO_CELLS(threshold->start_threshold_bytes, 1899 cell_bytes); 1900 stop_threshold = _MMU_BYTES_TO_CELLS(threshold->stop_threshold_bytes, 1901 cell_bytes); 1902 if (start_threshold> threshold_max || start_threshold <= 0 || 1903 stop_threshold > threshold_max || stop_threshold <= 0 || 1904 start_threshold <= stop_threshold) { 1905 /* start_threshold should be higher than stop_threshold */ 1906 LOG_INFO(BSL_LS_BCM_COSQ, 1907 (BSL_META_U(unit, 1908 "tcb profile create: start threshold %d or " 1909 "stop threshold %d is illegal.\n"), 1910 start_threshold, stop_threshold)); 1911 return BCM_E_PARAM; 1912 } 1913 1914 if (flags & BCM_COSQ_TCB_THRESHOLD_PROFILE_REPLACE) { 1915 if (!(flags & BCM_COSQ_TCB_THRESHOLD_PROFILE_WITH_ID)) { 1916 LOG_INFO(BSL_LS_BCM_COSQ, 1917 (BSL_META_U(unit, 1918 "tcb profile create: flags %d is illegal.\n"), 1919 flags)); 1920 return BCM_E_PARAM; 1921 } 1922 if (*index >= _BCM_TH2_TCB_PROFILE_MAX_NUM || *index <= 0) { 1923 LOG_INFO(BSL_LS_BCM_COSQ, 1924 (BSL_META_U(unit, 1925 "tcb profile create: index %d is illegal.\n"), 1926 *index)); 1927 return BCM_E_PARAM; 1928 } 1929 1930 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 1931 if (!SHR_BITGET(tcb_config->profile_bmp, *index)) 1932 { 1933 LOG_ERROR(BSL_LS_BCM_COSQ, 1934 (BSL_META_U(unit, "index %d is illegal.\n"), 1935 *index)); 1936 return BCM_E_NOT_FOUND; 1937 } 1938 } else if (flags & BCM_COSQ_TCB_THRESHOLD_PROFILE_WITH_ID) { 1939 if (*index >= _BCM_TH2_TCB_PROFILE_MAX_NUM || *index <= 0) { 1940 LOG_ERROR(BSL_LS_BCM_COSQ, 1941 (BSL_META_U(unit, "index %d is illegal.\n"), 1942 *index)); 1943 return BCM_E_PARAM; 1944 } 1945 1946 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 1947 if (SHR_BITGET(tcb_config->profile_bmp, *index)) 1948 { 1949 LOG_ERROR(BSL_LS_BCM_COSQ, 1950 (BSL_META_U(unit, "index %d is illegal.\n"), 1951 *index)); 1952 return BCM_E_EXISTS; 1953 } 1954 SHR_BITSET(tcb_config->profile_bmp, *index); 1955 1956 } else {/* allocate new profile*/ 1957 for (i = 0; i < _BCM_TH2_TCB_PROFILE_MAX_NUM; i++) { 1958 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_THRESHOLD_PROFILEr, 1959 buffer_id, i, &rval64)); 1960 start_cell = soc_reg64_field_get(unit, TCB_THRESHOLD_PROFILEr, rval64, 1961 CAPTURE_START_THRESHOLDf); 1962 stop_cell = soc_reg64_field_get(unit, TCB_THRESHOLD_PROFILEr, rval64, 1963 CAPTURE_END_THRESHOLDf); 1964 if (start_threshold == start_cell && stop_threshold == stop_cell) { 1965 *index = i; 1966 return BCM_E_NONE; 1967 } 1968 } 1969 BCM_IF_ERROR_RETURN( 1970 _bcm_th2_cosq_tcb_profile_id_alloc(unit, buffer_id, index)); 1971 } 1972 1973 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_THRESHOLD_PROFILEr, buffer_id, 1974 *index, &rval64)); 1975 soc_reg64_field_set(unit, TCB_THRESHOLD_PROFILEr, &rval64, 1976 CAPTURE_START_THRESHOLDf, start_threshold); 1977 soc_reg64_field_set(unit, TCB_THRESHOLD_PROFILEr, &rval64, 1978 CAPTURE_END_THRESHOLDf, stop_threshold); 1979 1980 soc_reg64_set(unit, TCB_THRESHOLD_PROFILEr, buffer_id, *index, rval64); 1981 1982 return BCM_E_NONE; 1983 } 1984 1985 /* 1986 * Function: 1987 * bcm_th2_cosq_tcb_threshold_profile_get 1988 * Purpose: 1989 * Get a threshold profile for a specified TCB buffer. 1990 * Parameters: 1991 * unit - (IN) BCM device number. 1992 * buffer_id - (IN) TCB buffer id. 1993 * index - (IN) profile index 1994 * threshold - (OUT) Threshold profile 1995 * Returns: 1996 * BCM_E_XXX 1997 */ 1998 int 1999 bcm_th2_cosq_tcb_threshold_profile_get(int unit, 2000 bcm_cosq_buffer_id_t buffer_id, int index, 2001 bcm_cosq_tcb_threshold_profile_t *threshold) 2002 { 2003 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 2004 _bcm_cosq_tcb_info_t *tcb_config; 2005 2006 uint64 rval64; 2007 int cells, cell_bytes; 2008 2009 LOG_INFO(BSL_LS_BCM_COSQ, 2010 (BSL_META_U(unit, 2011 "tcb_threshold_profile_get: unit %d, " 2012 "buffer_id %d index %d\n"), 2013 unit, buffer_id, index)); 2014 2015 tcb_unit_info = TCB_UNIT_CONTROL(unit); 2016 TCB_ID_CHECK(buffer_id); 2017 cell_bytes = tcb_unit_info->cell_bytes; 2018 2019 if (index >= _BCM_TH2_TCB_PROFILE_MAX_NUM || index <= 0) { 2020 LOG_ERROR(BSL_LS_BCM_COSQ, 2021 (BSL_META_U(unit, "index %d is illegal.\n"), index)); 2022 return BCM_E_PARAM; 2023 } 2024 2025 if (NULL == threshold) { 2026 LOG_ERROR(BSL_LS_BCM_COSQ, 2027 (BSL_META_U(unit, "threshold is null!\n"))); 2028 return BCM_E_PARAM; 2029 } 2030 2031 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 2032 if (!SHR_BITGET(tcb_config->profile_bmp, index)) 2033 { 2034 LOG_ERROR(BSL_LS_BCM_COSQ, 2035 (BSL_META_U(unit, "index %d is illegal.\n"), index)); 2036 return BCM_E_NOT_FOUND; 2037 } 2038 2039 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_THRESHOLD_PROFILEr, buffer_id, 2040 index, &rval64)); 2041 cells = soc_reg64_field_get(unit, TCB_THRESHOLD_PROFILEr, rval64, 2042 CAPTURE_START_THRESHOLDf); 2043 threshold->start_threshold_bytes = _MMU_CELLS_TO_BYTES(cells, cell_bytes); 2044 cells = soc_reg64_field_get(unit, TCB_THRESHOLD_PROFILEr, rval64, 2045 CAPTURE_END_THRESHOLDf); 2046 threshold->stop_threshold_bytes = _MMU_CELLS_TO_BYTES(cells, cell_bytes); 2047 2048 return BCM_E_NONE; 2049 } 2050 2051 /* 2052 * Function: 2053 * bcm_th2_cosq_tcb_threshold_profile_destroy 2054 * Purpose: 2055 * Destory a existing threshold profile for a specified TCB buffer. 2056 * Parameters: 2057 * unit - (IN) BCM device number. 2058 * buffer_id - (IN) TCB buffer id. 2059 * index - (IN) profile index 2060 * Returns: 2061 * BCM_E_XXX 2062 */ 2063 int 2064 bcm_th2_cosq_tcb_threshold_profile_destroy(int unit, 2065 bcm_cosq_buffer_id_t buffer_id, 2066 int index) 2067 { 2068 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 2069 _bcm_cosq_tcb_info_t *tcb_config; 2070 uint64 rval64; 2071 soc_mem_t profile_mem; 2072 soc_field_t field; 2073 int num_entries, mem_wsz; 2074 int i, j, index_min, index_max; 2075 int old_profile; 2076 void *pentry; 2077 char *dmabuf; 2078 2079 LOG_INFO(BSL_LS_BCM_COSQ, 2080 (BSL_META_U(unit, 2081 "tcb_threshold_profile_destroy: unit %d, " 2082 "buffer_id %d index %d\n"), 2083 unit, buffer_id, index)); 2084 2085 tcb_unit_info = TCB_UNIT_CONTROL(unit); 2086 TCB_ID_CHECK(buffer_id); 2087 2088 if (_bcm_cosq_tcb_is_enabled(unit, buffer_id)) { 2089 /* tcb can only be configured in idle state */ 2090 LOG_INFO(BSL_LS_BCM_COSQ, 2091 (BSL_META_U(unit, 2092 "tcb buffer %d is enabled\n"), 2093 buffer_id)); 2094 return BCM_E_BUSY; 2095 } 2096 2097 if (index >= _BCM_TH2_TCB_PROFILE_MAX_NUM || index <= 0) { 2098 LOG_ERROR(BSL_LS_BCM_COSQ, 2099 (BSL_META_U(unit, "index %d is illegal.\n"), index)); 2100 return BCM_E_PARAM; 2101 } 2102 2103 tcb_config = tcb_unit_info->tcb_info[buffer_id]; 2104 if (!SHR_BITGET(tcb_config->profile_bmp, index)) 2105 { 2106 LOG_ERROR(BSL_LS_BCM_COSQ, 2107 (BSL_META_U(unit, "index %d is illegal.\n"), index)); 2108 return BCM_E_NOT_FOUND; 2109 } 2110 2111 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, TCB_THRESHOLD_PROFILEr, buffer_id, 2112 index, &rval64)); 2113 soc_reg64_field_set(unit, TCB_THRESHOLD_PROFILEr, &rval64, 2114 CAPTURE_START_THRESHOLDf, 0); 2115 soc_reg64_field_set(unit, TCB_THRESHOLD_PROFILEr, &rval64, 2116 CAPTURE_END_THRESHOLDf, 0); 2117 soc_reg64_set(unit, TCB_THRESHOLD_PROFILEr, buffer_id, index, rval64); 2118 2119 /* Reset profile map table */ 2120 profile_mem = SOC_MEM_UNIQUE_ACC(unit, TCB_THRESHOLD_PROFILE_MAPm)[buffer_id]; 2121 num_entries = soc_mem_index_count(unit, profile_mem); 2122 index_min = soc_mem_index_min(unit, profile_mem); 2123 index_max = soc_mem_index_max(unit, profile_mem); 2124 mem_wsz = sizeof(uint32) * soc_mem_entry_words(unit, profile_mem); 2125 2126 dmabuf = soc_cm_salloc(unit, num_entries * mem_wsz, "tcb profile"); 2127 if (dmabuf == NULL) { 2128 return BCM_E_MEMORY; 2129 } 2130 2131 if (soc_mem_read_range(unit, profile_mem, MEM_BLOCK_ALL, 2132 index_min, index_max, dmabuf)) { 2133 soc_cm_sfree(unit, dmabuf); 2134 return BCM_E_INTERNAL; 2135 } 2136 2137 for (i = index_min; i <= index_max; i++) { 2138 pentry = soc_mem_table_idx_to_pointer(unit, profile_mem, void*, dmabuf, i); 2139 for (j = 0; j < _TH2_NUM_PROFILE_COS;j++) { 2140 field = _bcm_cosq_tcb_threshold_profile_map_fields[j]; 2141 old_profile = soc_mem_field32_get(unit, TCB_THRESHOLD_PROFILE_MAPm, 2142 pentry, field); 2143 if (old_profile == index) { 2144 tcb_config->profile_ref_count[index]--; 2145 soc_mem_field32_set(unit, TCB_THRESHOLD_PROFILE_MAPm, 2146 pentry, field, 0); 2147 tcb_config->profile_ref_count[0]++; 2148 } 2149 } 2150 } 2151 2152 if (soc_mem_write_range(unit, profile_mem, MEM_BLOCK_ALL, 2153 index_min, index_max, dmabuf)) { 2154 soc_cm_sfree(unit, dmabuf); 2155 return BCM_E_INTERNAL; 2156 } 2157 2158 if (tcb_config->profile_ref_count[index] != 0) { 2159 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 2160 "TCB buffer %d profile %d ref_count %d != 0\n"), 2161 buffer_id, index, 2162 tcb_config->profile_ref_count[index])); 2163 } 2164 2165 SHR_BITCLR(tcb_config->profile_bmp, index); 2166 soc_cm_sfree(unit, dmabuf); 2167 2168 return BCM_E_NONE; 2169 } 2170 2171 /* 2172 * Function: 2173 * bcm_th2_cosq_tcb_init 2174 * Purpose: 2175 * Initialize (clear) all TCB internal structure. 2176 * Parameters: 2177 * unit - (IN) BCM device number. 2178 * Returns: 2179 * BCM_E_XXX 2180 */ 2181 int 2182 bcm_th2_cosq_tcb_init(int unit) 2183 { 2184 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 2185 _bcm_cosq_tcb_info_t *tcb_info; 2186 bcm_cosq_buffer_id_t buffer_id = 0; 2187 soc_mem_t profile_mem; 2188 2189 (void)_bcm_th2_cosq_tcb_deinit(unit); 2190 2191 tcb_unit_info = TCB_UNIT_CONTROL(unit); 2192 if (NULL == tcb_unit_info) { 2193 tcb_unit_info = sal_alloc(sizeof(_bcm_cosq_tcb_unit_ctrl_t), "tcb_dev_info"); 2194 if (!tcb_unit_info) { 2195 return BCM_E_MEMORY; 2196 } 2197 } 2198 2199 sal_memset(tcb_unit_info, 0, sizeof(_bcm_cosq_tcb_unit_ctrl_t)); 2200 2201 TCB_UNIT_CONTROL(unit) = tcb_unit_info; 2202 2203 tcb_unit_info->tcb_num = _BCM_TH2_TCB_MAX_NUM; 2204 tcb_unit_info->cell_bytes = _TH_MMU_BYTES_PER_CELL; 2205 tcb_unit_info->threshold_max = _BCM_TH2_TCB_THRESHOLD_MAX; 2206 2207 /* Create protection mutex. */ 2208 if (tcb_unit_info->tcb_reslock == NULL) { 2209 tcb_unit_info->tcb_reslock = sal_mutex_create("tcb_resource_lock"); 2210 } 2211 2212 if (tcb_unit_info->tcb_reslock == NULL) { 2213 (void)_bcm_th2_cosq_tcb_deinit(unit); 2214 return BCM_E_MEMORY; 2215 } 2216 2217 for (buffer_id = 0; buffer_id < _BCM_TH2_TCB_MAX_NUM; buffer_id++) { 2218 tcb_unit_info->tcb_info[buffer_id] = 2219 sal_alloc(sizeof(_bcm_cosq_tcb_info_t), "tcb info"); 2220 if (NULL == tcb_unit_info->tcb_info[buffer_id]) { 2221 (void)_bcm_th2_cosq_tcb_deinit(unit); 2222 return BCM_E_MEMORY; 2223 } 2224 2225 sal_memset(tcb_unit_info->tcb_info[buffer_id], 0, sizeof(_bcm_cosq_tcb_info_t)); 2226 2227 tcb_info = tcb_unit_info->tcb_info[buffer_id]; 2228 tcb_info->profile_bmp = 2229 sal_alloc(SHR_BITALLOCSIZE(_BCM_TH2_TCB_PROFILE_MAX_NUM), 2230 "profile_bitmap"); 2231 if (NULL == tcb_info->profile_bmp) { 2232 (void)_bcm_th2_cosq_tcb_deinit(unit); 2233 return BCM_E_MEMORY; 2234 } 2235 sal_memset(tcb_info->profile_bmp, 0, 2236 SHR_BITALLOCSIZE(_BCM_TH2_TCB_PROFILE_MAX_NUM)); 2237 } 2238 2239 if (!SOC_WARM_BOOT(unit)) { 2240 for (buffer_id = 0; buffer_id < _BCM_TH2_TCB_MAX_NUM; buffer_id++) { 2241 SHR_BITSET(tcb_info->profile_bmp, 0); 2242 profile_mem = 2243 SOC_MEM_UNIQUE_ACC(unit, TCB_THRESHOLD_PROFILE_MAPm)[buffer_id]; 2244 tcb_info = tcb_unit_info->tcb_info[buffer_id]; 2245 tcb_info->profile_ref_count[0] = 2246 soc_mem_index_count(unit, profile_mem) * 10; 2247 } 2248 } 2249 2250 soc_th2_tcb_set_hw_intr_cb(unit); 2251 2252 return BCM_E_NONE; 2253 } 2254 2255 2256 /* 2257 * Function: 2258 * bcm_th2_cosq_tcb_buffer_multi_get 2259 * Purpose: 2260 * Get packet records in a specified TCB buffer. 2261 * Parameters: 2262 * unit - (IN) BCM device number. 2263 * buffer_id - (IN) buffer id 2264 * array_max - (IN) Number of entries to be retrieved 2265 * buffer_array - (OUT) Pakcet record array 2266 * array_count - (OUT) Number of packet records returned in buffer_array 2267 * Returns: 2268 * BCM_E_XXX 2269 * Notes: 2270 * When array_max is 0, buffer_array is NULL, array_count will return actural packet record 2271 * count in the TCB buffer. 2272 */ 2273 int 2274 bcm_th2_cosq_tcb_buffer_multi_get(int unit, 2275 bcm_cosq_buffer_id_t buffer_id, int count, 2276 bcm_cosq_tcb_buffer_t *entries, int *num) 2277 { 2278 int i_count = 0, status; 2279 2280 LOG_INFO(BSL_LS_BCM_COSQ, 2281 (BSL_META_U(unit, 2282 "tcb_buffer_multi_get: unit %d, buffer_id %d, count %d\n"), 2283 unit, buffer_id, count)); 2284 2285 TCB_ID_CHECK(buffer_id); 2286 2287 if (count < 0) { 2288 LOG_ERROR(BSL_LS_BCM_COSQ, 2289 (BSL_META_U(unit, "count %d is illegal\n"), count)); 2290 return BCM_E_PARAM; 2291 } 2292 2293 if((count > 0) && (NULL == entries)) { 2294 LOG_ERROR(BSL_LS_BCM_COSQ, 2295 (BSL_META_U(unit, "entries is null\n"))); 2296 return BCM_E_PARAM; 2297 } 2298 2299 if (NULL == num) { 2300 LOG_ERROR(BSL_LS_BCM_COSQ, 2301 (BSL_META_U(unit, "num is null\n"))); 2302 return BCM_E_PARAM; 2303 } 2304 2305 /* event buffer can only be read in freeze status */ 2306 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_current_phase_get(unit, buffer_id, &status)); 2307 if (_TCB_FROZEN_PHASE != status) { 2308 LOG_ERROR(BSL_LS_BCM_COSQ, 2309 (BSL_META_U(unit, 2310 "tcb buffer can only be read in freeze status " 2311 "current status %d\n"), 2312 status)); 2313 return BCM_E_BUSY; 2314 } 2315 2316 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_get_rd_num(unit, buffer_id, num)); 2317 2318 if((0 == *num) || (0 == count)) { 2319 return BCM_E_NONE; 2320 } 2321 2322 if(count < *num) { 2323 i_count = count; 2324 *num = count; 2325 } else { 2326 i_count = *num; 2327 } 2328 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_metadata_read(unit, buffer_id, i_count, 2329 entries)); 2330 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_celldata_read(unit, buffer_id, i_count, 2331 entries)); 2332 2333 return BCM_E_NONE; 2334 } 2335 2336 /* 2337 * Function: 2338 * bcm_th2_cosq_tcb_event_multi_get 2339 * Purpose: 2340 * Get drop event records in a specified TCB buffer. 2341 * Parameters: 2342 * unit - (IN) BCM device number. 2343 * buffer_id - (IN) buffer id 2344 * array_max - (IN) Number of entries to be retrieved 2345 * event_array - (OUT) Drop event record array 2346 * array_count - (OUT) Number of drop event records returned in event_array 2347 * overflow_count - (OUT) Drop event count exceed the event buffer. 2348 * Returns: 2349 * BCM_E_XXX 2350 * Notes: 2351 * When array_max is 0, event_array is NULL, array_count will return actural drop event 2352 * record count in the TCB buffer. 2353 */ 2354 int 2355 bcm_th2_cosq_tcb_event_multi_get(int unit, 2356 bcm_cosq_buffer_id_t buffer_id, int count, 2357 bcm_cosq_tcb_event_t *entries, int *num, 2358 int *overflow_num) 2359 { 2360 int i_count = 0; 2361 int status; 2362 2363 LOG_INFO(BSL_LS_BCM_COSQ, 2364 (BSL_META_U(unit, 2365 "tcb_event_multi_get: unit %d, buffer_id %d, count %d\n"), 2366 unit, buffer_id, count)); 2367 2368 TCB_ID_CHECK(buffer_id); 2369 2370 if (count < 0) { 2371 LOG_ERROR(BSL_LS_BCM_COSQ, 2372 (BSL_META_U(unit, "count %d is illegal\n"), count)); 2373 return BCM_E_PARAM; 2374 } 2375 2376 if((count > 0) && (NULL == entries)) { 2377 LOG_ERROR(BSL_LS_BCM_COSQ, 2378 (BSL_META_U(unit, "entries is null\n"))); 2379 return BCM_E_PARAM; 2380 } 2381 2382 if (NULL == num) { 2383 LOG_ERROR(BSL_LS_BCM_COSQ, 2384 (BSL_META_U(unit, "num is null\n"))); 2385 return BCM_E_PARAM; 2386 } 2387 2388 if (NULL == overflow_num) { 2389 LOG_ERROR(BSL_LS_BCM_COSQ, 2390 (BSL_META_U(unit, "overflow is null\n"))); 2391 return BCM_E_PARAM; 2392 } 2393 2394 /* event buffer can only be read in freeze status */ 2395 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_current_phase_get(unit, buffer_id, &status)); 2396 if (_TCB_FROZEN_PHASE != status) { 2397 LOG_ERROR(BSL_LS_BCM_COSQ, 2398 (BSL_META_U(unit, 2399 "event buffer can only be read in freeze status " 2400 "current status %d\n"), 2401 status)); 2402 return BCM_E_BUSY; 2403 } 2404 2405 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_buffer_info_get(unit, buffer_id, 2406 _TCB_BUF_STATUS_EVT_NUM, num)); 2407 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_evt_overflow_count_get(unit, buffer_id, 2408 overflow_num)); 2409 2410 if ((0 == *num) || (0 == count)) { 2411 return BCM_E_NONE; 2412 } 2413 2414 if (count < *num) { 2415 i_count = count; 2416 *num = count; 2417 } else { 2418 i_count = *num; 2419 } 2420 BCM_IF_ERROR_RETURN(_bcm_th2_cosq_tcb_event_buffer_read(unit, buffer_id, 2421 i_count, entries)); 2422 2423 return BCM_E_NONE; 2424 } 2425 2426 #ifndef BCM_SW_STATE_DUMP_DISABLE 2427 /* 2428 * Function: 2429 * bcm_th2_cosq_tcb_sw_dump 2430 * Purpose: 2431 * Displays TCB threshold information maintained by software. 2432 * Parameters: 2433 * unit - Device unit number 2434 * Returns: 2435 * None 2436 */ 2437 void 2438 bcm_th2_cosq_tcb_sw_dump(int unit) 2439 { 2440 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 2441 _bcm_cosq_tcb_info_t *tcb_config; 2442 int i, j; 2443 2444 tcb_unit_info = TCB_UNIT_CONTROL(unit); 2445 if (tcb_unit_info == NULL) { 2446 LOG_CLI((BSL_META_U(unit, 2447 "ERROR: TCB module not initialized on Unit:%d \n"), unit)); 2448 return; 2449 } 2450 2451 for (i = 0; i < tcb_unit_info->tcb_num; i++) { 2452 LOG_CLI((BSL_META_U(unit, 2453 "TCB profile info: TCB buffer %d \n"), i)); 2454 tcb_config = tcb_unit_info->tcb_info[i]; 2455 for (j = 0; j < _BCM_TH2_TCB_PROFILE_MAX_NUM; j++) { 2456 if (SHR_BITGET(tcb_config->profile_bmp, j)) { 2457 LOG_CLI((BSL_META_U(unit, 2458 " profile:%d ref_count:%d \n"), 2459 j, tcb_config->profile_ref_count[j])); 2460 } 2461 } 2462 } 2463 2464 return; 2465 } 2466 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 2467 2468 #endif /* INCLUDE_TCB && BCM_TCB_SUPPORT */ 2469