pstats.c (22388B)
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 * Utility routines for Pktstats 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 #include <sal/core/sync.h> 16 #include <sal/core/time.h> 17 18 #include <soc/defs.h> 19 #include <soc/error.h> 20 #include <soc/debug.h> 21 #include <soc/drv.h> 22 #include <soc/mem.h> 23 24 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 25 #include <soc/helix5.h> 26 #include <soc/trident3.h> 27 #include <soc/tomahawk.h> 28 #include <soc/tomahawk2.h> 29 #include <soc/pstats.h> 30 #ifdef BCM_TOMAHAWK3_SUPPORT 31 #include <soc/tomahawk3.h> 32 #endif 33 34 static sbusdma_desc_handle_t *pstats_tbl_handles[SOC_MAX_NUM_DEVICES] = {NULL}; 35 static soc_pstats_tbl_ctrl_t **pstats_tbl_ctrl[SOC_MAX_NUM_DEVICES] = {NULL}; 36 37 static void 38 soc_sbusdma_pstats_cb(int unit, int status, sbusdma_desc_handle_t handle, void *data) 39 { 40 soc_control_t *soc = SOC_CONTROL(unit); 41 soc_pstats_tbl_desc_t *tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 42 soc_pstats_tbl_ctrl_t *tbl_ctrl = pstats_tbl_ctrl[unit][PTR_TO_INT(data)]; 43 44 if (status != SOC_E_NONE) { 45 LOG_ERROR(BSL_LS_SOC_COMMON, 46 (BSL_META_U(unit, 47 "pstats sbusdma failed: blk: %d, index: %d, entries: %d, mode: %d.\n"), 48 tbl_ctrl->blk, tbl_ctrl->tindex, tbl_ctrl->entries, soc->pstats_mode)); 49 50 if (status == SOC_E_TIMEOUT) { 51 #ifdef BCM_TRIDENT3_SUPPORT 52 /* Lockup recovery for MOR */ 53 if (SOC_IS_TRIDENT3X(unit) && tbl_desc[tbl_ctrl->tindex].mor_dma) { 54 soc_trident3_mmu_splitter_reset(unit); 55 } 56 #endif 57 #ifdef BCM_TOMAHAWK2_SUPPORT 58 /* Lockup recovery for MOR */ 59 if (SOC_IS_TOMAHAWK2(unit) && tbl_desc[tbl_ctrl->tindex].mor_dma) { 60 soc_tomahawk2_mmu_splitter_reset(unit); 61 } 62 #endif 63 #ifdef BCM_TOMAHAWK3_SUPPORT 64 if (SOC_IS_TOMAHAWK3(unit) && tbl_desc[tbl_ctrl->tindex].mor_dma) { 65 soc_tomahawk3_mmu_splitter_reset(unit); 66 } 67 #endif 68 } 69 } 70 71 if (soc->pstats_mode == PSTATS_MODE_PKT_SYNC) { 72 sal_sem_give(tbl_ctrl->dma_done); 73 } 74 } 75 76 static void 77 soc_sbusdma_pstats_pc(int unit, sbusdma_desc_handle_t handle, void *data) 78 { 79 #ifdef BCM_TRIDENT3_SUPPORT 80 soc_control_t *soc = SOC_CONTROL(unit); 81 soc_pstats_tbl_desc_t *tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 82 soc_pstats_tbl_ctrl_t *tbl_ctrl = pstats_tbl_ctrl[unit][PTR_TO_INT(data)]; 83 84 LOG_VERBOSE(BSL_LS_SOC_COMMON, 85 (BSL_META_U(unit, 86 "pstats sbusdma preconfig: blk: %d, index: %d, entries: %d, mode: %d.\n"), 87 tbl_ctrl->blk, tbl_ctrl->tindex, tbl_ctrl->entries, soc->pstats_mode)); 88 89 if (SOC_IS_TRIDENT3X(unit) && tbl_desc[tbl_ctrl->tindex].mor_dma) { 90 soc_trident3_mmu_pstats_mor_enable(unit); 91 } 92 #endif 93 } 94 95 static int 96 soc_pstats_sbusdma_desc_setup(int unit) 97 { 98 soc_control_t *soc = SOC_CONTROL(unit); 99 soc_pstats_tbl_desc_t *tbl_desc; 100 soc_pstats_tbl_ctrl_t *tbl_ctrl; 101 uint8 *buff = soc->pstats_tbl_buf; 102 soc_sbusdma_desc_ctrl_t ctrl = {0}; 103 soc_sbusdma_desc_cfg_t *cfg; 104 uint8 at; 105 uint32 size; 106 int ti, mi, i; 107 int rv; 108 109 if (!soc->pstats_tbl_desc || 110 !soc->pstats_tbl_desc_count || 111 !pstats_tbl_handles[unit]) { 112 return SOC_E_INIT; 113 } 114 115 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 116 117 pstats_tbl_ctrl[unit] = sal_alloc(soc->pstats_tbl_desc_count * 118 sizeof(soc_pstats_tbl_ctrl_t *), 119 "pstats_tbl_ctrl_p"); 120 if (pstats_tbl_ctrl[unit] == NULL) { 121 return SOC_E_MEMORY; 122 } 123 124 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 125 mi = 0; 126 while (tbl_desc[ti].desc[mi].mem != INVALIDm) { 127 mi++; 128 } 129 if (!mi) { 130 continue; 131 } 132 133 cfg = sal_alloc(mi * sizeof(soc_sbusdma_desc_cfg_t), 134 "pstats_sbusdma_desc_cfg"); 135 if (cfg == NULL) { 136 return SOC_E_MEMORY; 137 } 138 sal_memset(cfg, 0, mi * sizeof(soc_sbusdma_desc_cfg_t)); 139 140 ctrl.flags = SOC_SBUSDMA_CFG_COUNTER_IS_MEM | SOC_SBUSDMA_CFG_USE_FLAGS; 141 if (tbl_desc[ti].mor_dma) { 142 if (soc->pstats_flags & (_TD3_MMU_PSTATS_MOR_EN | _TH2_MMU_PSTATS_MOR_EN | _HX5_MMU_PSTATS_MOR_EN)) { 143 ctrl.flags |= SOC_SBUSDMA_CFG_MOR; 144 } 145 ctrl.pc = soc_sbusdma_pstats_pc; 146 ctrl.pc_data = INT_TO_PTR(ti); 147 } else { 148 ctrl.pc = NULL; 149 ctrl.pc_data = NULL; 150 } 151 ctrl.cfg_count = mi; 152 ctrl.buff = buff; 153 ctrl.cb = soc_sbusdma_pstats_cb; 154 ctrl.data = INT_TO_PTR(ti); 155 #define PSTATS_TBLS "PSTATS TBLS" 156 sal_strncpy(ctrl.name, PSTATS_TBLS, sizeof(PSTATS_TBLS)); 157 158 tbl_ctrl = sal_alloc(sizeof(soc_pstats_tbl_ctrl_t), "pstats_tbl_ctrl"); 159 if (tbl_ctrl == NULL) { 160 sal_free(cfg); 161 return SOC_E_MEMORY; 162 } 163 tbl_ctrl->blk = tbl_desc[ti].blk; 164 tbl_ctrl->tindex = ti; 165 tbl_ctrl->entries = mi; 166 tbl_ctrl->buff = buff; 167 tbl_ctrl->size = 0; 168 tbl_ctrl->flags = ctrl.flags; 169 pstats_tbl_ctrl[unit][ti] = tbl_ctrl; 170 171 for (i = 0; i < mi; i++) { 172 cfg[i].flags = ctrl.flags; 173 cfg[i].blk = SOC_MEM_BLOCK_ANY(unit, tbl_desc[ti].desc[i].mem); 174 cfg[i].addr = soc_mem_addr_get(unit, tbl_desc[ti].desc[i].mem, 175 0, cfg[i].blk, 0, &at); 176 cfg[i].acc_type = at; 177 cfg[i].blk = SOC_BLOCK2SCH(unit, cfg[i].blk); 178 cfg[i].width = tbl_desc[ti].desc[i].width; 179 cfg[i].count = tbl_desc[ti].desc[i].entries; 180 cfg[i].addr_shift = tbl_desc[ti].desc[i].shift; 181 size = cfg[i].count * cfg[i].width * 4; 182 buff += size; 183 tbl_ctrl->size += size; 184 if (tbl_desc[ti].desc[i].mor_dma && 185 (!soc_property_get(unit, "pstats_mor_disable", 0))) { 186 cfg[i].flags |= SOC_SBUSDMA_CFG_MOR; 187 } 188 } 189 190 rv = soc_sbusdma_desc_create(unit, &ctrl, cfg, 191 &pstats_tbl_handles[unit][ti]); 192 sal_free(cfg); 193 if (rv != SOC_E_NONE) { 194 LOG_ERROR(BSL_LS_SOC_COMMON, 195 (BSL_META_U(unit, 196 "pstats sbusdma desc creation error for table: %d\n"), 197 ti)); 198 return rv; 199 } 200 tbl_ctrl->dma_done = sal_sem_create("pstats_sbusdma_done", sal_sem_BINARY, 0); 201 if (tbl_ctrl->dma_done == NULL) { 202 return SOC_E_MEMORY; 203 } 204 LOG_VERBOSE(BSL_LS_SOC_COMMON, 205 (BSL_META_U(unit, 206 "pstats handle: %d for table: %d\n"), 207 pstats_tbl_handles[unit][ti], ti)); 208 } 209 210 return SOC_E_NONE; 211 } 212 213 static int 214 soc_pstats_sbudma_desc_free(int unit) 215 { 216 soc_control_t *soc = SOC_CONTROL(unit); 217 uint32 ti; 218 int rv; 219 220 if (!soc->pstats_tbl_desc || 221 !soc->pstats_tbl_desc_count || 222 !pstats_tbl_handles[unit]) { 223 return SOC_E_INIT; 224 } 225 226 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 227 if (pstats_tbl_handles[unit][ti]) { 228 do { 229 rv = soc_sbusdma_desc_delete(unit, pstats_tbl_handles[unit][ti]); 230 if (rv == SOC_E_BUSY) { 231 sal_usleep(SAL_BOOT_QUICKTURN ? 10000 : 10); 232 } 233 } while (rv == SOC_E_BUSY); 234 if (rv != SOC_E_NONE) { 235 LOG_ERROR(BSL_LS_SOC_COMMON, 236 (BSL_META_U(unit, 237 "pstats sbusdma desc delete error for table: %d\n"), 238 ti)); 239 return rv; 240 } 241 pstats_tbl_handles[unit][ti] = 0; 242 if (pstats_tbl_ctrl[unit][ti]) { 243 if (pstats_tbl_ctrl[unit][ti]->dma_done) { 244 sal_sem_destroy(pstats_tbl_ctrl[unit][ti]->dma_done); 245 pstats_tbl_ctrl[unit][ti]->dma_done = NULL; 246 } 247 sal_free(pstats_tbl_ctrl[unit][ti]); 248 pstats_tbl_ctrl[unit][ti] = NULL; 249 } 250 } 251 } 252 if (pstats_tbl_ctrl[unit]) { 253 sal_free(pstats_tbl_ctrl[unit]); 254 pstats_tbl_ctrl[unit] = NULL; 255 } 256 257 return SOC_E_NONE; 258 } 259 260 int 261 soc_pstats_init(int unit) 262 { 263 soc_control_t *soc = SOC_CONTROL(unit); 264 soc_pstats_tbl_desc_t *tbl_desc; 265 uint32 entries, width, size = 0; 266 int ti, mi; 267 int rv = SOC_E_INIT; 268 269 if (!soc->pstats_tbl_desc || !soc->pstats_tbl_desc_count) { 270 return rv; 271 } 272 273 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 274 275 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 276 mi = 0; 277 while (tbl_desc[ti].desc[mi].mem != INVALIDm) { 278 entries = tbl_desc[ti].desc[mi].entries; 279 width = tbl_desc[ti].desc[mi].width; 280 size += entries * width * 4; 281 mi++; 282 } 283 } 284 soc->pstats_tbl_size = size; 285 286 LOG_VERBOSE(BSL_LS_SOC_COMMON, 287 (BSL_META_U(unit, 288 "Total pstats tbls: %d, Total size: %d\n"), 289 soc->pstats_tbl_desc_count, size)); 290 291 if (pstats_tbl_handles[unit] == NULL) { 292 pstats_tbl_handles[unit] = sal_alloc(soc->pstats_tbl_desc_count * 293 sizeof(sbusdma_desc_handle_t), 294 "pstats_tbl_handles"); 295 if (pstats_tbl_handles[unit] == NULL) { 296 goto error; 297 } 298 } 299 sal_memset(pstats_tbl_handles[unit], 0, 300 soc->pstats_tbl_desc_count * sizeof(sbusdma_desc_handle_t)); 301 302 if (soc->pstats_tbl_buf == NULL) { 303 soc->pstats_tbl_buf = soc_cm_salloc(unit, size, "pstats_tbl_buf"); 304 if (soc->pstats_tbl_buf == NULL) { 305 goto error; 306 } 307 } 308 sal_memset(soc->pstats_tbl_buf, 0, size); 309 310 if (soc->pstatsMutex == NULL) { 311 soc->pstatsMutex = sal_mutex_create("pstats"); 312 if (soc->pstatsMutex == NULL) { 313 goto error; 314 } 315 } 316 317 rv = soc_pstats_sbusdma_desc_setup(unit); 318 if (rv != SOC_E_NONE) { 319 goto error; 320 } 321 322 return SOC_E_NONE; 323 324 error: 325 if (soc->pstatsMutex) { 326 sal_mutex_destroy(soc->pstatsMutex); 327 soc->pstatsMutex = NULL; 328 } 329 330 if (soc->pstats_tbl_buf) { 331 soc_cm_sfree(unit, soc->pstats_tbl_buf); 332 soc->pstats_tbl_buf = NULL; 333 } 334 335 if (pstats_tbl_handles[unit]) { 336 sal_free(pstats_tbl_handles[unit]); 337 pstats_tbl_handles[unit] = NULL; 338 } 339 340 return rv; 341 } 342 343 int 344 soc_pstats_deinit(int unit) 345 { 346 soc_control_t *soc = SOC_CONTROL(unit); 347 int rv; 348 349 rv = soc_pstats_sbudma_desc_free(unit); 350 if (rv != SOC_E_NONE) { 351 return rv; 352 } 353 354 if (pstats_tbl_handles[unit]) { 355 sal_free(pstats_tbl_handles[unit]); 356 pstats_tbl_handles[unit] = NULL; 357 } 358 359 if (soc->pstats_tbl_buf) { 360 soc_cm_sfree(unit, soc->pstats_tbl_buf); 361 soc->pstats_tbl_buf = NULL; 362 } 363 364 if (soc->pstatsMutex) { 365 sal_mutex_destroy(soc->pstatsMutex); 366 soc->pstatsMutex = NULL; 367 } 368 369 return SOC_E_NONE; 370 } 371 372 int 373 soc_pstats_tbl_pattern_get(int unit, soc_pstats_tbl_desc_t *tdesc, 374 soc_mem_t *mem, uint32 *index, uint32 *count) 375 { 376 soc_control_t *soc = SOC_CONTROL(unit); 377 soc_pstats_tbl_desc_t *tbl_desc; 378 soc_pstats_tbl_ctrl_t *tbl_ctrl; 379 uint32 ti; 380 381 if (!soc->pstats_tbl_desc || 382 !soc->pstats_tbl_desc_count || 383 !pstats_tbl_ctrl[unit]) { 384 return SOC_E_INIT; 385 } 386 387 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 388 389 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 390 if (!pstats_tbl_ctrl[unit][ti]) { 391 continue; 392 } 393 tbl_ctrl = pstats_tbl_ctrl[unit][ti]; 394 if (&tbl_desc[tbl_ctrl->tindex] == tdesc) { 395 break; 396 } 397 } 398 if (ti >= soc->pstats_tbl_desc_count || !mem || !index || !count) { 399 return SOC_E_PARAM; 400 } 401 402 SOC_PSTATS_LOCK(unit); 403 404 if (tdesc->pattern_set) { 405 *mem = tdesc->mem; 406 *index = tdesc->index; 407 *count = tdesc->count; 408 } else { 409 *mem = MEM_BLOCK_ANY; 410 *index = 0; 411 *count = tdesc->desc[0].entries; 412 } 413 414 SOC_PSTATS_UNLOCK(unit); 415 return SOC_E_NONE; 416 } 417 418 int 419 soc_pstats_tbl_pattern_set(int unit, soc_pstats_tbl_desc_t *tdesc, 420 soc_mem_t mem, uint32 index, uint32 count) 421 { 422 soc_control_t *soc = SOC_CONTROL(unit); 423 soc_pstats_tbl_desc_t *tbl_desc; 424 soc_pstats_tbl_ctrl_t *tbl_ctrl = NULL; 425 soc_sbusdma_desc_ctrl_t ctrl = {0}; 426 soc_sbusdma_desc_cfg_t *cfg; 427 uint8 at; 428 uint32 size = 0; 429 uint32 ti, mi, cnt, i, j; 430 int rv; 431 432 if (!soc->pstats_tbl_desc || 433 !soc->pstats_tbl_desc_count || 434 !pstats_tbl_ctrl[unit]) { 435 return SOC_E_INIT; 436 } 437 438 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 439 440 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 441 if (!pstats_tbl_ctrl[unit][ti]) { 442 continue; 443 } 444 tbl_ctrl = pstats_tbl_ctrl[unit][ti]; 445 if (&tbl_desc[tbl_ctrl->tindex] == tdesc) { 446 break; 447 } 448 } 449 if (ti >= soc->pstats_tbl_desc_count) { 450 return SOC_E_PARAM; 451 } 452 453 SOC_PSTATS_LOCK(unit); 454 455 mi = 0; 456 if (mem == MEM_BLOCK_ANY) { 457 while (tdesc->desc[mi].mem != INVALIDm) { 458 mi++; 459 } 460 if (!mi) { 461 return SOC_E_PARAM; 462 } 463 cnt = mi; 464 } else { 465 while (tdesc->desc[mi].mem != INVALIDm) { 466 if (tdesc->desc[mi].mem == mem) { 467 break; 468 } 469 mi++; 470 } 471 if (tdesc->desc[mi].mem == INVALIDm || 472 count == 0 || 473 (index + count) > tdesc->desc[mi].entries) { 474 return SOC_E_PARAM; 475 } 476 cnt = 1; 477 } 478 479 cfg = sal_alloc(cnt * sizeof(soc_sbusdma_desc_cfg_t), "pstats_sbusdma_desc_cfg"); 480 if (cfg == NULL) { 481 return SOC_E_MEMORY; 482 } 483 sal_memset(cfg, 0, cnt * sizeof(soc_sbusdma_desc_cfg_t)); 484 485 ctrl.flags = SOC_SBUSDMA_CFG_COUNTER_IS_MEM; 486 if (tdesc->mor_dma) { 487 if (soc->pstats_flags & (_TD3_MMU_PSTATS_MOR_EN | _TH2_MMU_PSTATS_MOR_EN | _HX5_MMU_PSTATS_MOR_EN)) { 488 ctrl.flags |= SOC_SBUSDMA_CFG_MOR; 489 } 490 ctrl.pc = soc_sbusdma_pstats_pc; 491 ctrl.pc_data = INT_TO_PTR(ti); 492 } 493 ctrl.cfg_count = cnt; 494 ctrl.buff = tbl_ctrl->buff; 495 ctrl.cb = soc_sbusdma_pstats_cb; 496 ctrl.data = INT_TO_PTR(ti); 497 498 for (i = 0; i < cnt; i++) { 499 j = mem == MEM_BLOCK_ANY ? i : mi; 500 cfg[i].blk = SOC_MEM_BLOCK_ANY(unit, tdesc->desc[j].mem); 501 cfg[i].addr = soc_mem_addr_get(unit, tdesc->desc[j].mem, 502 0, cfg[i].blk, index, &at); 503 cfg[i].acc_type = at; 504 cfg[i].blk = SOC_BLOCK2SCH(unit, cfg[i].blk); 505 cfg[i].width = tdesc->desc[j].width; 506 cfg[i].count = count; 507 cfg[i].addr_shift = tdesc->desc[j].shift; 508 size += cfg[i].count * cfg[i].width * 4; 509 } 510 511 if (pstats_tbl_handles[unit][ti]) { 512 i = 0; 513 do { 514 rv = soc_sbusdma_desc_delete(unit, pstats_tbl_handles[unit][ti]); 515 if (rv == SOC_E_BUSY) { 516 sal_usleep(SAL_BOOT_QUICKTURN ? 10000 : 10); 517 } 518 } while (rv == SOC_E_BUSY && i++ < 100); 519 if (rv != SOC_E_NONE) { 520 LOG_ERROR(BSL_LS_SOC_COMMON, 521 (BSL_META_U(unit, 522 "pstats sbusdma desc delete error for talble: %d\n"), 523 ti)); 524 sal_free(cfg); 525 SOC_PSTATS_UNLOCK(unit); 526 return rv; 527 } 528 } 529 530 rv = soc_sbusdma_desc_create(unit, &ctrl, cfg, 531 &pstats_tbl_handles[unit][ti]); 532 sal_free(cfg); 533 if (rv != SOC_E_NONE) { 534 LOG_ERROR(BSL_LS_SOC_COMMON, 535 (BSL_META_U(unit, 536 "pstats sbusdma desc creation error for table: %d\n"), 537 ti)); 538 SOC_PSTATS_UNLOCK(unit); 539 return rv; 540 } 541 542 tbl_ctrl->size = size; 543 tbl_ctrl->flags = ctrl.flags; 544 tdesc->pattern_set = 1; 545 tdesc->mem = mem; 546 tdesc->index = index; 547 tdesc->count = count; 548 549 SOC_PSTATS_UNLOCK(unit); 550 return SOC_E_NONE; 551 } 552 553 int 554 soc_pstats_sync(int unit) 555 { 556 soc_control_t *soc = SOC_CONTROL(unit); 557 soc_pstats_tbl_desc_t *tbl_desc; 558 soc_pstats_tbl_ctrl_t *tbl_ctrl; 559 sbusdma_desc_handle_t desc_handle; 560 soc_mem_t mem; 561 uint32 index; 562 uint32 count; 563 uint32 ti; 564 soc_timeout_t to; 565 sal_usecs_t dma_timeout = 1000000; 566 sal_usecs_t stime, etime; 567 int rv; 568 569 if (!soc->pstats_tbl_desc || 570 !soc->pstats_tbl_desc_count || 571 !pstats_tbl_ctrl[unit]) { 572 return SOC_E_INIT; 573 } 574 575 SOC_PSTATS_LOCK(unit); 576 577 if (soc->pstats_mode != PSTATS_MODE_PKT_BUFF && 578 soc->pstats_mode != PSTATS_MODE_PKT_SYNC) { 579 LOG_WARN(BSL_LS_SOC_COMMON, 580 (BSL_META_U(unit, 581 "pstats is not in packetized stats mode.\n"))); 582 SOC_PSTATS_UNLOCK(unit); 583 return SOC_E_INTERNAL; 584 } 585 586 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 587 588 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 589 tbl_ctrl = pstats_tbl_ctrl[unit][ti]; 590 if (!tbl_desc[ti].mor_dma || 591 !!(soc->pstats_flags & (_TD3_MMU_PSTATS_MOR_EN | _TH2_MMU_PSTATS_MOR_EN | _HX5_MMU_PSTATS_MOR_EN)) == 592 !!(tbl_ctrl->flags & SOC_SBUSDMA_CFG_MOR)) { 593 continue; 594 } 595 if ((rv = soc_pstats_tbl_pattern_get(unit, &tbl_desc[ti], &mem, &index, &count)) || 596 (rv = soc_pstats_tbl_pattern_set(unit, &tbl_desc[ti], mem, index, count))) { 597 SOC_PSTATS_UNLOCK(unit); 598 return rv; 599 } 600 } 601 602 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 603 LOG_VERBOSE(BSL_LS_SOC_COMMON, 604 (BSL_META_U(unit, "pstats tbl %d\n"), ti)); 605 tbl_ctrl = pstats_tbl_ctrl[unit][ti]; 606 desc_handle = pstats_tbl_handles[unit][ti]; 607 if (tbl_ctrl && desc_handle) { 608 soc_timeout_init(&to, 2 * dma_timeout, 0); 609 do { 610 stime = sal_time_usecs(); 611 rv = soc_sbusdma_desc_start(unit, desc_handle); 612 if (rv == SOC_E_NONE) { 613 break; 614 } else if (rv == SOC_E_BUSY) { 615 sal_usleep(SAL_BOOT_QUICKTURN ? 10000 : 10); 616 } else { 617 SOC_PSTATS_UNLOCK(unit); 618 return SOC_E_INTERNAL; 619 } 620 if (soc_timeout_check(&to)) { 621 LOG_WARN(BSL_LS_SOC_COMMON, 622 (BSL_META_U(unit, 623 "pstats start dma timeout\n"))); 624 SOC_PSTATS_UNLOCK(unit); 625 return SOC_E_TIMEOUT; 626 } 627 } while (rv == SOC_E_BUSY); 628 if (soc->pstats_mode == PSTATS_MODE_PKT_SYNC) { 629 rv = sal_sem_take(tbl_ctrl->dma_done, dma_timeout); 630 if (rv) { 631 LOG_WARN(BSL_LS_SOC_COMMON, 632 (BSL_META_U(unit, 633 "pstats read operation timeout\n"))); 634 SOC_PSTATS_UNLOCK(unit); 635 return SOC_E_TIMEOUT; 636 } 637 } 638 etime = sal_time_usecs(); 639 LOG_INFO(BSL_LS_SOC_COMMON, 640 (BSL_META_U(unit, 641 "soc_pstats_sync: unit=%d tnum-%d mode(%s) done in %d usec\n"), 642 unit, ti, 643 tbl_desc[ti].mor_dma && (soc->pstats_flags & (_TD3_MMU_PSTATS_MOR_EN | _TH2_MMU_PSTATS_MOR_EN | _HX5_MMU_PSTATS_MOR_EN)) ? "MOR" : "Non-MOR", 644 SAL_USECS_SUB(etime, stime))); 645 } 646 } 647 648 SOC_PSTATS_UNLOCK(unit); 649 return SOC_E_NONE; 650 } 651 652 int 653 soc_pstats_mem_get(int unit, soc_mem_t mem, uint8 *buf, int try_num) 654 { 655 soc_control_t *soc = SOC_CONTROL(unit); 656 soc_pstats_tbl_desc_t *tbl_desc; 657 soc_pstats_tbl_ctrl_t *tbl_ctrl = NULL; 658 soc_pstats_mem_desc_t *mem_desc; 659 soc_mem_t tmem; 660 uint32 index, count; 661 uint32 ti, ei; 662 uint32 off = 0, size = 0, try = 0; 663 int rv; 664 665 if (!soc->pstats_tbl_desc || 666 !soc->pstats_tbl_desc_count || 667 !pstats_tbl_ctrl[unit]) { 668 return SOC_E_INIT; 669 } 670 671 tbl_desc = (soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc; 672 673 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 674 if (!pstats_tbl_ctrl[unit][ti]) { 675 continue; 676 } 677 tbl_ctrl = pstats_tbl_ctrl[unit][ti]; 678 rv = soc_pstats_tbl_pattern_get(unit, &tbl_desc[ti], 679 &tmem, &index, &count); 680 if (rv != SOC_E_NONE) { 681 return rv; 682 } 683 off = 0; 684 size = 0; 685 for (ei = 0; ei < tbl_ctrl->entries; ei++) { 686 mem_desc = &tbl_desc[ti].desc[ei]; 687 size = mem_desc->width * 4 * 688 (tbl_desc[ti].pattern_set ? count : mem_desc->entries); 689 if (mem_desc->mem == mem) { 690 if (try == try_num) { 691 break; 692 } else { 693 try++; 694 } 695 } 696 off += size; 697 } 698 if (ei < tbl_ctrl->entries) { 699 if (tbl_desc[ti].pattern_set && tmem != MEM_BLOCK_ANY) { 700 if (tmem != mem) { 701 return SOC_E_PARAM; 702 } 703 off = 0; 704 } 705 break; 706 } 707 } 708 if (ti >= soc->pstats_tbl_desc_count || !buf) { 709 return SOC_E_PARAM; 710 } 711 712 SOC_PSTATS_LOCK(unit); 713 sal_memcpy(buf, tbl_ctrl->buff + off, size); 714 SOC_PSTATS_UNLOCK(unit); 715 return SOC_E_NONE; 716 } 717 #endif /* !BCM_TRIDENT3_SUPPORT !BCM_TOMAHAWK2_SUPPORT !BCM_TOMAHAWK3_SUPPORT*/ 718