pstats.c (49095B)
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_TRIDENT3_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/trident3.h> 22 #include <soc/helix5.h> 23 #include <soc/pstats.h> 24 25 #include <bcm/error.h> 26 #include <bcm/pstats.h> 27 28 #include <bcm_int/esw/mbcm.h> 29 #include <bcm_int/esw/tomahawk.h> 30 #include <bcm_int/esw/trident3.h> 31 #include <bcm_int/esw/helix5.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 #define PSTATS_SESSION_MIN 1 41 #define PSTATS_SESSION_MAX 256 42 /* Max 1 XPEs and 2 PIPEs */ 43 #define HX5_MAX_XPEPIPE _HX5_PIPES_PER_DEV * _HX5_XPES_PER_DEV 44 45 #define HX5_MAX_POOL_COUNT 4 46 #define HX5_MAX_UCQ_COUNT 1280 47 48 /* Max Elements Count = UCQ + ING POOL + EGR POOL */ 49 #define HX5_MAX_ELEMENT_COUNT HX5_MAX_UCQ_COUNT + HX5_MAX_POOL_COUNT * 2 50 51 52 /* 53 * Macro to get buffer index 54 * Per XPE or PIPE instance (ING POOL & EGR POOL) 55 * buffer_id = xpe or pipe 56 * ---------------------- 57 * | buffer | pool id | 58 * | 0 | 0 | 59 * | 1 | 1 | 60 * | 2 | 2 | 61 * | 3 | 3 | 62 * ---------------------- 63 * Per XPE-PIPE instance (UCQ) 64 * buffer_id = xpe * NUM_PIPE(unit) + pipe 65 * -------------------- 66 * | buffer | xpe | pipe | 67 * | 0 | 0 | 0 | 68 * | 1 | 0 | 1 | 69 */ 70 #define HX5_XPE_PIPE_INDEX(unit, xpe, pipe) \ 71 (((xpe) == -1) ? (pipe) : \ 72 ((pipe) == -1) ? (xpe) : (xpe) * NUM_PIPE(unit) + (pipe)) 73 74 #define HX5_XPE_VALID(unit, xpe, valid) \ 75 if (xpe > NUM_XPE(unit)) { \ 76 valid = FALSE; \ 77 } \ 78 79 80 typedef struct pstats_session_s { 81 bcm_pstats_session_id_t session_id; 82 83 /* session buffer */ 84 bcm_pstats_timestamp_t timestamp; 85 bcm_pstats_data_t *data_array; 86 87 /* session element info */ 88 int element_array_count; 89 bcm_pstats_session_element_t element_array[HX5_MAX_ELEMENT_COUNT]; 90 91 uint32 enable; 92 93 /* prev session */ 94 struct pstats_session_s *prev_session; 95 /* next session */ 96 struct pstats_session_s *next_session; 97 } pstats_session_t; 98 99 typedef struct pstats_buffer_s { 100 soc_mem_t mem; 101 soc_mem_t clear_mem; 102 int min_idx; 103 int max_idx; 104 int num_entries; 105 uint8 *buf; 106 } pstats_buffer_t; 107 108 typedef struct pstats_control_s { 109 /* full buffer */ 110 #ifdef BCM_PSTATS_MEASURE 111 pstats_buffer_t local_time; 112 pstats_buffer_t local_time_end; 113 #endif 114 pstats_buffer_t utc_time; 115 pstats_buffer_t ucq_buffer[HX5_MAX_XPEPIPE]; 116 pstats_buffer_t ing_pool_buffer[HX5_MAX_POOL_COUNT]; 117 pstats_buffer_t egr_pool_buffer[HX5_MAX_POOL_COUNT]; 118 119 bcm_pstats_session_id_t next_session_id; 120 uint32 session_count; 121 #ifdef BCM_PSTATS_MEASURE 122 uint64 time_cost; 123 #endif 124 int stat_mode; 125 int hw_cor_in_max_use_count; 126 pstats_session_t *first_session; 127 } pstats_control_t; 128 129 static soc_field_t ucq_field[4] = {UCQ_COUNT0f, UCQ_COUNT1f, 130 UCQ_COUNT2f, UCQ_COUNT3f}; 131 static soc_field_t isp_field[4] = {SP0f, SP1f, SP2f, SP3f}; 132 static soc_field_t esp_field[4] = {COUNT_0f, COUNT_1f, 133 COUNT_2f, COUNT_3f}; 134 135 static pstats_control_t pstats_control[BCM_MAX_NUM_UNITS]; 136 #define PSTATS_CTRL(u) pstats_control[u] 137 138 STATIC int 139 bcm_hx5_pstats_session_create(int unit, int options, int array_count, 140 bcm_pstats_session_element_t *element_array, 141 bcm_pstats_session_id_t *session_id); 142 STATIC int 143 bcm_hx5_pstats_session_destroy(int unit, bcm_pstats_session_id_t session_id); 144 STATIC int 145 bcm_hx5_pstats_session_get(int unit, bcm_pstats_session_id_t session_id, 146 int array_max, 147 bcm_pstats_session_element_t *element_array, 148 int *array_count); 149 STATIC int bcm_hx5_pstats_data_sync(int unit); 150 STATIC int 151 bcm_hx5_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id, 152 int sync, 153 bcm_pstats_timestamp_t *timestamp, 154 int array_max, 155 bcm_pstats_data_t *data, 156 int *array_count); 157 STATIC int 158 bcm_hx5_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id); 159 160 STATIC int 161 bcm_hx5_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb, 162 void *user_data); 163 164 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 165 /* 166 * Function: 167 * bcm_hx5_pstats_sw_dump 168 * Purpose: 169 * Displays PSTATS information maintained by software. 170 * Parameters: 171 * unit - Device unit number 172 * Returns: 173 * None 174 */ 175 STATIC void 176 bcm_hx5_pstats_sw_dump(int unit) 177 { 178 pstats_session_t *cur_session; 179 180 LOG_CLI((BSL_META_U(unit, 181 "=========== \n"))); 182 LOG_CLI((BSL_META_U(unit, "Pstats mode: %s\n"), 183 PSTATS_CTRL(unit).stat_mode ? 184 "Max-use-count" : "Instantaneous")); 185 LOG_CLI((BSL_META_U(unit, "Total pstats session count: %d\n"), 186 PSTATS_CTRL(unit).session_count)); 187 cur_session = PSTATS_CTRL(unit).first_session; 188 while (NULL != cur_session) { 189 LOG_CLI((BSL_META_U(unit, 190 "Pstats session id: %d element count: %d\n"), 191 cur_session->session_id, 192 cur_session->element_array_count)); 193 cur_session = cur_session->next_session; 194 } 195 LOG_CLI((BSL_META_U(unit, 196 "=========== \n"))); 197 return; 198 } 199 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 200 201 STATIC void 202 _bcm_hx5_pstats_session_cleanup(int unit, pstats_session_t *session) 203 { 204 session->enable = FALSE; 205 if (NULL != session->data_array) { 206 sal_free(session->data_array); 207 } 208 209 sal_memset(session, 0, sizeof(pstats_session_t)); 210 211 return; 212 } 213 214 STATIC pstats_session_t* 215 _bcm_hx5_pstats_session_get(int unit, bcm_pstats_session_id_t session_id) 216 { 217 int found = 0; 218 pstats_session_t *cur_session; 219 220 cur_session = PSTATS_CTRL(unit).first_session; 221 while (NULL != cur_session) { 222 if (cur_session->session_id == session_id) { 223 found = 1; 224 break; 225 } 226 cur_session = cur_session->next_session; 227 } 228 229 if (found) { 230 return cur_session; 231 } 232 233 return NULL; 234 } 235 236 /* Set a minimum available session id */ 237 STATIC void 238 _bcm_hx5_pstats_session_next_id_set(int unit) 239 { 240 pstats_session_t *cur_session; 241 bcm_pstats_session_id_t id = PSTATS_SESSION_MIN; 242 243 cur_session = PSTATS_CTRL(unit).first_session; 244 while (NULL != cur_session) { 245 if (id < cur_session->session_id) { 246 break; 247 } else if (id == cur_session->session_id) { 248 /* this id already existed */ 249 id++; 250 } 251 cur_session = cur_session->next_session; 252 } 253 254 PSTATS_CTRL(unit).next_session_id = id; 255 256 LOG_INFO(BSL_LS_BCM_PSTATS, (BSL_META_U(unit, "next %d\n"), id)); 257 } 258 259 STATIC int 260 _bcm_hx5_pstats_session_delete(int unit, bcm_pstats_session_id_t session_id) 261 { 262 pstats_session_t *cur_session; 263 264 cur_session = _bcm_hx5_pstats_session_get(unit, session_id); 265 if (NULL == cur_session) { 266 LOG_INFO(BSL_LS_BCM_PSTATS, 267 (BSL_META_U(unit, "pstats session %d not found\n"), session_id)); 268 return BCM_E_NOT_FOUND; 269 } 270 /* update session link */ 271 if ((NULL == cur_session->prev_session) && 272 (NULL == cur_session->next_session)) { 273 /* only one session */ 274 PSTATS_CTRL(unit).first_session = NULL; 275 } else if (NULL == cur_session->prev_session) { 276 /* first session */ 277 PSTATS_CTRL(unit).first_session = cur_session->next_session; 278 cur_session->next_session->prev_session = NULL; 279 } else if (NULL == cur_session->next_session) { 280 /* last session */ 281 cur_session->prev_session->next_session = NULL; 282 } else { 283 cur_session->prev_session->next_session = cur_session->next_session; 284 cur_session->next_session->prev_session = cur_session->prev_session; 285 } 286 _bcm_hx5_pstats_session_cleanup(unit, cur_session); 287 if (NULL != cur_session) { 288 sal_free(cur_session); 289 } 290 PSTATS_CTRL(unit).session_count--; 291 292 _bcm_hx5_pstats_session_next_id_set(unit); 293 294 return BCM_E_NONE; 295 } 296 297 STATIC void 298 _bcm_hx5_pstats_session_insert(int unit, pstats_session_t *session) 299 { 300 pstats_session_t *cur_session; 301 bcm_pstats_session_id_t id = session->session_id; 302 303 cur_session = PSTATS_CTRL(unit).first_session; 304 if (NULL == cur_session) { 305 /* first session */ 306 PSTATS_CTRL(unit).first_session = session; 307 session->prev_session = NULL; 308 session->next_session = NULL; 309 } 310 while (NULL != cur_session) { 311 if (id > cur_session->session_id) { 312 /* last session */ 313 if (NULL == cur_session->next_session) { 314 cur_session->next_session = session; 315 session->prev_session = cur_session; 316 session->next_session = NULL; 317 break; 318 } else { 319 cur_session = cur_session->next_session; 320 } 321 } else { 322 /* first session */ 323 if (NULL == cur_session->prev_session) { 324 PSTATS_CTRL(unit).first_session = session; 325 session->prev_session = NULL; 326 session->next_session = cur_session; 327 cur_session->prev_session = session; 328 break; 329 } else { 330 session->prev_session = cur_session->prev_session; 331 session->next_session = cur_session; 332 cur_session->prev_session->next_session = session; 333 cur_session->prev_session = session; 334 break; 335 } 336 break; 337 } 338 } 339 PSTATS_CTRL(unit).session_count++; 340 341 session->enable = TRUE; 342 343 return; 344 } 345 346 STATIC void 347 _bcm_hx5_pstats_buffer_deinit(int unit, pstats_buffer_t *pbuf) 348 { 349 if (NULL == pbuf) { 350 return; 351 } 352 353 if (NULL != pbuf->buf) { 354 sal_free(pbuf->buf); 355 } 356 sal_memset(pbuf, 0, sizeof(pstats_buffer_t)); 357 358 return; 359 } 360 361 STATIC int 362 _bcm_hx5_pstats_buffer_init(int unit, soc_mem_t mem, soc_mem_t clear_mem, 363 pstats_buffer_t *pbuf) 364 { 365 int alloc_size; 366 367 if (NULL == pbuf) { 368 return BCM_E_PARAM; 369 } 370 371 if (NULL != pbuf->buf) { 372 return BCM_E_PARAM; 373 } 374 375 pbuf->mem = mem; 376 pbuf->clear_mem = clear_mem; 377 pbuf->min_idx = soc_mem_index_min(unit, mem); 378 pbuf->max_idx = soc_mem_index_max(unit, mem); 379 pbuf->num_entries = soc_mem_index_max(unit, mem) + 1; 380 alloc_size = sizeof(uint32) * soc_mem_entry_words(unit, mem); 381 alloc_size *= pbuf->num_entries; 382 383 pbuf->buf = sal_alloc(alloc_size, "pstats buffer"); 384 if (pbuf->buf == NULL) { 385 return BCM_E_MEMORY; 386 } 387 sal_memset(pbuf->buf, 0, alloc_size); 388 389 return BCM_E_NONE; 390 } 391 392 /* 393 * Function: 394 * bcm_hx5_pstats_deinit 395 * Purpose: 396 * Deinitialize PSTATS driver functions 397 * for Trident3 (BCM56870). 398 * Parameters: 399 * unit - (IN) StrataSwitch unit number. 400 * Returns: 401 * BCM_E_XXX 402 */ 403 void 404 bcm_hx5_pstats_deinit(int unit) 405 { 406 pstats_session_t *cur_session, *next_session; 407 int i; 408 409 soc_pstats_deinit(unit); 410 411 #ifdef BCM_PSTATS_MEASURE 412 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).local_time); 413 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).local_time_end); 414 #endif 415 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).utc_time); 416 for (i = 0; i < HX5_MAX_XPEPIPE; i++) { 417 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ucq_buffer[i]); 418 } 419 for (i = 0; i < HX5_MAX_POOL_COUNT; i++) { 420 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ing_pool_buffer[i]); 421 _bcm_hx5_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).egr_pool_buffer[i]); 422 } 423 424 cur_session = PSTATS_CTRL(unit).first_session; 425 while (NULL != cur_session) { 426 next_session = cur_session->next_session; 427 _bcm_hx5_pstats_session_cleanup(unit, cur_session); 428 if (NULL != cur_session) { 429 sal_free(cur_session); 430 } 431 PSTATS_CTRL(unit).session_count--; 432 cur_session = next_session; 433 } 434 435 if (PSTATS_CTRL(unit).session_count != 0) { 436 /* debug info */ 437 } 438 sal_memset(&PSTATS_CTRL(unit), 0, sizeof(pstats_control_t)); 439 440 return; 441 } 442 443 444 /* 445 * Function: 446 * bcm_hx5_pstats_init 447 * Purpose: 448 * Initialize PSTATS driver functions 449 * for Trident3 (BCM56970). 450 * Parameters: 451 * unit - (IN) StrataSwitch unit number. 452 * Returns: 453 * BCM_E_XXX 454 */ 455 int 456 bcm_hx5_pstats_init(int unit) 457 { 458 _bcm_pstats_unit_driver_t *pstats_driver; 459 pstats_buffer_t *pbuf; 460 int rv = BCM_E_NONE; 461 soc_mem_t mem, clear_mem, base_mem; 462 int index, pipe, xpe; 463 uint32 flag; 464 465 if (2 != soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1)) { 466 LOG_INFO(BSL_LS_BCM_PSTATS, 467 (BSL_META_U(unit, "current mode is not pstats, no need init\n"))); 468 return BCM_E_NONE; 469 } 470 471 pstats_driver = _BCM_PSTATS_UNIT_DRIVER(unit); 472 if (pstats_driver == NULL) { 473 return BCM_E_MEMORY; 474 } 475 476 /* Initializing Driver functions for PSTATS */ 477 pstats_driver->session_create = bcm_hx5_pstats_session_create; 478 pstats_driver->session_destroy = bcm_hx5_pstats_session_destroy; 479 pstats_driver->session_get = bcm_hx5_pstats_session_get; 480 pstats_driver->data_sync = bcm_hx5_pstats_data_sync; 481 pstats_driver->session_data_get = bcm_hx5_pstats_session_data_get; 482 pstats_driver->session_data_clear = bcm_hx5_pstats_session_data_clear; 483 pstats_driver->session_traverse = bcm_hx5_pstats_session_traverse; 484 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 485 pstats_driver->pstats_sw_dump = bcm_hx5_pstats_sw_dump; 486 #endif 487 488 /* alloc buffer for full pstats table */ 489 #ifdef BCM_PSTATS_MEASURE 490 /* local time */ 491 mem = MMU_INTFO_TIMESTAMPm; 492 pbuf = &PSTATS_CTRL(unit).local_time; 493 rv = _bcm_hx5_pstats_buffer_init(unit, mem, mem, pbuf); 494 if (BCM_FAILURE(rv)) { 495 goto cleanup; 496 } 497 mem = MMU_INTFO_TIMESTAMPm; 498 pbuf = &PSTATS_CTRL(unit).local_time_end; 499 rv = _bcm_hx5_pstats_buffer_init(unit, mem, mem, pbuf); 500 if (BCM_FAILURE(rv)) { 501 goto cleanup; 502 } 503 #endif 504 505 /* utc time */ 506 mem = MMU_INTFO_UTC_TIMESTAMPm; 507 pbuf = &PSTATS_CTRL(unit).utc_time; 508 rv = _bcm_hx5_pstats_buffer_init(unit, mem, mem, pbuf); 509 if (BCM_FAILURE(rv)) { 510 goto cleanup; 511 } 512 513 /* ucq buffer */ 514 base_mem = MMU_THDU_UCQ_STATS_TABLEm; 515 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 516 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 517 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 518 clear_mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, MMU_THDU_UCQ_STATSm, 519 xpe, pipe); 520 if (mem == INVALIDm) { 521 continue; 522 } 523 524 index = HX5_XPE_PIPE_INDEX(unit, xpe, pipe); 525 if (index >= HX5_MAX_XPEPIPE) { 526 rv = BCM_E_INTERNAL; 527 goto cleanup; 528 } 529 pbuf = &PSTATS_CTRL(unit).ucq_buffer[index]; 530 531 rv = _bcm_hx5_pstats_buffer_init(unit, mem, clear_mem, pbuf); 532 if (BCM_FAILURE(rv)) { 533 goto cleanup; 534 } 535 } 536 } /* ucq buffer */ 537 538 /* ing pool buffer */ 539 base_mem = THDI_PKT_STAT_SP_SHARED_COUNTm; 540 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 541 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[xpe]; 542 if (mem == INVALIDm) { 543 continue; 544 } 545 546 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 547 if (index >= HX5_MAX_POOL_COUNT) { 548 rv = BCM_E_INTERNAL; 549 goto cleanup; 550 } 551 552 pbuf = &PSTATS_CTRL(unit).ing_pool_buffer[index]; 553 554 rv = _bcm_hx5_pstats_buffer_init(unit, mem, mem, pbuf); 555 if (BCM_FAILURE(rv)) { 556 goto cleanup; 557 } 558 } /* ing pool buffer */ 559 560 /* egr pool buffer */ 561 base_mem = MMU_THDM_DB_POOL_MCUC_PKSTATm; 562 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 563 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[xpe]; 564 if (mem == INVALIDm) { 565 continue; 566 } 567 568 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 569 if (index >= HX5_MAX_POOL_COUNT) { 570 rv = BCM_E_INTERNAL; 571 goto cleanup; 572 } 573 574 pbuf = &PSTATS_CTRL(unit).egr_pool_buffer[index]; 575 576 rv = _bcm_hx5_pstats_buffer_init(unit, mem, mem, pbuf); 577 if (BCM_FAILURE(rv)) { 578 goto cleanup; 579 } 580 } /* egr pool buffer */ 581 582 PSTATS_CTRL(unit).next_session_id = PSTATS_SESSION_MIN; 583 584 rv = soc_pstats_init(unit); 585 if (BCM_FAILURE(rv)) { 586 LOG_INFO(BSL_LS_SOC_COMMON, 587 (BSL_META_U(unit, "soc_pstats_init failed rv = %d\n"), rv)); 588 goto cleanup; 589 } 590 591 #ifdef BCM_WARM_BOOT_SUPPORT 592 if (SOC_WARM_BOOT(unit)) { 593 int config; 594 595 /* get pstats config from HW */ 596 rv = soc_helix5_mmu_pstats_mode_get(unit, &flag); 597 if (BCM_FAILURE(rv)) { 598 goto cleanup; 599 } 600 601 /* HW config is different with config property */ 602 if (!(flag & _HX5_MMU_PSTATS_ENABLE) || 603 !(flag & _HX5_MMU_PSTATS_PKT_MOD)) { 604 LOG_ERROR(BSL_LS_SOC_COMMON, 605 (BSL_META_U(unit, 606 "WARMBOOT ERROR.\n" 607 "Current buffer stats mode is not pstats.\n"))); 608 rv = BCM_E_INIT; 609 goto cleanup; 610 } 611 612 if (flag & _HX5_MMU_PSTATS_HWM_MOD) { 613 PSTATS_CTRL(unit).stat_mode = 1; 614 if (flag & _HX5_MMU_PSTATS_RESET_ON_READ) { 615 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1; 616 } else { 617 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0; 618 } 619 } else { 620 PSTATS_CTRL(unit).stat_mode = 0; 621 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0; 622 } 623 624 config = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0); 625 if (config != PSTATS_CTRL(unit).stat_mode) { 626 LOG_WARN(BSL_LS_SOC_COMMON, 627 (BSL_META_U(unit, 628 "WARMBOOT WARNING.\n" 629 "Config mode %d. HW mode %d.\n"), 630 config, PSTATS_CTRL(unit).stat_mode)); 631 } 632 633 flag |= _HX5_MMU_PSTATS_SYNC | _HX5_MMU_PSTATS_MOR_EN; 634 635 /* Reset pstats mode in warmboot */ 636 rv = soc_helix5_mmu_pstats_mode_set(unit, flag); 637 if (BCM_FAILURE(rv)) { 638 goto cleanup; 639 } 640 } else 641 #endif 642 { 643 PSTATS_CTRL(unit).stat_mode = 644 soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0); 645 if ((PSTATS_CTRL(unit).stat_mode == 1) && 646 soc_property_get(unit, "oob_pstats_hw_cor_en", 1)) { 647 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1; 648 } 649 650 /* call soc function */ 651 flag = _HX5_MMU_PSTATS_ENABLE | 652 _HX5_MMU_PSTATS_SYNC | 653 _HX5_MMU_PSTATS_MOR_EN; 654 655 656 if (PSTATS_CTRL(unit).stat_mode) { 657 flag |= _HX5_MMU_PSTATS_HWM_MOD; 658 if (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1) { 659 flag |= _HX5_MMU_PSTATS_RESET_ON_READ; 660 } 661 } 662 663 rv = soc_helix5_mmu_pstats_mode_set(unit, flag); 664 if (BCM_FAILURE(rv)) { 665 goto cleanup; 666 } 667 } 668 669 return BCM_E_NONE; 670 671 cleanup: 672 soc_pstats_deinit(unit); 673 (void )bcm_hx5_pstats_deinit(unit); 674 675 return rv; 676 } 677 678 STATIC int 679 _bcm_hx5_pstats_session_element_check(int unit, 680 bcm_pstats_session_element_t element) 681 { 682 bcm_gport_t gport; 683 bcm_port_t local_port; 684 bcm_cos_queue_t cosq; 685 soc_info_t *si = &SOC_INFO(unit); 686 687 LOG_INFO(BSL_LS_BCM_PSTATS, 688 (BSL_META_U(unit, "pstats_session_element_check unit %d\n"), unit)); 689 690 LOG_INFO(BSL_LS_BCM_PSTATS, 691 (BSL_META_U(unit, " type = %d gport = %d cosq = %d \n"), unit, element.gport, element.cosq)); 692 693 if (element.type == bcmPStatsSessionUnicastQueue) { 694 gport = element.gport; 695 cosq = element.cosq; 696 if (BCM_GPORT_IS_SET(gport)) { 697 if (BCM_GPORT_IS_LOCAL(gport)) { 698 local_port = BCM_GPORT_LOCAL_GET(gport); 699 } else if (BCM_GPORT_IS_MODPORT(gport)) { 700 BCM_IF_ERROR_RETURN( 701 bcm_esw_port_local_get(unit, gport, &local_port)); 702 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 703 return BCM_E_NONE; 704 } else { 705 LOG_INFO(BSL_LS_BCM_PSTATS, 706 (BSL_META_U(unit, "pstats_session_element_check: " 707 "gport 0x%x is illegal!\n"), gport)); 708 return BCM_E_PARAM; 709 } 710 } else { 711 local_port = gport; 712 } 713 714 if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 715 LOG_INFO(BSL_LS_BCM_PSTATS, 716 (BSL_META_U(unit, "pstats_session_element_check: " 717 "gport 0x%x is illegal!\n"), gport)); 718 return BCM_E_PORT; 719 } 720 /* cosq check when gport is a port gport */ 721 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 722 LOG_INFO(BSL_LS_BCM_PSTATS, 723 (BSL_META_U(unit, "pstats_session_element_check: " 724 "cosq %d is illegal!\n"), cosq)); 725 return BCM_E_PARAM; 726 } 727 } else if ((element.type == bcmPStatsSessionIngPool) || 728 (element.type == bcmPStatsSessionEgrPool)) { 729 if ((element.pool < 0) || (element.pool >= HX5_MAX_POOL_COUNT)) { 730 LOG_INFO(BSL_LS_BCM_PSTATS, 731 (BSL_META_U(unit, "pstats_session_element_check: " 732 "pool_id %d is illegal!\n"), element.pool)); 733 return BCM_E_PARAM; 734 } 735 } else { 736 LOG_INFO(BSL_LS_BCM_PSTATS, 737 (BSL_META_U(unit, "pstats_session_element_check: " 738 "unknow element type %d\n"), element.type)); 739 return BCM_E_PARAM; 740 } 741 742 return BCM_E_NONE; 743 } 744 745 746 /* 747 * Function: 748 * bcm_hx5_pstats_session_create 749 * Purpose: 750 * Create a PKT STAT session instance for SDK management. 751 * Parameters: 752 * unit - (IN) StrataSwitch unit number. 753 * options - (IN) BCM_PSTATS_REPLACE: replace existing. 754 * BCM_PSTATS_WITH_ID: session_id argument is given. 755 * array_count - (IN) Number of elements in array. 756 * element_array - (IN) PSTATS session element array. 757 * session_id - (INOUT) id of a PSTATS session created via this API. 758 * Returns: 759 * BCM_E_XXX 760 */ 761 STATIC int 762 bcm_hx5_pstats_session_create(int unit, int options, int array_count, 763 bcm_pstats_session_element_t *element_array, 764 bcm_pstats_session_id_t *session_id) 765 { 766 int rv, i, alloc_size; 767 bcm_pstats_session_id_t id = 0; 768 pstats_session_t *cur_session = NULL; 769 770 LOG_INFO(BSL_LS_BCM_PSTATS, 771 (BSL_META_U(unit, "pstats_session_create unit %d options %d " 772 "array_count %d\n"), unit, options, array_count)); 773 774 /* element check */ 775 if ((array_count < 0) || 776 (array_count > HX5_MAX_ELEMENT_COUNT)) { 777 LOG_ERROR(BSL_LS_BCM_PSTATS, 778 (BSL_META_U(unit, "array_count %d is illegal!\n"), array_count)); 779 return BCM_E_PARAM; 780 } 781 if (NULL == element_array) { 782 LOG_ERROR(BSL_LS_BCM_PSTATS, 783 (BSL_META_U(unit, "element_array is null\n"))); 784 return BCM_E_PARAM; 785 } 786 787 for (i = 0; i < array_count; i++) { 788 BCM_IF_ERROR_RETURN( 789 _bcm_hx5_pstats_session_element_check(unit, element_array[i])); 790 } 791 792 if (options & BCM_PSTATS_OPTIONS_REPLACE) { 793 /* delete original session first */ 794 id = *session_id; 795 BCM_IF_ERROR_RETURN(_bcm_hx5_pstats_session_delete(unit, id)); 796 } else if (options & BCM_PSTATS_OPTIONS_WITH_ID) { 797 id = *session_id; 798 if (id < PSTATS_SESSION_MIN) { 799 LOG_ERROR(BSL_LS_BCM_PSTATS, 800 (BSL_META_U(unit, "input session_id %d is illegal!\n"), id)); 801 return BCM_E_PARAM; 802 } 803 cur_session = _bcm_hx5_pstats_session_get(unit, id); 804 if (NULL != cur_session) { 805 LOG_INFO(BSL_LS_BCM_PSTATS, 806 (BSL_META_U(unit, "pstats_session_create: " 807 "session_id %d is existed\n"), id)); 808 return BCM_E_EXISTS; 809 } 810 } else { 811 id = PSTATS_CTRL(unit).next_session_id; 812 } 813 814 /* SDK has a limitation of maxium session count */ 815 if (PSTATS_CTRL(unit).session_count >= PSTATS_SESSION_MAX) { 816 LOG_INFO(BSL_LS_BCM_PSTATS, 817 (BSL_META_U(unit, "pstats_session_create: " 818 "session count is full\n"))); 819 return BCM_E_FULL; 820 } 821 822 cur_session = 823 (pstats_session_t*) sal_alloc(sizeof(pstats_session_t), 824 "pstats session"); 825 if (NULL == cur_session) { 826 return BCM_E_MEMORY; 827 } 828 sal_memset(cur_session, 0, sizeof(pstats_session_t)); 829 830 /* record session info */ 831 cur_session->session_id = id; 832 cur_session->element_array_count = array_count; 833 sal_memcpy(cur_session->element_array, 834 element_array, 835 array_count * sizeof(bcm_pstats_session_element_t)); 836 837 alloc_size = array_count * sizeof(bcm_pstats_data_t); 838 cur_session->data_array = sal_alloc(alloc_size, "data array"); 839 if (NULL == cur_session->data_array) { 840 rv = BCM_E_MEMORY; 841 goto cleanup; 842 } 843 sal_memset(cur_session->data_array, 0, alloc_size); 844 845 _bcm_hx5_pstats_session_insert(unit, cur_session); 846 _bcm_hx5_pstats_session_next_id_set(unit); 847 848 *session_id = id; 849 return BCM_E_NONE; 850 cleanup: 851 _bcm_hx5_pstats_session_cleanup(unit, cur_session); 852 if (NULL != cur_session) { 853 sal_free(cur_session); 854 } 855 return rv; 856 } 857 858 /* 859 * Function: 860 * bcm_hx5_pstats_session_destroy 861 * Purpose: 862 * Destroy an existing PSTATS session. 863 * Parameters: 864 * unit - (IN) StrataSwitch unit number. 865 * session_id - (IN) id of a PSTATS session created via the 866 * bcm_pkt==stats_session_create 867 * Returns: 868 * BCM_E_XXX 869 */ 870 STATIC int 871 bcm_hx5_pstats_session_destroy(int unit, 872 bcm_pstats_session_id_t session_id) 873 { 874 return _bcm_hx5_pstats_session_delete(unit, session_id); 875 } 876 877 /* 878 * Function: 879 * bcm_hx5_pstats_session_get 880 * Purpose: 881 * Get an existing PSTATS session info. 882 * Parameters: 883 * unit - (IN) StrataSwitch unit number. 884 * session_id - (IN) id of a PSTATS session created via the 885 * bcm_pstats_session_create 886 * array_max - (IN) Maximum number of elements in array. 887 * element_array - (OUT) element array of a PSTATS session. 888 * array_count - (OUT) Number of elements in array. 889 * Returns: 890 * BCM_E_XXX 891 */ 892 STATIC int 893 bcm_hx5_pstats_session_get(int unit, 894 bcm_pstats_session_id_t session_id, 895 int array_max, 896 bcm_pstats_session_element_t *element_array, 897 int *array_count) 898 { 899 pstats_session_t *cur_session = NULL; 900 901 LOG_INFO(BSL_LS_BCM_PSTATS, 902 (BSL_META_U(unit, "pstats_session_get unit %d session_id %d\n"), 903 unit, session_id)); 904 905 if (NULL == element_array) { 906 LOG_ERROR(BSL_LS_BCM_PSTATS, 907 (BSL_META_U(unit, "element_array is null\n"))); 908 return BCM_E_PARAM; 909 } 910 911 cur_session = _bcm_hx5_pstats_session_get(unit, session_id); 912 if (NULL == cur_session) { 913 LOG_INFO(BSL_LS_BCM_PSTATS, 914 (BSL_META_U(unit, "pstats session %d not found\n"), session_id)); 915 return BCM_E_NOT_FOUND; 916 } 917 918 if (array_max >= cur_session->element_array_count) { 919 *array_count = cur_session->element_array_count; 920 } else if (array_max >= 0) { 921 *array_count = array_max; 922 } else { 923 return BCM_E_PARAM; 924 } 925 926 sal_memcpy(element_array, 927 cur_session->element_array, 928 *array_count * sizeof(bcm_pstats_session_element_t)); 929 930 return BCM_E_NONE; 931 } 932 933 STATIC int 934 _bcm_hx5_pstats_session_data_update(int unit, 935 bcm_pstats_session_element_t element, 936 bcm_pstats_data_t *data) 937 { 938 bcm_gport_t gport; 939 bcm_port_t local_port; 940 bcm_cos_queue_t cosq; 941 bcm_service_pool_id_t pool; 942 int index, pen_idx = 0; 943 int mode, i, xpe, pipe, startq, offset; 944 uint8 *total_buf; 945 uint32 cur_val = 0, *pre_p; 946 void *pentry; 947 soc_info_t *si = &SOC_INFO(unit); 948 soc_mem_t mem; 949 soc_field_t field; 950 951 mode = PSTATS_CTRL(unit).stat_mode; 952 953 if (element.type == bcmPStatsSessionUnicastQueue) { 954 /* update ucq use counts 955 * ucq_buf: 956 * 0-1 each XPE has two pipes */ 957 gport = element.gport; 958 cosq = element.cosq; 959 BCM_IF_ERROR_RETURN( 960 _bcm_hx5_cosq_index_resolve(unit, gport, cosq, 961 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 962 &local_port, &startq, NULL)); 963 pipe = si->port_pipe[local_port]; 964 965 for (xpe = 0, i = 0; xpe < NUM_XPE(unit); xpe++) { 966 967 if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) { 968 continue; 969 } 970 index = HX5_XPE_PIPE_INDEX(unit, xpe, pipe); 971 if (index >= HX5_MAX_XPEPIPE) { 972 return BCM_E_INTERNAL; 973 } 974 total_buf = PSTATS_CTRL(unit).ucq_buffer[index].buf; 975 mem = PSTATS_CTRL(unit).ucq_buffer[index].mem; 976 pen_idx = startq / 4; 977 offset = startq % 4; 978 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 979 total_buf, pen_idx); 980 cur_val = soc_mem_field32_get(unit, mem, pentry, ucq_field[offset]); 981 982 pre_p = &data->use_counts_array[i]; 983 if (mode) { 984 if (cur_val > *pre_p) { 985 *pre_p = cur_val; 986 } 987 } else { 988 *pre_p = cur_val; 989 } 990 i++; 991 } 992 data->array_count = i; 993 } else { 994 /* update pool use counts 995 * pool_buf: 996 * xpe0-p0 997 */ 998 pool = element.pool; 999 for (xpe = 0, i = 0; xpe < NUM_XPE(unit); xpe++) { 1000 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 1001 if (index >= HX5_MAX_POOL_COUNT) { 1002 return BCM_E_INTERNAL; 1003 } 1004 1005 if (element.type == bcmPStatsSessionIngPool) { 1006 total_buf = PSTATS_CTRL(unit).ing_pool_buffer[xpe].buf; 1007 mem = PSTATS_CTRL(unit).ing_pool_buffer[xpe].mem; 1008 field = isp_field[pool]; 1009 } else if (element.type == bcmPStatsSessionEgrPool) { 1010 total_buf = PSTATS_CTRL(unit).egr_pool_buffer[xpe].buf; 1011 mem = PSTATS_CTRL(unit).egr_pool_buffer[xpe].mem; 1012 field = esp_field[pool]; 1013 } else { 1014 return BCM_E_INTERNAL; 1015 } 1016 1017 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, 1018 total_buf, pen_idx); 1019 cur_val = soc_mem_field32_get(unit, mem, pentry, field); 1020 pre_p = &data->use_counts_array[i]; 1021 if (mode) { 1022 if (cur_val > *pre_p) { 1023 *pre_p = cur_val; 1024 } 1025 } else { 1026 *pre_p = cur_val; 1027 } 1028 i++; 1029 } 1030 data->array_count = i; 1031 } 1032 1033 return BCM_E_NONE; 1034 } 1035 1036 STATIC int 1037 _bcm_hx5_pstats_session_update(int unit, pstats_session_t *session) 1038 { 1039 bcm_pstats_session_element_t element; 1040 bcm_pstats_data_t *data; 1041 pstats_session_t *cur_session = session; 1042 uint8 *total_buf; 1043 int i; 1044 void *pentry; 1045 soc_mem_t mem; 1046 1047 /* update timestamp 1048 * if MMU_INTFO_TOD_TIMESTAMP is updated by ARM core, 1049 * MMU_INTFO_UTC_TIMESTAMP is a utc time. 1050 * otherwise it is a local time. 1051 */ 1052 total_buf = PSTATS_CTRL(unit).utc_time.buf; 1053 mem = PSTATS_CTRL(unit).utc_time.mem; 1054 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, total_buf, 0); 1055 cur_session->timestamp.nanoseconds = 1056 soc_mem_field32_get(unit, mem, pentry, UTC_TIMESTAMP_NSECf); 1057 soc_mem_field64_get(unit, mem, pentry, UTC_TIMESTAMP_SECf, 1058 &cur_session->timestamp.seconds); 1059 1060 #ifdef BCM_PSTATS_MEASURE 1061 if (soc_property_get(unit, "pstats_timestamp_info", 0) == 1) { 1062 COMPILER_64_TO_32_LO(cur_session->timestamp.nanoseconds, 1063 PSTATS_CTRL(unit).time_cost); 1064 } 1065 #endif 1066 1067 /* update element data */ 1068 for (i = 0; i < cur_session->element_array_count; i++) { 1069 element = cur_session->element_array[i]; 1070 data = &cur_session->data_array[i]; 1071 BCM_IF_ERROR_RETURN( 1072 _bcm_hx5_pstats_session_data_update(unit, element, data)); 1073 } 1074 1075 return BCM_E_NONE; 1076 } 1077 1078 /* 1079 * Function: 1080 * _bcm_hx5_pstats_hw_sync 1081 * Purpose: 1082 * Start a pstats sync operation. 1083 * Parameters: 1084 * unit - (IN) StrataSwitch unit number 1085 * Returns: 1086 * BCM_E_XXX 1087 */ 1088 STATIC int 1089 _bcm_hx5_pstats_hw_sync(int unit) 1090 { 1091 pstats_buffer_t *pbuf; 1092 int index, pipe, xpe; 1093 soc_info_t *si = &SOC_INFO(unit); 1094 #ifdef BCM_PSTATS_MEASURE 1095 void *pentry; 1096 uint64 start_ts, end_ts; 1097 #endif 1098 1099 SOC_IF_ERROR_RETURN(soc_pstats_sync(unit)); 1100 1101 #ifdef BCM_PSTATS_MEASURE 1102 /* sync local time */ 1103 pbuf = &PSTATS_CTRL(unit).local_time; 1104 SOC_IF_ERROR_RETURN( 1105 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1106 pentry = soc_mem_table_idx_to_pointer(unit, pbuf->mem, void*, 1107 pbuf->buf, 0); 1108 soc_mem_field64_get(unit, pbuf->mem, pentry, TIMESTAMPf, &start_ts); 1109 1110 pbuf = &PSTATS_CTRL(unit).local_time_end; 1111 SOC_IF_ERROR_RETURN( 1112 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 1)); 1113 pentry = soc_mem_table_idx_to_pointer(unit, pbuf->mem, void*, 1114 pbuf->buf, 0); 1115 soc_mem_field64_get(unit, pbuf->mem, pentry, TIMESTAMPf, &end_ts); 1116 1117 LOG_INFO(BSL_LS_BCM_PSTATS, 1118 (BSL_META_U(unit, "start 0x%x%8x end 0x%x%8x\n"), 1119 COMPILER_64_HI(start_ts), COMPILER_64_LO(start_ts), 1120 COMPILER_64_HI(end_ts), COMPILER_64_LO(end_ts))); 1121 1122 /* handle rollover */ 1123 if (COMPILER_64_LT(end_ts, start_ts)) { 1124 uint64 wrap_amt; 1125 int width; 1126 1127 width = soc_mem_field_length(unit, MMU_INTFO_TIMESTAMPm, TIMESTAMPf); 1128 COMPILER_64_SET(wrap_amt, 1UL << (width - 32), 0); 1129 COMPILER_64_ADD_64(end_ts, wrap_amt); 1130 } 1131 COMPILER_64_DELTA(PSTATS_CTRL(unit).time_cost, start_ts, end_ts); 1132 #endif 1133 1134 1135 /* sync utc time */ 1136 pbuf = &PSTATS_CTRL(unit).utc_time; 1137 SOC_IF_ERROR_RETURN( 1138 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1139 1140 /* sync uc queue */ 1141 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 1142 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1143 1144 if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) { 1145 continue; 1146 } 1147 index = HX5_XPE_PIPE_INDEX(unit, xpe, pipe); 1148 if (index >= HX5_MAX_XPEPIPE) { 1149 return BCM_E_INTERNAL; 1150 } 1151 pbuf = &PSTATS_CTRL(unit).ucq_buffer[index]; 1152 SOC_IF_ERROR_RETURN( 1153 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1154 } 1155 } 1156 1157 /* sync ing pool */ 1158 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1159 1160 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 1161 if (index >= HX5_MAX_POOL_COUNT) { 1162 return BCM_E_INTERNAL; 1163 } 1164 pbuf = &PSTATS_CTRL(unit).ing_pool_buffer[index]; 1165 SOC_IF_ERROR_RETURN( 1166 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1167 } 1168 1169 /* sync egr pool */ 1170 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1171 1172 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 1173 if (index >= HX5_MAX_POOL_COUNT) { 1174 return BCM_E_INTERNAL; 1175 } 1176 pbuf = &PSTATS_CTRL(unit).egr_pool_buffer[index]; 1177 SOC_IF_ERROR_RETURN( 1178 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0)); 1179 } 1180 1181 return BCM_E_NONE; 1182 } 1183 1184 /* 1185 * Function: 1186 * _bcm_hx5_pstats_session_data_sync 1187 * Purpose: 1188 * Start a pstats sync operation for a special session 1189 * Parameters: 1190 * unit - (IN) StrataSwitch unit number 1191 * Returns: 1192 * BCM_E_XXX 1193 */ 1194 STATIC int 1195 _bcm_hx5_pstats_session_data_sync(int unit, pstats_session_t *session) 1196 { 1197 BCM_IF_ERROR_RETURN(_bcm_hx5_pstats_hw_sync(unit)); 1198 BCM_IF_ERROR_RETURN(_bcm_hx5_pstats_session_update(unit, session)); 1199 return BCM_E_NONE; 1200 } 1201 1202 /* 1203 * Function: 1204 * bcm_hx5_pstats_data_sync 1205 * Purpose: 1206 * Start a pstats sync operation. 1207 * Parameters: 1208 * unit - (IN) StrataSwitch unit number 1209 * Returns: 1210 * BCM_E_XXX 1211 */ 1212 STATIC int 1213 bcm_hx5_pstats_data_sync(int unit) 1214 { 1215 pstats_session_t *cur_session = NULL; 1216 sal_usecs_t start_time = sal_time_usecs(); 1217 1218 BCM_IF_ERROR_RETURN(_bcm_hx5_pstats_hw_sync(unit)); 1219 LOG_DEBUG(BSL_LS_SOC_COMMON, 1220 (BSL_META_U(unit, "Time taken for pstats dma: %d usec\n"), 1221 SAL_USECS_SUB(sal_time_usecs(), start_time))); 1222 cur_session = PSTATS_CTRL(unit).first_session; 1223 while (NULL != cur_session) { 1224 if (cur_session->enable != TRUE) { 1225 continue; 1226 } 1227 BCM_IF_ERROR_RETURN( 1228 _bcm_hx5_pstats_session_update(unit, cur_session)); 1229 cur_session = cur_session->next_session; 1230 } 1231 return BCM_E_NONE; 1232 } 1233 1234 /* 1235 * Function: 1236 * bcm_hx5_pstats_session_data_get 1237 * Purpose: 1238 * Get an existing PSTATS session data. 1239 * Parameters: 1240 * unit - (IN) StrataSwitch unit number 1241 * session_id - (IN) id of a PSTATS session created via the 1242 * bcm_pstats_session_create 1243 * sync - (IN) Need a sync operation 1244 * timestamp - (OUT) time stamp info. 1245 * array_max - (IN) Maximum number of elements in array. 1246 * data - (OUT) array of use count data. 1247 * array_count - (OUT) Number of elements in array. 1248 * Returns: 1249 * BCM_E_XXX 1250 */ 1251 STATIC int 1252 bcm_hx5_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id, 1253 int sync, 1254 bcm_pstats_timestamp_t *timestamp, 1255 int array_max, 1256 bcm_pstats_data_t *data_array, 1257 int *array_count) 1258 { 1259 pstats_session_t *cur_session = NULL; 1260 int mode; 1261 1262 LOG_INFO(BSL_LS_BCM_PSTATS, 1263 (BSL_META_U(unit, "pstats_session_data_get unit %d session_id %d " 1264 "sync %d\n"), unit, session_id, sync)); 1265 1266 if (NULL == data_array) { 1267 LOG_ERROR(BSL_LS_BCM_PSTATS, 1268 (BSL_META_U(unit, "data_array is null\n"))); 1269 return BCM_E_PARAM; 1270 } 1271 1272 mode = PSTATS_CTRL(unit).stat_mode; 1273 cur_session = _bcm_hx5_pstats_session_get(unit, session_id); 1274 if (NULL == cur_session) { 1275 LOG_INFO(BSL_LS_BCM_PSTATS, 1276 (BSL_META_U(unit, "pstats_session_data_get: " 1277 "session_id %d is not found\n"), session_id)); 1278 return BCM_E_NOT_FOUND; 1279 } 1280 1281 if (array_max >= cur_session->element_array_count) { 1282 *array_count = cur_session->element_array_count; 1283 } else if (array_max >= 0) { 1284 *array_count = array_max; 1285 } else { 1286 LOG_ERROR(BSL_LS_BCM_PSTATS, 1287 (BSL_META_U(unit, "array_max %d is illegal\n"), array_max)); 1288 return BCM_E_PARAM; 1289 } 1290 1291 /* if PKT STAT mode is HWM, need to sync up all sessions */ 1292 if (TRUE == sync) { 1293 if (mode) { 1294 BCM_IF_ERROR_RETURN(bcm_hx5_pstats_data_sync(unit)); 1295 } else { 1296 BCM_IF_ERROR_RETURN( 1297 _bcm_hx5_pstats_session_data_sync(unit, cur_session)); 1298 } 1299 } 1300 1301 sal_memcpy(data_array, cur_session->data_array, 1302 *array_count * sizeof(bcm_pstats_data_t)); 1303 1304 sal_memcpy(timestamp, &cur_session->timestamp, sizeof(bcm_pstats_timestamp_t)); 1305 1306 return BCM_E_NONE; 1307 } 1308 1309 STATIC int 1310 _bcm_hx5_pstats_session_data_hw_clear(int unit, bcm_pstats_session_element_t element) 1311 { 1312 bcm_gport_t gport; 1313 bcm_port_t local_port; 1314 bcm_cos_queue_t cosq; 1315 bcm_service_pool_id_t pool; 1316 int index, xpe, pipe, startq; 1317 soc_info_t *si = &SOC_INFO(unit); 1318 soc_mem_t mem; 1319 soc_field_t field; 1320 uint32 entry[SOC_MAX_MEM_WORDS]; 1321 1322 if (element.type == bcmPStatsSessionUnicastQueue) { 1323 /* update ucq use counts 1324 * ucq_buf: 1325 * 0-1 each XPE has two pipes */ 1326 gport = element.gport; 1327 cosq = element.cosq; 1328 BCM_IF_ERROR_RETURN( 1329 _bcm_hx5_cosq_index_resolve(unit, gport, cosq, 1330 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 1331 &local_port, &startq, NULL)); 1332 pipe = si->port_pipe[local_port]; 1333 1334 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1335 1336 if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) { 1337 continue; 1338 } 1339 index = HX5_XPE_PIPE_INDEX(unit, xpe, pipe); 1340 if (index >= HX5_MAX_XPEPIPE) { 1341 return BCM_E_INTERNAL; 1342 } 1343 mem = PSTATS_CTRL(unit).ucq_buffer[index].clear_mem; 1344 SOC_IF_ERROR_RETURN( 1345 soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 1346 soc_mem_field32_set(unit, mem, entry, UCQ_COUNTf, 0); 1347 SOC_IF_ERROR_RETURN( 1348 soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 1349 } 1350 } else { 1351 /* update pool use counts 1352 * pool_buf: 1353 * 0-3 |xpe0-p0|xpe1-p0|xpe2-p0|xpe3-p0| 1354 */ 1355 pool = element.pool; 1356 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1357 1358 index = HX5_XPE_PIPE_INDEX(unit, xpe, -1); 1359 if (index >= HX5_MAX_POOL_COUNT) { 1360 return BCM_E_INTERNAL; 1361 } 1362 1363 if (element.type == bcmPStatsSessionIngPool) { 1364 mem = PSTATS_CTRL(unit).ing_pool_buffer[xpe].clear_mem; 1365 field = isp_field[pool]; 1366 } else if (element.type == bcmPStatsSessionEgrPool) { 1367 mem = PSTATS_CTRL(unit).egr_pool_buffer[xpe].clear_mem; 1368 field = esp_field[pool]; 1369 } else { 1370 return BCM_E_INTERNAL; 1371 } 1372 SOC_IF_ERROR_RETURN( 1373 soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, entry)); 1374 soc_mem_field32_set(unit, mem, entry, field, 0); 1375 SOC_IF_ERROR_RETURN( 1376 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry)); 1377 } 1378 } 1379 1380 return BCM_E_NONE; 1381 } 1382 1383 /* 1384 * Function: 1385 * bcm_pstats_session_data_clear 1386 * Purpose: 1387 * Clear an existing PSTATS session hw use counts and sw use counts buffer. 1388 * Parameters: 1389 * unit - (IN) StrataSwitch unit number. 1390 * session_id - (IN) id of a PSTATS session created via the 1391 * bcm_pstats_session_create. 1392 * Returns: 1393 * BCM_E_XXX 1394 */ 1395 STATIC int 1396 bcm_hx5_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id) 1397 { 1398 bcm_pstats_session_element_t element; 1399 pstats_session_t *cur_session = NULL; 1400 int i, need_hw_clear = 1; 1401 1402 LOG_INFO(BSL_LS_BCM_PSTATS, 1403 (BSL_META_U(unit, "pstats_session_data_clear unit %d session_id %d\n"), 1404 unit, session_id)); 1405 1406 cur_session = _bcm_hx5_pstats_session_get(unit, session_id); 1407 if (NULL == cur_session) { 1408 LOG_INFO(BSL_LS_BCM_PSTATS, 1409 (BSL_META_U(unit, "pstats_session_data_clear: " 1410 "session_id %d is not found\n"), session_id)); 1411 return BCM_E_NOT_FOUND; 1412 } 1413 1414 /* clear HW use count buffer */ 1415 if ((PSTATS_CTRL(unit).stat_mode == 1) && 1416 (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1)) { 1417 /* HW clear on read is enabled, no need do hw clear */ 1418 need_hw_clear = 0; 1419 } 1420 1421 if (need_hw_clear == 1) { 1422 for (i = 0; i < cur_session->element_array_count; i++) { 1423 element = cur_session->element_array[i]; 1424 BCM_IF_ERROR_RETURN( 1425 _bcm_hx5_pstats_session_data_hw_clear(unit, element)); 1426 } 1427 } 1428 1429 /* clear SW use count buffer */ 1430 sal_memset(cur_session->data_array, 0, 1431 cur_session->element_array_count * sizeof(bcm_pstats_data_t)); 1432 1433 return BCM_E_NONE; 1434 } 1435 1436 /* 1437 * Function: 1438 * bcm_hx5_pstats_session_traverse 1439 * Purpose: 1440 * Traverse through the pstats sessions and run callback at each 1441 * session. 1442 * Parameters: 1443 * unit - (IN) StrataSwitch unit number. 1444 * cb - (IN) bcm_pstats_session_traverse_cb. 1445 * user_data - (IN) User data to be passed to callback function. 1446 * Returns: 1447 * BCM_E_XXX 1448 */ 1449 STATIC int 1450 bcm_hx5_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb, 1451 void *user_data) 1452 { 1453 bcm_pstats_session_element_t *element_array; 1454 bcm_pstats_session_id_t session_id; 1455 pstats_session_t *cur_session = NULL; 1456 int array_count; 1457 int rv = BCM_E_NONE; 1458 1459 LOG_INFO(BSL_LS_BCM_PSTATS, 1460 (BSL_META_U(unit, "pstats_session_travers unit %d\n"), unit)); 1461 1462 element_array = (bcm_pstats_session_element_t *) 1463 sal_alloc(HX5_MAX_ELEMENT_COUNT * sizeof(bcm_pstats_session_element_t), 1464 "pstats traverse"); 1465 cur_session = PSTATS_CTRL(unit).first_session; 1466 while (NULL != cur_session) { 1467 session_id = cur_session->session_id; 1468 array_count = cur_session->element_array_count; 1469 sal_memcpy(element_array, cur_session->element_array, 1470 array_count * sizeof(bcm_pstats_session_element_t)); 1471 1472 cur_session = cur_session->next_session; 1473 1474 rv = cb(unit, session_id, array_count, element_array, user_data); 1475 #ifdef BCM_CB_ABORT_ON_ERR 1476 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 1477 if (NULL != element_array) { 1478 sal_free(element_array); 1479 } 1480 return rv; 1481 } 1482 #else 1483 /* 1484 * If CB_ABORT_ON_ERR is not defined don't return error 1485 * and continue. 1486 */ 1487 rv = BCM_E_NONE; 1488 #endif 1489 } 1490 1491 if (NULL != element_array) { 1492 sal_free(element_array); 1493 } 1494 return rv; 1495 } 1496 #else /* INCLUDE_PSTATS && BCM_TRIDENT3_SUPPORT */ 1497 int bcm_esw_trident3_pstats_not_empty; 1498 #endif /* INCLUDE_PSTATS && BCM_TRIDENT3_SUPPORT */