openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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