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

policer.c (86761B)


      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 
      8 #include <shared/bsl.h>
      9 
     10 #include <soc/debug.h>
     11 #include <soc/drv.h>
     12 #include <soc/scache.h>
     13 #include <soc/mem.h>
     14 #include <bcm/error.h>
     15 #include <bcm/types.h>
     16 #include <bcm/policer.h>
     17 #include <bcm/field.h>
     18 #if defined(BCM_GREYHOUND2_SUPPORT)
     19 #include <bcm_int/esw/greyhound2.h>
     20 #include <bcm_int/esw/policer.h>
     21 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
     22 
     23 #define GH2_GLOBAL_METER_TCAM_SIZE (SOC_INFO(unit).global_meter_tcam_size)
     24 
     25 #define UNKNOWN_PKT                 (0x00)
     26 #define CONTROL_PKT                 (0x01)
     27 #define OAM_PKT                     (0x02)
     28 #define BFD_PKT                     (0x03)
     29 #define BPDU_PKT                    (0x04)
     30 #define ICNM_PKT                    (0x05)
     31 #define PKT_IS_1588                 (0x06)
     32 #define KNOWN_L2UC_PKT              (0x07)
     33 
     34 #define UNKNOWN_L2UC_PKT            (0x08)
     35 #define KNOWN_L2MC_PKT              (0x09)
     36 #define UNKNOWN_L2MC_PKT            (0x0a)
     37 #define L2BC_PKT                    (0x0b)
     38 #define KNOWN_L3UC_PKT              (0x0c)
     39 #define UNKNOWN_L3UC_PKT            (0x0d)
     40 #define KNOWN_IPMC_PKT              (0x0e)
     41 #define UNKNOWN_IPMC_PKT            (0x0f)
     42 
     43 #define KNOWN_MPLS_L2_PKT           (0x10)
     44 #define UNKNOWN_MPLS_PKT            (0x11)
     45 #define KNOWN_MPLS_L3_PKT           (0x12)
     46 #define KNOWN_MPLS_PKT              (0x13)
     47 #define KNOWN_MPLS_MULTICAST_PKT    (0x14)
     48 #define KNOWN_MIM_PKT               (0x15)
     49 #define UNKNOWN_MIM_PKT             (0x16)
     50 #define KNOWN_TRILL_PKT             (0x17)
     51 
     52 #define UNKNOWN_TRILL_PKT           (0x18)
     53 #define KNOWN_NIV_PKT               (0x19)
     54 #define UNKNOWN_NIV_PKT             (0x1a)
     55 #define KNOWN_L2GRE_PKT             (0x1b)
     56 #define KNOWN_VDL2_PKT              (0x1c)
     57 #define KNOWN_FCOE_PKT              (0x1d)
     58 #define UNKNOWN_FCOE_PKT            (0x1e)
     59 #define SAT_DN_SAMP_RX              (0x1f)
     60 #define FP_RESOLUTION_MAX           (0x20)  /* Max value */
     61 
     62 /* For those unsupported packets will be mapped to 0 (GH2_UNKNOWN_PKT_VAL) */
     63 #define GH2_UNKNOWN_PKT_VAL                 (0)
     64 
     65 #define GH2_CONTROL_PKT_VAL                 (1)
     66 #define GH2_OAM_PKT_VAL                     (18)
     67 #define GH2_BFD_PKT_VAL                     (GH2_UNKNOWN_PKT_VAL)
     68 #define GH2_BPDU_PKT_VAL                    (2)
     69 #define GH2_ICNM_PKT_VAL                    (GH2_UNKNOWN_PKT_VAL)
     70 #define GH2_PKT_IS_1588_VAL                 (19)
     71 #define GH2_KNOWN_L2UC_PKT_VAL              (4)
     72 
     73 #define GH2_UNKNOWN_L2UC_PKT_VAL            (5)
     74 #define GH2_KNOWN_L2MC_PKT_VAL              (8)
     75 #define GH2_UNKNOWN_L2MC_PKT_VAL            (9)
     76 #define GH2_L2BC_PKT_VAL                    (3)
     77 #define GH2_KNOWN_L3UC_PKT_VAL              (10)
     78 #define GH2_UNKNOWN_L3UC_PKT_VAL            (11)
     79 #define GH2_KNOWN_IPMC_PKT_VAL              (7)
     80 #define GH2_UNKNOWN_IPMC_PKT_VAL            (6)
     81 
     82 #define GH2_KNOWN_MPLS_L2_PKT_VAL           (14)
     83 #define GH2_UNKNOWN_MPLS_PKT_VAL            (15)
     84 #define GH2_KNOWN_MPLS_L3_PKT_VAL           (13)
     85 #define GH2_KNOWN_MPLS_PKT_VAL              (12)
     86 #define GH2_KNOWN_MPLS_MULTICAST_PKT_VAL    (GH2_UNKNOWN_PKT_VAL)
     87 #define GH2_KNOWN_MIM_PKT_VAL               (16)
     88 #define GH2_UNKNOWN_MIM_PKT_VAL             (17)
     89 #define GH2_KNOWN_TRILL_PKT_VAL             (GH2_UNKNOWN_PKT_VAL)
     90 
     91 #define GH2_UNKNOWN_TRILL_PKT_VAL           (GH2_UNKNOWN_PKT_VAL)
     92 #define GH2_KNOWN_NIV_PKT_VAL               (20)
     93 #define GH2_UNKNOWN_NIV_PKT_VAL             (21)
     94 #define GH2_KNOWN_L2GRE_PKT_VAL             (GH2_UNKNOWN_PKT_VAL)
     95 #define GH2_KNOWN_VDL2_PKT_VAL              (GH2_UNKNOWN_PKT_VAL)
     96 #define GH2_KNOWN_FCOE_PKT_VAL              (GH2_UNKNOWN_PKT_VAL)
     97 #define GH2_UNKNOWN_FCOE_PKT_VAL            (GH2_UNKNOWN_PKT_VAL)
     98 #define GH2_SAT_DN_SAMP_RX_VAL              (GH2_UNKNOWN_PKT_VAL)
     99 
    100 /*
    101  * Refer to FP_RESOLUTION in reg bcm53570_a0
    102  */
    103 STATIC const uint8 bcmi_gh2_global_meter_pkt_res[FP_RESOLUTION_MAX] =
    104 {
    105     GH2_UNKNOWN_PKT_VAL,
    106     GH2_CONTROL_PKT_VAL,
    107     GH2_OAM_PKT_VAL,
    108     GH2_BFD_PKT_VAL,
    109     GH2_BPDU_PKT_VAL,
    110     GH2_ICNM_PKT_VAL,
    111     GH2_PKT_IS_1588_VAL,
    112     GH2_KNOWN_L2UC_PKT_VAL,
    113 
    114     GH2_UNKNOWN_L2UC_PKT_VAL,
    115     GH2_KNOWN_L2MC_PKT_VAL,
    116     GH2_UNKNOWN_L2MC_PKT_VAL,
    117     GH2_L2BC_PKT_VAL,
    118     GH2_KNOWN_L3UC_PKT_VAL,
    119     GH2_UNKNOWN_L3UC_PKT_VAL,
    120     GH2_KNOWN_IPMC_PKT_VAL,
    121     GH2_UNKNOWN_IPMC_PKT_VAL,
    122 
    123     GH2_KNOWN_MPLS_L2_PKT_VAL,
    124     GH2_UNKNOWN_MPLS_PKT_VAL,
    125     GH2_KNOWN_MPLS_L3_PKT_VAL,
    126     GH2_KNOWN_MPLS_PKT_VAL,
    127     GH2_KNOWN_MPLS_MULTICAST_PKT_VAL,
    128     GH2_KNOWN_MIM_PKT_VAL,
    129     GH2_UNKNOWN_MIM_PKT_VAL,
    130     GH2_KNOWN_TRILL_PKT_VAL,
    131 
    132     GH2_UNKNOWN_TRILL_PKT_VAL,
    133     GH2_KNOWN_NIV_PKT_VAL,
    134     GH2_UNKNOWN_NIV_PKT_VAL,
    135     GH2_KNOWN_L2GRE_PKT_VAL,
    136     GH2_KNOWN_VDL2_PKT_VAL,
    137     GH2_KNOWN_FCOE_PKT_VAL,
    138     GH2_UNKNOWN_FCOE_PKT_VAL,
    139     GH2_SAT_DN_SAMP_RX_VAL
    140 };
    141 
    142 /* Parameter NULL error handling */
    143 #define GH2_POL_CHECK_NULL_PARAMETER(_u_, _parameter_)           \
    144     do {                                                         \
    145         if (NULL == (_parameter_)) {                             \
    146             LOG_ERROR(BSL_LS_BCM_POLICER,                        \
    147                       (BSL_META_U((_u_),                         \
    148                                   "Error: NULL parameter\n")));  \
    149             return BCM_E_PARAM;                                  \
    150         }                                                        \
    151     } while (0)
    152 
    153 /* Function Enter/Leave Tracing */
    154 #define GH2_POL_FUNCTION_TRACE(_u_, _str_)                                 \
    155     do {                                                                   \
    156         LOG_VERBOSE(BSL_LS_BCM_POLICER,                                    \
    157                   (BSL_META_U((_u_),                                       \
    158                                "%s: " _str_ "\n"), __FUNCTION__));         \
    159     } while (0)
    160 
    161 /* Function DEBUG Tracing */
    162 #define GH2_POL_FUNCTION_DEBUG(_u_, fmt, _args_)                           \
    163     do {                                                                   \
    164         LOG_DEBUG(BSL_LS_BCM_POLICER,                                      \
    165                   (BSL_META_U((_u_),                                       \
    166                               "%s: " fmt "\n"), __FUNCTION__, _args_));    \
    167     } while (0)
    168 
    169 /* Function ERROR Tracing */
    170 #define GH2_POL_FUNCTION_ERROR(_u_, fmt, _args_)                           \
    171     do {                                                                   \
    172         LOG_ERROR(BSL_LS_BCM_POLICER,                                      \
    173                   (BSL_META_U((_u_),                                       \
    174                               fmt "\n"), _args_));                         \
    175     } while (0)
    176 
    177 /* Check if bcm_policer_action_t is supported or not */
    178 STATIC int
    179 bcmi_gh2_action_supported(
    180     int unit,
    181     bcm_policer_action_t action)
    182 {
    183     bcm_error_t rv = BCM_E_UNAVAIL;
    184 
    185     switch (action) {
    186         case bcmPolicerActionGpDrop:
    187         case bcmPolicerActionYpDrop:
    188         case bcmPolicerActionRpDrop:
    189         case bcmPolicerActionGpEcnNew:
    190         case bcmPolicerActionYpEcnNew:
    191         case bcmPolicerActionRpEcnNew:
    192         case bcmPolicerActionGpDscpNew:
    193         case bcmPolicerActionYpDscpNew:
    194         case bcmPolicerActionRpDscpNew:
    195         case bcmPolicerActionGpPrioIntNew:
    196         case bcmPolicerActionYpPrioIntNew:
    197         case bcmPolicerActionRpPrioIntNew:
    198         case bcmPolicerActionGpCngNew:
    199         case bcmPolicerActionYpCngNew:
    200         case bcmPolicerActionRpCngNew:
    201         case bcmPolicerActionGpVlanPrioNew:
    202         case bcmPolicerActionYpVlanPrioNew:
    203         case bcmPolicerActionRpVlanPrioNew:
    204         case bcmPolicerActionGpIntCongestionNotificationNew:
    205         case bcmPolicerActionYpIntCongestionNotificationNew:
    206         case bcmPolicerActionRpIntCongestionNotificationNew:
    207         {
    208             /* Supported */
    209             rv = BCM_E_NONE;
    210             break;
    211         }
    212         default:
    213         {
    214             /* Not Supported */
    215             rv = BCM_E_UNAVAIL;
    216             break;
    217         }
    218     }
    219 
    220     return rv;
    221 }
    222 
    223 /* Check if bcm_policer_group_mode_type_t is supported or not */
    224 STATIC int
    225 bcmi_gh2_group_mode_type_supported(
    226     int unit,
    227     bcm_policer_group_mode_type_t group_mode_type)
    228 {
    229     /* GH2 doesn't support Cascade metering */
    230     if (group_mode_type != bcmPolicerGroupModeTypeNormal) {
    231         GH2_POL_FUNCTION_ERROR(unit,
    232             "Greyhound2 only support following bcm_policer_group_mode_type_t :"
    233             "bcmPolicerGroupModeTypeNormal(%d)",
    234             bcmPolicerGroupModeTypeNormal);
    235         return BCM_E_UNAVAIL;
    236     }
    237 
    238     return BCM_E_NONE;
    239 }
    240 
    241 /* Check if bcm_policer_group_mode_t is supported or not */
    242 STATIC int
    243 bcmi_gh2_group_mode_supported(
    244     int unit,
    245     bcm_policer_group_mode_t group_mode)
    246 {
    247     bcm_error_t rv = BCM_E_UNAVAIL;
    248 
    249     switch (group_mode) {
    250         case bcmPolicerGroupModeSingle:
    251         case bcmPolicerGroupModeTrafficType:
    252         case bcmPolicerGroupModeDlfAll:
    253         case bcmPolicerGroupModeTyped:
    254         case bcmPolicerGroupModeTypedAll:
    255         case bcmPolicerGroupModeSingleWithControl:
    256         case bcmPolicerGroupModeTrafficTypeWithControl:
    257         case bcmPolicerGroupModeDlfAllWithControl:
    258         case bcmPolicerGroupModeTypedWithControl:
    259         case bcmPolicerGroupModeTypedAllWithControl:
    260         case bcmPolicerGroupModeDot1P:
    261         case bcmPolicerGroupModeInnerDot1P:
    262         case bcmPolicerGroupModeIntPri:
    263         case bcmPolicerGroupModeShortIntPri:
    264         case bcmPolicerGroupModeDlfIntPri:
    265         case bcmPolicerGroupModeTypedIntPri:
    266         case bcmPolicerGroupModeDlfIntPriWithControl:
    267         case bcmPolicerGroupModeTypedIntPriWithControl:
    268         case bcmPolicerGroupModePreemptable:
    269         {
    270             /* Supported */
    271             rv = BCM_E_NONE;
    272             break;
    273         }
    274         default:
    275         {
    276             /* Not Supported */
    277             rv = BCM_E_UNAVAIL;
    278             break;
    279         }
    280     }
    281 
    282     return rv;
    283 }
    284 
    285 /* Check if bcm_policer_group_mode_attr_t is supported or not */
    286 STATIC int
    287 bcmi_gh2_group_mode_attr_supported(
    288     int unit,
    289     bcm_policer_group_mode_attr_t group_mode_attr)
    290 {
    291     bcm_error_t rv = BCM_E_UNAVAIL;
    292 
    293     switch (group_mode_attr) {
    294         case bcmPolicerGroupModeAttrFieldIngressColor:
    295         case bcmPolicerGroupModeAttrIntPri:
    296         case bcmPolicerGroupModeAttrVlan:
    297         case bcmPolicerGroupModeAttrOuterPri:
    298         case bcmPolicerGroupModeAttrInnerPri:
    299         case bcmPolicerGroupModeAttrPort:
    300         case bcmPolicerGroupModeAttrTosDscp:
    301         case bcmPolicerGroupModeAttrPktType:
    302         case bcmPolicerGroupModeAttrPreemptable:
    303         case bcmPolicerGroupModeAttrEtherType:
    304         case bcmPolicerGroupModeAttrOuterVlanCfi:
    305         case bcmPolicerGroupModeAttrInnerVlanCfi:
    306         {
    307             /* Supported */
    308             rv = BCM_E_NONE;
    309             break;
    310         }
    311         default:
    312         {
    313             /* Not Supported */
    314             rv = BCM_E_UNAVAIL;
    315             break;
    316         }
    317     }
    318     return rv;
    319 }
    320 
    321 /* Clear all meter tables */
    322 STATIC int
    323 bcmi_gh2_global_meter_mem_clear(int unit)
    324 {
    325     bcm_error_t rv = BCM_E_NONE;
    326     int i;
    327     static const soc_mem_t clear_mem_list[] = {
    328         SVM_METER_TABLEm,
    329         SVM_POLICY_TABLEm,
    330         SVC_METER_OFFSET_TCAMm,
    331         SVC_METER_OFFSET_POLICY_TABLEm
    332     };
    333 
    334     GH2_POL_FUNCTION_TRACE(unit, "IN");
    335 
    336     for (i = 0;
    337          i < sizeof(clear_mem_list) / sizeof(soc_mem_t);
    338          i++) {
    339         soc_mem_lock(unit, clear_mem_list[i]);
    340         rv = soc_mem_clear(unit, clear_mem_list[i], MEM_BLOCK_ALL, TRUE);
    341         soc_mem_unlock(unit, clear_mem_list[i]);
    342         BCM_IF_ERROR_RETURN(rv);
    343     }
    344 
    345     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    346     return rv;
    347 }
    348 
    349 /* Clear a range (base_index ~ base_index + numbers) of meter table */
    350 STATIC int
    351 bcmi_gh2_global_meter_mem_range_clear(
    352     int unit,
    353     int base_index,
    354     uint32 numbers)
    355 {
    356     bcm_error_t rv = BCM_E_NONE;
    357     soc_mem_t policy_mem = SVM_POLICY_TABLEm;
    358     soc_mem_t meter_mem = SVM_METER_TABLEm;
    359     svm_policy_table_entry_t *policy_entry_buf;
    360     svm_meter_table_entry_t *svm_meter_buf;
    361     int entry_mem_size;    /* Size of table entry. */
    362     int entry_index_max = 0;
    363     int meter_base_index;
    364     uint32 meter_numbers;
    365 
    366 
    367     GH2_POL_FUNCTION_TRACE(unit, "IN");
    368 
    369     /* Clear base_index ~ base_index + numbers of SVM_POLICY_TABLEm */
    370     entry_mem_size = sizeof(svm_policy_table_entry_t);
    371     entry_index_max = base_index + numbers - 1;
    372     policy_entry_buf =
    373         soc_cm_salloc(unit, entry_mem_size * numbers,
    374                       "svm policy table entry");
    375     if (policy_entry_buf == NULL) {
    376         return BCM_E_MEMORY;
    377     }
    378     sal_memset(policy_entry_buf, 0, entry_mem_size * numbers);
    379 
    380     soc_mem_lock(unit, policy_mem);
    381     rv = soc_mem_write_range(
    382         unit, policy_mem, MEM_BLOCK_ALL, base_index,
    383         entry_index_max, policy_entry_buf);
    384     soc_mem_unlock(unit, policy_mem);
    385 
    386     if (policy_entry_buf != NULL) {
    387         soc_cm_sfree(unit, policy_entry_buf);
    388     }
    389     BCM_IF_ERROR_RETURN(rv);
    390 
    391     /* Clear base_index*2 ~ base_index*2 + numbers*2 of SVM_METER_TABLEm */
    392     meter_base_index = base_index * 2;
    393     meter_numbers = numbers * 2;
    394 
    395     entry_mem_size = sizeof(svm_meter_table_entry_t);
    396     entry_index_max = meter_base_index + meter_numbers - 1;
    397     svm_meter_buf =
    398         soc_cm_salloc(unit, entry_mem_size * meter_numbers,
    399                       "svm meter table entry");
    400     if (svm_meter_buf == NULL) {
    401         return BCM_E_MEMORY;
    402     }
    403     sal_memset(svm_meter_buf, 0, entry_mem_size * meter_numbers);
    404 
    405     soc_mem_lock(unit, meter_mem);
    406     rv = soc_mem_write_range(
    407         unit, meter_mem, MEM_BLOCK_ALL, meter_base_index,
    408         entry_index_max, svm_meter_buf);
    409     soc_mem_unlock(unit, meter_mem);
    410 
    411     if (svm_meter_buf != NULL) {
    412         soc_cm_sfree(unit, svm_meter_buf);
    413     }
    414 
    415     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    416     return rv;
    417 }
    418 
    419 /*
    420  * Function:
    421  *   bcmi_gh2_global_meter_ifg_set
    422  * Purpose:
    423  *   Enable/Disable Inter Frame Gap(IFG)
    424  * Parameters:
    425  *   unit       - (IN) unit number
    426  *   ifg_enable - (IN) Enable/disable
    427  * Returns:
    428  *   BCM_E_XXX
    429  */
    430 STATIC int
    431 bcmi_gh2_global_meter_ifg_set(
    432     int unit,
    433     uint8 ifg_enable)
    434 {
    435     uint32 rval = 0, val;
    436 
    437     GH2_POL_FUNCTION_TRACE(unit, "IN");
    438     GH2_POL_FUNCTION_DEBUG(unit, "ifg_set %d", ifg_enable);
    439 
    440     if (ifg_enable) {
    441         val = 1;
    442     } else {
    443         val = 0;
    444     }
    445 
    446     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    447     soc_reg_field_set(unit,
    448                       SVM_TSN_CONTROLr,
    449                       &rval,
    450                       SVM_PACKET_IFG_ENf,
    451                       val);
    452     BCM_IF_ERROR_RETURN(WRITE_SVM_TSN_CONTROLr(unit, rval));
    453     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    454     return BCM_E_NONE;
    455 }
    456 
    457 /*
    458  * Function:
    459  *   bcmi_gh2_global_meter_ifg_get
    460  * Purpose:
    461  *   Get Enable/Disable Inter Frame Gap(IFG)
    462  * Parameters:
    463  *   unit       - (IN) unit number
    464  *   ifg_enable - (OUT) Enable/disable
    465  * Returns:
    466  *   BCM_E_XXX
    467  */
    468 STATIC int
    469 bcmi_gh2_global_meter_ifg_get(
    470     int unit,
    471     uint8 *ifg_enable)
    472 {
    473     uint32 rval = 0;
    474 
    475     GH2_POL_FUNCTION_TRACE(unit, "IN");
    476 
    477     /* Parameter NULL error handling */
    478     GH2_POL_CHECK_NULL_PARAMETER(unit, ifg_enable);
    479 
    480     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    481     *ifg_enable = (uint8)soc_reg_field_get(unit,
    482                                            SVM_TSN_CONTROLr,
    483                                            rval,
    484                                            SVM_PACKET_IFG_ENf);
    485 
    486     GH2_POL_FUNCTION_DEBUG(unit, "ifg_set %d", *ifg_enable);
    487     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    488     return BCM_E_NONE;
    489 }
    490 
    491 /*
    492  * Function:
    493  *   bcmi_gh2_global_meter_enable
    494  * Purpose:
    495  *   Enable/Disable SVM Control block
    496  * Parameters:
    497  *   unit    - (IN) unit number
    498  *   enabled - (IN) Enable/disable
    499  * Returns:
    500  *   BCM_E_XXX
    501  */
    502 STATIC int
    503 bcmi_gh2_global_meter_enable(
    504     int unit,
    505     uint8 enable)
    506 {
    507     uint32 rval = 0, val;
    508 
    509     GH2_POL_FUNCTION_TRACE(unit, "IN");
    510     GH2_POL_FUNCTION_DEBUG(unit, "enable %d", enable);
    511 
    512     if (enable) {
    513         val = 0;
    514     } else {
    515         val = 1;
    516     }
    517     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    518     soc_reg_field_set(unit, SVM_TSN_CONTROLr, &rval, SVM_BLOCK_DISABLEf, val);
    519     BCM_IF_ERROR_RETURN(WRITE_SVM_TSN_CONTROLr(unit, rval));
    520 
    521     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    522     return BCM_E_NONE;
    523 }
    524 
    525 /*
    526  * Function:
    527  *   bcmi_gh2_global_meter_enable_get
    528  * Purpose:
    529  *   Get Enable/Disable of SVM Control block
    530  * Parameters:
    531  *   unit    - (IN) unit number
    532  *   enabled - (OUT) Enable/disable
    533  * Returns:
    534  *   BCM_E_XXX
    535  */
    536 STATIC int
    537 bcmi_gh2_global_meter_enable_get(
    538     int unit,
    539     uint8 *enabled)
    540 {
    541     uint32 rval = 0, val;
    542 
    543     GH2_POL_FUNCTION_TRACE(unit, "IN");
    544 
    545     /* Parameter NULL error handling */
    546     GH2_POL_CHECK_NULL_PARAMETER(unit, enabled);
    547 
    548     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    549     val = soc_reg_field_get(unit, SVM_TSN_CONTROLr, rval, SVM_BLOCK_DISABLEf);
    550 
    551     if (val == 1) {
    552         *enabled = FALSE;
    553     } else {
    554         *enabled = TRUE;
    555     }
    556 
    557     GH2_POL_FUNCTION_DEBUG(unit, "enabled %d", *enabled);
    558     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    559     return BCM_E_NONE;
    560 }
    561 
    562 /*
    563  * Function:
    564  *   bcmi_gh2_global_meter_seop_enable
    565  * Purpose:
    566  *   Enable/Disable SOP/EOP Metering
    567  * Note: SEOP Metering
    568  * In GH2, the SOP cell size is at maximum. 144 bytes. Which means if packet
    569  * arrives with size lesser than or equal to 144 bytes, both SOP & EOP happen
    570  * on same instance in IPIPE, and an SEOP signal is generated. For these packet
    571  * sizes, length of packet (L) is known at SOP itself, which is also EOP.
    572  * Parameters:
    573  *   unit    - (IN) unit number
    574  *   enabled - (IN) Enable/disable
    575  * Returns:
    576  *   BCM_E_XXX
    577  */
    578 STATIC int
    579 bcmi_gh2_global_meter_seop_enable(
    580     int unit,
    581     uint8 enable)
    582 {
    583     uint32 rval = 0;
    584 
    585     GH2_POL_FUNCTION_TRACE(unit, "IN");
    586     GH2_POL_FUNCTION_DEBUG(unit, "enable %d", enable);
    587 
    588     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    589     soc_reg_field_set(unit,
    590                       SVM_TSN_CONTROLr,
    591                       &rval,
    592                       SVM_SEOP_METERING_ENf,
    593                       enable);
    594     BCM_IF_ERROR_RETURN(WRITE_SVM_TSN_CONTROLr(unit, rval));
    595 
    596     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    597     return BCM_E_NONE;
    598 }
    599 
    600 /*
    601  * Function:
    602  *   bcmi_gh2_global_meter_seop_enable_get
    603  * Purpose:
    604  *   Get Enable/Disable of SOP/EOP Metering
    605  * Note: SEOP Metering
    606  * In GH2, the SOP cell size is at maximum. 144 bytes. Which means if packet
    607  * arrives with size lesser than or equal to 144 bytes, both SOP & EOP happen
    608  * on same instance in IPIPE, and an SEOP signal is generated. For these packet
    609  * sizes, length of packet (L) is known at SOP itself, which is also EOP.
    610  * Parameters:
    611  *   unit    - (IN) unit number
    612  *   enabled - (OUT) Enable/disable
    613  * Returns:
    614  *   BCM_E_XXX
    615  */
    616 STATIC int
    617 bcmi_gh2_global_meter_seop_enable_get(
    618     int unit,
    619     uint8 *enabled)
    620 {
    621     uint32 rval = 0;
    622 
    623     GH2_POL_FUNCTION_TRACE(unit, "IN");
    624 
    625     /* Parameter NULL error handling */
    626     GH2_POL_CHECK_NULL_PARAMETER(unit, enabled);
    627 
    628     BCM_IF_ERROR_RETURN(READ_SVM_TSN_CONTROLr(unit, &rval));
    629     *enabled = (uint8)soc_reg_field_get(unit,
    630                                         SVM_TSN_CONTROLr,
    631                                         rval,
    632                                         SVM_SEOP_METERING_ENf);
    633 
    634     GH2_POL_FUNCTION_DEBUG(unit, "enabled %d", *enabled);
    635     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    636     return BCM_E_NONE;
    637 }
    638 
    639 /*
    640  * Function:
    641  *   bcmi_gh2_global_meter_source_order_set
    642  * Purpose:
    643  *   Configure the priority of VFP/L2/VXLT/VLAN/Port in the case of
    644  *   conflict source happened.
    645  * Parameters:
    646  *   unit               - (IN) unit number
    647  *   source_order       - (IN) Service Metering Source Table Priority Config
    648  *   (The lower index of meter source in config array has higher priority)
    649  *   source_order_count - (IN) Valid index count in source_order
    650  * Returns:
    651  *   BCM_E_XXX
    652  */
    653 STATIC int
    654 bcmi_gh2_global_meter_source_order_set(
    655     int unit,
    656     bcm_policer_global_meter_source_t *source_order,
    657     uint32 source_order_count)
    658 {
    659     int priority, index;
    660     bcm_policer_global_meter_source_t source;
    661     soc_field_t source_field = INVALIDf;
    662 
    663     GH2_POL_FUNCTION_TRACE(unit, "IN");
    664 
    665     /* Parameter NULL error handling */
    666     GH2_POL_CHECK_NULL_PARAMETER(unit, source_order);
    667 
    668     if (source_order_count > 7) {
    669         return BCM_E_PARAM;
    670     }
    671 
    672     for (index = 0; index < source_order_count; index++) {
    673         source = source_order[index];
    674         if (source > 7) {
    675             LOG_ERROR(BSL_LS_BCM_POLICER,
    676                       (BSL_META_U(unit,
    677                                   "Invalid source(%d).\n"),
    678                                   source));
    679             return BCM_E_PARAM;
    680         }
    681         /* highest value will have the highest priority */
    682         priority = source_order_count - index - 1;
    683         if (source == bcmPolicerGlobalMeterSourceFieldStageLookup) {
    684             source_field = VFP_TABLEf;
    685         } else if (source == bcmPolicerGlobalMeterSourceDstMac) {
    686             source_field = L2_TABLE_DA_LOOKUPf;
    687         } else if (source == bcmPolicerGlobalMeterSourceSrcMac) {
    688             source_field = L2_TABLE_SA_LOOKUPf;
    689         } else if (source == bcmPolicerGlobalMeterSourceVlanTranslateFirst) {
    690             source_field = VXLT_TABLE_KEY1f;
    691         } else if (source == bcmPolicerGlobalMeterSourceVlanTranslateSecond) {
    692             source_field = VXLT_TABLE_KEY2f;
    693         } else if (source == bcmPolicerGlobalMeterSourceVlan) {
    694             source_field = VLAN_TABLEf;
    695         } else if (source == bcmPolicerGlobalMeterSourcePort) {
    696             source_field = PORT_TABLEf;
    697             /* need to write LPORT_TABLEf and PORT_TABLEf */
    698             BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
    699                 METER_SOURCE_PRIORITYr,
    700                 REG_PORT_ANY,
    701                 LPORT_TABLEf,
    702                 priority));
    703         }
    704         BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
    705             METER_SOURCE_PRIORITYr,
    706             REG_PORT_ANY,
    707             source_field,
    708             priority));
    709     }
    710 
    711     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    712     return BCM_E_NONE;
    713 }
    714 
    715 /*
    716  * Function:
    717  *    bcmi_gh2_global_meter_source_order_get
    718  * Purpose:
    719  *   Get the priority of VFP/L2/VXLT/VLAN/Port in the case of
    720  *   conflict source happened.
    721  * Parameters:
    722  *   unit               - (IN) unit number
    723  *   source_order_count - (IN) Valid index count in source_order
    724  *   source_order       - (OUT) Service Metering Source Table Priority Config
    725  * Returns:
    726  *   BCM_E_XXX
    727  */
    728 STATIC int
    729 bcmi_gh2_global_meter_source_order_get(
    730     int unit,
    731     uint32 source_order_count,
    732     bcm_policer_global_meter_source_t *source_order)
    733 {
    734     uint32 rval = 0;
    735     soc_field_t source_field = INVALIDf;
    736     int priority, index;
    737     bcm_policer_global_meter_source_t source;
    738 
    739     GH2_POL_FUNCTION_TRACE(unit, "IN");
    740 
    741     /* Parameter NULL error handling */
    742     GH2_POL_CHECK_NULL_PARAMETER(unit, source_order);
    743 
    744     if (source_order_count > 7) {
    745         return BCM_E_PARAM;
    746     }
    747 
    748     for (source = 0; source < source_order_count; source++) {
    749         if (source == bcmPolicerGlobalMeterSourceFieldStageLookup) {
    750             source_field = VFP_TABLEf;
    751         } else if (source == bcmPolicerGlobalMeterSourceDstMac) {
    752             source_field = L2_TABLE_DA_LOOKUPf;
    753         } else if (source == bcmPolicerGlobalMeterSourceSrcMac) {
    754             source_field = L2_TABLE_SA_LOOKUPf;
    755         } else if (source == bcmPolicerGlobalMeterSourceVlanTranslateFirst) {
    756             source_field = VXLT_TABLE_KEY1f;
    757         } else if (source == bcmPolicerGlobalMeterSourceVlanTranslateSecond) {
    758             source_field = VXLT_TABLE_KEY2f;
    759         } else if (source == bcmPolicerGlobalMeterSourceVlan) {
    760             source_field = VLAN_TABLEf;
    761         } else if (source == bcmPolicerGlobalMeterSourcePort) {
    762             source_field = PORT_TABLEf;
    763         }
    764 
    765         BCM_IF_ERROR_RETURN(READ_METER_SOURCE_PRIORITYr(unit, &rval));
    766         priority = soc_reg_field_get(unit,
    767                                      METER_SOURCE_PRIORITYr,
    768                                      rval,
    769                                      source_field);
    770         /* highest value will have the highest priority */
    771         index = source_order_count - priority - 1;
    772         source_order[index] = source;
    773     }
    774 
    775     GH2_POL_FUNCTION_TRACE(unit, "OUT");
    776     return BCM_E_NONE;
    777 }
    778 
    779 /* TCAM (SVC_METER_OFFSET_TCAM) fields mapping of bcm_policer_group_mode_t */
    780 const soc_field_t gh2_policer_group_mode_field_list[] =
    781 {
    782     INVALIDf,
    783     INVALIDf,
    784     /* bcmPolicerGroupModeAttrUdf = 1 not used */
    785     INVALIDf,
    786     INVALIDf,
    787     /* bcmPolicerGroupModeAttrFieldIngressColor */
    788     CNGf,
    789     CNG_MASKf,
    790     /* bcmPolicerGroupModeAttrIntPri */
    791     INT_PRIf,
    792     INT_PRI_MASKf,
    793     /* bcmPolicerGroupModeAttrVlan */
    794     VLAN_FORMATf,
    795     VLAN_FORMAT_MASKf,
    796     /* bcmPolicerGroupModeAttrOuterPri */
    797     OUTER_DOT1Pf,
    798     OUTER_DOT1P_MASKf,
    799     /* bcmPolicerGroupModeAttrInnerPri */
    800     INNER_DOT1Pf,
    801     INNER_DOT1P_MASKf,
    802     /* bcmPolicerGroupModeAttrPort */
    803     INGRESS_PORTf,
    804     INGRESS_PORT_MASKf,
    805     /* bcmPolicerGroupModeAttrTosDscp */
    806     TOSf,
    807     TOS_MASKf,
    808     /* bcmPolicerGroupModeAttrTosEcn */
    809     INVALIDf,
    810     INVALIDf,
    811     /* bcmPolicerGroupModeAttrPktType */
    812     PACKET_RESOLUTIONf,
    813     PACKET_RESOLUTION_MASKf,
    814     /* bcmPolicerGroupModeAttrIngNetworkGroup */
    815     INVALIDf,
    816     INVALIDf,
    817     /* bcmPolicerGroupModeAttrDrop */
    818     INVALIDf,
    819     INVALIDf,
    820     /* bcmPolicerGroupModeAttrPacketTypeIp */
    821     INVALIDf,
    822     INVALIDf,
    823     /* bcmPolicerGroupModeAttrPreemptable */
    824     PREEMPTABLE_CELLf,
    825     PREEMPTABLE_CELL_MASKf,
    826     /* bcmPolicerGroupModeAttrEtherType */
    827     ETHER_TYPEf,
    828     ETHER_TYPE_MASKf,
    829     /* bcmPolicerGroupModeAttrOuterVlanCfi */
    830     OUTER_DOT1Pf,
    831     OUTER_DOT1P_MASKf,
    832     /* bcmPolicerGroupModeAttrInnerVlanCfi */
    833     INNER_DOT1Pf,
    834     INNER_DOT1P_MASKf
    835 };
    836 
    837 /* validate bcm_policer_group_mode_attr_t & value */
    838 STATIC void
    839 bcmi_gh2_group_mode_attr_value_remapping(
    840     bcm_policer_group_mode_attr_t group_mode_attr,
    841     uint32 value,
    842     uint32 value_mask,
    843     uint32 *hw_value,
    844     uint32 *hw_value_mask)
    845 {
    846     uint32 val, val_mask;
    847 
    848     /* Parameter NULL error handling */
    849     if (hw_value == NULL || hw_value_mask == NULL) {
    850         return;
    851     }
    852     val = value;
    853     val_mask = value_mask;
    854     switch (group_mode_attr) {
    855         case bcmPolicerGroupModeAttrFieldIngressColor:
    856             /* Re-mapping packet color to CNG value */
    857             if (val == bcmColorYellow) {
    858                 val = 0x3;
    859             } else if (val == bcmColorRed) {
    860                 val = 0x1;
    861             }
    862             break;
    863         case bcmPolicerGroupModeAttrVlan:
    864             if (val == bcmPolicerGroupModeAttrVlanUnTagged) {
    865                 val = 0x0;
    866             } else if (val == bcmPolicerGroupModeAttrVlanInnerTag) {
    867                 val = 0x1;
    868             } else if (val == bcmPolicerGroupModeAttrVlanOuterTag) {
    869                 val = 0x2;
    870             } else if (val == bcmPolicerGroupModeAttrVlanStackedTag) {
    871                 val = 0x3;
    872             }
    873             break;
    874         case bcmPolicerGroupModeAttrOuterPri:
    875         case bcmPolicerGroupModeAttrInnerPri:
    876             /* 3bit PRI + 1 bit CFI */
    877             val = (val << 1);
    878             /* Skip CFI bit */
    879             val_mask = val_mask & (~0x1);
    880             break;
    881         case bcmPolicerGroupModeAttrOuterVlanCfi:
    882         case bcmPolicerGroupModeAttrInnerVlanCfi:
    883             /* 3bit PRI + 1 bit CFI */
    884             val = val & 0x1;
    885             /* Skip PRI bit */
    886             val_mask = val_mask & 0x1;
    887             break;
    888         case bcmPolicerGroupModeAttrPktType:
    889             switch(val) {
    890                 case bcmPolicerGroupModeAttrPktTypeUnknown:
    891                     val =
    892                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_PKT];
    893                     break;
    894                 case bcmPolicerGroupModeAttrPktTypeControl:
    895                     val =
    896                         bcmi_gh2_global_meter_pkt_res[CONTROL_PKT];
    897                     break;
    898                 case bcmPolicerGroupModeAttrPktTypeOAM:
    899                     val =
    900                         bcmi_gh2_global_meter_pkt_res[OAM_PKT];
    901                     break;
    902                 case bcmPolicerGroupModeAttrPktTypeBFD:
    903                     val =
    904                         bcmi_gh2_global_meter_pkt_res[BFD_PKT];
    905                     break;
    906                 case bcmPolicerGroupModeAttrPktTypeBPDU:
    907                     val =
    908                         bcmi_gh2_global_meter_pkt_res[BPDU_PKT];
    909                     break;
    910                 case bcmPolicerGroupModeAttrPktTypeICNM:
    911                     val =
    912                         bcmi_gh2_global_meter_pkt_res[ICNM_PKT];
    913                     break;
    914                 case bcmPolicerGroupModeAttrPktType1588:
    915                     val =
    916                         bcmi_gh2_global_meter_pkt_res[PKT_IS_1588];
    917                     break;
    918                 case bcmPolicerGroupModeAttrPktTypeKnownL2UC:
    919                     val =
    920                         bcmi_gh2_global_meter_pkt_res[KNOWN_L2UC_PKT];
    921                     break;
    922                 case bcmPolicerGroupModeAttrPktTypeUnknownL2UC:
    923                     val =
    924                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_L2UC_PKT];
    925                     break;
    926                 case bcmPolicerGroupModeAttrPktTypeL2BC:
    927                     val =
    928                         bcmi_gh2_global_meter_pkt_res[L2BC_PKT];
    929                     break;
    930                 case bcmPolicerGroupModeAttrPktTypeKnownL2MC:
    931                     val =
    932                         bcmi_gh2_global_meter_pkt_res[KNOWN_L2MC_PKT];
    933                     break;
    934                 case bcmPolicerGroupModeAttrPktTypeUnknownL2MC:
    935                     val =
    936                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_L2MC_PKT];
    937                     break;
    938                 case bcmPolicerGroupModeAttrPktTypeKnownL3UC:
    939                     val =
    940                         bcmi_gh2_global_meter_pkt_res[KNOWN_L3UC_PKT];
    941                     break;
    942                 case bcmPolicerGroupModeAttrPktTypeUnknownL3UC:
    943                     val =
    944                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_L3UC_PKT];
    945                     break;
    946                 case bcmPolicerGroupModeAttrPktTypeKnownIPMC:
    947                     val =
    948                         bcmi_gh2_global_meter_pkt_res[KNOWN_IPMC_PKT];
    949                     break;
    950                 case bcmPolicerGroupModeAttrPktTypeUnknownIPMC:
    951                     val =
    952                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_IPMC_PKT];
    953                     break;
    954                 case bcmPolicerGroupModeAttrPktTypeKnownMplsL2:
    955                     val =
    956                         bcmi_gh2_global_meter_pkt_res[KNOWN_MPLS_L2_PKT];
    957                     break;
    958                 case bcmPolicerGroupModeAttrPktTypeKnownMplsL3:
    959                     val =
    960                         bcmi_gh2_global_meter_pkt_res[KNOWN_MPLS_L3_PKT];
    961                     break;
    962                 case bcmPolicerGroupModeAttrPktTypeKnownMpls:
    963                     val =
    964                         bcmi_gh2_global_meter_pkt_res[KNOWN_MPLS_PKT];
    965                     break;
    966                 case bcmPolicerGroupModeAttrPktTypeUnknownMpls:
    967                     val =
    968                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_MPLS_PKT];
    969                     break;
    970                 case bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast:
    971                     val =
    972                     bcmi_gh2_global_meter_pkt_res[KNOWN_MPLS_MULTICAST_PKT];
    973                     break;
    974                 case bcmPolicerGroupModeAttrPktTypeKnownMim:
    975                     val =
    976                         bcmi_gh2_global_meter_pkt_res[KNOWN_MIM_PKT];
    977                     break;
    978                 case bcmPolicerGroupModeAttrPktTypeUnknownMim:
    979                     val =
    980                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_MIM_PKT];
    981                     break;
    982                 case bcmPolicerGroupModeAttrPktTypeKnownTrill:
    983                     val =
    984                         bcmi_gh2_global_meter_pkt_res[KNOWN_TRILL_PKT];
    985                     break;
    986                 case bcmPolicerGroupModeAttrPktTypeUnknownTrill:
    987                     val =
    988                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_TRILL_PKT];
    989                     break;
    990                 case bcmPolicerGroupModeAttrPktTypeKnownNiv:
    991                     val =
    992                         bcmi_gh2_global_meter_pkt_res[KNOWN_NIV_PKT];
    993                     break;
    994                 case bcmPolicerGroupModeAttrPktTypeUnknownNiv:
    995                     val =
    996                         bcmi_gh2_global_meter_pkt_res[UNKNOWN_NIV_PKT];
    997                     break;
    998                 default:
    999                     break;
   1000                 }
   1001             val_mask = 0x3F;
   1002             break;
   1003         default:
   1004             break;
   1005     }
   1006     *hw_value = val;
   1007     *hw_value_mask = val_mask;
   1008 }
   1009 
   1010 /* validate bcm_policer_group_mode_attr_t & value */
   1011 STATIC int
   1012 bcmi_gh2_group_mode_attr_validate(
   1013     int unit,
   1014     bcm_policer_group_mode_attr_t group_mode_attr,
   1015     uint32 value)
   1016 {
   1017     soc_mem_t meter_mem = SVC_METER_OFFSET_TCAMm;
   1018     soc_field_t field = INVALIDf;
   1019     uint32 hw_value = 0, hw_value_mask = 0;
   1020     uint32 value_mask = 0;
   1021 
   1022     /* Check if group_mode_attr supported */
   1023     BCM_IF_ERROR_RETURN(
   1024         bcmi_gh2_group_mode_attr_supported(
   1025             unit, group_mode_attr));
   1026 
   1027     /* Skip all cases checking */
   1028     if (value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) {
   1029         return BCM_E_UNAVAIL;
   1030     } else if (group_mode_attr == bcmPolicerGroupModeAttrVlan &&
   1031                value == bcmPolicerGroupModeAttrVlanAll) {
   1032         return BCM_E_UNAVAIL;
   1033     } else if (group_mode_attr == bcmPolicerGroupModeAttrPktType &&
   1034                value == bcmPolicerGroupModeAttrPktTypeAll) {
   1035         return BCM_E_UNAVAIL;
   1036     }
   1037 
   1038     /* group_mode_attr field for checking value */
   1039     field = gh2_policer_group_mode_field_list[group_mode_attr * 2];
   1040 
   1041     if (field == INVALIDf) {
   1042         LOG_ERROR(BSL_LS_BCM_POLICER,
   1043                   (BSL_META_U(unit,
   1044                               "Invalid field.\n"
   1045                               "GH2 doesn't support group_mode_attr(%d)\n"),
   1046                               group_mode_attr));
   1047         return BCM_E_PARAM;
   1048     }
   1049 
   1050     /* Check if the value fit to HW field */
   1051     bcmi_gh2_group_mode_attr_value_remapping(
   1052         group_mode_attr, value, value_mask, &hw_value, &hw_value_mask);
   1053 
   1054     if (group_mode_attr == bcmPolicerGroupModeAttrPktType &&
   1055         value != bcmPolicerGroupModeAttrPktTypeUnknown &&
   1056         hw_value == GH2_UNKNOWN_PKT_VAL) {
   1057         /*
   1058          * GH2 doesn't support this pkt resolution,
   1059          * Refer to FP_RESOLUTION in reg bcm53570_a0
   1060          */
   1061         return BCM_E_UNAVAIL;
   1062     }
   1063 
   1064     BCM_IF_ERROR_RETURN(
   1065         soc_mem_field32_fit(
   1066             unit, meter_mem, field, hw_value));
   1067     return BCM_E_NONE;
   1068 }
   1069 
   1070 /*
   1071  * Function:
   1072  *   bcmi_gh2_global_meter_tcam_keys_set
   1073  * Purpose:
   1074  *   Set the Packet Attribute to TCAM hardware
   1075  * Parameters:
   1076  *   unit                 - (IN) Unit number
   1077  *   pkt_attr_bits_v      - (IN) Packet TCAM attributes
   1078  * Returns:
   1079  *   BCM_E_xxx
   1080  */
   1081 STATIC bcm_error_t
   1082 bcmi_gh2_global_meter_tcam_keys_set(
   1083     int unit,
   1084     pkt_tcam_attr_bits_t *pkt_attr_bits_v)
   1085 {
   1086     uint32 hw_idx;
   1087     int attr;
   1088     uint32 value, value_mask;
   1089     uint32 hw_value = 0, hw_value_mask = 0;
   1090     uint32 fldbuf[SOC_MAX_MEM_WORDS] = { 0 };
   1091     uint8 pkt_attr_selector_enable = 0;
   1092     soc_mem_t meter_mem = SVC_METER_OFFSET_TCAMm;
   1093     soc_mem_t policy_mem = SVC_METER_OFFSET_POLICY_TABLEm;
   1094     soc_field_t field = INVALIDf, mask_field = INVALIDf;
   1095     svc_meter_offset_tcam_entry_t tcam;
   1096     svc_meter_offset_policy_table_entry_t policy;
   1097 
   1098     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1099 
   1100     /* Parameter NULL error handling */
   1101     GH2_POL_CHECK_NULL_PARAMETER(unit, pkt_attr_bits_v);
   1102 
   1103     hw_idx = pkt_attr_bits_v->tcam_idx;
   1104 
   1105     /* Validate hw_idx */
   1106     if (hw_idx >= GH2_GLOBAL_METER_TCAM_SIZE) {
   1107         LOG_ERROR(BSL_LS_BCM_POLICER,
   1108                   (BSL_META_U(unit,
   1109                               "Invalid hw_idx(%d).\n"),
   1110                               hw_idx));
   1111         return BCM_E_PARAM;
   1112     }
   1113 
   1114     sal_memset(&tcam, 0,
   1115                sizeof(svc_meter_offset_tcam_entry_t));
   1116     sal_memset(&policy, 0,
   1117                sizeof(svc_meter_offset_policy_table_entry_t));
   1118 
   1119     /* Write SVC_METER_OFFSET_TCAM start */
   1120     BCM_IF_ERROR_RETURN(
   1121         soc_mem_read(unit, meter_mem, MEM_BLOCK_ANY, hw_idx, &tcam));
   1122 
   1123     pkt_attr_selector_enable =
   1124         pkt_attr_bits_v->attr_bits_selector == 0 ? 0 : 1 ;
   1125 
   1126     /*
   1127      * Write SVC_METER_INDEXf and SVC_METER_OFFSET_MODEf
   1128      * looping all elements in gh2_policer_group_mode_field_list
   1129      */
   1130     for (attr = bcmPolicerGroupModeAttrFieldIngressColor;
   1131          attr <= bcmPolicerGroupModeAttrInnerVlanCfi;
   1132          attr++) {
   1133 
   1134         /* TCAM value field */
   1135         field = gh2_policer_group_mode_field_list[attr * 2];
   1136         if (field == INVALIDf) {
   1137             continue;
   1138         }
   1139         /* TCAM value mask field */
   1140         mask_field = gh2_policer_group_mode_field_list[attr * 2 + 1];
   1141 
   1142         if (pkt_attr_selector_enable &&
   1143             pkt_attr_bits_v->value_mask[attr] != 0) {
   1144             value = pkt_attr_bits_v->value[attr];
   1145             value_mask = pkt_attr_bits_v->value_mask[attr];
   1146             GH2_POL_FUNCTION_DEBUG(unit, "TCAM attr %d", attr);
   1147             GH2_POL_FUNCTION_DEBUG(unit, "TCAM value 0x%x", value);
   1148             GH2_POL_FUNCTION_DEBUG(unit, "TCAM value_mask 0x%x", value_mask);
   1149             bcmi_gh2_group_mode_attr_value_remapping(
   1150                 attr, value, value_mask, &hw_value, &hw_value_mask);
   1151             GH2_POL_FUNCTION_DEBUG(unit, "TCAM hw_value 0x%x", hw_value);
   1152             GH2_POL_FUNCTION_DEBUG(unit, "TCAM hw_value_mask 0x%x", hw_value_mask);
   1153         } else {
   1154             hw_value = 0;
   1155             hw_value_mask = 0;
   1156         }
   1157 
   1158         /*
   1159          * PRI & CFI Share the same field, we need to avoid overwrite issue
   1160          * OUTER_DOT1Pf & OUTER_DOT1P_MASKf
   1161          * INNER_DOT1Pf & INNER_DOT1P_MASKf
   1162          */
   1163         if (attr == bcmPolicerGroupModeAttrOuterPri ||
   1164             attr == bcmPolicerGroupModeAttrInnerPri) {
   1165             uint32 fldval = 0;
   1166             soc_mem_field_get(
   1167                 unit, meter_mem, (uint32 *)&tcam, field, &fldval);
   1168             /* OR original 1-bit CFI value & mask */
   1169             hw_value |= (fldval & 0x1);
   1170             soc_mem_field_get(
   1171                 unit, meter_mem, (uint32 *)&tcam, mask_field, &fldval);
   1172             hw_value_mask |= (fldval & 0x1);
   1173         }
   1174 
   1175         if (attr == bcmPolicerGroupModeAttrOuterVlanCfi ||
   1176             attr == bcmPolicerGroupModeAttrInnerVlanCfi) {
   1177             uint32 fldval = 0;
   1178             soc_mem_field_get(
   1179                 unit, meter_mem, (uint32 *)&tcam, field, &fldval);
   1180             /* OR original 3-bit PRI value & mask */
   1181             hw_value |= (fldval & (0x7 << 1));
   1182             soc_mem_field_get(
   1183                 unit, meter_mem, (uint32 *)&tcam, mask_field, &fldval);
   1184             hw_value_mask |= (fldval & (0x7 << 1));
   1185         }
   1186 
   1187         /* Write value */
   1188         if (SOC_MEM_FIELD_VALID(unit, meter_mem, field)) {
   1189             BCM_IF_ERROR_RETURN(
   1190                 soc_mem_field32_fit(
   1191                     unit, meter_mem, field, hw_value));
   1192             soc_mem_field_set(
   1193                 unit, meter_mem, (uint32 *)&tcam, field, &hw_value);
   1194         }
   1195         /* Write value_mask */
   1196         if (SOC_MEM_FIELD_VALID(unit, meter_mem, mask_field)) {
   1197             sal_memset(fldbuf, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1198             sal_memcpy(fldbuf, &hw_value_mask, sizeof(uint32));
   1199             soc_mem_field_width_fit_set(
   1200                 unit, meter_mem, (uint32 *)&tcam, mask_field, fldbuf);
   1201         }
   1202     }
   1203 
   1204     /* UDF0 */
   1205     if (pkt_attr_bits_v->udf.udf0 != 0) {
   1206         if (pkt_attr_selector_enable &&
   1207             pkt_attr_bits_v->udf_mask.udf0 != 0) {
   1208             hw_value = (uint32)pkt_attr_bits_v->udf.udf0;
   1209             hw_value_mask = (uint32)pkt_attr_bits_v->udf_mask.udf0;
   1210         } else {
   1211             hw_value = 0;
   1212             hw_value_mask = 0;
   1213         }
   1214         GH2_POL_FUNCTION_DEBUG(unit, "UDF0 hw_value 0x%x", hw_value);
   1215         GH2_POL_FUNCTION_DEBUG(unit, "UDF0 hw_value_mask 0x%x", hw_value_mask);
   1216         BCM_IF_ERROR_RETURN(
   1217             soc_mem_field32_fit(
   1218                 unit, meter_mem, UDF0f, hw_value));
   1219         BCM_IF_ERROR_RETURN(
   1220             soc_mem_field32_fit(
   1221                 unit, meter_mem, UDF0_MASKf, hw_value_mask));
   1222 
   1223         soc_mem_field32_set(
   1224             unit, meter_mem, &tcam, UDF0f, hw_value);
   1225         soc_mem_field32_set(
   1226             unit, meter_mem, &tcam, UDF0_MASKf, hw_value_mask);
   1227         soc_mem_field32_set(
   1228             unit, meter_mem, &tcam, UDF_VALID0f, 1);
   1229         soc_mem_field32_set(
   1230             unit, meter_mem, &tcam, UDF_VALID0_MASKf, 1);
   1231     }
   1232 
   1233     /* UDF1 */
   1234     if (pkt_attr_bits_v->udf.udf1 != 0) {
   1235         if (pkt_attr_selector_enable &&
   1236             pkt_attr_bits_v->udf_mask.udf1 != 0) {
   1237             hw_value = (uint32)pkt_attr_bits_v->udf.udf1;
   1238             hw_value_mask = (uint32)pkt_attr_bits_v->udf_mask.udf1;
   1239         } else {
   1240             hw_value = 0;
   1241             hw_value_mask = 0;
   1242         }
   1243         GH2_POL_FUNCTION_DEBUG(unit, "UDF1 hw_value 0x%x", hw_value);
   1244         GH2_POL_FUNCTION_DEBUG(unit, "UDF1 hw_value_mask 0x%x", hw_value_mask);
   1245         BCM_IF_ERROR_RETURN(
   1246             soc_mem_field32_fit(
   1247                 unit, meter_mem, UDF1f, hw_value));
   1248         BCM_IF_ERROR_RETURN(
   1249             soc_mem_field32_fit(
   1250                 unit, meter_mem, UDF1_MASKf, hw_value_mask));
   1251 
   1252         soc_mem_field32_set(
   1253             unit, meter_mem, &tcam, UDF1f, hw_value);
   1254         soc_mem_field32_set(
   1255             unit, meter_mem, &tcam, UDF1_MASKf, hw_value_mask);
   1256         soc_mem_field32_set(
   1257             unit, meter_mem, &tcam, UDF_VALID1f, 1);
   1258         soc_mem_field32_set(
   1259             unit, meter_mem, &tcam, UDF_VALID1_MASKf, 1);
   1260     }
   1261 
   1262     /* OFFSET_MODE */
   1263     if (pkt_attr_selector_enable) {
   1264         hw_value = (uint32)pkt_attr_bits_v->offset_mode;
   1265         hw_value_mask = 0x3;
   1266     } else {
   1267         hw_value = 0;
   1268         hw_value_mask = 0;
   1269     }
   1270     GH2_POL_FUNCTION_DEBUG(
   1271         unit, "OFFSET_MODE hw_value 0x%x", hw_value);
   1272     GH2_POL_FUNCTION_DEBUG(
   1273         unit, "OFFSET_MODE hw_value_mask 0x%x", hw_value_mask);
   1274     BCM_IF_ERROR_RETURN(
   1275         soc_mem_field32_fit(
   1276             unit, meter_mem, OFFSET_MODEf, hw_value));
   1277 
   1278     soc_SVC_METER_OFFSET_TCAMm_field32_set(unit,
   1279         &tcam, OFFSET_MODEf, hw_value);
   1280     soc_SVC_METER_OFFSET_TCAMm_field32_set(unit,
   1281         &tcam, OFFSET_MODE_MASKf, hw_value_mask);
   1282 
   1283     /* ENABLE / DISABLE pkt_attr_selector */
   1284     soc_SVC_METER_OFFSET_TCAMm_field32_set(unit,
   1285         &tcam, VALIDf, (uint32)pkt_attr_selector_enable);
   1286 
   1287     BCM_IF_ERROR_RETURN(
   1288         soc_mem_write(unit, meter_mem, MEM_BLOCK_ALL, hw_idx, &tcam));
   1289     /* Write SVC_METER_OFFSET_TCAM end */
   1290 
   1291     /* Write SVC_METER_OFFSET_POLICY_TABLE start */
   1292     BCM_IF_ERROR_RETURN(
   1293         soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY, hw_idx, &policy));
   1294 
   1295     soc_mem_field32_set(
   1296         unit, policy_mem, &policy, FINAL_OFFSET_ENABLEf,
   1297         pkt_attr_selector_enable);
   1298 
   1299     soc_mem_field32_set(
   1300         unit, policy_mem, &policy, FINAL_OFFSETf,
   1301         pkt_attr_bits_v->final_offset);
   1302 
   1303     BCM_IF_ERROR_RETURN(
   1304         soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, hw_idx, &policy));
   1305     /* Write SVC_METER_OFFSET_POLICY_TABLE end */
   1306 
   1307     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1308     return BCM_E_NONE;
   1309 }
   1310 
   1311 /*
   1312  * Function:
   1313  *   bcmi_gh2_global_meter_tcam_keys_get
   1314  * Purpose:
   1315  *   Get the Packet Attribute from TCAM hardware
   1316  * Parameters:
   1317  *   unit                 - (IN) Unit number
   1318  *   pkt_tcam_attr_bits_t - (OUT) Packet TCAM attributes
   1319  * Returns:
   1320  *   BCM_E_xxx
   1321  */
   1322 STATIC bcm_error_t
   1323 bcmi_gh2_global_meter_tcam_keys_get(
   1324     int unit,
   1325     pkt_tcam_attr_bits_t *pkt_attr_bits_v)
   1326 {
   1327     bcm_error_t rv = BCM_E_UNAVAIL;
   1328     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1329     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1330     return rv;
   1331 }
   1332 
   1333 /*
   1334  * Function:
   1335  *   bcmi_gh2_global_meter_tcam_keys_delete
   1336  * Purpose:
   1337  *   Delete the Packet Attribute on TCAM hardware
   1338  * Parameters:
   1339  *   unit   - (IN) Unit number
   1340  *  sw_idx  - (IN) SW memory index.
   1341  * Returns:
   1342  *   BCM_E_xxx
   1343  */
   1344 STATIC bcm_error_t
   1345 bcmi_gh2_global_meter_tcam_keys_delete(
   1346     int unit,
   1347     uint32 sw_idx)
   1348 {
   1349     bcm_error_t rv = BCM_E_NONE;
   1350     uint32 hw_idx;
   1351     pkt_tcam_attr_bits_t pkt_attr_bits_v;
   1352 
   1353     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1354 
   1355     hw_idx = sw_idx;
   1356 
   1357     /* Validate hw_idx */
   1358     if (hw_idx >= GH2_GLOBAL_METER_TCAM_SIZE) {
   1359         LOG_ERROR(BSL_LS_BCM_POLICER,
   1360                   (BSL_META_U(unit,
   1361                               "Invalid hw_idx(%d).\n"),
   1362                               hw_idx));
   1363         return BCM_E_PARAM;
   1364     }
   1365 
   1366     /* attr_bits_selector set to 0 will reset all value to 0 */
   1367     (void)pkt_tcam_attr_bits_t_init(&pkt_attr_bits_v);
   1368     pkt_attr_bits_v.tcam_idx = hw_idx;
   1369 
   1370     rv = bcmi_gh2_global_meter_tcam_keys_set(unit, &pkt_attr_bits_v);
   1371     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1372     return rv;
   1373 }
   1374 
   1375 /* Write meter_index & meter_offset_mode to source table */
   1376 STATIC bcm_error_t
   1377 bcmi_gh2_global_meter_policer_to_table_set(
   1378     int unit,
   1379     soc_mem_t mem,
   1380     uint32 mem_index,
   1381     void *mem_data,
   1382     int meter_index,
   1383     int meter_offset_mode,
   1384     int skip_read)
   1385 {
   1386     uint32 hw_idx = mem_index;
   1387 
   1388     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1389 
   1390     /* Parameter NULL error handling */
   1391     GH2_POL_CHECK_NULL_PARAMETER(unit, mem_data);
   1392 
   1393     if (!SOC_MEM_IS_VALID(unit, mem) ||
   1394         !SOC_MEM_FIELD_VALID(unit, mem, SVC_METER_INDEXf) ||
   1395         !SOC_MEM_FIELD_VALID(unit, mem, SVC_METER_OFFSET_MODEf)) {
   1396         return BCM_E_INTERNAL;
   1397     }
   1398 
   1399     /* Validate hw_idx */
   1400     if (hw_idx > (soc_mem_index_max(unit, mem)))
   1401     {
   1402         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   1403         return BCM_E_PARAM;
   1404     }
   1405 
   1406     if (FALSE == skip_read) {
   1407         BCM_IF_ERROR_RETURN(
   1408             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, mem_data));
   1409     }
   1410 
   1411     /* Write SVC_METER_INDEXf and SVC_METER_OFFSET_MODEf */
   1412     soc_mem_field32_set(unit, mem, mem_data,
   1413                         SVC_METER_INDEXf, meter_index);
   1414 
   1415     soc_mem_field32_set(unit, mem, mem_data,
   1416                         SVC_METER_OFFSET_MODEf, meter_offset_mode);
   1417 
   1418     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1419     return BCM_E_NONE;
   1420 }
   1421 
   1422 /* Read meter_index & meter_offset_mode from source table */
   1423 STATIC bcm_error_t
   1424 bcmi_gh2_global_meter_policer_to_table_get(
   1425     int unit,
   1426     soc_mem_t mem,
   1427     uint32 mem_index,
   1428     void *mem_data,
   1429     int *meter_index,
   1430     int *meter_offset_mode,
   1431     int skip_read)
   1432 {
   1433     uint32 hw_idx = mem_index;
   1434 
   1435     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1436 
   1437     /* Parameter NULL error handling */
   1438     GH2_POL_CHECK_NULL_PARAMETER(unit, mem_data);
   1439     GH2_POL_CHECK_NULL_PARAMETER(unit, meter_index);
   1440     GH2_POL_CHECK_NULL_PARAMETER(unit, meter_offset_mode);
   1441 
   1442     if (!SOC_MEM_IS_VALID(unit, mem) ||
   1443         !SOC_MEM_FIELD_VALID(unit, mem, SVC_METER_INDEXf) ||
   1444         !SOC_MEM_FIELD_VALID(unit, mem, SVC_METER_OFFSET_MODEf)) {
   1445         return BCM_E_INTERNAL;
   1446     }
   1447 
   1448     /* Validate hw_idx */
   1449     if (hw_idx > (soc_mem_index_max(unit, mem)))
   1450     {
   1451         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   1452         return BCM_E_PARAM;
   1453     }
   1454 
   1455     if (FALSE == skip_read) {
   1456         BCM_IF_ERROR_RETURN(
   1457             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, mem_data));
   1458     }
   1459 
   1460     /* Write SVC_METER_INDEXf and SVC_METER_OFFSET_MODEf */
   1461     *meter_index =
   1462         soc_mem_field32_get(unit, mem, mem_data,
   1463                             SVC_METER_INDEXf);
   1464     *meter_offset_mode =
   1465         soc_mem_field32_get(unit, mem, mem_data,
   1466                             SVC_METER_OFFSET_MODEf);
   1467     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1468     return BCM_E_NONE;
   1469 }
   1470 
   1471 /*
   1472  * Function:
   1473  *  bcmi_gh2_global_meter_meter_table_set
   1474  * Purpose:
   1475  *  Update (Install) the policer parameters
   1476  * Parameters:
   1477  *  unit          - (IN) BCM device number.
   1478  *  sw_idx        - (IN) SW memory index.
   1479  *  meter_mode    - (IN) policer meter mode.
   1480  *  meter_flags   - (IN) policer meter flag.
   1481  *  bucket_size   - (IN) Encoded bucket size.
   1482  *  bucket_count  - (IN) Encoded bucket count.
   1483  *  refresh_rate  - (IN) Tokens refresh rate.
   1484  *  granularity   - (IN) Tokens granularity.
   1485  * Returns:
   1486  *  BCM_E_XXX
   1487  */
   1488 STATIC bcm_error_t
   1489 bcmi_gh2_global_meter_meter_table_set(
   1490     int unit,
   1491     uint32 sw_idx,
   1492     bcm_policer_mode_t meter_mode,
   1493     uint32 meter_flags,
   1494     uint32 average_pkt_size,
   1495     uint32 meter_gran_mode,
   1496     uint32 bucket_size,
   1497     uint32 bucket_count,
   1498     uint32 refresh_rate,
   1499     uint32 granularity)
   1500 {
   1501     int rv = BCM_E_NONE;
   1502     uint32 hw_idx = sw_idx;
   1503     svm_meter_table_entry_t entry;
   1504     uint32 refresh_mode = 0, tsn_modified = 0, pkt_bytes = 0;
   1505     soc_mem_t mem = SVM_METER_TABLEm;
   1506 
   1507     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1508 
   1509     /* Validate hw_idx */
   1510     if (hw_idx > (soc_mem_index_max(unit, mem)))
   1511     {
   1512         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   1513         return BCM_E_PARAM;
   1514     }
   1515 
   1516     /* Refresh mode is only set to 1 for Single Rate. Other modes get 0 */
   1517     if (meter_mode == bcmPolicerModeSrTcmTsn) {
   1518         refresh_mode = 1;
   1519         tsn_modified = 1;
   1520     } else if ((meter_mode == bcmPolicerModeSrTcm) ||
   1521                (meter_mode == bcmPolicerModeSrTcmModified)) {
   1522         refresh_mode = 1;
   1523         tsn_modified = 0;
   1524     } else {
   1525         refresh_mode = 0;
   1526         tsn_modified = 0;
   1527     }
   1528 
   1529     /* PKT/BYTE - by default BYTE counter */
   1530     if (meter_flags & BCM_POLICER_MODE_PACKETS) {
   1531         pkt_bytes = 1;
   1532     }
   1533     soc_mem_lock(unit, mem);
   1534 
   1535     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &entry);
   1536     if (BCM_FAILURE(rv)) {
   1537         soc_mem_unlock(unit, mem);
   1538         return rv;
   1539     }
   1540 
   1541     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1542                                    BUCKETCOUNTf,
   1543                                    &bucket_count);
   1544     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1545                                    REFRESHCOUNTf,
   1546                                    &refresh_rate);
   1547     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1548                                    BUCKETSIZEf,
   1549                                    &bucket_size);
   1550     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1551                                    REFRESH_MODEf,
   1552                                    &refresh_mode);
   1553     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1554                                    METER_MODE_TSN_MODIFIERf,
   1555                                    &tsn_modified);
   1556     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1557                                    PKTS_BYTESf,
   1558                                    &pkt_bytes);
   1559     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1560                                    METER_GRANf,
   1561                                    &granularity);
   1562     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1563                                    THRESHOLD_CHECKf,
   1564                                    &average_pkt_size);
   1565     soc_SVM_METER_TABLEm_field_set(unit, &entry,
   1566                                    METER_GRAN_MODEf,
   1567                                    &meter_gran_mode);
   1568 
   1569     /* write to hw */
   1570     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, &entry);
   1571     soc_mem_unlock(unit, mem);
   1572 
   1573     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1574     return rv;
   1575 }
   1576 
   1577 /*
   1578  * Function:
   1579  *  bcmi_gh2_global_meter_meter_table_get
   1580  * Purpose:
   1581  *  Get the policer parameters
   1582  * Parameters:
   1583  *  unit          - (IN) BCM device number.
   1584  *  sw_idx        - (IN) SW memory index.
   1585  *  bucket_size   - (OUT) policer meter flag.
   1586  *  bucket_count  - (OUT) Encoded bucket count.
   1587  *  refresh_rate  - (OUT) Tokens refresh rate.
   1588  *  granularity   - (OUT) Tokens granularity.
   1589  *  pkt_bytes     - (OUT) packet mode or byte mode.
   1590  *  tsn_modified  - (OUT) TSN mode or not.
   1591  * Returns:
   1592  *  BCM_E_XXX
   1593  */
   1594 STATIC bcm_error_t
   1595 bcmi_gh2_global_meter_meter_table_get(
   1596     int unit,
   1597     uint32 sw_idx,
   1598     uint32 *bucket_size,
   1599     uint32 *bucket_count,
   1600     uint32 *refresh_rate,
   1601     uint32 *granularity,
   1602     uint32 *pkt_bytes,
   1603     uint32 *tsn_modified,
   1604     uint32 *meter_gran_mode,
   1605     uint32 *average_pkt_size)
   1606 {
   1607     int rv = BCM_E_NONE;
   1608     uint32 hw_idx = sw_idx;
   1609     svm_meter_table_entry_t entry;
   1610     soc_mem_t meter_mem = SVM_METER_TABLEm;
   1611 
   1612     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1613 
   1614     /* Parameter NULL error handling */
   1615     GH2_POL_CHECK_NULL_PARAMETER(unit, bucket_size);
   1616     GH2_POL_CHECK_NULL_PARAMETER(unit, bucket_count);
   1617     GH2_POL_CHECK_NULL_PARAMETER(unit, refresh_rate);
   1618     GH2_POL_CHECK_NULL_PARAMETER(unit, granularity);
   1619     GH2_POL_CHECK_NULL_PARAMETER(unit, pkt_bytes);
   1620     GH2_POL_CHECK_NULL_PARAMETER(unit, tsn_modified);
   1621     GH2_POL_CHECK_NULL_PARAMETER(unit, meter_gran_mode);
   1622     GH2_POL_CHECK_NULL_PARAMETER(unit, average_pkt_size);
   1623 
   1624     /* Validate hw_idx */
   1625     if (hw_idx > (soc_mem_index_max(unit, meter_mem)))
   1626     {
   1627         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   1628         return BCM_E_PARAM;
   1629     }
   1630 
   1631     BCM_IF_ERROR_RETURN(
   1632         soc_mem_read(unit, meter_mem, MEM_BLOCK_ANY, hw_idx, &entry));
   1633 
   1634     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1635                                    BUCKETCOUNTf,
   1636                                    bucket_count);
   1637     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1638                                    REFRESHCOUNTf,
   1639                                    refresh_rate);
   1640     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1641                                    BUCKETSIZEf,
   1642                                    bucket_size);
   1643     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1644                                    METER_MODE_TSN_MODIFIERf,
   1645                                    tsn_modified);
   1646     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1647                                    METER_GRANf,
   1648                                    granularity);
   1649     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1650                                    PKTS_BYTESf,
   1651                                    pkt_bytes);
   1652     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1653                                    THRESHOLD_CHECKf,
   1654                                    average_pkt_size);
   1655     soc_SVM_METER_TABLEm_field_get(unit, &entry,
   1656                                    METER_GRAN_MODEf,
   1657                                    meter_gran_mode);
   1658 
   1659     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1660     return rv;
   1661 }
   1662 
   1663 /*
   1664  * Function:
   1665  *  bcmi_gh2_global_meter_meter_table_bitsize_get
   1666  * Purpose:
   1667  *  Get the policer parameters
   1668  * Parameters:
   1669  *  unit          - (IN) BCM device number.
   1670  *  sw_idx        - (IN) SW memory index.
   1671  *  refresh_bitsize  - (OUT) length of REFRESHCOUNTf
   1672  *  bucket_max_bitsize   - (OUT) length of BUCKETSIZEf
   1673  *  bucket_cnt_bitsize  - (OUT) length of BUCKETCOUNTf
   1674  * Returns:
   1675  *  BCM_E_XXX
   1676  */
   1677 STATIC int
   1678 bcmi_gh2_global_meter_meter_table_bitsize_get(
   1679     int unit,
   1680     uint32 sw_idx,
   1681     uint32 *refresh_bitsize,
   1682     uint32 *bucket_max_bitsize,
   1683     uint32 *bucket_cnt_bitsize)
   1684 {
   1685     int rv = BCM_E_NONE;
   1686     uint32 hw_idx = sw_idx;
   1687     svm_meter_table_entry_t entry;
   1688     soc_mem_t meter_mem = SVM_METER_TABLEm;
   1689 
   1690     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1691 
   1692     /* Parameter NULL error handling */
   1693     GH2_POL_CHECK_NULL_PARAMETER(unit, refresh_bitsize);
   1694     GH2_POL_CHECK_NULL_PARAMETER(unit, bucket_max_bitsize);
   1695     GH2_POL_CHECK_NULL_PARAMETER(unit, bucket_cnt_bitsize);
   1696 
   1697     /* Validate hw_idx */
   1698     if (hw_idx > (soc_mem_index_max(unit, meter_mem)))
   1699     {
   1700         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx(%d)\n", hw_idx);
   1701         return BCM_E_PARAM;
   1702     }
   1703 
   1704     BCM_IF_ERROR_RETURN(
   1705         soc_mem_read(unit, meter_mem, MEM_BLOCK_ANY, hw_idx, &entry));
   1706 
   1707     *refresh_bitsize =
   1708         soc_mem_field_length(unit, meter_mem, REFRESHCOUNTf);
   1709     *bucket_max_bitsize =
   1710         soc_mem_field_length(unit, meter_mem, BUCKETSIZEf);
   1711     *bucket_cnt_bitsize =
   1712         soc_mem_field_length(unit, meter_mem, BUCKETCOUNTf);
   1713 
   1714     GH2_POL_FUNCTION_DEBUG(unit, "sw_idx %d", sw_idx);
   1715     GH2_POL_FUNCTION_DEBUG(unit, "refresh_bitsize %d", *refresh_bitsize);
   1716     GH2_POL_FUNCTION_DEBUG(unit, "bucket_max_bitsize %d", *bucket_max_bitsize);
   1717     GH2_POL_FUNCTION_DEBUG(unit, "bucket_cnt_bitsize %d", *bucket_cnt_bitsize);
   1718     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1719     return rv;
   1720 }
   1721 
   1722 /* Set the policy meter mode and flags to global meter */
   1723 STATIC int
   1724 bcmi_gh2_global_meter_policy_mode_set(
   1725     int unit,
   1726     uint32 sw_idx,
   1727     bcm_policer_mode_t meter_mode,
   1728     uint32 meter_flags)
   1729 {
   1730     int rv = BCM_E_NONE;
   1731     uint32 hw_idx = sw_idx;
   1732     svm_policy_table_entry_t policy_entry;
   1733     soc_mem_t policy_mem = SVM_POLICY_TABLEm;
   1734     uint32 modifier_mode = 0, pair_mode = 0;
   1735 
   1736     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1737     GH2_POL_FUNCTION_DEBUG(unit, "meter_mode %d", meter_mode);
   1738     GH2_POL_FUNCTION_DEBUG(unit, "meter_flags 0x%x", meter_flags);
   1739 
   1740     /* Validate hw_idx */
   1741     if (hw_idx > soc_mem_index_max(unit, policy_mem)) {
   1742         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   1743         return BCM_E_PARAM;
   1744     }
   1745 
   1746     sal_memset(&policy_entry, 0,
   1747                sizeof(svm_policy_table_entry_t));
   1748 
   1749     /* Refresh mode is only set to 1 for Single Rate. Other modes get 0 */
   1750     switch (meter_mode) {
   1751         case bcmPolicerModeGreen:
   1752             pair_mode = BCM_FIELD_METER_MODE_DEFAULT; /* 0 */
   1753             break;
   1754         case bcmPolicerModeCommitted:
   1755             pair_mode = BCM_FIELD_METER_MODE_FLOW; /* 1 */
   1756             break;
   1757         case bcmPolicerModeTrTcm:
   1758             pair_mode =
   1759                 (meter_flags & BCM_POLICER_COLOR_BLIND) ?
   1760                     BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND: /* 2 */
   1761                     BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE; /* 3 */
   1762             break;
   1763         case bcmPolicerModeTrTcmDs:
   1764             pair_mode =
   1765                 (meter_flags & BCM_POLICER_COLOR_BLIND) ? 4 : 5;
   1766             break;
   1767         case bcmPolicerModeSrTcmModified:
   1768             modifier_mode = 1;
   1769             /* fall through */
   1770         case bcmPolicerModeSrTcm:
   1771             pair_mode =
   1772                 (meter_flags & BCM_POLICER_COLOR_BLIND) ?
   1773                     BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND: /* 6 */
   1774                     BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE; /* 7 */
   1775             break;
   1776         case bcmPolicerModeSrTcmTsn:
   1777             pair_mode =
   1778                 (meter_flags & BCM_POLICER_COLOR_BLIND) ?
   1779                     BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND: /* 6 */
   1780                     BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE; /* 7 */
   1781             modifier_mode = 0;
   1782             break;
   1783         default:
   1784             pair_mode = 0;
   1785             break;
   1786     }
   1787 
   1788     /* SVM_POLICY_TABLEm */
   1789     BCM_IF_ERROR_RETURN(
   1790         soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY, hw_idx, &policy_entry));
   1791     GH2_POL_FUNCTION_DEBUG(unit, "pair_mode %d", pair_mode);
   1792     GH2_POL_FUNCTION_DEBUG(unit, "modifier_mode %d", modifier_mode);
   1793 
   1794     soc_SVM_POLICY_TABLEm_field_set(unit, &policy_entry,
   1795                                     METER_PAIR_MODEf,
   1796                                     &pair_mode);
   1797     soc_SVM_POLICY_TABLEm_field_set(unit, &policy_entry,
   1798                                     METER_PAIR_MODE_MODIFIERf,
   1799                                     &modifier_mode);
   1800     /* write to hw */
   1801     BCM_IF_ERROR_RETURN(
   1802         soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, hw_idx, &policy_entry));
   1803 
   1804     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1805     return rv;
   1806 }
   1807 
   1808 /* Get the policy meter mode and flags from global meter */
   1809 STATIC int
   1810 bcmi_gh2_global_meter_policy_mode_get(
   1811     int unit,
   1812     uint32 sw_idx,
   1813     bcm_policer_mode_t *meter_mode,
   1814     uint32 *meter_flags)
   1815 {
   1816     int rv = BCM_E_NONE;
   1817     uint32 meter_hw_idx = sw_idx * 2;
   1818     uint32 policy_hw_idx = sw_idx;
   1819     svm_meter_table_entry_t meter_entry;
   1820     svm_policy_table_entry_t policy_entry;
   1821     soc_mem_t meter_mem = SVM_METER_TABLEm;
   1822     soc_mem_t policy_mem = SVM_POLICY_TABLEm;
   1823     uint32 modifier_mode, pair_mode, tsn_modifier;
   1824 
   1825     GH2_POL_FUNCTION_TRACE(unit, "IN");
   1826 
   1827     /* Parameter NULL error handling */
   1828     GH2_POL_CHECK_NULL_PARAMETER(unit, meter_mode);
   1829     GH2_POL_CHECK_NULL_PARAMETER(unit, meter_flags);
   1830 
   1831     /* Validate meter_mem hw_idx */
   1832     if (meter_hw_idx > soc_mem_index_max(unit, meter_mem)) {
   1833         GH2_POL_FUNCTION_ERROR(
   1834             unit, "Invalid meter_hw_idx (%d) \n", meter_hw_idx);
   1835         return BCM_E_PARAM;
   1836     }
   1837 
   1838     /* Validate policy_mem hw_idx */
   1839     if (policy_hw_idx > soc_mem_index_max(unit, policy_mem)) {
   1840         GH2_POL_FUNCTION_ERROR(
   1841             unit, "Invalid policy_hw_idx (%d) \n", policy_hw_idx);
   1842         return BCM_E_PARAM;
   1843     }
   1844 
   1845     sal_memset(&meter_entry, 0,
   1846                sizeof(svm_meter_table_entry_t));
   1847     sal_memset(&policy_entry, 0,
   1848                sizeof(svm_policy_table_entry_t));
   1849 
   1850     BCM_IF_ERROR_RETURN(
   1851         soc_mem_read(
   1852             unit, meter_mem, MEM_BLOCK_ANY, meter_hw_idx, &meter_entry));
   1853 
   1854     BCM_IF_ERROR_RETURN(
   1855         soc_mem_read(
   1856             unit, policy_mem, MEM_BLOCK_ANY, policy_hw_idx, &policy_entry));
   1857 
   1858     pair_mode =
   1859         soc_mem_field32_get(unit, policy_mem,
   1860                             &policy_entry, METER_PAIR_MODEf);
   1861     modifier_mode =
   1862         soc_mem_field32_get(unit, policy_mem,
   1863                             &policy_entry, METER_PAIR_MODE_MODIFIERf);
   1864 
   1865     GH2_POL_FUNCTION_DEBUG(unit, "pair_mode %d", pair_mode);
   1866     GH2_POL_FUNCTION_DEBUG(unit, "modifier_mode %d", modifier_mode);
   1867 
   1868     switch (pair_mode) {
   1869         case BCM_FIELD_METER_MODE_DEFAULT: /* 0 */
   1870             *meter_mode = bcmPolicerModeGreen;
   1871             break;
   1872         case BCM_FIELD_METER_MODE_FLOW: /* 1 */
   1873             *meter_mode = bcmPolicerModeCommitted;
   1874             break;
   1875         case BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND: /* 2 */
   1876             *meter_flags |= BCM_POLICER_COLOR_BLIND;
   1877             /* Fall thru */
   1878         case BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE: /* 3 */
   1879             *meter_mode = bcmPolicerModeTrTcm;
   1880             break;
   1881         case BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND: /* 6 */
   1882             *meter_flags |= BCM_POLICER_COLOR_BLIND;
   1883             /* Fall thru */
   1884         case BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE: /* 7 */
   1885             *meter_mode = modifier_mode
   1886                           ? bcmPolicerModeSrTcmModified
   1887                           : bcmPolicerModeSrTcm;
   1888             tsn_modifier =
   1889                 soc_mem_field32_get(unit, meter_mem, &meter_entry,
   1890                                     METER_MODE_TSN_MODIFIERf);
   1891             if (tsn_modifier == 1) {
   1892                 *meter_mode = bcmPolicerModeSrTcmTsn;
   1893             }
   1894             break;
   1895         case 4:
   1896             *meter_flags |= BCM_POLICER_COLOR_BLIND;
   1897             /* Fall thru */
   1898         case 5:
   1899             *meter_mode = bcmPolicerModeTrTcmDs;
   1900             break;
   1901         default:
   1902             ;
   1903     }
   1904     GH2_POL_FUNCTION_DEBUG(unit, "meter_mode %d", *meter_mode);
   1905     GH2_POL_FUNCTION_DEBUG(unit, "meter_flags 0x%x", *meter_flags);
   1906     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   1907     return rv;
   1908 }
   1909 
   1910 /* refer to # FORMAT SVM_ACTIONS */
   1911 
   1912 /* NEW_PKT_PRI (other chip called NEW_DOT1P) */
   1913 #define GH2_POLICER_ACTION_PKT_PRI_POS                   (0)
   1914 /* NEW_INT_CN */
   1915 #define GH2_POLICER_ACTION_INT_CN_BIT_POS                (3)
   1916 /* NEW_DSCP_TOS */
   1917 #define GH2_POLICER_ACTION_DSCP_BIT_POS                  (5)
   1918 /* DROP_PRECEDENCE (other chip called CHANGE_CNG) */
   1919 #define GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS       (11)
   1920 /* DROP */
   1921 #define GH2_POLICER_ACTION_DROP_BIT_POS                  (13)
   1922 /* COS_INT_PRI */
   1923 #define GH2_POLICER_ACTION_INT_PRI_BIT_POS               (15)
   1924 /* CHANGE_PKT_PRI (other chip called CHANGE_DOT1P) */
   1925 #define GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS        (23)
   1926 /* CHANGE_INT_CN */
   1927 #define GH2_POLICER_ACTION_CHANGE_INT_CN_BIT_POS         (26)
   1928 /* CHANGE_ECN */
   1929 #define GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS            (27)
   1930 /* CHANGE_DSCP_TOS */
   1931 #define GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS           (29)
   1932 /* CHANGE_COS_OR_INT_PRI, 2*32 bit value, thus need to minus by 32 */
   1933 #define GH2_POLICER_ACTION_CHANGE_COS_OR_INT_PRI_BIT_POS (32 - 32)
   1934 
   1935 /*
   1936  * Function:
   1937  *  bcmi_gh2_global_meter_policy_action_param_configure
   1938  * Purpose:
   1939  *  Update (Install) the policer action parameters
   1940  * Parameters:
   1941  *  unit     - (IN) BCM device number.
   1942  *  g_action - (IN) Green action
   1943  *  y_action - (IN) Yellow action
   1944  *  r_action - (IN) Red action
   1945  * Returns:
   1946  *  BCM_E_XXX
   1947  */
   1948 STATIC int
   1949 bcmi_gh2_global_meter_policy_action_param_configure(
   1950     int unit,
   1951     bcm_policer_action_t action,
   1952     uint32 param0,
   1953     uint64 *g_action,
   1954     uint64 *y_action,
   1955     uint64 *r_action)
   1956 {
   1957     uint32 green_action[2] = {0}, yellow_action[2] = {0}, red_action[2] = {0};
   1958 
   1959     GH2_POL_CHECK_NULL_PARAMETER(unit, green_action);
   1960     GH2_POL_CHECK_NULL_PARAMETER(unit, yellow_action);
   1961     GH2_POL_CHECK_NULL_PARAMETER(unit, red_action);
   1962 
   1963     COMPILER_64_TO_32_LO(green_action[0], *g_action);
   1964     COMPILER_64_TO_32_HI(green_action[1], *g_action);
   1965     COMPILER_64_TO_32_LO(yellow_action[0], *y_action);
   1966     COMPILER_64_TO_32_HI(yellow_action[1], *y_action);
   1967     COMPILER_64_TO_32_LO(red_action[0], *r_action);
   1968     COMPILER_64_TO_32_HI(red_action[1], *r_action);
   1969 
   1970     switch (action) {
   1971         case bcmPolicerActionGpDrop:
   1972             if (param0 != 0) {
   1973                 LOG_ERROR(BSL_LS_BCM_POLICER,
   1974                          (BSL_META_U(unit,
   1975                                      "Invalid value for Drop\n")));
   1976                 return BCM_E_PARAM;
   1977             }
   1978             SHR_BITSET(green_action,
   1979                 GH2_POLICER_ACTION_DROP_BIT_POS);
   1980             break;
   1981         case bcmPolicerActionYpDrop:
   1982             if (param0 != 0) {
   1983                 LOG_ERROR(BSL_LS_BCM_POLICER,
   1984                          (BSL_META_U(unit,
   1985                                      "Invalid value for Drop\n")));
   1986                 return BCM_E_PARAM;
   1987             }
   1988             SHR_BITSET(yellow_action,
   1989                 GH2_POLICER_ACTION_DROP_BIT_POS);
   1990            break;
   1991         case bcmPolicerActionRpDrop:
   1992             if (param0 != 0) {
   1993                 LOG_ERROR(BSL_LS_BCM_POLICER,
   1994                          (BSL_META_U(unit,
   1995                                      "Invalid value for Drop\n")));
   1996                 return BCM_E_PARAM;
   1997             }
   1998             SHR_BITSET(red_action,
   1999                 GH2_POLICER_ACTION_DROP_BIT_POS);
   2000             break;
   2001         case bcmPolicerActionGpEcnNew:
   2002             if (param0 > 0x3) {
   2003                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2004                          (BSL_META_U(unit,
   2005                                      "Invalid value for ECN\n")));
   2006                 return BCM_E_PARAM;
   2007             }
   2008             /* GH2 merge CHANGE_ECN and NEW_ECN into CHANGE_ECN */
   2009             SHR_BITCLR_RANGE(green_action,
   2010                 GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS, 2);
   2011             green_action[0] = green_action[0] |
   2012                    (param0 << GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS);
   2013             break;
   2014         case bcmPolicerActionYpEcnNew:
   2015             if (param0 > 0x3) {
   2016                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2017                          (BSL_META_U(unit,
   2018                                      "Invalid value for ECN\n")));
   2019                 return BCM_E_PARAM;
   2020             }
   2021             /* GH2 merge CHANGE_ECN and NEW_ECN into CHANGE_ECN */
   2022             SHR_BITCLR_RANGE(yellow_action,
   2023                 GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS, 2);
   2024             yellow_action[0] = yellow_action[0] |
   2025                    (param0 << GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS);
   2026             break;
   2027         case bcmPolicerActionRpEcnNew:
   2028             if (param0 > 0x3) {
   2029                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2030                          (BSL_META_U(unit,
   2031                                      "Invalid value for ECN\n")));
   2032                 return BCM_E_PARAM;
   2033             }
   2034             /* GH2 merge CHANGE_ECN and NEW_ECN into CHANGE_ECN */
   2035             SHR_BITCLR_RANGE(red_action,
   2036                 GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS, 2);
   2037             red_action[0] = red_action[0] |
   2038                (param0 << GH2_POLICER_ACTION_CHANGE_ECN_BIT_POS);
   2039             break;
   2040         case bcmPolicerActionGpDscpNew:
   2041             if (param0 > 0x3f) {
   2042                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2043                          (BSL_META_U(unit,
   2044                                      "Invalid value for DSCP\n")));
   2045                 return BCM_E_PARAM;
   2046             }
   2047             SHR_BITCLR_RANGE(green_action,
   2048                 GH2_POLICER_ACTION_DSCP_BIT_POS, 6);
   2049             green_action[0] = green_action[0] |
   2050                 (param0 << GH2_POLICER_ACTION_DSCP_BIT_POS);
   2051 
   2052             /* CHANGE_DSCP_TOS = 3 for CHANGE_DSCP */
   2053             SHR_BITCLR_RANGE(green_action,
   2054                 GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS, 3);
   2055             green_action[0] = green_action[0] |
   2056                 (0x3 << GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS);
   2057 
   2058             break;
   2059         case bcmPolicerActionYpDscpNew:
   2060             if (param0 > 0x3f) {
   2061                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2062                          (BSL_META_U(unit,
   2063                                      "Invalid value for DSCP\n")));
   2064                 return BCM_E_PARAM;
   2065             }
   2066             SHR_BITCLR_RANGE(yellow_action,
   2067                 GH2_POLICER_ACTION_DSCP_BIT_POS, 6);
   2068             yellow_action[0] = yellow_action[0] |
   2069                 (param0 << GH2_POLICER_ACTION_DSCP_BIT_POS);
   2070 
   2071             /* CHANGE_DSCP_TOS = 3 for CHANGE_DSCP */
   2072             SHR_BITCLR_RANGE(yellow_action,
   2073                 GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS, 3);
   2074             yellow_action[0] = yellow_action[0] |
   2075                 (0x3 << GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS);
   2076             break;
   2077         case bcmPolicerActionRpDscpNew:
   2078             if (param0 > 0x3f) {
   2079                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2080                          (BSL_META_U(unit,
   2081                                      "Invalid value for DSCP\n")));
   2082                 return BCM_E_PARAM;
   2083             }
   2084             SHR_BITCLR_RANGE(red_action,
   2085                 GH2_POLICER_ACTION_DSCP_BIT_POS, 6);
   2086             red_action[0] = red_action[0] |
   2087                 (param0 << GH2_POLICER_ACTION_DSCP_BIT_POS);
   2088 
   2089             /* CHANGE_DSCP_TOS = 3 for CHANGE_DSCP */
   2090             SHR_BITCLR_RANGE(red_action,
   2091                 GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS, 3);
   2092             red_action[0] = red_action[0] |
   2093                 (0x3 << GH2_POLICER_ACTION_CHANGE_DSCP_BIT_POS);
   2094             break;
   2095         case bcmPolicerActionGpPrioIntNew:
   2096             if (param0 > 0xf) {
   2097                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2098                          (BSL_META_U(unit,
   2099                                      "Invalid value for int pri\n")));
   2100                 return BCM_E_PARAM;
   2101             }
   2102             /* COS_INT_PRI */
   2103             SHR_BITCLR_RANGE(green_action,
   2104                 GH2_POLICER_ACTION_INT_PRI_BIT_POS, 4);
   2105             green_action[0] = green_action[0] |
   2106                 (param0 <<
   2107                  GH2_POLICER_ACTION_INT_PRI_BIT_POS);
   2108             /* CHANGE_COS_OR_INT_PRI = 5 for CHANGE_INT_PRIORITY_NEW */
   2109             green_action[1] = green_action[1] |
   2110                 (0x5 << GH2_POLICER_ACTION_CHANGE_COS_OR_INT_PRI_BIT_POS);
   2111             break;
   2112         case bcmPolicerActionYpPrioIntNew:
   2113             if (param0 > 0xf) {
   2114                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2115                          (BSL_META_U(unit,
   2116                                      "Invalid value for int pri\n")));
   2117                 return BCM_E_PARAM;
   2118             }
   2119             /* COS_INT_PRI */
   2120             SHR_BITCLR_RANGE(yellow_action,
   2121                 GH2_POLICER_ACTION_INT_PRI_BIT_POS, 4);
   2122             yellow_action[0] = yellow_action[0] |
   2123                 (param0 <<
   2124                  GH2_POLICER_ACTION_INT_PRI_BIT_POS);
   2125             /* CHANGE_COS_OR_INT_PRI = 5 for CHANGE_INT_PRIORITY_NEW */
   2126             yellow_action[1] = yellow_action[1] |
   2127                 (0x5 << GH2_POLICER_ACTION_CHANGE_COS_OR_INT_PRI_BIT_POS);
   2128             break;
   2129         case bcmPolicerActionRpPrioIntNew:
   2130             if (param0 > 0xf) {
   2131                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2132                          (BSL_META_U(unit,
   2133                                      "Invalid value for int pri\n")));
   2134                 return BCM_E_PARAM;
   2135             }
   2136             /* COS_INT_PRI */
   2137             SHR_BITCLR_RANGE(red_action,
   2138                 GH2_POLICER_ACTION_INT_PRI_BIT_POS, 4);
   2139             red_action[0] = red_action[0] |
   2140                 (param0 <<
   2141                  GH2_POLICER_ACTION_INT_PRI_BIT_POS);
   2142             /* CHANGE_COS_OR_INT_PRI = 5 for CHANGE_INT_PRIORITY_NEW */
   2143             red_action[1] = red_action[1] |
   2144                 (0x5 << GH2_POLICER_ACTION_CHANGE_COS_OR_INT_PRI_BIT_POS);
   2145             break;
   2146         case bcmPolicerActionGpCngNew:
   2147             if (param0 > 0x3) {
   2148                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2149                          (BSL_META_U(unit,
   2150                                      "Invalid value for CNG\n")));
   2151                 return BCM_E_PARAM;
   2152             }
   2153             /* DROP_PRECEDENCE (other chip called CHANGE_CNG) */
   2154             SHR_BITCLR_RANGE(green_action,
   2155                 GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS, 2);
   2156             green_action[0] = green_action[0] |
   2157                 (param0 <<
   2158                  GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS);
   2159             break;
   2160         case bcmPolicerActionYpCngNew:
   2161             if (param0 > 0x3) {
   2162                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2163                          (BSL_META_U(unit,
   2164                                      "Invalid value for CNG\n")));
   2165                 return BCM_E_PARAM;
   2166             }
   2167             /* DROP_PRECEDENCE (other chip called CHANGE_CNG) */
   2168             SHR_BITCLR_RANGE(yellow_action,
   2169                 GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS, 2);
   2170             yellow_action[0] = yellow_action[0] |
   2171                 (param0 <<
   2172                  GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS);
   2173             break;
   2174         case bcmPolicerActionRpCngNew:
   2175             if (param0 > 0x3) {
   2176                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2177                          (BSL_META_U(unit,
   2178                                      "Invalid value for CNG\n")));
   2179                 return BCM_E_PARAM;
   2180             }
   2181             /* DROP_PRECEDENCE (other chip called CHANGE_CNG) */
   2182             SHR_BITCLR_RANGE(red_action,
   2183                 GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS, 2);
   2184             red_action[0] = red_action[0] |
   2185                 (param0 <<
   2186                  GH2_POLICER_ACTION_DROP_PRECEDENCE_BIT_POS);
   2187             break;
   2188         case bcmPolicerActionGpVlanPrioNew:
   2189             if (param0 > 0x7) {
   2190                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2191                          (BSL_META_U(unit,
   2192                                      "Invalid value for vlan pri\n")));
   2193                 return BCM_E_PARAM;
   2194             }
   2195             /* NEW_PKT_PRI */
   2196             SHR_BITCLR_RANGE(green_action,
   2197                 GH2_POLICER_ACTION_PKT_PRI_POS, 3);
   2198             green_action[0] = green_action[0] |
   2199                 (param0 <<
   2200                  GH2_POLICER_ACTION_PKT_PRI_POS);
   2201 
   2202             /* CHANGE_PKT_PRI = 5 for NEW_PKT_PRI */
   2203             SHR_BITCLR_RANGE(green_action,
   2204                 GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS, 3);
   2205             green_action[0] = green_action[0] |
   2206                 (0x5 << GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS);
   2207             break;
   2208         case bcmPolicerActionYpVlanPrioNew:
   2209             if (param0 > 0x7) {
   2210                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2211                          (BSL_META_U(unit,
   2212                                      "Invalid value for vlan pri\n")));
   2213                 return BCM_E_PARAM;
   2214             }
   2215             /* NEW_PKT_PRI */
   2216             SHR_BITCLR_RANGE(yellow_action,
   2217                 GH2_POLICER_ACTION_PKT_PRI_POS, 3);
   2218             yellow_action[0] = yellow_action[0] |
   2219                 (param0 <<
   2220                  GH2_POLICER_ACTION_PKT_PRI_POS);
   2221 
   2222             /* CHANGE_PKT_PRI = 5 for NEW_PKT_PRI */
   2223             SHR_BITCLR_RANGE(yellow_action,
   2224                 GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS, 3);
   2225             yellow_action[0] = yellow_action[0] |
   2226                 (0x5 << GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS);
   2227             break;
   2228         case bcmPolicerActionRpVlanPrioNew:
   2229             if (param0 > 0x7) {
   2230                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2231                          (BSL_META_U(unit,
   2232                                      "Invalid value for vlan pri\n")));
   2233                 return BCM_E_PARAM;
   2234             }
   2235             /* NEW_PKT_PRI */
   2236             SHR_BITCLR_RANGE(red_action,
   2237                 GH2_POLICER_ACTION_PKT_PRI_POS, 3);
   2238             red_action[0] = red_action[0] |
   2239                 (param0 <<
   2240                  GH2_POLICER_ACTION_PKT_PRI_POS);
   2241 
   2242             /* CHANGE_PKT_PRI = 5 for NEW_PKT_PRI */
   2243             SHR_BITCLR_RANGE(red_action,
   2244                 GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS, 3);
   2245             red_action[0] = red_action[0] |
   2246                 (0x5 << GH2_POLICER_ACTION_CHANGE_PKT_PRI_BIT_POS);
   2247             break;
   2248         case bcmPolicerActionGpIntCongestionNotificationNew:
   2249             if (param0 > 0x3) {
   2250                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2251                          (BSL_META_U(unit,
   2252                                      "Invalid value for "
   2253                                      "Congestion Notification\n")));
   2254                 return BCM_E_PARAM;
   2255             }
   2256             SHR_BITCLR_RANGE(green_action,
   2257                 GH2_POLICER_ACTION_INT_CN_BIT_POS, 2);
   2258             green_action[0] = green_action[0] |
   2259                 (param0 << GH2_POLICER_ACTION_INT_CN_BIT_POS);
   2260 
   2261             /* CHANGE_INT_CN = 1 for NEW_INT_CN */
   2262             green_action[0] = green_action[0] |
   2263                 (0x1 << GH2_POLICER_ACTION_CHANGE_INT_CN_BIT_POS);
   2264             break;
   2265         case bcmPolicerActionYpIntCongestionNotificationNew:
   2266             if (param0 > 0x3) {
   2267                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2268                          (BSL_META_U(unit,
   2269                                      "Invalid value for "
   2270                                      "Congestion Notification\n")));
   2271                 return BCM_E_PARAM;
   2272             }
   2273             SHR_BITCLR_RANGE(yellow_action,
   2274                 GH2_POLICER_ACTION_INT_CN_BIT_POS, 2);
   2275             yellow_action[0] = yellow_action[0] |
   2276                 (param0 << GH2_POLICER_ACTION_INT_CN_BIT_POS);
   2277 
   2278             /* CHANGE_INT_CN = 1 for NEW_INT_CN */
   2279             yellow_action[0] = yellow_action[0] |
   2280                 (0x1 << GH2_POLICER_ACTION_CHANGE_INT_CN_BIT_POS);
   2281             break;
   2282         case bcmPolicerActionRpIntCongestionNotificationNew:
   2283             if (param0 > 0x3) {
   2284                 LOG_ERROR(BSL_LS_BCM_POLICER,
   2285                          (BSL_META_U(unit,
   2286                                      "Invalid value for "
   2287                                      "Congestion Notification\n")));
   2288                 return BCM_E_PARAM;
   2289             }
   2290             SHR_BITCLR_RANGE(red_action,
   2291                 GH2_POLICER_ACTION_INT_CN_BIT_POS, 2);
   2292             red_action[0] = red_action[0] |
   2293                 (param0 << GH2_POLICER_ACTION_INT_CN_BIT_POS);
   2294 
   2295             /* CHANGE_INT_CN = 1 for NEW_INT_CN */
   2296             red_action[0] = red_action[0] |
   2297                 (0x1 << GH2_POLICER_ACTION_CHANGE_INT_CN_BIT_POS);
   2298             break;
   2299         default:
   2300             LOG_ERROR(BSL_LS_BCM_POLICER,
   2301                       (BSL_META_U(unit,
   2302                                   "Unsupported Action specified\n")));
   2303             return BCM_E_PARAM;
   2304     }
   2305 
   2306     COMPILER_64_SET(*g_action, green_action[1], green_action[0]);
   2307     COMPILER_64_SET(*y_action, yellow_action[1], yellow_action[0]);
   2308     COMPILER_64_SET(*r_action, red_action[1], red_action[0]);
   2309     return BCM_E_NONE;
   2310 }
   2311 
   2312 /*
   2313  * Function:
   2314  *  bcmi_gh2_global_meter_policy_action_set
   2315  * Purpose:
   2316  *  Update (Install) the policer action parameters
   2317  * Parameters:
   2318  *  unit     - (IN) BCM device number.
   2319  *  g_action - (IN) Green action
   2320  *  y_action - (IN) Yellow action
   2321  *  r_action - (IN) Red action
   2322  * Returns:
   2323  *  BCM_E_XXX
   2324  */
   2325 STATIC int
   2326 bcmi_gh2_global_meter_policy_action_set(
   2327     int unit,
   2328     uint32 sw_idx,
   2329     uint64 g_action,
   2330     uint64 y_action,
   2331     uint64 r_action)
   2332 {
   2333     int rv = BCM_E_NONE;
   2334     uint32 hw_idx = sw_idx;
   2335     soc_mem_t policy_mem = SVM_POLICY_TABLEm;
   2336     svm_policy_table_entry_t policy_entry;
   2337 
   2338     GH2_POL_FUNCTION_TRACE(unit, "IN");
   2339     GH2_POL_FUNCTION_DEBUG(unit, "sw_idx %d", sw_idx);
   2340     GH2_POL_FUNCTION_DEBUG(unit, "Green H 0x%x", COMPILER_64_HI(g_action));
   2341     GH2_POL_FUNCTION_DEBUG(unit, "Green L 0x%x", COMPILER_64_LO(g_action));
   2342     GH2_POL_FUNCTION_DEBUG(unit, "Yellow H 0x%x", COMPILER_64_HI(y_action));
   2343     GH2_POL_FUNCTION_DEBUG(unit, "Yellow L 0x%x", COMPILER_64_LO(y_action));
   2344     GH2_POL_FUNCTION_DEBUG(unit, "Red H 0x%x", COMPILER_64_HI(r_action));
   2345     GH2_POL_FUNCTION_DEBUG(unit, "Red L 0x%x", COMPILER_64_LO(r_action));
   2346 
   2347     /* Validate hw_idx */
   2348     if (hw_idx > soc_mem_index_max(unit, policy_mem)) {
   2349         LOG_ERROR(BSL_LS_BCM_POLICER,
   2350                   (BSL_META_U(unit,
   2351                               "Invalid hw_idx \n")));
   2352         return BCM_E_PARAM;
   2353     }
   2354 
   2355     sal_memset(&policy_entry, 0,
   2356                sizeof(svm_policy_table_entry_t));
   2357 
   2358     BCM_IF_ERROR_RETURN(
   2359         READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, hw_idx, &policy_entry));
   2360 
   2361     soc_mem_field64_set(unit, policy_mem, &policy_entry, G_ACTIONSf, g_action);
   2362     soc_mem_field64_set(unit, policy_mem, &policy_entry, Y_ACTIONSf, y_action);
   2363     soc_mem_field64_set(unit, policy_mem, &policy_entry, R_ACTIONSf, r_action);
   2364 
   2365     BCM_IF_ERROR_RETURN(
   2366         WRITE_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ALL, hw_idx, &policy_entry));
   2367 
   2368     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   2369     return rv;
   2370 }
   2371 
   2372 /*
   2373  * Function:
   2374  *  bcmi_gh2_global_meter_policy_action_get
   2375  * Purpose:
   2376  *  Get the policer action parameters
   2377  * Parameters:
   2378  *  unit     - (IN) BCM device number.
   2379  *  g_action - (OUT) Green action
   2380  *  y_action - (OUT) Yellow action
   2381  *  r_action - (OUT) Red action
   2382  * Returns:
   2383  *  BCM_E_XXX
   2384  */
   2385 STATIC int
   2386 bcmi_gh2_global_meter_policy_action_get(
   2387     int unit,
   2388     uint32 sw_idx,
   2389     uint64 *g_action,
   2390     uint64 *y_action,
   2391     uint64 *r_action)
   2392 {
   2393     int rv = BCM_E_NONE;
   2394     uint32 hw_idx = sw_idx;
   2395     soc_mem_t policy_mem = SVM_POLICY_TABLEm;
   2396     svm_policy_table_entry_t policy_entry;
   2397 
   2398     GH2_POL_FUNCTION_TRACE(unit, "IN");
   2399 
   2400     /* Parameter NULL error handling */
   2401     GH2_POL_CHECK_NULL_PARAMETER(unit, g_action);
   2402     GH2_POL_CHECK_NULL_PARAMETER(unit, y_action);
   2403     GH2_POL_CHECK_NULL_PARAMETER(unit, r_action);
   2404 
   2405     /* Validate hw_idx */
   2406     if (hw_idx > soc_mem_index_max(unit, policy_mem)) {
   2407         GH2_POL_FUNCTION_ERROR(unit, "Invalid hw_idx (%d) \n", hw_idx);
   2408         return BCM_E_PARAM;
   2409     }
   2410 
   2411     sal_memset(&policy_entry, 0,
   2412                sizeof(svm_policy_table_entry_t));
   2413 
   2414     BCM_IF_ERROR_RETURN(
   2415         READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, hw_idx, &policy_entry));
   2416     soc_mem_field64_get(
   2417         unit, policy_mem, &policy_entry, G_ACTIONSf, g_action);
   2418     soc_mem_field64_get(
   2419         unit, policy_mem, &policy_entry, Y_ACTIONSf, y_action);
   2420     soc_mem_field64_get(
   2421         unit, policy_mem, &policy_entry, R_ACTIONSf, r_action);
   2422 
   2423     GH2_POL_FUNCTION_DEBUG(unit, "sw_idx %d", sw_idx);
   2424     GH2_POL_FUNCTION_DEBUG(unit, "Green H 0x%x", COMPILER_64_HI(*g_action));
   2425     GH2_POL_FUNCTION_DEBUG(unit, "Green L 0x%x", COMPILER_64_LO(*g_action));
   2426     GH2_POL_FUNCTION_DEBUG(unit, "Yellow H 0x%x", COMPILER_64_HI(*y_action));
   2427     GH2_POL_FUNCTION_DEBUG(unit, "Yellow L 0x%x", COMPILER_64_LO(*y_action));
   2428     GH2_POL_FUNCTION_DEBUG(unit, "Red H 0x%x", COMPILER_64_HI(*r_action));
   2429     GH2_POL_FUNCTION_DEBUG(unit, "Red L 0x%x", COMPILER_64_LO(*r_action));
   2430     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   2431     return rv;
   2432 }
   2433 
   2434 STATIC const bcmi_global_meter_dev_info_t bcmi_gh2_global_meter_dev_info = {
   2435     "gh2_global_meter_dev_info",                    /* table_name */
   2436     bcmi_gh2_action_supported,                      /* action_supported */
   2437     bcmi_gh2_group_mode_supported,                  /* group_mode_supported */
   2438     bcmi_gh2_group_mode_type_supported,        /* group_mode_type_supported */
   2439     bcmi_gh2_group_mode_attr_supported,        /* group_mode_attr_supported */
   2440     bcmi_gh2_group_mode_attr_validate,          /* group_mode_attr_validate */
   2441     bcmi_gh2_global_meter_mem_clear,                /* mem_clear */
   2442     bcmi_gh2_global_meter_mem_range_clear,          /* mem_range_clear */
   2443     bcmi_gh2_global_meter_ifg_set,                  /* ifg_set */
   2444     bcmi_gh2_global_meter_ifg_get,                  /* ifg_get */
   2445     bcmi_gh2_global_meter_source_order_set,         /* source_order_set */
   2446     bcmi_gh2_global_meter_source_order_get,         /* source_order_get */
   2447     bcmi_gh2_global_meter_enable,                   /* svm_enable */
   2448     bcmi_gh2_global_meter_enable_get,               /* svm_enable_get */
   2449     bcmi_gh2_global_meter_seop_enable,              /* seop_enable */
   2450     bcmi_gh2_global_meter_seop_enable_get,          /* seop_enable_get */
   2451     bcmi_gh2_global_meter_tcam_keys_set,            /* tcam_keys_set */
   2452     bcmi_gh2_global_meter_tcam_keys_get,            /* tcam_keys_get */
   2453     bcmi_gh2_global_meter_tcam_keys_delete,         /* tcam_keys_delete */
   2454     bcmi_gh2_global_meter_policer_to_table_set,     /* policer_to_table_set */
   2455     bcmi_gh2_global_meter_policer_to_table_get,     /* policer_to_table_get */
   2456     bcmi_gh2_global_meter_meter_table_bitsize_get,/* meter_table_bitsize_get */
   2457     bcmi_gh2_global_meter_meter_table_set,          /* meter_table_set */
   2458     bcmi_gh2_global_meter_meter_table_get,          /* meter_table_get */
   2459     bcmi_gh2_global_meter_policy_mode_set,          /* policy_mode_set */
   2460     bcmi_gh2_global_meter_policy_mode_get,          /* policy_mode_get */
   2461     bcmi_gh2_global_meter_policy_action_param_configure,
   2462                                         /* policy_action_param_configure */
   2463     bcmi_gh2_global_meter_policy_action_set,        /* policy_action_set */
   2464     bcmi_gh2_global_meter_policy_action_get         /* policy_action_get */
   2465 };
   2466 
   2467 /*
   2468  * Function:
   2469  *  bcmi_gh2_global_meter_dev_info_init
   2470  * Description:
   2471  *  Set-up the chip specific info.
   2472  * Parameters:
   2473  *  unit    - (IN) Unit number.
   2474  *  dev_info - (OUT) device info structure.
   2475  * Returns:
   2476  *  BCM_E_XXX
   2477  */
   2478 int
   2479 bcmi_gh2_global_meter_dev_info_init(
   2480     int unit,
   2481     const bcmi_global_meter_dev_info_t **dev_info)
   2482 {
   2483     GH2_POL_FUNCTION_TRACE(unit, "IN");
   2484 
   2485     /* Parameter NULL error handling */
   2486     GH2_POL_CHECK_NULL_PARAMETER(unit, dev_info);
   2487 
   2488     /* Return the chip info structure */
   2489     *dev_info = &bcmi_gh2_global_meter_dev_info;
   2490 
   2491     GH2_POL_FUNCTION_TRACE(unit, "OUT");
   2492     return BCM_E_NONE;
   2493 }
   2494 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
   2495 #endif /* BCM_GREYHOUND2_SUPPORT */
   2496 
   2497 
   2498