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