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