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

preemption_cnt.c (11982B)


      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 #include <soc/drv.h>
      8 #include <bcm/error.h>
      9 #include <bcm/types.h>
     10 #include <bcm/port.h>
     11 #include <bcm_int/esw/preemption_cnt.h>
     12 
     13 #if defined(BCM_GREYHOUND2_SUPPORT)
     14 /* for ingress table ING_RX_COUNTERm :
     15  * entry 0~127 is for non-preemptable, entry 128~255 is for preemptable packet
     16  * so the number of entries is half of table
     17  */
     18 #define IGR_COUNTER_ENTRY_NUM (soc_mem_index_count(unit, ING_RX_COUNTERm) >> 1)
     19 #define EGR_COUNTER_ENTRY_NUM (soc_mem_index_count(unit, EGR_MFRAME_COUNTERm))
     20 
     21 /* sw database for ingress counter mode (packet or byte mode)
     22  * (need not sw database for egress, because always packet mode)
     23  */
     24 STATIC uint32 *igr_counter_mode_non_preempt[SOC_MAX_NUM_DEVICES];
     25 STATIC uint32 *igr_counter_mode_preempt[SOC_MAX_NUM_DEVICES];
     26 
     27 STATIC int
     28 bcmi_gh2_preemption_counter_set(int unit, bcm_port_t local_port,
     29                                 bcm_port_stat_t stat, uint64 val)
     30 {
     31     int mode = 1;
     32 
     33     if(NULL == igr_counter_mode_non_preempt[unit] ||
     34        NULL == igr_counter_mode_preempt[unit]) {
     35        return BCM_E_INIT;
     36     }
     37 
     38     /* check local_port valid */
     39     switch (stat) {
     40         case bcmPortStatIngressPackets:
     41         case bcmPortStatIngressBytes:
     42         case bcmPortStatIngressPreemptPackets:
     43         case bcmPortStatIngressPreemptBytes:
     44             if (local_port < 0 || local_port >= IGR_COUNTER_ENTRY_NUM) {
     45                 return BCM_E_PARAM;
     46             }
     47             break;
     48         case bcmPortStatEgressPreemptPackets:
     49         case bcmPortStatEgressPackets:
     50         case bcmPortStatEgressBytes:
     51         case bcmPortStatEgressPreemptBytes:
     52             if (local_port < 0 || local_port >= EGR_COUNTER_ENTRY_NUM) {
     53                 return BCM_E_PARAM;
     54             }
     55             break;
     56     }
     57 
     58     /* set counter */
     59     switch (stat) {
     60         case bcmPortStatIngressPackets:
     61         case bcmPortStatIngressBytes:
     62             BCM_IF_ERROR_RETURN(
     63                 soc_counter_set(
     64                     unit, local_port,
     65                     SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT,
     66                     0, val));
     67             break;
     68         case bcmPortStatIngressPreemptPackets:
     69         case bcmPortStatIngressPreemptBytes:
     70             BCM_IF_ERROR_RETURN(
     71                 soc_counter_set(
     72                     unit, local_port,
     73                     SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT,
     74                     0, val));
     75             break;
     76         case bcmPortStatEgressPreemptPackets:
     77             BCM_IF_ERROR_RETURN(
     78                 soc_counter_set(
     79                     unit, local_port,
     80                     SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT,
     81                     0, val));
     82             break;
     83         case bcmPortStatEgressPackets:
     84         case bcmPortStatEgressBytes:
     85         case bcmPortStatEgressPreemptBytes:
     86             /* egress: only support preemptable packet mode in GH2 */
     87             return BCM_E_UNAVAIL;
     88     }
     89 
     90     /* update counter mode */
     91     switch (stat) {
     92         case bcmPortStatIngressPackets:
     93             mode = 0;
     94             /* fall through */
     95         case bcmPortStatIngressBytes:
     96             BCM_IF_ERROR_RETURN(
     97                 soc_mem_field32_modify(
     98                     unit, ING_RX_COUNTERm,
     99                     local_port,
    100                     COUNT_BYTEf, mode));
    101             BCM_IF_ERROR_RETURN(
    102                 soc_mem_field32_modify(
    103                     unit, ING_RX_COUNTERm,
    104                     IGR_COUNTER_ENTRY_NUM + local_port,
    105                     COUNT_BYTEf, mode));
    106             igr_counter_mode_non_preempt[unit][local_port] = mode;
    107             igr_counter_mode_preempt[unit][local_port] = mode;
    108             break;
    109         case bcmPortStatIngressPreemptPackets:
    110             mode = 0;
    111             /* fall through */
    112         case bcmPortStatIngressPreemptBytes:
    113             BCM_IF_ERROR_RETURN(
    114                 soc_mem_field32_modify(
    115                     unit, ING_RX_COUNTERm,
    116                     IGR_COUNTER_ENTRY_NUM + local_port,
    117                     COUNT_BYTEf, mode));
    118             igr_counter_mode_preempt[unit][local_port] = mode;
    119             break;
    120         default:
    121             /* need not update coutner mode for egress in GH2
    122              *(because always packet mode)
    123              */
    124             break;
    125     }
    126     return BCM_E_NONE;
    127 }
    128 
    129 STATIC int
    130 bcmi_gh2_preemption_counter_get(int unit, int sync_mode, bcm_port_t local_port,
    131                                 bcm_port_stat_t stat, uint64 *val)
    132 {
    133     uint64 local_val;
    134 
    135     if (NULL == val) {
    136         return BCM_E_PARAM;
    137     }
    138     if(NULL == igr_counter_mode_non_preempt[unit] ||
    139        NULL == igr_counter_mode_preempt[unit]) {
    140        return BCM_E_INIT;
    141     }
    142 
    143     /* check local_port valid */
    144     switch (stat) {
    145         case bcmPortStatIngressPackets:
    146         case bcmPortStatIngressBytes:
    147         case bcmPortStatIngressPreemptPackets:
    148         case bcmPortStatIngressPreemptBytes:
    149             if (local_port < 0 || local_port >= IGR_COUNTER_ENTRY_NUM) {
    150                 return BCM_E_PARAM;
    151             }
    152             break;
    153         case bcmPortStatEgressPreemptPackets:
    154         case bcmPortStatEgressPackets:
    155         case bcmPortStatEgressBytes:
    156         case bcmPortStatEgressPreemptBytes:
    157             if (local_port < 0 || local_port >= EGR_COUNTER_ENTRY_NUM) {
    158                 return BCM_E_PARAM;
    159             }
    160             break;
    161     }
    162 
    163     /* check counter mode first */
    164     switch (stat) {
    165         case bcmPortStatIngressPackets:
    166             if (0 != igr_counter_mode_non_preempt[unit][local_port]) {
    167                 return BCM_E_PARAM;
    168             }
    169             if (0 != igr_counter_mode_preempt[unit][local_port]) {
    170                 return BCM_E_PARAM;
    171             }
    172             break;
    173         case bcmPortStatIngressBytes:
    174             if (1 != igr_counter_mode_non_preempt[unit][local_port]) {
    175                 return BCM_E_PARAM;
    176             }
    177             if (1 != igr_counter_mode_preempt[unit][local_port]) {
    178                 return BCM_E_PARAM;
    179             }
    180             break;
    181         case bcmPortStatIngressPreemptPackets:
    182             if (0 != igr_counter_mode_preempt[unit][local_port]) {
    183                 return BCM_E_PARAM;
    184             }
    185             break;
    186         case bcmPortStatIngressPreemptBytes:
    187             if (1 != igr_counter_mode_preempt[unit][local_port]) {
    188                 return BCM_E_PARAM;
    189             }
    190             break;
    191         case bcmPortStatEgressPreemptPackets:
    192             break;
    193         case bcmPortStatEgressPackets:
    194         case bcmPortStatEgressBytes:
    195         case bcmPortStatEgressPreemptBytes:
    196             /* egress: only support preemptable packet mode in GH2 */
    197             return BCM_E_UNAVAIL;
    198     }
    199 
    200     /* get counter */
    201     COMPILER_64_ZERO(*val);
    202     switch (stat) {
    203         case bcmPortStatIngressPackets:
    204         case bcmPortStatIngressBytes:
    205             if (1 == sync_mode) {
    206                 BCM_IF_ERROR_RETURN(
    207                     soc_counter_sync_get(
    208                         unit, local_port,
    209                         SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT,
    210                         0, &local_val));
    211             } else {
    212                 BCM_IF_ERROR_RETURN(
    213                     soc_counter_get(
    214                         unit, local_port,
    215                         SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT,
    216                         0, &local_val));
    217             }
    218             COMPILER_64_ADD_64(*val, local_val);
    219             /* fall through */
    220         case bcmPortStatIngressPreemptPackets:
    221         case bcmPortStatIngressPreemptBytes:
    222             if (1 == sync_mode) {
    223                 BCM_IF_ERROR_RETURN(
    224                     soc_counter_sync_get(
    225                         unit, local_port,
    226                         SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT,
    227                         0, &local_val));
    228             } else {
    229                 BCM_IF_ERROR_RETURN(
    230                     soc_counter_get(
    231                         unit, local_port,
    232                         SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT,
    233                         0, &local_val));
    234             }
    235             COMPILER_64_ADD_64(*val, local_val);
    236             break;
    237         case bcmPortStatEgressPreemptPackets:
    238             if (1 == sync_mode) {
    239                 BCM_IF_ERROR_RETURN(
    240                     soc_counter_sync_get(
    241                         unit, local_port,
    242                         SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT,
    243                         0, &local_val));
    244             } else {
    245                 BCM_IF_ERROR_RETURN(
    246                     soc_counter_get(
    247                         unit, local_port,
    248                         SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT,
    249                         0, &local_val));
    250             }
    251             COMPILER_64_ADD_64(*val, local_val);
    252             break;
    253         default:
    254             return BCM_E_INTERNAL; /* should not enter here */
    255     }
    256 
    257     return BCM_E_NONE;
    258 }
    259 
    260 STATIC int
    261 bcmi_gh2_preemption_counter_clean(int unit)
    262 {
    263     if(NULL != igr_counter_mode_non_preempt[unit]) {
    264         sal_free(igr_counter_mode_non_preempt[unit]);
    265         igr_counter_mode_non_preempt[unit] = NULL;
    266     }
    267     if(NULL != igr_counter_mode_preempt[unit]) {
    268         sal_free(igr_counter_mode_preempt[unit]);
    269         igr_counter_mode_preempt[unit] = NULL;
    270     }
    271     return BCM_E_NONE;
    272 }
    273 
    274 STATIC int
    275 bcmi_gh2_preemption_counter_init(int unit)
    276 {
    277     int i;
    278     uint32 **counter_mode[2];
    279 
    280     /* prepare sw database for ingress counter mode
    281      * entry 0~127 for non-preempt, 128~255 for preempt
    282      */
    283     counter_mode[0] = &(igr_counter_mode_non_preempt[unit]);
    284     counter_mode[1] = &(igr_counter_mode_preempt[unit]);
    285 
    286     if(NULL != *(counter_mode[0]) || NULL != *(counter_mode[1])) {
    287         bcmi_gh2_preemption_counter_clean(unit);
    288     }
    289 
    290     for (i = 0; i < 2; i++) {
    291         uint8 *dma_buffer = NULL;
    292         int alloc_size, j, entry_byte, rv;
    293 
    294         /* alloc sw database */
    295         alloc_size = IGR_COUNTER_ENTRY_NUM * sizeof(uint32);
    296         *(counter_mode[i]) = sal_alloc(alloc_size, "igr_counter_mode");
    297         if (NULL == *(counter_mode[i])) {
    298             bcmi_gh2_preemption_counter_clean(unit);
    299             return BCM_E_MEMORY;
    300         }
    301 
    302         /* sync sw database with hw at initial time */
    303         entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, ING_RX_COUNTERm));
    304         alloc_size = IGR_COUNTER_ENTRY_NUM * entry_byte;
    305         dma_buffer = soc_cm_salloc(unit, alloc_size, "dma_buffer");
    306         if (NULL == dma_buffer) {
    307             bcmi_gh2_preemption_counter_clean(unit);
    308             return BCM_E_MEMORY;
    309         }
    310         rv = soc_mem_read_range(unit, ING_RX_COUNTERm, MEM_BLOCK_ANY,
    311                                 (IGR_COUNTER_ENTRY_NUM * i),
    312                                 (IGR_COUNTER_ENTRY_NUM * (i+1)) -1,
    313                                 dma_buffer);
    314         if (SOC_FAILURE(rv)) {
    315             bcmi_gh2_preemption_counter_clean(unit);
    316             soc_cm_sfree(unit, dma_buffer);
    317             return BCM_E_MEMORY;
    318         }
    319         for (j = 0; j < IGR_COUNTER_ENTRY_NUM; j++) {
    320             uint32 mode;
    321 
    322             mode = soc_mem_field32_get(unit, ING_RX_COUNTERm,
    323                                        &dma_buffer[j * entry_byte],
    324                                        COUNT_BYTEf);
    325             (*(counter_mode[i]))[j] = mode;
    326         }
    327         soc_cm_sfree(unit, dma_buffer);
    328     }
    329 
    330     return BCM_E_NONE;
    331 }
    332 
    333 int
    334 bcmi_gh2_preemption_counter_dev_func_init(
    335     bcmi_preemption_counte_func_t* dev_func)
    336 {
    337     dev_func->preemption_counter_init = bcmi_gh2_preemption_counter_init;
    338     dev_func->preemption_counter_clean = bcmi_gh2_preemption_counter_clean;
    339     dev_func->preemption_counter_get = bcmi_gh2_preemption_counter_get;
    340     dev_func->preemption_counter_set = bcmi_gh2_preemption_counter_set;
    341     return BCM_E_NONE;
    342 }
    343 #endif /* BCM_GREYHOUND2_SUPPORT */