pstats.c (42623B)
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 * Packetized Statistic 8 * Purpose: API to set Packetized Stats registers. 9 */ 10 11 #include <sal/core/libc.h> 12 13 #include <shared/bsl.h> 14 #include <soc/defs.h> 15 16 #if defined(INCLUDE_PSTATS) && defined(BCM_TOMAHAWK3_SUPPORT) 17 #include <soc/drv.h> 18 #include <soc/mem.h> 19 #include <soc/profile_mem.h> 20 #include <soc/debug.h> 21 #include <soc/tomahawk3.h> 22 #include <soc/pstats.h> 23 24 #include <bcm/error.h> 25 #include <bcm/pstats.h> 26 27 #include <bcm_int/bst.h> 28 #include <bcm_int/esw/mbcm.h> 29 #include <bcm_int/esw/tomahawk.h> 30 #include <bcm_int/esw/tomahawk2.h> 31 #include <bcm_int/esw/tomahawk3.h> 32 33 #include <bcm_int/esw_dispatch.h> 34 #include <bcm_int/esw/pstats.h> 35 36 #ifdef BCM_WARM_BOOT_SUPPORT 37 #include <bcm_int/esw/switch.h> 38 #endif /* BCM_WARM_BOOT_SUPPORT */ 39 40 /* MMU pktstats control flags */ 41 42 43 #define PSTATS_SESSION_MIN 1 44 #define PSTATS_SESSION_MAX 256 45 46 #define TH3_MAX_POOL_COUNT 4 47 #define TH3_MAX_UCQ_COUNT 1908 48 49 /* Max Elements Count = UCQ + ING POOL + EGR POOL */ 50 #define TH3_MAX_ELEMENT_COUNT TH3_MAX_UCQ_COUNT + TH3_MAX_POOL_COUNT * 2 51 52 #define TH3_PORT_NUM_COS(unit, port) \ 53 ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \ 54 (IS_LB_PORT(unit, port)) ? 12 : NUM_COS(unit)) 55 56 57 typedef struct pstats_session_s { 58 bcm_pstats_session_id_t session_id; 59 60 /* session buffer */ 61 bcm_pstats_timestamp_t timestamp; 62 bcm_pstats_data_t *data_array; 63 64 /* session element info */ 65 int element_array_count; 66 bcm_pstats_session_element_t element_array[TH3_MAX_ELEMENT_COUNT]; 67 68 uint32 enable; 69 70 /* prev session */ 71 struct pstats_session_s *prev_session; 72 /* next session */ 73 struct pstats_session_s *next_session; 74 } pstats_session_t; 75 76 typedef struct pstats_buffer_s { 77 soc_mem_t mem; 78 soc_mem_t clear_mem; 79 int min_idx; 80 int max_idx; 81 int num_entries; 82 uint8 *buf; 83 } pstats_buffer_t; 84 85 86 typedef struct pstats_control_s { 87 /* full buffer */ 88 #ifdef BCM_PSTATS_MEASURE 89 uint64 local_time; 90 uint64 local_time_end; 91 #endif 92 uint64 utc_time; 93 pstats_buffer_t ucq_buffer[2]; 94 _bcm_bst_cmn_unit_info_t *bst_info; 95 bcm_pstats_session_id_t next_session_id; 96 uint32 session_count; 97 #ifdef BCM_PSTATS_MEASURE 98 uint64 time_cost; 99 #endif 100 int stat_mode; 101 int hw_cor_in_max_use_count; 102 pstats_session_t *first_session; 103 } pstats_control_t; 104 105 static soc_field_t ucq_field[4] = {BST_QUEUE_TOTAL_COUNT_0f, BST_QUEUE_TOTAL_COUNT_1f, 106 BST_QUEUE_TOTAL_COUNT_2f, BST_QUEUE_TOTAL_COUNT_3f}; 107 108 static pstats_control_t *pstats_control[BCM_MAX_NUM_UNITS]; 109 #define PSTATS_CTRL_PTR(u) (pstats_control[u]) 110 #define PSTATS_CTRL(u) (*(pstats_control[u])) 111 112 STATIC int 113 bcm_th3_pstats_session_create(int unit, int options, int array_count, 114 bcm_pstats_session_element_t *element_array, 115 bcm_pstats_session_id_t *session_id); 116 STATIC int 117 bcm_th3_pstats_session_destroy(int unit, bcm_pstats_session_id_t session_id); 118 STATIC int 119 bcm_th3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id, 120 int array_max, 121 bcm_pstats_session_element_t *element_array, 122 int *array_count); 123 STATIC int bcm_th3_pstats_data_sync(int unit); 124 STATIC int 125 bcm_th3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id, 126 int sync, 127 bcm_pstats_timestamp_t *timestamp, 128 int array_max, 129 bcm_pstats_data_t *data, 130 int *array_count); 131 STATIC int 132 bcm_th3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id); 133 STATIC int 134 bcm_th3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb, 135 void *user_data); 136 137 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 138 /* 139 * Function: 140 * bcm_th3_pstats_sw_dump 141 * Purpose: 142 * Displays PSTATS information maintained by software. 143 * Parameters: 144 * unit - Device unit number 145 * Returns: 146 * None 147 */ 148 STATIC void 149 bcm_th3_pstats_sw_dump(int unit) 150 { 151 pstats_session_t *cur_session; 152 153 LOG_CLI((BSL_META_U(unit, 154 "=========== \n"))); 155 LOG_CLI((BSL_META_U(unit, "Pstats mode: %s\n"), 156 PSTATS_CTRL(unit).stat_mode ? 157 "Max-use-count" : "Instantaneous")); 158 LOG_CLI((BSL_META_U(unit, "Total pstats session count: %d\n"), 159 PSTATS_CTRL(unit).session_count)); 160 cur_session = PSTATS_CTRL(unit).first_session; 161 while (NULL != cur_session) { 162 LOG_CLI((BSL_META_U(unit, 163 "Pstats session id: %d element count: %d\n"), 164 cur_session->session_id, 165 cur_session->element_array_count)); 166 cur_session = cur_session->next_session; 167 } 168 LOG_CLI((BSL_META_U(unit, 169 "=========== \n"))); 170 return; 171 } 172 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 173 174 175 STATIC void 176 _bcm_th3_pstats_session_cleanup(int unit, pstats_session_t *session) 177 { 178 session->enable = FALSE; 179 if (NULL != session->data_array) { 180 sal_free(session->data_array); 181 } 182 183 sal_memset(session, 0, sizeof(pstats_session_t)); 184 185 return; 186 } 187 188 STATIC pstats_session_t* 189 _bcm_th3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id) 190 { 191 int found = 0; 192 pstats_session_t *cur_session; 193 194 cur_session = PSTATS_CTRL(unit).first_session; 195 while (NULL != cur_session) { 196 if (cur_session->session_id == session_id) { 197 found = 1; 198 break; 199 } 200 cur_session = cur_session->next_session; 201 } 202 203 if (found) { 204 return cur_session; 205 } 206 207 return NULL; 208 } 209 210 /* Set a minimum available session id */ 211 STATIC void 212 _bcm_th3_pstats_session_next_id_set(int unit) 213 { 214 pstats_session_t *cur_session; 215 bcm_pstats_session_id_t id = PSTATS_SESSION_MIN; 216 217 cur_session = PSTATS_CTRL(unit).first_session; 218 while (NULL != cur_session) { 219 if (id < cur_session->session_id) { 220 break; 221 } else if (id == cur_session->session_id) { 222 /* this id already existed */ 223 id++; 224 } 225 cur_session = cur_session->next_session; 226 } 227 228 PSTATS_CTRL(unit).next_session_id = id; 229 230 LOG_INFO(BSL_LS_BCM_PSTATS, (BSL_META_U(unit, "next %d\n"), id)); 231 } 232 233 STATIC int 234 _bcm_th3_pstats_session_delete(int unit, bcm_pstats_session_id_t session_id) 235 { 236 pstats_session_t *cur_session; 237 238 cur_session = _bcm_th3_pstats_session_get(unit, session_id); 239 if (NULL == cur_session) { 240 LOG_INFO(BSL_LS_BCM_PSTATS, 241 (BSL_META_U(unit, "pstats session %d not found\n"), session_id)); 242 return BCM_E_NOT_FOUND; 243 } 244 /* update session link */ 245 if ((NULL == cur_session->prev_session) && 246 (NULL == cur_session->next_session)) { 247 /* only one session */ 248 PSTATS_CTRL(unit).first_session = NULL; 249 } else if (NULL == cur_session->prev_session) { 250 /* first session */ 251 PSTATS_CTRL(unit).first_session = cur_session->next_session; 252 cur_session->next_session->prev_session = NULL; 253 } else if (NULL == cur_session->next_session) { 254 /* last session */ 255 cur_session->prev_session->next_session = NULL; 256 } else { 257 cur_session->prev_session->next_session = cur_session->next_session; 258 cur_session->next_session->prev_session = cur_session->prev_session; 259 } 260 _bcm_th3_pstats_session_cleanup(unit, cur_session); 261 if (NULL != cur_session) { 262 sal_free(cur_session); 263 } 264 PSTATS_CTRL(unit).session_count--; 265 266 _bcm_th3_pstats_session_next_id_set(unit); 267 268 return BCM_E_NONE; 269 } 270 271 STATIC void 272 _bcm_th3_pstats_session_insert(int unit, pstats_session_t *session) 273 { 274 pstats_session_t *cur_session; 275 bcm_pstats_session_id_t id = session->session_id; 276 277 cur_session = PSTATS_CTRL(unit).first_session; 278 if (NULL == cur_session) { 279 /* first session */ 280 PSTATS_CTRL(unit).first_session = session; 281 session->prev_session = NULL; 282 session->next_session = NULL; 283 } 284 while (NULL != cur_session) { 285 if (id > cur_session->session_id) { 286 /* last session */ 287 if (NULL == cur_session->next_session) { 288 cur_session->next_session = session; 289 session->prev_session = cur_session; 290 session->next_session = NULL; 291 break; 292 } else { 293 cur_session = cur_session->next_session; 294 } 295 } else { 296 /* first session */ 297 if (NULL == cur_session->prev_session) { 298 PSTATS_CTRL(unit).first_session = session; 299 session->prev_session = NULL; 300 session->next_session = cur_session; 301 cur_session->prev_session = session; 302 break; 303 } else { 304 session->prev_session = cur_session->prev_session; 305 session->next_session = cur_session; 306 cur_session->prev_session->next_session = session; 307 cur_session->prev_session = session; 308 break; 309 } 310 break; 311 } 312 } 313 PSTATS_CTRL(unit).session_count++; 314 315 session->enable = TRUE; 316 317 return; 318 } 319 320 STATIC void 321 _bcm_th3_pstats_buffer_deinit(int unit, pstats_buffer_t *pbuf) 322 { 323 if (NULL == pbuf) { 324 return; 325 } 326 327 if (NULL != pbuf->buf) { 328 sal_free(pbuf->buf); 329 } 330 sal_memset(pbuf, 0, sizeof(pstats_buffer_t)); 331 332 return; 333 } 334 335 336 STATIC int 337 _bcm_th3_pstats_buffer_init(int unit, soc_mem_t mem, soc_mem_t clear_mem, 338 pstats_buffer_t *pbuf) 339 { 340 int alloc_size; 341 342 if (NULL == pbuf) { 343 return BCM_E_PARAM; 344 } 345 346 if (NULL != pbuf->buf) { 347 return BCM_E_PARAM; 348 } 349 350 pbuf->mem = mem; 351 pbuf->clear_mem = clear_mem; 352 pbuf->min_idx = soc_mem_index_min(unit, mem); 353 pbuf->max_idx = soc_mem_index_max(unit, mem); 354 pbuf->num_entries = soc_mem_index_max(unit, mem) + 1; 355 alloc_size = sizeof(uint32) * soc_mem_entry_words(unit, mem); 356 alloc_size *= pbuf->num_entries; 357 358 pbuf->buf = sal_alloc(alloc_size, "pstats buffer"); 359 if (pbuf->buf == NULL) { 360 return BCM_E_MEMORY; 361 } 362 sal_memset(pbuf->buf, 0, alloc_size); 363 364 return BCM_E_NONE; 365 } 366 367 368 /* 369 * Function: 370 * bcm_th3_pstats_deinit 371 * Purpose: 372 * Deinitialize PSTATS driver functions 373 * for Tomahawk2 (BCM56970). 374 * Parameters: 375 * unit - (IN) StrataSwitch unit number. 376 * Returns: 377 * BCM_E_XXX 378 */ 379 void 380 bcm_th3_pstats_deinit(int unit) 381 { 382 pstats_session_t *cur_session, *next_session; 383 int i; 384 385 soc_pstats_deinit(unit); 386 if (NULL != PSTATS_CTRL_PTR(unit)) { 387 /* deinit Service pool will be done in BST*/ 388 389 for (i = 0; i < NUM_ITM(unit); i++) { 390 if (soc_tomahawk3_itm_valid(unit, i)) { 391 _bcm_th3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ucq_buffer[i]); 392 } 393 } 394 395 cur_session = PSTATS_CTRL(unit).first_session; 396 while (NULL != cur_session) { 397 next_session = cur_session->next_session; 398 _bcm_th3_pstats_session_cleanup(unit, cur_session); 399 if (NULL != cur_session) { 400 sal_free(cur_session); 401 } 402 PSTATS_CTRL(unit).session_count--; 403 cur_session = next_session; 404 } 405 406 if (PSTATS_CTRL(unit).session_count != 0) { 407 /* debug info */ 408 } 409 sal_free(PSTATS_CTRL_PTR(unit)); 410 PSTATS_CTRL_PTR(unit) = NULL; 411 } 412 413 return; 414 } 415 416 417 /* 418 * Function: 419 * bcm_th3_pstats_init 420 * Purpose: 421 * Initialize PSTATS driver functions 422 * for Tomahawk3 (BCM56980). 423 * Parameters: 424 * unit - (IN) StrataSwitch unit number. 425 * Returns: 426 * BCM_E_XXX 427 */ 428 int 429 bcm_th3_pstats_init(int unit) 430 { 431 _bcm_pstats_unit_driver_t *pstats_driver; 432 pstats_buffer_t *pbuf; 433 int rv = BCM_E_NONE; 434 soc_mem_t mem, clear_mem, base_mem; 435 int itm; 436 uint32 flag; 437 pstats_control_t *ctrl; 438 439 if (2 != soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1)) { 440 LOG_INFO(BSL_LS_BCM_PSTATS, 441 (BSL_META_U(unit, "current mode is not pstats, no need init\n"))); 442 return BCM_E_NONE; 443 } 444 445 pstats_driver = _BCM_PSTATS_UNIT_DRIVER(unit); 446 if (pstats_driver == NULL) { 447 return BCM_E_MEMORY; 448 } 449 450 ctrl = PSTATS_CTRL_PTR(unit); 451 452 if (NULL == ctrl) { 453 ctrl = sal_alloc(sizeof(pstats_control_t), "pstats_control_t"); 454 if (ctrl == NULL) { 455 return BCM_E_MEMORY; 456 } 457 } 458 sal_memset(ctrl, 0, sizeof(pstats_control_t)); 459 ctrl->bst_info = _BCM_UNIT_BST_INFO(unit); 460 if (ctrl->bst_info == NULL) { 461 return BCM_E_INTERNAL; 462 } 463 PSTATS_CTRL_PTR(unit) = ctrl; 464 /* Initializing Driver functions for PSTATS */ 465 pstats_driver->session_create = bcm_th3_pstats_session_create; 466 pstats_driver->session_destroy = bcm_th3_pstats_session_destroy; 467 pstats_driver->session_get = bcm_th3_pstats_session_get; 468 pstats_driver->data_sync = bcm_th3_pstats_data_sync; 469 pstats_driver->session_data_get = bcm_th3_pstats_session_data_get; 470 pstats_driver->session_data_clear = bcm_th3_pstats_session_data_clear; 471 pstats_driver->session_traverse = bcm_th3_pstats_session_traverse; 472 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 473 pstats_driver->pstats_sw_dump = bcm_th3_pstats_sw_dump; 474 #endif 475 476 /* alloc buffer for full pstats table */ 477 478 /* ucq buffer */ 479 base_mem = MMU_THDO_BST_TOTAL_QUEUE_PKTSTATm; 480 for (itm = 0; itm < NUM_ITM(unit); itm++) { 481 if (!soc_tomahawk3_itm_valid(unit, itm)) { 482 continue; 483 } 484 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, itm); 485 clear_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, MMU_THDO_BST_TOTAL_QUEUEm, itm); 486 if (mem == INVALIDm) { 487 continue; 488 } 489 490 pbuf = &PSTATS_CTRL(unit).ucq_buffer[itm]; 491 492 rv = _bcm_th3_pstats_buffer_init(unit, mem, clear_mem, pbuf); 493 if (BCM_FAILURE(rv)) { 494 goto cleanup; 495 } 496 } 497 498 PSTATS_CTRL(unit).next_session_id = PSTATS_SESSION_MIN; 499 500 rv = soc_pstats_init(unit); 501 if (BCM_FAILURE(rv)) { 502 LOG_INFO(BSL_LS_SOC_COMMON, 503 (BSL_META_U(unit, "soc_pstats_init failed rv = %d\n"), rv)); 504 goto cleanup; 505 } 506 507 #ifdef BCM_WARM_BOOT_SUPPORT 508 if (SOC_WARM_BOOT(unit)) { 509 int config; 510 511 /* get pstats config from HW */ 512 rv = soc_tomahawk3_mmu_pstats_mode_get(unit, &flag); 513 if (BCM_FAILURE(rv)) { 514 goto cleanup; 515 } 516 517 /* HW config is different with config property */ 518 if (!(flag & _TH3_MMU_PSTATS_ENABLE)) { 519 LOG_ERROR(BSL_LS_SOC_COMMON, 520 (BSL_META_U(unit, 521 "WARMBOOT ERROR.\n" 522 "Current buffer stats mode is not pstats.\n"))); 523 rv = BCM_E_INIT; 524 goto cleanup; 525 } 526 527 if (flag & _TH3_MMU_PSTATS_HWM_MOD) { 528 PSTATS_CTRL(unit).stat_mode = 1; 529 if (flag & _TH3_MMU_PSTATS_RESET_ON_READ) { 530 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1; 531 } else { 532 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0; 533 } 534 } else { 535 PSTATS_CTRL(unit).stat_mode = 0; 536 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0; 537 } 538 539 config = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0); 540 if (config != PSTATS_CTRL(unit).stat_mode) { 541 LOG_WARN(BSL_LS_SOC_COMMON, 542 (BSL_META_U(unit, 543 "WARMBOOT WARNING.\n" 544 "Config mode %d. HW mode %d.\n"), 545 config, PSTATS_CTRL(unit).stat_mode)); 546 } 547 548 flag |= _TH3_MMU_PSTATS_SYNC | _TH3_MMU_PSTATS_MOR_EN; 549 550 /* Reset pstats mode in warmboot */ 551 rv = soc_tomahawk3_mmu_pstats_mode_set(unit, flag); 552 if (BCM_FAILURE(rv)) { 553 goto cleanup; 554 } 555 } else 556 #endif 557 { 558 PSTATS_CTRL(unit).stat_mode = 559 soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0); 560 if ((PSTATS_CTRL(unit).stat_mode == 1) && 561 soc_property_get(unit, "oob_pstats_hw_cor_en", 1)) { 562 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1; 563 } else { 564 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0; 565 } 566 567 /* call soc function */ 568 flag = _TH3_MMU_PSTATS_ENABLE | 569 _TH3_MMU_PSTATS_SYNC | 570 _TH3_MMU_PSTATS_MOR_EN; 571 572 573 if (PSTATS_CTRL(unit).stat_mode) { 574 flag |= _TH3_MMU_PSTATS_HWM_MOD; 575 if (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1) { 576 flag |= _TH3_MMU_PSTATS_RESET_ON_READ; 577 } 578 } 579 580 rv = soc_tomahawk3_mmu_pstats_mode_set(unit, flag); 581 if (BCM_FAILURE(rv)) { 582 goto cleanup; 583 } 584 } 585 return BCM_E_NONE; 586 587 cleanup: 588 soc_pstats_deinit(unit); 589 (void)bcm_th3_pstats_deinit(unit); 590 591 return rv; 592 } 593 594 STATIC int 595 _bcm_th3_pstats_session_element_check(int unit, 596 bcm_pstats_session_element_t element) 597 { 598 bcm_gport_t gport; 599 bcm_port_t local_port; 600 bcm_cos_queue_t cosq; 601 602 LOG_INFO(BSL_LS_BCM_PSTATS, 603 (BSL_META_U(unit, "pstats_session_element_check unit %d\n"), unit)); 604 605 if (element.type == bcmPStatsSessionUnicastQueue) { 606 gport = element.gport; 607 cosq = element.cosq; 608 if (BCM_GPORT_IS_SET(gport)) { 609 if (BCM_GPORT_IS_LOCAL(gport)) { 610 local_port = BCM_GPORT_LOCAL_GET(gport); 611 } else if (BCM_GPORT_IS_MODPORT(gport)) { 612 BCM_IF_ERROR_RETURN( 613 bcm_esw_port_local_get(unit, gport, &local_port)); 614 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 615 return BCM_E_NONE; 616 } else { 617 LOG_INFO(BSL_LS_BCM_PSTATS, 618 (BSL_META_U(unit, 619 "pstats_session_element_check: " 620 "gport 0x%x is illegal!\n"), gport)); 621 return BCM_E_PARAM; 622 } 623 } else { 624 local_port = gport; 625 } 626 627 if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 628 LOG_INFO(BSL_LS_BCM_PSTATS, 629 (BSL_META_U(unit, 630 "pstats_session_element_check: " 631 "gport 0x%x is illegal!\n"), gport)); 632 return BCM_E_PORT; 633 } 634 /* cosq check when gport is a port gport */ 635 if ((cosq < 0) || (cosq >= TH3_PORT_NUM_COS(unit, local_port))) { 636 LOG_INFO(BSL_LS_BCM_PSTATS, 637 (BSL_META_U(unit, 638 "pstats_session_element_check: " 639 "cosq %d is illegal!\n"), cosq)); 640 return BCM_E_PARAM; 641 } 642 } else if ((element.type == bcmPStatsSessionIngPool) || 643 (element.type == bcmPStatsSessionEgrPool)) { 644 if ((element.pool < 0) || (element.pool >= TH3_MAX_POOL_COUNT)) { 645 LOG_INFO(BSL_LS_BCM_PSTATS, 646 (BSL_META_U(unit, 647 "pstats_session_element_check: " 648 "pool_id %d is illegal!\n"), element.pool)); 649 return BCM_E_PARAM; 650 } 651 } else { 652 LOG_INFO(BSL_LS_BCM_PSTATS, 653 (BSL_META_U(unit, 654 "pstats_session_element_check: " 655 "unknow element type %d\n"), element.type)); 656 return BCM_E_PARAM; 657 } 658 659 return BCM_E_NONE; 660 } 661 662 663 /* 664 * Function: 665 * bcm_th3_pstats_session_create 666 * Purpose: 667 * Create a PKT STAT session instance for SDK management. 668 * Parameters: 669 * unit - (IN) StrataSwitch unit number. 670 * options - (IN) BCM_PSTATS_REPLACE: replace existing. 671 * BCM_PSTATS_WITH_ID: session_id argument is given. 672 * array_count - (IN) Number of elements in array. 673 * element_array - (IN) PSTATS session element array. 674 * session_id - (INOUT) id of a PSTATS session created via this API. 675 * Returns: 676 * BCM_E_XXX 677 */ 678 STATIC int 679 bcm_th3_pstats_session_create(int unit, int options, int array_count, 680 bcm_pstats_session_element_t *element_array, 681 bcm_pstats_session_id_t *session_id) 682 { 683 int rv, i, alloc_size; 684 bcm_pstats_session_id_t id = 0; 685 pstats_session_t *cur_session = NULL; 686 687 LOG_INFO(BSL_LS_BCM_PSTATS, 688 (BSL_META_U(unit, "pstats_session_create unit %d options %d " 689 "array_count %d\n"), unit, options, array_count)); 690 691 /* element check */ 692 if ((array_count < 0) || 693 (array_count > TH3_MAX_ELEMENT_COUNT)) { 694 LOG_ERROR(BSL_LS_BCM_PSTATS, 695 (BSL_META_U(unit, "array_count %d is illegal!\n"), array_count)); 696 return BCM_E_PARAM; 697 } 698 if (NULL == element_array) { 699 LOG_ERROR(BSL_LS_BCM_PSTATS, 700 (BSL_META_U(unit, "element_array is null\n"))); 701 return BCM_E_PARAM; 702 } 703 704 for (i = 0; i < array_count; i++) { 705 BCM_IF_ERROR_RETURN( 706 _bcm_th3_pstats_session_element_check(unit, element_array[i])); 707 } 708 709 if (options & BCM_PSTATS_OPTIONS_REPLACE) { 710 /* delete original session first */ 711 id = *session_id; 712 BCM_IF_ERROR_RETURN(_bcm_th3_pstats_session_delete(unit, id)); 713 } else if (options & BCM_PSTATS_OPTIONS_WITH_ID) { 714 id = *session_id; 715 if (id < PSTATS_SESSION_MIN) { 716 LOG_ERROR(BSL_LS_BCM_PSTATS, 717 (BSL_META_U(unit, "input session_id %d is illegal!\n"), id)); 718 return BCM_E_PARAM; 719 } 720 cur_session = _bcm_th3_pstats_session_get(unit, id); 721 if (NULL != cur_session) { 722 LOG_INFO(BSL_LS_BCM_PSTATS, 723 (BSL_META_U(unit, "pstats_session_create: " 724 "session_id %d is existed\n"), id)); 725 return BCM_E_EXISTS; 726 } 727 } else { 728 id = PSTATS_CTRL(unit).next_session_id; 729 } 730 731 /* SDK has a limitation of maxium session count */ 732 if (PSTATS_CTRL(unit).session_count >= PSTATS_SESSION_MAX) { 733 LOG_INFO(BSL_LS_BCM_PSTATS, 734 (BSL_META_U(unit, "pstats_session_create: " 735 "session count is full\n"))); 736 return BCM_E_FULL; 737 } 738 739 cur_session = 740 (pstats_session_t*) sal_alloc(sizeof(pstats_session_t), 741 "pstats session"); 742 if (NULL == cur_session) { 743 return BCM_E_MEMORY; 744 } 745 sal_memset(cur_session, 0, sizeof(pstats_session_t)); 746 747 /* record session info */ 748 cur_session->session_id = id; 749 cur_session->element_array_count = array_count; 750 sal_memcpy(cur_session->element_array, 751 element_array, 752 array_count * sizeof(bcm_pstats_session_element_t)); 753 754 alloc_size = array_count * sizeof(bcm_pstats_data_t); 755 cur_session->data_array = sal_alloc(alloc_size, "data array"); 756 if (NULL == cur_session->data_array) { 757 rv = BCM_E_MEMORY; 758 goto cleanup; 759 } 760 sal_memset(cur_session->data_array, 0, alloc_size); 761 762 _bcm_th3_pstats_session_insert(unit, cur_session); 763 _bcm_th3_pstats_session_next_id_set(unit); 764 765 *session_id = id; 766 return BCM_E_NONE; 767 cleanup: 768 _bcm_th3_pstats_session_cleanup(unit, cur_session); 769 if (NULL != cur_session) { 770 sal_free(cur_session); 771 } 772 return rv; 773 } 774 775 /* 776 * Function: 777 * bcm_th3_pstats_session_destroy 778 * Purpose: 779 * Destroy an existing PSTATS session. 780 * Parameters: 781 * unit - (IN) StrataSwitch unit number. 782 * session_id - (IN) id of a PSTATS session created via the 783 * bcm_pkt==stats_session_create 784 * Returns: 785 * BCM_E_XXX 786 */ 787 STATIC int 788 bcm_th3_pstats_session_destroy(int unit, 789 bcm_pstats_session_id_t session_id) 790 { 791 return _bcm_th3_pstats_session_delete(unit, session_id); 792 } 793 794 /* 795 * Function: 796 * bcm_th3_pstats_session_get 797 * Purpose: 798 * Get an existing PSTATS session info. 799 * Parameters: 800 * unit - (IN) StrataSwitch unit number. 801 * session_id - (IN) id of a PSTATS session created via the 802 * bcm_pstats_session_create 803 * array_max - (IN) Maximum number of elements in array. 804 * element_array - (OUT) element array of a PSTATS session. 805 * array_count - (OUT) Number of elements in array. 806 * Returns: 807 * BCM_E_XXX 808 */ 809 STATIC int 810 bcm_th3_pstats_session_get(int unit, 811 bcm_pstats_session_id_t session_id, 812 int array_max, 813 bcm_pstats_session_element_t *element_array, 814 int *array_count) 815 { 816 pstats_session_t *cur_session = NULL; 817 LOG_INFO(BSL_LS_BCM_PSTATS, 818 (BSL_META_U(unit, "pstats_session_get unit %d session_id %d\n"), 819 unit, session_id)); 820 821 if (NULL == element_array) { 822 LOG_ERROR(BSL_LS_BCM_PSTATS, 823 (BSL_META_U(unit, "element_array is null\n"))); 824 return BCM_E_PARAM; 825 } 826 827 cur_session = _bcm_th3_pstats_session_get(unit, session_id); 828 if (NULL == cur_session) { 829 LOG_INFO(BSL_LS_BCM_PSTATS, 830 (BSL_META_U(unit, "pstats session %d not found\n"), session_id)); 831 return BCM_E_NOT_FOUND; 832 } 833 834 if (array_max >= cur_session->element_array_count) { 835 *array_count = cur_session->element_array_count; 836 } else if (array_max >= 0){ 837 *array_count = array_max; 838 } else { 839 return BCM_E_PARAM; 840 } 841 842 sal_memcpy(element_array, 843 cur_session->element_array, 844 *array_count * sizeof(bcm_pstats_session_element_t)); 845 846 return BCM_E_NONE; 847 } 848 849 STATIC int 850 _bcm_th3_pstats_session_data_update(int unit, 851 bcm_pstats_session_element_t element, 852 bcm_pstats_data_t *data) 853 { 854 bcm_gport_t gport; 855 bcm_port_t local_port; 856 bcm_cos_queue_t cosq; 857 int pen_idx = 0; 858 int mode, i, itm, startq, offset; 859 uint8 *total_buf; 860 uint32 cur_val = 0, *pre_p; 861 void *pentry; 862 soc_mem_t mem; 863 _bcm_bst_cmn_unit_info_t *bst_info; 864 865 mode = PSTATS_CTRL(unit).stat_mode; 866 867 if (element.type == bcmPStatsSessionUnicastQueue) { 868 869 gport = element.gport; 870 cosq = element.cosq; 871 BCM_IF_ERROR_RETURN( 872 _bcm_th3_cosq_index_resolve(unit, gport, cosq, 873 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 874 &local_port, &startq, NULL)); 875 for (itm = 0, i = 0; itm < NUM_ITM(unit); itm++) { 876 if (!soc_tomahawk3_itm_valid(unit, itm)) { 877 continue; 878 } 879 total_buf = PSTATS_CTRL(unit).ucq_buffer[itm].buf; 880 mem = PSTATS_CTRL(unit).ucq_buffer[itm].mem; 881 pen_idx = startq / 4; 882 offset = startq % 4; 883 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 884 total_buf, pen_idx); 885 cur_val = soc_mem_field32_get(unit, mem, pentry, ucq_field[offset]); 886 887 pre_p = &data->use_counts_array[i]; 888 if (mode) { 889 if (cur_val > *pre_p) { 890 *pre_p = cur_val; 891 } 892 } else { 893 *pre_p = cur_val; 894 } 895 i++; 896 } 897 data->array_count = i; 898 } else if(element.type == bcmPStatsSessionIngPool || 899 element.type == bcmPStatsSessionEgrPool) { 900 bcm_bst_stat_id_t bid = -1; 901 bcm_service_pool_id_t pool = element.pool; 902 bst_info = PSTATS_CTRL(unit).bst_info; 903 if (pool < 0 || pool >= TH3_MAX_POOL_COUNT) { 904 return BCM_E_PARAM; 905 } 906 if (element.type == bcmPStatsSessionIngPool) { 907 bid = bcmBstStatIdIngPool; 908 } else { 909 bid = bcmBstStatIdEgrPool; 910 } 911 for (itm = 0, i = 0; itm < NUM_ITM(unit); itm++) { 912 if (!soc_tomahawk3_itm_valid(unit, itm)) { 913 continue; 914 } 915 cur_val = 916 bst_info->resource_tbl[bid].p_stat[itm * TH3_MAX_POOL_COUNT + pool]; 917 pre_p = &data->use_counts_array[i]; 918 if (mode) { 919 if (cur_val > *pre_p) { 920 *pre_p = cur_val; 921 } 922 } else { 923 *pre_p = cur_val; 924 } 925 i++; 926 } 927 data->array_count = i; 928 } 929 930 return BCM_E_NONE; 931 } 932 933 STATIC int 934 _bcm_th3_pstats_session_update(int unit, pstats_session_t *session) 935 { 936 bcm_pstats_session_element_t element; 937 bcm_pstats_data_t *data; 938 pstats_session_t *cur_session = session; 939 int i; 940 soc_reg_t reg; 941 uint32 fval; 942 /* 943 * update UTC timestamp 944 */ 945 reg = MMU_GLBCFG_UTC_TIMESTAMPr; 946 cur_session->timestamp.nanoseconds = 947 soc_reg64_field32_get 948 (unit, reg, PSTATS_CTRL(unit).utc_time, UTC_TIMESTAMP_NSECf); 949 950 fval = soc_reg64_field32_get(unit, reg, PSTATS_CTRL(unit).utc_time, UTC_TIMESTAMP_SECf); 951 COMPILER_64_ADD_32(cur_session->timestamp.seconds, fval); 952 953 #ifdef BCM_PSTATS_MEASURE 954 if (soc_property_get(unit, "pstats_timestamp_info", 0) == 1) { 955 COMPILER_64_TO_32_LO(cur_session->timestamp.nanoseconds, 956 PSTATS_CTRL(unit).time_cost); 957 } 958 #endif 959 960 /* update element data */ 961 for (i = 0; i < cur_session->element_array_count; i++) { 962 element = cur_session->element_array[i]; 963 data = &cur_session->data_array[i]; 964 BCM_IF_ERROR_RETURN( 965 _bcm_th3_pstats_session_data_update(unit, element, data)); 966 } 967 968 return BCM_E_NONE; 969 } 970 971 /* 972 * Function: 973 * _bcm_th3_pstats_hw_sync 974 * Purpose: 975 * Start a pstats sync operation. 976 * Parameters: 977 * unit - (IN) StrataSwitch unit number 978 * Returns: 979 * BCM_E_XXX 980 */ 981 STATIC int 982 _bcm_th3_pstats_hw_sync(int unit) 983 { 984 pstats_buffer_t *pbuf; 985 int itm; 986 soc_reg_t reg; 987 SOC_IF_ERROR_RETURN(soc_pstats_sync(unit)); 988 989 #ifdef BCM_PSTATS_MEASURE 990 991 reg = MMU_GLBCFG_TIMESTAMPr; 992 SOC_IF_ERROR_RETURN( 993 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).local_time)); 994 995 SOC_IF_ERROR_RETURN( 996 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).local_time)); 997 #endif 998 /*sync UTC time */ 999 COMPILER_64_ZERO(PSTATS_CTRL(unit).utc_time); 1000 reg = MMU_GLBCFG_UTC_TIMESTAMPr; 1001 SOC_IF_ERROR_RETURN( 1002 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).utc_time)); 1003 /* sync uc queue */ 1004 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1005 if (soc_tomahawk3_itm_valid(unit, itm)) { 1006 pbuf = &PSTATS_CTRL(unit).ucq_buffer[itm]; 1007 SOC_IF_ERROR_RETURN( 1008 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1009 } 1010 } 1011 1012 /* following resources are shared with BST */ 1013 BCM_IF_ERROR_RETURN(bcm_th_cosq_bst_stat_sync(unit, bcmBstStatIdIngPool)); 1014 1015 BCM_IF_ERROR_RETURN(bcm_th_cosq_bst_stat_sync(unit, bcmBstStatIdEgrPool)); 1016 1017 return BCM_E_NONE; 1018 } 1019 1020 /* 1021 * Function: 1022 * _bcm_th3_pstats_session_data_sync 1023 * Purpose: 1024 * Start a pstats sync operation for a special session 1025 * Parameters: 1026 * unit - (IN) StrataSwitch unit number 1027 * Returns: 1028 * BCM_E_XXX 1029 */ 1030 STATIC int 1031 _bcm_th3_pstats_session_data_sync(int unit, pstats_session_t *session) 1032 { 1033 BCM_IF_ERROR_RETURN(_bcm_th3_pstats_hw_sync(unit)); 1034 BCM_IF_ERROR_RETURN(_bcm_th3_pstats_session_update(unit, session)); 1035 return BCM_E_NONE; 1036 } 1037 1038 /* 1039 * Function: 1040 * bcm_th3_pstats_data_sync 1041 * Purpose: 1042 * Start a pstats sync operation. 1043 * Parameters: 1044 * unit - (IN) StrataSwitch unit number 1045 * Returns: 1046 * BCM_E_XXX 1047 */ 1048 STATIC int 1049 bcm_th3_pstats_data_sync(int unit) 1050 { 1051 pstats_session_t *cur_session = NULL; 1052 sal_usecs_t start_time = sal_time_usecs(); 1053 1054 BCM_IF_ERROR_RETURN(_bcm_th3_pstats_hw_sync(unit)); 1055 LOG_DEBUG(BSL_LS_SOC_COMMON, 1056 (BSL_META_U(unit, "Time taken for pstats dma: %d usec\n"), 1057 SAL_USECS_SUB(sal_time_usecs(), start_time))); 1058 cur_session = PSTATS_CTRL(unit).first_session; 1059 while (NULL != cur_session) { 1060 if (cur_session->enable != TRUE) { 1061 continue; 1062 } 1063 BCM_IF_ERROR_RETURN( 1064 _bcm_th3_pstats_session_update(unit, cur_session)); 1065 cur_session = cur_session->next_session; 1066 } 1067 return BCM_E_NONE; 1068 } 1069 1070 /* 1071 * Function: 1072 * bcm_th3_pstats_session_data_get 1073 * Purpose: 1074 * Get an existing PSTATS session data. 1075 * Parameters: 1076 * unit - (IN) StrataSwitch unit number 1077 * session_id - (IN) id of a PSTATS session created via the 1078 * bcm_pstats_session_create 1079 * sync - (IN) Need a sync operation 1080 * timestamp - (OUT) time stamp info. 1081 * array_max - (IN) Maximum number of elements in array. 1082 * data - (OUT) array of use count data. 1083 * array_count - (OUT) Number of elements in array. 1084 * Returns: 1085 * BCM_E_XXX 1086 */ 1087 STATIC int 1088 bcm_th3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id, 1089 int sync, 1090 bcm_pstats_timestamp_t *timestamp, 1091 int array_max, 1092 bcm_pstats_data_t *data_array, 1093 int *array_count) 1094 { 1095 pstats_session_t *cur_session = NULL; 1096 int mode; 1097 1098 LOG_INFO(BSL_LS_BCM_PSTATS, 1099 (BSL_META_U(unit, "pstats_session_data_get unit %d session_id %d " 1100 "sync %d\n"), unit, session_id, sync)); 1101 1102 if (NULL == data_array) { 1103 LOG_ERROR(BSL_LS_BCM_PSTATS, 1104 (BSL_META_U(unit, "data_array is null\n"))); 1105 return BCM_E_PARAM; 1106 } 1107 1108 mode = PSTATS_CTRL(unit).stat_mode; 1109 cur_session = _bcm_th3_pstats_session_get(unit, session_id); 1110 if (NULL == cur_session) { 1111 LOG_INFO(BSL_LS_BCM_PSTATS, 1112 (BSL_META_U(unit, "pstats_session_data_get: " 1113 "session_id %d is not found\n"), session_id)); 1114 return BCM_E_NOT_FOUND; 1115 } 1116 1117 if (array_max >= cur_session->element_array_count) { 1118 *array_count = cur_session->element_array_count; 1119 } else if (array_max >= 0){ 1120 *array_count = array_max; 1121 } else { 1122 LOG_ERROR(BSL_LS_BCM_PSTATS, 1123 (BSL_META_U(unit, "array_max %d is illegal\n"), array_max)); 1124 return BCM_E_PARAM; 1125 } 1126 1127 /* if PKT STAT mode is HWM, need to sync up all sessions */ 1128 if (TRUE == sync) { 1129 if (mode) { 1130 BCM_IF_ERROR_RETURN(bcm_th3_pstats_data_sync(unit)); 1131 } else { 1132 BCM_IF_ERROR_RETURN( 1133 _bcm_th3_pstats_session_data_sync(unit, cur_session)); 1134 } 1135 } 1136 1137 sal_memcpy(data_array, cur_session->data_array, 1138 *array_count * sizeof(bcm_pstats_data_t)); 1139 1140 sal_memcpy(timestamp, &cur_session->timestamp, sizeof(bcm_pstats_timestamp_t)); 1141 1142 return BCM_E_NONE; 1143 } 1144 1145 STATIC int 1146 _bcm_th3_pstats_session_data_hw_clear(int unit, bcm_pstats_session_element_t element) 1147 { 1148 bcm_gport_t gport; 1149 bcm_port_t local_port; 1150 bcm_cos_queue_t cosq; 1151 int itm, startq; 1152 soc_mem_t mem; 1153 uint32 entry[SOC_MAX_MEM_WORDS]; 1154 _bcm_bst_cmn_unit_info_t *bst_info; 1155 1156 bst_info = PSTATS_CTRL(unit).bst_info; 1157 1158 if (element.type == bcmPStatsSessionUnicastQueue) { 1159 gport = element.gport; 1160 cosq = element.cosq; 1161 /* Retrieve HW mem Index from resolve */ 1162 BCM_IF_ERROR_RETURN( 1163 _bcm_th3_cosq_index_resolve(unit, gport, cosq, 1164 _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE, 1165 &local_port, &startq, NULL)); 1166 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1167 if (!soc_tomahawk3_itm_valid(unit, itm)) { 1168 continue; 1169 } 1170 mem = PSTATS_CTRL(unit).ucq_buffer[itm].clear_mem; 1171 SOC_IF_ERROR_RETURN( 1172 soc_mem_read(unit, mem, MEM_BLOCK_ANY, startq, entry)); 1173 soc_mem_field32_set(unit, mem, entry, BST_QUEUE_TOTAL_COUNTf, 0); 1174 SOC_IF_ERROR_RETURN( 1175 soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 1176 } 1177 } else if (element.type == bcmPStatsSessionIngPool 1178 || element.type == bcmPStatsSessionEgrPool) { 1179 bcm_bst_stat_id_t bid = -1; 1180 if (element.type == bcmPStatsSessionIngPool) { 1181 bid = bcmBstStatIdIngPool; 1182 } else { 1183 bid = bcmBstStatIdEgrPool; 1184 } 1185 1186 BCM_IF_ERROR_RETURN( 1187 bcm_bst_th3_hw_stat_clear(unit, &bst_info->resource_tbl[bid], 1188 bid, -1, -1, element.pool, -1)); 1189 } 1190 return BCM_E_NONE; 1191 } 1192 1193 /* 1194 * Function: 1195 * bcm_th3_pstats_session_data_clear 1196 * Purpose: 1197 * Clear an existing PSTATS session hw use counts and sw use counts buffer. 1198 * Parameters: 1199 * unit - (IN) StrataSwitch unit number. 1200 * session_id - (IN) id of a PSTATS session created via the 1201 * bcm_pstats_session_create. 1202 * Returns: 1203 * BCM_E_XXX 1204 */ 1205 STATIC int 1206 bcm_th3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id) 1207 { 1208 bcm_pstats_session_element_t element; 1209 pstats_session_t *cur_session = NULL; 1210 int i, need_hw_clear = 1; 1211 1212 LOG_INFO(BSL_LS_BCM_PSTATS, 1213 (BSL_META_U(unit, "pstats_session_data_clear unit %d session_id %d\n"), 1214 unit, session_id)); 1215 1216 cur_session = _bcm_th3_pstats_session_get(unit, session_id); 1217 if (NULL == cur_session) { 1218 LOG_INFO(BSL_LS_BCM_PSTATS, 1219 (BSL_META_U(unit, "pstats_session_data_clear: " 1220 "session_id %d is not found\n"), session_id)); 1221 return BCM_E_NOT_FOUND; 1222 } 1223 1224 /* clear HW use count buffer */ 1225 if ((PSTATS_CTRL(unit).stat_mode == 1) && 1226 (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1)) { 1227 /* HW clear on read is enabled, no need do hw clear */ 1228 need_hw_clear = 0; 1229 } 1230 1231 if (need_hw_clear == 1) { 1232 for (i = 0; i < cur_session->element_array_count; i++) { 1233 element = cur_session->element_array[i]; 1234 BCM_IF_ERROR_RETURN( 1235 _bcm_th3_pstats_session_data_hw_clear(unit, element)); 1236 } 1237 } 1238 1239 /* clear SW use count buffer */ 1240 sal_memset(cur_session->data_array, 0, 1241 cur_session->element_array_count * sizeof(bcm_pstats_data_t)); 1242 1243 return BCM_E_NONE; 1244 } 1245 1246 /* 1247 * Function: 1248 * bcm_th3_pstats_session_traverse 1249 * Purpose: 1250 * Traverse through the pstats sessions and run callback at each session. 1251 * Parameters: 1252 * unit - (IN) StrataSwitch unit number. 1253 * cb - (IN) bcm_pstats_session_traverse_cb. 1254 * user_data - (IN) User data to be passed to callback function. 1255 * Returns: 1256 * BCM_E_XXX 1257 */ 1258 STATIC int 1259 bcm_th3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb, 1260 void *user_data) 1261 { 1262 bcm_pstats_session_element_t *element_array; 1263 bcm_pstats_session_id_t session_id; 1264 pstats_session_t *cur_session = NULL; 1265 int array_count; 1266 int rv = BCM_E_NONE; 1267 1268 LOG_INFO(BSL_LS_BCM_PSTATS, 1269 (BSL_META_U(unit, "pstats_session_travers unit %d\n"), unit)); 1270 1271 cur_session = PSTATS_CTRL(unit).first_session; 1272 while (NULL != cur_session) { 1273 session_id = cur_session->session_id; 1274 array_count = cur_session->element_array_count; 1275 element_array = (bcm_pstats_session_element_t *) sal_alloc( 1276 sizeof(bcm_pstats_session_element_t) * array_count, 1277 "pstats session elements"); 1278 if (element_array == NULL) { 1279 return BCM_E_MEMORY; 1280 } 1281 1282 sal_memcpy(element_array, cur_session->element_array, 1283 array_count * sizeof(bcm_pstats_session_element_t)); 1284 1285 cur_session = cur_session->next_session; 1286 1287 rv = cb(unit, session_id, array_count, element_array, user_data); 1288 #ifdef BCM_CB_ABORT_ON_ERR 1289 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 1290 sal_free(element_array); 1291 return rv; 1292 } 1293 #else 1294 /* 1295 * If CB_ABORT_ON_ERR is not defined don't return error 1296 * and continue. 1297 */ 1298 sal_free(element_array); 1299 rv = BCM_E_NONE; 1300 #endif 1301 } 1302 1303 return rv; 1304 } 1305 #else /* INCLUDE_PSTATS && BCM_TOMAHAWK3_SUPPORT */ 1306 int bcm_esw_tomahawk3_pstats_not_empty; 1307 #endif /* INCLUDE_PSTATS && BCM_TOMAHAWK3_SUPPORT */ 1308 1309 1310