flowcnt_common.c (155806B)
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: flowcnt_common.c 8 * Purpose: Manage common functionality for flow counter implementation 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <bcm/stat.h> 14 #include <bcm/module.h> 15 #include <bcm_int/esw/flowcnt.h> 16 #include <bcm_int/esw/stat.h> 17 #include <soc/scache.h> 18 19 20 static _bcm_esw_flowcnt_control_t *flowcnt_control[SOC_MAX_NUM_DEVICES]={NULL}; 21 22 typedef struct { 23 uint32 entry_data[BYTES2WORDS(5)]; 24 }counter_table_entry_t; 25 26 #define MAX_FLOWCNT_COUNTER_TABLE_SIZE (512) 27 28 static counter_table_entry_t *flowcnt_temp_counter[SOC_MAX_NUM_DEVICES] = {NULL}; 29 30 /* for those counter indexes created but not attached */ 31 #define MAX_FLOWCNT_SCACHE_SIZE (32) 32 static uint8 *local_scache_ptr[SOC_MAX_NUM_DEVICES]={NULL}; 33 static uint32 local_scache_size=0; 34 35 #define FLOWCNT_SCACHE_SIZE_1 (MAX_FLOWCNT_SCACHE_SIZE * sizeof(uint32)) 36 #ifdef BCM_WARM_BOOT_SUPPORT 37 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 38 static soc_scache_handle_t handle=0; 39 static uint32 flowcnt_scache_allocated_size[SOC_MAX_NUM_DEVICES]= {0}; 40 static uint8 *flowcnt_scache_ptr[SOC_MAX_NUM_DEVICES]={NULL}; 41 STATIC int _bcm_esw_flowcnt_warmboot_info_recover(int unit,uint8 *scache_ptr); 42 STATIC int _bcm_esw_flowcnt_warmboot_object_retrive(int unit); 43 /* scache layout of flowcnt 44 * 1. stat_counter_id 45 * 2. default_attr_mode_id (size maybe change because of 46 * bcmStatGroupModeAttrMaxValue) 47 * local : the size according the current mode attr max value 48 * recover : the size in scache 49 * when firmware upgrade, "local" maybe be larger than "recover" 50 * when firmware downgrade, "local" maybe be less than "recover" 51 * 3. flowcnt_group_info 52 */ 53 #define FLOWCNT_SCACHE_SIZE_2_LOCAL (sizeof(_bcm_flowcnt_warmboot_info_t)) 54 #define FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) (flowcnt_scache_allocated_size[unit]\ 55 - FLOWCNT_SCACHE_SIZE_1\ 56 - FLOWCNT_SCACHE_SIZE_3) 57 #define FLOWCNT_SCACHE_SIZE_3 (sizeof(_bcm_flowcnt_warmboot_group_info_t) *\ 58 _BCM_STAT_FLOWCNT_MAX_PROFILE_GROUP *\ 59 _BCM_STAT_FLOWCNT_MAX_PROFILES) 60 #endif 61 62 #define _BCM_FLOWCNT_MODE_ID_VALID (0x80000000) 63 64 /* need to add bias to tell if value of the pgroup is valid*/ 65 #define _BCM_FLOWCNT_PGROUP_BIAS (0xF) 66 /* 67 * Macro: 68 * _FLOWCNT_IS_INIT (internal) 69 * Purpose: 70 * Check that the unit is valid and confirm that the oam functions 71 * are initialized. 72 * Parameters: 73 * unit - BCM device number 74 * Notes: 75 * Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or 76 * return(BCM_E_INIT) if fails. 77 */ 78 #define _FLOWCNT_IS_INIT(unit) \ 79 do { \ 80 if (!soc_feature(unit, soc_feature_flowcnt)) { \ 81 return (BCM_E_UNAVAIL); \ 82 } \ 83 if (flowcnt_control[unit] == NULL) { \ 84 LOG_ERROR(BSL_LS_BCM_FLEXCTR, \ 85 (BSL_META_U(unit, \ 86 "Flowcnt Error: Module not initialized\n"))); \ 87 return (BCM_E_INIT); \ 88 } \ 89 } while (0) 90 91 /* 92 * Macro: 93 * _FLOWCNT_ALLOC 94 * Purpose: 95 * Generic memory allocation routine. 96 * Parameters: 97 * _unit_ - Unit. 98 * _ptr_ - Pointer to allocated memory. 99 * _ptype_ - Pointer type. 100 * _size_ - Size of heap memory to be allocated. 101 * _descr_ - Information about this memory allocation. 102 * _dma_ - use sal_alloc or soc_cm_alloc. 103 * _rv_ - return value 104 */ 105 #define _FLOWCNT_ALLOC(_unit_,_ptr_,_ptype_,_size_,_descr_,_dma_,_rv_) \ 106 do { \ 107 if (NULL == (_ptr_)) { \ 108 if (0 == (_dma_)) { \ 109 (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \ 110 } else { \ 111 (_ptr_) = (_ptype_ *) soc_cm_salloc((_unit_),(_size_), \ 112 (_descr_)); \ 113 } \ 114 } \ 115 if((_ptr_) != NULL) { \ 116 sal_memset((_ptr_), 0, (_size_)); \ 117 _rv_ = BCM_E_NONE; \ 118 } else { \ 119 LOG_ERROR(BSL_LS_BCM_FLEXCTR, \ 120 (BSL_META("Flowcnt Error: Allocation failure %s\n"), \ 121 (_descr_))); \ 122 _rv_ = BCM_E_MEMORY; \ 123 } \ 124 } while (0) 125 126 #define _FLOWCNT_FREE(_unit, _ptr, _dma) \ 127 do {\ 128 if (0 == (_dma)) { \ 129 sal_free((_ptr)); \ 130 } else { \ 131 soc_cm_sfree((_unit), (_ptr)); \ 132 }\ 133 } while (0) 134 135 #define _FLOWCNT_LOCK(fc) \ 136 sal_mutex_take((fc)->flowcnt_mutex, sal_mutex_FOREVER); 137 #define _FLOWCNT_UNLOCK(fc) \ 138 sal_mutex_give((fc)->flowcnt_mutex); 139 140 #define _FLOWCNT_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 141 142 typedef struct flowcnt_profile_table_info_s { 143 soc_mem_t mem; /* profile mem */ 144 int num_groups; /* numbers of group per profile */ 145 bcm_stat_group_mode_attr_t attr; 146 bcm_stat_flex_direction_t direction; 147 } flowcnt_profile_table_info_t; 148 149 typedef struct flowcnt_object_table_fields_s { 150 char *key_type; 151 soc_field_t base_index_field; 152 soc_field_t profile_ptr_field; 153 } flowcnt_object_table_fields_t; 154 155 typedef struct flowcnt_object_info_s { 156 bcm_stat_object_t object; 157 soc_mem_t object_mem; 158 soc_mem_t offset_mem; 159 soc_mem_t counter_mem; 160 soc_field_t view_field; 161 flowcnt_object_table_fields_t counter_fields; 162 }flowcnt_object_info_t; 163 164 /* 165 * Normally reserve_count is 1. i.e. reserve index 0 for warmboot 166 */ 167 typedef struct flowcnt_pool_table_info_s { 168 soc_mem_t pool_mem; 169 uint32 reserve_base; 170 uint32 reserve_count; 171 }flowcnt_pool_table_info_t; 172 173 static flowcnt_profile_table_info_t _hr3_flowcnt_profile_table[] = { 174 {ING_VLAN_COUNTER_PRI_COS_MAPm, 4, 175 bcmStatGroupModeAttrPktCfiPri, bcmStatFlexDirectionIngress}, 176 {EGR_VLAN_COUNTER_PRI_COS_MAPm, 4, 177 bcmStatGroupModeAttrPktCfiPri, bcmStatFlexDirectionEgress}, 178 }; 179 180 /* in HR3, reserve indx0-7 for ambiguous count */ 181 static flowcnt_pool_table_info_t _hr3_flowcnt_pool_table[] = { 182 {ING_VLAN_COUNTER_TABLEm, 0, 8}, 183 {EGR_VLAN_COUNTER_TABLEm, 0, 8}, 184 }; 185 186 static int _hr3_stat_group_mode_info[] = { 187 bcmStatGroupModeSingle, 188 -1 189 }; 190 191 static flowcnt_object_info_t _hr3_stat_object_info[] = { 192 {bcmStatObjectIngVlanXlate, VLAN_XLATEm, 193 ING_VLAN_COUNTER_PRI_COS_MAPm, 194 ING_VLAN_COUNTER_TABLEm, KEY_TYPEf, 195 {"XLATE", XLATE__VLAN_CTR_BASE_INDEXf, XLATE__VLAN_CTR_PROFILE_PTRf} 196 }, 197 {bcmStatObjectIngFieldStageLookup, VFP_POLICY_TABLEm, 198 ING_VLAN_COUNTER_PRI_COS_MAPm, 199 ING_VLAN_COUNTER_TABLEm, -1, 200 {"", VLAN_CTR_BASE_INDEXf, VLAN_CTR_PROFILE_PTRf} 201 }, 202 {bcmStatObjectEgrVlanXlate, EGR_VLAN_XLATEm, 203 EGR_VLAN_COUNTER_PRI_COS_MAPm, 204 EGR_VLAN_COUNTER_TABLEm, ENTRY_TYPEf, 205 {"XLATE", XLATE__VLAN_CTR_BASE_INDEXf, XLATE__VLAN_CTR_PROFILE_PTRf} 206 }, 207 {-1, -1, -1, -1, -1,{NULL,-1,-1}} 208 }; 209 210 static flowcnt_pool_table_info_t *flowcnt_pool_table[SOC_MAX_NUM_DEVICES] = {NULL}; 211 static flowcnt_profile_table_info_t *flowcnt_profile_table[SOC_MAX_NUM_DEVICES] = {NULL}; 212 static int *valid_stat_group_mode_list[SOC_MAX_NUM_DEVICES] = {NULL}; 213 static flowcnt_object_info_t *valid_stat_object_list[SOC_MAX_NUM_DEVICES] = {NULL}; 214 215 216 STATIC int 217 _bcm_esw_flowcnt_control_get(int unit, _bcm_esw_flowcnt_control_t **fc) 218 { 219 if (NULL == fc) { 220 return (BCM_E_PARAM); 221 } 222 /* Ensure flowcnt module is initialized. */ 223 _FLOWCNT_IS_INIT(unit); 224 225 *fc = flowcnt_control[unit]; 226 227 return (BCM_E_NONE); 228 } 229 230 STATIC 231 int _bcm_esw_flowcnt_stat_object_validate( 232 int unit, 233 bcm_stat_object_t object) 234 { 235 int i; 236 int rv = BCM_E_PARAM; 237 flowcnt_object_info_t *stat_object_list; 238 239 if (valid_stat_object_list[unit] == NULL){ 240 return BCM_E_INTERNAL; 241 } 242 stat_object_list = valid_stat_object_list[unit]; 243 for (i = 0; stat_object_list[i].object != -1; i++) { 244 if (stat_object_list[i].object == object){ 245 rv = BCM_E_NONE; 246 break; 247 } 248 } 249 250 return rv; 251 252 } 253 254 STATIC int 255 _bcm_esw_flowcnt_stat_group_mode_validate(int unit, 256 bcm_stat_group_mode_t group_mode) 257 { 258 int i; 259 int rv = BCM_E_PARAM; 260 261 if (valid_stat_group_mode_list[unit] == NULL){ 262 return BCM_E_INTERNAL; 263 } 264 for (i = 0; valid_stat_group_mode_list[unit][i] != -1; i++) { 265 if (valid_stat_group_mode_list[unit][i] == group_mode){ 266 rv = BCM_E_NONE; 267 break; 268 } 269 } 270 return rv; 271 } 272 273 STATIC int 274 _bcm_hr3_flowcnt_ctrl_init(int unit, _bcm_esw_flowcnt_control_t *fc) 275 { 276 int rv; 277 valid_stat_group_mode_list[unit] = _hr3_stat_group_mode_info; 278 valid_stat_object_list[unit] = _hr3_stat_object_info; 279 flowcnt_profile_table[unit] = _hr3_flowcnt_profile_table; 280 flowcnt_pool_table[unit] = _hr3_flowcnt_pool_table; 281 fc->num_profiles = _FLOWCNT_ARRAY_SIZE(_hr3_flowcnt_profile_table); 282 fc->num_pools = _FLOWCNT_ARRAY_SIZE(_hr3_flowcnt_pool_table); 283 /* The max value of the offset field on ING/EGR_VLAN_COUNTER_PRI_COS_MAP 284 in power of two */ 285 fc->counter_block = 3; 286 _FLOWCNT_ALLOC(unit, flowcnt_temp_counter[unit], counter_table_entry_t, 287 MAX_FLOWCNT_COUNTER_TABLE_SIZE * 288 sizeof(counter_table_entry_t), 289 "temp_counter", 1, rv); 290 291 if (BCM_FAILURE(rv)) { 292 return rv; 293 } 294 return BCM_E_NONE; 295 } 296 297 /* 298 * Function: 299 * _bcm_esw_flowcnt_object_table_index_get 300 * Description: 301 * Get the object table index based on the object mem informantion based 302 * on the object or object_mem. 303 * Parameters: 304 * unit - (IN) unit number 305 * index - (IN) index in the object mem. 306 * table - (IN) object memory. 307 * data - (IN) entry data 308 * object_index - (OUT) valid_stat_object_list index 309 * 310 * Return Value: 311 * BCM_E_XXX 312 * Notes: 313 */ 314 STATIC int 315 _bcm_esw_flowcnt_object_table_index_get( 316 int unit, 317 uint32 index, 318 soc_mem_t table, 319 void *data, 320 int *object_index) 321 { 322 int i; 323 soc_field_t view_field = INVALIDf; 324 soc_mem_info_t *memp; 325 uint32 key_type=0; 326 flowcnt_object_info_t *stat_object_list; 327 flowcnt_object_table_fields_t *o_fields; 328 329 *object_index = -1; 330 stat_object_list = valid_stat_object_list[unit]; 331 for (i = 0; stat_object_list[i].object_mem != -1; i++) { 332 if (stat_object_list[i].object_mem == table) { 333 memp = &SOC_MEM_INFO(unit, table); 334 view_field = stat_object_list[i].view_field; 335 o_fields = &stat_object_list[i].counter_fields; 336 if (view_field == INVALIDf) { 337 *object_index = i; 338 break; 339 } else { 340 key_type = soc_mem_field32_get(unit, table, data, view_field); 341 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 342 (BSL_META_U(unit, 343 "key_type %d "), 344 key_type)); 345 if (sal_strcmp(memp->views[key_type], o_fields->key_type) == 0) { 346 *object_index = i; 347 break; 348 } 349 } 350 } 351 } 352 if (*object_index == -1) { 353 return BCM_E_INTERNAL; 354 } 355 356 return BCM_E_NONE; 357 } 358 359 STATIC int 360 _bcm_esw_flowcnt_object_table_fields_get( 361 int unit, 362 uint32 index, 363 soc_mem_t table, 364 void *data, 365 soc_field_t *profile_ptr_field, 366 soc_field_t *base_idx_field) 367 { 368 int object_index=-1,rv=BCM_E_NONE; 369 flowcnt_object_table_fields_t *o_fields; 370 flowcnt_object_info_t *stat_object_list; 371 372 rv = _bcm_esw_flowcnt_object_table_index_get( 373 unit, index, table, data, &object_index); 374 if (BCM_FAILURE(rv)){ 375 return rv; 376 } 377 stat_object_list = valid_stat_object_list[unit]; 378 o_fields = &stat_object_list[object_index].counter_fields; 379 380 *profile_ptr_field = o_fields->profile_ptr_field; 381 *base_idx_field = o_fields->base_index_field; 382 383 /* Just a safety check */ 384 if ((soc_mem_field_valid(unit,table,*profile_ptr_field) == FALSE) || 385 (soc_mem_field_valid(unit,table,*base_idx_field) == FALSE)){ 386 LOG_WARN(BSL_LS_BCM_FLEXCTR, 387 (BSL_META_U(unit, 388 "INTERNAL Error i.e. " 389 "required offset,base_idx fields are " 390 "not valid \n"))); 391 return BCM_E_INTERNAL; 392 } 393 394 return BCM_E_NONE; 395 } 396 397 398 STATIC int 399 _bcm_esw_flowcnt_object_table_fields_values_get( 400 int unit, 401 uint32 index, 402 soc_mem_t table, 403 void *data, 404 uint32 *profile_ptr, 405 uint32 *base_idx) 406 { 407 int rv = BCM_E_NONE; 408 soc_field_t profile_ptr_field = INVALIDf; 409 soc_field_t base_index_field = INVALIDf; 410 411 rv = _bcm_esw_flowcnt_object_table_fields_get( 412 unit, index, table, data, &profile_ptr_field, 413 &base_index_field); 414 415 if (BCM_FAILURE(rv)){ 416 return rv; 417 } 418 *profile_ptr = soc_mem_field32_get(unit,table,data,profile_ptr_field); 419 *base_idx = soc_mem_field32_get(unit,table,data,base_index_field); 420 return rv; 421 } 422 423 STATIC int 424 _bcm_esw_flowcnt_object_table_fields_values_set( 425 int unit, 426 uint32 index, 427 soc_mem_t table, 428 void *data, 429 uint32 profile_ptr, 430 uint32 base_idx) 431 { 432 int rv = BCM_E_NONE; 433 soc_field_t profile_ptr_field = INVALIDf; 434 soc_field_t base_index_field = INVALIDf; 435 436 rv = _bcm_esw_flowcnt_object_table_fields_get( 437 unit, index, table, data, &profile_ptr_field, 438 &base_index_field); 439 440 if (BCM_FAILURE(rv)){ 441 return rv; 442 } 443 soc_mem_field32_set(unit,table,data,profile_ptr_field,profile_ptr); 444 soc_mem_field32_set(unit,table,data,base_index_field,base_idx); 445 return rv; 446 } 447 448 /* 449 * Function: 450 * _bcm_esw_flowcnt_stat_id_insert 451 * Description: 452 * Inserts stat id in local scache table. Useful for WARM-BOOT purpose 453 * Parameters: 454 * scache_ptr - (IN) Local scache table pointer 455 * stat_counter_id - (IN) Flex Stat Counter Id 456 * Return Value: 457 * BCM_E_XXX 458 * Notes: 459 */ 460 static int 461 _bcm_esw_flowcnt_stat_id_insert(uint8 *scache_ptr, uint32 stat_counter_id) 462 { 463 uint32 index = 0; 464 uint32 *ptr = (uint32 *)scache_ptr; 465 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 466 (BSL_META("Inserting %d "), 467 stat_counter_id)); 468 for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) { 469 if (ptr[index] == 0) { 470 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 471 (BSL_META("Inserted \n"))); 472 ptr[index] = stat_counter_id; 473 break; 474 } 475 } 476 if (index == MAX_FLOWCNT_SCACHE_SIZE) { 477 return BCM_E_FAIL; 478 } 479 return BCM_E_NONE; 480 } 481 /* 482 * Function: 483 * _bcm_esw_flowcnt_stat_id_delete 484 * Description: 485 * Deletes stat id from local scache table. Useful for WARM-BOOT purpose 486 * Parameters: 487 * scache_ptr - (IN) Local scache table pointer 488 * stat_counter_id - (IN) Flex Stat Counter Id 489 * Return Value: 490 * BCM_E_XXX 491 * Notes: 492 */ 493 static int 494 _bcm_esw_flowcnt_stat_id_delete(uint8 *scache_ptr,uint32 stat_counter_id) 495 { 496 uint32 index = 0; 497 uint32 *ptr = (uint32 *)scache_ptr; 498 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 499 (BSL_META("Deleting ID:%d "), 500 stat_counter_id)); 501 for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) { 502 if (ptr[index] == stat_counter_id) { 503 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 504 (BSL_META("Deleted \n"))); 505 ptr[index] = 0; 506 break; 507 } 508 } 509 if (index == MAX_FLOWCNT_SCACHE_SIZE) { 510 return BCM_E_FAIL; 511 } 512 return BCM_E_NONE; 513 } 514 /* 515 * Function: 516 * _bcm_esw_flowcnt_accounting_object_info_get 517 * Description: 518 * Get object table info for given accounting table and index 519 * Parameters 520 * unit - (IN) unit number 521 * table - (IN) Accounting Tables 522 * index - (IN) index of the accounting tables 523 * profile_ptr - (OUT) profile group mode 524 * base_index - (OUT) base index 525 * object_index - (OUT) index to internal object table 526 * valid_stat_object_list 527 * Return Value: 528 * BCM_E_XXX 529 * Notes: 530 */ 531 STATIC int 532 _bcm_esw_flowcnt_accounting_object_info_get( 533 int unit, 534 soc_mem_t table, 535 int index, 536 uint32 *profile_ptr, 537 uint32 *base_index, 538 int *object_index) 539 { 540 soc_mem_info_t *memp = NULL; 541 int rv = BCM_E_NONE; 542 void *entry_data = NULL; 543 uint32 entry_data_size = 0; 544 545 memp = &SOC_MEM_INFO(unit, table); 546 entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes)); 547 _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size, 548 "object table entry", 0, rv); 549 if (BCM_FAILURE(rv)){ 550 return rv; 551 } 552 if (soc_mem_read(unit, table, MEM_BLOCK_ANY, 553 index, 554 entry_data) != SOC_E_NONE) { 555 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 556 (BSL_META_U(unit, 557 "Read failure for Table %s with index %d \n"), 558 SOC_MEM_UFNAME(unit, table),index)); 559 _FLOWCNT_FREE(unit, entry_data, 0); 560 return BCM_E_INTERNAL; 561 } 562 if (soc_mem_field_valid(unit,table,VALIDf)) { 563 if (soc_mem_field32_get(unit, table, entry_data, VALIDf)==0) { 564 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 565 (BSL_META_U(unit, 566 "Table %s with index %d is Not valid \n"), 567 SOC_MEM_UFNAME(unit, table),index)); 568 _FLOWCNT_FREE(unit, entry_data, 0); 569 return BCM_E_PARAM; 570 } 571 } 572 573 rv = _bcm_esw_flowcnt_object_table_fields_values_get( 574 unit, index, table, entry_data, 575 profile_ptr, base_index); 576 if (BCM_FAILURE(rv)){ 577 _FLOWCNT_FREE(unit, entry_data, 0); 578 return rv; 579 } 580 rv = _bcm_esw_flowcnt_object_table_index_get( 581 unit, index, table, entry_data, object_index); 582 if (BCM_FAILURE(rv)){ 583 _FLOWCNT_FREE(unit, entry_data, 0); 584 return rv; 585 } 586 _FLOWCNT_FREE(unit, entry_data, 0); 587 588 return BCM_E_NONE; 589 } 590 591 592 /* 593 * Function: 594 * _bcm_flowcnt_ctrl_common_init 595 * Description: 596 * Initialize and allocate all required resources for Hurricane3 597 * Parameters: 598 * unit - (IN) unit number 599 * Return Value: 600 * BCM_E_XXX 601 * - if resource allocation errored, just returned. 602 * Resource free should be taken care in upper layer. 603 * Notes: 604 * 605 * _bcm_esw_flowcnt_profile_t *flowcnt_profile; 606 * int num_profiles; 607 * _bcm_esw_flowcnt_pool_t *flowcnt_pool; 608 * int num_pool; 609 * Above should be allocated and assigned per chip profile table. 610 * 611 * shr_aidxres_list_handle_t flowcnt_aidxres_list_handle; 612 * uint32 flow_packet_counter; 613 * uint64 flow_byte_counter; 614 * uint64 flow_packet64_counter; 615 * uint16 flow_base_index_reference_count; 616 * Above should be allocated and assigned per chip counter table. 617 */ 618 STATIC int 619 _bcm_flowcnt_ctrl_common_init(int unit, _bcm_esw_flowcnt_control_t *fc) 620 { 621 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 622 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 623 int i; 624 int rv = BCM_E_NONE; 625 soc_mem_t mem; 626 soc_mem_info_t *memp; 627 int entry_words, num_ctr; 628 flowcnt_profile_table_info_t *profile_table; 629 flowcnt_pool_table_info_t *pool_table; 630 631 if (fc == NULL) { 632 return BCM_E_MEMORY; 633 } 634 /* Allocate default attr mode id */ 635 _FLOWCNT_ALLOC(unit, fc->default_attr_mode_id, uint32, 636 bcmStatGroupModeAttrMaxValue * sizeof(uint32), 637 "Flowcnt default attr mode_id", 0, rv); 638 if (BCM_FAILURE(rv)) { 639 return rv; 640 } 641 642 /* Allocate the profile resource */ 643 _FLOWCNT_ALLOC(unit, fc->flowcnt_profile, _bcm_esw_flowcnt_profile_t, 644 fc->num_profiles * sizeof(_bcm_esw_flowcnt_profile_t), 645 "Flowcnt profile", 0, rv); 646 if (BCM_FAILURE(rv)) { 647 return rv; 648 } 649 profile_table = flowcnt_profile_table[unit]; 650 for (i = 0; i < fc->num_profiles; i++) { 651 fc_profile = &fc->flowcnt_profile[i]; 652 mem = profile_table[i].mem; 653 memp = &SOC_MEM_INFO(unit, mem); 654 entry_words = BYTES2WORDS(memp->bytes); 655 soc_profile_mem_t_init(&fc_profile->profile_mem); 656 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 657 &fc_profile->profile_mem); 658 if (BCM_FAILURE(rv)) { 659 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 660 (BSL_META_U(unit, 661 "Flowcnt profile create - Failed.\n"))); 662 return (rv); 663 } 664 fc_profile->num_groups = profile_table[i].num_groups; 665 _FLOWCNT_ALLOC(unit, fc_profile->flowcnt_group, 666 _bcm_esw_flowcnt_profile_group_t, 667 fc_profile->num_groups * 668 sizeof(_bcm_esw_flowcnt_profile_group_t), 669 "Flowcnt profile group", 0, rv); 670 if (BCM_FAILURE(rv)) { 671 return rv; 672 } 673 fc_profile->direction = profile_table[i].direction; 674 fc_profile->attr = profile_table[i].attr; 675 fc_profile->profile_table = mem; 676 fc_profile->num_entries = soc_mem_index_count(unit, mem) / 677 profile_table[i].num_groups; 678 } 679 680 /* Allocate the counter table resource */ 681 _FLOWCNT_ALLOC(unit, fc->flowcnt_pool, _bcm_esw_flowcnt_pool_t, 682 fc->num_pools * sizeof (_bcm_esw_flowcnt_pool_t), 683 "Flowcnt pool", 0, rv); 684 if (BCM_FAILURE(rv)) { 685 return rv; 686 } 687 pool_table = flowcnt_pool_table[unit]; 688 for (i = 0; i < fc->num_pools; i++) { 689 fc_pool = &fc->flowcnt_pool[i]; 690 fc_pool->mem = pool_table[i].pool_mem; 691 num_ctr = soc_mem_index_count(unit, fc_pool->mem); 692 693 _FLOWCNT_ALLOC(unit, fc_pool->flow_byte_counter, 694 uint64, 695 sizeof(uint64) * num_ctr, 696 "Flow byte counter", 1, rv); 697 if (BCM_FAILURE(rv)) { 698 return rv; 699 } 700 _FLOWCNT_ALLOC(unit, fc_pool->flow_packet64_counter, 701 uint64, 702 sizeof(uint64) * num_ctr, 703 "Flow packet64 counter", 1, rv); 704 if (BCM_FAILURE(rv)) { 705 return rv; 706 } 707 _FLOWCNT_ALLOC(unit, fc_pool->flow_packet_counter, 708 uint32, 709 sizeof(uint32) * num_ctr, 710 "Flow packet counter", 1, rv); 711 if (BCM_FAILURE(rv)) { 712 return rv; 713 } 714 _FLOWCNT_ALLOC(unit, fc_pool->flow_base_index_reference_count, 715 uint16, 716 sizeof(uint16) * num_ctr, 717 "Flow BaseIndexAllocation", 0, rv); 718 if (BCM_FAILURE(rv)) { 719 return rv; 720 } 721 _FLOWCNT_ALLOC(unit, fc_pool->associate_profile_group, 722 uint16, 723 sizeof(uint16) * num_ctr, 724 "Flow associate_profile_group", 0, rv); 725 if (BCM_FAILURE(rv)) { 726 return rv; 727 } 728 _FLOWCNT_ALLOC(unit, fc_pool->object, 729 bcm_stat_object_t, 730 sizeof(bcm_stat_object_t) * num_ctr, 731 "Flow stat object", 0, rv); 732 if (BCM_FAILURE(rv)) { 733 return rv; 734 } 735 _FLOWCNT_ALLOC(unit, fc_pool->flow_stat_type, 736 _bcm_flowcnt_stat_type_t, 737 sizeof(_bcm_flowcnt_stat_type_t) * num_ctr, 738 "Flow stat type", 0, rv); 739 if (BCM_FAILURE(rv)) { 740 return rv; 741 } 742 if (shr_aidxres_list_create( 743 &fc_pool->flowcnt_aidxres_list_handle, 744 0, num_ctr-1, 745 0, num_ctr-1, 746 fc->counter_block, 747 "flow-counter") != BCM_E_NONE) { 748 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 749 (BSL_META_U(unit, 750 "Unrecoverable error. " 751 "Couldn't Create AllignedList:" 752 "FlowCounter\n"))); 753 return BCM_E_INTERNAL; 754 } 755 /* reserve first counter entry for warmboot recovery */ 756 shr_aidxres_list_reserve_block( 757 fc_pool->flowcnt_aidxres_list_handle, 758 pool_table->reserve_base, 759 pool_table->reserve_count); 760 } 761 762 return BCM_E_NONE; 763 } 764 765 /* 766 * Function: 767 * _bcm_esw_flowcnt_counter_collect 768 * Description: 769 * Flex Counter accumulation routine called periodically 770 * to sync s/w copy with h/w copy. 771 * Parameters: 772 * unit - (IN) unit number 773 * mem - (IN) Ingress or Egress flow counter memory 774 * if -1 Both Ingress and Egress memories 775 * else Ingress or Egress pool. 776 * counter_idx - (IN) counter index. 777 * if -1 accumulate for all counters 778 * else retrieve a specific counter. 779 * Return Value: 780 * None 781 * Notes: 782 * This routine accumulates all the flow counters and 783 * update the software copy of the flow counters. 784 * Counter thread invokes periodically this routine. 785 * If counter index is not -1 then only a specific counter 786 * value is read from harware and synced to the software copy. 787 * used by all the counter_sync_get API's 788 */ 789 STATIC void 790 _bcm_esw_flowcnt_counter_collect(int unit, 791 soc_mem_t mem, 792 uint32 counter_idx) 793 { 794 795 uint32 packet_count=0, count_mode; 796 uint64 byte_count; 797 uint32 mem_index_min; 798 uint32 mem_index_max; 799 uint32 zero=0; 800 uint32 one=1; 801 uint64 packet64_count; 802 uint64 prev_masked_byte_count, prev_masked_packet64_count; 803 uint64 max_byte_size, max_byte_mask, max_packet64_size, max_packet64_mask; 804 soc_memacc_t memacc_pkt; 805 soc_memacc_t memacc_byte; 806 soc_memacc_t memacc_countmode; 807 soc_mem_t l_mem; 808 int i, index; 809 _bcm_esw_flowcnt_control_t *fc = NULL; 810 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 811 (void)_bcm_esw_flowcnt_control_get(unit, &fc); 812 813 if (fc == NULL) { 814 return; 815 } 816 817 COMPILER_64_ZERO(byte_count); 818 COMPILER_64_ZERO(prev_masked_byte_count); 819 COMPILER_64_ZERO(max_byte_size); 820 COMPILER_64_ZERO(max_byte_mask); 821 822 COMPILER_64_ZERO(packet64_count); 823 COMPILER_64_ZERO(prev_masked_packet64_count); 824 COMPILER_64_ZERO(max_packet64_size); 825 COMPILER_64_ZERO(max_packet64_mask); 826 827 l_mem = fc->flowcnt_pool[0].mem; 828 COMPILER_64_SET(max_byte_size, zero, one); 829 COMPILER_64_SHL(max_byte_size, 830 soc_mem_field_length(unit, l_mem, BYTE_COUNTERf)); 831 832 COMPILER_64_SET(max_byte_mask, 833 COMPILER_64_HI(max_byte_size), 834 COMPILER_64_LO(max_byte_size)); 835 COMPILER_64_SUB_32(max_byte_mask,one); 836 837 COMPILER_64_SET(max_packet64_size, zero, one); 838 COMPILER_64_SHL(max_packet64_size, 839 soc_mem_field_length(unit, l_mem, PACKET_COUNTERf)); 840 841 COMPILER_64_SET(max_packet64_mask, 842 COMPILER_64_HI(max_packet64_size), 843 COMPILER_64_LO(max_packet64_size)); 844 COMPILER_64_SUB_32(max_packet64_mask,one); 845 846 for (i = 0; i < fc->num_pools; i ++) { 847 l_mem = fc->flowcnt_pool[i].mem; 848 if ((mem == -1) || (l_mem == mem)){ 849 fc_pool = &fc->flowcnt_pool[i]; 850 851 mem_index_min = soc_mem_index_min(unit, l_mem); 852 mem_index_max = soc_mem_index_max(unit, l_mem); 853 /* 854 * if counter_idx != -1, retrieve specific 855 * counter index from the flex counter memory pool. 856 */ 857 if (counter_idx != -1) { 858 if ((counter_idx < mem_index_min) || 859 (counter_idx > mem_index_max)) { 860 return; 861 } 862 mem_index_min = mem_index_max = counter_idx; 863 } 864 /* read all the counters or a specific counter from memory */ 865 if (counter_idx == -1 ) { 866 if (soc_mem_read_range(unit, l_mem, MEM_BLOCK_ANY, 867 mem_index_min, mem_index_max, 868 flowcnt_temp_counter[unit]) 869 != BCM_E_NONE) { 870 return; 871 } 872 } else { 873 if (soc_mem_read(unit, l_mem, MEM_BLOCK_ANY, 874 counter_idx, 875 &flowcnt_temp_counter[unit][counter_idx]) 876 != BCM_E_NONE) { 877 return; 878 } 879 } 880 if (((soc_memacc_init(unit, l_mem, PACKET_COUNTERf, &memacc_pkt))) || 881 ((soc_memacc_init(unit, l_mem, BYTE_COUNTERf, &memacc_byte))) || 882 ((soc_memacc_init(unit, l_mem, COUNT_BYTEf, &memacc_countmode)))) { 883 return; 884 } 885 886 for (index = mem_index_min; index <= mem_index_max; index++) { 887 count_mode = soc_memacc_field32_get(&memacc_countmode, 888 (uint32 *)&flowcnt_temp_counter[unit][index]); 889 890 if (count_mode) { 891 soc_memacc_field64_get(&memacc_byte, 892 (uint32 *)&flowcnt_temp_counter[unit][index], 893 &byte_count); 894 } else { 895 packet_count = soc_memacc_field32_get(&memacc_pkt, 896 (uint32 *)&flowcnt_temp_counter[unit][index]); 897 if (fc_pool->flow_packet_counter[index] != packet_count) { 898 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 899 (BSL_META_U(unit, 900 "Pool:%d==>" 901 "Old Packet Count Value\t:" 902 "Index:%d %x\t" 903 "New Packet Count Value %x\n"), 904 i, 905 index, 906 fc_pool->flow_packet_counter[index], 907 packet_count)); 908 fc_pool->flow_packet_counter[index] = packet_count; 909 } 910 } 911 912 COMPILER_64_SET(packet64_count,0, packet_count); 913 COMPILER_64_SET(prev_masked_packet64_count, 914 COMPILER_64_HI(fc_pool->flow_packet64_counter[index]), 915 COMPILER_64_LO(fc_pool->flow_packet64_counter[index])); 916 COMPILER_64_AND(prev_masked_packet64_count,max_packet64_mask); 917 918 if (COMPILER_64_GT(prev_masked_packet64_count, packet64_count)) { 919 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 920 (BSL_META_U(unit, 921 "Roll over happend \n"))); 922 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 923 (BSL_META_U(unit, 924 "...Read Packet64 Count : %x:%x\n"), 925 COMPILER_64_HI(packet64_count), 926 COMPILER_64_LO(packet64_count))); 927 COMPILER_64_ADD_64(packet64_count,max_packet64_size); 928 COMPILER_64_SUB_64(packet64_count,prev_masked_packet64_count); 929 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 930 (BSL_META_U(unit, 931 "...Diffed 64-Packet Count : %x:%x\n"), 932 COMPILER_64_HI(packet64_count), 933 COMPILER_64_LO(packet64_count))); 934 } else { 935 COMPILER_64_SUB_64(packet64_count,prev_masked_packet64_count); 936 } 937 /* Add difference (if it is) */ 938 if (!COMPILER_64_IS_ZERO(packet64_count)) { 939 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 940 (BSL_META_U(unit, 941 "Pool:%d==>" 942 "Old 64-Packet Count Value\t" 943 ":Index:%d %x:%x\t"), 944 i, index, 945 COMPILER_64_HI(fc_pool-> 946 flow_packet64_counter[index]), 947 COMPILER_64_LO(fc_pool-> 948 flow_packet64_counter[index]))); 949 COMPILER_64_ADD_64(fc_pool->flow_packet64_counter[index], 950 packet64_count); 951 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 952 (BSL_META_U(unit, 953 "New 64-Packet Value : %x:%x\n"), 954 COMPILER_64_HI(fc_pool-> 955 flow_packet64_counter[index]), 956 COMPILER_64_LO(fc_pool-> 957 flow_packet64_counter[index]))); 958 } 959 COMPILER_64_SET(prev_masked_byte_count, 960 COMPILER_64_HI(fc_pool->flow_byte_counter 961 [index]), 962 COMPILER_64_LO(fc_pool->flow_byte_counter 963 [index])); 964 COMPILER_64_AND(prev_masked_byte_count,max_byte_mask); 965 if (COMPILER_64_GT(prev_masked_byte_count, byte_count)) { 966 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 967 (BSL_META_U(unit, 968 "Roll over happend \n"))); 969 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 970 (BSL_META_U(unit, 971 "...Read Byte Count : %x:%x\n"), 972 COMPILER_64_HI(byte_count), 973 COMPILER_64_LO(byte_count))); 974 COMPILER_64_ADD_64(byte_count,max_byte_size); 975 COMPILER_64_SUB_64(byte_count,prev_masked_byte_count); 976 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 977 (BSL_META_U(unit, 978 "...Diffed Byte Count : %x:%x\n"), 979 COMPILER_64_HI(byte_count), 980 COMPILER_64_LO(byte_count))); 981 } else { 982 COMPILER_64_SUB_64(byte_count,prev_masked_byte_count); 983 } 984 /* Add difference (if it is) */ 985 if (!COMPILER_64_IS_ZERO(byte_count)) { 986 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 987 (BSL_META_U(unit, 988 "Pool:%d==>" 989 "Old Byte Count Value\t" 990 ":Index:%d %x:%x\t"), 991 i, index, 992 COMPILER_64_HI(fc_pool-> 993 flow_byte_counter[index]), 994 COMPILER_64_LO(fc_pool-> 995 flow_byte_counter[index]))); 996 COMPILER_64_ADD_64(fc_pool->flow_byte_counter[index], 997 byte_count); 998 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 999 (BSL_META_U(unit, 1000 "New Byte Count Value : %x:%x\n"), 1001 COMPILER_64_HI(fc_pool-> 1002 flow_byte_counter[index]), 1003 COMPILER_64_LO(fc_pool-> 1004 flow_byte_counter[index]))); 1005 } 1006 } 1007 } 1008 } 1009 return; 1010 } 1011 1012 1013 /* 1014 * Function: 1015 * _bcm_esw_flowcnt_callback 1016 * Description: 1017 * Flex Counter threads callback function. It is called periodically 1018 * to sync s/w copy with h/w copy. 1019 * Parameters: 1020 * unit - (IN) unit number 1021 * Return Value: 1022 * BCM_E_XXX 1023 * Notes: 1024 */ 1025 void _bcm_esw_flowcnt_callback(int unit) 1026 { 1027 _bcm_esw_flowcnt_control_t *fc = NULL; 1028 1029 (void)_bcm_esw_flowcnt_control_get(unit, &fc); 1030 if (fc == NULL) { 1031 return; 1032 } 1033 _FLOWCNT_LOCK(fc); 1034 _bcm_esw_flowcnt_counter_collect(unit, -1, -1); 1035 _FLOWCNT_UNLOCK(fc); 1036 1037 return; 1038 } 1039 1040 /* 1041 * Function: 1042 * _bcm_esw_flowcnt_cleanup 1043 * Description: 1044 * Clean and free all allocated flow counter resources 1045 * Parameters: 1046 * unit - (IN) unit number 1047 * Return Value: 1048 * BCM_E_XXX 1049 * Notes: 1050 */ 1051 int 1052 _bcm_esw_flowcnt_cleanup(int unit) 1053 { 1054 _bcm_esw_flowcnt_control_t *fc = NULL; 1055 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1056 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 1057 int i; 1058 1059 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1060 (BSL_META_U(unit, 1061 "_bcm_esw_flowcnt_cleanup \n"))); 1062 if (flowcnt_control[unit] != NULL) { 1063 fc = flowcnt_control[unit]; 1064 if (valid_stat_group_mode_list[unit] != NULL) { 1065 valid_stat_group_mode_list[unit] = NULL; 1066 } 1067 if (valid_stat_object_list[unit] != NULL) { 1068 valid_stat_object_list[unit] = NULL; 1069 } 1070 if (flowcnt_profile_table[unit] != NULL) { 1071 flowcnt_profile_table[unit] = NULL; 1072 } 1073 if (flowcnt_pool_table[unit] != NULL) { 1074 flowcnt_pool_table[unit] = NULL; 1075 } 1076 if (flowcnt_temp_counter[unit] != NULL) { 1077 _FLOWCNT_FREE(unit, flowcnt_temp_counter[unit], 1); 1078 flowcnt_temp_counter[unit] = NULL; 1079 } 1080 if (local_scache_ptr[unit] != NULL) { 1081 _FLOWCNT_FREE(unit, local_scache_ptr[unit], 0); 1082 local_scache_ptr[unit] = NULL; 1083 } 1084 if (fc->default_attr_mode_id != NULL) { 1085 _FLOWCNT_FREE(unit, fc->default_attr_mode_id, 0); 1086 } 1087 1088 if(fc->flowcnt_profile != NULL) { 1089 for (i = 0; i < fc->num_profiles; i++) { 1090 fc_profile = &fc->flowcnt_profile[i]; 1091 if (fc_profile->flowcnt_group != NULL) { 1092 _FLOWCNT_FREE(unit, fc_profile->flowcnt_group, 0); 1093 fc_profile->flowcnt_group = NULL; 1094 } 1095 if (fc_profile->profile_mem.tables != NULL) { 1096 soc_profile_mem_destroy(unit, &fc_profile->profile_mem); 1097 } 1098 sal_memset(fc_profile, 0, sizeof(_bcm_esw_flowcnt_profile_t)); 1099 } 1100 _FLOWCNT_FREE(unit, fc->flowcnt_profile, 0); 1101 fc->flowcnt_profile = NULL; 1102 } 1103 1104 if(fc->flowcnt_pool != NULL) { 1105 for (i = 0; i < fc->num_pools; i++) { 1106 fc_pool = &fc->flowcnt_pool[i]; 1107 if (fc_pool->flow_byte_counter != NULL) { 1108 _FLOWCNT_FREE(unit, fc_pool->flow_byte_counter, 1); 1109 fc_pool->flow_byte_counter = NULL; 1110 } 1111 if (fc_pool->flow_packet64_counter != NULL) { 1112 _FLOWCNT_FREE(unit, fc_pool->flow_packet64_counter, 1); 1113 fc_pool->flow_packet64_counter = NULL; 1114 } 1115 if (fc_pool->flow_packet_counter != NULL) { 1116 _FLOWCNT_FREE(unit, fc_pool->flow_packet_counter, 1); 1117 fc_pool->flow_packet_counter = NULL; 1118 } 1119 if (fc_pool->flow_base_index_reference_count != NULL) { 1120 _FLOWCNT_FREE(unit, 1121 fc_pool->flow_base_index_reference_count, 1122 0); 1123 fc_pool->flow_base_index_reference_count = NULL; 1124 } 1125 if (fc_pool->associate_profile_group != NULL) { 1126 _FLOWCNT_FREE(unit, 1127 fc_pool->associate_profile_group, 1128 0); 1129 fc_pool->associate_profile_group = NULL; 1130 } 1131 if (fc_pool->object != NULL) { 1132 _FLOWCNT_FREE(unit, 1133 fc_pool->object, 1134 0); 1135 fc_pool->object = NULL; 1136 } 1137 if (fc_pool->flow_stat_type != NULL) { 1138 _FLOWCNT_FREE(unit, fc_pool->flow_stat_type, 0); 1139 fc_pool->flow_stat_type = NULL; 1140 } 1141 if (fc_pool->flowcnt_aidxres_list_handle != 0) { 1142 shr_aidxres_list_destroy(fc_pool->flowcnt_aidxres_list_handle); 1143 fc_pool->flowcnt_aidxres_list_handle = 0; 1144 } 1145 sal_memset(fc_pool, 0, sizeof(_bcm_esw_flowcnt_pool_t)); 1146 } 1147 _FLOWCNT_FREE(unit, fc->flowcnt_pool, 0); 1148 fc->flowcnt_pool = NULL; 1149 } 1150 soc_counter_extra_unregister(unit, _bcm_esw_flowcnt_callback); 1151 if (fc->flowcnt_mutex != NULL) { 1152 sal_mutex_destroy(fc->flowcnt_mutex); 1153 fc->flowcnt_mutex = NULL; 1154 } 1155 _FLOWCNT_FREE(unit, flowcnt_control[unit], 0); 1156 flowcnt_control[unit] = NULL; 1157 } 1158 1159 return BCM_E_NONE; 1160 } 1161 1162 void 1163 _bcm_esw_flowcnt_counter_id_set( 1164 bcm_stat_group_mode_t group, 1165 bcm_stat_object_t object, 1166 uint32 profile_group, 1167 uint32 pool_idx, 1168 uint32 base_idx, 1169 uint32 *stat_counter_id) 1170 { 1171 *stat_counter_id = ((profile_group & _BCM_FLOWCNT_MODE_MASK) << 1172 _BCM_FLOWCNT_MODE_START_BIT) | 1173 ((group & _BCM_FLOWCNT_GROUP_MASK) << 1174 _BCM_FLOWCNT_GROUP_START_BIT) | 1175 ((pool_idx & _BCM_FLOWCNT_POOL_MASK) << 1176 _BCM_FLOWCNT_POOL_START_BIT) | 1177 ((object & _BCM_FLOWCNT_OBJECT_MASK) << 1178 _BCM_FLOWCNT_OBJECT_START_BIT) | 1179 (base_idx & _BCM_FLOWCNT_BASE_IDX_MASK); 1180 } 1181 void 1182 _bcm_esw_flowcnt_counter_id_get( 1183 uint32 stat_counter_id, 1184 bcm_stat_group_mode_t *group, 1185 bcm_stat_object_t *object, 1186 uint32 *profile_group, 1187 uint32 *pool_idx, 1188 uint32 *base_idx) 1189 { 1190 *profile_group= (uint32 ) ((stat_counter_id >> 1191 _BCM_FLOWCNT_MODE_START_BIT) & 1192 (_BCM_FLOWCNT_MODE_MASK)); 1193 *group = (bcm_stat_group_mode_t) ((stat_counter_id >> 1194 _BCM_FLOWCNT_GROUP_START_BIT) & 1195 (_BCM_FLOWCNT_GROUP_MASK)); 1196 *pool_idx = ((stat_counter_id >> _BCM_FLOWCNT_POOL_START_BIT) & 1197 (_BCM_FLOWCNT_POOL_MASK)); 1198 *object = (bcm_stat_object_t) ((stat_counter_id >> 1199 _BCM_FLOWCNT_OBJECT_START_BIT) & 1200 (_BCM_FLOWCNT_OBJECT_MASK)); 1201 *base_idx = (stat_counter_id & _BCM_FLOWCNT_BASE_IDX_MASK); 1202 } 1203 1204 /* **********************************************************/ 1205 /* COMPOSITION OF CUSTOM MODE ID */ 1206 /* **********************************************************/ 1207 /* profile_id 8 bit */ 1208 /* profile_group_id 8 bits */ 1209 /* ----- 00 - 00 */ 1210 /* Reserved profile_id profile_group_id */ 1211 /* **********************************************************/ 1212 #define _BCM_FLOWCNT_PROFILE_ID_START_BIT 8 1213 #define _BCM_FLOWCNT_PROFILE_ID_END_BIT 15 1214 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_START_BIT 0 1215 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_END_BIT 7 1216 1217 #define _BCM_FLOWCNT_PROFILE_ID_MASK \ 1218 ((1<<(_BCM_FLOWCNT_PROFILE_ID_END_BIT - _BCM_FLOWCNT_PROFILE_ID_START_BIT+1))-1) 1219 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK \ 1220 ((1<<(_BCM_FLOWCNT_PROFILE_GROUP_ID_END_BIT - _BCM_FLOWCNT_PROFILE_GROUP_ID_START_BIT+1))-1) 1221 1222 static 1223 void _bcm_esw_flowcnt_custom_mode_id_get( 1224 uint32 mode_id, int *profile_index, int *group_index) 1225 { 1226 *profile_index = ((mode_id >> _BCM_FLOWCNT_PROFILE_ID_START_BIT) & 1227 (_BCM_FLOWCNT_PROFILE_ID_MASK)); 1228 *group_index = mode_id & _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK; 1229 } 1230 1231 static 1232 void _bcm_esw_flowcnt_custom_mode_id_set( 1233 int profile_index, int group_index, uint32 *mode_id) 1234 { 1235 *mode_id = ((profile_index & _BCM_FLOWCNT_PROFILE_ID_MASK) << 1236 _BCM_FLOWCNT_PROFILE_ID_START_BIT) | 1237 (group_index & _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK); 1238 } 1239 1240 /* 1241 * internal fuction : _bcm_esw_flowcnt_selectors_cmp 1242 * Description: : compare the profile table contents 1243 * 1244 * Parameters: 1245 * unit - (IN) unit number 1246 * table - (IN) profile table 1247 * num_entries - (IN) num entries to be compared 1248 * num_src_selectors - (IN) num of selectores 1249 * num_dst_selectors - (IN) num of selectores 1250 * src_attr_selectors - (IN) src attr selectors 1251 * dst_attr_selectors - (IN) target sttr selectors 1252 * 1253 * Return Value: 1254 * 0: identical content 1255 */ 1256 static 1257 int 1258 _bcm_esw_flowcnt_selectors_cmp(int unit, soc_mem_t table, 1259 int num_entries, 1260 int num_src_selectors, 1261 int num_dst_selectors, 1262 _bcm_flowcnt_group_mode_attr_selector_t *src_attr_selectors, 1263 bcm_stat_group_mode_attr_selector_t *dst_attr_selectors) 1264 { 1265 uint32 entry_data_size = 0; 1266 uint32 *s_entries=NULL; 1267 uint32 *d_entries=NULL; 1268 int s_entry_index, d_entry_index; 1269 int i, rv; 1270 1271 entry_data_size = sizeof(uint32); 1272 _FLOWCNT_ALLOC(unit, s_entries, uint32, entry_data_size * num_entries, 1273 "temp selectors table src", 0, rv); 1274 if (BCM_FAILURE(rv)) { 1275 return BCM_E_RESOURCE; 1276 } 1277 1278 _FLOWCNT_ALLOC(unit, d_entries, uint32, entry_data_size * num_entries, 1279 "temp selectors table dst", 0, rv); 1280 if (BCM_FAILURE(rv)) { 1281 _FLOWCNT_FREE(unit, s_entries, 0); 1282 return BCM_E_RESOURCE; 1283 } 1284 1285 /* Fill the entries according to attr_selectors*/ 1286 for (i = 0; i < num_src_selectors; i++){ 1287 s_entry_index = src_attr_selectors[i].attr_value; 1288 if (SOC_MEM_FIELD_VALID(unit, table, OFFSET_VALIDf)){ 1289 soc_mem_field32_set(unit, table, &s_entries[s_entry_index], 1290 OFFSET_VALIDf, 1); 1291 } 1292 if (SOC_MEM_FIELD_VALID(unit, table, OFFSETf)){ 1293 soc_mem_field32_set(unit, table, &s_entries[s_entry_index], 1294 OFFSETf, src_attr_selectors[i].counter_offset); 1295 } 1296 } 1297 /* Fill the entries according to attr_selectors*/ 1298 for (i = 0; i < num_dst_selectors; i++){ 1299 d_entry_index = dst_attr_selectors[i].attr_value; 1300 if (SOC_MEM_FIELD_VALID(unit, table, OFFSET_VALIDf)){ 1301 soc_mem_field32_set(unit, table, &d_entries[d_entry_index], 1302 OFFSET_VALIDf, 1); 1303 } 1304 if (SOC_MEM_FIELD_VALID(unit, table, OFFSETf)){ 1305 soc_mem_field32_set(unit, table, &d_entries[d_entry_index], 1306 OFFSETf, dst_attr_selectors[i].counter_offset); 1307 } 1308 } 1309 1310 rv = sal_memcmp(s_entries, d_entries, num_entries*entry_data_size); 1311 _FLOWCNT_FREE(unit, s_entries, 0); 1312 _FLOWCNT_FREE(unit, d_entries, 0); 1313 1314 return rv; 1315 } 1316 1317 /* 1318 * Function: 1319 * _bcm_esw_flowcnt_profile_group_create 1320 * Description: 1321 * Create profile group 1322 * Parameters: 1323 * unit - (IN) unit number 1324 * direction - (IN) ingress/egress profile table 1325 * group_mode - (IN) group mode from API 1326 * total_counters - (IN) numbers of counter 1327 * num_selectors - (IN) numbers of selectors 1328 * attr_selectors - (IN) attribute selectors 1329 * profile_index - (OUT) profile_index from API 1330 * group_index - (OUT) group_index 1331 * 1332 * Return Value: 1333 * BCM_E_XXX 1334 * Notes: 1335 */ 1336 int 1337 _bcm_esw_flowcnt_profile_group_create( 1338 int unit, 1339 bcm_stat_flex_direction_t direction, 1340 bcm_stat_group_mode_t group_mode, 1341 int total_counters, 1342 int num_selectors, 1343 bcm_stat_group_mode_attr_selector_t *attr_selectors, 1344 int *profile_index, 1345 int *group_index) 1346 1347 { 1348 _bcm_esw_flowcnt_control_t *fc = NULL; 1349 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1350 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 1351 bcm_stat_group_mode_attr_t attr; 1352 int i, entry_size=0, entry_index, profile_group; 1353 int rv = BCM_E_NONE; 1354 soc_profile_mem_t profile; 1355 soc_mem_t target_table = -1; 1356 int num_group, num_entry; 1357 uint32 *entries = NULL; 1358 1359 1360 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1361 1362 if ((num_selectors !=0) && (attr_selectors == NULL)) { 1363 return BCM_E_PARAM; 1364 } 1365 attr = attr_selectors->attr; 1366 1367 _FLOWCNT_LOCK(fc); 1368 for (i = 0; i < fc->num_profiles; i++) { 1369 fc_profile = &fc->flowcnt_profile[i]; 1370 if ((fc_profile->direction == direction) && 1371 (fc_profile->attr == attr)){ 1372 target_table = fc_profile->profile_table; 1373 *profile_index = i; 1374 profile = fc_profile->profile_mem; 1375 num_group = fc_profile->num_groups; 1376 break; 1377 } 1378 } 1379 if (target_table == -1) { 1380 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1381 (BSL_META_U(unit, 1382 "Couldn't find the matched profile.\n"))); 1383 _FLOWCNT_UNLOCK(fc); 1384 return BCM_E_INTERNAL; 1385 } 1386 if (total_counters > (1 << fc->counter_block)) { 1387 _FLOWCNT_UNLOCK(fc); 1388 return BCM_E_PARAM; 1389 } 1390 num_entry = soc_mem_index_count(unit, target_table) / num_group; 1391 if (num_selectors > num_entry) { 1392 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1393 (BSL_META_U(unit, 1394 "Couldn't support %d selectors. " 1395 "Maximum %d selectors\n"), 1396 num_selectors, num_entry)); 1397 _FLOWCNT_UNLOCK(fc); 1398 return BCM_E_PARAM; 1399 } 1400 /* Allocate the entries */ 1401 entry_size = sizeof(uint32); 1402 _FLOWCNT_ALLOC(unit, entries, uint32, num_entry * entry_size, 1403 "flowcnt offset table entries", 0, rv); 1404 1405 if (BCM_FAILURE(rv)){ 1406 _FLOWCNT_UNLOCK(fc); 1407 return rv; 1408 } 1409 _FLOWCNT_UNLOCK(fc); 1410 1411 /* Fill the entries according to attr_selectors*/ 1412 for (i = 0; i < num_selectors; i++){ 1413 entry_index = attr_selectors[i].attr_value; 1414 if (entry_index > (num_entry - 1)) { 1415 _FLOWCNT_FREE(unit, entries, 0); 1416 return BCM_E_PARAM; 1417 } 1418 if (attr_selectors[i].counter_offset > ((1 << fc->counter_block)-1)) { 1419 _FLOWCNT_FREE(unit, entries, 0); 1420 return BCM_E_PARAM; 1421 } 1422 if (SOC_MEM_FIELD_VALID(unit, target_table, OFFSET_VALIDf)){ 1423 soc_mem_field32_set(unit, target_table, &entries[entry_index], 1424 OFFSET_VALIDf, 1); 1425 } 1426 if (SOC_MEM_FIELD_VALID(unit, target_table, OFFSETf)){ 1427 soc_mem_field32_set(unit, target_table, &entries[entry_index], 1428 OFFSETf, attr_selectors[i].counter_offset); 1429 } 1430 } 1431 soc_mem_lock(unit, target_table); 1432 rv = soc_profile_mem_add(unit, &profile, 1433 (void *)&entries, num_entry, (uint32 *)group_index); 1434 if (BCM_FAILURE(rv)) { 1435 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1436 (BSL_META_U(unit, 1437 "Error: Adding profile entry" 1438 " - %s.\n"), bcm_errmsg(rv))); 1439 _FLOWCNT_FREE(unit, entries, 0); 1440 soc_mem_unlock(unit, target_table); 1441 return (rv); 1442 } 1443 profile_group = *group_index / num_entry; 1444 *group_index = profile_group; 1445 soc_mem_unlock(unit, target_table); 1446 _FLOWCNT_FREE(unit, entries, 0); 1447 1448 /* Update the profile group reference count */ 1449 _FLOWCNT_LOCK(fc); 1450 fc_profile = &fc->flowcnt_profile[*profile_index]; 1451 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 1452 1453 if (fc_pgroup->available == 0) { 1454 _FLOWCNT_ALLOC(unit, fc_pgroup->attr_selectors, 1455 _bcm_flowcnt_group_mode_attr_selector_t, 1456 num_selectors * 1457 sizeof(_bcm_flowcnt_group_mode_attr_selector_t), 1458 "flowcnt pkt attr per profile group", 0, rv); 1459 1460 if (BCM_FAILURE(rv)){ 1461 _FLOWCNT_FREE(unit, attr_selectors, 0); 1462 _FLOWCNT_UNLOCK(fc); 1463 return rv; 1464 } 1465 for (i = 0; i < num_selectors; i++) { 1466 fc_pgroup->attr_selectors[i].attr = 1467 attr_selectors[i].attr; 1468 fc_pgroup->attr_selectors[i].counter_offset = 1469 attr_selectors[i].counter_offset; 1470 fc_pgroup->attr_selectors[i].attr_value = 1471 attr_selectors[i].attr_value; 1472 } 1473 fc_pgroup->num_selectors = num_selectors; 1474 fc_pgroup->total_counters = total_counters; 1475 fc_pgroup->group_mode = group_mode; 1476 fc_pgroup->available = 1; 1477 } 1478 _FLOWCNT_UNLOCK(fc); 1479 1480 return rv; 1481 } 1482 1483 int 1484 _bcm_esw_flowcnt_default_attr_config(int unit, 1485 bcm_stat_group_mode_attr_t attr, 1486 int num_selctors, 1487 bcm_stat_group_mode_attr_selector_t *attr_selectors) 1488 { 1489 int i; 1490 for (i = 0; i < num_selctors; i++){ 1491 attr_selectors[i].attr = attr; 1492 attr_selectors[i].attr_value = i; 1493 attr_selectors[i].counter_offset = 0; 1494 } 1495 return BCM_E_NONE; 1496 } 1497 1498 /* 1499 * Function: 1500 * _bcm_esw_flowcnt_object_table_map 1501 * Description: 1502 * Get the object table informantion based on the the giving object 1503 * Parameters: 1504 * unit - (IN) unit number 1505 * object - (IN) object. 1506 * profile_index - (OUT) profile_index 1507 * pool_index - (OUT) pool_index 1508 * 1509 * Return Value: 1510 * BCM_E_XXX 1511 * Notes: 1512 */ 1513 STATIC int 1514 _bcm_esw_flowcnt_object_table_map(int unit, 1515 bcm_stat_object_t object, 1516 int *profile_index, 1517 int *pool_index) 1518 { 1519 int i; 1520 int object_index = -1; 1521 soc_mem_t pool_table, offset_table; 1522 _bcm_esw_flowcnt_control_t *fc = NULL; 1523 1524 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1525 1526 *pool_index = -1; 1527 *profile_index = -1; 1528 1529 for (i = 0; valid_stat_object_list[unit][i].object != -1; i++) { 1530 if (valid_stat_object_list[unit][i].object == object) { 1531 object_index = i; 1532 break; 1533 } 1534 } 1535 1536 if (object_index == -1) { 1537 return BCM_E_INTERNAL; 1538 } 1539 pool_table = valid_stat_object_list[unit][object_index].counter_mem; 1540 offset_table = valid_stat_object_list[unit][object_index].offset_mem; 1541 1542 for (i = 0; i < fc->num_profiles; i ++) { 1543 if (flowcnt_profile_table[unit][i].mem == offset_table) { 1544 *profile_index = i; 1545 break; 1546 } 1547 } 1548 if (*profile_index == -1) { 1549 return BCM_E_INTERNAL; 1550 } 1551 for (i = 0; i < fc->num_pools; i ++) { 1552 if (flowcnt_pool_table[unit][i].pool_mem == pool_table) { 1553 *pool_index = i; 1554 break; 1555 } 1556 } 1557 if (*pool_index == -1) { 1558 return BCM_E_INTERNAL; 1559 } 1560 return BCM_E_NONE; 1561 } 1562 1563 /* 1564 * Function: 1565 * _bcm_esw_flowcnt_counter_destroy 1566 * Description: 1567 * Destroy accounting table's statistics completely 1568 * Parameters: 1569 * unit - (IN) unit number 1570 * object - (IN) Accounting Object 1571 * profile_group - (IN) profile group for Accounting Object 1572 * base_idx - (IN) Base Index for Accounting Object 1573 * pool_number - (IN) Pool Number for Accounting Object 1574 * 1575 * Return Value: 1576 * BCM_E_XXX 1577 * Notes: 1578 */ 1579 int 1580 _bcm_esw_flowcnt_counter_destroy( 1581 int unit, 1582 bcm_stat_object_t object, 1583 uint32 profile_group, 1584 uint32 base_idx, 1585 uint32 pool_number) 1586 { 1587 _bcm_esw_flowcnt_control_t *fc = NULL; 1588 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 1589 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1590 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 1591 int pool_idx, profile_index; 1592 int total_counters; 1593 int rv, i; 1594 uint32 free_count=0; 1595 uint32 alloc_count=0; 1596 uint32 largest_free=0, stat_counter_id=0; 1597 1598 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1599 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 1600 &profile_index, 1601 &pool_idx); 1602 if (BCM_FAILURE(rv)){ 1603 return rv; 1604 } 1605 if (pool_idx != pool_number){ 1606 return BCM_E_PARAM; 1607 } 1608 1609 _FLOWCNT_LOCK(fc); 1610 fc_pool = &fc->flowcnt_pool[pool_idx]; 1611 fc_profile = &fc->flowcnt_profile[profile_index]; 1612 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 1613 1614 if (fc_pgroup->available == 0) { 1615 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1616 (BSL_META_U(unit, 1617 "The profile_group is not available.\n"))); 1618 _FLOWCNT_UNLOCK(fc); 1619 return BCM_E_NOT_FOUND; 1620 } 1621 if (shr_aidxres_list_elem_state(fc_pool->flowcnt_aidxres_list_handle, 1622 base_idx) != BCM_E_EXISTS) { 1623 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1624 (BSL_META_U(unit, 1625 "Wrong base index %u \n"), 1626 base_idx)); 1627 _FLOWCNT_UNLOCK(fc); 1628 return BCM_E_NOT_FOUND; 1629 } 1630 1631 total_counters = fc_pgroup->total_counters; 1632 rv = shr_aidxres_list_free(fc_pool->flowcnt_aidxres_list_handle, base_idx); 1633 if (BCM_SUCCESS(rv)){ 1634 fc_pool->pool_stat.used_entries -= total_counters; 1635 for (i = 0; i < total_counters; i ++){ 1636 fc_pool->flow_stat_type[base_idx+i] = 0; 1637 } 1638 fc_pool->associate_profile_group[base_idx] = 0; 1639 fc_pool->object[base_idx] = 0; 1640 shr_aidxres_list_state(fc_pool->flowcnt_aidxres_list_handle, 1641 NULL,NULL,NULL,NULL,&free_count,&alloc_count,&largest_free, 1642 NULL); 1643 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1644 (BSL_META_U(unit, 1645 "Current Pool status free_count:%d alloc_count:%d " 1646 "largest_free:%d " 1647 "used_entries:%d\n"), 1648 free_count,alloc_count,largest_free, 1649 fc_pool->pool_stat.used_entries)); 1650 1651 fc_pgroup->reference_count--; 1652 _bcm_esw_flowcnt_counter_id_set( 1653 fc_pgroup->group_mode, 1654 object, 1655 profile_group, 1656 pool_idx, 1657 base_idx, 1658 &stat_counter_id); 1659 if (_bcm_esw_flowcnt_stat_id_delete( 1660 local_scache_ptr[unit], stat_counter_id) != BCM_E_NONE) { 1661 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 1662 (BSL_META_U(unit, 1663 "Could not delete entry in scache memory.\n"))); 1664 } 1665 } 1666 _FLOWCNT_UNLOCK(fc); 1667 1668 return rv; 1669 } 1670 1671 /* 1672 * Function: 1673 * _bcm_esw_flowcnt_counter_create 1674 * Description: 1675 * Allocate counter based on pool_index basis 1676 * Parameters: 1677 * unit - (IN) unit number 1678 * object - (IN) object. 1679 * total_counters - (IN) Total Counters need to be allocated. 1680 * base_index - (OUT) profile_index 1681 * pool_index - (OUT) pool_index 1682 * 1683 * Return Value: 1684 * BCM_E_XXX 1685 * Notes: 1686 */ 1687 int 1688 _bcm_esw_flowcnt_counter_create(int unit, bcm_stat_object_t object, 1689 uint32 profile_group, 1690 int total_counters, int *base_index, 1691 int *pool_index) 1692 { 1693 _bcm_esw_flowcnt_control_t *fc = NULL; 1694 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1695 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 1696 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 1697 int rv, base_idx_l; 1698 int pool_idx, profile_index, i; 1699 uint32 free_count=0; 1700 uint32 alloc_count=0; 1701 uint32 largest_free=0; 1702 uint32 stat_counter_id; 1703 1704 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1705 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 1706 &profile_index, 1707 &pool_idx); 1708 if (BCM_FAILURE(rv)){ 1709 return rv; 1710 } 1711 _FLOWCNT_LOCK(fc); 1712 fc_profile = &fc->flowcnt_profile[profile_index]; 1713 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 1714 fc_pool = &fc->flowcnt_pool[pool_idx]; 1715 1716 if (fc_pgroup->available == 0) { 1717 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1718 (BSL_META_U(unit, 1719 "The profile_group is not available.\n"))); 1720 _FLOWCNT_UNLOCK(fc); 1721 return BCM_E_PARAM; 1722 } 1723 rv = shr_aidxres_list_alloc_block(fc_pool->flowcnt_aidxres_list_handle, 1724 total_counters, (uint32 *)&base_idx_l); 1725 1726 if (BCM_SUCCESS(rv)){ 1727 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1728 (BSL_META_U(unit, 1729 "Allocated counter for Table:%s " 1730 "pool_idx:%d base_idx:%d \n"), 1731 SOC_MEM_UFNAME(unit, fc_pool->mem), 1732 pool_idx, base_idx_l)); 1733 1734 fc_pool->pool_stat.used_entries += total_counters; 1735 for (i = 0; i < total_counters; i ++) { 1736 fc_pool->flow_stat_type[base_idx_l+i] = bcmFlowcntStatTypePacket; 1737 } 1738 fc_pool->associate_profile_group[base_idx_l] = 1739 profile_group + _BCM_FLOWCNT_PGROUP_BIAS; 1740 fc_pool->object[base_idx_l] = object; 1741 shr_aidxres_list_state(fc_pool->flowcnt_aidxres_list_handle, 1742 NULL,NULL,NULL,NULL,&free_count,&alloc_count,&largest_free, 1743 NULL); 1744 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1745 (BSL_META_U(unit, 1746 "Current Pool status free_count:%d alloc_count:%d " 1747 "largest_free:%d " 1748 "used_entries:%d\n"), 1749 free_count,alloc_count,largest_free, 1750 fc_pool->pool_stat.used_entries)); 1751 *base_index = base_idx_l; 1752 *pool_index = pool_idx; 1753 1754 fc_pgroup->reference_count++; 1755 _bcm_esw_flowcnt_counter_id_set( 1756 fc_pgroup->group_mode, 1757 object, 1758 profile_group, 1759 *pool_index, 1760 *base_index, 1761 &stat_counter_id); 1762 if (_bcm_esw_flowcnt_stat_id_insert( 1763 local_scache_ptr[unit],stat_counter_id) != BCM_E_NONE) { 1764 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 1765 (BSL_META_U(unit, 1766 "Could not add entry in scache memory." 1767 "Attach it\n"))); 1768 } 1769 } 1770 _FLOWCNT_UNLOCK(fc); 1771 1772 return rv; 1773 } 1774 /* 1775 * Function: 1776 * _bcm_esw_flowcnt_object_table_detach 1777 * Description: 1778 * Detach i.e. Disable Igresss accounting table's statistics 1779 * Parameters: 1780 * unit - (IN) unit number 1781 * table - (IN) Flex Accounting Table 1782 * index - (IN) Flex Accounting Table's Index 1783 * 1784 * Return Value: 1785 * BCM_E_XXX 1786 * Notes: 1787 */ 1788 int _bcm_esw_flowcnt_object_table_detach( 1789 int unit, 1790 soc_mem_t table, 1791 uint32 index) 1792 { 1793 _bcm_esw_flowcnt_control_t *fc = NULL; 1794 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 1795 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1796 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 1797 void *entry_data = NULL; 1798 uint32 entry_data_size = 0; 1799 soc_mem_info_t *memp = NULL; 1800 int i, valid = -1; 1801 uint32 profile_ptr, base_index; 1802 flowcnt_object_info_t *stat_object_list; 1803 int object_index, pool_index, profile_index; 1804 counter_table_entry_t counter_entry; 1805 int rv; 1806 bcm_stat_object_t object; 1807 uint32 stat_counter_id; 1808 1809 stat_object_list = valid_stat_object_list[unit]; 1810 for (i = 0; stat_object_list[i].object_mem != -1; i++) { 1811 if (table == stat_object_list[i].object_mem) { 1812 object = stat_object_list[i].object; 1813 valid = 1; 1814 break; 1815 } 1816 } 1817 if (valid == -1) { 1818 return BCM_E_PARAM; 1819 } 1820 1821 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1822 1823 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get( 1824 unit, table, index, 1825 &profile_ptr, &base_index, &object_index)); 1826 1827 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_object_table_map( 1828 unit, stat_object_list[object_index].object, 1829 &profile_index, &pool_index)); 1830 1831 _FLOWCNT_LOCK(fc); 1832 fc_pool = &fc->flowcnt_pool[pool_index]; 1833 fc_profile = &fc->flowcnt_profile[profile_index]; 1834 fc_pgroup = &fc_profile->flowcnt_group[profile_ptr]; 1835 fc_pool->flow_base_index_reference_count[base_index]--; 1836 fc_pool->pool_stat.attached_entries -= fc_pgroup->total_counters; 1837 /* Clear Counter Values */ 1838 if (fc_pool->flow_base_index_reference_count[base_index] == 0) { 1839 sal_memset(&counter_entry, 0, sizeof(counter_table_entry_t)); 1840 for (i = 0; i < fc_pgroup->total_counters; i ++) { 1841 COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index + i], 1842 0, 0); 1843 COMPILER_64_SET(fc_pool->flow_byte_counter[base_index + i], 1844 0, 0); 1845 fc_pool->flow_packet_counter[base_index + i] = 0; 1846 soc_mem_write(unit, fc_pool->mem, MEM_BLOCK_ALL, 1847 base_index + i, 1848 &counter_entry); 1849 } 1850 } 1851 1852 memp = &SOC_MEM_INFO(unit, table); 1853 entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes)); 1854 _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size, 1855 "object table entry", 0, rv); 1856 1857 rv = soc_mem_read(unit, table, MEM_BLOCK_ANY, 1858 index, entry_data); 1859 if (BCM_FAILURE(rv)) { 1860 _FLOWCNT_FREE(unit, entry_data, 0); 1861 _FLOWCNT_UNLOCK(fc); 1862 return rv; 1863 } 1864 1865 rv = _bcm_esw_flowcnt_object_table_fields_values_set( 1866 unit, index, table, entry_data, 0, 0); 1867 1868 if (BCM_FAILURE(rv)) { 1869 _FLOWCNT_FREE(unit, entry_data, 0); 1870 _FLOWCNT_UNLOCK(fc); 1871 return rv; 1872 } 1873 1874 if (soc_mem_write(unit, table, MEM_BLOCK_ALL, 1875 index, 1876 entry_data) != SOC_E_NONE) { 1877 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1878 (BSL_META_U(unit, 1879 "Table:%s:Index:%d: encounter some problem \n"), 1880 SOC_MEM_UFNAME(unit, table), index)); 1881 _FLOWCNT_FREE(unit, entry_data, 0); 1882 _FLOWCNT_UNLOCK(fc); 1883 return BCM_E_INTERNAL; 1884 } 1885 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 1886 (BSL_META_U(unit, 1887 "Deallocated Table:%s:Index:%d:mode:%d" 1888 "reference_count %d \n"), 1889 SOC_MEM_UFNAME(unit, table),index,profile_ptr, 1890 fc_pool->flow_base_index_reference_count[base_index])); 1891 1892 _FLOWCNT_FREE(unit, entry_data, 0); 1893 1894 _bcm_esw_flowcnt_counter_id_set( 1895 fc_pgroup->group_mode, 1896 object, 1897 profile_ptr, 1898 pool_index, 1899 base_index, 1900 &stat_counter_id); 1901 if (fc_pool->flow_base_index_reference_count[base_index] == 0) { 1902 if (_bcm_esw_flowcnt_stat_id_insert( 1903 local_scache_ptr[unit],stat_counter_id) != BCM_E_NONE) { 1904 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 1905 (BSL_META_U(unit, 1906 "Could not add entry in scache memory.\n"))); 1907 } 1908 } 1909 _FLOWCNT_UNLOCK(fc); 1910 return BCM_E_NONE; 1911 } 1912 1913 /* 1914 * Function: 1915 * _bcm_esw_flowcnt_object_table_attach 1916 * Description: 1917 * Atach i.e. Enable Ingresss accounting table's statistics 1918 * Parameters: 1919 * unit - (IN) unit number 1920 * table - (IN) Flex Accounting Table 1921 * index - (IN) Flex Accounting Table's Index 1922 * mode - (IN) Flex offset mode for Accounting Object 1923 * base_idx - (IN) Flex Base Index for Accounting Object 1924 * pool_idx - (IN) Flex Pool Index for Accounting Object 1925 * ingress_entry_data1 - (IN) Entry Data(Null or Valid) 1926 * Null, table will be modified 1927 * NON-Null, table won't be modified 1928 * Return Value: 1929 * BCM_E_XXX 1930 */ 1931 int _bcm_esw_flowcnt_object_table_attach( 1932 int unit, 1933 bcm_stat_object_t object, 1934 soc_mem_t table, 1935 uint32 index, 1936 int profile_group, 1937 uint32 base_idx, 1938 uint32 pool_idx, 1939 void *entry_data1) 1940 { 1941 _bcm_esw_flowcnt_control_t *fc = NULL; 1942 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 1943 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 1944 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 1945 int rv; 1946 void *entry_data_temp = NULL; 1947 void *entry_data = NULL; 1948 uint32 entry_data_size = 0; 1949 soc_mem_info_t *memp = NULL; 1950 uint32 profile_ptr, base_index; 1951 int object_table_index, pool_idx_l, profile_index; 1952 uint32 stat_counter_id; 1953 1954 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 1955 1956 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 1957 &profile_index, &pool_idx_l); 1958 if (BCM_FAILURE(rv)) { 1959 return rv; 1960 } 1961 if (pool_idx_l != pool_idx) { 1962 return BCM_E_INTERNAL; 1963 } 1964 1965 _FLOWCNT_LOCK(fc); 1966 fc_pool = &fc->flowcnt_pool[pool_idx]; 1967 fc_profile = &fc->flowcnt_profile[profile_index]; 1968 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 1969 1970 if (fc_pgroup->available == 0) { 1971 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1972 (BSL_META_U(unit, 1973 "flowcnt profile group:%d:Not configured yet\n"), 1974 profile_group)); 1975 _FLOWCNT_UNLOCK(fc); 1976 return BCM_E_NOT_FOUND; 1977 } 1978 if (shr_aidxres_list_elem_state(fc_pool->flowcnt_aidxres_list_handle, 1979 base_idx) != BCM_E_EXISTS) { 1980 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 1981 (BSL_META_U(unit, 1982 "Wrong base index %u \n"), 1983 base_idx)); 1984 _FLOWCNT_UNLOCK(fc); 1985 return BCM_E_NOT_FOUND; 1986 } 1987 _FLOWCNT_UNLOCK(fc); 1988 1989 memp = &SOC_MEM_INFO(unit, table); 1990 entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes)); 1991 1992 if (entry_data1 == NULL ) { 1993 _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size, 1994 "object table entry", 0, rv); 1995 if (BCM_FAILURE(rv)){ 1996 return rv; 1997 } 1998 if (soc_mem_read(unit, table, MEM_BLOCK_ANY, 1999 index, 2000 entry_data) != SOC_E_NONE) { 2001 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 2002 (BSL_META_U(unit, 2003 "Read failure for Table %s with index %d \n"), 2004 SOC_MEM_UFNAME(unit, table),index)); 2005 _FLOWCNT_FREE(unit, entry_data, 0); 2006 return BCM_E_INTERNAL; 2007 } 2008 entry_data_temp = entry_data; 2009 } else { 2010 entry_data_temp = entry_data1; 2011 } 2012 2013 if (soc_mem_field_valid(unit, table, VALIDf)) { 2014 if (soc_mem_field32_get(unit, table, entry_data_temp, 2015 VALIDf) == 0) { 2016 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 2017 (BSL_META_U(unit, 2018 "Table %s with index %d is Not valid \n"), 2019 SOC_MEM_UFNAME(unit, table),index)); 2020 if (entry_data1 == NULL) { 2021 _FLOWCNT_FREE(unit, entry_data, 0); 2022 } 2023 return BCM_E_PARAM; 2024 } 2025 } 2026 rv = _bcm_esw_flowcnt_object_table_fields_values_get( 2027 unit, index, table, entry_data_temp, 2028 &profile_ptr, &base_index); 2029 if (BCM_FAILURE(rv)) { 2030 if (entry_data1 == NULL) { 2031 _FLOWCNT_FREE(unit, entry_data, 0); 2032 } 2033 return rv; 2034 } 2035 if (base_index != 0) { 2036 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 2037 (BSL_META_U(unit, 2038 "Table:%s Has already allocated with index:%d" 2039 "base %d mode %d." 2040 "First dealloc it \n"), 2041 SOC_MEM_UFNAME(unit, table), 2042 index,base_index,profile_ptr)); 2043 if (entry_data1 == NULL) { 2044 _FLOWCNT_FREE(unit, entry_data, 0); 2045 } 2046 return BCM_E_EXISTS;/*Either NotConfigured or deallocated before */ 2047 } 2048 rv = _bcm_esw_flowcnt_object_table_fields_values_set( 2049 unit, index, table, entry_data_temp, profile_group, base_idx); 2050 if (BCM_FAILURE(rv)) { 2051 if (entry_data1 == NULL) { 2052 _FLOWCNT_FREE(unit, entry_data, 0); 2053 } 2054 return rv; 2055 } 2056 if (entry_data1 == NULL) { 2057 if (soc_mem_write(unit, table, MEM_BLOCK_ALL, 2058 index, 2059 entry_data_temp) != SOC_E_NONE) { 2060 _FLOWCNT_FREE(unit, entry_data, 0); 2061 return BCM_E_INTERNAL; 2062 } 2063 } 2064 2065 rv = _bcm_esw_flowcnt_object_table_index_get( 2066 unit, index, table, entry_data_temp, &object_table_index); 2067 if (BCM_FAILURE(rv)) { 2068 if (entry_data1 == NULL) { 2069 _FLOWCNT_FREE(unit, entry_data, 0); 2070 } 2071 return rv; 2072 } 2073 2074 if (entry_data1 == NULL) { 2075 _FLOWCNT_FREE(unit, entry_data, 0); 2076 } 2077 2078 _FLOWCNT_LOCK(fc); 2079 _bcm_esw_flowcnt_counter_id_set( 2080 fc_pgroup->group_mode, 2081 object, 2082 profile_group, 2083 pool_idx, 2084 base_idx, 2085 &stat_counter_id); 2086 if (fc_pool->flow_base_index_reference_count[base_idx] == 0) { 2087 if (_bcm_esw_flowcnt_stat_id_delete( 2088 local_scache_ptr[unit], stat_counter_id) != BCM_E_NONE) { 2089 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 2090 (BSL_META_U(unit, 2091 "Could not delete entry in scache memory.\n"))); 2092 } 2093 } 2094 fc_pool->flow_base_index_reference_count[base_idx]++; 2095 fc_pool->pool_stat.attached_entries += fc_pgroup->total_counters; 2096 _FLOWCNT_UNLOCK(fc); 2097 2098 return rv; 2099 } 2100 2101 /* 2102 * Function: 2103 * _bcm_esw_flowcnt_init 2104 * Description: 2105 * Initialize and allocate all required resources 2106 * Parameters: 2107 * unit - (IN) unit number 2108 * Return Value: 2109 * BCM_E_XXX 2110 * Notes: 2111 */ 2112 int 2113 _bcm_esw_flowcnt_init(int unit) 2114 { 2115 int rv=BCM_E_NONE; 2116 _bcm_esw_flowcnt_control_t *fc = NULL; 2117 #ifdef BCM_WARM_BOOT_SUPPORT 2118 int stable_size=0; 2119 int stable_used_size=0; 2120 int additional_scache_size = 0; 2121 #endif 2122 2123 /* clean up the resource */ 2124 if (flowcnt_control[unit] != NULL) { 2125 rv = _bcm_esw_flowcnt_cleanup(unit); 2126 if (BCM_FAILURE(rv)){ 2127 return rv; 2128 } 2129 } 2130 2131 /* Allocate Flowcnt control memeory for this unit. */ 2132 _FLOWCNT_ALLOC(unit, fc, _bcm_esw_flowcnt_control_t, 2133 sizeof(_bcm_esw_flowcnt_control_t), 2134 "Flowcnt control", 0, rv); 2135 if (BCM_FAILURE(rv)){ 2136 return rv; 2137 } 2138 2139 /* Set up the unit flowcnt control structure. */ 2140 flowcnt_control[unit] = fc; 2141 2142 /* Create protection mutex. */ 2143 fc->flowcnt_mutex = sal_mutex_create("flowcnt_control.lock"); 2144 if (NULL == fc->flowcnt_mutex) { 2145 _bcm_esw_flowcnt_cleanup(unit); 2146 return (BCM_E_INTERNAL); 2147 } 2148 /* 2149 * chip specific table assignment 2150 * NOTE: chip specific information need to be addressed here. 2151 */ 2152 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2153 rv = _bcm_hr3_flowcnt_ctrl_init(unit, fc); 2154 if (BCM_FAILURE(rv)) { 2155 _bcm_esw_flowcnt_cleanup(unit); 2156 return (BCM_E_MEMORY); 2157 } 2158 } 2159 /* common flowcnt ctrl init */ 2160 rv = _bcm_flowcnt_ctrl_common_init(unit, fc); 2161 if (BCM_FAILURE(rv)) { 2162 _bcm_esw_flowcnt_cleanup(unit); 2163 return (BCM_E_MEMORY); 2164 } 2165 2166 rv = soc_counter_extra_register(unit, _bcm_esw_flowcnt_callback); 2167 if (BCM_FAILURE(rv)) { 2168 _bcm_esw_flowcnt_cleanup(unit); 2169 return (BCM_E_MEMORY); 2170 } 2171 2172 local_scache_size = FLOWCNT_SCACHE_SIZE_1; 2173 _FLOWCNT_ALLOC(unit, local_scache_ptr[unit], uint8, 2174 local_scache_size, 2175 "local scahced", 0, rv); 2176 if (BCM_FAILURE(rv)) { 2177 _bcm_esw_flowcnt_cleanup(unit); 2178 return (BCM_E_MEMORY); 2179 } 2180 2181 /* WARMBOOT related */ 2182 #ifdef BCM_WARM_BOOT_SUPPORT 2183 flowcnt_scache_allocated_size[unit] = 0; 2184 /* flowcnt will not co-exist with flex cnt, use the same partition */ 2185 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_STAT, 2186 _BCM_STAT_WARM_BOOT_CHUNK_FLEX); 2187 SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_STAT, 1); 2188 local_scache_size += FLOWCNT_SCACHE_SIZE_2_LOCAL; 2189 local_scache_size += FLOWCNT_SCACHE_SIZE_3; 2190 if (!SOC_WARM_BOOT(unit)) { 2191 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2192 (BSL_META_U(unit, 2193 "ColdBoot: Modified Local Scache Size %d \n"), 2194 local_scache_size)); 2195 rv = soc_stable_size_get(unit, &stable_size); 2196 if (BCM_FAILURE(rv)) { 2197 _bcm_esw_flowcnt_cleanup(unit); 2198 return (rv); 2199 } 2200 if (stable_size == 0) { 2201 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2202 (BSL_META_U(unit, 2203 "STABLE size is zero.Probably NotConfigured yet\n"))); 2204 return BCM_E_NONE; 2205 } 2206 2207 /* Check if scache already allocated */ 2208 rv = soc_scache_ptr_get(unit, 2209 handle, 2210 (uint8 **)&flowcnt_scache_ptr[unit], 2211 &flowcnt_scache_allocated_size[unit]); 2212 if (rv == BCM_E_NOT_FOUND) { 2213 /* We have not allocated scache, continue with allocation */ 2214 rv = soc_stable_used_get(unit, &stable_used_size); 2215 if (BCM_FAILURE(rv)) { 2216 _bcm_esw_flowcnt_cleanup(unit); 2217 return rv; 2218 } 2219 2220 if ((stable_size - stable_used_size) < local_scache_size) { 2221 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2222 (BSL_META_U(unit, 2223 "Not enough scache memory left...\n"))); 2224 _bcm_esw_flowcnt_cleanup(unit); 2225 return BCM_E_CONFIG; 2226 } 2227 2228 rv = soc_scache_alloc(unit, handle, local_scache_size); 2229 if (!((rv == BCM_E_NONE) || (rv == BCM_E_EXISTS))) { 2230 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2231 (BSL_META_U(unit, 2232 "Seems to be some internal " 2233 "problem.\n"))); 2234 _bcm_esw_flowcnt_cleanup(unit); 2235 return rv; 2236 } 2237 } else if (rv == SOC_E_NONE) { 2238 /* We have already allocated scache (reload case) confirmed size */ 2239 if (flowcnt_scache_allocated_size[unit] < local_scache_size) { 2240 /* scache is increased due to increase in attribute selectors. 2241 * So realloc size to accomodate wb sync. 2242 */ 2243 additional_scache_size = local_scache_size - 2244 flowcnt_scache_allocated_size[unit]; 2245 rv = soc_scache_realloc(unit, handle, 2246 additional_scache_size); 2247 if (!((rv == BCM_E_NONE) || (rv == BCM_E_EXISTS))) { 2248 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2249 (BSL_META_U(unit, 2250 "Seems to be some internal " 2251 "problem.\n"))); 2252 _bcm_esw_flowcnt_cleanup(unit); 2253 return rv; 2254 } 2255 } 2256 } else { 2257 LOG_WARN(BSL_LS_BCM_FLEXCTR, 2258 (BSL_META_U(unit, 2259 "Seems to be some internal problem.\n"))); 2260 _bcm_esw_flowcnt_cleanup(unit); 2261 return rv; 2262 } 2263 2264 rv = soc_scache_ptr_get(unit, 2265 handle, 2266 (uint8 **)&flowcnt_scache_ptr[unit], 2267 &flowcnt_scache_allocated_size[unit]); 2268 if (BCM_FAILURE(rv)) { 2269 LOG_WARN(BSL_LS_BCM_FLEXCTR, 2270 (BSL_META_U(unit, 2271 "Error getting scache handle\n"))); 2272 _bcm_esw_flowcnt_cleanup(unit); 2273 return rv; 2274 } 2275 } else { 2276 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2277 (BSL_META_U(unit, 2278 "WARM Booting... \n"))); 2279 2280 rv = soc_scache_ptr_get(unit, 2281 handle, 2282 (uint8 **)&flowcnt_scache_ptr[unit], 2283 &flowcnt_scache_allocated_size[unit]); 2284 2285 /* You may get BCM_E_NOT_FOUND for level 1 warm boot */ 2286 if (rv == BCM_E_NOT_FOUND) { 2287 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 2288 (BSL_META_U(unit, 2289 "Seems to be Level-1 Warm boot..." 2290 "continuing..\n"))); 2291 _bcm_esw_flowcnt_warmboot_object_retrive(unit); 2292 return BCM_E_NONE; 2293 } 2294 if (rv != BCM_E_NONE) { 2295 LOG_WARN(BSL_LS_BCM_FLEXCTR, 2296 (BSL_META_U(unit, 2297 "Seems to be some internal problem.\n"))); 2298 _bcm_esw_flowcnt_cleanup(unit); 2299 return rv; 2300 } 2301 } 2302 if (flowcnt_scache_ptr[unit] == NULL) { 2303 _bcm_esw_flowcnt_cleanup(unit); 2304 return BCM_E_MEMORY; 2305 } 2306 if (flowcnt_scache_allocated_size[unit] != local_scache_size) { 2307 if (!SOC_WARM_BOOT(unit)) { 2308 _bcm_esw_flowcnt_cleanup(unit); 2309 return BCM_E_INTERNAL; 2310 } else if (flowcnt_scache_allocated_size[unit] > local_scache_size){ 2311 LOG_WARN(BSL_LS_BCM_FLEXCTR, 2312 (BSL_META_U(unit, 2313 "Seems like the info in scache is larger\ 2314 (maybe because of firmware downgrade)\n"))); 2315 } 2316 } 2317 if (SOC_WARM_BOOT(unit)) { 2318 sal_memcpy(&local_scache_ptr[unit][0], 2319 &flowcnt_scache_ptr[unit][0], 2320 FLOWCNT_SCACHE_SIZE_1); 2321 _bcm_esw_flowcnt_warmboot_info_recover(unit, 2322 flowcnt_scache_ptr[unit]); 2323 _bcm_esw_flowcnt_warmboot_object_retrive(unit); 2324 } 2325 #else 2326 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2327 (BSL_META_U(unit, 2328 "COLD Booting... \n"))); 2329 #endif 2330 2331 return BCM_E_NONE; 2332 } 2333 /* 2334 * Function: 2335 * _bcm_esw_flowcnt_profile_group_destroy 2336 * Description: 2337 * Destroys profile group resources 2338 * Parameters: 2339 * 2340 * unit : (IN) UNIT number 2341 * profile_index : (IN) index to profile table 2342 * group_index : (IN) index to profile group 2343 * 2344 * Returns: 2345 * BCM_E_* 2346 */ 2347 STATIC int 2348 _bcm_esw_flowcnt_profile_group_destroy( 2349 int unit, 2350 int profile_index, 2351 int group_index) 2352 { 2353 _bcm_esw_flowcnt_control_t *fc = NULL; 2354 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 2355 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 2356 bcm_stat_group_mode_attr_t attr; 2357 int d_profile_index, d_profile_group; 2358 int rv; 2359 2360 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2361 _FLOWCNT_LOCK(fc); 2362 if (profile_index >= fc->num_profiles) { 2363 _FLOWCNT_UNLOCK(fc); 2364 return BCM_E_PARAM; 2365 } 2366 fc_profile = &fc->flowcnt_profile[profile_index]; 2367 if (group_index >= fc_profile->num_groups) { 2368 _FLOWCNT_UNLOCK(fc); 2369 return BCM_E_PARAM; 2370 } 2371 fc_pgroup = &fc_profile->flowcnt_group[group_index]; 2372 2373 if (fc_pgroup->available == 0) { 2374 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 2375 (BSL_META_U(unit, 2376 "flex counter mode %d not configured yet\n"), 2377 group_index)); 2378 _FLOWCNT_UNLOCK(fc); 2379 return BCM_E_NOT_FOUND; 2380 } 2381 if (fc_pgroup->reference_count != 0) { 2382 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2383 (BSL_META_U(unit, 2384 "FlexCounterMode:%d:IsBeingUsed." 2385 "ReferenceCount:%d:\n"), 2386 group_index,fc_pgroup->reference_count)); 2387 _FLOWCNT_UNLOCK(fc); 2388 return BCM_E_INTERNAL; 2389 } 2390 soc_mem_lock(unit, fc_profile->profile_table); 2391 /* Reset profile(offset) table */ 2392 rv = soc_profile_mem_delete(unit, &fc_profile->profile_mem, 2393 group_index*fc_profile->num_entries); 2394 soc_mem_unlock(unit, fc_profile->profile_table); 2395 if (BCM_FAILURE(rv)) { 2396 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2397 (BSL_META_U(unit, 2398 "Fail to reset profile group %d\n"), 2399 group_index)); 2400 _FLOWCNT_UNLOCK(fc); 2401 return rv; 2402 } 2403 attr = fc_profile->attr; 2404 d_profile_index = -1; 2405 d_profile_group = -1; 2406 if (fc->default_attr_mode_id[attr] != 0) { 2407 _bcm_esw_flowcnt_custom_mode_id_get(fc->default_attr_mode_id[attr], 2408 &d_profile_index, &d_profile_group); 2409 if ((d_profile_index == profile_index) && 2410 (d_profile_group == group_index)) { 2411 fc->default_attr_mode_id[attr] = 0; 2412 } 2413 } 2414 fc_pgroup->available = 0; 2415 _FLOWCNT_FREE(unit, fc_pgroup->attr_selectors, 0); 2416 sal_memset(fc_pgroup, 0, sizeof(_bcm_esw_flowcnt_profile_group_t)); 2417 _FLOWCNT_UNLOCK(fc); 2418 return BCM_E_NONE; 2419 } 2420 /* 2421 * Function: 2422 * _bcm_esw_flowcnt_group_destroy 2423 * Description: 2424 * Release HW counter resources as per given counter id and makes system 2425 * unavailable for any further stat collection action 2426 * Parameters: 2427 * unit - (IN) unit number 2428 * Stat_counter_id - (IN) Stat Counter Id 2429 * Return Value: 2430 * BCM_E_XXX 2431 * Notes: 2432 */ 2433 int _bcm_esw_flowcnt_group_destroy( 2434 int unit, 2435 uint32 stat_counter_id) 2436 { 2437 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 2438 bcm_stat_object_t object = bcmStatObjectIngPort; 2439 uint32 profile_group, pool_index, base_index; 2440 int profile_index, pool_idx; 2441 int rv = BCM_E_NONE; 2442 2443 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object, 2444 &profile_group, &pool_index, &base_index); 2445 2446 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 2447 (BSL_META_U(unit, 2448 "Deleting : mode:%d group_mode:%d pool:%d object:%d" 2449 "base:%d\n stat_counter_id:%d\n"),profile_group, 2450 group_mode, pool_index, object, base_index, 2451 stat_counter_id)); 2452 2453 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_object_table_map( 2454 unit, object, &profile_index, &pool_idx)); 2455 2456 if (pool_idx != pool_index) { 2457 return BCM_E_INTERNAL; 2458 } 2459 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_counter_destroy( 2460 unit, object, profile_group, 2461 base_index, pool_index)); 2462 2463 /* clean up the profile_group when no stat_couter_id assocated with */ 2464 /* rv = BCM_E_INTERNAL could be ignored here */ 2465 rv = _bcm_esw_flowcnt_profile_group_destroy( 2466 unit, profile_index, profile_group); 2467 if (rv == BCM_E_INTERNAL) { 2468 rv = BCM_E_NONE; 2469 } 2470 2471 return rv; 2472 } 2473 2474 /* 2475 * Function: 2476 * _bcm_esw_flowcnt_group_mode_id_destroy 2477 * Description: 2478 * Destroys Customized Group mode 2479 * Parameters: 2480 * 2481 * unit : (IN) UNIT number 2482 * mode_id : (IN) Created Mode Identifier for Flowcnt Group Mode 2483 * 2484 * Returns: 2485 * BCM_E_* 2486 */ 2487 int _bcm_esw_flowcnt_group_mode_id_destroy( 2488 int unit, 2489 uint32 mode_id) 2490 { 2491 int profile_id, profile_group_id; 2492 2493 _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id); 2494 2495 return _bcm_esw_flowcnt_profile_group_destroy(unit, profile_id, profile_group_id); 2496 } 2497 2498 /* 2499 * Function: 2500 * _bcm_esw_flowcnt_group_mode_id_get 2501 * Description: 2502 * Retrieves Customized Stat Group mode Attributes for given mode_id 2503 * Parameters: 2504 * 2505 * unit : (IN) UNIT number 2506 * mode_id : (IN) Created Mode Identifier for Stat Flex Group Mode 2507 * flags : (OUT) STAT_GROUP_MODE_* flags (INGRESS/EGRESS) 2508 * total_counters : (OUT) Total Counters for Stat Flex Group Mode 2509 * num_selectors : (IN) Number of Selectors for Stat Flex Group Mode 2510 * attr_selectors : (OUT) Attribute Selectors for Stat Flex Group Mode 2511 * actual_num_selectors: (OUT) Actual Number of Selectors for Stat Flex 2512 * Group Mode 2513 * 2514 * Returns: 2515 * BCM_E_* 2516 */ 2517 int _bcm_esw_flowcnt_group_mode_id_get( 2518 int unit, 2519 uint32 mode_id, 2520 uint32 *flags, 2521 uint32 *total_counters, 2522 uint32 num_selectors, 2523 bcm_stat_group_mode_attr_selector_t *attr_selectors, 2524 uint32 *actual_num_selectors) 2525 { 2526 int profile_id, profile_group_id, i; 2527 _bcm_esw_flowcnt_control_t *fc = NULL; 2528 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 2529 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 2530 int effect_num; 2531 2532 if ((flags == NULL) || 2533 (total_counters == NULL) || 2534 (actual_num_selectors == NULL)) { 2535 return BCM_E_PARAM; 2536 } 2537 2538 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2539 _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id); 2540 2541 _FLOWCNT_LOCK(fc); 2542 if (profile_id >= fc->num_profiles) { 2543 _FLOWCNT_UNLOCK(fc); 2544 return BCM_E_PARAM; 2545 } 2546 fc_profile = &fc->flowcnt_profile[profile_id]; 2547 if (profile_group_id >= fc_profile->num_groups) { 2548 _FLOWCNT_UNLOCK(fc); 2549 return BCM_E_PARAM; 2550 } 2551 fc_pgroup = &fc_profile->flowcnt_group[profile_group_id]; 2552 2553 if (fc_pgroup->available == 0) { 2554 _FLOWCNT_UNLOCK(fc); 2555 return BCM_E_NOT_FOUND; 2556 } 2557 2558 *flags = fc_pgroup->flags; 2559 *total_counters = fc_pgroup->total_counters; 2560 *actual_num_selectors = fc_pgroup->num_selectors; 2561 2562 if (num_selectors <= *actual_num_selectors) { 2563 effect_num = num_selectors; 2564 } else { 2565 effect_num = *actual_num_selectors; 2566 } 2567 for (i = 0 ; i < effect_num; i++) { 2568 sal_memset(&(attr_selectors[i]), 0, 2569 sizeof(bcm_stat_group_mode_attr_selector_t)); 2570 attr_selectors[i].attr 2571 = fc_pgroup->attr_selectors[i].attr; 2572 attr_selectors[i].counter_offset 2573 = fc_pgroup->attr_selectors[i].counter_offset; 2574 attr_selectors[i].attr_value 2575 = fc_pgroup->attr_selectors[i].attr_value; 2576 } 2577 _FLOWCNT_UNLOCK(fc); 2578 2579 return BCM_E_NONE; 2580 } 2581 2582 /* 2583 * Function: 2584 * _bcm_esw_flowcnt_group_mode_id_create 2585 * Description: 2586 * Create Customized Stat Group mode for given Counter Attributes 2587 * Parameters: 2588 * 2589 * unit : (IN) UNIT number 2590 * flags : (IN) STAT_GROUP_MODE_* flags (INGRESS/EGRESS) 2591 * total_counters : (IN) Total Counters for Stat Flex Group Mode 2592 * num_selectors : (IN) Number of Selectors for Stat Flex Group Mode 2593 * attr_selectors : (IN) Attribute Selectors for Stat Flex Group Mode 2594 * mode_id : (OUT) Created Mode Identifier for Stat Flex Group Mode 2595 * 2596 * Returns: 2597 * BCM_E_* 2598 */ 2599 int 2600 _bcm_esw_flowcnt_group_mode_id_create( 2601 int unit, 2602 uint32 flags, 2603 uint32 total_counters, 2604 uint32 num_selectors, 2605 bcm_stat_group_mode_attr_selector_t *attr_selectors, 2606 uint32 *mode_id) 2607 { 2608 int i, j; 2609 bcm_stat_group_mode_attr_t attr; 2610 _bcm_esw_flowcnt_control_t *fc = NULL; 2611 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 2612 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 2613 int direction; 2614 int rv; 2615 int profile_group, profile_index; 2616 2617 /* Perform Sanity Checks */ 2618 if (!((flags & BCM_STAT_GROUP_MODE_INGRESS) || 2619 (flags & BCM_STAT_GROUP_MODE_EGRESS))) { 2620 return BCM_E_PARAM; 2621 } 2622 2623 if (total_counters == 0) { 2624 return BCM_E_PARAM; 2625 } 2626 attr = -1; 2627 for (i = 0; i < num_selectors; i ++) { 2628 if (i == 0) { 2629 attr = attr_selectors[i].attr; 2630 } else if (attr != attr_selectors[i].attr) { 2631 /* in current HR3 flowcnt, each mode has the same attribute */ 2632 return BCM_E_PARAM; 2633 } 2634 } 2635 2636 if (flags & BCM_STAT_GROUP_MODE_INGRESS) { 2637 direction = bcmStatFlexDirectionIngress; 2638 } else { 2639 direction = bcmStatFlexDirectionEgress; 2640 } 2641 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2642 2643 _FLOWCNT_LOCK(fc); 2644 2645 /* Checck for existing mode */ 2646 for (i = 0; i < fc->num_profiles; i ++) { 2647 fc_profile = &fc->flowcnt_profile[i]; 2648 if ((fc_profile->direction == direction) && 2649 (fc_profile->attr == attr)) { 2650 for (j = 0; j < fc_profile->num_groups; j++) { 2651 fc_pgroup = &fc_profile->flowcnt_group[j]; 2652 if (fc_pgroup->available) { 2653 if (_bcm_esw_flowcnt_selectors_cmp ( 2654 unit, fc_profile->profile_table, 2655 fc_profile->num_entries, 2656 fc_pgroup->num_selectors, 2657 num_selectors, 2658 fc_pgroup->attr_selectors, 2659 attr_selectors) == 0){ 2660 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 2661 (BSL_META_U(unit, 2662 "Mode exist \n"))); 2663 _bcm_esw_flowcnt_custom_mode_id_set( 2664 i, j, mode_id); 2665 _FLOWCNT_UNLOCK(fc); 2666 return BCM_E_EXISTS; 2667 } 2668 } 2669 } 2670 } 2671 } 2672 /* 2673 * Create and add the profile group 2674 * profile table(HW)would be configured 2675 */ 2676 rv = _bcm_esw_flowcnt_profile_group_create(unit, 2677 direction, 2678 0, 2679 total_counters, 2680 num_selectors, 2681 attr_selectors, 2682 &profile_index, 2683 &profile_group); 2684 2685 if (BCM_FAILURE(rv)){ 2686 _FLOWCNT_UNLOCK(fc); 2687 return rv; 2688 } 2689 2690 fc_profile = &fc->flowcnt_profile[profile_index]; 2691 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 2692 fc_pgroup->flags = flags; 2693 2694 _bcm_esw_flowcnt_custom_mode_id_set(profile_index, profile_group, mode_id); 2695 2696 _FLOWCNT_UNLOCK(fc); 2697 2698 return BCM_E_NONE; 2699 } 2700 2701 /* 2702 * Function: 2703 * _bcm_esw_flowcnt_custom_group_create 2704 * Description: 2705 * Associate an accounting object to customized group mode 2706 * 2707 * Parameters: 2708 * 2709 * unit : (IN) UNIT number 2710 * mode_id : (IN) Created Mode Identifier for Stat Flex Group Mode 2711 * object : (IN) Accounting object 2712 * Stat_counter_id : (OUT) Stat Counter Id 2713 * num_entries : (OUT) Number of Counter entries created 2714 * 2715 * Returns: 2716 * BCM_E_* 2717 */ 2718 int _bcm_esw_flowcnt_custom_group_create( 2719 int unit, 2720 uint32 mode_id, 2721 bcm_stat_object_t object, 2722 uint32 *stat_counter_id, 2723 uint32 *num_entries) 2724 { 2725 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 2726 uint32 total_counters=0; 2727 _bcm_esw_flowcnt_control_t *fc = NULL; 2728 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 2729 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 2730 int profile_id, profile_group_id; 2731 int pool_index, base_index; 2732 int rv; 2733 2734 BCM_IF_ERROR_RETURN( 2735 _bcm_esw_flowcnt_stat_object_validate(unit, object)); 2736 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2737 _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id); 2738 2739 _FLOWCNT_LOCK(fc); 2740 if (profile_id >= fc->num_profiles) { 2741 _FLOWCNT_UNLOCK(fc); 2742 return BCM_E_PARAM; 2743 } 2744 fc_profile = &fc->flowcnt_profile[profile_id]; 2745 if (profile_group_id >= fc_profile->num_groups) { 2746 _FLOWCNT_UNLOCK(fc); 2747 return BCM_E_PARAM; 2748 } 2749 fc_pgroup = &fc_profile->flowcnt_group[profile_group_id]; 2750 total_counters = fc_pgroup->total_counters; 2751 group_mode = bcmFlowcntProfileGroup1 + profile_group_id; 2752 fc_pgroup->group_mode = group_mode; 2753 _FLOWCNT_UNLOCK(fc); 2754 2755 /* Reserve the counter table */ 2756 rv = _bcm_esw_flowcnt_counter_create(unit, object, profile_group_id, 2757 total_counters, 2758 &base_index, &pool_index); 2759 if (BCM_FAILURE(rv)){ 2760 return rv; 2761 } 2762 2763 _bcm_esw_flowcnt_counter_id_set( 2764 group_mode, object, 2765 profile_group_id, 2766 pool_index, 2767 base_index, 2768 stat_counter_id); 2769 *num_entries = total_counters; 2770 2771 return BCM_E_NONE; 2772 } 2773 2774 /* 2775 * Function: 2776 * _bcm_esw_flowcnt_group_create 2777 * Description: 2778 * Reserve HW counter resources as per given group mode and acounting 2779 * object and make system ready for further stat collection action 2780 * 2781 * Parameters: 2782 * Unit (IN) Unit number 2783 * object (IN) Accounting Object 2784 * Group_mode (IN) Group Mode 2785 * Stat_counter_id (OUT) Stat Counter Id 2786 * num_entries (OUT) Number of Counter entries created 2787 * Return Value: 2788 * BCM_E_XXX 2789 * Notes: 2790 */ 2791 int _bcm_esw_flowcnt_group_create ( 2792 int unit, 2793 bcm_stat_object_t object, 2794 bcm_stat_group_mode_t group_mode, 2795 uint32 *stat_counter_id, 2796 uint32 *num_entries) 2797 { 2798 int total_counters=0; 2799 int num_selectors; 2800 bcm_stat_group_mode_attr_selector_t *attr_selectors = NULL; 2801 bcm_stat_group_mode_attr_t attr; 2802 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 2803 int profile_group, profile_index; 2804 _bcm_esw_flowcnt_control_t *fc = NULL; 2805 int rv = BCM_E_NONE; 2806 int base_index, pool_index; 2807 uint32 default_attr_mode_id = 0; 2808 2809 2810 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2811 2812 BCM_IF_ERROR_RETURN( 2813 _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode)); 2814 BCM_IF_ERROR_RETURN( 2815 _bcm_esw_flowcnt_stat_object_validate(unit, object)); 2816 2817 switch (group_mode) { 2818 case bcmStatGroupModeSingle: 2819 total_counters = 1; 2820 break; 2821 default: 2822 return BCM_E_PARAM; 2823 } 2824 switch (object) { 2825 case bcmStatObjectIngVlanXlate: 2826 case bcmStatObjectIngFieldStageLookup: 2827 case bcmStatObjectEgrVlanXlate: 2828 num_selectors = 16; 2829 attr = bcmStatGroupModeAttrPktCfiPri; 2830 if ((int)object == bcmStatObjectEgrVlanXlate) { 2831 direction = bcmStatFlexDirectionEgress; 2832 } 2833 break; 2834 default: 2835 return BCM_E_PARAM; 2836 } 2837 2838 _FLOWCNT_LOCK(fc); 2839 if (fc->default_attr_mode_id[attr] == 0) { 2840 _FLOWCNT_ALLOC(unit, attr_selectors, bcm_stat_group_mode_attr_selector_t, 2841 num_selectors * 2842 sizeof(bcm_stat_group_mode_attr_selector_t), 2843 "flowcnt default pkt attr", 0, rv); 2844 if (BCM_FAILURE(rv)){ 2845 _FLOWCNT_UNLOCK(fc); 2846 return rv; 2847 } 2848 /* setup the default attr_selectors based on the the attr */ 2849 rv = _bcm_esw_flowcnt_default_attr_config(unit, attr, 2850 num_selectors, 2851 attr_selectors); 2852 if (BCM_FAILURE(rv)){ 2853 _FLOWCNT_UNLOCK(fc); 2854 _FLOWCNT_FREE(unit, attr_selectors, 0); 2855 return rv; 2856 } 2857 /* 2858 * Create and add the profile group 2859 * profile table(HW)would be configured 2860 */ 2861 rv = _bcm_esw_flowcnt_profile_group_create(unit, 2862 direction, 2863 group_mode, 2864 total_counters, 2865 num_selectors, 2866 attr_selectors, 2867 &profile_index, 2868 &profile_group); 2869 if (BCM_FAILURE(rv)){ 2870 _FLOWCNT_UNLOCK(fc); 2871 _FLOWCNT_FREE(unit, attr_selectors, 0); 2872 return rv; 2873 } 2874 2875 _bcm_esw_flowcnt_custom_mode_id_set(profile_index, profile_group, 2876 &fc->default_attr_mode_id[attr]); 2877 fc->default_attr_mode_id[attr] |= _BCM_FLOWCNT_MODE_ID_VALID; 2878 _FLOWCNT_FREE(unit, attr_selectors, 0); 2879 } else { 2880 default_attr_mode_id = fc->default_attr_mode_id[attr]; 2881 default_attr_mode_id &= ~(_BCM_FLOWCNT_MODE_ID_VALID); 2882 _bcm_esw_flowcnt_custom_mode_id_get(default_attr_mode_id, 2883 &profile_index, &profile_group); 2884 } 2885 /* Reserve the counter table */ 2886 rv = _bcm_esw_flowcnt_counter_create(unit, object, profile_group, 2887 total_counters, 2888 &base_index, &pool_index); 2889 2890 if (BCM_FAILURE(rv)){ 2891 _FLOWCNT_UNLOCK(fc); 2892 return rv; 2893 } 2894 2895 _FLOWCNT_UNLOCK(fc); 2896 2897 _bcm_esw_flowcnt_counter_id_set( 2898 group_mode, object, 2899 profile_group, 2900 pool_index, 2901 base_index, 2902 stat_counter_id); 2903 *num_entries = total_counters; 2904 2905 return BCM_E_NONE; 2906 } 2907 2908 /* 2909 * Function: 2910 * _bcm_esw_flowcnt_counter_set 2911 * Description: 2912 * Set Flex Counter Values 2913 * Parameters: 2914 * unit - (IN) unit number 2915 * index - (IN) Flex Accounting Table Index 2916 * table - (IN) Flex Accounting Table 2917 * byte_flag - (IN) Byte/Packet Flag 2918 * counter - (IN) Counter Index 2919 * values - (IN) Counter Value 2920 * Return Value: 2921 * BCM_E_XXX 2922 * Notes: 2923 */ 2924 int _bcm_esw_flowcnt_counter_set( 2925 int unit, 2926 uint32 index, 2927 soc_mem_t table, 2928 uint32 byte_flag, 2929 uint32 counter_index, 2930 bcm_stat_value_t *value) 2931 { 2932 _bcm_esw_flowcnt_control_t *fc = NULL; 2933 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 2934 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 2935 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 2936 int pool_index, offset_index, total_entries; 2937 int profile_index, object_index; 2938 uint32 base_index, profile_ptr; 2939 int rv = BCM_E_NONE; 2940 void *entry_data = NULL; 2941 uint32 entry_data_size = 0; 2942 soc_mem_info_t *memp = NULL; 2943 bcm_stat_object_t object; 2944 soc_mem_t counter_mem; 2945 uint32 max_packet_mask=0; 2946 uint64 max_byte_mask; 2947 uint32 hw_val[2]; 2948 2949 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 2950 2951 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get( 2952 unit, table, index, 2953 &profile_ptr, &base_index, &object_index)); 2954 2955 object = valid_stat_object_list[unit][object_index].object; 2956 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 2957 &profile_index, 2958 &pool_index); 2959 if (BCM_FAILURE(rv)){ 2960 return rv; 2961 } 2962 2963 _FLOWCNT_LOCK(fc); 2964 fc_pool = &fc->flowcnt_pool[pool_index]; 2965 fc_profile = &fc->flowcnt_profile[profile_index]; 2966 fc_pgroup = &fc_profile->flowcnt_group[profile_ptr]; 2967 counter_mem = fc_pool->mem; 2968 total_entries = fc_pgroup->total_counters; 2969 offset_index = counter_index; 2970 2971 if (offset_index >= total_entries) { 2972 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 2973 (BSL_META_U(unit, 2974 "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"), 2975 total_entries)); 2976 _FLOWCNT_UNLOCK(fc); 2977 return BCM_E_PARAM; 2978 } 2979 2980 memp = &SOC_MEM_INFO(unit, counter_mem); 2981 entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes)); 2982 _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size, 2983 "counter table entry", 0, rv); 2984 if (BCM_FAILURE(rv)){ 2985 _FLOWCNT_UNLOCK(fc); 2986 return rv; 2987 } 2988 if (soc_mem_read(unit, 2989 counter_mem, 2990 MEM_BLOCK_ANY, 2991 base_index+offset_index, 2992 entry_data) != BCM_E_NONE){ 2993 _FLOWCNT_UNLOCK(fc); 2994 _FLOWCNT_FREE(unit, entry_data, 0); 2995 return BCM_E_INTERNAL; 2996 } 2997 COMPILER_64_ZERO(max_byte_mask); 2998 if (byte_flag == 1) { 2999 fc_pool->flow_stat_type[base_index+offset_index] = 3000 bcmFlowcntStatTypeByte; 3001 3002 /* Mask to possible max values */ 3003 COMPILER_64_AND(value->bytes, max_byte_mask); 3004 /* Update Soft Copy */ 3005 COMPILER_64_SET(fc_pool->flow_byte_counter[base_index+offset_index], 3006 COMPILER_64_HI(value->bytes), 3007 COMPILER_64_LO(value->bytes)); 3008 /* Change Read Hw Copy */ 3009 hw_val[0] = COMPILER_64_LO(value->bytes); 3010 hw_val[1] = COMPILER_64_HI(value->bytes); 3011 soc_mem_field_set(unit, 3012 counter_mem, 3013 (uint32 *)entry_data, 3014 BYTE_COUNTERf, 3015 hw_val); 3016 soc_mem_field_set(unit, 3017 counter_mem, 3018 (uint32 *)entry_data, 3019 COUNT_BYTEf, 3020 &byte_flag); 3021 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3022 (BSL_META_U(unit, 3023 "Byte Count Value\t:TABLE:%sINDEX:%d " 3024 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3025 SOC_MEM_UFNAME(unit, counter_mem), 3026 index, 3027 pool_index, 3028 base_index+offset_index, 3029 COMPILER_64_HI(value->bytes), 3030 COMPILER_64_LO(value->bytes))); 3031 } else { 3032 fc_pool->flow_stat_type[base_index+offset_index] = 3033 bcmFlowcntStatTypePacket; 3034 3035 value->packets &= max_packet_mask; 3036 /* Update Soft Copy */ 3037 fc_pool->flow_packet_counter[base_index+offset_index] = value->packets; 3038 3039 /* Update Soft Copy */ 3040 COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index+offset_index],0, 3041 value->packets); 3042 /* Change Read Hw Copy */ 3043 soc_mem_field_set(unit, 3044 counter_mem, 3045 (uint32 *)entry_data, 3046 PACKET_COUNTERf, 3047 &(value->packets)); 3048 soc_mem_field_set(unit, 3049 counter_mem, 3050 (uint32 *)entry_data, 3051 COUNT_BYTEf, 3052 &byte_flag); 3053 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3054 (BSL_META_U(unit, 3055 "Packet Count Value\t:TABLE:%sINDEX:%d " 3056 "(@Pool:%d ActualOffset%d) : %x \n"), 3057 SOC_MEM_UFNAME(unit, counter_mem), 3058 index, 3059 pool_index, 3060 base_index+offset_index, 3061 value->packets)); 3062 } 3063 /* Update Hw Copy */ 3064 if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL, 3065 base_index+offset_index, 3066 entry_data) != BCM_E_NONE){ 3067 _FLOWCNT_UNLOCK(fc); 3068 _FLOWCNT_FREE(unit, entry_data, 0); 3069 return BCM_E_INTERNAL; 3070 } 3071 _FLOWCNT_UNLOCK(fc); 3072 _FLOWCNT_FREE(unit, entry_data, 0); 3073 return BCM_E_NONE; 3074 } 3075 3076 /* 3077 * Function: 3078 * _bcm_esw_flowcnt_counter_get 3079 * Description: 3080 * Get Flex Counter Values 3081 * if sync_mode is set, sync the sw accumulated count 3082 * with hw count value first, else return sw count. 3083 * 3084 * Parameters: 3085 * unit - (IN) unit number 3086 * sync_mode - (IN) hwcount is to be synced to sw count 3087 * index - (IN) Flex Accounting Table Index 3088 * table - (IN) Flex Accounting Table 3089 * byte_flag - (IN) Byte/Packet Flag 3090 * counter - (IN) Counter Index 3091 * values - (OUT) Counter Value 3092 * 3093 * Return Value: 3094 * BCM_E_XXX 3095 * Notes: 3096 */ 3097 int _bcm_esw_flowcnt_counter_get( 3098 int unit, 3099 int sync_mode, 3100 uint32 index, 3101 soc_mem_t table, 3102 uint32 byte_flag, 3103 uint32 counter_index, 3104 bcm_stat_value_t *value) 3105 { 3106 _bcm_esw_flowcnt_control_t *fc = NULL; 3107 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3108 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 3109 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3110 int object_index, pool_index, profile_index, offset_index, total_entries; 3111 uint32 base_index, profile_ptr; 3112 int rv = BCM_E_NONE; 3113 bcm_stat_object_t object; 3114 soc_mem_t counter_mem; 3115 3116 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3117 3118 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get( 3119 unit, table, index, 3120 &profile_ptr, &base_index, &object_index)); 3121 3122 object = valid_stat_object_list[unit][object_index].object; 3123 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 3124 &profile_index, 3125 &pool_index); 3126 if (BCM_FAILURE(rv)){ 3127 return rv; 3128 } 3129 3130 _FLOWCNT_LOCK(fc); 3131 fc_pool = &fc->flowcnt_pool[pool_index]; 3132 fc_profile = &fc->flowcnt_profile[profile_index]; 3133 fc_pgroup = &fc_profile->flowcnt_group[profile_ptr]; 3134 counter_mem = fc_pool->mem; 3135 total_entries = fc_pgroup->total_counters; 3136 offset_index = counter_index; 3137 3138 if (offset_index >= total_entries) { 3139 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 3140 (BSL_META_U(unit, 3141 "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"), 3142 total_entries)); 3143 _FLOWCNT_UNLOCK(fc); 3144 return BCM_E_PARAM; 3145 } 3146 3147 if (byte_flag == 1) { 3148 if (fc_pool->flow_stat_type[base_index+offset_index] != 3149 bcmFlowcntStatTypeByte) { 3150 _FLOWCNT_UNLOCK(fc); 3151 return BCM_E_PARAM; 3152 } 3153 } else { 3154 if (fc_pool->flow_stat_type[base_index+offset_index] != 3155 bcmFlowcntStatTypePacket) { 3156 _FLOWCNT_UNLOCK(fc); 3157 return BCM_E_PARAM; 3158 } 3159 } 3160 3161 /* sync the software counter with hardware counter */ 3162 if (sync_mode == 1) { 3163 _bcm_esw_flowcnt_counter_collect(unit, 3164 counter_mem, 3165 base_index + offset_index); 3166 } 3167 3168 bcm_stat_value_t_init(value); 3169 if (byte_flag == 1) { 3170 COMPILER_64_SET(value->bytes, 3171 COMPILER_64_HI(fc_pool-> 3172 flow_byte_counter[base_index+offset_index]), 3173 COMPILER_64_LO(fc_pool-> 3174 flow_byte_counter[base_index+offset_index])); 3175 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3176 (BSL_META_U(unit, 3177 "Byte Count Value\t:TABLE:%sINDEX:%d" 3178 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3179 SOC_MEM_UFNAME(unit, counter_mem), 3180 index, 3181 pool_index, 3182 base_index+offset_index, 3183 COMPILER_64_HI(value->bytes), 3184 COMPILER_64_LO(value->bytes))); 3185 } else { 3186 value->packets= fc_pool-> 3187 flow_packet_counter[base_index+offset_index]; 3188 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3189 (BSL_META_U(unit, 3190 "Packet Count Value\t:TABLE:%sINDEX:%d " 3191 "(@Pool:%dActualOffset%d) : %x \n"), 3192 SOC_MEM_UFNAME(unit, counter_mem), 3193 index, 3194 pool_index, 3195 base_index+offset_index, 3196 value->packets)); 3197 COMPILER_64_SET(value->packets64, 3198 COMPILER_64_HI(fc_pool-> 3199 flow_packet64_counter 3200 [base_index+offset_index]), 3201 COMPILER_64_LO(fc_pool-> 3202 flow_packet64_counter 3203 [base_index+offset_index])); 3204 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3205 (BSL_META_U(unit, 3206 "Packet64 Count Value\t:TABLE:%sINDEX:%d " 3207 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3208 SOC_MEM_UFNAME(unit, counter_mem), 3209 index, 3210 pool_index, 3211 base_index+offset_index, 3212 COMPILER_64_HI(value->packets64), 3213 COMPILER_64_LO(value->packets64))); 3214 } 3215 _FLOWCNT_UNLOCK(fc); 3216 3217 return BCM_E_NONE; 3218 } 3219 3220 3221 /* 3222 * Function: 3223 * _bcm_esw_flowcnt_stat_id_get 3224 * Description: 3225 * Get stat id of the accounting object 3226 * 3227 * Parameters: 3228 * unit - (IN) unit number 3229 * table - (IN) Accounting Table 3230 * index - (IN) Accounting Table Index 3231 * stat_counter_id - (OUT) Stat Id 3232 * 3233 * Return Value: 3234 * BCM_E_XXX 3235 * Notes: 3236 */ 3237 int 3238 _bcm_esw_flowcnt_stat_id_get( 3239 int unit, 3240 soc_mem_t table, 3241 int index, 3242 uint32 *stat_counter_id) 3243 { 3244 uint32 base_index, profile_ptr; 3245 bcm_stat_object_t object; 3246 _bcm_esw_flowcnt_control_t *fc = NULL; 3247 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3248 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3249 int object_index, pool_index, profile_index; 3250 int rv; 3251 3252 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get( 3253 unit, table, index, 3254 &profile_ptr, &base_index, &object_index)); 3255 3256 object = valid_stat_object_list[unit][object_index].object; 3257 3258 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3259 3260 3261 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 3262 &profile_index, &pool_index); 3263 if (BCM_FAILURE(rv)) { 3264 return rv; 3265 } 3266 3267 _FLOWCNT_LOCK(fc); 3268 3269 fc_profile = &fc->flowcnt_profile[profile_index]; 3270 fc_pgroup = &fc_profile->flowcnt_group[profile_ptr]; 3271 3272 _FLOWCNT_UNLOCK(fc); 3273 3274 _bcm_esw_flowcnt_counter_id_set( 3275 fc_pgroup->group_mode, 3276 object, 3277 profile_ptr, 3278 pool_index, 3279 base_index, 3280 stat_counter_id); 3281 3282 return BCM_E_NONE; 3283 } 3284 3285 3286 3287 /* 3288 * Function: 3289 * _bcm_esw_flowcnt_stat_type_validate 3290 * Description: 3291 * Validate the stat type of the accounting table entry 3292 * 3293 * Parameters: 3294 * unit - (IN) unit number 3295 * table - (IN) Accounting Table 3296 * index - (IN) Accounting Table Index 3297 * flow_stat_type - (IN) stat type (bcmFlowcntStatTypeByte/Packet) 3298 * 3299 * Return Value: 3300 * BCM_E_XXX 3301 * Notes: 3302 */ 3303 int 3304 _bcm_esw_flowcnt_stat_type_validate( 3305 int unit, 3306 soc_mem_t table, 3307 int index, 3308 _bcm_flowcnt_stat_type_t flow_stat_type) 3309 { 3310 uint32 base_index, profile_ptr; 3311 bcm_stat_object_t object; 3312 _bcm_esw_flowcnt_control_t *fc = NULL; 3313 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 3314 int object_index, pool_index, profile_index; 3315 int rv; 3316 3317 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get( 3318 unit, table, index, 3319 &profile_ptr, &base_index, &object_index)); 3320 3321 object = valid_stat_object_list[unit][object_index].object; 3322 3323 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3324 3325 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 3326 &profile_index, &pool_index); 3327 if (BCM_FAILURE(rv)) { 3328 return rv; 3329 } 3330 3331 _FLOWCNT_LOCK(fc); 3332 fc_pool = &fc->flowcnt_pool[pool_index]; 3333 3334 if (fc_pool->flow_stat_type[base_index] == 0) { 3335 _FLOWCNT_UNLOCK(fc); 3336 return BCM_E_NOT_FOUND; 3337 } 3338 if (fc_pool->flow_stat_type[base_index] != flow_stat_type) { 3339 _FLOWCNT_UNLOCK(fc); 3340 return BCM_E_PARAM; 3341 } 3342 _FLOWCNT_UNLOCK(fc); 3343 3344 return BCM_E_NONE; 3345 3346 } 3347 3348 /* 3349 * Function: 3350 * _bcm_esw_flowcnt_group_dump_info 3351 * Description: 3352 * Dump Useful Info about configured group 3353 * Parameters: 3354 * unit - (IN) unit number 3355 * all_flag - (IN) If 1, object and group_mode are ignored 3356 * object - (IN) Flex Accounting object 3357 * group - (IN) Flex Group Mode 3358 * Return Value: 3359 * BCM_E_XXX 3360 * Notes: 3361 */ 3362 int _bcm_esw_flowcnt_group_dump_info( 3363 int unit, 3364 int all_flag, 3365 bcm_stat_object_t object, 3366 bcm_stat_group_mode_t group) 3367 { 3368 int i; 3369 uint32 index = 0, stat_counter_id; 3370 bcm_stat_object_t l_object; 3371 bcm_stat_group_mode_t group_mode; 3372 _bcm_esw_flowcnt_control_t *fc = NULL; 3373 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3374 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3375 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 3376 uint32 profile_group, pool_index, base_index; 3377 int profile_index, pool_idx; 3378 uint32 total_counters, num_ctr; 3379 char *oname[] = BCM_STAT_OBJECT; 3380 uint32 *ptr = (uint32 *)&local_scache_ptr[unit][0]; 3381 3382 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3383 _FLOWCNT_LOCK(fc); 3384 LOG_CLI((BSL_META_U(unit, 3385 "Not attached(MAX=%d) Stat counter Id info \n"), 3386 MAX_FLOWCNT_SCACHE_SIZE)); 3387 for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) { 3388 if (ptr[index] != 0) { 3389 stat_counter_id = ptr[index]; 3390 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, 3391 &l_object,&profile_group, 3392 &pool_index, &base_index); 3393 if (_bcm_esw_flowcnt_object_table_map( 3394 unit, l_object, &profile_index, &pool_idx) != BCM_E_NONE){ 3395 continue; 3396 } 3397 fc_profile = &fc->flowcnt_profile[profile_index]; 3398 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3399 fc_pool = &fc->flowcnt_pool[pool_idx]; 3400 total_counters = fc_pgroup->total_counters; 3401 if (total_counters == 0) { 3402 continue; 3403 } 3404 if ((all_flag == TRUE) || 3405 ((l_object == object) && (group_mode == group))) { 3406 LOG_CLI((BSL_META_U(unit, 3407 "\tstat_counter_id = %d=0x%x \n"), 3408 stat_counter_id, stat_counter_id)); 3409 LOG_CLI((BSL_META_U(unit, 3410 "\t\t mode:%d profile_mem:%s" 3411 "\n\t\tpool:%d object:%s base:%d" 3412 " total_counters=%d\n"), 3413 profile_group, 3414 SOC_MEM_UFNAME(unit, fc_profile->profile_table), 3415 pool_idx, oname[l_object], 3416 base_index, total_counters)); 3417 } 3418 } 3419 } 3420 LOG_CLI((BSL_META_U(unit, 3421 "Atached Stat counter Id info \n"))); 3422 for (l_object = 0; l_object < bcmStatObjectMaxValue; l_object++){ 3423 if (_bcm_esw_flowcnt_object_table_map( 3424 unit, l_object, &profile_index, &pool_idx) != BCM_E_NONE){ 3425 continue; 3426 } 3427 fc_profile = &fc->flowcnt_profile[profile_index]; 3428 fc_pool = &fc->flowcnt_pool[pool_idx]; 3429 num_ctr = soc_mem_index_count(unit, fc_pool->mem); 3430 for (i = 0; i < num_ctr; i++) { 3431 if (fc_pool->flow_base_index_reference_count[i] != 0){ 3432 if (fc_pool->associate_profile_group[i] < 3433 _BCM_FLOWCNT_PGROUP_BIAS){ 3434 continue; 3435 } 3436 if (fc_pool->object[i] != l_object) { 3437 continue; 3438 } 3439 profile_group = fc_pool->associate_profile_group[i] - 3440 _BCM_FLOWCNT_PGROUP_BIAS; 3441 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3442 group_mode = fc_pgroup->group_mode; 3443 _bcm_esw_flowcnt_counter_id_set( 3444 group_mode, 3445 l_object, 3446 profile_group, 3447 pool_idx, 3448 i, 3449 &stat_counter_id); 3450 if ((all_flag == TRUE) || 3451 ((l_object == object) && (group_mode == group))) { 3452 LOG_CLI((BSL_META_U(unit, 3453 "\tstat counter id %d (0x%x) " 3454 "object=%s base index=%d (0x%x)\n"), 3455 stat_counter_id,stat_counter_id, 3456 oname[l_object], 3457 i, i)); 3458 } 3459 } 3460 } 3461 } 3462 _FLOWCNT_UNLOCK(fc); 3463 return BCM_E_NONE; 3464 } 3465 3466 /* 3467 * Function: 3468 * _bcm_esw_flowcnt_counter_raw_set 3469 * Description: 3470 * Set Flex Counter Values 3471 * Parameters: 3472 * unit - (IN) unit number 3473 * stat_counter_id - (IN) Stat Counter Id 3474 * byte_flag - (IN) Byte/Packet Flag 3475 * counter - (IN) Counter Index 3476 * values - (IN) Counter Value 3477 * 3478 * Return Value: 3479 * BCM_E_XXX 3480 * Notes: Must be called carefully. 3481 * Preference should be given to _bcm_esw_flowcnt_counter_set() 3482 */ 3483 int _bcm_esw_flowcnt_counter_raw_set( 3484 int unit, 3485 uint32 stat_counter_id, 3486 uint32 byte_flag, 3487 uint32 counter_index, 3488 bcm_stat_value_t *value) 3489 { 3490 _bcm_esw_flowcnt_control_t *fc = NULL; 3491 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3492 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 3493 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3494 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 3495 bcm_stat_object_t object = bcmStatObjectIngPort; 3496 uint32 profile_group, pool_index, base_index; 3497 int profile_index, pool_idx, total_entries, offset_index; 3498 soc_mem_t counter_mem; 3499 soc_mem_info_t *memp = NULL; 3500 void *entry_data = NULL; 3501 uint32 entry_data_size = 0; 3502 int rv = BCM_E_NONE; 3503 uint32 max_packet_mask=0; 3504 uint64 max_byte_mask; 3505 uint32 hw_val[2]; 3506 3507 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3508 3509 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object, 3510 &profile_group, &pool_index, &base_index); 3511 3512 if (group_mode >= bcmStatGroupModeCount) { 3513 /* custom group */ 3514 if ((group_mode - bcmStatGroupModeCount) != profile_group) { 3515 return BCM_E_PARAM; 3516 } 3517 } else { 3518 BCM_IF_ERROR_RETURN( 3519 _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode)); 3520 } 3521 BCM_IF_ERROR_RETURN( 3522 _bcm_esw_flowcnt_stat_object_validate(unit, object)); 3523 3524 BCM_IF_ERROR_RETURN( 3525 _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index, 3526 &pool_idx)); 3527 3528 if (pool_idx != pool_index) { 3529 return BCM_E_INTERNAL; 3530 } 3531 _FLOWCNT_LOCK(fc); 3532 fc_pool = &fc->flowcnt_pool[pool_index]; 3533 fc_profile = &fc->flowcnt_profile[profile_index]; 3534 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3535 counter_mem = fc_pool->mem; 3536 total_entries = fc_pgroup->total_counters; 3537 offset_index = counter_index; 3538 3539 if (offset_index >= total_entries) { 3540 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 3541 (BSL_META_U(unit, 3542 "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"), 3543 total_entries)); 3544 _FLOWCNT_UNLOCK(fc); 3545 return BCM_E_PARAM; 3546 } 3547 memp = &SOC_MEM_INFO(unit, counter_mem); 3548 entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes)); 3549 _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size, 3550 "counter table entry", 0, rv); 3551 if (BCM_FAILURE(rv)){ 3552 _FLOWCNT_UNLOCK(fc); 3553 return rv; 3554 } 3555 if (soc_mem_read(unit, 3556 counter_mem, 3557 MEM_BLOCK_ANY, 3558 base_index+offset_index, 3559 entry_data) != BCM_E_NONE){ 3560 _FLOWCNT_UNLOCK(fc); 3561 _FLOWCNT_FREE(unit, entry_data, 0); 3562 return BCM_E_INTERNAL; 3563 } 3564 COMPILER_64_ZERO(max_byte_mask); 3565 if (byte_flag == 1) { 3566 fc_pool->flow_stat_type[base_index+offset_index] = 3567 bcmFlowcntStatTypeByte; 3568 3569 /* Mask to possible max values */ 3570 COMPILER_64_AND(value->bytes, max_byte_mask); 3571 /* Update Soft Copy */ 3572 COMPILER_64_SET(fc_pool->flow_byte_counter[base_index+offset_index], 3573 COMPILER_64_HI(value->bytes), 3574 COMPILER_64_LO(value->bytes)); 3575 /* Change Read Hw Copy */ 3576 hw_val[0] = COMPILER_64_LO(value->bytes); 3577 hw_val[1] = COMPILER_64_HI(value->bytes); 3578 soc_mem_field_set(unit, 3579 counter_mem, 3580 (uint32 *)entry_data, 3581 BYTE_COUNTERf, 3582 hw_val); 3583 soc_mem_field_set(unit, 3584 counter_mem, 3585 (uint32 *)entry_data, 3586 COUNT_BYTEf, 3587 &byte_flag); 3588 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3589 (BSL_META_U(unit, 3590 "Byte Count Value\t:TABLE:%s" 3591 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3592 SOC_MEM_UFNAME(unit, counter_mem), 3593 pool_index, 3594 base_index+offset_index, 3595 COMPILER_64_HI(value->bytes), 3596 COMPILER_64_LO(value->bytes))); 3597 } else { 3598 fc_pool->flow_stat_type[base_index+offset_index] = 3599 bcmFlowcntStatTypePacket; 3600 3601 value->packets &= max_packet_mask; 3602 /* Update Soft Copy */ 3603 fc_pool->flow_packet_counter[base_index+offset_index] = value->packets; 3604 3605 /* Update Soft Copy */ 3606 COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index+offset_index],0, 3607 value->packets); 3608 /* Change Read Hw Copy */ 3609 soc_mem_field_set(unit, 3610 counter_mem, 3611 (uint32 *)entry_data, 3612 PACKET_COUNTERf, 3613 &(value->packets)); 3614 soc_mem_field_set(unit, 3615 counter_mem, 3616 (uint32 *)entry_data, 3617 COUNT_BYTEf, 3618 &byte_flag); 3619 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3620 (BSL_META_U(unit, 3621 "Packet Count Value\t:TABLE:%s" 3622 "(@Pool:%d ActualOffset%d) : %x \n"), 3623 SOC_MEM_UFNAME(unit, counter_mem), 3624 pool_index, 3625 base_index+offset_index, 3626 value->packets)); 3627 } 3628 /* Update Hw Copy */ 3629 if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL, 3630 base_index+offset_index, 3631 entry_data) != BCM_E_NONE){ 3632 _FLOWCNT_UNLOCK(fc); 3633 _FLOWCNT_FREE(unit, entry_data, 0); 3634 return BCM_E_INTERNAL; 3635 } 3636 _FLOWCNT_UNLOCK(fc); 3637 _FLOWCNT_FREE(unit, entry_data, 0); 3638 return BCM_E_NONE; 3639 } 3640 3641 /* 3642 * Function: 3643 * _bcm_esw_flowcnt_counter_raw_get 3644 * Description: 3645 * Get Flex Counter Values 3646 * Parameters: 3647 * unit - (IN) unit number 3648 * sync_mode - (IN) hwcount is to be synced to sw count 3649 * stat_counter_id - (IN) Stat Counter Id 3650 * byte_flag - (IN) Byte/Packet Flag 3651 * counter - (IN) Counter Index 3652 * values - (OUT) Counter Value 3653 * 3654 * Return Value: 3655 * BCM_E_XXX 3656 * Notes: Must be called carefully. 3657 * Preference should be given to _bcm_esw_flowcnt_counter_get() 3658 */ 3659 int _bcm_esw_flowcnt_counter_raw_get( 3660 int unit, 3661 int sync_mode, 3662 uint32 stat_counter_id, 3663 uint32 byte_flag, 3664 uint32 counter_index, 3665 bcm_stat_value_t *value) 3666 { 3667 _bcm_esw_flowcnt_control_t *fc = NULL; 3668 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3669 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 3670 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3671 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 3672 bcm_stat_object_t object = bcmStatObjectIngPort; 3673 uint32 profile_group, pool_index, base_index; 3674 int profile_index, pool_idx, total_entries, offset_index; 3675 soc_mem_t counter_mem; 3676 3677 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3678 3679 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object, 3680 &profile_group, &pool_index, &base_index); 3681 3682 if (group_mode >= bcmStatGroupModeCount) { 3683 /* custom group */ 3684 if ((group_mode - bcmStatGroupModeCount) != profile_group) { 3685 return BCM_E_PARAM; 3686 } 3687 } else { 3688 BCM_IF_ERROR_RETURN( 3689 _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode)); 3690 } 3691 3692 BCM_IF_ERROR_RETURN( 3693 _bcm_esw_flowcnt_stat_object_validate(unit, object)); 3694 3695 BCM_IF_ERROR_RETURN( 3696 _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index, 3697 &pool_idx)); 3698 3699 if (pool_idx != pool_index) { 3700 return BCM_E_INTERNAL; 3701 } 3702 3703 _FLOWCNT_LOCK(fc); 3704 fc_pool = &fc->flowcnt_pool[pool_index]; 3705 fc_profile = &fc->flowcnt_profile[profile_index]; 3706 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3707 counter_mem = fc_pool->mem; 3708 total_entries = fc_pgroup->total_counters; 3709 offset_index = counter_index; 3710 3711 if (offset_index >= total_entries) { 3712 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3713 (BSL_META_U(unit, 3714 "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"), 3715 total_entries)); 3716 _FLOWCNT_UNLOCK(fc); 3717 return BCM_E_PARAM; 3718 } 3719 if (byte_flag == 1) { 3720 if (fc_pool->flow_stat_type[base_index+offset_index] != 3721 bcmFlowcntStatTypeByte) { 3722 _FLOWCNT_UNLOCK(fc); 3723 return BCM_E_PARAM; 3724 } 3725 } else { 3726 if (fc_pool->flow_stat_type[base_index+offset_index] != 3727 bcmFlowcntStatTypePacket) { 3728 _FLOWCNT_UNLOCK(fc); 3729 return BCM_E_PARAM; 3730 } 3731 } 3732 3733 /* sync the software counter with hardware counter */ 3734 if (sync_mode == 1) { 3735 _bcm_esw_flowcnt_counter_collect(unit, 3736 counter_mem, 3737 base_index + offset_index); 3738 } 3739 3740 bcm_stat_value_t_init(value); 3741 if (byte_flag == 1) { 3742 COMPILER_64_SET(value->bytes, 3743 COMPILER_64_HI(fc_pool-> 3744 flow_byte_counter 3745 [base_index+offset_index]), 3746 COMPILER_64_LO(fc_pool-> 3747 flow_byte_counter 3748 [base_index+offset_index])); 3749 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3750 (BSL_META_U(unit, 3751 "Byte Count Value\t:TABLE:%s " 3752 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3753 SOC_MEM_UFNAME(unit, counter_mem), 3754 pool_index, 3755 base_index+offset_index, 3756 COMPILER_64_HI(value->bytes), 3757 COMPILER_64_LO(value->bytes))); 3758 } else { 3759 value->packets= fc_pool-> 3760 flow_packet_counter[base_index+offset_index]; 3761 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3762 (BSL_META_U(unit, 3763 "Packet Count Value\t:TABLE:%s " 3764 "(@Pool:%dActualOffset%d) : %x \n"), 3765 SOC_MEM_UFNAME(unit, counter_mem), 3766 pool_index, 3767 base_index+offset_index, 3768 value->packets)); 3769 COMPILER_64_SET(value->packets64, 3770 COMPILER_64_HI(fc_pool-> 3771 flow_packet64_counter 3772 [base_index+offset_index]), 3773 COMPILER_64_LO(fc_pool-> 3774 flow_packet64_counter 3775 [base_index+offset_index])); 3776 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3777 (BSL_META_U(unit, 3778 "Packet64 Count Value\t:TABLE:%s" 3779 "(@Pool:%d ActualOffset%d) : %x:%x \n"), 3780 SOC_MEM_UFNAME(unit, counter_mem), 3781 pool_index, 3782 base_index+offset_index, 3783 COMPILER_64_HI(value->packets64), 3784 COMPILER_64_LO(value->packets64))); 3785 } 3786 _FLOWCNT_UNLOCK(fc); 3787 3788 return BCM_E_NONE; 3789 } 3790 3791 /* 3792 * Function: 3793 * _bcm_esw_flowcnt_total_counters_get 3794 * Description: 3795 * Get the total counters per profile group (derived from stat_counter_id) 3796 * Parameters: 3797 * unit - (IN) unit number 3798 * stat_counter_id - (IN) Stat Counter Id 3799 * total_counters - (OUT) Total Counters allocated 3800 * 3801 * Return Value: 3802 * BCM_E_XXX 3803 */ 3804 int 3805 _bcm_esw_flowcnt_total_counters_get( 3806 int unit, 3807 uint32 stat_counter_id, 3808 uint32 *total_counters) 3809 { 3810 _bcm_esw_flowcnt_control_t *fc = NULL; 3811 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3812 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3813 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 3814 bcm_stat_object_t object = bcmStatObjectIngPort; 3815 uint32 profile_group, pool_index, base_index; 3816 int profile_index, pool_idx; 3817 int rv = BCM_E_NONE; 3818 3819 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3820 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object, 3821 &profile_group, &pool_index, &base_index); 3822 3823 if (group_mode >= bcmStatGroupModeCount) { 3824 /* custom group */ 3825 if ((group_mode - bcmStatGroupModeCount) != profile_group) { 3826 return BCM_E_PARAM; 3827 } 3828 } else { 3829 BCM_IF_ERROR_RETURN( 3830 _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode)); 3831 } 3832 3833 BCM_IF_ERROR_RETURN( 3834 _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index, 3835 &pool_idx)); 3836 if (pool_idx != pool_index) { 3837 return BCM_E_INTERNAL; 3838 } 3839 _FLOWCNT_LOCK(fc); 3840 fc_profile = &fc->flowcnt_profile[profile_index]; 3841 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3842 *total_counters = fc_pgroup->total_counters; 3843 _FLOWCNT_UNLOCK(fc); 3844 3845 return rv; 3846 } 3847 3848 #ifdef BCM_WARM_BOOT_SUPPORT 3849 3850 /* 3851 * Function: 3852 * _bcm_esw_flowcnt_sync 3853 * Description: 3854 * Sync flex s/w copy to h/w copy 3855 * Parameters: 3856 * unit - (IN) unit number 3857 * Return Value: 3858 * BCM_E_XXX 3859 * Notes: 3860 */ 3861 int _bcm_esw_flowcnt_sync(int unit) 3862 { 3863 _bcm_flowcnt_warmboot_info_t *flowcnt_wb_info; 3864 _bcm_flowcnt_warmboot_group_info_t *flowcnt_wb_group_info; 3865 _bcm_esw_flowcnt_control_t *fc = NULL; 3866 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3867 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3868 int i, j, sel; 3869 int scache_size = 0; 3870 int scache_group_mode_num_limit; /* the limit num of group_mode in scache */ 3871 3872 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 3873 (BSL_META_U(unit, 3874 "_bcm_esw_flowcnt_sync \n"))); 3875 if ((handle == 0) || 3876 (flowcnt_scache_allocated_size[unit] == 0) || 3877 (flowcnt_scache_ptr[unit] == NULL)) { 3878 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 3879 (BSL_META_U(unit, 3880 "Scache memory was not allocate in init!! \n"))); 3881 return BCM_E_CONFIG; 3882 } 3883 3884 scache_group_mode_num_limit = FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) / sizeof(uint32); 3885 if (scache_group_mode_num_limit < bcmStatGroupModeAttrMaxValue) { 3886 /* in firmware upgrade, the number of group mode maybe increase 3887 * so dafault_id of some group mode cannot be synced into scache 3888 */ 3889 LOG_WARN(BSL_LS_BCM_FLEXCTR, 3890 (BSL_META_U(unit, 3891 "Cannot sync dafault_id after mode id %d\n"), 3892 scache_group_mode_num_limit)); 3893 } 3894 3895 scache_size = FLOWCNT_SCACHE_SIZE_1; 3896 sal_memcpy(&flowcnt_scache_ptr[unit][0], &local_scache_ptr[unit][0], 3897 scache_size); 3898 3899 flowcnt_wb_info = (_bcm_flowcnt_warmboot_info_t *) 3900 (&flowcnt_scache_ptr[unit][0] + 3901 scache_size); 3902 scache_size += FLOWCNT_SCACHE_SIZE_2_LOCAL; 3903 flowcnt_wb_group_info = (_bcm_flowcnt_warmboot_group_info_t *) 3904 (&flowcnt_scache_ptr[unit][0] + 3905 scache_size); 3906 3907 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3908 3909 _FLOWCNT_LOCK(fc); 3910 3911 for (i = 0; i < bcmStatGroupModeAttrMaxValue; i ++) { 3912 if (i >= scache_group_mode_num_limit) { 3913 break; 3914 } 3915 sal_memcpy(&flowcnt_wb_info->default_attr_mode_id[i], 3916 &fc->default_attr_mode_id[i], 3917 sizeof(uint32)); 3918 } 3919 3920 for (i = 0; i < fc->num_profiles; i++ ){ 3921 fc_profile = &fc->flowcnt_profile[i]; 3922 for (j = 0; j < fc_profile->num_groups; j ++) { 3923 fc_pgroup = &fc_profile->flowcnt_group[j]; 3924 flowcnt_wb_group_info->group_mode = fc_pgroup->group_mode; 3925 flowcnt_wb_group_info->flags = fc_pgroup->flags; 3926 flowcnt_wb_group_info->total_counters = fc_pgroup->total_counters; 3927 flowcnt_wb_group_info->num_selectors = fc_pgroup->num_selectors; 3928 for (sel = 0; sel < fc_pgroup->num_selectors; sel ++) { 3929 sal_memcpy(&flowcnt_wb_group_info->attr_selectors[sel], 3930 &fc_pgroup->attr_selectors[sel], 3931 sizeof(_bcm_flowcnt_group_mode_attr_selector_t)); 3932 } 3933 flowcnt_wb_group_info++; 3934 } 3935 } 3936 _FLOWCNT_UNLOCK(fc); 3937 return BCM_E_NONE; 3938 } 3939 /* 3940 * Retrive the total counters per profile group from HW(profile table) 3941 * NOTE: warmboot purpose 3942 */ 3943 STATIC int 3944 _bcm_esw_flowcnt_profile_table_retrieve( 3945 int unit, 3946 int profile_index, 3947 int profile_group) 3948 { 3949 soc_mem_t profile_table; 3950 uint32 entry_data_size = 0; 3951 uint32 *p_entries = NULL; 3952 int num_entries, total_counters; 3953 _bcm_esw_flowcnt_control_t *fc = NULL; 3954 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 3955 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 3956 uint32 offset_valid, offset; 3957 int i, rv; 3958 3959 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 3960 _FLOWCNT_LOCK(fc); 3961 fc_profile = &fc->flowcnt_profile[profile_index]; 3962 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 3963 profile_table = fc_profile->profile_table; 3964 num_entries = fc_profile->num_entries; 3965 3966 entry_data_size = sizeof(uint32); 3967 _FLOWCNT_ALLOC(unit, p_entries, uint32, entry_data_size * num_entries, 3968 "temp selectors table src", 1, rv); 3969 3970 rv = soc_mem_read_range(unit, profile_table, MEM_BLOCK_ANY, 3971 profile_group * num_entries, 3972 (profile_group + 1) * num_entries, 3973 p_entries); 3974 if (BCM_FAILURE(rv)){ 3975 _FLOWCNT_FREE(unit, p_entries, 1); 3976 _FLOWCNT_UNLOCK(fc); 3977 return rv; 3978 } 3979 total_counters = 0; 3980 for (i = 0; i < num_entries; i++ ){ 3981 soc_mem_field_get(unit, profile_table, 3982 (uint32 *)&p_entries[i], 3983 OFFSET_VALIDf, &offset_valid); 3984 soc_mem_field_get(unit, profile_table, 3985 (uint32 *)&p_entries[i], 3986 OFFSETf, &offset); 3987 if (offset_valid) { 3988 /* find the max offset */ 3989 if (total_counters < offset) { 3990 total_counters = offset; 3991 } 3992 } 3993 } 3994 /* numbers of counters should be offset +1 */ 3995 fc_pgroup-> total_counters = total_counters + 1; 3996 _FLOWCNT_FREE(unit, p_entries, 1); 3997 _FLOWCNT_UNLOCK(fc); 3998 return BCM_E_NONE; 3999 } 4000 4001 /* 4002 * Retrive the pool, profile_table info from HW(object table) 4003 * NOTE: warmboot purpose 4004 */ 4005 STATIC int 4006 _bcm_esw_flowcnt_warmboot_object_table_retrieve( 4007 int unit, 4008 bcm_stat_object_t object, 4009 soc_mem_t table, 4010 int min_index, 4011 int max_index) 4012 { 4013 uint32 profile_ptr, base_idx; 4014 uint32 entry_data_size=0; 4015 void *entry_data = NULL, *entry_full_data = NULL, *counter_entry_data = NULL; 4016 uint32 byte_flag; 4017 soc_mem_t counter_mem; 4018 int index=0, profile_index, pool_idx; 4019 int rv; 4020 _bcm_esw_flowcnt_control_t *fc = NULL; 4021 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 4022 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 4023 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 4024 4025 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 4026 4027 rv = _bcm_esw_flowcnt_object_table_map(unit, object, 4028 &profile_index, 4029 &pool_idx); 4030 if (BCM_FAILURE(rv)){ 4031 return rv; 4032 } 4033 _FLOWCNT_LOCK(fc); 4034 fc_profile = &fc->flowcnt_profile[profile_index]; 4035 fc_pool = &fc->flowcnt_pool[pool_idx]; 4036 4037 entry_data_size = WORDS2BYTES(BYTES2WORDS( 4038 SOC_MEM_INFO(unit, table).bytes)); 4039 if (max_index > soc_mem_index_max(unit, table)) { 4040 max_index = soc_mem_index_max(unit, table); 4041 } 4042 _FLOWCNT_ALLOC(unit, entry_full_data, void, 4043 entry_data_size * (max_index - min_index + 1), 4044 "object table", 1, rv); 4045 if (BCM_FAILURE(rv)){ 4046 _FLOWCNT_UNLOCK(fc); 4047 return rv; 4048 } 4049 4050 rv = soc_mem_read_range(unit, table, MEM_BLOCK_ANY, 4051 min_index, max_index, entry_full_data); 4052 if (BCM_FAILURE(rv)) { 4053 _FLOWCNT_FREE(unit, entry_full_data, 1); 4054 _FLOWCNT_UNLOCK(fc); 4055 return rv; 4056 } 4057 4058 for(index=0; index <= (max_index - min_index) ; index++) { 4059 entry_data = soc_mem_table_idx_to_pointer(unit, table, 4060 void *, entry_full_data, 4061 index); 4062 if (soc_mem_field_valid(unit, table, VALIDf)) { 4063 if (soc_mem_field32_get(unit, table, entry_data, 4064 VALIDf) == 0) { 4065 continue; 4066 } 4067 } 4068 rv = _bcm_esw_flowcnt_object_table_fields_values_get( 4069 unit, index, table, entry_data, 4070 &profile_ptr, &base_idx); 4071 if (BCM_FAILURE(rv)) { 4072 _FLOWCNT_FREE(unit, entry_full_data, 1); 4073 _FLOWCNT_UNLOCK(fc); 4074 return rv; 4075 } 4076 if ((profile_ptr == 0) && (base_idx == 0)) { 4077 continue; 4078 } 4079 fc_pgroup = &fc_profile->flowcnt_group[profile_ptr]; 4080 if (fc_pgroup->available == 0) { 4081 fc_pgroup->available = 1; 4082 } 4083 fc_pool->flow_base_index_reference_count[base_idx]++; 4084 fc_pool->associate_profile_group[base_idx] = 4085 profile_ptr + _BCM_FLOWCNT_PGROUP_BIAS; 4086 fc_pool->object[base_idx] = object; 4087 if (fc_pool->flow_base_index_reference_count[base_idx] == 1) { 4088 fc_pgroup->reference_count++; 4089 } 4090 if (fc_pgroup-> total_counters == 0) { 4091 /* total_counters should be able recovered by flowcnt_scache_ptr*/ 4092 rv = _bcm_esw_flowcnt_profile_table_retrieve(unit, profile_index, 4093 profile_ptr); 4094 if (BCM_FAILURE(rv)) { 4095 _FLOWCNT_UNLOCK(fc); 4096 _FLOWCNT_FREE(unit, entry_full_data, 1); 4097 return rv; 4098 } 4099 } 4100 shr_aidxres_list_reserve_block( 4101 fc_pool->flowcnt_aidxres_list_handle, 4102 base_idx, 4103 fc_pgroup->total_counters); 4104 fc_pool->pool_stat.used_entries += fc_pgroup->total_counters; 4105 fc_pool->pool_stat.attached_entries += fc_pgroup->total_counters; 4106 4107 counter_mem = fc_pool->mem; 4108 entry_data_size = WORDS2BYTES(BYTES2WORDS( 4109 SOC_MEM_INFO(unit, counter_mem).bytes)); 4110 _FLOWCNT_ALLOC(unit, counter_entry_data, void, entry_data_size, 4111 "counter table entry", 0, rv); 4112 if (BCM_FAILURE(rv)){ 4113 _FLOWCNT_UNLOCK(fc); 4114 _FLOWCNT_FREE(unit, entry_full_data, 1); 4115 return rv; 4116 } 4117 4118 if (soc_mem_read(unit, 4119 counter_mem, 4120 MEM_BLOCK_ANY, 4121 base_idx, 4122 counter_entry_data) != BCM_E_NONE){ 4123 _FLOWCNT_UNLOCK(fc); 4124 _FLOWCNT_FREE(unit, entry_full_data, 1); 4125 return BCM_E_INTERNAL; 4126 } 4127 4128 soc_mem_field_get(unit, 4129 counter_mem, 4130 (uint32 *)counter_entry_data, 4131 COUNT_BYTEf, 4132 &byte_flag); 4133 4134 if (byte_flag){ 4135 fc_pool->flow_stat_type[base_idx]= bcmFlowcntStatTypeByte; 4136 } else { 4137 fc_pool->flow_stat_type[base_idx] = bcmFlowcntStatTypePacket; 4138 } 4139 LOG_DEBUG(BSL_LS_BCM_FLEXCTR, 4140 (BSL_META_U(unit, 4141 "Table:%s index=%d mode:%d pool_number:%d " 4142 "base_idx:%d\n"), 4143 SOC_MEM_UFNAME(unit, table), 4144 index+min_index, profile_ptr, pool_idx, base_idx)); 4145 } 4146 _FLOWCNT_UNLOCK(fc); 4147 _FLOWCNT_FREE(unit, entry_full_data, 1); 4148 _FLOWCNT_FREE(unit, counter_entry_data, 0); 4149 return BCM_E_NONE; 4150 } 4151 #define _BCM_FLOWCNT_WARMBOOT_READ_CHUNK 256 4152 STATIC int 4153 _bcm_esw_flowcnt_warmboot_object_retrive(int unit) 4154 { 4155 int i, rv = BCM_E_NONE; 4156 uint32 index = 0; 4157 bcm_stat_object_t object; 4158 soc_mem_t table; 4159 for (i = 0; valid_stat_object_list[unit][i].object != -1; i++) { 4160 table = valid_stat_object_list[unit][i].object_mem; 4161 object = valid_stat_object_list[unit][i].object; 4162 index = 0; 4163 4164 if (soc_mem_index_max(unit, table) < 0) { 4165 continue; 4166 } 4167 4168 do { 4169 rv = _bcm_esw_flowcnt_warmboot_object_table_retrieve( 4170 unit, object, table, index, 4171 (index + _BCM_FLOWCNT_WARMBOOT_READ_CHUNK - 1)); 4172 if (BCM_FAILURE(rv)) { 4173 return rv; 4174 } 4175 index += _BCM_FLOWCNT_WARMBOOT_READ_CHUNK; 4176 } while (index < soc_mem_index_count(unit,table)); 4177 } 4178 return rv; 4179 } 4180 STATIC int 4181 _bcm_esw_flowcnt_warmboot_info_recover(int unit, uint8 *scache_ptr) 4182 { 4183 _bcm_esw_flowcnt_control_t *fc = NULL; 4184 _bcm_esw_flowcnt_profile_t *fc_profile = NULL; 4185 _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL; 4186 _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 4187 _bcm_flowcnt_warmboot_info_t *flowcnt_wb_info; 4188 _bcm_flowcnt_warmboot_group_info_t *flowcnt_wb_group_info; 4189 int i, j, sel; 4190 uint32 stat_counter_id; 4191 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 4192 bcm_stat_object_t object = bcmStatObjectIngPort; 4193 uint32 profile_group, pool_index, base_index; 4194 int profile_index, pool_idx; 4195 uint32 total_counters; 4196 int rv; 4197 int scache_size = 0; 4198 int scache_group_mode_num; /* the num of group_mode in scache */ 4199 uint32 *ptr = (uint32 *)scache_ptr; 4200 4201 if (flowcnt_scache_allocated_size[unit] == 0) { 4202 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 4203 (BSL_META_U(unit, 4204 "allocated size error\n"))); 4205 return BCM_E_CONFIG; 4206 } 4207 4208 scache_size = FLOWCNT_SCACHE_SIZE_1; 4209 flowcnt_wb_info = (_bcm_flowcnt_warmboot_info_t *) 4210 (scache_ptr + scache_size); 4211 scache_group_mode_num = FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) / sizeof(uint32); 4212 scache_size += FLOWCNT_SCACHE_SIZE_2_RECOVER(unit); 4213 flowcnt_wb_group_info = (_bcm_flowcnt_warmboot_group_info_t *) 4214 (scache_ptr + scache_size); 4215 4216 BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 4217 _FLOWCNT_LOCK(fc); 4218 4219 if (_bcm_esw_stat_sync_version_above_equal(unit,BCM_WB_VERSION_1_3)) { 4220 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 4221 (BSL_META_U(unit, 4222 "NEW Version\n"))); 4223 for (i = 0; i < bcmStatGroupModeAttrMaxValue; i ++){ 4224 if (i >= scache_group_mode_num) { 4225 break; 4226 } 4227 sal_memcpy(&fc->default_attr_mode_id[i], 4228 &flowcnt_wb_info->default_attr_mode_id[i], 4229 sizeof(uint32)); 4230 } 4231 4232 for (i = 0; i < fc->num_profiles; i++ ){ 4233 fc_profile = &fc->flowcnt_profile[i]; 4234 for (j = 0; j < fc_profile->num_groups; j ++) { 4235 fc_pgroup = &fc_profile->flowcnt_group[j]; 4236 fc_pgroup->group_mode = flowcnt_wb_group_info->group_mode; 4237 fc_pgroup->flags = flowcnt_wb_group_info->flags; 4238 fc_pgroup->total_counters = flowcnt_wb_group_info->total_counters; 4239 fc_pgroup->num_selectors = flowcnt_wb_group_info->num_selectors; 4240 if (fc_pgroup->num_selectors) { 4241 fc_pgroup->available = 1; 4242 rv = soc_profile_mem_reference(unit, 4243 &fc_profile->profile_mem, 4244 j*fc_profile->num_entries, 4245 1); 4246 if (BCM_FAILURE(rv)){ 4247 _FLOWCNT_UNLOCK(fc); 4248 return rv; 4249 } 4250 _FLOWCNT_ALLOC(unit, fc_pgroup->attr_selectors, 4251 _bcm_flowcnt_group_mode_attr_selector_t, 4252 fc_pgroup->num_selectors * 4253 sizeof(_bcm_flowcnt_group_mode_attr_selector_t), 4254 "flowcnt pkt attr per profile group", 0, rv); 4255 if (BCM_FAILURE(rv)){ 4256 _FLOWCNT_UNLOCK(fc); 4257 return rv; 4258 } 4259 for (sel = 0; sel < fc_pgroup->num_selectors; sel ++) { 4260 sal_memcpy(&fc_pgroup->attr_selectors[sel], 4261 &flowcnt_wb_group_info->attr_selectors[sel], 4262 sizeof(_bcm_flowcnt_group_mode_attr_selector_t)); 4263 } 4264 } 4265 flowcnt_wb_group_info++; 4266 } 4267 } 4268 } else { 4269 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR, 4270 (BSL_META_U(unit, 4271 "OLD Version so skipping NEW FLEX Layout..\n"))); 4272 } 4273 for (i = 0; i < MAX_FLOWCNT_SCACHE_SIZE; i++) { 4274 if (ptr[i] != 0) { 4275 stat_counter_id = ptr[i]; 4276 _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, 4277 &object,&profile_group, &pool_index, 4278 &base_index); 4279 if (_bcm_esw_flowcnt_object_table_map( 4280 unit, object, &profile_index, &pool_idx) != BCM_E_NONE){ 4281 continue; 4282 } 4283 fc_profile = &fc->flowcnt_profile[profile_index]; 4284 fc_pgroup = &fc_profile->flowcnt_group[profile_group]; 4285 fc_pool = &fc->flowcnt_pool[pool_idx]; 4286 total_counters = fc_pgroup->total_counters; 4287 if (total_counters == 0) { 4288 continue; 4289 } 4290 shr_aidxres_list_reserve_block( 4291 fc_pool->flowcnt_aidxres_list_handle, 4292 base_index, 4293 total_counters); 4294 fc_pool->pool_stat.used_entries += total_counters; 4295 fc_pgroup->reference_count++; 4296 } 4297 } 4298 _FLOWCNT_UNLOCK(fc); 4299 return BCM_E_NONE; 4300 } 4301 #endif 4302