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 (1043208B)


      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  * All Rights Reserved.$
      9  *
     10  * Module: Service Meter(global meter)
     11  *
     12  * Purpose:
     13  *     These routines manage the handling of service meter(global meter)
     14  *      functionality
     15  */
     16 #include <shared/bsl.h>
     17 #include <shared/idxres_afl.h>
     18 
     19 #include <sal/core/libc.h>
     20 
     21 #include <soc/defs.h>
     22 #include <soc/scache.h>
     23 
     24 #include <bcm/policer.h>
     25 #include <bcm/module.h>
     26 #include <bcm_int/esw/policer.h>
     27 #include <bcm_int/esw/port.h>
     28 #include <bcm_int/esw/vlan.h>
     29 #include <bcm_int/esw/firebolt.h>
     30 #include <bcm_int/esw/switch.h>
     31 #include <bcm_int/esw_dispatch.h>
     32 #include <bcm_int/esw/field.h>
     33 #include <bcm_int/esw/xgs4.h>
     34 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(BCM_FIELD_SUPPORT)
     35 #include <bcm/field.h>
     36 #endif
     37 
     38 #if defined(BCM_GREYHOUND2_SUPPORT)
     39 #include <bcm_int/esw/greyhound2.h>
     40 #endif /* BCM_GREYHOUND2_SUPPORT */
     41 
     42 #ifdef BCM_WARM_BOOT_SUPPORT
     43 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     44 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
     45 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
     46 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
     47 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_3
     48 #endif
     49 
     50 #define _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER _BCM_XGS_METER_FLAG_FP_POLICER
     51 
     52 
     53 #define UNKNOWN_PKT                 0x00
     54 #define CONTROL_PKT                 0x01
     55 #define OAM_PKT                     0x02
     56 #define BFD_PKT                     0x03
     57 #define BPDU_PKT                    0x04
     58 #define ICNM_PKT                    0x05
     59 #define PKT_IS_1588                 0x06
     60 #define KNOWN_L2UC_PKT              0x07
     61 
     62 #define UNKNOWN_L2UC_PKT            0x08
     63 #define KNOWN_L2MC_PKT              0x09
     64 #define UNKNOWN_L2MC_PKT            0x0a
     65 #define L2BC_PKT                    0x0b
     66 #define KNOWN_L3UC_PKT              0x0c
     67 #define UNKNOWN_L3UC_PKT            0x0d
     68 #define KNOWN_IPMC_PKT              0x0e
     69 #define UNKNOWN_IPMC_PKT            0x0f
     70 
     71 #define KNOWN_MPLS_L2_PKT           0x10
     72 #define UNKNOWN_MPLS_PKT            0x11
     73 #define KNOWN_MPLS_L3_PKT           0x12
     74 #define KNOWN_MPLS_PKT              0x13
     75 #define KNOWN_MPLS_MULTICAST_PKT    0x14
     76 #define KNOWN_MIM_PKT               0x15
     77 #define UNKNOWN_MIM_PKT             0x16
     78 #define KNOWN_TRILL_PKT             0x17
     79 
     80 #define UNKNOWN_TRILL_PKT           0x18
     81 #define KNOWN_NIV_PKT               0x19
     82 #define UNKNOWN_NIV_PKT             0x1a
     83 #define KNOWN_L2GRE_PKT             0x1b
     84 #define KNOWN_VDL2_PKT              0x1c
     85 #define KNOWN_FCOE_PKT              0x1d
     86 #define UNKNOWN_FCOE_PKT            0x1e
     87 #define SAT_DN_SAMP_RX              0x1f
     88 #define FP_RESOLUTION_MAX           0x20  /* Max value */
     89 
     90 #define METER_REFRESH_INTERVAL      8     /* 7.8125usec */
     91 #define MIN_BURST_MULTIPLE          2
     92 
     93 #define CONVERT_SECOND_TO_MICROSECOND 1000000
     94 
     95 static soc_reg_t _pkt_attr_sel_key_reg[4] = {
     96                 ING_SVM_PKT_ATTR_SELECTOR_KEY_0r,
     97                 ING_SVM_PKT_ATTR_SELECTOR_KEY_1r,
     98                 ING_SVM_PKT_ATTR_SELECTOR_KEY_2r,
     99                 ING_SVM_PKT_ATTR_SELECTOR_KEY_3r
    100             };
    101 
    102 STATIC sal_mutex_t global_meter_mutex[BCM_MAX_NUM_UNITS] = {NULL};
    103 
    104 /* Refer to FP_RESOLUTION */
    105 static uint8 kt_pkt_res[FP_RESOLUTION_MAX] =
    106                               {
    107                                    0x0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x4,
    108                                    0x5, 0x8, 0x9, 0x3, 0xa, 0xb, 0x7, 0x6,
    109                                    0xe, 0xf, 0xd, 0xc, 0x12, 0x10, 0x11, 0,
    110                                    0, 0, 0, 0, 0, 0, 0, 0
    111                                };
    112 #ifdef BCM_TRIUMPH3_SUPPORT
    113 static uint8 tr3_pkt_res[FP_RESOLUTION_MAX] =
    114                           {
    115                                0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x8,
    116                                0x9, 0xa, 0xb, 0xc, 0x10, 0x11, 0x12, 0x13,
    117                                0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21, 0x28,
    118                                0x29, 0x30, 0x31, 0, 0, 0, 0, 0
    119                           };
    120 #endif
    121 #ifdef BCM_KATANA2_SUPPORT
    122 static uint8 kt2_pkt_res[FP_RESOLUTION_MAX] =
    123                           {
    124                                0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,   0x8,
    125                                0x9,  0xa,  0xb,  0xc,  0x10, 0x11, 0x12,  0x13,
    126                                0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21,  0x28,
    127                                0x29, 0x30, 0x31, 0,    0,    0,    0,     0
    128                           };
    129 #endif
    130 #ifdef BCM_SABER2_SUPPORT
    131 static uint8 sb2_pkt_res[FP_RESOLUTION_MAX] =
    132                           {
    133                                0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,   0x8,
    134                                0x9,  0xa,  0xb,  0xc,  0x10, 0x11, 0x12,  0x13,
    135                                0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21,  0x28,
    136                                0x29, 0x30, 0x31, 0,    0,    0,    0,     0x32
    137                           };
    138 #endif
    139 #ifdef BCM_APACHE_SUPPORT
    140 static uint8 ap_pkt_res[FP_RESOLUTION_MAX] =
    141                           {
    142                                0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,   0x8,
    143                                0x9,  0xa,  0xb,  0xc,  0x10, 0x11, 0x12,  0x13,
    144                                0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21,  0x28,
    145                                0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,  0x00
    146                           };
    147 #endif
    148 
    149 static uint32 refresh_max[] =  { 100, 125, 150, 175,
    150                                  200, 225, 250, 275,
    151                                  300, 325, 350, 375,
    152                                  400, 425, 450, 475,
    153                                  500, 525, 550, 575,
    154                                  600, 625, 650, 675,
    155                                  700, 725, 750, 775,
    156                                  800, 0 };
    157 
    158 
    159 typedef enum pkt_cmprsd_attr_map_e {
    160     pkt_attr_pri_cng_map,
    161     pkt_attr_pkt_pri_map,
    162     pkt_attr_port_map,
    163     pkt_attr_tos_map,
    164     pkt_attr_pkt_res_map,
    165     pkt_attr_ip_pkt_map, /* no map for IP_PKT in h/w */
    166     pkt_attr_map_count
    167 } pkt_cmprsd_attrs_map_t;
    168 
    169 static _bcm_policer_pkt_attr_bit_pos_t  kt_pkt_cmprsd_attr_map_bit_pos[] =  {
    170                                        {32,37}, {24,31}, {17,23}, {9,16},
    171                                        {1,8}, {0,0}
    172                                   };
    173 #ifdef BCM_KATANA2_SUPPORT
    174 static _bcm_policer_pkt_attr_bit_pos_t kt2_pkt_cmprsd_attr_map_bit_pos[] =  {
    175                                        {33,38}, {25,32}, {17,24}, {9,16},
    176                                        {1,8}, {0,0}
    177                                   };
    178 #endif
    179 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_SABER2_SUPPORT)
    180 static _bcm_policer_pkt_attr_bit_pos_t sb2_pkt_cmprsd_attr_map_bit_pos[] =  {
    181                                        {32,37}, {24,31}, {17,23}, {9,16},
    182                                        {1,8}, {0,0}
    183                                   };
    184 #endif
    185 
    186 /*
    187  * Global meter policer control data, one per device.
    188 */
    189 static _global_meter_policer_control_t
    190                     **global_meter_policer_bookkeep[BCM_MAX_NUM_UNITS];
    191 /*
    192  * Global meter horizontal alloc management data, one per device.
    193  */
    194 static _global_meter_horizontal_alloc_t
    195               *global_meter_hz_alloc_bookkeep[BCM_MAX_NUM_UNITS];
    196 
    197 static bcm_policer_svc_meter_bookkeep_mode_t
    198       global_meter_offset_mode[BCM_MAX_NUM_UNITS]\
    199                               [BCM_POLICER_SVC_METER_MAX_MODE];
    200 
    201 /*
    202  * Global meter packet compressed attributes maps information per device.
    203  */
    204 static _bcm_policer_pkt_compressed_attr_maps_t
    205       *svm_pkt_compressed_attr_maps_g[BCM_MAX_NUM_UNITS];
    206 
    207 static _bcm_policer_global_meter_control_t
    208       *bcm_esw_svm_control[BCM_MAX_NUM_UNITS];
    209 
    210 #define BCM_SVM_DEV_ATTR(unit)      (&(bcm_esw_svm_control[(unit)]->svm_dev_attr_info))
    211 #define BCM_SVM_SOURCE(unit, index) (bcm_esw_svm_control[(unit)]->svm_source[(index)])
    212 
    213 static bcm_policer_global_meter_action_bookkeep_t
    214           *global_meter_action_bookkeep[BCM_MAX_NUM_UNITS];
    215 
    216 /* Global meter module status - initialised or not initilised */
    217 static bcm_policer_global_meter_init_status_t
    218                         global_meter_status[BCM_MAX_NUM_UNITS] = {{0}};
    219 /*
    220  * Global meter resource lock
    221  */
    222 #define GLOBAL_METER_LOCK(unit) \
    223         sal_mutex_take(global_meter_mutex[unit], sal_mutex_FOREVER);
    224 
    225 #define GLOBAL_METER_UNLOCK(unit) \
    226         sal_mutex_give(global_meter_mutex[unit]);
    227 
    228 /* Handles for indexed allocation - one for meter action id allocation
    229    and the other for policer id alloaction  */
    230 shr_aidxres_list_handle_t
    231           meter_action_list_handle[BCM_UNITS_MAX] = {NULL};
    232 shr_aidxres_list_handle_t  meter_alloc_list_handle[BCM_UNITS_MAX]\
    233           [BCM_POLICER_GLOBAL_METER_MAX_POOL * \
    234           BCM_POLICER_GLOBAL_METER_MAX_BANKS_PER_POOL] = {{NULL}};
    235 
    236 #define CHECK_GLOBAL_METER_INIT(unit)                            \
    237     do {                                                         \
    238         if (!global_meter_status[unit].initialised) {            \
    239             LOG_ERROR(BSL_LS_BCM_POLICER,                        \
    240                       (BSL_META_U(unit,                          \
    241                                   "Global Meter Error:"          \
    242                                   " not initialized\n")));       \
    243             return BCM_E_INIT;                                   \
    244         }                                                        \
    245     } while (0)
    246 
    247 /* Parameter NULL error handling */
    248 #define POL_CHECK_NULL_PARAMETER(_u_, _parameter_)               \
    249     do {                                                         \
    250         if (NULL == (_parameter_)) {                             \
    251             LOG_ERROR(BSL_LS_BCM_POLICER,                        \
    252                       (BSL_META_U((_u_),                         \
    253                                   "Error: NULL parameter\n")));  \
    254             return BCM_E_PARAM;                                  \
    255         }                                                        \
    256     } while (0)
    257 
    258 /* Device Information NULL error handling */
    259 #define POL_CHECK_NULL_DEV_INSTANCE(_u_, _instance_)                          \
    260     do {                                                                      \
    261         if (NULL == (_instance_)) {                                           \
    262             LOG_ERROR(BSL_LS_BCM_POLICER,                                     \
    263                       (BSL_META_U((_u_),                                      \
    264                                   "Error: NULL driver function \n")));        \
    265             return BCM_E_UNAVAIL;                                             \
    266         }                                                                     \
    267     } while (0)
    268 
    269 /* Function Enter/Leave Tracing */
    270 #define POL_FUNCTION_TRACE(_u_, _str_)                                        \
    271     do {                                                                      \
    272         LOG_VERBOSE(BSL_LS_BCM_POLICER,                                       \
    273                     (BSL_META_U((_u_),                                        \
    274                                 "%s: " _str_ "\n"), __FUNCTION__));           \
    275     } while (0)
    276 
    277 /* Function VERBOSE Tracing */
    278 #define POL_FUNCTION_DEBUG(_u_, fmt, _args_)                                  \
    279     do {                                                                      \
    280         LOG_DEBUG(BSL_LS_BCM_POLICER,                                         \
    281                   (BSL_META_U((_u_),                                          \
    282                               "%s: " fmt "\n"), __FUNCTION__, _args_));       \
    283     } while (0)
    284 
    285 #define POL_MEM_ALLOC _GLOBAL_METER_XGS3_ALLOC
    286 
    287 #define POL_MEM_FREE(_mem_)                                      \
    288     do {                                                         \
    289         if (NULL != (_mem_)) {                                   \
    290             sal_free(_mem_);                                     \
    291             (_mem_) = NULL;                                      \
    292         }                                                        \
    293     } while (0)
    294 
    295 /* Convenient macro: get log2 for a non-zero power-of-2 number */
    296 #define POL_GET_LOG2(_n_, _power_)                                          \
    297     do {                                                                    \
    298         unsigned int _num = (unsigned int)(_n_);                            \
    299         for ((_power_) = -1; _num; (_power_)++) {                           \
    300             _num >>= 1;                                                     \
    301         }                                                                   \
    302     } while (0)
    303 
    304 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
    305 #ifdef BCM_WARM_BOOT_SUPPORT
    306 typedef struct bcm_policer_config_wb_s {
    307     uint32 flags;                       /* BCM_POLICER_* Flags. */
    308     bcm_policer_mode_t mode;            /* Policer mode. */
    309     uint32 ckbits_sec;                  /* Committed rate (kbits per sec). */
    310     uint32 cbits_sec_lower;             /* Committed rate (lower digits; 0~999
    311                                            bits per sec). */
    312     uint32 max_ckbits_sec;              /* Maximum Committed rate (kbits per
    313                                            sec), Applicable only for cascade
    314                                            mode. */
    315     uint32 max_cbits_sec_lower;         /* Maximum Committed rate (lower
    316 digits;
    317                                            0~999 bits per sec). */
    318     uint32 ckbits_burst;                /* Committed burst size (kbits). */
    319     uint32 cbits_burst_lower;           /* Committed burst size (lower digits;
    320                                            0~999 bits). */
    321     uint32 pkbits_sec;                  /* Peak rate (kbits per sec). */
    322     uint32 pbits_sec_lower;             /* Peak rate (lower digits; 0~999 bits
    323                                            per sec). */
    324     uint32 max_pkbits_sec;              /* Maximum Peak rate (kbits per sec),
    325                                            Applicable only for cascade mode. */
    326     uint32 max_pbits_sec_lower;         /* Maximum Peak rate (lower digits;
    327                                            0~999 bits per sec). */
    328     uint32 pkbits_burst;                /* Peak burst size (kbits). */
    329     uint32 pbits_burst_lower;           /* Peak burst size (lower digits; 0~999
    330                                            bits). */
    331     uint32 kbits_current;               /* Current size (kbits). */
    332     uint32 bits_current_lower;          /* Current size (lower digits; 0~999
    333                                            bits). */
    334     uint32 action_id;                   /* Index of the global meter action
    335                                            entry */
    336     uint32 sharing_mode;                /* Meter sharing mode in case of Macro
    337                                            meter of Envelop */
    338     uint32 entropy_id;                  /* If set, indicate the configuration
    339                                            group the policer belongs to */
    340     bcm_policer_pool_t pool_id;         /* Meter Pool Id of the current
    341 policer */
    342     uint32 bucket_width;                /* Bucket width in bits of the current
    343                                            policer */
    344     uint32 token_gran;                  /* Token granularity of the current
    345                                            policer */
    346     uint32 bucket_init_val;             /* Initial bucket count of the current
    347                                            policer */
    348     uint32 bucket_rollover_val;         /* Rollover bucket count of the current
    349                                            policer */
    350     bcm_core_t core_id;                 /* Device core on which to allocate the
    351                                            policer */
    352     bcm_policer_t ncoflow_policer_id;   /* Next lower priority committed
    353 policer
    354                                            ID to overflow to. Applicable in
    355                                            Cascaded  policer modes on MEF 10.3+
    356                                            compliant devices */
    357     bcm_policer_t npoflow_policer_id;   /* Next lower priority peak policer ID
    358                                            to overflow to. Applicable in
    359                                            Cascaded and CoupledCascade policer
    360                                            modes on MEF 10.3+  compliant
    361 devices */
    362     uint32 average_pkt_size;            /* Estimated average Ethernet packet
    363                                            size (1 to 16383 Bytes) for more
    364                                            accurate metering. */
    365     int mark_drop_as_black;             /* For drop decision (no committed or
    366                                            Excess credits), mark it as black
    367                                            (otherwise, it will be marked as
    368                                            red). */
    369     int color_resolve_profile;          /* Input data for the resolved table.
    370 */
    371 } bcm_policer_config_wb_t;
    372 #endif /* BCM_WARM_BOOT_SUPPORT */
    373 
    374 #define BCMI_GLOBAL_METER_HASH_SIZE                  (0x100)
    375 #define BCMI_GLOBAL_METER_HASH_MASK                  (0xff)
    376 #define BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES (2048)
    377 #define BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY  (8)
    378 #define BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY (4)
    379 #define BCMI_POLICER_METER_GRAN_SHFIT                (8)
    380 #define BCMI_POLICER_METER_GRAN_LOWER_UNIT           (1000)
    381 #define BCMI_POLICER_INVALID_POLICER_ID              (0)
    382 
    383 #define BCMI_POLICER_SVC_METER_TCAM_SIZE \
    384     SOC_INFO(unit).global_meter_tcam_size
    385 
    386 #define BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE \
    387     SOC_INFO(unit).global_meter_offset_mode_max
    388 
    389 #define BCMI_POLICER_SVC_METER_ACTION_SIZE \
    390     SOC_INFO(unit).global_meter_action_size
    391 
    392 #define BCMI_POLICER_SVC_METER_POOL_SIZE \
    393     SOC_INFO(unit).global_meter_size_of_pool
    394 
    395 /* Global Meter platform-specific information */
    396 STATIC const bcmi_global_meter_dev_info_t
    397     *bcmi_global_meter_dev_info[BCM_MAX_NUM_UNITS];
    398 
    399 /* Initialization flag for bcmi_global_meter_dev_info_t info structure */
    400 STATIC int
    401     bcmi_global_meter_dev_info_initialized = FALSE;
    402 
    403 #define BCM_SVM_DEV_INFO_GET(_u_) (bcmi_global_meter_dev_info[(_u_)])
    404 
    405 #define CHECK_GLOBAL_METER_DEV_INFO_INIT(_u_)                  \
    406     do {                                                       \
    407         if (!soc_feature(unit, soc_feature_global_meter_v2)) { \
    408             return BCM_E_UNAVAIL;                              \
    409         }                                                      \
    410         if (!BCM_SVM_DEV_INFO_GET(_u_)) {                      \
    411             return BCM_E_UNAVAIL;                              \
    412         }                                                      \
    413     } while (0)
    414 
    415 typedef struct pkt_res_final_offset_s {
    416     uint8 final_offset;
    417     bcm_policer_group_mode_attr_pkt_type_t attr_pkt_type;
    418 }pkt_res_final_offset_t;
    419 
    420 static bcmi_global_meter_policer_control_t
    421     **global_meter_policer_bk[BCM_MAX_NUM_UNITS];
    422 
    423 static bcmi_policer_global_meter_action_bk_t
    424     *global_meter_action_bk[BCM_MAX_NUM_UNITS];
    425 
    426 shr_aidxres_list_handle_t
    427     action_list_handle[BCM_MAX_NUM_UNITS] = { NULL };
    428 shr_aidxres_list_handle_t
    429     policer_list_handle[BCM_MAX_NUM_UNITS] = { NULL };
    430 
    431 #define BCMI_POLICER_BK_GET(_u_) \
    432     (global_meter_policer_bk[(_u_)])
    433 
    434 #define BCMI_POLICER_HASH_BK_GET(_u_, _hash_) \
    435     (global_meter_policer_bk[(_u_)][(_hash_)])
    436 
    437 #define BCMI_ACTION_BK_GET(_u_) \
    438     (global_meter_action_bk[(_u_)])
    439 
    440 #define BCMI_ACTION_ID_BK_GET(_u_, _action_id_) \
    441     (global_meter_action_bk[(_u_)][(_action_id_)])
    442 
    443 #define BCMI_ACTION_LIST_HANDLE_GET(_u_) \
    444     (action_list_handle[(_u_)])
    445 
    446 #define BCMI_POLICER_LIST_HANDLE_GET(_u_) \
    447     (policer_list_handle[(_u_)])
    448 
    449 static bcmi_policer_svm_bk_t bcmi_bk_svm[BCM_MAX_NUM_UNITS];
    450 
    451 #define GLOBAL_METER_BK_LOCK(unit) \
    452         sal_mutex_take(bcmi_bk_svm[unit].mutex, sal_mutex_FOREVER);
    453 
    454 #define GLOBAL_METER_BK_UNLOCK(unit) \
    455         sal_mutex_give(bcmi_bk_svm[unit].mutex);
    456 
    457 #define BCMI_SVM_BK_GET(_u_) \
    458     (&bcmi_bk_svm[(_u_)])
    459 #define BCMI_SVM_OFFSET_MODE_BK_GET(_u_, _offset_mode_) \
    460     (&bcmi_bk_svm[(_u_)].offset_mode_v[_offset_mode_])
    461 
    462 /* SVM TCAM usage bitmap operations */
    463 #define BCMI_SVM_TCAM_INTF_GET(_u_, _intf_) \
    464         SHR_BITGET(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_))
    465 #define BCMI_SVM_TCAM_INTF_SET(_u_, _intf_) \
    466         SHR_BITSET(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_))
    467 #define BCMI_SVM_TCAM_INTF_CLR(_u_, _intf_) \
    468         SHR_BITCLR(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_))
    469 
    470 /* SVM Offset Mode usage bitmap operations */
    471 #define BCMI_OFFSET_MODE_ID_INTF_GET(_u_, _intf_) \
    472         SHR_BITGET(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_))
    473 #define BCMI_OFFSET_MODE_ID_INTF_SET(_u_, _intf_) \
    474         SHR_BITSET(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_))
    475 #define BCMI_OFFSET_MODE_ID_INTF_CLR(_u_, _intf_) \
    476         SHR_BITCLR(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_))
    477 
    478 /* SVM Mode ID & Offset Mode conversion */
    479 #define OFFSET_MODE_TO_MODE_ID(_offset_mode_) \
    480         (_offset_mode_ + 1)
    481 
    482 #define MODE_ID_TO_OFFSET_MODE(_mode_id_) \
    483         (_mode_id_ - 1)
    484 
    485 /*
    486  * SVM Policer ID encoding:
    487  * 1bit (reserved) + 3-bit mode_id (1~4) + hw_policer_idx
    488  */
    489 #define BCMI_POLICER_GLOBAL_METER_INDEX_MASK  0x0FFFFFFF
    490 #define BCMI_POLICER_GLOBAL_METER_MODE_MASK   0x70000000
    491 #define BCMI_POLICER_GLOBAL_METER_MODE_SHIFT  28
    492 
    493 #define POLICER_IDX_TO_POLICER_ID(_offset_mode_, _policer_idx_) \
    494         (_policer_idx_) | \
    495         (OFFSET_MODE_TO_MODE_ID(_offset_mode_) << \
    496          BCMI_POLICER_GLOBAL_METER_MODE_SHIFT)
    497 
    498 #define POLICER_ID_TO_POLICER_IDX(_policer_id_) \
    499         ((_policer_id_) & BCMI_POLICER_GLOBAL_METER_INDEX_MASK)
    500 
    501 #define POLICER_ID_MODE_ID_GET(_policer_id_) \
    502         (((_policer_id_) & BCMI_POLICER_GLOBAL_METER_MODE_MASK) >> \
    503          BCMI_POLICER_GLOBAL_METER_MODE_SHIFT)
    504 
    505 #define POLICER_ID_OFFSET_MODE_GET(_policer_id_) \
    506         (MODE_ID_TO_OFFSET_MODE(POLICER_ID_MODE_ID_GET(_policer_id_)))
    507 
    508 #define POLICER_ID_API_SECTION 1
    509 #define MODE_ID_API_SECTION 1
    510 #define ACTION_API_SECTION 1
    511 
    512 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
    513 
    514 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
    515 #ifdef BCM_WARM_BOOT_SUPPORT
    516 /* helper macro to copy content between policer and wb policer structures */
    517 #define POLICER_CONFIG_ASSIGN(_dst_, _src_ , _arg_)                 \
    518         (_dst_->_arg_ = _src_->_arg_)
    519 /*
    520  * Function:
    521  *     policer_config_copy_to_wb_policer_config
    522  * Purpose:
    523  *     Copy the content of policer config from
    524  *     bcm_policer_config_t to
    525  *     bcm_policer_config_wb_t
    526  * Parameters:
    527  *     bcm_policer_config_t (IN) - bcm API policer config.
    528  *     bcm_policer_config_wb_t (OUT) - policer config. for GH2 WB structure
    529  * Returns:
    530  *     BCM_E_XXX
    531  */
    532 STATIC void
    533 policer_config_copy_to_wb_policer_config(
    534     bcm_policer_config_t *pol_cfg,
    535     bcm_policer_config_wb_t *pol_cfg_wb)
    536 {
    537     if (NULL == pol_cfg || NULL == pol_cfg_wb) {
    538         return;
    539     }
    540     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, flags);
    541     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, mode);
    542     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ckbits_sec);
    543     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, cbits_sec_lower);
    544     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_ckbits_sec);
    545     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_cbits_sec_lower);
    546     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ckbits_burst);
    547     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, cbits_burst_lower);
    548     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pkbits_sec);
    549     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pbits_sec_lower);
    550     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_pkbits_sec);
    551     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_pbits_sec_lower);
    552     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pkbits_burst);
    553     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pbits_burst_lower);
    554     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, kbits_current);
    555     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bits_current_lower);
    556     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, action_id);
    557     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, sharing_mode);
    558     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, entropy_id);
    559     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pool_id);
    560     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_width);
    561     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, token_gran);
    562     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_init_val);
    563     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_rollover_val);
    564     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, core_id);
    565     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ncoflow_policer_id);
    566     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, npoflow_policer_id);
    567     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, average_pkt_size);
    568     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, mark_drop_as_black);
    569     POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, color_resolve_profile);
    570 }
    571 
    572 /*
    573  * Function:
    574  *     wb_policer_config_copy_to_policer_config
    575  * Purpose:
    576  *     Copy the content of policer config from
    577  *     bcm_policer_config_wb_t to bcm_policer_config_t
    578  * Parameters:
    579  *     bcm_policer_config_wb_t (IN) - policer config. for GH2 WB structure
    580  *     bcm_policer_config_t (OUT) - bcm API policer config.
    581  * Returns:
    582  *     BCM_E_XXX
    583  */
    584 STATIC void
    585 wb_policer_config_copy_to_policer_config(
    586     bcm_policer_config_wb_t *pol_cfg_wb,
    587     bcm_policer_config_t *pol_cfg)
    588 {
    589     if (NULL == pol_cfg_wb || NULL == pol_cfg) {
    590         return;
    591     }
    592     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, flags);
    593     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, mode);
    594     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ckbits_sec);
    595     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, cbits_sec_lower);
    596     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_ckbits_sec);
    597     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_cbits_sec_lower);
    598     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ckbits_burst);
    599     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, cbits_burst_lower);
    600     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pkbits_sec);
    601     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pbits_sec_lower);
    602     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_pkbits_sec);
    603     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_pbits_sec_lower);
    604     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pkbits_burst);
    605     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pbits_burst_lower);
    606     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, kbits_current);
    607     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bits_current_lower);
    608     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, action_id);
    609     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, sharing_mode);
    610     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, entropy_id);
    611     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pool_id);
    612     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_width);
    613     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, token_gran);
    614     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_init_val);
    615     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_rollover_val);
    616     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, core_id);
    617     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ncoflow_policer_id);
    618     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, npoflow_policer_id);
    619     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, average_pkt_size);
    620     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, mark_drop_as_black);
    621     POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, color_resolve_profile);
    622 }
    623 #endif /* BCM_WARM_BOOT_SUPPORT */
    624 /*
    625  * Function:
    626  *      bcmi_global_meter_dev_info_init
    627  * Purpose:
    628  *      register Global Meter platform specific information & functions
    629  * Parameters:
    630  *      unit - (IN) Unit number
    631  * Returns:
    632  *      BCM_E_xxx
    633  */
    634 STATIC int
    635 bcmi_global_meter_dev_info_init(int unit)
    636 {
    637     bcm_error_t rv = BCM_E_UNAVAIL;
    638 
    639     POL_FUNCTION_TRACE(unit, "IN");
    640 
    641 #if defined(BCM_GREYHOUND2_SUPPORT)
    642     if (SOC_IS_GREYHOUND2(unit)) {
    643         rv = bcmi_gh2_global_meter_dev_info_init(unit,
    644                 &(bcmi_global_meter_dev_info[unit]));
    645     } else
    646 #endif /* BCM_GREYHOUND2_SUPPORT */
    647     {
    648         return BCM_E_UNAVAIL;
    649     }
    650 
    651     if (BCM_FAILURE(rv) || NULL == bcmi_global_meter_dev_info[unit]) {
    652         /* No chip specific information initialized */
    653         LOG_WARN(BSL_LS_BCM_SWITCH,
    654                  (BSL_META_U(unit,
    655                              "Global Meter not supported:\n"
    656                              "dev_info_init failed.\n")));
    657         if (BCM_SUCCESS(rv)) {
    658             return BCM_E_UNAVAIL;
    659         }
    660         return rv;
    661     }
    662 
    663     POL_FUNCTION_TRACE(unit, "OUT");
    664     return rv;
    665 }
    666 
    667 STATIC const char
    668 *bcm_policer_group_mode_attr_t_str[bcmPolicerGroupModeAttrCount] = {
    669     "Invalid String", /* Since bcm_policer_group_mode_attr_t start from 1 */
    670     "bcmPolicerGroupModeAttrUdf",                  /* 1 */
    671     "bcmPolicerGroupModeAttrFieldIngressColor",
    672     "bcmPolicerGroupModeAttrIntPri",
    673     "bcmPolicerGroupModeAttrVlan",
    674     "bcmPolicerGroupModeAttrOuterPri",             /* 5 */
    675     "bcmPolicerGroupModeAttrInnerPri",
    676     "bcmPolicerGroupModeAttrPort",
    677     "bcmPolicerGroupModeAttrTosDscp",
    678     "bcmPolicerGroupModeAttrTosEcn",
    679     "bcmPolicerGroupModeAttrPktType",              /* 10 */
    680     "bcmPolicerGroupModeAttrIngNetworkGroup",
    681     "bcmPolicerGroupModeAttrDrop",
    682     "bcmPolicerGroupModeAttrPacketTypeIp",
    683     "bcmPolicerGroupModeAttrPreemptable",
    684     "bcmPolicerGroupModeAttrEtherType"             /* 15 */
    685 };
    686 
    687 STATIC const char
    688 *bcm_policer_group_mode_t_str[bcmPolicerGroupModeCount] = {
    689     "bcmPolicerGroupModeSingle",                   /* 0 */
    690     "bcmPolicerGroupModeTrafficType",
    691     "bcmPolicerGroupModeDlfAll",
    692     "bcmPolicerGroupModeDlfIntPri",
    693     "bcmPolicerGroupModeTyped",
    694     "bcmPolicerGroupModeTypedAll",                 /* 5 */
    695     "bcmPolicerGroupModeTypedIntPri",
    696     "bcmPolicerGroupModeSingleWithControl",
    697     "bcmPolicerGroupModeTrafficTypeWithControl",
    698     "bcmPolicerGroupModeDlfAllWithControl",
    699     "bcmPolicerGroupModeDlfIntPriWithControl",     /* 10 */
    700     "bcmPolicerGroupModeTypedWithControl",
    701     "bcmPolicerGroupModeTypedAllWithControl",
    702     "bcmPolicerGroupModeTypedIntPriWithControl",
    703     "bcmPolicerGroupModeDot1P",
    704     "bcmPolicerGroupModeIntPri",                   /* 15 */
    705     "bcmPolicerGroupModeIntPriCng",
    706     "bcmPolicerGroupModeSvpType",
    707     "bcmPolicerGroupModeDscp",
    708     "bcmPolicerGroupModeCascade",
    709     "bcmPolicerGroupModeCascadeWithCoupling",      /* 20 */
    710     "bcmPolicerGroupModeInnerDot1P",
    711     "bcmPolicerGroupModeEgressSingle",
    712     "bcmPolicerGroupModeEgressIntPri",
    713     "bcmPolicerGroupModeShortIntPri",
    714     "bcmPolicerGroupModeIntPriCascade",            /* 25 */
    715     "bcmPolicerGroupModeIntPriCascadeWithCoupling",
    716     "bcmPolicerGroupModePreemptable",
    717     "bcmPolicerGroupModeCascadeDroppedPktExclude"
    718 };
    719 
    720 STATIC const uint32
    721 attr_to_bit_selector[bcmPolicerGroupModeAttrCount] = {
    722     /* Since bcm_policer_group_mode_attr_t start from 1 */
    723     0,
    724     /* bcmPolicerGroupModeAttrUdf = 1 */
    725     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_UDF_ATTR_BITS,
    726     /* bcmPolicerGroupModeAttrFieldIngressColor */
    727     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS,
    728     /* bcmPolicerGroupModeAttrIntPri */
    729     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS,
    730     /* bcmPolicerGroupModeAttrVlan */
    731     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS,
    732     /* bcmPolicerGroupModeAttrOuterPri */
    733     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS,
    734     /* bcmPolicerGroupModeAttrInnerPri */
    735     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS,
    736     /* bcmPolicerGroupModeAttrPort */
    737     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS,
    738     /* bcmPolicerGroupModeAttrTosDscp */
    739     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS,
    740     /* bcmPolicerGroupModeAttrTosEcn */
    741     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS,
    742     /* bcmPolicerGroupModeAttrPktType */
    743     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS,
    744     /* bcmPolicerGroupModeAttrIngNetworkGroup = 11 */
    745     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS,
    746     /* bcmPolicerGroupModeAttrDrop */
    747     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS,
    748     /* bcmPolicerGroupModeAttrPacketTypeIp */
    749     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS,
    750     /* bcmPolicerGroupModeAttrPreemptable */
    751     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PREEMPTABLE_ATTR_BITS,
    752     /* bcmPolicerGroupModeAttrEtherType */
    753     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_ETHERTYPE_ATTR_BITS
    754 };
    755 
    756 /*
    757  * Function:
    758  *     check_attr_to_bit_selector
    759  * Purpose:
    760  *     Check if attr_to_bit_selector is mapping correctly.
    761  * Parameters:
    762  * Returns:
    763  *     none
    764  */
    765 STATIC void
    766 check_attr_to_bit_selector(void)
    767 {
    768     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrUdf] ==
    769         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_UDF_ATTR_BITS);
    770 
    771     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrOuterPri] ==
    772         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS);
    773 
    774     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrInnerPri] ==
    775         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS);
    776 
    777     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPort] ==
    778         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS);
    779 
    780     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrTosDscp] ==
    781         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS);
    782 
    783     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrTosEcn] ==
    784         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS);
    785 
    786     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPktType] ==
    787         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS);
    788 
    789     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrIngNetworkGroup] ==
    790         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS);
    791 
    792     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrDrop] ==
    793         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS);
    794 
    795     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPacketTypeIp] ==
    796         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS);
    797 
    798     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPreemptable] ==
    799         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PREEMPTABLE_ATTR_BITS);
    800 
    801     assert(attr_to_bit_selector[bcmPolicerGroupModeAttrEtherType] ==
    802         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_ETHERTYPE_ATTR_BITS);
    803 }
    804 
    805 /*
    806  * Function:
    807  *     pkt_tcam_attr_bits_t_init
    808  * Purpose:
    809  *     Init pkt_tcam_attr_bits_t
    810  * Parameters:
    811  *     pkt_attr_selectors - pointer instance to pkt_tcam_attr_bits_t
    812  * Returns:
    813  *     BCM_E_XXX
    814  */
    815 void
    816 pkt_tcam_attr_bits_t_init(pkt_tcam_attr_bits_t *attr)
    817 {
    818     /* Parameter NULL error handling */
    819     if (NULL == attr) {
    820         return;
    821     }
    822 
    823     sal_memset(attr, 0, sizeof(pkt_tcam_attr_bits_t));
    824 }
    825 
    826 /*
    827  * Function:
    828  *     bcmi_policer_tcam_attr_selectors_t_init
    829  * Purpose:
    830  *     Init bcmi_policer_tcam_attr_selectors_t
    831  * Parameters:
    832  *     pkt_attr_selectors - pointer instance to bcmi_policer_tcam_attr_selectors_t
    833  * Returns:
    834  *     BCM_E_XXX
    835  */
    836 STATIC void
    837 bcmi_policer_tcam_attr_selectors_t_init(
    838     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
    839 {
    840     /* Parameter NULL error handling */
    841     if (NULL == pkt_attr_selectors) {
    842         return;
    843     }
    844 
    845     sal_memset(pkt_attr_selectors, 0,
    846         sizeof(bcmi_policer_tcam_attr_selectors_t));
    847 }
    848 
    849 /*
    850  * Function:
    851  *     bcmi_policer_svm_offset_mode_bk_t_init
    852  * Purpose:
    853  *     Init bcmi_policer_svm_offset_mode_bk_t
    854  * Parameters:
    855  *     bk_svm_mode_info - pointer instance to bcmi_policer_svm_offset_mode_bk_t
    856  * Returns:
    857  *     BCM_E_XXX
    858  */
    859 STATIC void
    860 bcmi_policer_svm_offset_mode_bk_t_init(
    861     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info)
    862 {
    863     /* Parameter NULL error handling */
    864     if (NULL == bk_svm_mode_info) {
    865         return;
    866     }
    867     bk_svm_mode_info->ref_cnt = 0;
    868     bk_svm_mode_info->used = 0;
    869     bk_svm_mode_info->is_custom_group = FALSE;
    870     bk_svm_mode_info->group_mode = bcmPolicerGroupModeCount;
    871     bk_svm_mode_info->group_mode_type = bcmPolicerGroupModeTypeCount;
    872     bk_svm_mode_info->no_of_policers = 0;
    873     bk_svm_mode_info->no_of_attr_selectors = 0;
    874     bk_svm_mode_info->attr_selectors = NULL;
    875     bk_svm_mode_info->pkt_attr_v_cnt = 0;
    876     bk_svm_mode_info->pkt_attr_v = NULL;
    877 }
    878 
    879 /*
    880  * Function:
    881  *     bcmi_global_meter_policer_control_t_init
    882  * Purpose:
    883  *     Init bcmi_global_meter_policer_control_t
    884  * Parameters:
    885  *     policer_control - pointer instance to bcmi_global_meter_policer_control_t
    886  * Returns:
    887  *     BCM_E_XXX
    888  */
    889 STATIC void
    890 bcmi_global_meter_policer_control_t_init(
    891     bcmi_global_meter_policer_control_t *policer_control)
    892 {
    893     /* Parameter NULL error handling */
    894     if (NULL == policer_control) {
    895         return;
    896     }
    897     policer_control->pid = 0;
    898     policer_control->pol_cfg = NULL;
    899     policer_control->ref_count = 0;
    900     policer_control->no_of_policers = 0;
    901     policer_control->grp_mode = bcmPolicerGroupModeCount;
    902     policer_control->next = NULL;
    903 }
    904 
    905 /*
    906  * Function:
    907  *      bcmi_global_meter_dump_config
    908  * Purpose:
    909  *      dump the config of Global Meter
    910  * Parameters:
    911  *      unit   - (IN) Unit number
    912  *      prefix - (IN) Prefix string for dump message
    913  *      config - (IN) Global Meter Config
    914  * Returns:
    915  *      BCM_E_xxx
    916  */
    917 STATIC void
    918 bcmi_global_meter_dump_config(
    919     int unit,
    920     char *prefix,
    921     bcm_policer_global_meter_config_t *config)
    922 {
    923     int i;
    924 
    925     /* Input parameters check. */
    926     if ((NULL == prefix) || (NULL == config)) {
    927         return;
    928     }
    929 
    930     if (bsl_check(bslLayerBcm, bslSourcePolicer, bslSeverityDebug, unit)) {
    931         LOG_DEBUG(BSL_LS_BCM_POLICER,
    932                   (BSL_META_U(unit,
    933                               "[bcm_policer_global_meter_config_t]:\n")));
    934         LOG_DEBUG(BSL_LS_BCM_POLICER,
    935                   (BSL_META_U(unit,
    936                              "%s ifg_enable: %d.\n"),
    937                              prefix,
    938                              config->ifg_enable
    939                              ));
    940 
    941         LOG_DEBUG(BSL_LS_BCM_POLICER,
    942                   (BSL_META_U(unit,
    943                              "%s source_order_count: %d.\n"),
    944                              prefix,
    945                              config->source_order_count
    946                              ));
    947 
    948         for (i = 0; i < bcmPolicerGlobalMeterSourceCount; i++) {
    949             LOG_DEBUG(BSL_LS_BCM_POLICER,
    950                       (BSL_META_U(unit,
    951                                   "%s source_order[%d]: %d.\n"),
    952                                   prefix,
    953                                   i,
    954                                   config->source_order[i]
    955                                   ));
    956         }
    957     }
    958 }
    959 
    960 /*
    961  * Function:
    962  *      bcmi_policer_tcam_attr_dump
    963  * Purpose:
    964  *      dump the config of Global Meter
    965  * Parameters:
    966  *      unit   - (IN) Unit number
    967  *      prefix - (IN) Prefix string for dump message
    968  *      attr   - (IN) Global Meter Config
    969  * Returns:
    970  *      BCM_E_xxx
    971  */
    972 STATIC void
    973 bcmi_policer_tcam_attr_dump(
    974     int unit,
    975     char *prefix,
    976     pkt_tcam_attr_bits_t *attr)
    977 {
    978     int i;
    979 
    980     if ((NULL == prefix) || (NULL == attr)) {
    981         return;
    982     }
    983 
    984     if (bsl_check(bslLayerBcm, bslSourcePolicer, bslSeverityDebug, unit)) {
    985         LOG_DEBUG(BSL_LS_BCM_POLICER,
    986                   (BSL_META_U(unit,
    987                              "%s: ref_count %d, tcam_idx %d, final_offset %d\n"),
    988                              prefix,
    989                              attr->ref_count,
    990                              attr->tcam_idx,
    991                              attr->final_offset));
    992 
    993         LOG_DEBUG(BSL_LS_BCM_POLICER,
    994                   (BSL_META_U(unit,
    995                              "%s: attr_bits_selector 0x%8x\n"),
    996                              prefix,
    997                              attr->attr_bits_selector));
    998         LOG_DEBUG(BSL_LS_BCM_POLICER,
    999                   (BSL_META_U(unit,
   1000                              "%s: udf0 value 0x%4x, mask 0x%4x\n"),
   1001                              prefix,
   1002                              attr->udf.udf0,
   1003                              attr->udf_mask.udf0));
   1004 
   1005         LOG_DEBUG(BSL_LS_BCM_POLICER,
   1006                   (BSL_META_U(unit,
   1007                              "%s: udf1 value 0x%4x, mask 0x%4x\n"),
   1008                              prefix,
   1009                              attr->udf.udf1,
   1010                              attr->udf_mask.udf1));
   1011 
   1012         for (i = bcmPolicerGroupModeAttrUdf;
   1013              i < bcmPolicerGroupModeAttrCount; i++) {
   1014             if (attr->attr_bits_selector & attr_to_bit_selector[i]) {
   1015                 LOG_DEBUG(BSL_LS_BCM_POLICER,
   1016                           (BSL_META_U(unit,
   1017                                       "%s: [%d] value %4x, mask %4x, %s\n"),
   1018                                       prefix,
   1019                                       i,
   1020                                       attr->value[i],
   1021                                       attr->value_mask[i],
   1022                                       bcm_policer_group_mode_attr_t_str[i]));
   1023             }
   1024         }
   1025     }
   1026 }
   1027 
   1028 /*
   1029  * Function:
   1030  *     bcmi_policer_tcam_allocate_check
   1031  * Purpose:
   1032  *     Check TCAM size is enough or not
   1033  * Parameters:
   1034  *     Unit            - (IN) unit number
   1035  *     pkt_attr_v_cnt  - (IN) pkt_attr_v_cnt
   1036  * Returns:
   1037  *     BCM_E_XXX
   1038  */
   1039 STATIC bcm_error_t
   1040 bcmi_policer_tcam_allocate_check(int unit, uint32 pkt_attr_v_cnt)
   1041 {
   1042     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   1043 
   1044     POL_FUNCTION_TRACE(unit, "IN");
   1045 
   1046     /* Initialization check */
   1047     CHECK_GLOBAL_METER_INIT(unit);
   1048     bk_svm_info = BCMI_SVM_BK_GET(unit);
   1049 
   1050     /* Check if total TCAM is enough or not */
   1051     if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   1052         LOG_ERROR(BSL_LS_BCM_POLICER,
   1053                   (BSL_META_U(unit,
   1054                               "TCAM entry (%d) isn't enough, need %d TCAMs\n"),
   1055                               BCMI_POLICER_SVC_METER_TCAM_SIZE,
   1056                               pkt_attr_v_cnt));
   1057         return BCM_E_UNAVAIL;
   1058     }
   1059 
   1060     /* Check if empty TCAM is enough */
   1061     if (pkt_attr_v_cnt > bk_svm_info->empty_tcam_idx_cnt) {
   1062         LOG_ERROR(BSL_LS_BCM_POLICER,
   1063                   (BSL_META_U(unit,
   1064                               "No enough empty TCAM(%d), need %d TCAMs\n"),
   1065                               bk_svm_info->empty_tcam_idx_cnt,
   1066                               pkt_attr_v_cnt));
   1067         return BCM_E_RESOURCE;
   1068     }
   1069 
   1070     POL_FUNCTION_TRACE(unit, "OUT");
   1071     return BCM_E_NONE;
   1072 }
   1073 
   1074 /*
   1075  * Function:
   1076  *     bcmi_policer_tcam_configurate_hw
   1077  * Purpose:
   1078  *     Check TCAM size is enough or not
   1079  * Parameters:
   1080  *     Unit            - (IN) unit number
   1081  *     pkt_attr_v_cnt  - (IN) pkt_attr_v_cnt
   1082  * Returns:
   1083  *     BCM_E_XXX
   1084  */
   1085 STATIC bcm_error_t
   1086 bcmi_policer_tcam_configurate_hw(
   1087     int unit,
   1088     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
   1089 {
   1090     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
   1091     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   1092     int sel, sel2;
   1093 
   1094     POL_FUNCTION_TRACE(unit, "IN");
   1095 
   1096     /* Parameter NULL error handling */
   1097     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   1098 
   1099     /* Initialization check */
   1100     CHECK_GLOBAL_METER_INIT(unit);
   1101     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1102     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   1103 
   1104     /* Check if the chip specific function existed */
   1105     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_set);
   1106     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_delete);
   1107 
   1108     /* Configured TCAM HW with pkt_attr_selectors */
   1109     for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt; sel++) {
   1110         rv = gm_dev_info->tcam_keys_set(
   1111                 unit, &pkt_attr_selectors->pkt_attr_v[sel]);
   1112         if (BCM_FAILURE(rv)) {
   1113             LOG_ERROR(BSL_LS_BCM_POLICER,
   1114                       (BSL_META_U(unit,
   1115                                   "HW Operation failed(rv = %d)\n"),
   1116                                   rv));
   1117             /* Reset the TCAM to defaul value */
   1118             for (sel2 = 0; sel2 <= sel; sel2++) {
   1119                 rv2 = gm_dev_info->tcam_keys_delete(
   1120                         unit, pkt_attr_selectors->pkt_attr_v[sel2].tcam_idx);
   1121                 if (BCM_FAILURE(rv2)) {
   1122                     /* tcam_keys_delete shouldn't return error, need to check */
   1123                     LOG_ERROR(BSL_LS_BCM_POLICER,
   1124                               (BSL_META_U(unit,
   1125                                           "tcam_keys_delete failed\n")));
   1126                     return rv2;
   1127                 }
   1128             }
   1129             return rv;
   1130         }
   1131     }
   1132 
   1133     POL_FUNCTION_TRACE(unit, "OUT");
   1134     return BCM_E_NONE;
   1135 }
   1136 
   1137 /*
   1138  * Function:
   1139  *      bcmi_policer_offset_mode_validate
   1140  * Purpose:
   1141  *      Validate the given offset_mode
   1142  * Parameters:
   1143  *     Unit             - (IN) unit number
   1144  *     offset_mode      - (IN) Meter offset_mode
   1145  * Returns:
   1146  *     BCM_E_XXX
   1147  */
   1148 STATIC bcm_error_t
   1149 bcmi_policer_offset_mode_validate(int unit, uint32 offset_mode)
   1150 {
   1151     POL_FUNCTION_TRACE(unit, "IN");
   1152     if (offset_mode >= BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE)
   1153     {
   1154         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   1155                     (BSL_META_U(unit,
   1156                                 "Invalid Offset mode.\n")));
   1157         POL_FUNCTION_TRACE(unit, "OUT Invalid Offset mode");
   1158         return BCM_E_PARAM;
   1159 
   1160     }
   1161     POL_FUNCTION_TRACE(unit, "OUT");
   1162     return BCM_E_NONE;
   1163 }
   1164 
   1165 /*
   1166  * Function:
   1167  *      bcmi_policer_mode_id_validate
   1168  * Purpose:
   1169  *      Validate the given mode_id
   1170  * Parameters:
   1171  *     Unit                  - (IN) unit number
   1172  *     mode_id               - (IN) mode_id
   1173  * Returns:
   1174  *     BCM_E_XXX
   1175  */
   1176 STATIC bcm_error_t
   1177 bcmi_policer_mode_id_validate(int unit, uint32 mode_id)
   1178 {
   1179     int rv = BCM_E_NONE;
   1180     uint32 offset_mode = 0;
   1181 
   1182     POL_FUNCTION_TRACE(unit, "IN");
   1183 
   1184     /* Initialization check */
   1185     CHECK_GLOBAL_METER_INIT(unit);
   1186 
   1187     /* Validate offset_mode */
   1188     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   1189     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1190     BCM_IF_ERROR_RETURN(rv);
   1191 
   1192     POL_FUNCTION_TRACE(unit, "OUT");
   1193     return BCM_E_NONE;
   1194 }
   1195 
   1196 /*
   1197  * Function:
   1198  *     bcmi_policer_svc_meter_reserve_mode
   1199  * Purpose:
   1200  *     Internal function to allocate/reserve meter offset mode
   1201  * Parameters:
   1202  *     Unit                  - (IN) unit number
   1203  *     offset_mode           - (IN) Meter offset mode
   1204  *     group_mode            - (IN) Policer group mode
   1205  *     group_mode_type       - (IN) Policer group mode type
   1206  *     npolicers             - (IN) Number of policers
   1207  *     pkt_attr_selectors    - (IN) tcam packet attribute selectors
   1208  * Returns:
   1209  *     BCM_E_XXX
   1210  */
   1211 STATIC bcm_error_t
   1212 bcmi_policer_svc_meter_reserve_mode(
   1213     int unit,
   1214     bcm_policer_svc_meter_mode_t offset_mode,
   1215     bcm_policer_group_mode_t group_mode,
   1216     bcm_policer_group_mode_type_t group_mode_type,
   1217     int npolicers,
   1218     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
   1219 {
   1220     bcm_error_t rv = BCM_E_NONE;
   1221     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   1222     int sel;
   1223 
   1224     POL_FUNCTION_TRACE(unit, "IN");
   1225 
   1226     /* Parameter NULL error handling */
   1227     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   1228 
   1229     /* Initialization check */
   1230     CHECK_GLOBAL_METER_INIT(unit);
   1231 
   1232     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1233     BCM_IF_ERROR_RETURN(rv);
   1234 
   1235     GLOBAL_METER_BK_LOCK(unit);
   1236     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   1237     bk_svm_mode_info->ref_cnt = 0;
   1238     bk_svm_mode_info->used = 1;
   1239     bk_svm_mode_info->group_mode_type = group_mode_type;
   1240     bk_svm_mode_info->group_mode = group_mode;
   1241     bk_svm_mode_info->no_of_policers = npolicers;
   1242 
   1243     POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v);
   1244     bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt;
   1245     POL_MEM_ALLOC(
   1246         bk_svm_mode_info->pkt_attr_v,
   1247         bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t),
   1248         "pkt_attr_v in offset mode instance");
   1249     if (NULL == bk_svm_mode_info->pkt_attr_v) {
   1250         GLOBAL_METER_BK_UNLOCK(unit);
   1251         LOG_ERROR(BSL_LS_BCM_POLICER,
   1252                   (BSL_META_U(unit,
   1253                               "Unable to allocate memory for "
   1254                               "pkt_attr_v\n")));
   1255         return (BCM_E_MEMORY);
   1256     }
   1257 
   1258     for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt ; sel++) {
   1259         sal_memcpy(&bk_svm_mode_info->pkt_attr_v[sel],
   1260                    &pkt_attr_selectors->pkt_attr_v[sel],
   1261                    sizeof(pkt_tcam_attr_bits_t));
   1262     }
   1263     /* Configured TCAM HW with pkt_attr_selectors */
   1264     rv = bcmi_policer_tcam_configurate_hw(unit, pkt_attr_selectors);
   1265     if (BCM_FAILURE(rv)) {
   1266         GLOBAL_METER_BK_UNLOCK(unit);
   1267         return rv;
   1268     }
   1269 
   1270     /*
   1271      * if and only if using bcmi_esw_policer_group_mode_id_create need
   1272      * to record attr_selectors
   1273      */
   1274     bk_svm_mode_info->is_custom_group = FALSE;
   1275     bk_svm_mode_info->no_of_attr_selectors = 0;
   1276     POL_MEM_FREE(bk_svm_mode_info->attr_selectors);
   1277 
   1278     GLOBAL_METER_BK_UNLOCK(unit);
   1279 
   1280     POL_FUNCTION_TRACE(unit, "OUT");
   1281     return BCM_E_NONE;
   1282 }
   1283 
   1284 STATIC int
   1285 bcmi_esw_policer_group_mode_id_delete(
   1286     int unit,
   1287     uint32 mode_id);
   1288 
   1289 /*
   1290  * Function:
   1291  *      bcmi_policer_svc_meter_unreserve_mode
   1292  * Purpose:
   1293  *     Internal function to unreserve meter offset mode
   1294  * Parameters:
   1295  *     Unit                  - (IN) unit number
   1296  *     offset_mode           - (IN) Meter offset mode
   1297  * Returns:
   1298  *     BCM_E_XXX
   1299  */
   1300 STATIC bcm_error_t
   1301 bcmi_policer_svc_meter_unreserve_mode(
   1302     int unit,
   1303     bcm_policer_svc_meter_mode_t offset_mode)
   1304 {
   1305     bcm_error_t rv = BCM_E_NONE;
   1306     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   1307     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   1308     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   1309     int sel;
   1310     uint32 d_tcam_idx;
   1311 
   1312     POL_FUNCTION_TRACE(unit, "IN");
   1313 
   1314     /* Initialization check */
   1315     CHECK_GLOBAL_METER_INIT(unit);
   1316     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1317     bk_svm_info = BCMI_SVM_BK_GET(unit);
   1318 
   1319     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1320     BCM_IF_ERROR_RETURN(rv);
   1321     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   1322     if (bk_svm_mode_info->used == 0) {
   1323         LOG_WARN(BSL_LS_BCM_POLICER,
   1324                  (BSL_META_U(unit,
   1325                              "Wrong offset mode: Mode is not in use\n")));
   1326         return BCM_E_NOT_FOUND;
   1327     }
   1328     if (bk_svm_mode_info->ref_cnt != 0) {
   1329         LOG_WARN(BSL_LS_BCM_POLICER,
   1330                  (BSL_META_U(unit,
   1331                              "Mode is still in use\n")));
   1332         return BCM_E_BUSY;
   1333     }
   1334 
   1335     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   1336     /* Check if the chip specific function existed */
   1337     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_delete);
   1338     /* Delete TCAM and Reset TCAM HW selector keys */
   1339     for (sel = 0; sel < bk_svm_mode_info->pkt_attr_v_cnt ; sel++) {
   1340         d_tcam_idx = bk_svm_mode_info->pkt_attr_v[sel].tcam_idx;
   1341         GLOBAL_METER_LOCK(unit);
   1342         rv = gm_dev_info->tcam_keys_delete(
   1343                 unit, d_tcam_idx);
   1344         GLOBAL_METER_UNLOCK(unit);
   1345         if (BCM_FAILURE(rv)) {
   1346             /* tcam_keys_delete shouldn't return error, need to check */
   1347             LOG_ERROR(BSL_LS_BCM_POLICER,
   1348                       (BSL_META_U(unit,
   1349                                   "tcam_keys_delete failed\n")));
   1350             return rv;
   1351         }
   1352         GLOBAL_METER_BK_LOCK(unit);
   1353 
   1354         /* Delete the TCAM idx */
   1355         BCMI_SVM_TCAM_INTF_CLR(unit, d_tcam_idx);
   1356 
   1357         /* Update empty start and end */
   1358         if (d_tcam_idx < bk_svm_info->empty_tcam_idx_start) {
   1359             bk_svm_info->empty_tcam_idx_start = d_tcam_idx;
   1360         } else if (d_tcam_idx > bk_svm_info->empty_tcam_idx_end) {
   1361             bk_svm_info->empty_tcam_idx_end = d_tcam_idx;
   1362         }
   1363 
   1364         bk_svm_info->empty_tcam_idx_cnt++;
   1365         if (bk_svm_info->valid_tcam_idx_cnt > 0) {
   1366             bk_svm_info->valid_tcam_idx_cnt--;
   1367         } else {
   1368             GLOBAL_METER_BK_UNLOCK(unit);
   1369             LOG_WARN(BSL_LS_BCM_POLICER,
   1370                      (BSL_META_U(unit,
   1371                                  "Need to check valid_tcam_idx_cnt logic\n")));
   1372             return BCM_E_INTERNAL;
   1373         }
   1374         GLOBAL_METER_BK_UNLOCK(unit);
   1375     }
   1376 
   1377     /* Delete the offset mode SW database */
   1378     rv = bcmi_esw_policer_group_mode_id_delete(
   1379             unit, OFFSET_MODE_TO_MODE_ID(offset_mode));
   1380 
   1381     BCM_IF_ERROR_RETURN(rv);
   1382 
   1383     POL_FUNCTION_DEBUG(unit,
   1384         "Free %d TCAM", bk_svm_mode_info->pkt_attr_v_cnt);
   1385     POL_FUNCTION_DEBUG(unit,
   1386         "%d empty TCAM left", bk_svm_info->empty_tcam_idx_cnt);
   1387 
   1388     POL_FUNCTION_TRACE(unit, "OUT");
   1389     return BCM_E_NONE;
   1390 }
   1391 
   1392 /*
   1393  * Function:
   1394  *     bcmi_policer_svc_meter_delete_mode
   1395  * Purpose:
   1396  *     Delete a meter offset mode
   1397  * Parameters:
   1398  *     Unit                  - (IN) unit number
   1399  *     offset_mode           - (IN) Meter offset mode
   1400  * Returns:
   1401  *     BCM_E_XXX
   1402  */
   1403 STATIC bcm_error_t
   1404 bcmi_policer_svc_meter_delete_mode(
   1405     int unit,
   1406     bcm_policer_svc_meter_mode_t offset_mode)
   1407 {
   1408     bcm_error_t rv = BCM_E_NONE;
   1409 
   1410     POL_FUNCTION_TRACE(unit, "IN");
   1411 
   1412     /* Initialization check */
   1413     CHECK_GLOBAL_METER_INIT(unit);
   1414 
   1415     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1416     BCM_IF_ERROR_RETURN(rv);
   1417 
   1418     rv = bcmi_policer_svc_meter_unreserve_mode(unit, offset_mode);
   1419     BCM_IF_ERROR_RETURN(rv);
   1420 
   1421     POL_FUNCTION_TRACE(unit, "OUT");
   1422     return rv;
   1423 }
   1424 
   1425 /*
   1426  * Function:
   1427  *     bcmi_policer_svc_meter_inc_mode_ref_cnt
   1428  * Purpose:
   1429  *     Internal function to increment meter offset mode usage count
   1430  * Parameters:
   1431  *     Unit                  - (IN) unit number
   1432  *     offset_mode           - (IN) Meter offset mode
   1433  * Returns:
   1434  *     BCM_E_XXX
   1435  */
   1436 STATIC bcm_error_t
   1437 bcmi_policer_svc_meter_inc_mode_ref_cnt(
   1438     uint32 unit,
   1439     bcm_policer_svc_meter_mode_t offset_mode)
   1440 {
   1441     bcm_error_t rv = BCM_E_NONE;
   1442     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   1443 
   1444     POL_FUNCTION_TRACE(unit, "IN");
   1445 
   1446     /* Initialization check */
   1447     CHECK_GLOBAL_METER_INIT(unit);
   1448     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1449 
   1450     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1451     BCM_IF_ERROR_RETURN(rv);
   1452 
   1453     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   1454     GLOBAL_METER_BK_LOCK(unit);
   1455     bk_svm_mode_info->ref_cnt++;
   1456     GLOBAL_METER_BK_UNLOCK(unit);
   1457     POL_FUNCTION_TRACE(unit, "OUT");
   1458     return BCM_E_NONE;
   1459 }
   1460 
   1461 /*
   1462  * Function:
   1463  *     bcmi_policer_svc_meter_dec_mode_ref_cnt
   1464  * Purpose:
   1465  *     Internal function to decrement meter offset mode usage count
   1466  * Parameters:
   1467  *     Unit                  - (IN) unit number
   1468  *     offset_mode           - (IN) Meter offset mode
   1469  * Returns:
   1470  *     BCM_E_XXX
   1471  */
   1472 STATIC bcm_error_t
   1473 bcmi_policer_svc_meter_dec_mode_ref_cnt(
   1474     uint32 unit,
   1475     bcm_policer_svc_meter_mode_t offset_mode)
   1476 {
   1477     bcm_error_t rv = BCM_E_NONE;
   1478     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   1479 
   1480     POL_FUNCTION_TRACE(unit, "IN");
   1481 
   1482     /* Initialization check */
   1483     CHECK_GLOBAL_METER_INIT(unit);
   1484     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1485 
   1486     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   1487     BCM_IF_ERROR_RETURN(rv);
   1488 
   1489     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   1490 
   1491     GLOBAL_METER_BK_LOCK(unit);
   1492     if (bk_svm_mode_info->ref_cnt > 0) {
   1493        bk_svm_mode_info->ref_cnt--;
   1494     }
   1495     if (bk_svm_mode_info->is_custom_group) {
   1496         /* Deletion of the mode is done through
   1497            bcm_policer_group_mode_id_destroy */
   1498         GLOBAL_METER_BK_UNLOCK(unit);
   1499         POL_FUNCTION_TRACE(unit, "OUT:is_custom_group");
   1500         return BCM_E_NONE;
   1501     }
   1502     if (bk_svm_mode_info->ref_cnt == 0) {
   1503         rv = bcmi_policer_svc_meter_delete_mode(unit, offset_mode);
   1504     }
   1505     GLOBAL_METER_BK_UNLOCK(unit);
   1506     POL_FUNCTION_TRACE(unit, "OUT");
   1507     return rv;
   1508 }
   1509 
   1510 #if MODE_ID_API_SECTION
   1511 /*
   1512  * Function:
   1513  *     bcmi_esw_policer_group_mode_fillup_tcam_idx
   1514  * Purpose:
   1515  *     update offset mode
   1516  * Parameters:
   1517  *     unit            - (IN) unit number
   1518  *     pkt_attr_v      - (IN) Packet TCAM attributes
   1519  * Returns:
   1520  *     BCM_E_XXX
   1521  */
   1522 STATIC int
   1523 bcmi_esw_policer_group_mode_fillup_tcam_idx(
   1524     int unit,
   1525     pkt_tcam_attr_bits_t *pkt_attr_v)
   1526 {
   1527     uint32 e_tcam_idx;
   1528     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   1529 
   1530     POL_FUNCTION_TRACE(unit, "IN");
   1531 
   1532     /* Parameter NULL error handling */
   1533     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_v);
   1534 
   1535     /* Initialization check */
   1536     CHECK_GLOBAL_METER_INIT(unit);
   1537     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1538     bk_svm_info = BCMI_SVM_BK_GET(unit);
   1539 
   1540     GLOBAL_METER_BK_LOCK(unit);
   1541     /* Check if empty tcam is enough */
   1542     if (bk_svm_info->empty_tcam_idx_cnt == 0) {
   1543         GLOBAL_METER_BK_UNLOCK(unit);
   1544         LOG_ERROR(BSL_LS_BCM_TSN,
   1545                   (BSL_META_U(unit,
   1546                               "Not enough tcam \n")));
   1547         return BCM_E_RESOURCE;
   1548     }
   1549 
   1550     for (e_tcam_idx = bk_svm_info->empty_tcam_idx_start;
   1551          e_tcam_idx <= bk_svm_info->empty_tcam_idx_end;
   1552          e_tcam_idx++) {
   1553         if (BCMI_SVM_TCAM_INTF_GET(unit, e_tcam_idx) == 0) {
   1554             /* fill with the found empty tcam idx */
   1555             BCMI_SVM_TCAM_INTF_SET(unit, e_tcam_idx);
   1556 
   1557             /* Update valid start and end */
   1558             if (e_tcam_idx < bk_svm_info->valid_tcam_idx_start) {
   1559                 bk_svm_info->valid_tcam_idx_start = e_tcam_idx;
   1560             } else if (e_tcam_idx > bk_svm_info->valid_tcam_idx_end) {
   1561                 bk_svm_info->valid_tcam_idx_end = e_tcam_idx;
   1562             }
   1563             bk_svm_info->empty_tcam_idx_start = e_tcam_idx + 1;
   1564             bk_svm_info->valid_tcam_idx_cnt++;
   1565             if (bk_svm_info->empty_tcam_idx_cnt > 0) {
   1566                 bk_svm_info->empty_tcam_idx_cnt--;
   1567             }
   1568 
   1569             pkt_attr_v->tcam_idx = e_tcam_idx;
   1570             break;
   1571         }
   1572     }
   1573     GLOBAL_METER_BK_UNLOCK(unit);
   1574     POL_FUNCTION_TRACE(unit, "OUT");
   1575     return BCM_E_NONE;
   1576 }
   1577 
   1578 /*
   1579  * Function:
   1580  *      bcmi_esw_policer_group_empty_mode_id_get
   1581  * Purpose:
   1582  *      Get an empty mode_id
   1583  * Parameters:
   1584  *      unit     - (IN) Unit number
   1585  *      mode_id   - (OUT) Meter Mode ID
   1586  * Returns:
   1587  *      BCM_E_NONE - Success on finding a empty mode_id
   1588  */
   1589 STATIC int
   1590 bcmi_esw_policer_group_empty_mode_id_get(
   1591     int unit,
   1592     uint32 *mode_id)
   1593 {
   1594     bcm_error_t rv = BCM_E_UNAVAIL;
   1595     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   1596     /* Empty offset_mode */
   1597     uint32 e_offset_mode;
   1598 
   1599     POL_FUNCTION_TRACE(unit, "IN");
   1600 
   1601     /* Parameter NULL error handling */
   1602     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   1603 
   1604     /* Initialization check */
   1605     CHECK_GLOBAL_METER_INIT(unit);
   1606     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1607     bk_svm_info = BCMI_SVM_BK_GET(unit);
   1608 
   1609     /* Check if empty mode_id is enough */
   1610     if (bk_svm_info->empty_offset_mode_cnt == 0) {
   1611         LOG_ERROR(BSL_LS_BCM_TSN,
   1612                   (BSL_META_U(unit,
   1613                               "Not enough empty mode_id\n")));
   1614         return BCM_E_RESOURCE;
   1615     }
   1616 
   1617     GLOBAL_METER_BK_LOCK(unit);
   1618     /* Try to find an empty id */
   1619     for (e_offset_mode = bk_svm_info->empty_offset_mode_start;
   1620          e_offset_mode <= bk_svm_info->empty_offset_mode_end;
   1621          e_offset_mode++) {
   1622         if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, e_offset_mode) == 0) {
   1623 
   1624             /* An empty id found, set bit map as used */
   1625             BCMI_OFFSET_MODE_ID_INTF_SET(unit, e_offset_mode);
   1626 
   1627             /* Update valid start and end */
   1628             if (bk_svm_info->valid_offset_mode_cnt == 0) {
   1629                 bk_svm_info->valid_offset_mode_start = e_offset_mode;
   1630                 bk_svm_info->valid_offset_mode_end = e_offset_mode;
   1631             } else if (e_offset_mode <
   1632                        bk_svm_info->valid_offset_mode_start) {
   1633                 bk_svm_info->valid_offset_mode_start = e_offset_mode;
   1634             } else if (e_offset_mode >
   1635                        bk_svm_info->valid_offset_mode_end) {
   1636                 bk_svm_info->valid_offset_mode_end = e_offset_mode;
   1637             }
   1638             bk_svm_info->valid_offset_mode_cnt++;
   1639             if (bk_svm_info->empty_offset_mode_cnt > 0) {
   1640                 bk_svm_info->empty_offset_mode_cnt--;
   1641             }
   1642             *mode_id = OFFSET_MODE_TO_MODE_ID(e_offset_mode);
   1643 
   1644             /* Update the empty start, assume next one is real empty */
   1645             bk_svm_info->empty_offset_mode_start = e_offset_mode + 1;
   1646 
   1647             /* An empty id found, break and return BCM_E_NONE */
   1648             rv = BCM_E_NONE;
   1649             break;
   1650         } else {
   1651             /* Not empty id, and then update the bk empty start */
   1652 
   1653             /* Update the empty start, assume next one is real empty */
   1654             bk_svm_info->empty_offset_mode_start = e_offset_mode + 1;
   1655         }
   1656     }
   1657     GLOBAL_METER_BK_UNLOCK(unit);
   1658 
   1659     POL_FUNCTION_DEBUG(unit, "mode_id %d\n", *mode_id);
   1660     POL_FUNCTION_TRACE(unit, "OUT");
   1661     return rv;
   1662 }
   1663 
   1664 /*
   1665  * Function:
   1666  *   bcmi_esw_policer_group_mode_id_delete
   1667  * Purpose:
   1668  *   Destroy Customized Policer Group mode with given mode_id.
   1669  * Parameters:
   1670  *   unit     - (IN) unit number
   1671  *   mode_id  - (IN) Destroy Policer Group Mode with given mode_id
   1672  * Returns:
   1673  *   BCM_E_NONE - Success on destroying the given mode_id
   1674  */
   1675 STATIC int
   1676 bcmi_esw_policer_group_mode_id_delete(
   1677     int unit,
   1678     uint32 mode_id)
   1679 {
   1680     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   1681     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   1682     uint32 destroy_offset_mode;
   1683     uint32 n_valid_offset_mode;
   1684 
   1685     POL_FUNCTION_TRACE(unit, "IN");
   1686 
   1687     POL_FUNCTION_DEBUG(unit, "mode_id %d\n", mode_id);
   1688 
   1689     /* Initialization check */
   1690     CHECK_GLOBAL_METER_INIT(unit);
   1691     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1692 
   1693     bk_svm_info = BCMI_SVM_BK_GET(unit);
   1694     destroy_offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   1695     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, destroy_offset_mode);
   1696 
   1697     /* Free allocate memory allocated in bcmi_policer_svm_offset_mode_bk_t */
   1698     POL_MEM_FREE(bk_svm_mode_info->attr_selectors);
   1699     POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v);
   1700 
   1701     /* Reset bcmi_policer_svm_offset_mode_bk_t */
   1702     bcmi_policer_svm_offset_mode_bk_t_init(bk_svm_mode_info);
   1703 
   1704     GLOBAL_METER_BK_LOCK(unit);
   1705     /* Destroy bit map */
   1706     BCMI_OFFSET_MODE_ID_INTF_CLR(unit, destroy_offset_mode);
   1707 
   1708     /* Update empty start and end */
   1709     if (destroy_offset_mode < bk_svm_info->empty_offset_mode_start) {
   1710         bk_svm_info->empty_offset_mode_start = destroy_offset_mode;
   1711     } else if (destroy_offset_mode > bk_svm_info->empty_offset_mode_end) {
   1712         bk_svm_info->empty_offset_mode_end = destroy_offset_mode;
   1713     }
   1714 
   1715     /* Update valid, find a next valid start or next valid end */
   1716     n_valid_offset_mode = destroy_offset_mode;
   1717     if (bk_svm_info->valid_offset_mode_cnt > 1) {
   1718         if (n_valid_offset_mode == bk_svm_info->valid_offset_mode_start) {
   1719             do {
   1720                 n_valid_offset_mode++;
   1721             } while (BCMI_OFFSET_MODE_ID_INTF_GET(unit, n_valid_offset_mode) == 0);
   1722             bk_svm_info->valid_offset_mode_start = n_valid_offset_mode;
   1723         } else if (n_valid_offset_mode == bk_svm_info->valid_offset_mode_end) {
   1724             do {
   1725                 n_valid_offset_mode--;
   1726             } while (BCMI_OFFSET_MODE_ID_INTF_GET(unit, n_valid_offset_mode) == 0);
   1727             bk_svm_info->valid_offset_mode_end = n_valid_offset_mode;
   1728         }
   1729     }
   1730     bk_svm_info->valid_offset_mode_cnt--;
   1731     bk_svm_info->empty_offset_mode_cnt++;
   1732     GLOBAL_METER_BK_UNLOCK(unit);
   1733 
   1734     POL_FUNCTION_TRACE(unit, "OUT");
   1735     return BCM_E_NONE;
   1736 }
   1737 
   1738 /*
   1739  * Function:
   1740  *     bcmi_esw_policer_group_mode_id_associate
   1741  * Purpose:
   1742  *     This function is used to reserve svm meter mode and
   1743  *     update h/w register/table
   1744  * Parameters:
   1745  *     unit                  - (IN) unit number
   1746  *     flags                 - (IN) flags
   1747  *     group_mode_type       - (IN) type of group mode
   1748  *     pkt_attr_selectors    - (IN) tcam packet attribute selectors
   1749  *     mode_id               - (OUT) mode_id which used by policer group
   1750  * Returns:
   1751  *     BCM_E_XXX
   1752  */
   1753 STATIC int
   1754 bcmi_esw_policer_group_mode_id_associate(
   1755     int unit,
   1756     uint32 flags,
   1757     bcm_policer_group_mode_type_t group_mode_type,
   1758     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors,
   1759     uint32 *mode_id)
   1760 {
   1761     int rv = BCM_E_UNAVAIL;
   1762     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   1763     int sel = 0;
   1764     uint32 pkt_attr_v_cnt;
   1765 
   1766     POL_FUNCTION_TRACE(unit, "IN");
   1767 
   1768     /* Parameter NULL error handling */
   1769     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   1770     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   1771 
   1772     /* Initialization check */
   1773     CHECK_GLOBAL_METER_INIT(unit);
   1774     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1775     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   1776 
   1777     /* Check if the chip specific function existed */
   1778     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_type_supported);
   1779 
   1780     rv = gm_dev_info->group_mode_type_supported(unit, group_mode_type);
   1781     BCM_IF_ERROR_RETURN(rv);
   1782 
   1783     pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt;
   1784 
   1785     GLOBAL_METER_BK_LOCK(unit);
   1786     /* Check if TCAM size if enough or not */
   1787     rv = bcmi_policer_tcam_allocate_check(unit, pkt_attr_v_cnt);
   1788     if (BCM_FAILURE(rv)) {
   1789         GLOBAL_METER_BK_UNLOCK(unit);
   1790         return rv;
   1791     }
   1792 
   1793     /* Get an empty mode_id(offset_mode) */
   1794     rv = bcmi_esw_policer_group_empty_mode_id_get(unit, mode_id);
   1795     if (BCM_FAILURE(rv)) {
   1796         GLOBAL_METER_BK_UNLOCK(unit);
   1797         LOG_ERROR(BSL_LS_BCM_TSN,
   1798                   (BSL_META_U(unit,
   1799                               "no empty mode_id(rv = %d)\n"),
   1800                               rv));
   1801         return rv;
   1802     }
   1803 
   1804     /* Allocate empty TCAM for each pkt_attr_v with mode and offset_mode */
   1805     for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   1806         /* Assign an empty TCAM idx */
   1807         rv = bcmi_esw_policer_group_mode_fillup_tcam_idx(
   1808                 unit, &pkt_attr_selectors->pkt_attr_v[sel]);
   1809         if (BCM_FAILURE(rv)) {
   1810             /*
   1811              * This case shouldn't happen since the TCAM size is enough
   1812              * (already checked in above bcmi_policer_tcam_allocate_check)
   1813              */
   1814             GLOBAL_METER_BK_UNLOCK(unit);
   1815             return rv;
   1816         }
   1817 
   1818         /* Assign mode id */
   1819         pkt_attr_selectors->pkt_attr_v[sel].mode_id = *mode_id;
   1820         /* Assign offset_mode */
   1821         pkt_attr_selectors->pkt_attr_v[sel].offset_mode =
   1822             MODE_ID_TO_OFFSET_MODE(*mode_id);
   1823     }
   1824     GLOBAL_METER_BK_UNLOCK(unit);
   1825 
   1826     POL_FUNCTION_TRACE(unit, "OUT");
   1827     return BCM_E_NONE;
   1828 }
   1829 
   1830 /*
   1831  * Function:
   1832  *     bcmi_esw_policer_custom_group_mode_fillup_tcam_values
   1833  * Purpose:
   1834  *     Fill up temporary tcam structures in appropriate order for efficient
   1835  *     management of user input
   1836  * Parameters:
   1837  *     unit                  - (IN) unit number
   1838  *     pol_offset            - (IN) flags
   1839  *     attr                  - (IN) group mode packet attr type
   1840  *     attr_value            - (IN) attribute value
   1841  *     attr_value_mask       - (IN) mask of attribute value
   1842  *     pkt_attr_v            - (OUT) Packet TCAM attributes
   1843  * Returns:
   1844  *     BCM_E_XXX
   1845  */
   1846 STATIC int
   1847 bcmi_esw_policer_custom_group_mode_fillup_tcam_values(
   1848     int unit,
   1849     uint32 pol_offset,
   1850     bcm_policer_group_mode_attr_t attr,
   1851     uint32 attr_value,
   1852     uint32 attr_value_mask,
   1853     pkt_tcam_attr_bits_t *pkt_attr_v)
   1854 {
   1855     POL_FUNCTION_TRACE(unit, "IN");
   1856 
   1857     /* Parameter NULL error handling */
   1858     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_v);
   1859 
   1860     /* Initialization check */
   1861     CHECK_GLOBAL_METER_INIT(unit);
   1862 
   1863     /* "OR" the added attr to current attr_bits_selector */
   1864     pkt_attr_v->attr_bits_selector |= attr_to_bit_selector[attr];
   1865     pkt_attr_v->value[attr] = attr_value;
   1866     pkt_attr_v->value_mask[attr] = attr_value_mask;
   1867     pkt_attr_v->final_offset = pol_offset;
   1868 
   1869     POL_FUNCTION_TRACE(unit, "OUT");
   1870     return BCM_E_NONE;
   1871 }
   1872 
   1873 /*
   1874  * Function:
   1875  *     bcmi_esw_policer_custom_group_mode_fillup_values
   1876  * Purpose:
   1877  *     Fill up temporary structures in appropriate order for efficient
   1878  *     management of user input
   1879  * Parameters:
   1880  *     unit                  - (IN) unit number
   1881  *     flags                 - (IN) flags
   1882  *     group_mode_type       - (IN) type of group mode
   1883  *     total_policers        - (IN) total policers
   1884  *     num_selectors         - (IN) number of selectors
   1885  *     attr_selectors        - (IN) list of attributes selectors
   1886  *     pkt_attr_selectors    - (OUT) tcam packet attribute selectors
   1887  * Returns:
   1888  *     BCM_E_XXX
   1889  */
   1890 STATIC int
   1891 bcmi_esw_policer_custom_group_mode_fillup_values(
   1892     int unit,
   1893     uint32 flags,
   1894     bcm_policer_group_mode_type_t group_mode_type,
   1895     uint32 total_policers,
   1896     uint32 num_selectors,
   1897     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   1898     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
   1899 {
   1900     int rv;
   1901     uint32 sel = 0, mul_sel = 0;
   1902     uint32 pol_offset = 0, max_pol_offset = 0;
   1903     SHR_BITDCL *pol_offset_int_f_bitmap;
   1904     uint32 shr_bitdcl_size;
   1905     uint32 acutal_total_policers = 0;
   1906     bcm_policer_group_mode_attr_t attr;
   1907     uint32 attr_value = 0, attr_value_mask = 0;
   1908     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   1909 
   1910     POL_FUNCTION_TRACE(unit, "IN");
   1911 
   1912     /* Parameter NULL error handling */
   1913     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   1914     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   1915 
   1916     /* Initialization check */
   1917     CHECK_GLOBAL_METER_INIT(unit);
   1918     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   1919     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   1920 
   1921     /* Check if the chip specific function existed */
   1922     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_attr_validate);
   1923 
   1924     /* Loop all selectors checking if group_mode_attr & value is supported */
   1925     for (sel = 0; sel < num_selectors; sel++) {
   1926         if (BCM_POLICER_ATTR_MULTI & attr_selectors[sel].flags) {
   1927             for (mul_sel = 0;
   1928                  mul_sel < attr_selectors[sel].multi_attr_count;
   1929                  mul_sel++) {
   1930                 rv = gm_dev_info->group_mode_attr_validate(
   1931                         unit,
   1932                         attr_selectors[sel].multi_attr[mul_sel],
   1933                         attr_selectors[sel].multi_attr_value[mul_sel]);
   1934                 BCM_IF_ERROR_RETURN(rv);
   1935             }
   1936         } else {
   1937             rv = gm_dev_info->group_mode_attr_validate(
   1938                     unit,
   1939                     attr_selectors[sel].attr,
   1940                     attr_selectors[sel].attr_value);
   1941             BCM_IF_ERROR_RETURN(rv);
   1942         }
   1943     }
   1944 
   1945 #define POL_OFFSET_INTF_GET(_intf_) \
   1946         SHR_BITGET(pol_offset_int_f_bitmap, (_intf_))
   1947 #define POL_OFFSET_INTF_SET(_intf_) \
   1948         SHR_BITSET(pol_offset_int_f_bitmap, (_intf_))
   1949 
   1950     /* Allocate usage bitmap */
   1951     shr_bitdcl_size = SHR_BITALLOCSIZE(num_selectors);
   1952     pol_offset_int_f_bitmap =
   1953         sal_alloc(shr_bitdcl_size, "pol_offset_int_f_bitmap");
   1954     if (NULL == pol_offset_int_f_bitmap) {
   1955         LOG_ERROR(BSL_LS_BCM_TSN,
   1956                   (BSL_META_U(unit,
   1957                               "bcmi_esw_tsn_init: failed to "
   1958                               "allocate memory\n")));
   1959         return BCM_E_MEMORY;
   1960     }
   1961     sal_memset(pol_offset_int_f_bitmap, 0, shr_bitdcl_size);
   1962 
   1963     /* Loop all selectors */
   1964     for (sel = 0; sel < num_selectors; sel++) {
   1965 
   1966         /* make sure the attr bits selector is 0 */
   1967         pkt_attr_selectors->pkt_attr_v[sel].attr_bits_selector = 0;
   1968 
   1969         LOG_DEBUG(BSL_LS_BCM_POLICER,
   1970                   (BSL_META_U(unit,
   1971                               "pkt_attr_v [sel] %d:\n"
   1972                               "pol_offset %d, flags %d \n"),
   1973                               sel,
   1974                               attr_selectors[sel].policer_offset,
   1975                               attr_selectors[sel].flags));
   1976         /* Final Offset */
   1977         pol_offset = attr_selectors[sel].policer_offset;
   1978 
   1979         /* Record used Policer Offset */
   1980         if (!POL_OFFSET_INTF_GET(pol_offset)) {
   1981                 /* new Policer Offset found,
   1982                  * the same policer offset means the same policer
   1983                  */
   1984             POL_OFFSET_INTF_SET(pol_offset);
   1985             acutal_total_policers++;
   1986         }
   1987 
   1988         /* Record Maximum Policer Offset */
   1989         if (max_pol_offset < pol_offset) {
   1990             max_pol_offset = pol_offset;
   1991         }
   1992 
   1993         /* Fill attributes */
   1994         if (BCM_POLICER_ATTR_MULTI & attr_selectors[sel].flags) {
   1995             POL_FUNCTION_DEBUG(
   1996                 unit, "flag 0x%x, Multiple attributes for TCAM\n",
   1997                 attr_selectors[sel].flags);
   1998             /* Multiple attributes for TCAM */
   1999             for (mul_sel = 0;
   2000                  mul_sel < attr_selectors[sel].multi_attr_count;
   2001                  mul_sel++) {
   2002 
   2003                 attr = attr_selectors[sel].multi_attr[mul_sel];
   2004                 attr_value =
   2005                     attr_selectors[sel].multi_attr_value[mul_sel];
   2006                 attr_value_mask =
   2007                     attr_selectors[sel].multi_attr_value_mask[mul_sel];
   2008 
   2009                 /* Copy to pkt_attr_selectors */
   2010                 bcmi_esw_policer_custom_group_mode_fillup_tcam_values(
   2011                     unit,
   2012                     pol_offset,
   2013                     attr,
   2014                     attr_value,
   2015                     attr_value_mask,
   2016                     &pkt_attr_selectors->pkt_attr_v[sel]);
   2017             }
   2018         }
   2019         else {
   2020             POL_FUNCTION_DEBUG(
   2021                 unit, "flag 0x%x, Single attribute for TCAM\n",
   2022                 attr_selectors[sel].flags);
   2023             /* Single attribute for TCAM */
   2024             attr = attr_selectors[sel].attr;
   2025             attr_value = attr_selectors[sel].attr_value;
   2026             attr_value_mask = attr_selectors[sel].attr_value_mask;
   2027 
   2028             /* Copy to pkt_attr_selectors */
   2029             bcmi_esw_policer_custom_group_mode_fillup_tcam_values(
   2030                 unit,
   2031                 pol_offset,
   2032                 attr,
   2033                 attr_value,
   2034                 attr_value_mask,
   2035                 &pkt_attr_selectors->pkt_attr_v[sel]);
   2036         }
   2037         (void)bcmi_policer_tcam_attr_dump(
   2038                 unit, "pkt_attr_v", &pkt_attr_selectors->pkt_attr_v[sel]);
   2039     }
   2040 
   2041     /* Give pkt_attr_v(TCAM entries) number */
   2042     pkt_attr_selectors->pkt_attr_v_cnt = num_selectors;
   2043 
   2044     /* Check if total_policers equal to acutal_total_policers */
   2045     if (total_policers != acutal_total_policers) {
   2046         POL_MEM_FREE(pol_offset_int_f_bitmap);
   2047         LOG_ERROR(BSL_LS_BCM_POLICER,
   2048                   (BSL_META_U(unit,
   2049                               "total_policers(%d) should equal to "
   2050                               "acutal_total_policers(%d)\n"),
   2051                               total_policers,
   2052                               acutal_total_policers));
   2053         return BCM_E_PARAM;
   2054     }
   2055 
   2056     /* Check Maximum Policer Offset match calculated total policer # */
   2057     if (max_pol_offset != acutal_total_policers - 1) {
   2058         POL_MEM_FREE(pol_offset_int_f_bitmap);
   2059         LOG_ERROR(BSL_LS_BCM_POLICER,
   2060                   (BSL_META_U(unit,
   2061                               "Maximum policer offset(%d) should equal to"
   2062                               " acutal_total_policers(%d) - 1.\n"
   2063                               "Please check 'policer_offset' of "
   2064                               " bcm_policer_group_mode_attr_selector_t\n"),
   2065                               max_pol_offset,
   2066                               max_pol_offset));
   2067         return BCM_E_PARAM;
   2068     }
   2069 
   2070     /* Free memory */
   2071     POL_MEM_FREE(pol_offset_int_f_bitmap);
   2072 
   2073     /* Give total policer number */
   2074     pkt_attr_selectors->total_policers = total_policers;
   2075 
   2076     POL_FUNCTION_DEBUG(unit, "total_policers %d", total_policers);
   2077 
   2078     POL_FUNCTION_TRACE(unit, "OUT");
   2079     return BCM_E_NONE;
   2080 }
   2081 
   2082 /*
   2083  * Function:
   2084  *     bcmi_esw_policer_custom_group_mode_id_existed_check
   2085  * Purpose:
   2086  *     Check if given attribute selectors list is already
   2087  *     configured or not
   2088  * Parameters:
   2089  *     unit                  - (IN) unit number
   2090  *     flags                 - (IN) flags
   2091  *     group_mode_type       - (IN) type of group mode
   2092  *     num_selectors         - (IN) number of selectors
   2093  *     attr_selectors        - (IN) list of attributes selectors
   2094  *     mode_id               - (OUT) pointer to meter mode_id
   2095  * Returns:
   2096  *     BCM_E_XXX
   2097  */
   2098 STATIC int
   2099 bcmi_esw_policer_custom_group_mode_id_existed_check(
   2100     uint32 unit,
   2101     uint32 flags,
   2102     bcm_policer_group_mode_type_t group_mode_type,
   2103     uint32 num_selectors,
   2104     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   2105     uint32 *mode_id)
   2106 {
   2107     uint32 offset_mode_idx = 0;
   2108     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   2109     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   2110 
   2111     POL_FUNCTION_TRACE(unit, "IN");
   2112 
   2113     /* Parameter NULL error handling */
   2114     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   2115     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2116 
   2117     /* Initialization check */
   2118     CHECK_GLOBAL_METER_INIT(unit);
   2119     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2120     bk_svm_info = BCMI_SVM_BK_GET(unit);
   2121 
   2122     /* No valid mode_id */
   2123     if (bk_svm_info->valid_offset_mode_cnt == 0) {
   2124         POL_FUNCTION_TRACE(unit, "OUT No valid mode_id");
   2125         return BCM_E_NONE;
   2126     }
   2127 
   2128     /* Loop through all valid mode_id and try to find a match one */
   2129     for (offset_mode_idx = bk_svm_info->valid_offset_mode_start;
   2130          offset_mode_idx <= bk_svm_info->valid_offset_mode_end;
   2131          offset_mode_idx++) {
   2132 
   2133         if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode_idx)) {
   2134             continue;
   2135         }
   2136 
   2137         bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode_idx);
   2138         if (bk_svm_mode_info->group_mode_type != group_mode_type) {
   2139             continue;
   2140         }
   2141 
   2142         /* Check num selectors */
   2143         if (bk_svm_mode_info->no_of_attr_selectors == num_selectors) {
   2144             if (bk_svm_mode_info->attr_selectors != NULL) {
   2145                 if (sal_memcmp(&attr_selectors[0],
   2146                                bk_svm_mode_info->attr_selectors,
   2147                                sizeof(bcm_policer_group_mode_attr_selector_t) *
   2148                                num_selectors) == 0) {
   2149                     *mode_id = OFFSET_MODE_TO_MODE_ID(offset_mode_idx);
   2150                     LOG_ERROR(BSL_LS_BCM_POLICER,
   2151                               (BSL_META_U(unit,
   2152                                           "Same attr_selectors existed")));
   2153                     return BCM_E_EXISTS;
   2154                 }
   2155             }
   2156         }
   2157     }
   2158     POL_FUNCTION_TRACE(unit, "OUT");
   2159     return BCM_E_NONE;
   2160 }
   2161 
   2162 /*
   2163  * Function:
   2164  *     bcmi_esw_policer_custom_group_mode_id_info_update
   2165  * Purpose:
   2166  *     update offset mode info
   2167  * Parameters:
   2168  *     unit                  - (IN) unit number
   2169  *     mode_id               - (IN) meter mode_id
   2170  *     group_mode_type       - (IN) type of group mode
   2171  *     num_selectors         - (IN) number of selectors
   2172  *     attr_selectors        - (IN) list of attributes selectors
   2173  *     pkt_attr_selectors    - (IN) tcam packet attribute selectors
   2174  * Returns:
   2175  *     BCM_E_XXX
   2176  */
   2177 STATIC int
   2178 bcmi_esw_policer_custom_group_mode_id_info_update(
   2179     int unit,
   2180     bcm_policer_svc_meter_mode_t mode_id,
   2181     bcm_policer_group_mode_type_t group_mode_type,
   2182     int num_selectors,
   2183     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   2184     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
   2185 {
   2186     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   2187     int sel;
   2188     uint32 total_policers;
   2189     uint32 offset_mode;
   2190 
   2191     POL_FUNCTION_TRACE(unit, "IN");
   2192 
   2193     /* Parameter NULL error handling */
   2194     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   2195     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   2196 
   2197     /* Initialization check */
   2198     CHECK_GLOBAL_METER_INIT(unit);
   2199     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2200 
   2201     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   2202     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   2203 
   2204     total_policers = pkt_attr_selectors->total_policers;
   2205 
   2206     bk_svm_mode_info->no_of_policers = total_policers;
   2207     bk_svm_mode_info->is_custom_group = TRUE;
   2208     bk_svm_mode_info->group_mode_type = group_mode_type;
   2209     bk_svm_mode_info->used = 1;
   2210 
   2211     POL_FUNCTION_DEBUG(unit, "mode_id %d", mode_id);
   2212     POL_FUNCTION_DEBUG(unit, "offset_mode %d", offset_mode);
   2213     POL_FUNCTION_DEBUG(unit, "group_mode_type %d", group_mode_type);
   2214     POL_FUNCTION_DEBUG(unit, "num_selectors %d", num_selectors);
   2215     POL_FUNCTION_DEBUG(unit, "total_policers %d", total_policers);
   2216 
   2217     /* Store bcm_policer_group_mode_attr_selector_t start */
   2218 
   2219     /* Free memory */
   2220     POL_MEM_FREE(bk_svm_mode_info->attr_selectors);
   2221 
   2222     bk_svm_mode_info->no_of_attr_selectors = num_selectors;
   2223 
   2224     POL_MEM_ALLOC(
   2225         bk_svm_mode_info->attr_selectors,
   2226         num_selectors * sizeof(bcm_policer_group_mode_attr_selector_t),
   2227         "attr selectors");
   2228     if (NULL == bk_svm_mode_info->attr_selectors) {
   2229         LOG_ERROR(BSL_LS_BCM_POLICER,
   2230                   (BSL_META_U(unit,
   2231                               "Unable to allocate memory for "
   2232                               "attr_selectors\n")));
   2233         return BCM_E_MEMORY;
   2234     }
   2235     sal_memcpy(bk_svm_mode_info->attr_selectors,
   2236                attr_selectors,
   2237                sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors);
   2238     /* Store bcm_policer_group_mode_attr_selector_t end */
   2239 
   2240     /* Store pkt_tcam_attr_bits_t start */
   2241     POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v);
   2242 
   2243     bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt;
   2244 
   2245     POL_MEM_ALLOC(
   2246         bk_svm_mode_info->pkt_attr_v,
   2247         bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t),
   2248         "pkt_attr_v in offset mode instance");
   2249     if (NULL == bk_svm_mode_info->pkt_attr_v) {
   2250         LOG_ERROR(BSL_LS_BCM_POLICER,
   2251                   (BSL_META_U(unit,
   2252                               "Unable to allocate memory for "
   2253                               "pkt_attr_v\n")));
   2254         return (BCM_E_MEMORY);
   2255     }
   2256 
   2257     for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt ; sel++) {
   2258         sal_memcpy(&bk_svm_mode_info->pkt_attr_v[sel],
   2259                    &pkt_attr_selectors->pkt_attr_v[sel],
   2260                    sizeof(pkt_tcam_attr_bits_t));
   2261     }
   2262     /* Configured TCAM HW with pkt_attr_selectors */
   2263     BCM_IF_ERROR_RETURN(
   2264         bcmi_policer_tcam_configurate_hw(unit, pkt_attr_selectors));
   2265 
   2266     /* Store pkt_tcam_attr_bits_t end */
   2267     POL_FUNCTION_TRACE(unit, "OUT");
   2268     return BCM_E_NONE;
   2269 }
   2270 
   2271 /*
   2272  * Function:
   2273  *     bcmi_esw_policer_custom_group_mode_id_create
   2274  * Purpose:
   2275  *     This function is used to configure customized group mode
   2276  * Parameters:
   2277  *     unit                  - (IN) unit number
   2278  *     flags                 - (IN) flags
   2279  *     group_mode_type       - (IN) type of group mode
   2280  *     total_policers        - (IN) total policers
   2281  *     num_selectors         - (IN) number of selectors
   2282  *     attr_selectors        - (IN) list of attributes selectors
   2283  *     mode_id               - (OUT) pointer to meter mode_id
   2284  * Returns:
   2285  *     BCM_E_XXX
   2286  */
   2287 STATIC int
   2288 bcmi_esw_policer_custom_group_mode_id_create(
   2289     int unit,
   2290     uint32 flags,
   2291     bcm_policer_group_mode_type_t group_mode_type,
   2292     uint32 total_policers,
   2293     uint32 num_selectors,
   2294     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   2295     uint32 *mode_id)
   2296 {
   2297     int rv = BCM_E_UNAVAIL;
   2298     bcmi_policer_tcam_attr_selectors_t pkt_attr_selectors;
   2299 
   2300     POL_FUNCTION_TRACE(unit, "IN");
   2301 
   2302     /* Parameter NULL error handling */
   2303     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   2304     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2305 
   2306     /* Initialization check */
   2307     CHECK_GLOBAL_METER_INIT(unit);
   2308     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2309 
   2310     /* Check if mode info already exists */
   2311     rv = bcmi_esw_policer_custom_group_mode_id_existed_check(
   2312             unit, flags, group_mode_type,
   2313             num_selectors, attr_selectors, mode_id);
   2314     BCM_IF_ERROR_RETURN(rv);
   2315 
   2316     (void)bcmi_policer_tcam_attr_selectors_t_init(&pkt_attr_selectors);
   2317     POL_MEM_ALLOC(
   2318         pkt_attr_selectors.pkt_attr_v,
   2319         sizeof(pkt_tcam_attr_bits_t) * BCMI_POLICER_SVC_METER_TCAM_SIZE,
   2320         "allocate pkt_attr_v");
   2321 
   2322     /* Create temportary pkt information from selectors */
   2323     rv = bcmi_esw_policer_custom_group_mode_fillup_values(
   2324             unit, flags, group_mode_type,
   2325             total_policers, num_selectors, attr_selectors,
   2326             &pkt_attr_selectors);
   2327     if (BCM_FAILURE(rv)) {
   2328         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   2329         return rv;
   2330     }
   2331 
   2332     GLOBAL_METER_LOCK(unit);
   2333     /* Add a new mode_id associated with pkt_attr_selectors information */
   2334     rv = bcmi_esw_policer_group_mode_id_associate(unit,
   2335             flags, group_mode_type, &pkt_attr_selectors, mode_id);
   2336     if (BCM_FAILURE(rv)) {
   2337         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   2338         GLOBAL_METER_UNLOCK(unit);
   2339         return rv;
   2340     }
   2341 
   2342     /* Update above pkt information to bookkeeping */
   2343     rv = bcmi_esw_policer_custom_group_mode_id_info_update(
   2344             unit, *mode_id, group_mode_type, num_selectors,
   2345             attr_selectors, &pkt_attr_selectors);
   2346     if (BCM_FAILURE(rv)) {
   2347         /* Delete the offset mode SW database */
   2348         bcmi_esw_policer_group_mode_id_delete(unit, *mode_id);
   2349         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   2350         GLOBAL_METER_UNLOCK(unit);
   2351         return rv;
   2352     }
   2353     POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   2354     GLOBAL_METER_UNLOCK(unit);
   2355 
   2356     POL_FUNCTION_TRACE(unit, "OUT");
   2357     return rv;
   2358 }
   2359 
   2360 /*
   2361  * Function:
   2362  *     bcmi_esw_policer_group_mode_id_existed_check
   2363  * Purpose:
   2364  *     Check if given attribute selectors list is already
   2365  *     configured or not
   2366  * Parameters:
   2367  *     unit                  - (IN) unit number
   2368  *     group_mode            - (IN) Policer group mode
   2369  *     npolicers             - (IN) Number of policers
   2370  *     pkt_attr_selectors    - (IN) tcam packet attribute selectors
   2371  *     mode_id               - (OUT) pointer to found existed mode_id
   2372  *     existed               - (OUT) existed or not existed
   2373  * Returns:
   2374  *     BCM_E_XXX
   2375  */
   2376 STATIC int
   2377 bcmi_esw_policer_group_mode_id_existed_check(
   2378     int unit,
   2379     bcm_policer_group_mode_t group_mode,
   2380     int npolicers,
   2381     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors,
   2382     uint32 *mode_id,
   2383     int *existed)
   2384 {
   2385     uint32 offset_mode_idx = 0;
   2386     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   2387     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   2388 
   2389     POL_FUNCTION_TRACE(unit, "IN");
   2390 
   2391     /* Parameter NULL error handling */
   2392     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   2393     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2394     POL_CHECK_NULL_PARAMETER(unit, existed);
   2395 
   2396     POL_FUNCTION_DEBUG(unit, "group_mode %d", group_mode);
   2397     POL_FUNCTION_DEBUG(unit, "group_mode %s",
   2398         bcm_policer_group_mode_t_str[group_mode]);
   2399     POL_FUNCTION_DEBUG(unit, "npolicers %d", npolicers);
   2400 
   2401     *existed = FALSE;
   2402 
   2403     /* Initialization check */
   2404     CHECK_GLOBAL_METER_INIT(unit);
   2405     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2406     bk_svm_info = BCMI_SVM_BK_GET(unit);
   2407 
   2408     /* No valid mode_id */
   2409     if (bk_svm_info->valid_offset_mode_cnt == 0) {
   2410         /* no exsiting mode_id, thus don't need to check */
   2411         POL_FUNCTION_TRACE(unit, "OUT");
   2412         return BCM_E_NONE;
   2413     }
   2414 
   2415     /* Loop through all valid mode_id and try to find a match one */
   2416     for (offset_mode_idx = bk_svm_info->valid_offset_mode_start;
   2417          offset_mode_idx <= bk_svm_info->valid_offset_mode_end;
   2418          offset_mode_idx++) {
   2419 
   2420         if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode_idx)) {
   2421             continue;
   2422         }
   2423 
   2424         bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode_idx);
   2425         if (bk_svm_mode_info->group_mode != group_mode) {
   2426             continue;
   2427         }
   2428         if (bk_svm_mode_info->no_of_policers != npolicers) {
   2429             continue;
   2430         }
   2431         *mode_id = OFFSET_MODE_TO_MODE_ID(offset_mode_idx);
   2432         *existed = TRUE;
   2433         POL_FUNCTION_TRACE(unit, "OUT");
   2434         return BCM_E_NONE;
   2435     }
   2436     POL_FUNCTION_TRACE(unit, "OUT");
   2437     return BCM_E_NONE;
   2438 }
   2439 
   2440 /*
   2441  * Function:
   2442  *     bcmi_esw_policer_group_mode_id_create
   2443  * Purpose:
   2444  *     Create Customized Policer Group mode for given Policer Attributes
   2445  * Parameters:
   2446  *     unit                  - (IN) unit number
   2447  *     flags                 - (IN) flags
   2448  *     group_mode_type       - (IN) modes of policer group creation -
   2449  *                                  normal/cascade/cascade with coupling.
   2450  *     total_policers        - (IN) Total Policers in Policer Group Mode
   2451  *     num_selectors         - (IN) Number of Selectors for policer Group Mode
   2452  *     attr_selectors        - (IN) Attribute Selectors for Policer Group Mode
   2453  *     mode_id               - (OUT) Created mode Id for Policer Group Mode
   2454  * Returns:
   2455  *     BCM_E_XXX
   2456  */
   2457 
   2458 STATIC int
   2459 bcmi_esw_policer_group_mode_id_create(
   2460     int unit,
   2461     uint32 flags,
   2462     bcm_policer_group_mode_type_t group_mode_type,
   2463     uint32 total_policers,
   2464     uint32 num_selectors,
   2465     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   2466     uint32 *mode_id)
   2467 {
   2468     bcm_error_t rv = BCM_E_UNAVAIL;
   2469 
   2470     POL_FUNCTION_TRACE(unit, "IN");
   2471 
   2472     /* Parameter NULL error handling */
   2473     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2474 
   2475     /* Initialization check */
   2476     CHECK_GLOBAL_METER_INIT(unit);
   2477     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2478 
   2479     if (group_mode_type >= bcmPolicerGroupModeTypeCount) {
   2480         return (BCM_E_PARAM);
   2481     }
   2482 
   2483     /* Attribute selectors are used for selecting one of the policers created in
   2484      * policer group. For total_policer = 1 there is just one policer.
   2485      * Hence, attribute selectors have no significance.
   2486      * All other IN parameters are set fixed to avoid any confusion
   2487      * while fetching group policer config via bcm_policer_group_mode_id_get()
   2488      */
   2489     if (total_policers == 1) {
   2490         if ((group_mode_type == bcmPolicerGroupModeTypeNormal) &&
   2491             (attr_selectors == NULL) &&
   2492             (num_selectors == 0)) {
   2493             *mode_id = 1;
   2494             return (BCM_E_NONE);
   2495         } else {
   2496             return (BCM_E_PARAM);
   2497         }
   2498     }
   2499 
   2500     /* Parameter NULL error handling */
   2501     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   2502     if ((total_policers == 0) || (num_selectors == 0)) {
   2503         return (BCM_E_PARAM);
   2504     }
   2505 
   2506     if ((group_mode_type == bcmPolicerGroupModeTypeNormal) &&
   2507         (num_selectors > BCMI_POLICER_SVC_METER_TCAM_SIZE)) {
   2508         return (BCM_E_PARAM);
   2509     }
   2510 
   2511     rv = bcmi_esw_policer_custom_group_mode_id_create(
   2512             unit, flags, group_mode_type,
   2513             total_policers, num_selectors, attr_selectors, mode_id);
   2514     if (BCM_FAILURE(rv)) {
   2515         LOG_ERROR(BSL_LS_BCM_POLICER,
   2516                   (BSL_META_U(unit,
   2517                               "Unable to create policer group\n")));
   2518         return (rv);
   2519     }
   2520 
   2521     POL_FUNCTION_DEBUG(unit,
   2522         "Created policer group with mode id %x \n", *mode_id);
   2523     POL_FUNCTION_TRACE(unit, "OUT");
   2524     return rv;
   2525 }
   2526 
   2527 /*
   2528  * Function:
   2529  *     bcmi_esw_policer_group_mode_id_get
   2530  * Purpose:
   2531  *     Retrieves Customized Policer Group mode Attributes for given mode_id.
   2532  * Parameters:
   2533  *     unit                  - (IN) unit number
   2534  *     mode_id               - (IN) Created mode Id for Policer Group Mode
   2535  *     num_selectors         - (IN) Number of Selectors for policer Group Mode
   2536  *     flags                 - (OUT) flags
   2537  *     group_mode_type       - (OUT) modes of policer group creation -
   2538  *                                   normal/cascade/cascade with coupling.
   2539  *     total_policers        - (OUT) Total Policers in Policer Group Mode
   2540  *     attr_selectors        - (OUT) Attribute Selectors for Policer Group Mode
   2541  *     actual_num_selectors  - (OUT) Actual Number of Selectors for Policer
   2542  *                                   Group Mode
   2543  * Returns:
   2544  *     BCM_E_XXX
   2545  */
   2546 STATIC int
   2547 bcmi_esw_policer_group_mode_id_get(
   2548     int unit,
   2549     uint32 mode_id,
   2550     uint32 num_selectors,
   2551     uint32 *flags,
   2552     bcm_policer_group_mode_type_t *group_mode_type,
   2553     uint32 *total_policers,
   2554     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   2555     uint32 *actual_num_selectors)
   2556 {
   2557     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   2558     uint32 offset_mode;
   2559     int i = 0;
   2560 
   2561     POL_FUNCTION_TRACE(unit, "IN");
   2562 
   2563     /* Parameter NULL error handling */
   2564     POL_CHECK_NULL_PARAMETER(unit, flags);
   2565     POL_CHECK_NULL_PARAMETER(unit, group_mode_type);
   2566     POL_CHECK_NULL_PARAMETER(unit, total_policers);
   2567     POL_CHECK_NULL_PARAMETER(unit, attr_selectors);
   2568     POL_CHECK_NULL_PARAMETER(unit, actual_num_selectors);
   2569 
   2570     /* Initialization check */
   2571     CHECK_GLOBAL_METER_INIT(unit);
   2572     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2573 
   2574     /* Validate mode_id */
   2575     BCM_IF_ERROR_RETURN(
   2576         bcmi_policer_mode_id_validate(unit, mode_id));
   2577 
   2578     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   2579     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   2580 
   2581     *total_policers = bk_svm_mode_info->no_of_policers;
   2582     *actual_num_selectors = bk_svm_mode_info->no_of_attr_selectors;
   2583     *group_mode_type = bk_svm_mode_info->group_mode_type;
   2584 
   2585     if (*actual_num_selectors > num_selectors) {
   2586         return (BCM_E_PARAM);
   2587     }
   2588 
   2589     for (i = 0; i < *actual_num_selectors; i++) {
   2590         sal_memcpy (&attr_selectors[i],
   2591                     &bk_svm_mode_info->attr_selectors[i],
   2592                     sizeof(bcm_policer_group_mode_attr_selector_t));
   2593     }
   2594     POL_FUNCTION_TRACE(unit, "OUT");
   2595     return BCM_E_NONE;
   2596 }
   2597 
   2598 /*
   2599  * Function:
   2600  *   bcmi_esw_policer_group_mode_id_destroy
   2601  * Purpose:
   2602  *   Destroy Customized Policer Group mode with given mode_id.
   2603  * Parameters:
   2604  *   unit     - (IN) unit number
   2605  *   mode_id  - (IN) Destroy Policer Group Mode with given mode Id
   2606  * Returns:
   2607  *   BCM_E_NONE - Success on destroying the given mode_id
   2608  */
   2609 STATIC int
   2610 bcmi_esw_policer_group_mode_id_destroy(
   2611     int unit,
   2612     uint32 mode_id)
   2613 {
   2614     bcm_error_t rv = BCM_E_UNAVAIL;
   2615     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   2616     uint32 offset_mode;
   2617 
   2618     POL_FUNCTION_TRACE(unit, "IN");
   2619     POL_FUNCTION_DEBUG(unit, "mode_id %d\n", mode_id);
   2620 
   2621     /* Initialization check */
   2622     CHECK_GLOBAL_METER_INIT(unit);
   2623     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2624 
   2625     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   2626     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   2627 
   2628     if (bk_svm_mode_info->ref_cnt > 0) {
   2629         LOG_WARN(BSL_LS_BCM_POLICER,
   2630                  (BSL_META_U(unit,
   2631                              "Policer group mode is still in use \n")));
   2632         return (BCM_E_BUSY);
   2633     }
   2634     /* Destory SW & HW of allocated offset mode */
   2635     rv = bcmi_policer_svc_meter_delete_mode(unit, offset_mode);
   2636 
   2637     POL_FUNCTION_TRACE(unit, "OUT");
   2638     return rv;
   2639 }
   2640 
   2641 #endif /* MODE_ID_API_SECTION */
   2642 
   2643 #if POLICER_ID_API_SECTION
   2644 /*
   2645  * Function:
   2646  *     global_meter_policer_id_alloc
   2647  * Purpose:
   2648  *     Allocate a new policer.
   2649  * Parameters:
   2650  *     unit                  - (IN) unit number
   2651  *     numbers               - (IN/OUT) Number of policers
   2652  *     pid                   - (OUT) base policer id
   2653  * Returns:
   2654  *     BCM_E_XXX
   2655  */
   2656 STATIC int
   2657 bcmi_global_meter_policer_id_alloc(
   2658     int unit,
   2659     int numbers,
   2660     bcm_policer_t *pid)
   2661 {
   2662     int rv = BCM_E_NONE;
   2663 
   2664     POL_FUNCTION_TRACE(unit, "IN");
   2665 
   2666     /* Parameter NULL error handling */
   2667     POL_CHECK_NULL_PARAMETER(unit, pid);
   2668 
   2669     if (!(numbers > 0)) {
   2670         return BCM_E_PARAM;
   2671     }
   2672 
   2673     /* Initialization check */
   2674     CHECK_GLOBAL_METER_INIT(unit);
   2675 
   2676     rv = shr_aidxres_list_alloc_block(
   2677             BCMI_POLICER_LIST_HANDLE_GET(unit),
   2678             numbers,
   2679             (uint32 *)pid);
   2680     BCM_IF_ERROR_RETURN(rv);
   2681 
   2682     POL_FUNCTION_DEBUG(
   2683         unit, "allocated %d policers\n", numbers);
   2684     POL_FUNCTION_DEBUG(
   2685         unit, "allocated policer with pid %d", *pid);
   2686 
   2687     POL_FUNCTION_TRACE(unit, "OUT");
   2688     return rv;
   2689 }
   2690 
   2691 /*
   2692  * Function:
   2693  *     bcmi_global_meter_free_allocated_policer_on_error
   2694  * Purpose:
   2695  *     Clean up the internal data structure in case of error.
   2696  * Parameters:
   2697  *     unit                  - (IN) unit number
   2698  *     numbers               - (IN) Number of policer to be freed
   2699  *     policer_index         - (IN) Base policer id
   2700  * Returns:
   2701  *     BCM_E_XXX
   2702  */
   2703 STATIC int
   2704 bcmi_global_meter_free_allocated_policer_on_error(
   2705     int unit,
   2706     uint32 numbers,
   2707     uint32 policer_index)
   2708 {
   2709     int rv = BCM_E_NONE;
   2710     int base_index = 0, index = 0;
   2711 
   2712     POL_FUNCTION_TRACE(unit, "IN");
   2713 
   2714     /* Initialization check */
   2715     CHECK_GLOBAL_METER_INIT(unit);
   2716     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2717 
   2718     for (index = 0;index < numbers; index++) {
   2719         base_index = policer_index + index;
   2720         rv = shr_aidxres_list_free(
   2721                 BCMI_POLICER_LIST_HANDLE_GET(unit),
   2722                 base_index);
   2723         if (BCM_FAILURE(rv)) {
   2724             LOG_DEBUG(BSL_LS_BCM_POLICER,
   2725                       (BSL_META_U(unit,
   2726                                   "Unable to free policer handle \n")));
   2727             return BCM_E_INTERNAL;
   2728         }
   2729     }
   2730     POL_FUNCTION_TRACE(unit, "OUT");
   2731     return rv;
   2732 }
   2733 
   2734 /*
   2735  * Function:
   2736  *     bcmi_global_meter_policer_control_alloc
   2737  * Purpose:
   2738  *     Allocate a new bcmi_global_meter_policer_control_t.
   2739  * Parameters:
   2740  *     unit                  - (IN) unit number
   2741  *     npolicers             - (IN) Number of policers created
   2742  *     policer_control       - (OUT) Policer control info
   2743  * Returns:
   2744  *     BCM_E_XXX
   2745  */
   2746 STATIC int
   2747 bcmi_global_meter_policer_control_alloc(
   2748     int unit,
   2749     uint32 npolicers,
   2750     bcmi_global_meter_policer_control_t **policer_control)
   2751 {
   2752     POL_FUNCTION_TRACE(unit, "IN");
   2753 
   2754     POL_CHECK_NULL_PARAMETER(unit, policer_control);
   2755 
   2756     POL_MEM_ALLOC(
   2757         *policer_control,
   2758         sizeof(bcmi_global_meter_policer_control_t),
   2759         "Global meter policer");
   2760     if (NULL == (*policer_control)) {
   2761         return (BCM_E_MEMORY);
   2762     }
   2763     (void)bcmi_global_meter_policer_control_t_init(*policer_control);
   2764 
   2765     POL_MEM_ALLOC(
   2766         (*policer_control)->pol_cfg,
   2767         sizeof(bcm_policer_config_t) * npolicers,
   2768         "pol_cfg of Global meter policer");
   2769 
   2770     if (NULL == (*policer_control)->pol_cfg) {
   2771         POL_MEM_FREE(*policer_control);
   2772         return (BCM_E_MEMORY);
   2773     }
   2774     POL_FUNCTION_TRACE(unit, "OUT");
   2775     return BCM_E_NONE;
   2776 }
   2777 
   2778 /*
   2779  * Function:
   2780  *     bcmi_policer_svc_meter_create_mode
   2781  * Purpose:
   2782  *     Function to create an offset mode with uncompressed packet attributes
   2783  * Parameters:
   2784  *     Unit                  - (IN) unit number
   2785  *     pkt_attr_selectors    - (IN) tcam packet attribute selectors
   2786  *     group_mode            - (IN) Policer group mode
   2787  *     mode_id               - (OUT) Meter mode id
   2788  * Returns:
   2789  *     BCM_E_XXX
   2790  */
   2791 STATIC int
   2792 bcmi_policer_svc_meter_create_mode(
   2793     int unit,
   2794     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors,
   2795     bcm_policer_group_mode_t group_mode,
   2796     bcm_policer_group_mode_type_t group_mode_type,
   2797     uint32 *mode_id)
   2798 {
   2799     bcm_error_t rv = BCM_E_NONE;
   2800     uint32 flags = 0;
   2801 
   2802     POL_FUNCTION_TRACE(unit, "IN");
   2803 
   2804     /* Input parameters check. */
   2805     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   2806     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2807 
   2808     /* Initialization check */
   2809     CHECK_GLOBAL_METER_INIT(unit);
   2810     GLOBAL_METER_LOCK(unit);
   2811 
   2812     /* Add a new mode_id associated with pkt_attr_selectors information */
   2813     rv = bcmi_esw_policer_group_mode_id_associate(unit,
   2814             flags, group_mode_type, pkt_attr_selectors, mode_id);
   2815     if (BCM_FAILURE(rv)) {
   2816         GLOBAL_METER_UNLOCK(unit);
   2817         return rv;
   2818     }
   2819     GLOBAL_METER_UNLOCK(unit);
   2820 
   2821     POL_FUNCTION_TRACE(unit, "OUT");
   2822     return rv;
   2823 }
   2824 
   2825 /*
   2826  * Function:
   2827  *     bcmi_esw_policer_svc_meter_create_mode
   2828  * Purpose:
   2829  *     Function to create an Meter offset mode
   2830  * Parameters:
   2831  *     Unit                  - (IN) unit number
   2832  *     pkt_attr_selectors    - (IN) Packet attribute selectors
   2833  *     group_mode            - (IN) Policer group mode
   2834  *     group_mode_type       - (IN) Policer group mode type
   2835  *     npolicers             - (IN) Number of policers created
   2836  *     mode_id               - (OUT) Meter mode id
   2837  * Returns:
   2838  *     BCM_E_XXX
   2839  */
   2840 STATIC int
   2841 bcmi_esw_policer_svc_meter_create_mode(
   2842     int unit,
   2843     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors,
   2844     bcm_policer_group_mode_t group_mode,
   2845     bcm_policer_group_mode_type_t group_mode_type,
   2846     int npolicers,
   2847     uint32 *mode_id)
   2848 {
   2849     bcm_error_t rv = BCM_E_UNAVAIL;
   2850     int existed;
   2851     bcm_policer_svc_meter_mode_t offset_mode;
   2852 
   2853     POL_FUNCTION_TRACE(unit, "IN");
   2854 
   2855     /* Input parameters check. */
   2856     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   2857     POL_CHECK_NULL_PARAMETER(unit, mode_id);
   2858 
   2859     /* Initialization check */
   2860     CHECK_GLOBAL_METER_INIT(unit);
   2861     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   2862 
   2863     /* Check if mode info already exists */
   2864     rv = bcmi_esw_policer_group_mode_id_existed_check(
   2865             unit, group_mode, npolicers,
   2866             pkt_attr_selectors, mode_id, &existed);
   2867     BCM_IF_ERROR_RETURN(rv);
   2868 
   2869     if (existed) {
   2870         POL_FUNCTION_DEBUG(
   2871             unit, "mode_id %d already existed", *mode_id);
   2872     } else {
   2873         rv = bcmi_policer_svc_meter_create_mode(
   2874                 unit, pkt_attr_selectors, group_mode,
   2875                 group_mode_type, mode_id);
   2876         BCM_IF_ERROR_RETURN(rv);
   2877         offset_mode = MODE_ID_TO_OFFSET_MODE(*mode_id);
   2878 
   2879         rv = bcmi_policer_svc_meter_reserve_mode(
   2880                 unit, offset_mode, group_mode,
   2881                 group_mode_type, npolicers, pkt_attr_selectors);
   2882         BCM_IF_ERROR_RETURN(rv);
   2883     }
   2884 
   2885     POL_FUNCTION_DEBUG(unit, "mode_id %d", *mode_id);
   2886 
   2887     POL_FUNCTION_TRACE(unit, "OUT");
   2888     return BCM_E_NONE;
   2889 }
   2890 
   2891 /*
   2892  * Function:
   2893  *      bcmi_esw_get_policer_id_from_index_offset
   2894  * Purpose:
   2895  *      Get policer id, given the HW policer index and offset_mode
   2896  * Parameters:
   2897  *     Unit                  - (IN) unit number
   2898  *     index                 - (IN) HW policer index
   2899  *     offset_mode           - (IN) offset mode
   2900  *     pid                   - (OUT) policer Id
   2901  * Returns:
   2902  *     BCM_E_XXX
   2903  */
   2904 STATIC int
   2905 bcmi_esw_get_policer_id_from_index_offset(
   2906     int unit,
   2907     int index,
   2908     int offset_mode,
   2909     bcm_policer_t *pid)
   2910 {
   2911     POL_FUNCTION_TRACE(unit, "IN");
   2912 
   2913     /* Input parameters check. */
   2914     POL_CHECK_NULL_PARAMETER(unit, pid);
   2915 
   2916     if (index == 0) {
   2917         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   2918                     (BSL_META_U(unit,
   2919                                 "0 is reserved invalid table index\n")));
   2920     } else {
   2921         *pid = POLICER_IDX_TO_POLICER_ID(offset_mode, index);
   2922     }
   2923 
   2924     POL_FUNCTION_TRACE(unit, "OUT");
   2925 
   2926     return BCM_E_NONE;
   2927 }
   2928 
   2929 /*
   2930  * Function:
   2931  *     bcmi_esw_policer_table_index_get
   2932  * Purpose:
   2933  *     Get the HW policer index, given a policer id.
   2934  * Parameters:
   2935  *     Unit                  - (IN) unit number
   2936  *     policer_id            - (IN) policer Id
   2937  *     index                 - (OUT) HW policer index
   2938  * Returns:
   2939  *     BCM_E_XXX
   2940  */
   2941 STATIC int
   2942 bcmi_esw_policer_table_index_get(
   2943     int unit,
   2944     bcm_policer_t policer_id,
   2945     int *index)
   2946 {
   2947     int rv = BCM_E_NONE;
   2948 
   2949     POL_FUNCTION_TRACE(unit, "IN");
   2950 
   2951     /* Input parameters check. */
   2952     POL_CHECK_NULL_PARAMETER(unit, index);
   2953 
   2954     *index = POLICER_ID_TO_POLICER_IDX(policer_id);
   2955 
   2956     if (*index >= soc_mem_index_count(unit, SVM_METER_TABLEm)) {
   2957         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   2958                     (BSL_META_U(unit,
   2959                                 "Invalid table index for "
   2960                                 "SVM_METER_TABLE\n")));
   2961         return BCM_E_PARAM;
   2962     }
   2963 
   2964     POL_FUNCTION_TRACE(unit, "OUT");
   2965     return rv;
   2966 }
   2967 
   2968 /*
   2969  * Function:
   2970  *     bcmi_esw_policer_offset_mode_get
   2971  * Purpose:
   2972  *     Get the offset_mode with given a policer id.
   2973  * Parameters:
   2974  *     Unit                  - (IN) unit number
   2975  *     policer_id            - (IN) policer Id
   2976  *     offset_mode                 - (OUT) HW policer index
   2977  * Returns:
   2978  *     BCM_E_XXX
   2979  */
   2980 STATIC int
   2981 bcmi_esw_policer_offset_mode_get(
   2982     int unit,
   2983     bcm_policer_t policer_id,
   2984     int *offset_mode)
   2985 {
   2986     int rv = BCM_E_NONE;
   2987 
   2988     POL_FUNCTION_TRACE(unit, "IN");
   2989 
   2990     /* Input parameters check. */
   2991     POL_CHECK_NULL_PARAMETER(unit, offset_mode);
   2992 
   2993     if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) {
   2994         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   2995                     (BSL_META_U(unit,
   2996                                 "Policer id passed is 0\n")));
   2997         *offset_mode = 0;
   2998         return rv;
   2999     }
   3000 
   3001     *offset_mode = POLICER_ID_OFFSET_MODE_GET(policer_id);
   3002 
   3003     POL_FUNCTION_TRACE(unit, "OUT");
   3004     return rv;
   3005 }
   3006 
   3007 STATIC int
   3008 bcmi_esw_global_meter_base_policer_get(
   3009     int unit,
   3010     bcm_policer_t policer_id,
   3011     bcmi_global_meter_policer_control_t **policer_p);
   3012 
   3013 /*
   3014  * Function:
   3015  *     bcmi_esw_policer_validate
   3016  * Purpose:
   3017  *     Validate the given policer id
   3018  * Parameters:
   3019  *     Unit                  - (IN) unit number
   3020  *     policer_id            - (IN) policer Id
   3021  * Returns:
   3022  *     BCM_E_XXX
   3023  */
   3024 STATIC int
   3025 bcmi_esw_policer_validate(
   3026     int unit,
   3027     bcm_policer_t policer_id)
   3028 {
   3029     int rv = BCM_E_NONE;
   3030     int index = 0;
   3031     uint32 offset_mode = 0;
   3032     bcmi_global_meter_policer_control_t *policer_control = NULL;
   3033 
   3034     POL_FUNCTION_TRACE(unit, "IN");
   3035 
   3036     /* Initialization check */
   3037     CHECK_GLOBAL_METER_INIT(unit);
   3038 
   3039     if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) {
   3040         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3041                     (BSL_META_U(unit,
   3042                                 "Policer id passed is 0\n")));
   3043         return rv;
   3044     }
   3045 
   3046     /* valid the policer id is create in current SW database or not */
   3047     rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control);
   3048     BCM_IF_ERROR_RETURN(rv);
   3049 
   3050     /* get the HW index for the policer */
   3051     rv = bcmi_esw_policer_table_index_get(unit, policer_id, &index);
   3052     BCM_IF_ERROR_RETURN(rv);
   3053     if (index > (soc_mem_index_max(unit, SVM_METER_TABLEm))) {
   3054         LOG_WARN(BSL_LS_BCM_POLICER,
   3055                  (BSL_META_U(unit,
   3056                              "Invalid table index for SVM_POLICY_TABLE\n")));
   3057         return BCM_E_PARAM;
   3058     }
   3059 
   3060     if (index == 0) {
   3061         /* Default HW value will be 0 and it's not a valid table index */
   3062         return BCM_E_PARAM;
   3063     }
   3064 
   3065     /* Get mode id from policer id */
   3066     offset_mode = POLICER_ID_OFFSET_MODE_GET(policer_id);
   3067 
   3068     /* Validate offset_mode */
   3069     rv = bcmi_policer_offset_mode_validate(unit, offset_mode);
   3070 
   3071     POL_FUNCTION_TRACE(unit, "OUT");
   3072     return rv;
   3073 }
   3074 
   3075 /*
   3076  * Function:
   3077  *     bcmi_esw_base_policer_validate
   3078  * Purpose:
   3079  *     Validate the given policer id if
   3080  *     it is base policer.
   3081  * Parameters:
   3082  *     Unit                  - (IN) unit number
   3083  *     base_policer_id       - (IN) base policer Id
   3084  * Returns:
   3085  *     BCM_E_XXX
   3086  */
   3087 STATIC int
   3088 bcmi_esw_base_policer_validate(
   3089     int unit,
   3090     bcm_policer_t base_policer_id)
   3091 {
   3092     bcmi_global_meter_policer_control_t *policer_control = NULL;
   3093     uint32 hash_index;      /* Entry hash.  */
   3094     uint32 hash_max;
   3095 
   3096     POL_FUNCTION_TRACE(unit, "IN");
   3097 
   3098     /* Initialization check */
   3099     CHECK_GLOBAL_METER_INIT(unit);
   3100     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3101 
   3102     BCM_IF_ERROR_RETURN(
   3103         bcmi_esw_policer_validate(unit, base_policer_id));
   3104 
   3105     hash_max = base_policer_id & BCMI_GLOBAL_METER_HASH_MASK;
   3106     for (hash_index = 0; hash_index <= hash_max; hash_index++) {
   3107         policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index);
   3108         while (NULL != policer_control) {
   3109             /* Match entry's base policer id. */
   3110             if (base_policer_id == policer_control->pid) {
   3111                 POL_FUNCTION_TRACE(unit, "OUT: is base policer id");
   3112                 return (BCM_E_NONE);
   3113             }
   3114             policer_control = policer_control->next;
   3115         }
   3116     }
   3117     /* Not a base_policer_id. */
   3118     POL_FUNCTION_TRACE(unit, "OUT: not base policer id");
   3119     return (BCM_E_NOT_FOUND);
   3120 }
   3121 
   3122 /*
   3123  * Function:
   3124  *      bcmi_esw_policer_increment_ref_count
   3125  * Purpose:
   3126  *      Increment the policer usage reference count
   3127  * Parameters:
   3128  *     unit                  - (IN) unit number
   3129  *     policer               - (IN) policer Id
   3130  * Returns:
   3131  *     BCM_E_XXX
   3132  */
   3133 STATIC int
   3134 bcmi_esw_policer_increment_ref_count(
   3135     int unit,
   3136     bcm_policer_t policer_id)
   3137 {
   3138     int rv = BCM_E_NONE;
   3139     bcmi_global_meter_policer_control_t *policer_control = NULL;
   3140 
   3141     POL_FUNCTION_TRACE(unit, "OUT");
   3142 
   3143     if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) {
   3144         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3145                     (BSL_META_U(unit,
   3146                                 "inc refcnt:Policer id passed is 0\n")));
   3147         return rv;
   3148     }
   3149 
   3150     /* validate policer id */
   3151     rv = bcmi_esw_policer_validate(unit, policer_id);
   3152     if (BCM_FAILURE(rv)) {
   3153         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3154                     (BSL_META_U(unit,
   3155                                 "Invalid policer id passed: %x \n"),
   3156                      policer_id));
   3157         return (rv);
   3158     }
   3159 
   3160     GLOBAL_METER_BK_LOCK(unit);
   3161     rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control);
   3162 
   3163     if (BCM_FAILURE(rv)) {
   3164         GLOBAL_METER_BK_UNLOCK(unit);
   3165         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3166                     (BSL_META_U(unit,
   3167                                 "Unable to get policer control for policer "
   3168                                 "id %d\n"), policer_id));
   3169         return (rv);
   3170     }
   3171     policer_control->ref_count++;
   3172     GLOBAL_METER_BK_UNLOCK(unit);
   3173 
   3174     POL_FUNCTION_TRACE(unit, "OUT");
   3175     return rv;
   3176 }
   3177 
   3178 /*
   3179  * Function:
   3180  *      bcmi_esw_policer_decrement_ref_count
   3181  * Purpose:
   3182  *     Decrement the policer usage refernce count
   3183  * Parameters:
   3184  *     unit                  - (IN) unit number
   3185  *     policer               - (IN) policer Id
   3186  * Returns:
   3187  *     BCM_E_XXX
   3188  */
   3189 STATIC int
   3190 bcmi_esw_policer_decrement_ref_count(
   3191     int unit,
   3192     bcm_policer_t policer_id)
   3193 {
   3194     int rv = BCM_E_NONE;
   3195     bcmi_global_meter_policer_control_t *policer_control = NULL;
   3196 
   3197     POL_FUNCTION_TRACE(unit, "IN");
   3198 
   3199     if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) {
   3200         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3201                     (BSL_META_U(unit,
   3202                                 "dec refcnt:Policer id passed is 0\n")));
   3203         return rv;
   3204     }
   3205 
   3206     /* validate policer id */
   3207     rv = bcmi_esw_policer_validate(unit, policer_id);
   3208     if (BCM_FAILURE(rv)) {
   3209         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3210                     (BSL_META_U(unit,
   3211                                 "Invalid policer id passed: %x \n"),
   3212                      policer_id));
   3213         return (rv);
   3214     }
   3215 
   3216     GLOBAL_METER_BK_LOCK(unit);
   3217     rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control);
   3218 
   3219     if (BCM_FAILURE(rv)) {
   3220         GLOBAL_METER_BK_UNLOCK(unit);
   3221         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3222                     (BSL_META_U(unit,
   3223                                 "Unable to get policer control for policer "
   3224                                 "id %d\n"), policer_id));
   3225         return (rv);
   3226     }
   3227     if (policer_control->ref_count > 0) {
   3228         policer_control->ref_count--;
   3229     }
   3230     GLOBAL_METER_BK_UNLOCK(unit);
   3231 
   3232     POL_FUNCTION_TRACE(unit, "OUT");
   3233     return rv;
   3234 }
   3235 
   3236 /*
   3237  * Function:
   3238  *     bcmi_esw_get_policer_from_table
   3239  * Purpose:
   3240  *     Read the policer id configured in the given table
   3241  * Parameters:
   3242  *     unit                  - (IN) unit number
   3243  *     table                 - (IN) Table from which the entry needs to be got
   3244  *     index                 - (IN) index in the table
   3245  *     data                  - (IN) Data to be written
   3246  *     policer               - (OUT) policer Id
   3247  *     skip_read             - (IN) Skip reading the policer entry
   3248  * Returns:
   3249  *     BCM_E_XXX
   3250  */
   3251 STATIC int
   3252 bcmi_esw_get_policer_from_table(
   3253     int unit,
   3254     soc_mem_t table,
   3255     int index,
   3256     void *data,
   3257     bcm_policer_t *policer_id,
   3258     int skip_read)
   3259 {
   3260     bcm_error_t rv = BCM_E_UNAVAIL;
   3261     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3262     int meter_index, meter_offset_mode;
   3263 
   3264     POL_FUNCTION_TRACE(unit, "IN");
   3265 
   3266     /* Input parameters check. */
   3267     POL_CHECK_NULL_PARAMETER(unit, data);
   3268     POL_CHECK_NULL_PARAMETER(unit, policer_id);
   3269 
   3270     /* Initialization check */
   3271     CHECK_GLOBAL_METER_INIT(unit);
   3272     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3273     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3274 
   3275     /* Check if the chip specific function existed */
   3276     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_get);
   3277 
   3278     GLOBAL_METER_LOCK(unit);
   3279     rv = gm_dev_info->policer_to_table_get(unit,
   3280                                            table,
   3281                                            index,
   3282                                            data,
   3283                                            &meter_index,
   3284                                            &meter_offset_mode,
   3285                                            skip_read);
   3286     GLOBAL_METER_UNLOCK(unit);
   3287     if (BCM_FAILURE(rv)) {
   3288         LOG_ERROR(BSL_LS_BCM_POLICER,
   3289                   (BSL_META_U(unit,
   3290                               "HW Operation failed(rv = %d)\n"),
   3291                               rv));
   3292         return rv;
   3293     }
   3294 
   3295     BCM_IF_ERROR_RETURN(
   3296         bcmi_esw_get_policer_id_from_index_offset(
   3297             unit, meter_index, meter_offset_mode, policer_id));
   3298     POL_FUNCTION_TRACE(unit, "OUT");
   3299     return BCM_E_NONE;
   3300 }
   3301 
   3302 /*
   3303  * Function:
   3304  *     bcmi_esw_add_policer_to_table
   3305  * Purpose:
   3306  *     Add policer id to the table entry specified
   3307  * Parameters:
   3308  *     unit                  - (IN) unit number
   3309  *     policer_id            - (IN) policer Id
   3310  *     table                 - (IN) Table to which the entry needs to be added
   3311  *     index                 - (IN) index in the table
   3312  *     data                  - (IN) Data to be written
   3313  * Returns:
   3314  *     BCM_E_XXX
   3315  */
   3316 STATIC int
   3317 bcmi_esw_add_policer_to_table(int unit,
   3318     bcm_policer_t policer_id,
   3319     soc_mem_t table,
   3320     int index,
   3321     void *data)
   3322 {
   3323     bcm_error_t rv = BCM_E_UNAVAIL;
   3324     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3325     int meter_offset_mode = 0;
   3326     int meter_index = 0;
   3327     int skip_read = TRUE;
   3328     bcm_policer_t current_policer_id = 0;
   3329 
   3330     POL_FUNCTION_TRACE(unit, "IN");
   3331 
   3332     /* Input parameters check. */
   3333     POL_CHECK_NULL_PARAMETER(unit, data);
   3334 
   3335     /* Initialization check */
   3336     CHECK_GLOBAL_METER_INIT(unit);
   3337     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3338     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3339 
   3340     /* validate policer id */
   3341     rv = bcmi_esw_policer_validate(unit, policer_id);
   3342     if (BCM_FAILURE(rv)) {
   3343         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3344                     (BSL_META_U(unit,
   3345                                 "Invalid policer id passed: %x \n"),
   3346                                 policer_id));
   3347         return (rv);
   3348     }
   3349 
   3350     /* get the policer id that is currently configured */
   3351     rv = bcmi_esw_get_policer_from_table(unit, table, index, data,
   3352                                          &current_policer_id, skip_read);
   3353     if (BCM_FAILURE(rv)) {
   3354         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   3355                     (BSL_META_U(unit,
   3356                                 "Unable to read the table entry %d at "
   3357                                 "index %d \n"), table, index));
   3358         return (rv);
   3359     }
   3360 
   3361     /* Set policer id */
   3362     BCM_IF_ERROR_RETURN(
   3363         bcmi_esw_policer_table_index_get(unit, policer_id, &meter_index));
   3364     BCM_IF_ERROR_RETURN(
   3365         bcmi_esw_policer_offset_mode_get(unit, policer_id, &meter_offset_mode));
   3366 
   3367     /* Check if the chip specific function existed */
   3368     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_set);
   3369 
   3370     GLOBAL_METER_LOCK(unit);
   3371 
   3372     rv = gm_dev_info->policer_to_table_set(unit,
   3373                                            table,
   3374                                            index,
   3375                                            data,
   3376                                            meter_index,
   3377                                            meter_offset_mode,
   3378                                            skip_read);
   3379     GLOBAL_METER_UNLOCK(unit);
   3380     if (BCM_FAILURE(rv)) {
   3381         LOG_ERROR(BSL_LS_BCM_POLICER,
   3382                   (BSL_META_U(unit,
   3383                               "HW Operation failed(rv = %d)\n"),
   3384                               rv));
   3385         return rv;
   3386     }
   3387 
   3388     /* increment new set policer ref_cnt */
   3389     rv = bcmi_esw_policer_increment_ref_count(unit, policer_id);
   3390     BCM_IF_ERROR_RETURN(rv);
   3391 
   3392     /* decrement current hw policer ref_cnt */
   3393     rv = bcmi_esw_policer_validate(unit, current_policer_id);
   3394 
   3395     /* Don't need to handle fail case since existed index could be 0 */
   3396     if (BCM_SUCCESS(rv)) {
   3397         rv = bcmi_esw_policer_decrement_ref_count(unit, current_policer_id);
   3398         BCM_IF_ERROR_RETURN(rv);
   3399     }
   3400 
   3401     POL_FUNCTION_TRACE(unit, "OUT");
   3402     return BCM_E_NONE;
   3403 }
   3404 
   3405 /*
   3406  * Function:
   3407  *     bcmi_esw_delete_policer_from_table
   3408  * Purpose:
   3409  *     Remove the policer id configured from a table and re-adjust
   3410  *     policer usage reference count
   3411  * Parameters:
   3412  *     unit                  - (IN) unit number
   3413  *     policer_id            - (IN) policer Id
   3414  *     table                 - (IN) Table in which an entry needs to be deleted
   3415  *     index                 - (IN) index in the table
   3416  *     data                  - (IN) Data to be written
   3417  * Returns:
   3418  *     BCM_E_XXX
   3419  */
   3420 int bcmi_esw_delete_policer_from_table(
   3421     int unit,
   3422     bcm_policer_t policer_id,
   3423     soc_mem_t table,
   3424     int index,
   3425     void *data)
   3426 {
   3427     bcm_error_t rv = BCM_E_UNAVAIL;
   3428     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3429     bcm_policer_t current_policer_id = 0;
   3430     int meter_offset_mode = 0;
   3431     int meter_index = 0;
   3432     int skip_read = FALSE;
   3433 
   3434     POL_FUNCTION_TRACE(unit, "IN");
   3435 
   3436     /* Input parameters check. */
   3437     POL_CHECK_NULL_PARAMETER(unit, data);
   3438 
   3439     /* Initialization check */
   3440     CHECK_GLOBAL_METER_INIT(unit);
   3441     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3442 
   3443     /* validate policer id */
   3444     rv = bcmi_esw_policer_validate(unit, policer_id);
   3445     if (BCM_FAILURE(rv)) {
   3446         LOG_DEBUG(BSL_LS_BCM_POLICER,
   3447                   (BSL_META_U(unit,
   3448                               "Invalid policer id passed: %x \n"),
   3449                               policer_id));
   3450         return (rv);
   3451     }
   3452     /* Deleting VFP_POLICY_TABLEm is handled in field module */
   3453     if (VFP_POLICY_TABLEm != table) {
   3454         rv = bcmi_esw_get_policer_from_table(unit, table, index, data,
   3455                                              &current_policer_id, skip_read);
   3456         if (BCM_FAILURE(rv)) {
   3457             LOG_ERROR(BSL_LS_BCM_POLICER,
   3458                       (BSL_META_U(unit,
   3459                                   "Unable to read the policer from table "
   3460                                   "%d at index %d\n"), table, index));
   3461             return (rv);
   3462         }
   3463         if (current_policer_id != policer_id) {
   3464             LOG_ERROR(BSL_LS_BCM_POLICER,
   3465                       (BSL_META_U(unit,
   3466                                   "Policer Id passed is different from the "
   3467                                   "one that is configured in the table."
   3468                                   "configured value is %d \n"),
   3469                                   current_policer_id));
   3470             return BCM_E_INTERNAL;
   3471         }
   3472 
   3473         GLOBAL_METER_LOCK(unit);
   3474         gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3475 
   3476         /* Check if the chip specific function existed */
   3477         POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_set);
   3478         rv = gm_dev_info->policer_to_table_set(unit,
   3479                                                table,
   3480                                                index,
   3481                                                data,
   3482                                                meter_index,
   3483                                                meter_offset_mode,
   3484                                                skip_read);
   3485         GLOBAL_METER_UNLOCK(unit);
   3486         if (BCM_FAILURE(rv)) {
   3487             LOG_ERROR(BSL_LS_BCM_POLICER,
   3488                       (BSL_META_U(unit,
   3489                                   "HW Operation failed(rv = %d)\n"),
   3490                                   rv));
   3491             return rv;
   3492         }
   3493     }
   3494 
   3495     /* decrement current policer if any */
   3496     rv = bcmi_esw_policer_decrement_ref_count(unit, policer_id);
   3497     BCM_IF_ERROR_RETURN(rv);
   3498 
   3499     POL_FUNCTION_TRACE(unit, "OUT");
   3500     return BCM_E_NONE;
   3501 }
   3502 
   3503 /*
   3504  * Function:
   3505  *     bcmi_esw_global_meter_read_config_from_hw
   3506  * Purpose:
   3507  *     Read policer configuration form the HW table entry.
   3508  * Parameters:
   3509  *     unit                  - (IN) unit number
   3510  *     policer_id            - (IN) policer id
   3511  *     pol_cfg               - (OUT) policer configuration
   3512  * Returns:
   3513  *     BCM_E_XXX
   3514  */
   3515 STATIC int
   3516 bcmi_esw_global_meter_read_config_from_hw(
   3517     int unit,
   3518     bcm_policer_t policer_id,
   3519     bcm_policer_config_t *pol_cfg)
   3520 {
   3521     bcm_error_t rv = BCM_E_UNAVAIL;
   3522     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3523     uint32 refresh_rate = 0;    /* Policer refresh rate.    */
   3524     uint32 granularity = 0;     /* Policer granularity.     */
   3525     uint32 bucket_count = 0, bucket_size = 0;
   3526     uint32 pkt_bytes = 0, tsn_modified = 0, average_pkt_size = 0;
   3527     uint32 flags = 0;
   3528     int index = 0, e_idx, c_idx, p_idx;
   3529     uint32 meter_gran_mode = 0;
   3530     uint32 pkbits_sec, pkbits_burst, ckbits_sec, ckbits_burst;
   3531 
   3532     POL_FUNCTION_TRACE(unit, "IN");
   3533 
   3534     /* Input parameters check. */
   3535     POL_CHECK_NULL_PARAMETER(unit, pol_cfg);
   3536 
   3537     (void)bcm_policer_config_t_init(pol_cfg);
   3538 
   3539     /* Initialization check */
   3540     CHECK_GLOBAL_METER_INIT(unit);
   3541     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3542     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3543 
   3544     /* get the HW index for the policer */
   3545     BCM_IF_ERROR_RETURN(
   3546         bcmi_esw_policer_table_index_get(unit, policer_id, &index));
   3547 
   3548     /* Policy Table */
   3549     p_idx = index ;
   3550 
   3551     /* Check if the chip specific function existed */
   3552     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_get);
   3553     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_get);
   3554 
   3555     rv = gm_dev_info->policy_mode_get(
   3556                         unit,
   3557                         p_idx,
   3558                         &pol_cfg->mode,
   3559                         &pol_cfg->flags);
   3560 
   3561     if (BCM_FAILURE(rv)) {
   3562         LOG_ERROR(BSL_LS_BCM_POLICER,
   3563                   (BSL_META_U(unit,
   3564                               "HW Operation failed(rv = %d)\n"),
   3565                               rv));
   3566         return rv;
   3567     }
   3568 
   3569     /* Commit */
   3570     c_idx = index * 2 + 1;
   3571 
   3572     rv = gm_dev_info->meter_table_get(
   3573                         unit,
   3574                         c_idx,
   3575                         &bucket_size,
   3576                         &bucket_count,
   3577                         &refresh_rate,
   3578                         &granularity,
   3579                         &pkt_bytes,
   3580                         &tsn_modified,
   3581                         &meter_gran_mode,
   3582                         &average_pkt_size);
   3583 
   3584     if (BCM_FAILURE(rv)) {
   3585         LOG_ERROR(BSL_LS_BCM_POLICER,
   3586                   (BSL_META_U(unit,
   3587                               "HW Operation failed(rv = %d)\n"),
   3588                               rv));
   3589         return rv;
   3590     }
   3591 
   3592     if (pkt_bytes == 0) {
   3593         pol_cfg->flags |= BCM_POLICER_MODE_BYTES;
   3594     } else {
   3595         pol_cfg->flags |= BCM_POLICER_MODE_PACKETS;
   3596     }
   3597 
   3598     if (tsn_modified == 1) {
   3599         pol_cfg->mode = bcmPolicerModeSrTcmTsn;
   3600     }
   3601     pol_cfg->average_pkt_size = average_pkt_size;
   3602 
   3603     flags =  _BCM_XGS_METER_FLAG_GRANULARITY |
   3604                         _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
   3605 
   3606     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
   3607         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
   3608     }
   3609 
   3610     rv = _bcm_xgs_bucket_encoding_to_kbits(
   3611             refresh_rate, bucket_size, granularity, flags,
   3612             &ckbits_sec, &ckbits_burst);
   3613 
   3614     if (BCM_FAILURE(rv)) {
   3615         LOG_ERROR(BSL_LS_BCM_POLICER,
   3616                   (BSL_META_U(unit,
   3617                               "Unable to translate rate in kbps to bucket size "
   3618                               "and granularity \n")));
   3619         return rv;
   3620     }
   3621     /* ckbits_sec = (pol_cfg->ckbits_sec << 8) + (pol_cfg->cbits_sec_lower << 8) / 1000 */
   3622     if (meter_gran_mode) {
   3623         pol_cfg->ckbits_sec =
   3624             ckbits_sec >> BCMI_POLICER_METER_GRAN_SHFIT;
   3625         pol_cfg->cbits_sec_lower =
   3626             (ckbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >>
   3627              BCMI_POLICER_METER_GRAN_SHFIT;
   3628         pol_cfg->cbits_sec_lower -=
   3629             (pol_cfg->ckbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT);
   3630 
   3631         pol_cfg->ckbits_burst =
   3632             ckbits_burst >> BCMI_POLICER_METER_GRAN_SHFIT;
   3633         pol_cfg->cbits_burst_lower =
   3634             (ckbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >>
   3635              BCMI_POLICER_METER_GRAN_SHFIT;
   3636         pol_cfg->cbits_burst_lower -=
   3637             (pol_cfg->ckbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT);
   3638     } else {
   3639         pol_cfg->ckbits_sec = ckbits_sec;
   3640         pol_cfg->ckbits_burst = ckbits_burst;
   3641     }
   3642 
   3643     /* Exceed */
   3644     e_idx = index * 2;
   3645 
   3646     rv = gm_dev_info->meter_table_get(
   3647                         unit,
   3648                         e_idx,
   3649                         &bucket_size,
   3650                         &bucket_count,
   3651                         &refresh_rate,
   3652                         &granularity,
   3653                         &pkt_bytes,
   3654                         &tsn_modified,
   3655                         &meter_gran_mode,
   3656                         &average_pkt_size);
   3657 
   3658     if (BCM_FAILURE(rv)) {
   3659         LOG_ERROR(BSL_LS_BCM_POLICER,
   3660                   (BSL_META_U(unit,
   3661                               "HW Operation failed(rv = %d)\n"),
   3662                               rv));
   3663         return rv;
   3664     }
   3665 
   3666     rv = _bcm_xgs_bucket_encoding_to_kbits(
   3667             refresh_rate, bucket_size, granularity, flags,
   3668             &pkbits_sec, &pkbits_burst);
   3669     if (BCM_FAILURE(rv)) {
   3670         LOG_ERROR(BSL_LS_BCM_POLICER,
   3671                   (BSL_META_U(unit,
   3672                               "Unable to translate rate in kbps to bucket size "
   3673                               "and granularity \n")));
   3674         return rv;
   3675     }
   3676     /* pkbit_sec = (pol_cfg->pkbits_sec << 8) + (pol_cfg->pbits_sec_lower << 8) / 1000 */
   3677     if (meter_gran_mode) {
   3678         pol_cfg->pkbits_sec =
   3679             pkbits_sec >> BCMI_POLICER_METER_GRAN_SHFIT;
   3680         pol_cfg->pbits_sec_lower =
   3681             (pkbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >>
   3682              BCMI_POLICER_METER_GRAN_SHFIT;
   3683         pol_cfg->pbits_sec_lower -=
   3684             (pol_cfg->pkbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT);
   3685 
   3686         pol_cfg->pkbits_burst =
   3687             pkbits_burst >> BCMI_POLICER_METER_GRAN_SHFIT;
   3688         pol_cfg->pbits_burst_lower =
   3689             (pkbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >>
   3690              BCMI_POLICER_METER_GRAN_SHFIT;
   3691         pol_cfg->pbits_burst_lower -=
   3692             (pol_cfg->pkbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT);
   3693     } else {
   3694         pol_cfg->pkbits_sec = pkbits_sec;
   3695         pol_cfg->pkbits_burst = pkbits_burst;
   3696     }
   3697 
   3698     POL_FUNCTION_TRACE(unit, "OUT");
   3699     return BCM_E_NONE;
   3700 }
   3701 
   3702 /*
   3703  * Function:
   3704  *     bcmi_esw_global_meter_clear_config_on_hw
   3705  * Purpose:
   3706  *     Clear policer configuration to meter table.
   3707  * Parameters:
   3708  *     unit                  - (IN) unit number
   3709  *     pol_cfg               - (IN) policer configuration
   3710  *     policer_id            - (IN) policer id
   3711  *     policer_control       - (IN) Policer control info
   3712  * Returns:
   3713  *     BCM_E_XXX
   3714  */
   3715 STATIC int
   3716 bcmi_esw_global_meter_clear_config_on_hw(
   3717     int unit,
   3718     bcm_policer_t policer_id)
   3719 {
   3720     bcm_error_t rv = BCM_E_UNAVAIL;
   3721     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3722     uint32 c_bucketsize = 0, e_bucketsize = 0;  /* Bucket size */
   3723     uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */
   3724     uint32 granularity = 0;     /* Policer granularity */
   3725     uint32 average_pkt_size = 0;
   3726     uint32 c_bucketcount = 0, e_bucketcount;
   3727     int index = 0, e_idx, c_idx, p_idx;
   3728     bcm_policer_config_t pol_cfg;
   3729     uint32 meter_gran_mode = 0;
   3730 
   3731     POL_FUNCTION_TRACE(unit, "IN");
   3732 
   3733     (void)bcm_policer_config_t_init(&pol_cfg);
   3734 
   3735     /* Initialization check */
   3736     CHECK_GLOBAL_METER_INIT(unit);
   3737     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3738     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3739 
   3740     /* get the HW index for the policer */
   3741     BCM_IF_ERROR_RETURN(
   3742         bcmi_esw_policer_table_index_get(unit, policer_id, &index));
   3743 
   3744     /* Check if the chip specific function existed */
   3745     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set);
   3746     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_set);
   3747 
   3748     /* Commit */
   3749     c_idx = index * 2 + 1;
   3750     c_bucketsize = 0;
   3751     c_bucketcount = 0;
   3752     c_refresh_rate = 0;
   3753 
   3754     /* Write to HW */
   3755     rv = gm_dev_info->meter_table_set(
   3756                         unit,
   3757                         c_idx,
   3758                         pol_cfg.mode,
   3759                         pol_cfg.flags,
   3760                         average_pkt_size,
   3761                         meter_gran_mode,
   3762                         c_bucketsize,
   3763                         c_bucketcount,
   3764                         c_refresh_rate,
   3765                         granularity);
   3766     BCM_IF_ERROR_RETURN(rv);
   3767 
   3768     /* Exceed */
   3769     e_idx = index * 2;
   3770     e_bucketsize = 0;
   3771     e_bucketcount = 0;
   3772     e_refresh_rate = 0;
   3773     granularity = 0;
   3774 
   3775     /* Write to HW */
   3776     rv = gm_dev_info->meter_table_set(
   3777                         unit,
   3778                         e_idx,
   3779                         pol_cfg.mode,
   3780                         pol_cfg.flags,
   3781                         average_pkt_size,
   3782                         meter_gran_mode,
   3783                         e_bucketsize,
   3784                         e_bucketcount,
   3785                         e_refresh_rate,
   3786                         granularity);
   3787     BCM_IF_ERROR_RETURN(rv);
   3788 
   3789     /* Policy Table */
   3790     p_idx = index;
   3791 
   3792     rv = gm_dev_info->policy_mode_set(
   3793                         unit,
   3794                         p_idx,
   3795                         pol_cfg.mode,
   3796                         pol_cfg.flags);
   3797     BCM_IF_ERROR_RETURN(rv);
   3798 
   3799     POL_FUNCTION_TRACE(unit, "OUT");
   3800     return BCM_E_NONE;
   3801 }
   3802 
   3803 /*
   3804  * Function:
   3805  *      bcmi_esw_global_meter_write_config_to_hw
   3806  * Purpose:
   3807  *      Write policer configuration to meter table.
   3808  * Parameters:
   3809  *     unit                  - (IN) unit number
   3810  *     pol_cfg               - (IN) policer configuration
   3811  *     policer_id            - (IN) policer id
   3812  *     policer_control       - (IN) Policer control info
   3813  * Returns:
   3814  *     BCM_E_XXX
   3815  */
   3816 STATIC int
   3817 bcmi_esw_global_meter_write_config_to_hw(
   3818     int unit,
   3819     bcm_policer_config_t *pol_cfg,
   3820     bcm_policer_t policer_id)
   3821 {
   3822     bcm_error_t rv = BCM_E_UNAVAIL;
   3823     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   3824     uint32 flags = 0;
   3825     uint32 c_bucketsize = 0, e_bucketsize = 0;  /* Bucket size */
   3826     uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */
   3827     uint32 granularity = 0;     /* Policer granularity */
   3828     uint32 refresh_bitsize;     /* Number of bits for the
   3829                                       refresh rate field */
   3830     uint32 bucket_max_bitsize;  /* Number of bits for the
   3831                                       bucket max field */
   3832     uint32 c_bucketcount = 0, e_bucketcount = 0, bucket_cnt_bitsize = 0;
   3833     int index = 0, e_idx, c_idx, p_idx;
   3834     uint32 meter_gran_mode = 0;
   3835     uint32 pkbits_sec, pkbits_burst, ckbits_sec, ckbits_burst;
   3836 
   3837     POL_FUNCTION_TRACE(unit, "IN");
   3838 
   3839     /* Input parameters check. */
   3840     POL_CHECK_NULL_PARAMETER(unit, pol_cfg);
   3841 
   3842     /* Initialization check */
   3843     CHECK_GLOBAL_METER_INIT(unit);
   3844     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   3845     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   3846 
   3847     /* get the HW index for the policer */
   3848     BCM_IF_ERROR_RETURN(
   3849         bcmi_esw_policer_table_index_get(unit, policer_id, &index));
   3850 
   3851     flags = _BCM_XGS_METER_FLAG_GRANULARITY |
   3852             _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
   3853 
   3854     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
   3855         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
   3856     }
   3857 
   3858     /*
   3859      * Gran   Meter  Bytes       Min           Max
   3860      * mode   Gran   /Token   Refresh Rate MaxRefresh Rate
   3861      *  1      0    1/2^15      32bps         8Mbps
   3862      *         1    1/2^14      64bps        16Mbps
   3863      *         2    1/2^13     128bps        32Mbps
   3864      *         3    1/2^12     256bps        64Mbps
   3865      *         4    1/2^11     512bps       128Mbps
   3866      *         5    1/2^10      1Kbps       256Mbps
   3867      *         6    1/2^9       2Kbps       512Mbps
   3868      *         7    1/2^8       4Kbps         1Gbps
   3869      * Gran   Meter  Bytes       Min           Max
   3870      * mode   Gran   /Token   Refresh Rate MaxRefresh Rate
   3871      *  0      0    1/2^7       8Kbps         2Gbps
   3872      *         1    1/2^6      16Kbps         4Gbps
   3873      *         2    1/2^5      32Kbps         8Gbps
   3874      *         3    1/2^4      64Kbps        16Gbps
   3875      *         4    1/2^3     128Kbps        32Gbps
   3876      *         5    1/2^2     256Kbps        64Gbps
   3877      *         6    1/2^1     512Kbps       128Gbps
   3878      *         7    1/2^0    1024Kbps       256Gbps
   3879      */
   3880 
   3881     /* pkbit_sec = (pol_cfg->pkbits_sec << 8) + (pol_cfg->pbits_sec_lower << 8) / 1000 */
   3882     if (pol_cfg->pkbits_sec < BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY &&
   3883         pol_cfg->pkbits_burst < BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY &&
   3884         pol_cfg->ckbits_sec < BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY &&
   3885         pol_cfg->ckbits_burst < BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY) {
   3886         pkbits_sec =
   3887             (pol_cfg->pkbits_sec << BCMI_POLICER_METER_GRAN_SHFIT) +
   3888             (pol_cfg->pbits_sec_lower << BCMI_POLICER_METER_GRAN_SHFIT) /
   3889              BCMI_POLICER_METER_GRAN_LOWER_UNIT;
   3890         pkbits_burst =
   3891             (pol_cfg->pkbits_burst << BCMI_POLICER_METER_GRAN_SHFIT) +
   3892             (pol_cfg->pbits_burst_lower << BCMI_POLICER_METER_GRAN_SHFIT) /
   3893              BCMI_POLICER_METER_GRAN_LOWER_UNIT;
   3894         ckbits_sec =
   3895             (pol_cfg->ckbits_sec << BCMI_POLICER_METER_GRAN_SHFIT) +
   3896             (pol_cfg->cbits_sec_lower << BCMI_POLICER_METER_GRAN_SHFIT) /
   3897              BCMI_POLICER_METER_GRAN_LOWER_UNIT;
   3898         ckbits_burst =
   3899             (pol_cfg->ckbits_burst << BCMI_POLICER_METER_GRAN_SHFIT) +
   3900             (pol_cfg->cbits_burst_lower << BCMI_POLICER_METER_GRAN_SHFIT) /
   3901              BCMI_POLICER_METER_GRAN_LOWER_UNIT;
   3902 
   3903         meter_gran_mode = 1;
   3904     } else {
   3905         pkbits_sec = pol_cfg->pkbits_sec;
   3906         pkbits_burst = pol_cfg->pkbits_burst;
   3907         ckbits_sec = pol_cfg->ckbits_sec;
   3908         ckbits_burst = pol_cfg->ckbits_burst;
   3909 
   3910         meter_gran_mode = 0;
   3911     }
   3912 
   3913     /* Commit */
   3914     c_idx = index * 2 + 1;
   3915 
   3916     /* Check if the chip specific function existed */
   3917     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_bitsize_get);
   3918     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set);
   3919     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_set);
   3920 
   3921     /* Read from HW */
   3922     rv = gm_dev_info->meter_table_bitsize_get(
   3923                         unit,
   3924                         c_idx,
   3925                         &refresh_bitsize,
   3926                         &bucket_max_bitsize,
   3927                         &bucket_cnt_bitsize);
   3928 
   3929     if (BCM_FAILURE(rv)) {
   3930         LOG_ERROR(BSL_LS_BCM_POLICER,
   3931                   (BSL_META_U(unit,
   3932                               "HW Operation failed(rv = %d)\n"),
   3933                               rv));
   3934         return rv;
   3935     }
   3936 
   3937     /* Calculate policer bucket size/refresh_rate/granularity. */
   3938     if (pkbits_sec > ckbits_sec) {
   3939         rv = _bcm_xgs_kbits_to_bucket_encoding(pkbits_sec,
   3940                                                pkbits_burst,
   3941                                                flags, refresh_bitsize,
   3942                                                bucket_max_bitsize,
   3943                                                &c_refresh_rate,
   3944                                                &c_bucketsize,
   3945                                                &granularity);
   3946         BCM_IF_ERROR_RETURN(rv);
   3947         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
   3948                                             ckbits_sec,
   3949                                             ckbits_burst,
   3950                                             flags, refresh_bitsize,
   3951                                             bucket_max_bitsize,
   3952                                             &c_refresh_rate,
   3953                                             &c_bucketsize,
   3954                                             &granularity);
   3955         BCM_IF_ERROR_RETURN(rv);
   3956     }  else {
   3957          rv = _bcm_xgs_kbits_to_bucket_encoding(ckbits_sec,
   3958                                                 ckbits_burst,
   3959                                                 flags, refresh_bitsize,
   3960                                                 bucket_max_bitsize,
   3961                                                 &c_refresh_rate,
   3962                                                 &c_bucketsize,
   3963                                                 &granularity);
   3964         BCM_IF_ERROR_RETURN(rv);
   3965     }
   3966 
   3967     /* Calculate initial bucket count.
   3968      * bucket size << (bit count diff - 1(sign) -1 (overflow))  - 1
   3969      */
   3970     if (c_bucketsize == 0 && c_refresh_rate == 0) {
   3971         /* Committed should always be out of profile */
   3972         c_bucketcount = (1 << bucket_cnt_bitsize) - 1;
   3973     } else if (c_bucketsize) {
   3974         c_bucketcount =
   3975             (c_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1;
   3976         c_bucketcount &= ((1 << bucket_cnt_bitsize) - 1);
   3977     } else {
   3978         c_bucketcount = 0;
   3979     }
   3980 
   3981     /* Check if the chip specific function existed */
   3982     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set);
   3983 
   3984     /* Write to HW */
   3985     rv = gm_dev_info->meter_table_set(
   3986                         unit,
   3987                         c_idx,
   3988                         pol_cfg->mode,
   3989                         pol_cfg->flags,
   3990                         pol_cfg->average_pkt_size,
   3991                         meter_gran_mode,
   3992                         c_bucketsize,
   3993                         c_bucketcount,
   3994                         c_refresh_rate,
   3995                         granularity);
   3996 
   3997     if (BCM_FAILURE(rv)) {
   3998         LOG_ERROR(BSL_LS_BCM_POLICER,
   3999                   (BSL_META_U(unit,
   4000                               "HW Operation failed(rv = %d)\n"),
   4001                               rv));
   4002         return rv;
   4003     }
   4004 
   4005     /* Exceed */
   4006     e_idx = index * 2;
   4007 
   4008     /* Read from HW */
   4009     rv = gm_dev_info->meter_table_bitsize_get(
   4010                         unit,
   4011                         e_idx,
   4012                         &refresh_bitsize,
   4013                         &bucket_max_bitsize,
   4014                         &bucket_cnt_bitsize);
   4015 
   4016     if ((ckbits_sec == 0) && (ckbits_burst == 0)) {
   4017         rv = _bcm_xgs_kbits_to_bucket_encoding(pkbits_sec,
   4018                                                pkbits_burst,
   4019                                                flags, refresh_bitsize,
   4020                                                bucket_max_bitsize,
   4021                                                &e_refresh_rate,
   4022                                                &e_bucketsize,
   4023                                                &granularity);
   4024 
   4025     } else {
   4026         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
   4027                                             pkbits_sec,
   4028                                             pkbits_burst,
   4029                                             flags, refresh_bitsize,
   4030                                             bucket_max_bitsize,
   4031                                             &e_refresh_rate,
   4032                                             &e_bucketsize,
   4033                                             &granularity);
   4034     }
   4035     BCM_IF_ERROR_RETURN(rv);
   4036     /* Calculate initial bucket count.
   4037      * bucket size << (bit count diff - 1(sign) -1 (overflow))  - 1
   4038      */
   4039     if (e_bucketsize == 0 && e_refresh_rate == 0) {
   4040         /* Excess should always be out of profile */
   4041         e_bucketcount = (1 << bucket_cnt_bitsize) - 1;
   4042     } else if (e_bucketsize) {
   4043         e_bucketcount =
   4044             (e_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1;
   4045         e_bucketcount &= ((1 << bucket_cnt_bitsize) - 1);
   4046     } else {
   4047         e_bucketcount = 0;
   4048     }
   4049 
   4050     /* Write to HW */
   4051     rv = gm_dev_info->meter_table_set(
   4052                         unit,
   4053                         e_idx,
   4054                         pol_cfg->mode,
   4055                         pol_cfg->flags,
   4056                         pol_cfg->average_pkt_size,
   4057                         meter_gran_mode,
   4058                         e_bucketsize,
   4059                         e_bucketcount,
   4060                         e_refresh_rate,
   4061                         granularity);
   4062 
   4063     if (BCM_FAILURE(rv)) {
   4064         LOG_ERROR(BSL_LS_BCM_POLICER,
   4065                   (BSL_META_U(unit,
   4066                               "HW Operation failed(rv = %d)\n"),
   4067                               rv));
   4068         return rv;
   4069     }
   4070 
   4071     /* Policy Table */
   4072     p_idx = index ;
   4073 
   4074     rv = gm_dev_info->policy_mode_set(
   4075                         unit,
   4076                         p_idx,
   4077                         pol_cfg->mode,
   4078                         pol_cfg->flags);
   4079 
   4080     if (BCM_FAILURE(rv)) {
   4081         LOG_ERROR(BSL_LS_BCM_POLICER,
   4082                   (BSL_META_U(unit,
   4083                               "HW Operation failed(rv = %d)\n"),
   4084                               rv));
   4085         return rv;
   4086     }
   4087 
   4088     POL_FUNCTION_TRACE(unit, "OUT");
   4089     return BCM_E_NONE;
   4090 }
   4091 
   4092 /*
   4093  * Function:
   4094  *     bcmi_esw_global_meter_base_policer_get
   4095  * Purpose:
   4096  *     Get the internal data sructure for a given polier id if
   4097  *     it is base policer.
   4098  * Parameters:
   4099  *     unit                  - (IN) unit number
   4100  *     pid                   - (IN) policer id
   4101  *     policer_p             - (OUT) Policer control info
   4102  * Returns:
   4103  *     BCM_E_XXX
   4104  */
   4105 STATIC int
   4106 bcmi_esw_global_meter_base_policer_get(
   4107     int unit,
   4108     bcm_policer_t policer_id,
   4109     bcmi_global_meter_policer_control_t **policer_p)
   4110 {
   4111     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4112     uint32 hash_index;      /* Entry hash.  */
   4113     uint32 hash_max;
   4114 
   4115     POL_FUNCTION_TRACE(unit, "IN");
   4116 
   4117     /* Input parameters check. */
   4118     POL_CHECK_NULL_PARAMETER(unit, policer_p);
   4119 
   4120     /* Initialization check */
   4121     CHECK_GLOBAL_METER_INIT(unit);
   4122     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4123 
   4124     hash_max = policer_id & BCMI_GLOBAL_METER_HASH_MASK;
   4125     for (hash_index = 0; hash_index <= hash_max; hash_index++) {
   4126         policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index);
   4127         while (NULL != policer_control) {
   4128             /* Match entry id. */
   4129             if (policer_id >= policer_control->pid &&
   4130                 policer_id < policer_control->pid + policer_control->no_of_policers) {
   4131                 *policer_p = policer_control;
   4132                 POL_FUNCTION_TRACE(unit, "OUT found");
   4133                 return (BCM_E_NONE);
   4134             }
   4135             policer_control = policer_control->next;
   4136         }
   4137     }
   4138     /* Policer with policer_id was not found. */
   4139     POL_FUNCTION_TRACE(unit, "OUT not found");
   4140     return (BCM_E_NOT_FOUND);
   4141 }
   4142 
   4143 int _bcm_global_meter_min_burst_size_set(
   4144     bcm_policer_config_t *pol_cfg);
   4145 
   4146 STATIC int
   4147 bcmi_esw_policer_action_attach(
   4148     int unit,
   4149     bcm_policer_t policer_id,
   4150     uint32 action_id);
   4151 
   4152 STATIC int
   4153 bcmi_esw_policer_action_detach(
   4154     int unit,
   4155     bcm_policer_t policer_id,
   4156     uint32 action_id);
   4157 
   4158 STATIC int
   4159 bcmi_esw_policer_action_attach_get(
   4160     int unit,
   4161     bcm_policer_t policer_id,
   4162     uint32 *action_id);
   4163 
   4164 /*
   4165  * Function:
   4166  *      bcmi_esw_global_meter_policer_set
   4167  * Purpose:
   4168  *     Configure the parmeters for a policer already created.
   4169  * Parameters:
   4170  *     unit                  - (IN) unit number
   4171  *     policer_id            - (IN) policer id
   4172  *     pol_cfg               - (IN) Policer control info
   4173  * Returns:
   4174  *     BCM_E_XXX
   4175  */
   4176 STATIC int
   4177 bcmi_esw_global_meter_policer_set(
   4178     int unit,
   4179     bcm_policer_t policer_id,
   4180     bcm_policer_config_t *pol_cfg)
   4181 {
   4182     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
   4183     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4184     uint32 pol_cfg_idx;
   4185 
   4186     POL_FUNCTION_TRACE(unit, "IN");
   4187 
   4188     /* Input parameters check. */
   4189     POL_CHECK_NULL_PARAMETER(unit, pol_cfg);
   4190 
   4191     /* lower must be 0 ~ 999 */
   4192     if (pol_cfg->cbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT ||
   4193         pol_cfg->cbits_burst_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT ||
   4194         pol_cfg->pbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT ||
   4195         pol_cfg->pbits_burst_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT ||
   4196         pol_cfg->max_cbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT ||
   4197         pol_cfg->max_pbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT) {
   4198         return BCM_E_PARAM;
   4199     }
   4200 
   4201     /* Initialization check */
   4202     CHECK_GLOBAL_METER_INIT(unit);
   4203     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4204 
   4205     /* validate policer id */
   4206     rv = bcmi_esw_policer_validate(unit, policer_id);
   4207     if (BCM_FAILURE(rv)) {
   4208         LOG_DEBUG(BSL_LS_BCM_POLICER,
   4209                   (BSL_META_U(unit,
   4210                               "Invalid policer id %x\n"),
   4211                    policer_id));
   4212         return (rv);
   4213     }
   4214     GLOBAL_METER_LOCK(unit);
   4215 
   4216     if (BCM_SUCCESS(rv)) {
   4217        /* Check whether the burst size is >= min required. If not, set it
   4218           to minimum required value */
   4219         rv = _bcm_global_meter_min_burst_size_set(pol_cfg);
   4220         if (BCM_FAILURE(rv)) {
   4221             GLOBAL_METER_UNLOCK(unit);
   4222             return (rv);
   4223         }
   4224 
   4225         /* Add code to write this to HW */
   4226         rv = bcmi_esw_global_meter_write_config_to_hw(unit,
   4227                 pol_cfg, policer_id);
   4228         if (BCM_FAILURE(rv)) {
   4229             GLOBAL_METER_UNLOCK(unit);
   4230             rv2 = bcmi_esw_global_meter_clear_config_on_hw(unit, policer_id);
   4231             BCM_IF_ERROR_RETURN(rv2);
   4232             LOG_ERROR(BSL_LS_BCM_POLICER,
   4233                       (BSL_META_U(unit,
   4234                                   "Unable to write policer config to hw %x\n"),
   4235                        policer_id));
   4236             return (rv);
   4237         }
   4238     }
   4239     GLOBAL_METER_UNLOCK(unit);
   4240 
   4241     rv = bcmi_esw_global_meter_base_policer_get(
   4242             unit, policer_id, &policer_control);
   4243     if (BCM_FAILURE(rv)) {
   4244         LOG_ERROR(BSL_LS_BCM_POLICER,
   4245                   (BSL_META_U(unit,
   4246                               "Unable to get policer control for "
   4247                               "policer id 0x%x(%d)\n"),
   4248                               policer_id,
   4249                               policer_id));
   4250         return (rv);
   4251     }
   4252     pol_cfg_idx = policer_id - policer_control->pid;
   4253 
   4254     /* Detach bk action */
   4255     if (BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID !=
   4256         policer_control->pol_cfg[pol_cfg_idx].action_id) {
   4257         BCM_IF_ERROR_RETURN(
   4258             bcmi_esw_policer_action_detach(
   4259                 unit, policer_id,
   4260                 policer_control->pol_cfg[pol_cfg_idx].action_id));
   4261     }
   4262 
   4263     /* Attach new action */
   4264     if (BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID !=
   4265         pol_cfg->action_id) {
   4266         BCM_IF_ERROR_RETURN(
   4267             bcmi_esw_policer_action_attach(
   4268                 unit, policer_id, pol_cfg->action_id));
   4269     }
   4270 
   4271     /* store pol_cfg to bk */
   4272     GLOBAL_METER_BK_LOCK(unit);
   4273     sal_memcpy(&(policer_control->pol_cfg[pol_cfg_idx]),
   4274                pol_cfg,
   4275                sizeof(bcm_policer_config_t));
   4276     GLOBAL_METER_BK_UNLOCK(unit);
   4277 
   4278     POL_FUNCTION_TRACE(unit, "OUT");
   4279     return rv;
   4280 }
   4281 
   4282 /*
   4283  * Function:
   4284  *     bcmi_esw_global_meter_policer_get
   4285  * Purpose:
   4286  *     Get the configuration info for a given policer id
   4287  * Parameters:
   4288  *     unit                  - (IN) unit number
   4289  *     policer_id            - (IN) policer id
   4290  *     pol_cfg               - (OUT) Policer control info
   4291  * Returns:
   4292  *     BCM_E_XXX
   4293  */
   4294 STATIC int
   4295 bcmi_esw_global_meter_policer_get(
   4296     int unit,
   4297     bcm_policer_t policer_id,
   4298     bcm_policer_config_t *pol_cfg)
   4299 {
   4300     int rv = BCM_E_NONE;
   4301     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4302     uint32 pol_cfg_idx;
   4303     bcm_policer_config_t actual_pol_cfg;
   4304 
   4305     POL_FUNCTION_TRACE(unit, "IN");
   4306 
   4307     /* Input parameters check. */
   4308     POL_CHECK_NULL_PARAMETER(unit, pol_cfg);
   4309 
   4310     /* Initialization check */
   4311     CHECK_GLOBAL_METER_INIT(unit);
   4312     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4313 
   4314     /* validate policer id */
   4315     rv = bcmi_esw_policer_validate(unit, policer_id);
   4316     if (BCM_FAILURE(rv)) {
   4317         LOG_DEBUG(BSL_LS_BCM_POLICER,
   4318                   (BSL_META_U(unit,
   4319                               "Invalid policer id %x  \n"),
   4320                    policer_id));
   4321         return (rv);
   4322     }
   4323 
   4324     /* read pol_cfg from bk */
   4325     GLOBAL_METER_BK_LOCK(unit);
   4326     rv = bcmi_esw_global_meter_base_policer_get(
   4327             unit, policer_id, &policer_control);
   4328     if (BCM_FAILURE(rv)) {
   4329         GLOBAL_METER_BK_UNLOCK(unit);
   4330         LOG_ERROR(BSL_LS_BCM_POLICER,
   4331                   (BSL_META_U(unit,
   4332                               "Unable to get policer control for "
   4333                               "policer id 0x%x(%d)\n"),
   4334                               policer_id,
   4335                               policer_id));
   4336         return (rv);
   4337     }
   4338     pol_cfg_idx = policer_id - policer_control->pid;
   4339     sal_memcpy(pol_cfg,
   4340                &(policer_control->pol_cfg[pol_cfg_idx]),
   4341                sizeof(bcm_policer_config_t));
   4342     GLOBAL_METER_BK_UNLOCK(unit);
   4343 
   4344     /* read from HW for actual_xxx */
   4345     GLOBAL_METER_LOCK(unit);
   4346     rv = bcmi_esw_global_meter_read_config_from_hw(unit,
   4347             policer_id, &actual_pol_cfg);
   4348     GLOBAL_METER_UNLOCK(unit);
   4349     if (BCM_FAILURE(rv)) {
   4350         LOG_DEBUG(BSL_LS_BCM_POLICER,
   4351                   (BSL_META_U(unit,
   4352                               "Unable to read policer config from hw %x\n"),
   4353                    policer_id));
   4354         return (rv);
   4355     }
   4356     pol_cfg->actual_ckbits_sec =
   4357         actual_pol_cfg.ckbits_sec;
   4358     pol_cfg->actual_cbits_sec_lower =
   4359         actual_pol_cfg.cbits_sec_lower;
   4360     pol_cfg->actual_ckbits_burst =
   4361         actual_pol_cfg.ckbits_burst;
   4362     pol_cfg->actual_cbits_burst_lower =
   4363         actual_pol_cfg.cbits_burst_lower;
   4364     pol_cfg->actual_pkbits_sec =
   4365         actual_pol_cfg.pkbits_sec;
   4366     pol_cfg->actual_pbits_sec_lower =
   4367         actual_pol_cfg.pbits_sec_lower;
   4368     pol_cfg->actual_pkbits_burst =
   4369         actual_pol_cfg.pkbits_burst;
   4370     pol_cfg->actual_pbits_burst_lower =
   4371         actual_pol_cfg.pbits_burst_lower;
   4372 
   4373     POL_FUNCTION_TRACE(unit, "OUT");
   4374     return rv;
   4375 }
   4376 
   4377 /*
   4378  * Function:
   4379  *     bcmi_esw_global_meter_policer_delete
   4380  * Purpose:
   4381  *     Internal function that destroys a policer and readjusts action
   4382  *     usage reference count and policer allocation management data structure.
   4383  * Parameters:
   4384  *     unit                  - (IN) unit number
   4385  *     policer_control       - (IN) policer control info
   4386  * Returns:
   4387  *     BCM_E_XXX
   4388  */
   4389 STATIC int
   4390 bcmi_esw_global_meter_policer_delete(
   4391     int unit,
   4392     bcmi_global_meter_policer_control_t *policer_control)
   4393 {
   4394     int rv = BCM_E_NONE;
   4395     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   4396     uint32 numbers = 0, idx;
   4397     int offset_mode = 0;
   4398     int policer_idx;
   4399 
   4400     POL_FUNCTION_TRACE(unit, "IN");
   4401 
   4402     /* Input parameters check. */
   4403     POL_CHECK_NULL_PARAMETER(unit, policer_control);
   4404 
   4405     numbers = policer_control->no_of_policers;
   4406 
   4407     /* Initialization check */
   4408     CHECK_GLOBAL_METER_INIT(unit);
   4409     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4410 
   4411     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   4412 
   4413     GLOBAL_METER_LOCK(unit);
   4414 
   4415     /* Make sure policer is not attached to any entry. */
   4416     if (0 != policer_control->ref_count) {
   4417         GLOBAL_METER_UNLOCK(unit);
   4418         LOG_DEBUG(BSL_LS_BCM_POLICER,
   4419                   (BSL_META_U(unit,
   4420                               "Policer is still in use\n")));
   4421         return (BCM_E_BUSY);
   4422     }
   4423 
   4424     /* Decrease the reference count of actions. */
   4425     for (idx = 0; idx < policer_control->no_of_policers; idx++) {
   4426         if (BCMI_ACTION_ID_BK_GET(
   4427                 unit,
   4428                 policer_control->pol_cfg[idx].action_id).reference_count > 0) {
   4429             BCMI_ACTION_ID_BK_GET(
   4430                 unit,
   4431                 policer_control->pol_cfg[idx].action_id).reference_count--;
   4432         }
   4433     }
   4434 
   4435     /* get the HW index for the policer to be deleted */
   4436     rv = bcmi_esw_policer_table_index_get(
   4437             unit, policer_control->pid, &policer_idx);
   4438     if (BCM_FAILURE(rv)) {
   4439         GLOBAL_METER_UNLOCK(unit);
   4440         LOG_DEBUG(BSL_LS_BCM_POLICER,
   4441                   (BSL_META_U(unit,
   4442                               "Unable to Get policer index for "
   4443                               "policer \n")));
   4444         return rv;
   4445     }
   4446 
   4447     bcmi_global_meter_free_allocated_policer_on_error(
   4448         unit, numbers, policer_idx);
   4449 
   4450     /* Check if the chip specific function existed */
   4451     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->mem_range_clear);
   4452 
   4453     /* Clear SVM METER TABLE */
   4454     rv = gm_dev_info->mem_range_clear(unit, policer_idx, numbers);
   4455     if (BCM_FAILURE(rv)) {
   4456         GLOBAL_METER_UNLOCK(unit);
   4457     }
   4458 
   4459     /* Delete policer from policers hash. */
   4460     _GLOBAL_METER_HASH_REMOVE(
   4461         BCMI_POLICER_BK_GET(unit), bcmi_global_meter_policer_control_t,
   4462         policer_control, (policer_control->pid & BCMI_GLOBAL_METER_HASH_MASK));
   4463 
   4464     /* decrement mode reference count  */
   4465     BCM_IF_ERROR_RETURN(
   4466         bcmi_esw_policer_offset_mode_get(unit, policer_control->pid, &offset_mode));
   4467     bcmi_policer_svc_meter_dec_mode_ref_cnt(unit, offset_mode);
   4468     GLOBAL_METER_UNLOCK(unit);
   4469 
   4470     /* De-allocate policer descriptor. */
   4471     POL_MEM_FREE(policer_control->pol_cfg);
   4472     POL_MEM_FREE(policer_control);
   4473 
   4474     POL_FUNCTION_TRACE(unit, "OUT");
   4475     return rv;
   4476 }
   4477 
   4478 /*
   4479  * Function:
   4480  *     bcmi_esw_global_meter_policer_destroy
   4481  * Purpose:
   4482  *     Destroys a policer and readjusts action
   4483  *     usage reference count and policer allocation management data structure.
   4484  * Parameters:
   4485  *     unit                  - (IN) unit number
   4486  *     policer_id            - (IN) policer id
   4487  * Returns:
   4488  *     BCM_E_XXX
   4489  */
   4490 STATIC int
   4491 bcmi_esw_global_meter_policer_destroy(
   4492     int unit,
   4493     bcm_policer_t policer_id)
   4494 {
   4495     int rv = BCM_E_NONE;
   4496     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4497 
   4498     POL_FUNCTION_TRACE(unit, "IN");
   4499 
   4500     /* Initialization check */
   4501     CHECK_GLOBAL_METER_INIT(unit);
   4502     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4503 
   4504     /* Validate policer id */
   4505     rv = bcmi_esw_policer_validate(unit, policer_id);
   4506     if (BCM_FAILURE(rv)) {
   4507         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   4508                     (BSL_META_U(unit,
   4509                                 "Invalid policer id %x(%d)\n"),
   4510                                 policer_id, policer_id));
   4511         return (rv);
   4512     }
   4513 
   4514     GLOBAL_METER_LOCK(unit);
   4515     rv = bcmi_esw_global_meter_base_policer_get(unit,
   4516             policer_id, &policer_control);
   4517     if (BCM_FAILURE(rv)) {
   4518         GLOBAL_METER_UNLOCK(unit);
   4519         LOG_ERROR(BSL_LS_BCM_POLICER,
   4520                   (BSL_META_U(unit,
   4521                               "Unable to get policer control for "
   4522                               "policer id 0x%x(%d)\n"),
   4523                               policer_id,
   4524                               policer_id));
   4525         return (rv);
   4526     }
   4527     rv = bcmi_esw_global_meter_policer_delete(unit, policer_control);
   4528     GLOBAL_METER_UNLOCK(unit);
   4529 
   4530     POL_FUNCTION_TRACE(unit, "OUT");
   4531     return (rv);
   4532 }
   4533 
   4534 /*
   4535  * Function:
   4536  *     bcmi_esw_global_meter_policer_destroy_all
   4537  * Purpose:
   4538  *     Destroy all the policers.
   4539  * Parameters:
   4540  *     unit                  - (IN) unit number
   4541  * Returns:
   4542  *     BCM_E_XXX
   4543  */
   4544 STATIC int
   4545 bcmi_esw_global_meter_policer_destroy_all(int unit)
   4546 {
   4547     int rv = BCM_E_NONE;
   4548     int idx = 0;
   4549     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4550 
   4551     CHECK_GLOBAL_METER_INIT(unit);
   4552 
   4553     GLOBAL_METER_LOCK(unit);
   4554 
   4555     /* Iterate over all hash buckets. */
   4556     for (idx = 0; idx < BCMI_GLOBAL_METER_HASH_SIZE; idx++) {
   4557         policer_control = BCMI_POLICER_HASH_BK_GET(unit, idx);
   4558         /* Destroy entries in each bucket. */
   4559         while (NULL != policer_control) {
   4560             rv = bcmi_esw_global_meter_policer_delete(unit, policer_control);
   4561             if (BCM_FAILURE(rv)) {
   4562                 break;
   4563             }
   4564             policer_control = policer_control->next;
   4565         }
   4566     }
   4567 
   4568     GLOBAL_METER_UNLOCK(unit);
   4569     return rv;
   4570 }
   4571 
   4572 /*
   4573  * Function:
   4574  *     bcmi_esw_global_meter_policer_traverse
   4575  * Purpose:
   4576  *     Traverse through all the policers that are configured and
   4577  *     call the given call back function with policer configuration.
   4578  * Parameters:
   4579  *     unit                  - (IN) unit number
   4580  *     cb                    - (IN) Call back function
   4581  *     user_data             - (OUT) Data for callback function
   4582  * Returns:
   4583  *     BCM_E_XXX
   4584  */
   4585 STATIC int
   4586 bcmi_esw_global_meter_policer_traverse(
   4587     int unit,
   4588     bcm_policer_traverse_cb cb,
   4589     void *user_data)
   4590 {
   4591     int rv = BCM_E_NONE;
   4592     int hash_index = 0;
   4593     bcm_policer_config_t cfg;      /* Policer configuration. */
   4594     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4595 
   4596     /* Iterate over all hash buckets. */
   4597     for (hash_index = 0; hash_index < BCMI_GLOBAL_METER_HASH_SIZE; hash_index++) {
   4598         policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index);
   4599         /* Iterate all entries in each bucket. */
   4600         while (NULL != policer_control) {
   4601             rv = bcmi_esw_global_meter_policer_get(unit,
   4602                     policer_control->pid, &cfg);
   4603             if (BCM_FAILURE(rv)) {
   4604                 break;
   4605             }
   4606             rv = (*cb)(unit, policer_control->pid, &cfg, user_data);
   4607             if (BCM_FAILURE(rv)) {
   4608                 break;
   4609             }
   4610             policer_control = policer_control->next;
   4611         }
   4612         if (BCM_FAILURE(rv)) {
   4613             break;
   4614         }
   4615     }
   4616     return rv;
   4617 }
   4618 
   4619 /*
   4620  * Function:
   4621  *     bcmi_esw_policer_envelop_create
   4622  * Purpose:
   4623  *     Create a single policer in Envelop mode. The policer created is
   4624  *     micro or a macro meter depending on the configuration.
   4625  * Parameters:
   4626  *     unit                  - (IN) unit number
   4627  *     flags                 - (IN) Indicates micro/macro flow policer
   4628  *     macro_flow_policer_id - (IN) macro flow policer id
   4629  *     policer_id            - (OUT) policer Id
   4630  * Returns:
   4631  *     BCM_E_XXX
   4632  */
   4633 STATIC int
   4634 bcmi_esw_policer_envelop_create(int unit,
   4635     uint32 flags,
   4636     bcm_policer_t macro_flow_policer_id,
   4637     bcm_policer_t *policer_id)
   4638 {
   4639     bcm_error_t rv = BCM_E_UNAVAIL;
   4640 
   4641     /* Not supported */
   4642     POL_FUNCTION_TRACE(unit, "IN");
   4643     POL_FUNCTION_TRACE(unit, "OUT");
   4644     return rv;
   4645 }
   4646 
   4647 /*
   4648  * Function:
   4649  *      bcmi_esw_policer_envelop_group_create
   4650  * Purpose:
   4651  *      Create a group of policers based on the mode.
   4652  * Parameters:
   4653  *     unit                  - (IN) unit number
   4654  *     flags                 - (IN) Indicates micro/macro flow policer
   4655  *     mode                  - (IN) policer group mode
   4656  *     macro_flow_policer_id - (IN) macro flow policer id
   4657  *     policer_id            - (OUT)Base policer Id
   4658  *     npolicers             - (OUT) Number of policers created
   4659  * Returns:
   4660  *     BCM_E_XXX
   4661  */
   4662 STATIC int
   4663 bcmi_esw_policer_envelop_group_create(int unit,
   4664     uint32 flags,
   4665     bcm_policer_group_mode_t mode,
   4666     bcm_policer_t macro_flow_policer_id,
   4667     bcm_policer_t *policer_id,
   4668     int *npolicers)
   4669 {
   4670     bcm_error_t rv = BCM_E_UNAVAIL;
   4671 
   4672     /* Not supported */
   4673     POL_FUNCTION_TRACE(unit, "IN");
   4674     POL_FUNCTION_TRACE(unit, "OUT");
   4675     return rv;
   4676 }
   4677 
   4678 /*
   4679  * Function:
   4680  *     bcmi_esw_policer_custom_group_create
   4681  * Purpose:
   4682  *     Create a group of policers based on the mode.
   4683  * Parameters:
   4684  *     unit                  - (IN) unit number
   4685  *     flags                 - (IN) flags
   4686  *     mode_id               - (IN) Created Mode Id for Policer Group Mode
   4687  *     macro_flow_policer_id - (IN) Is an optional parameter and needs to be
   4688  *                                  passed only while creating the micro flow
   4689  *                                  policers of a hierarchical groupi
   4690  *                                  (2 stage policers).
   4691  *     policer_id            - (OUT)Base policer Id
   4692  *     npolicers             - (OUT) Number of policers created
   4693  * Returns:
   4694  *     BCM_E_XXX
   4695  */
   4696 STATIC int
   4697 bcmi_esw_policer_custom_group_create(
   4698     int unit,
   4699     uint32 flags,
   4700     uint32 mode_id,
   4701     bcm_policer_t macro_flow_policer_id,
   4702     bcm_policer_t *policer_id,
   4703     uint32 *npolicers)
   4704 {
   4705     bcm_error_t rv = BCM_E_NONE;
   4706     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   4707     uint32 offset_mode;
   4708     int policer_idx;
   4709     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4710     bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeSingle;
   4711 
   4712     POL_FUNCTION_TRACE(unit, "IN");
   4713 
   4714     /* Parameter NULL error handling */
   4715     POL_CHECK_NULL_PARAMETER(unit, policer_id);
   4716     POL_CHECK_NULL_PARAMETER(unit, npolicers);
   4717 
   4718     POL_FUNCTION_DEBUG(unit, "flags %x", flags);
   4719     POL_FUNCTION_DEBUG(unit, "mode_id %d", mode_id);
   4720     POL_FUNCTION_DEBUG(unit, "macro_flow_policer_id %d",
   4721         macro_flow_policer_id);
   4722 
   4723     /* Initialization check */
   4724     CHECK_GLOBAL_METER_INIT(unit);
   4725     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4726 
   4727     /* Validate mode_id */
   4728     BCM_IF_ERROR_RETURN(
   4729         bcmi_policer_mode_id_validate(unit, mode_id));
   4730 
   4731     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   4732     bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   4733 
   4734     *npolicers = bk_svm_mode_info->no_of_policers;
   4735 
   4736     POL_FUNCTION_DEBUG(unit, "offset_mode %d", offset_mode);
   4737     POL_FUNCTION_DEBUG(unit, "npolicers %d", *npolicers);
   4738 
   4739     GLOBAL_METER_LOCK(unit);
   4740     rv = bcmi_global_meter_policer_id_alloc(
   4741             unit, *npolicers, &policer_idx);
   4742     if (BCM_FAILURE(rv)) {
   4743         GLOBAL_METER_UNLOCK(unit);
   4744         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   4745                     (BSL_META_U(unit,
   4746                                 "Failed to allocate policer\n")));
   4747         return rv;
   4748     }
   4749 
   4750     /* Allocate policer descriptor. */
   4751     rv = bcmi_global_meter_policer_control_alloc(
   4752             unit, *npolicers, &policer_control);
   4753     if (BCM_FAILURE(rv)) {
   4754         GLOBAL_METER_UNLOCK(unit);
   4755         bcmi_global_meter_free_allocated_policer_on_error(
   4756             unit, *npolicers, policer_idx);
   4757         LOG_ERROR(BSL_LS_BCM_POLICER,
   4758                   (BSL_META_U(unit,
   4759                               "Unable to allocate memory for "
   4760                               "policer control\n")));
   4761         return (rv);
   4762     }
   4763 
   4764     /* Add mode info to the policer index */
   4765     *policer_id = POLICER_IDX_TO_POLICER_ID(offset_mode, policer_idx);
   4766 
   4767     /* Set policer configuration */
   4768     policer_control->pid = *policer_id;
   4769     policer_control->no_of_policers =  *npolicers;
   4770     policer_control->grp_mode = group_mode;
   4771 
   4772     /* increment mode reference count for new policer  */
   4773     rv = bcmi_policer_svc_meter_inc_mode_ref_cnt(unit, offset_mode);
   4774     if (BCM_FAILURE(rv)) {
   4775         /* free all the allocated policers */
   4776         bcmi_global_meter_free_allocated_policer_on_error(
   4777             unit, *npolicers, policer_idx);
   4778         /* De-allocate policer descriptor. */
   4779         POL_MEM_FREE(policer_control->pol_cfg);
   4780         POL_MEM_FREE(policer_control);
   4781         GLOBAL_METER_UNLOCK(unit);
   4782         return rv;
   4783     }
   4784 
   4785     /* Insert policer into policers hash. */
   4786     _GLOBAL_METER_HASH_INSERT(BCMI_POLICER_BK_GET(unit),
   4787                               policer_control,
   4788                               (*policer_id & _GLOBAL_METER_HASH_MASK));
   4789 
   4790     GLOBAL_METER_UNLOCK(unit);
   4791     POL_FUNCTION_DEBUG(unit, "policer_id 0x%x", *policer_id);
   4792     POL_FUNCTION_TRACE(unit, "OUT");
   4793     return rv;
   4794 }
   4795 
   4796 /*
   4797  * Function:
   4798  *   bcmi_esw_policer_group_get
   4799  * Purpose:
   4800  *   Get the list of policer members for a given policer group represented
   4801  *   by its base policer id
   4802  * Parameters:
   4803  *   unit                  - (IN) unit number
   4804  *   base_policer_id       - (IN) Base policer Id
   4805  *   member_max            - (IN) Maximum number of policers to return in
   4806  *                            the member_array parameter
   4807  *   member_array          - (OUT) Place to store policer members of the given
   4808  *                            policer group represented by its base_policer_id
   4809  *                            Memory need to be allocated by the end user before
   4810  *                            calling the API
   4811  *   member_count          - (OUT) Place to store total number of policers
   4812  *                            configured in the given policer group represented
   4813  *                            by base_policer_id
   4814 
   4815  * Returns:
   4816  *     BCM_E_XXX
   4817  */
   4818 STATIC int
   4819 bcmi_esw_policer_group_get(
   4820     int unit,
   4821     bcm_policer_t base_policer_id,
   4822     int member_max,
   4823     bcm_policer_t *member_array,
   4824     int *member_count)
   4825 {
   4826     bcm_error_t rv = BCM_E_UNAVAIL;
   4827     bcmi_global_meter_policer_control_t *policer_control = NULL;
   4828     int index, indices_to_fill;
   4829 
   4830     POL_FUNCTION_TRACE(unit, "IN");
   4831     CHECK_GLOBAL_METER_INIT(unit);
   4832     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4833 
   4834     /* verify arguments */
   4835     if ((base_policer_id == 0) || (member_count == NULL)) {
   4836         return BCM_E_PARAM;
   4837     }
   4838     /* verify arguments, desired array elements to be retrived */
   4839     if ((member_max > 0) && (member_array == NULL)) {
   4840         return BCM_E_PARAM;
   4841     }
   4842 
   4843     rv = bcmi_esw_base_policer_validate(unit, base_policer_id);
   4844     BCM_IF_ERROR_RETURN(rv);
   4845 
   4846     GLOBAL_METER_LOCK(unit);
   4847     rv = bcmi_esw_global_meter_base_policer_get(
   4848             unit, base_policer_id, &policer_control);
   4849     if (BCM_FAILURE(rv)) {
   4850         GLOBAL_METER_UNLOCK(unit);
   4851         LOG_ERROR(BSL_LS_BCM_POLICER,
   4852                   (BSL_META_U(unit,
   4853                               "Unable to get policer control for "
   4854                               "policer id 0x%x(%d)\n"),
   4855                               base_policer_id,
   4856                               base_policer_id));
   4857         return (rv);
   4858     }
   4859 
   4860     *member_count = policer_control->no_of_policers;
   4861 
   4862     if (member_max < *member_count) {
   4863         indices_to_fill = member_max;
   4864         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   4865                     (BSL_META_U(unit,
   4866             "member_count(%d) of base_policer_id(%d)"
   4867             "is large than the member_array size(%d)"),
   4868             *member_count,
   4869             base_policer_id,
   4870             member_max));
   4871     } else {
   4872         indices_to_fill = *member_count;
   4873     }
   4874 
   4875     for (index = 0; index < indices_to_fill; index++) {
   4876         member_array[index] = base_policer_id + index;
   4877     }
   4878 
   4879     GLOBAL_METER_UNLOCK(unit);
   4880     POL_FUNCTION_TRACE(unit, "OUT");
   4881     return rv;
   4882 }
   4883 
   4884 /*
   4885  * Function:
   4886  *     bcmi_esw_policer_group_set_mode_and_map
   4887  * Purpose:
   4888  *     create group set from given policer group mode and offset_map
   4889  * Parameters:
   4890  *     unit                  - (IN) unit number
   4891  *     mode                  - (IN) Policer group mode
   4892  *     mapping               - (IN) customized offset mapping
   4893  *     npolicers             - (OUT) Number of policers
   4894  *     pkt_attr_selectors    - (OUT) Packet attribute selectors
   4895  * Returns:
   4896  *     BCM_E_XXX
   4897  */
   4898 STATIC int
   4899 bcmi_esw_policer_group_set_mode_and_map(
   4900     int unit,
   4901     bcm_policer_group_mode_t group_mode,
   4902     bcm_policer_map_t *mapping,
   4903     int *npolicers,
   4904     bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors)
   4905 {
   4906     int rv = BCM_E_NONE;
   4907     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   4908     int count = 0;          /* Number of offset mappings */
   4909     uint8 *final_offset = NULL;
   4910     uint8 base_final_offset = 0;
   4911     uint32 pkt_attr_pkt_type_cnt = 0, pkt_attr_v_cnt = 0;
   4912     bcm_policer_group_mode_attr_t attr = bcmPolicerGroupModeAttrPktType;
   4913     pkt_tcam_attr_bits_t *pkt_attr_v = NULL;
   4914     int sel = 0;
   4915     uint32 pol_offset = 0, max_pol_offset = 0;
   4916 
   4917     POL_FUNCTION_TRACE(unit, "IN");
   4918 
   4919     /* Parameter NULL error handling */
   4920     POL_CHECK_NULL_PARAMETER(unit, npolicers);
   4921     POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors);
   4922 
   4923     /* Initialization check */
   4924     CHECK_GLOBAL_METER_INIT(unit);
   4925     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   4926     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   4927 
   4928     /* Check if the chip specific function existed */
   4929     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_supported);
   4930 
   4931     /* Check if group mode is supported */
   4932     rv = gm_dev_info->group_mode_supported(unit, group_mode);
   4933     if (BCM_FAILURE(rv)) {
   4934         /* dump all support group_mode */
   4935         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   4936                     (BSL_META_U(unit,
   4937                                 "Supported group mode:\n")));
   4938         for (group_mode = bcmPolicerGroupModeSingle;
   4939              group_mode < bcmPolicerGroupModeCount;
   4940              group_mode++) {
   4941             rv = gm_dev_info->group_mode_supported(unit, group_mode);
   4942             if (BCM_SUCCESS(rv)) {
   4943                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
   4944                             (BSL_META_U(unit, "%s\n"),
   4945                     bcm_policer_group_mode_t_str[group_mode]));
   4946             }
   4947         }
   4948         return BCM_E_UNAVAIL;
   4949     }
   4950 
   4951     /* Check group mode support user defined "mapping->offset_map" */
   4952     switch (group_mode) {
   4953         case bcmPolicerGroupModeDot1P:
   4954         case bcmPolicerGroupModeInnerDot1P:
   4955         case bcmPolicerGroupModeIntPri:
   4956         case bcmPolicerGroupModeIntPriCng:
   4957         case bcmPolicerGroupModeShortIntPri:
   4958         case bcmPolicerGroupModeSvpType:
   4959         case bcmPolicerGroupModeDscp:
   4960         case bcmPolicerGroupModeCascade:
   4961         case bcmPolicerGroupModeIntPriCascade:
   4962         case bcmPolicerGroupModeCascadeDroppedPktExclude:
   4963         case bcmPolicerGroupModeCascadeWithCoupling:
   4964         case bcmPolicerGroupModeIntPriCascadeWithCoupling:
   4965         case bcmPolicerGroupModePreemptable:
   4966         {
   4967             /* Supported */
   4968             if (mapping != NULL) {
   4969                 final_offset = mapping->offset_map;
   4970                 count = mapping->count;
   4971             }
   4972             break;
   4973         }
   4974         default:
   4975         {
   4976             /* Not Supported and mapping should be NULL */
   4977             if (mapping != NULL) {
   4978                 LOG_ERROR(BSL_LS_BCM_POLICER,
   4979                           (BSL_META_U(unit,
   4980                     "group_mode(%d = %s) doesn't not support "
   4981                     "flexible mapping of offset. offset_map should be NULL\n"),
   4982                     group_mode,
   4983                     bcm_policer_group_mode_t_str[group_mode]));
   4984                 return BCM_E_PARAM;
   4985             }
   4986         }
   4987     }
   4988 
   4989     switch (group_mode) {
   4990         /* A single policer used for all traffic types */
   4991         case bcmPolicerGroupModeSingle:
   4992         {
   4993             *npolicers = 1;
   4994             pkt_attr_v_cnt = 1;
   4995             pkt_attr_v =
   4996                 &pkt_attr_selectors->pkt_attr_v[0];
   4997             pkt_attr_v->attr_bits_selector = 1;
   4998             break;
   4999         }
   5000         /********************************************************************/
   5001         /* A dedicated policer per traffic type Unicast, multicast,         */
   5002         /* broadcast                                                        */
   5003         /* 1) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT            */
   5004         /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|               */
   5005         /*     UNKNOWN_IPMC_PKT                                             */
   5006         /* 3) L2BC_PKT|                                                     */
   5007         /********************************************************************/
   5008         case bcmPolicerGroupModeTrafficType:
   5009         {
   5010             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5011             {
   5012                 /* 1) CONTROL_PKT|BPDU_PKT */
   5013                 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5014                 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5015                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5016                 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|
   5017                 KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT */
   5018                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5019                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5020                 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5021                 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5022                 /* 3) L2BC_PKT */
   5023                 {2, bcmPolicerGroupModeAttrPktTypeL2BC}
   5024             };
   5025 
   5026             *npolicers = 3;
   5027 
   5028             /* following is array size of pkt_res_final_offset_v */
   5029             pkt_attr_v_cnt = 3 + 4 + 1;
   5030 
   5031             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5032                 return BCM_E_RESOURCE;
   5033             }
   5034 
   5035             attr = bcmPolicerGroupModeAttrPktType;
   5036             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5037                 pkt_attr_v =
   5038                     &pkt_attr_selectors->pkt_attr_v[sel];
   5039                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5040                 pkt_attr_v->value_mask[attr] =
   5041                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5042                 pkt_attr_v->value[attr] =
   5043                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5044                 pkt_attr_v->final_offset =
   5045                     pkt_res_final_offset_v[sel].final_offset;
   5046             }
   5047             break;
   5048         }
   5049         /*****************************************************************/
   5050         /* A pair of policers where the base policer is used for dlf and */
   5051         /* the other is used for all traffic types                       */
   5052         /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT)                                */
   5053         /* 2) UNKNOWN_PKT | CONTROL_PKT|BPDU_PKT|L2BC_PKT|L2UC_PKT|      */
   5054         /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|            */
   5055         /*    UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|                           */
   5056         /*    UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|         */
   5057         /*    KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|          */
   5058         /*    UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                   */
   5059         /*****************************************************************/
   5060         case bcmPolicerGroupModeDlfAll:
   5061         {
   5062             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5063             {
   5064                 /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT) */
   5065                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC},
   5066                 /* 2) */
   5067                 {1, bcmPolicerGroupModeAttrPktTypeUnknown},
   5068                 {1, bcmPolicerGroupModeAttrPktTypeControl},
   5069                 {1, bcmPolicerGroupModeAttrPktTypeBPDU},
   5070                 {1, bcmPolicerGroupModeAttrPktTypeL2BC},
   5071                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5072                 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5073                 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5074                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5075                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5076                 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5077                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5078                 {1, bcmPolicerGroupModeAttrPktTypeKnownMpls},
   5079                 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsL3},
   5080                 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsL2},
   5081                 {1, bcmPolicerGroupModeAttrPktTypeUnknownMpls},
   5082                 {1, bcmPolicerGroupModeAttrPktTypeKnownMim},
   5083                 {1, bcmPolicerGroupModeAttrPktTypeUnknownMim},
   5084                 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast}
   5085             };
   5086 
   5087             *npolicers = 2;
   5088             /* following is array size of pkt_res_final_offset_v */
   5089             pkt_attr_v_cnt = 1 + 18;
   5090 
   5091             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5092                 return BCM_E_RESOURCE;
   5093             }
   5094 
   5095             attr = bcmPolicerGroupModeAttrPktType;
   5096             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5097                 pkt_attr_v =
   5098                     &pkt_attr_selectors->pkt_attr_v[sel];
   5099                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5100                 pkt_attr_v->value_mask[attr] =
   5101                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5102                 pkt_attr_v->value[attr] =
   5103                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5104                 pkt_attr_v->final_offset =
   5105                     pkt_res_final_offset_v[sel].final_offset;
   5106             }
   5107             break;
   5108         }
   5109          /* ******************************************************* */
   5110          /* A dedicated policer for unknown unicast, known unicast, */
   5111          /* multicast, broadcast                                    */
   5112          /* 1) UNKNOWN_L3UC_PKT                                     */
   5113          /* 2) L2UC_PKT | KNOWN_L3UC_PKT                            */
   5114          /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT |                    */
   5115          /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                    */
   5116          /* 4) L2BC_PKT                                             */
   5117          /* ******************************************************* */
   5118         case bcmPolicerGroupModeTyped:
   5119         {
   5120             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5121             {
   5122                 /* 1) UNKNOWN_L3UC_PKT */
   5123                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5124                 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */
   5125                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5126                 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5127                 /* 3) */
   5128                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5129                 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5130                 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5131                 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5132                 /* 4) L2BC_PKT */
   5133                 {3, bcmPolicerGroupModeAttrPktTypeL2BC}
   5134             };
   5135 
   5136             *npolicers = 4;
   5137             /* following is array size of pkt_res_final_offset_v */
   5138             pkt_attr_v_cnt = 1 + 2 + 4 + 1;
   5139 
   5140             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5141                 return BCM_E_RESOURCE;
   5142             }
   5143 
   5144             attr = bcmPolicerGroupModeAttrPktType;
   5145             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5146                 pkt_attr_v =
   5147                     &pkt_attr_selectors->pkt_attr_v[sel];
   5148                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5149                 pkt_attr_v->value_mask[attr] =
   5150                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5151                 pkt_attr_v->value[attr] =
   5152                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5153                 pkt_attr_v->final_offset =
   5154                     pkt_res_final_offset_v[sel].final_offset;
   5155             }
   5156             break;
   5157         }
   5158         /* ******************************************************** */
   5159         /* A dedicated policer for unknown unicast, known unicast,  */
   5160         /* multicast, broadcast and one for all traffic(not already */
   5161         /* counted)                                                 */
   5162         /* 1) UNKNOWN_L3UC_PKT                                      */
   5163         /* 2) L2UC_PKT | KNOWN_L3UC_PKT                             */
   5164         /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                       */
   5165         /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                     */
   5166         /* 4) L2BC_PKT                                              */
   5167         /* 5) UNKNOWN_PKT|CONTROL_PKT|BPDU_PKT|L2DLF_PKT|           */
   5168         /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_MPLS_PKT |      */
   5169         /*    KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT  */
   5170         /*    KNOWN_MIM_PKT|UNKNOWN_MIM_PKT|                        */
   5171         /*    KNOWN_MPLS_MULTICAST_PKT                              */
   5172         /* ******************************************************** */
   5173         case bcmPolicerGroupModeTypedAll:
   5174         {
   5175             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5176             {
   5177                 /* 1) UNKNOWN_L3UC_PKT */
   5178                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5179                 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */
   5180                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5181                 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5182                 /* 3) */
   5183                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5184                 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5185                 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5186                 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5187                 /* 4) L2BC_PKT */
   5188                 {3, bcmPolicerGroupModeAttrPktTypeL2BC},
   5189                 /* 5) */
   5190                 {4, bcmPolicerGroupModeAttrPktTypeUnknown},
   5191                 {4, bcmPolicerGroupModeAttrPktTypeControl},
   5192                 {4, bcmPolicerGroupModeAttrPktTypeBPDU},
   5193                 {4, bcmPolicerGroupModeAttrPktTypeUnknownL2UC},
   5194                 {4, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5195                 {4, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5196                 {4, bcmPolicerGroupModeAttrPktTypeKnownMpls},
   5197                 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsL3},
   5198                 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsL2},
   5199                 {4, bcmPolicerGroupModeAttrPktTypeUnknownMpls},
   5200                 {4, bcmPolicerGroupModeAttrPktTypeKnownMim},
   5201                 {4, bcmPolicerGroupModeAttrPktTypeUnknownMim},
   5202                 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast}
   5203             };
   5204 
   5205             *npolicers = 5;
   5206             /* following is array size of pkt_res_final_offset_v */
   5207             pkt_attr_v_cnt = 1 + 2 + 4 + 1 + 13;
   5208 
   5209             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5210                 return BCM_E_RESOURCE;
   5211             }
   5212 
   5213             attr = bcmPolicerGroupModeAttrPktType;
   5214             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5215                 pkt_attr_v =
   5216                     &pkt_attr_selectors->pkt_attr_v[sel];
   5217                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5218                 pkt_attr_v->value_mask[attr] =
   5219                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5220                 pkt_attr_v->value[attr] =
   5221                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5222                 pkt_attr_v->final_offset =
   5223                     pkt_res_final_offset_v[sel].final_offset;
   5224             }
   5225             break;
   5226         }
   5227         /* ************************************************************** */
   5228         /* A single policer used for all traffic types with an additional */
   5229         /* policer for control traffic                                    */
   5230         /* 1) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|L2DLF_PKT|                    */
   5231         /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|             */
   5232         /*    UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|                            */
   5233         /*    UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|          */
   5234         /*    KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|           */
   5235         /*    UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                    */
   5236         /* 2) CONTROL_PKT|BPDU_PKT                                        */
   5237         /* ************************************************************** */
   5238         case bcmPolicerGroupModeSingleWithControl:
   5239         {
   5240             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5241             {
   5242                 /* 1) */
   5243                 {0, bcmPolicerGroupModeAttrPktTypeUnknown},
   5244                 {0, bcmPolicerGroupModeAttrPktTypeL2BC},
   5245                 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5246                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC},
   5247                 {0, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5248                 {0, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5249                 {0, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5250                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5251                 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5252                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5253                 {0, bcmPolicerGroupModeAttrPktTypeKnownMpls},
   5254                 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsL3},
   5255                 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsL2},
   5256                 {0, bcmPolicerGroupModeAttrPktTypeUnknownMpls},
   5257                 {0, bcmPolicerGroupModeAttrPktTypeKnownMim},
   5258                 {0, bcmPolicerGroupModeAttrPktTypeUnknownMim},
   5259                 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast},
   5260                 /* 2) CONTROL_PKT|BPDU_PKT */
   5261                 {1, bcmPolicerGroupModeAttrPktTypeControl},
   5262                 {1, bcmPolicerGroupModeAttrPktTypeBPDU}
   5263             };
   5264 
   5265             *npolicers = 2;
   5266             /* following is array size of pkt_res_final_offset_v */
   5267             pkt_attr_v_cnt = 17 + 2;
   5268 
   5269             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5270                 return BCM_E_RESOURCE;
   5271             }
   5272 
   5273             attr = bcmPolicerGroupModeAttrPktType;
   5274             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5275                 pkt_attr_v =
   5276                     &pkt_attr_selectors->pkt_attr_v[sel];
   5277                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5278                 pkt_attr_v->value_mask[attr] =
   5279                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5280                 pkt_attr_v->value[attr] =
   5281                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5282                 pkt_attr_v->final_offset =
   5283                     pkt_res_final_offset_v[sel].final_offset;
   5284             }
   5285             break;
   5286         }
   5287         /* ******************************************************** */
   5288         /* A dedicated policer per traffic type unicast, multicast, */
   5289         /* broadcast with an additional counter for control traffic */
   5290         /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT          */
   5291         /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|                      */
   5292         /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                     */
   5293         /* 3) L2BC_PKT|                                             */
   5294         /* 4) CONTROL_PKT|BPDU_PKT                                  */
   5295         /* ******************************************************** */
   5296         case bcmPolicerGroupModeTrafficTypeWithControl:
   5297         {
   5298             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5299             {
   5300                 /* 1) L2UC_PKT|KNOWN_L3UC_PKT|UNKNOWN_L3UC_PKT */
   5301                 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5302                 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5303                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5304                 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|
   5305                KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */
   5306                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5307                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5308                 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5309                 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5310                 /* 3) L2BC_PKT */
   5311                 {2, bcmPolicerGroupModeAttrPktTypeL2BC},
   5312                 /* 4) CONTROL_PKT|BPDU_PKT */
   5313                 {3, bcmPolicerGroupModeAttrPktTypeControl},
   5314                 {3, bcmPolicerGroupModeAttrPktTypeBPDU}
   5315             };
   5316 
   5317             *npolicers = 4;
   5318             /* following is array size of pkt_res_final_offset_v */
   5319             pkt_attr_v_cnt = 3 + 4 + 1 + 2;
   5320 
   5321             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5322                 return BCM_E_RESOURCE;
   5323             }
   5324 
   5325             attr = bcmPolicerGroupModeAttrPktType;
   5326             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5327                 pkt_attr_v =
   5328                     &pkt_attr_selectors->pkt_attr_v[sel];
   5329                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5330                 pkt_attr_v->value_mask[attr] =
   5331                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5332                 pkt_attr_v->value[attr] =
   5333                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5334                 pkt_attr_v->final_offset =
   5335                     pkt_res_final_offset_v[sel].final_offset;
   5336             }
   5337             break;
   5338         }
   5339         /* *************************************************************** */
   5340         /* A set of 3 policers where the base policer is used for control, */
   5341         /* the next one for dlf and the other counter is used for all      */
   5342         /* traffic types                                                   */
   5343         /* 1) CONTROL_PKT|BPDU_PKT                                         */
   5344         /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT)                                  */
   5345         /* 3) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|                               */
   5346         /*   UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|               */
   5347         /*   UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|                              */
   5348         /*   UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|            */
   5349         /*   KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|             */
   5350         /*   UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                      */
   5351         /* *************************************************************** */
   5352         case bcmPolicerGroupModeDlfAllWithControl:
   5353         {
   5354             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5355             {
   5356                 /* 1) CONTROL_PKT|BPDU_PKT */
   5357                 {0, bcmPolicerGroupModeAttrPktTypeControl},
   5358                 {0, bcmPolicerGroupModeAttrPktTypeBPDU},
   5359                 /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT) */
   5360                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2UC},
   5361                 /* 3) */
   5362                 {2, bcmPolicerGroupModeAttrPktTypeUnknown},
   5363                 {2, bcmPolicerGroupModeAttrPktTypeL2BC},
   5364                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5365                 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5366                 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5367                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5368                 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5369                 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5370                 {2, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5371                 {2, bcmPolicerGroupModeAttrPktTypeKnownMpls},
   5372                 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsL3},
   5373                 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsL2},
   5374                 {2, bcmPolicerGroupModeAttrPktTypeUnknownMpls},
   5375                 {2, bcmPolicerGroupModeAttrPktTypeKnownMim},
   5376                 {2, bcmPolicerGroupModeAttrPktTypeUnknownMim},
   5377                 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast}
   5378             };
   5379 
   5380             *npolicers = 3;
   5381             /* following is array size of pkt_res_final_offset_v */
   5382             pkt_attr_v_cnt = 2 + 1 + 16;
   5383 
   5384             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5385                 return BCM_E_RESOURCE;
   5386             }
   5387 
   5388             attr = bcmPolicerGroupModeAttrPktType;
   5389             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5390                 pkt_attr_v =
   5391                     &pkt_attr_selectors->pkt_attr_v[sel];
   5392                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5393                 pkt_attr_v->value_mask[attr] =
   5394                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5395                 pkt_attr_v->value[attr] =
   5396                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5397                 pkt_attr_v->final_offset =
   5398                     pkt_res_final_offset_v[sel].final_offset;
   5399             }
   5400             break;
   5401         }
   5402         /* **************************************************************** */
   5403         /* A dedicated policer for control, unknown unicast, known unicast, */
   5404         /* multicast, broadcast                                             */
   5405         /* 1) CONTROL_PKT|BPDU_PKT                                          */
   5406         /* 2) UNKNOWN_L3UC_PKT                                              */
   5407         /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                               */
   5408         /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|                              */
   5409         /*    KNOWN_IPMC_PKT| UNKNOWN_IPMC_PKT                              */
   5410         /* 5) L2BC_PKT                                                      */
   5411         /* **************************************************************** */
   5412         case bcmPolicerGroupModeTypedWithControl:
   5413         {
   5414             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5415             {
   5416                 /* 1) CONTROL_PKT|BPDU_PKT */
   5417                 {0, bcmPolicerGroupModeAttrPktTypeControl},
   5418                 {0, bcmPolicerGroupModeAttrPktTypeBPDU},
   5419                 /* 2) UNKNOWN_L3UC_PKT */
   5420                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5421                 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */
   5422                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5423                 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5424                 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|
   5425                             KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT */
   5426                 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5427                 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5428                 {3, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5429                 {3, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5430                 /* 5) L2BC_PKT */
   5431                 {4, bcmPolicerGroupModeAttrPktTypeL2BC}
   5432             };
   5433 
   5434             *npolicers = 5;
   5435             /* following is array size of pkt_res_final_offset_v */
   5436             pkt_attr_v_cnt = 2 + 1 + 2 + 4 + 1;
   5437 
   5438             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5439                 return BCM_E_RESOURCE;
   5440             }
   5441 
   5442             attr = bcmPolicerGroupModeAttrPktType;
   5443             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5444                 pkt_attr_v =
   5445                     &pkt_attr_selectors->pkt_attr_v[sel];
   5446                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5447                 pkt_attr_v->value_mask[attr] =
   5448                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5449                 pkt_attr_v->value[attr] =
   5450                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5451                 pkt_attr_v->final_offset =
   5452                     pkt_res_final_offset_v[sel].final_offset;
   5453             }
   5454             break;
   5455         }
   5456         /* ***************************************************************** */
   5457         /* A dedicated policer for control, unknown unicast, known unicast,  */
   5458         /* multicast, broadcast and one for all traffic (not already policed)*/
   5459         /* 1) CONTROL_PKT|BPDU_PKT                                           */
   5460         /* 2) UNKNOWN_L3UC_PKT                                               */
   5461         /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                                */
   5462         /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|                */
   5463         /*    UNKNOWN_IPMC_PKT                                               */
   5464         /* 5) L2BC_PKT                                                       */
   5465         /* 6) UNKNOWN_PKT|L2DLF_PKT|UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT          */
   5466         /*    KNOWN_MPLS_PKT | KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|          */
   5467         /*    UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|UNKNOWN_MIM_PKT|                */
   5468         /*    KNOWN_MPLS_MULTICAST_PKT                                       */
   5469         /* ***************************************************************** */
   5470         case bcmPolicerGroupModeTypedAllWithControl:
   5471         {
   5472             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5473             {
   5474                 /* 1) CONTROL_PKT|BPDU_PKT */
   5475                 {0, bcmPolicerGroupModeAttrPktTypeControl},
   5476                 {0, bcmPolicerGroupModeAttrPktTypeBPDU},
   5477                 /* 2) UNKNOWN_L3UC_PKT */
   5478                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5479                 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */
   5480                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5481                 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5482                 /* 4) */
   5483                 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5484                 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5485                 {3, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5486                 {3, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5487                 /* 5) L2BC_PKT */
   5488                 {4, bcmPolicerGroupModeAttrPktTypeL2BC},
   5489                 /* 6) */
   5490                 {5, bcmPolicerGroupModeAttrPktTypeUnknown},
   5491                 {5, bcmPolicerGroupModeAttrPktTypeUnknownL2UC},
   5492                 {5, bcmPolicerGroupModeAttrPktTypeUnknownIPMC},
   5493                 {5, bcmPolicerGroupModeAttrPktTypeKnownIPMC},
   5494                 {5, bcmPolicerGroupModeAttrPktTypeKnownMpls},
   5495                 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsL3},
   5496                 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsL2},
   5497                 {5, bcmPolicerGroupModeAttrPktTypeUnknownMpls},
   5498                 {5, bcmPolicerGroupModeAttrPktTypeKnownMim},
   5499                 {5, bcmPolicerGroupModeAttrPktTypeUnknownMim},
   5500                 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast}
   5501             };
   5502 
   5503             *npolicers = 6;
   5504             /* following is array size of pkt_res_final_offset_v */
   5505             pkt_attr_v_cnt = 2 + 1 + 2 + 4 + 1 + 11;
   5506 
   5507             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5508                 return BCM_E_RESOURCE;
   5509             }
   5510 
   5511             attr = bcmPolicerGroupModeAttrPktType;
   5512             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5513                 pkt_attr_v =
   5514                     &pkt_attr_selectors->pkt_attr_v[sel];
   5515                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5516                 pkt_attr_v->value_mask[attr] =
   5517                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5518                 pkt_attr_v->value[attr] =
   5519                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5520                 pkt_attr_v->final_offset =
   5521                     pkt_res_final_offset_v[sel].final_offset;
   5522             }
   5523             break;
   5524         }
   5525         /* ********************************************************* */
   5526         /* A set of 8(2^3) policers selected based on outer Vlan pri */
   5527         /* outer_dot1p; 3 bits 1..8                                  */
   5528         /* ********************************************************* */
   5529         case bcmPolicerGroupModeDot1P:
   5530         {
   5531             *npolicers = 8;
   5532             /* following is array size of pkt_res_final_offset_v */
   5533             pkt_attr_v_cnt = 8;
   5534 
   5535             /* customize defined count & final_offset */
   5536             if (mapping != NULL) {
   5537                 pkt_attr_v_cnt = count;
   5538                 *npolicers = pkt_attr_v_cnt;
   5539             }
   5540 
   5541             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5542                 return BCM_E_RESOURCE;
   5543             }
   5544 
   5545             attr = bcmPolicerGroupModeAttrOuterPri;
   5546             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5547                 pkt_attr_v =
   5548                     &pkt_attr_selectors->pkt_attr_v[sel];
   5549                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5550                 pkt_attr_v->value[attr] = sel;
   5551                 pkt_attr_v->value_mask[attr] =
   5552                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5553                 pkt_attr_v->final_offset = (mapping == NULL) ?
   5554                     sel : final_offset[sel];
   5555             }
   5556             break;
   5557         }
   5558         /* ********************************************************* */
   5559         /* A set of 8(2^3) policers selected based on inner Vlan pri */
   5560         /* inner_dot1p; 3 bits 1..8                                  */
   5561         /* ******************************************************** */
   5562         case bcmPolicerGroupModeInnerDot1P:
   5563         {
   5564             *npolicers = 8;
   5565             pkt_attr_v_cnt = 8;
   5566 
   5567             /* customize defined count & final_offset */
   5568             if (mapping != NULL) {
   5569                 pkt_attr_v_cnt = count;
   5570                 *npolicers = pkt_attr_v_cnt;
   5571             }
   5572 
   5573             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5574                 return BCM_E_RESOURCE;
   5575             }
   5576 
   5577             attr = bcmPolicerGroupModeAttrInnerPri;
   5578             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5579                 pkt_attr_v =
   5580                     &pkt_attr_selectors->pkt_attr_v[sel];
   5581                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5582                 pkt_attr_v->value[attr] = sel;
   5583                 pkt_attr_v->value_mask[attr] =
   5584                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5585                 pkt_attr_v->final_offset = (mapping == NULL) ?
   5586                     sel : final_offset[sel];
   5587             }
   5588             break;
   5589         }
   5590         /* **************************************************** */
   5591         /* A set of 16(2^4) policers based on internal priority */
   5592         /* 1..16 INT_PRI bits: 4bits                            */
   5593         /* **************************************************** */
   5594         case bcmPolicerGroupModeIntPri:
   5595         {
   5596             *npolicers = 16;
   5597             pkt_attr_v_cnt = 16;
   5598 
   5599             /* customize defined count & final_offset */
   5600             if (mapping != NULL) {
   5601                 pkt_attr_v_cnt = count;
   5602                 *npolicers = pkt_attr_v_cnt;
   5603             }
   5604 
   5605             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5606                 return BCM_E_RESOURCE;
   5607             }
   5608 
   5609             attr = bcmPolicerGroupModeAttrIntPri;
   5610             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5611                 pkt_attr_v =
   5612                     &pkt_attr_selectors->pkt_attr_v[sel];
   5613                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5614                 pkt_attr_v->value[attr] = sel;
   5615                 pkt_attr_v->value_mask[attr] =
   5616                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5617                 pkt_attr_v->final_offset = (mapping == NULL) ?
   5618                     sel : final_offset[sel];
   5619             }
   5620             break;
   5621         }
   5622         /* ********************************************************** */
   5623         /* set of 64 policers(2^(4+2)) based on Internal priority+CNG */
   5624         /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits                    */
   5625         /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits                    */
   5626         /* ********************************************************** */
   5627         case bcmPolicerGroupModeIntPriCng:
   5628         {
   5629             return BCM_E_UNAVAIL;
   5630             break;
   5631         }
   5632         /* ********************************************************** */
   5633         /* set of 8 policers(2^3) based on Internal priority          */
   5634         /* 1..8 INT_PRI bits: 3bits                                  */
   5635         /* ********************************************************** */
   5636         case bcmPolicerGroupModeShortIntPri:
   5637         {
   5638             *npolicers = 8;
   5639             pkt_attr_v_cnt = 8;
   5640 
   5641             /* customize defined count & final_offset */
   5642             if (mapping != NULL) {
   5643                 pkt_attr_v_cnt = count;
   5644                 *npolicers = pkt_attr_v_cnt;
   5645             }
   5646 
   5647             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5648                 return BCM_E_RESOURCE;
   5649             }
   5650 
   5651             attr = bcmPolicerGroupModeAttrIntPri;
   5652             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5653                 pkt_attr_v =
   5654                     &pkt_attr_selectors->pkt_attr_v[sel];
   5655                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5656                 pkt_attr_v->value[attr] = sel;
   5657                 pkt_attr_v->value_mask[attr] =
   5658                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5659                 pkt_attr_v->final_offset = (mapping == NULL) ?
   5660                     sel : final_offset[sel];
   5661             }
   5662             break;
   5663         }
   5664         /* ****************************************** */
   5665         /* A set of 2 policers(2^1) based on SVP type */
   5666         /* 1..2 (SVP 1 bit). In case of KT2, SVP is 3 */
   5667         /* 3 bits and hence no of policers is 8       */
   5668         /* ********************************************/
   5669         case bcmPolicerGroupModeSvpType:
   5670         {
   5671             return BCM_E_UNAVAIL;
   5672         }
   5673         /* ******************************************** */
   5674         /* A set of 64 policers(2^6) based on DSCP bits */
   5675         /* 1..64 (6 bits from TOS 8 bits)               */
   5676         /* ******************************************** */
   5677         case bcmPolicerGroupModeDscp:
   5678         {
   5679             return BCM_E_UNAVAIL;
   5680         }
   5681         /* ******************************************** */
   5682         /* A set of n policers based on user input      */
   5683         /* ******************************************** */
   5684         case bcmPolicerGroupModeCascade:
   5685         {
   5686             return BCM_E_UNAVAIL;
   5687            }
   5688         /* ******************************************************* */
   5689         /* A set of n policers based on user input based on IntPri */
   5690         /* ******************************************************* */
   5691         case bcmPolicerGroupModeIntPriCascade:
   5692         {
   5693             return BCM_E_UNAVAIL;
   5694         }
   5695         /* ************************************************************** */
   5696         /* A set of n policers based on user input, with dropped packets  */ 
   5697         /* not eligible for metering                                      */   
   5698         /* ************************************************************** */
   5699         case bcmPolicerGroupModeCascadeDroppedPktExclude:
   5700         {
   5701             return BCM_E_UNAVAIL;
   5702         }
   5703         /* ******************************************** */
   5704         /* A set of n policers based on user input      */
   5705         /* ******************************************** */
   5706         case bcmPolicerGroupModeCascadeWithCoupling:
   5707         {
   5708             return BCM_E_UNAVAIL;
   5709         }
   5710         /* ******************************************** */
   5711         /* A set of n policers based on user input      */
   5712         /* ******************************************** */
   5713         case bcmPolicerGroupModeIntPriCascadeWithCoupling:
   5714         {
   5715             return BCM_E_UNAVAIL;
   5716         }
   5717         /* *************************************************************** */
   5718         /* N+1 policers where in the base counter is used for dlf and next */
   5719         /* N are used as per Cos                                           */
   5720         /* 1) L2_DLF(UNKNOWN_L2UC_PKT)                                     */
   5721         /* 2..17) INT_PRI bits: 4bits                                      */
   5722         /* *************************************************************** */
   5723         case bcmPolicerGroupModeDlfIntPri:
   5724         {
   5725             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5726             {
   5727                 /* 1) L2_DLF(UNKNOWN_L2UC_PKT) */
   5728                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}
   5729             };
   5730 
   5731             *npolicers = 17;
   5732 
   5733             /* following is array size of pkt_res_final_offset_v */
   5734             pkt_attr_pkt_type_cnt = 1;
   5735             pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16;
   5736 
   5737             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5738                 return BCM_E_RESOURCE;
   5739             }
   5740 
   5741             attr = bcmPolicerGroupModeAttrPktType;
   5742             for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) {
   5743                 pkt_attr_v =
   5744                     &pkt_attr_selectors->pkt_attr_v[sel];
   5745                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5746                 pkt_attr_v->value_mask[attr] =
   5747                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5748                 pkt_attr_v->value[attr] =
   5749                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5750                 pkt_attr_v->final_offset =
   5751                     pkt_res_final_offset_v[sel].final_offset;
   5752 
   5753                 /* for following final_offset */
   5754                 if (base_final_offset < pkt_attr_v->final_offset) {
   5755                     base_final_offset = pkt_attr_v->final_offset;
   5756                 }
   5757             }
   5758             base_final_offset += 1;
   5759 
   5760             attr = bcmPolicerGroupModeAttrIntPri;
   5761             for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) {
   5762                 pkt_attr_v =
   5763                     &pkt_attr_selectors->pkt_attr_v[sel];
   5764                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5765                 pkt_attr_v->value[attr] =
   5766                     sel - pkt_attr_pkt_type_cnt;
   5767                 pkt_attr_v->value_mask[attr] =
   5768                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5769                 pkt_attr_v->final_offset =
   5770                     base_final_offset + sel - pkt_attr_pkt_type_cnt;
   5771             }
   5772             break;
   5773         }
   5774         /* ***************************************************************** */
   5775         /* A dedicated policer for unknown unicast, known unicast,           */
   5776         /* multicast, broadcast and N internal priority policers for traffic */
   5777         /* (not already policed)                                             */
   5778         /* 1) UNKNOWN_L3UC_PKT                                               */
   5779         /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                                */
   5780         /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                                */
   5781         /* 4) L2BC_PKT                                                       */
   5782         /* 5..20) INT_PRI bits: 4bits                                        */
   5783         /* ***************************************************************** */
   5784         case bcmPolicerGroupModeTypedIntPri:
   5785         {
   5786             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5787             {
   5788                 /* 1) UNKNOWN_L3UC_PKT */
   5789                 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5790                 /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */
   5791                 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5792                 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5793                 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */
   5794                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5795                 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5796                 /* 4) L2BC_PKT */
   5797                 {3, bcmPolicerGroupModeAttrPktTypeL2BC}
   5798             };
   5799 
   5800             *npolicers = 20;
   5801             /* following is array size of pkt_res_final_offset_v */
   5802             pkt_attr_pkt_type_cnt = 1 + 2 + 2 + 1;
   5803             pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16;
   5804 
   5805             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5806                 return BCM_E_RESOURCE;
   5807             }
   5808 
   5809             attr = bcmPolicerGroupModeAttrPktType;
   5810             for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) {
   5811                 pkt_attr_v =
   5812                     &pkt_attr_selectors->pkt_attr_v[sel];
   5813                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5814                 pkt_attr_v->value_mask[attr] =
   5815                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5816                 pkt_attr_v->value[attr] =
   5817                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5818                 pkt_attr_v->final_offset =
   5819                     pkt_res_final_offset_v[sel].final_offset;
   5820                 /* for following final_offset */
   5821                 if (base_final_offset < pkt_attr_v->final_offset) {
   5822                     base_final_offset = pkt_attr_v->final_offset;
   5823                 }
   5824             }
   5825             base_final_offset += 1;
   5826 
   5827             attr = bcmPolicerGroupModeAttrIntPri;
   5828             for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) {
   5829                 pkt_attr_v =
   5830                     &pkt_attr_selectors->pkt_attr_v[sel];
   5831                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5832                 pkt_attr_v->value[attr] =
   5833                     sel - pkt_attr_pkt_type_cnt;
   5834                 pkt_attr_v->value_mask[attr] =
   5835                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5836                 pkt_attr_v->final_offset =
   5837                     base_final_offset + sel - pkt_attr_pkt_type_cnt;
   5838             }
   5839             break;
   5840         }
   5841         /* ************************************************************* */
   5842         /* N+2 policers where the base policers is used for control, the */
   5843         /* next one for dlf and next N are used per Cos                  */
   5844         /* 1) CONTROL_PKT|BPDU_PKT                                       */
   5845         /* 2) L2_DLF(UNKNOWN_L2UC_PKT)                                   */
   5846         /* 3..18) INT_PRI bits: 4bits                                    */
   5847         /* ************************************************************* */
   5848         case bcmPolicerGroupModeDlfIntPriWithControl:
   5849         {
   5850             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5851             {
   5852                 /* 1) CONTROL_PKT|BPDU_PKT */
   5853                 {0, bcmPolicerGroupModeAttrPktTypeControl},
   5854                 {0, bcmPolicerGroupModeAttrPktTypeBPDU},
   5855                 /* 2) L2_DLF(UNKNOWN_L2UC_PKT) */
   5856                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}
   5857             };
   5858 
   5859             *npolicers = 18;
   5860             /* following is array size of pkt_res_final_offset_v */
   5861             pkt_attr_pkt_type_cnt = 2 + 1;
   5862             pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16;
   5863 
   5864             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5865                 return BCM_E_RESOURCE;
   5866             }
   5867 
   5868             attr = bcmPolicerGroupModeAttrPktType;
   5869             for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) {
   5870                 pkt_attr_v =
   5871                     &pkt_attr_selectors->pkt_attr_v[sel];
   5872                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5873                 pkt_attr_v->value_mask[attr] =
   5874                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5875                 pkt_attr_v->value[attr] =
   5876                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5877                 pkt_attr_v->final_offset =
   5878                     pkt_res_final_offset_v[sel].final_offset;
   5879                 /* for following final_offset */
   5880                 if (base_final_offset < pkt_attr_v->final_offset) {
   5881                     base_final_offset = pkt_attr_v->final_offset;
   5882                 }
   5883             }
   5884             base_final_offset += 1;
   5885 
   5886             /* 3..18) INT_PRI bits: 4bits */
   5887             attr = bcmPolicerGroupModeAttrIntPri;
   5888             for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) {
   5889                 pkt_attr_v =
   5890                     &pkt_attr_selectors->pkt_attr_v[sel];
   5891                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5892                 pkt_attr_v->value[attr] =
   5893                     sel - pkt_attr_pkt_type_cnt;
   5894                 pkt_attr_v->value_mask[attr] =
   5895                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5896                 pkt_attr_v->final_offset =
   5897                     base_final_offset + sel - pkt_attr_pkt_type_cnt;
   5898             }
   5899             break;
   5900         }
   5901         /* *************************************************************** */
   5902         /* A dedicated counter for control, unknown unicast, known unicast */
   5903         /* , multicast, broadcast and N internal priority counters for     */
   5904         /* traffic (not already counted)                                   */
   5905         /* 1) CONTROL_PKT|BPDU_PKT                                         */
   5906         /* 2) UNKNOWN_L3UC_PKT                                             */
   5907         /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                              */
   5908         /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                              */
   5909         /* 5) L2BC_PKT                                                     */
   5910         /* 6..21) INT_PRI bits: 4bits                                      */
   5911         /* *************************************************************** */
   5912         case bcmPolicerGroupModeTypedIntPriWithControl:
   5913         {
   5914             pkt_res_final_offset_t pkt_res_final_offset_v[] =
   5915             {
   5916                 /* 1) CONTROL_PKT|BPDU_PKT */
   5917                 {0, bcmPolicerGroupModeAttrPktTypeControl},
   5918                 {0, bcmPolicerGroupModeAttrPktTypeBPDU},
   5919                 /* 2) UNKNOWN_L3UC_PKT */
   5920                 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC},
   5921                 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */
   5922                 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC},
   5923                 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC},
   5924                 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */
   5925                 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC},
   5926                 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC},
   5927                 /* 5) L2BC_PKT */
   5928                 {4, bcmPolicerGroupModeAttrPktTypeL2BC}
   5929             };
   5930             *npolicers = 21;
   5931             /* following is array size of pkt_res_final_offset_v */
   5932             pkt_attr_pkt_type_cnt = 2 + 1 + 2 + 2 + 1;
   5933             pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16;
   5934 
   5935             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5936                 return BCM_E_RESOURCE;
   5937             }
   5938 
   5939             attr = bcmPolicerGroupModeAttrPktType;
   5940             for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) {
   5941                 pkt_attr_v =
   5942                     &pkt_attr_selectors->pkt_attr_v[sel];
   5943                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5944                 pkt_attr_v->value_mask[attr] =
   5945                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5946                 pkt_attr_v->value[attr] =
   5947                     pkt_res_final_offset_v[sel].attr_pkt_type;
   5948                 pkt_attr_v->final_offset =
   5949                     pkt_res_final_offset_v[sel].final_offset;
   5950                 /* for following final_offset */
   5951                 if (base_final_offset < pkt_attr_v->final_offset) {
   5952                     base_final_offset = pkt_attr_v->final_offset;
   5953                 }
   5954             }
   5955             base_final_offset += 1;
   5956 
   5957             /* 6..21) INT_PRI bits: 4bits */
   5958             attr = bcmPolicerGroupModeAttrIntPri;
   5959             for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) {
   5960                 pkt_attr_v =
   5961                     &pkt_attr_selectors->pkt_attr_v[sel];
   5962                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5963                 pkt_attr_v->value[attr] =
   5964                     sel - pkt_attr_pkt_type_cnt;
   5965                 pkt_attr_v->value_mask[attr] =
   5966                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5967                 pkt_attr_v->final_offset =
   5968                     base_final_offset + sel - pkt_attr_pkt_type_cnt;
   5969             }
   5970             break;
   5971         }
   5972         /* ************************************************** */
   5973         /* A dedicated counter for control, preemptable and   */
   5974         /* non-preemptable packet                             */
   5975         /* 1) none-preemptable PKT                            */
   5976         /* 2) preemptable PKT                                 */
   5977         /* ************************************************** */
   5978         case bcmPolicerGroupModePreemptable:
   5979         {
   5980             *npolicers = 2;
   5981             pkt_attr_v_cnt = 2;
   5982 
   5983             if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) {
   5984                 return BCM_E_RESOURCE;
   5985             }
   5986 
   5987             attr = bcmPolicerGroupModeAttrPreemptable;
   5988             for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   5989                 pkt_attr_v =
   5990                     &pkt_attr_selectors->pkt_attr_v[sel];
   5991                 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr];
   5992                 pkt_attr_v->value[attr] = sel;
   5993                 pkt_attr_v->value_mask[attr] =
   5994                     BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL;
   5995                 pkt_attr_v->final_offset = (mapping == NULL) ?
   5996                     sel : final_offset[sel];
   5997 
   5998             }
   5999             break;
   6000         }
   6001 
   6002         default:
   6003             LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6004                         (BSL_META_U(unit,
   6005                                     "Invalid policer group mode\n")));
   6006             return BCM_E_PARAM;
   6007 
   6008     }
   6009 
   6010     for (sel = 0; sel < pkt_attr_v_cnt; sel++) {
   6011         pkt_attr_v = &pkt_attr_selectors->pkt_attr_v[sel];
   6012 
   6013         (void)bcmi_policer_tcam_attr_dump(
   6014             unit, "pkt_attr_v", pkt_attr_v);
   6015 
   6016         /* Final Offset */
   6017         pol_offset = pkt_attr_v->final_offset;
   6018 
   6019         /* Record Maximum Policer Offset */
   6020         if (max_pol_offset < pol_offset) {
   6021             max_pol_offset = pol_offset;
   6022         }
   6023     }
   6024 
   6025     /* Check Maximum Policer Offset */
   6026     if (max_pol_offset >= *npolicers) {
   6027         LOG_ERROR(BSL_LS_BCM_POLICER,
   6028                   (BSL_META_U(unit,
   6029                               "Maximum policer offset(%d) should less than"
   6030                               " total policer number(%d).\n"),
   6031                               max_pol_offset,
   6032                               *npolicers));
   6033         return BCM_E_PARAM;
   6034     }
   6035 
   6036     pkt_attr_selectors->total_policers = *npolicers;
   6037     pkt_attr_selectors->pkt_attr_v_cnt = pkt_attr_v_cnt;
   6038 
   6039     POL_FUNCTION_TRACE(unit, "OUT");
   6040     return rv;
   6041 }
   6042 
   6043 /*
   6044  * Function:
   6045  *   bcmi_esw_policer_group_create
   6046  * Purpose:
   6047  *   Create a group of policers based on the mode.
   6048  * Parameters:
   6049  *   unit            - (IN) unit number
   6050  *   group_mode      - (IN) Policer group mode
   6051  *   flow_info       - (IN) Information regarding flow type and skip pool
   6052  *   offset_map      - (IN) Attr_value to policer_offset mapping
   6053  *   policer_id      - (OUT) Base policer id
   6054  *   npolicers       - (OUT) Number of policers
   6055  * Returns:
   6056  *   BCM_E_XXX
   6057  */
   6058 STATIC int
   6059 bcmi_esw_policer_group_create(
   6060     int unit,
   6061     bcm_policer_group_mode_t group_mode,
   6062     _bcm_policer_flow_info_t *flow_info,
   6063     bcm_policer_map_t *offset_map,
   6064     bcm_policer_t *policer_id,
   6065     int *npolicers)
   6066 {
   6067     bcm_error_t rv = BCM_E_UNAVAIL;
   6068     bcm_policer_svc_meter_mode_t offset_mode = 0;
   6069     uint32 mode_id = 0;
   6070     int policer_idx;
   6071     bcmi_policer_tcam_attr_selectors_t pkt_attr_selectors;
   6072     bcmi_global_meter_policer_control_t *policer_control = NULL;
   6073     bcm_policer_group_mode_type_t group_mode_type;
   6074 
   6075     POL_FUNCTION_TRACE(unit, "IN");
   6076 
   6077     /* Parameter NULL error handling */
   6078     POL_CHECK_NULL_PARAMETER(unit, flow_info);
   6079     POL_CHECK_NULL_PARAMETER(unit, policer_id);
   6080     POL_CHECK_NULL_PARAMETER(unit, npolicers);
   6081 
   6082     /* Initialization check */
   6083     CHECK_GLOBAL_METER_INIT(unit);
   6084     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6085 
   6086     (void)bcmi_policer_tcam_attr_selectors_t_init(&pkt_attr_selectors);
   6087     POL_MEM_ALLOC(
   6088         pkt_attr_selectors.pkt_attr_v,
   6089         sizeof(pkt_tcam_attr_bits_t) * BCMI_POLICER_SVC_METER_TCAM_SIZE,
   6090         "Global meter policer");
   6091 
   6092     if (NULL == pkt_attr_selectors.pkt_attr_v) {
   6093         LOG_ERROR(BSL_LS_BCM_POLICER,
   6094                   (BSL_META_U(unit,
   6095                               "Unable to allocate memory for "
   6096                               "pkt_attr_selectors.pkt_attr_v\n")));
   6097         return (BCM_E_MEMORY);
   6098     }
   6099 
   6100     /* Create temporary pkt information from group_mode */
   6101     rv = bcmi_esw_policer_group_set_mode_and_map(
   6102             unit, group_mode, offset_map, npolicers, &pkt_attr_selectors);
   6103 
   6104     if (BCM_FAILURE(rv)) {
   6105         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6106         LOG_ERROR(BSL_LS_BCM_POLICER,
   6107                   (BSL_META_U(unit,
   6108                               "Failed to set mode and map\n")));
   6109         return rv;
   6110     }
   6111 
   6112     GLOBAL_METER_LOCK(unit);
   6113 
   6114     if (group_mode == bcmPolicerGroupModeCascade) {
   6115         group_mode_type = bcmPolicerGroupModeTypeCascade;
   6116     } else if (group_mode == bcmPolicerGroupModeCascadeWithCoupling) {
   6117         group_mode_type = bcmPolicerGroupModeTypeCascadeWithCoupling;
   6118     } else {
   6119         group_mode_type = bcmPolicerGroupModeTypeNormal;
   6120     }
   6121 
   6122     if (*npolicers >= 1) {
   6123         rv = bcmi_esw_policer_svc_meter_create_mode(unit,
   6124                 &pkt_attr_selectors, group_mode, group_mode_type,
   6125                 *npolicers, &mode_id);
   6126         if (BCM_FAILURE(rv)) {
   6127             POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6128             GLOBAL_METER_UNLOCK(unit);
   6129             return rv;
   6130         }
   6131     }
   6132 
   6133     offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id);
   6134 
   6135     rv = bcmi_global_meter_policer_id_alloc(
   6136             unit, *npolicers, &policer_idx);
   6137 
   6138     if (BCM_FAILURE(rv)) {
   6139         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6140         GLOBAL_METER_UNLOCK(unit);
   6141         LOG_ERROR(BSL_LS_BCM_POLICER,
   6142                   (BSL_META_U(unit,
   6143                               "Failed to allocate policer\n")));
   6144         return rv;
   6145     }
   6146 
   6147     /* Allocate policer descriptor. */
   6148     rv = bcmi_global_meter_policer_control_alloc(
   6149             unit, *npolicers, &policer_control);
   6150     if (BCM_FAILURE(rv)) {
   6151         GLOBAL_METER_UNLOCK(unit);
   6152         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6153         bcmi_global_meter_free_allocated_policer_on_error(
   6154             unit, *npolicers, policer_idx);
   6155         LOG_ERROR(BSL_LS_BCM_POLICER,
   6156                   (BSL_META_U(unit,
   6157                               "Unable to allocate memory for "
   6158                               "policer control\n")));
   6159         return (rv);
   6160     }
   6161 
   6162     /* Add mode info to the policer index */
   6163     *policer_id = POLICER_IDX_TO_POLICER_ID(offset_mode, policer_idx);
   6164 
   6165     /* Set policer configuration */
   6166     policer_control->pid = *policer_id;
   6167     policer_control->no_of_policers =  *npolicers;
   6168     policer_control->grp_mode = group_mode;
   6169 
   6170     /* increment mode reference count for new policer */
   6171     rv = bcmi_policer_svc_meter_inc_mode_ref_cnt(unit, offset_mode);
   6172     if (BCM_FAILURE(rv)) {
   6173         POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6174         /* free all the allocated policers */
   6175         bcmi_global_meter_free_allocated_policer_on_error(
   6176             unit, *npolicers, policer_idx);
   6177         /* De-allocate policer descriptor. */
   6178         POL_MEM_FREE(policer_control->pol_cfg);
   6179         POL_MEM_FREE(policer_control);
   6180         GLOBAL_METER_UNLOCK(unit);
   6181         return rv;
   6182     }
   6183 
   6184     /* Insert policer into policers hash. */
   6185     _GLOBAL_METER_HASH_INSERT(BCMI_POLICER_BK_GET(unit),
   6186                               policer_control,
   6187                               (*policer_id & _GLOBAL_METER_HASH_MASK));
   6188     GLOBAL_METER_UNLOCK(unit);
   6189     POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v);
   6190 
   6191     POL_FUNCTION_DEBUG(unit, "policer_id 0x%x", *policer_id);
   6192     POL_FUNCTION_TRACE(unit, "OUT");
   6193     return BCM_E_NONE;
   6194 }
   6195 
   6196 #endif /* POLICER_ID_API_SECTION */
   6197 
   6198 #if ACTION_API_SECTION
   6199 /*
   6200  * Function:
   6201  *     bcmi_esw_policer_action_create
   6202  * Purpose:
   6203  *     Create a new action entry in meter action table
   6204  * Parameters:
   6205  *     unit                  - (IN) unit number
   6206  *     action_id             - (OUT) Action Id created
   6207  * Returns:
   6208  *     BCM_E_XXX
   6209  */
   6210 STATIC int
   6211 bcmi_esw_policer_action_create(
   6212     int unit,
   6213     uint32 *action_id)
   6214 {
   6215     int rv = BCM_E_NONE;
   6216 
   6217     /* Parameter NULL error handling */
   6218     POL_CHECK_NULL_PARAMETER(unit, action_id);
   6219 
   6220     CHECK_GLOBAL_METER_INIT(unit);
   6221     rv = shr_aidxres_list_alloc_block(
   6222             BCMI_ACTION_LIST_HANDLE_GET(unit), 1, (uint32 *)action_id);
   6223     if (BCM_FAILURE(rv)) {
   6224         LOG_ERROR(BSL_LS_BCM_POLICER,
   6225                   (BSL_META_U(unit,
   6226                               "Unable to allocate a handle for new "
   6227                               "action\n")));
   6228         return (rv);
   6229     }
   6230     BCMI_ACTION_ID_BK_GET(unit, *action_id).actions_count = 0;
   6231     BCMI_ACTION_ID_BK_GET(unit, *action_id).used = 1;
   6232 
   6233     POL_FUNCTION_DEBUG(unit, "action_id (%d) created", *action_id);
   6234     return rv;
   6235 }
   6236 
   6237 /* Validate the action para is in the valid value range or not */
   6238 STATIC int
   6239 bcmi_esw_policer_action_add_param_check(
   6240     int unit,
   6241     bcm_policer_action_t action,
   6242     uint32 param0)
   6243 {
   6244     switch (action) {
   6245         case bcmPolicerActionGpDrop:
   6246         case bcmPolicerActionYpDrop:
   6247         case bcmPolicerActionRpDrop:
   6248             if (param0 != 0) {
   6249                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6250                          (BSL_META_U(unit,
   6251                                      "Invalid value for Drop\n")));
   6252                 return BCM_E_PARAM;
   6253             }
   6254             break;
   6255         case bcmPolicerActionGpEcnNew:
   6256         case bcmPolicerActionYpEcnNew:
   6257         case bcmPolicerActionRpEcnNew:
   6258             if (param0 > 0x3) {
   6259                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6260                          (BSL_META_U(unit,
   6261                                      "Invalid value for ECN\n")));
   6262                 return BCM_E_PARAM;
   6263             }
   6264             break;
   6265         case bcmPolicerActionGpDscpNew:
   6266         case bcmPolicerActionYpDscpNew:
   6267         case bcmPolicerActionRpDscpNew:
   6268             if (param0 > 0x3f) {
   6269                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6270                          (BSL_META_U(unit,
   6271                                      "Invalid value for DSCP\n")));
   6272                 return BCM_E_PARAM;
   6273             }
   6274             break;
   6275         case bcmPolicerActionGpPrioIntNew:
   6276         case bcmPolicerActionYpPrioIntNew:
   6277         case bcmPolicerActionRpPrioIntNew:
   6278             if (param0 > 0xf) {
   6279                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6280                          (BSL_META_U(unit,
   6281                                      "Invalid value for int pri\n")));
   6282                 return BCM_E_PARAM;
   6283             }
   6284             break;
   6285         case bcmPolicerActionGpCngNew:
   6286         case bcmPolicerActionYpCngNew:
   6287         case bcmPolicerActionRpCngNew:
   6288             if (param0 > 0x3) {
   6289                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6290                          (BSL_META_U(unit,
   6291                                      "Invalid value for CNG\n")));
   6292                 return BCM_E_PARAM;
   6293             }
   6294             break;
   6295         case bcmPolicerActionGpVlanPrioNew:
   6296         case bcmPolicerActionYpVlanPrioNew:
   6297         case bcmPolicerActionRpVlanPrioNew:
   6298             if (param0 > 0x7) {
   6299                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6300                          (BSL_META_U(unit,
   6301                                      "Invalid value for vlan pri\n")));
   6302                 return BCM_E_PARAM;
   6303             }
   6304             break;
   6305         case bcmPolicerActionGpIntCongestionNotificationNew:
   6306         case bcmPolicerActionYpIntCongestionNotificationNew:
   6307         case bcmPolicerActionRpIntCongestionNotificationNew:
   6308             if (param0 > 0x3) {
   6309                 LOG_ERROR(BSL_LS_BCM_POLICER,
   6310                          (BSL_META_U(unit,
   6311                                      "Invalid value for "
   6312                                      "Congestion Notification\n")));
   6313                 return BCM_E_PARAM;
   6314             }
   6315             break;
   6316         default:
   6317             LOG_ERROR(BSL_LS_BCM_POLICER,
   6318                       (BSL_META_U(unit,
   6319                                   "Unsupported Action specified\n")));
   6320             return BCM_E_PARAM;
   6321     }
   6322     return BCM_E_NONE;
   6323 }
   6324 
   6325 /*
   6326  * Function:
   6327  *     bcmi_esw_policer_action_add
   6328  * Purpose:
   6329  *     Add an entry to meter action table
   6330  * Parameters:
   6331  *     unit                  - (IN) unit number
   6332  *     action_id             - (IN) Action Id created
   6333  *     action                - (IN) Action to be added
   6334  *     param0                - (IN) Parameter associated with action
   6335  * Returns:
   6336  *     BCM_E_XXX
   6337  */
   6338 STATIC int
   6339 bcmi_esw_policer_action_add(
   6340     int unit,
   6341     uint32 action_id,
   6342     bcm_policer_action_t action,
   6343     uint32 param0)
   6344 {
   6345     bcm_error_t rv = BCM_E_UNAVAIL;
   6346     uint32 idx = 0;
   6347     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   6348 
   6349     POL_FUNCTION_TRACE(unit, "IN");
   6350     POL_FUNCTION_DEBUG(unit, "action_id %d", action_id);
   6351     POL_FUNCTION_DEBUG(unit, "bcm_policer_action_t %d", action);
   6352     POL_FUNCTION_DEBUG(unit, "param0 %d", param0);
   6353 
   6354     if (action >= bcmPolicerActionCount) {
   6355         return BCM_E_PARAM;
   6356     }
   6357     BCM_IF_ERROR_RETURN(
   6358         bcmi_esw_policer_action_add_param_check(unit, action, param0));
   6359 
   6360     /* Initialization check */
   6361     CHECK_GLOBAL_METER_INIT(unit);
   6362     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6363     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   6364 
   6365     /* Check if the chip specific function existed */
   6366     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->action_supported);
   6367 
   6368     rv = gm_dev_info->action_supported(unit, action);
   6369     BCM_IF_ERROR_RETURN(rv);
   6370 
   6371     if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) {
   6372         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6373                   (BSL_META_U(unit,
   6374                               "Action id is not created \n")));
   6375         return BCM_E_PARAM;
   6376     }
   6377 
   6378     if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count != 0) {
   6379         LOG_ERROR(BSL_LS_BCM_POLICER,
   6380                   (BSL_META_U(unit,
   6381                               "Action Id specified still being used \n")));
   6382         return BCM_E_BUSY;
   6383     }
   6384 
   6385     GLOBAL_METER_LOCK(unit);
   6386 
   6387     /* Since there is no HW action table for GH2, we need to store actions */
   6388     idx = BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count;
   6389     BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx] = action;
   6390     BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx] = param0;
   6391     BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count++;
   6392 
   6393     GLOBAL_METER_UNLOCK(unit);
   6394     POL_FUNCTION_TRACE(unit, "OUT");
   6395     return BCM_E_NONE;
   6396 }
   6397 
   6398 /*
   6399  * Function:
   6400  *     bcmi_esw_policer_action_get
   6401  * Purpose:
   6402  *     get action parameter for a given action
   6403  * Parameters:
   6404  *     unit                  - (IN) unit number
   6405  *     action_id             - (IN) Action Id
   6406  *     action                - (IN) Action for which param is needed
   6407  *     param0                - (OUT) Parameter associated with action id
   6408  * Returns:
   6409  *     BCM_E_XXX
   6410  */
   6411 STATIC int
   6412 bcmi_esw_policer_action_get(
   6413     int unit,
   6414     uint32 action_id,
   6415     bcm_policer_action_t action,
   6416     uint32 *param0)
   6417 {
   6418     bcm_error_t rv = BCM_E_UNAVAIL;
   6419     uint32 idx = 0;
   6420     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   6421     bcm_policer_action_t bk_action;
   6422     uint32 bk_param0;
   6423 
   6424     POL_FUNCTION_TRACE(unit, "IN");
   6425 
   6426     if (action >= bcmPolicerActionCount) {
   6427         return BCM_E_PARAM;
   6428     }
   6429 
   6430     /* Parameter NULL error handling */
   6431     POL_CHECK_NULL_PARAMETER(unit, param0);
   6432 
   6433     /* Initialization check */
   6434     CHECK_GLOBAL_METER_INIT(unit);
   6435     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6436     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   6437 
   6438     if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) {
   6439         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6440                   (BSL_META_U(unit,
   6441                               "Action id is not created \n")));
   6442         return BCM_E_PARAM;
   6443     }
   6444 
   6445     /* Check if the chip specific function existed */
   6446     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->action_supported);
   6447 
   6448     rv = gm_dev_info->action_supported(unit, action);
   6449     BCM_IF_ERROR_RETURN(rv);
   6450 
   6451     for (idx = 0;
   6452          idx < BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count;
   6453          idx++) {
   6454         bk_action = BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx];
   6455         bk_param0 = BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx];
   6456         if (action == bk_action) {
   6457             *param0 = bk_param0;
   6458             return BCM_E_NONE;
   6459         }
   6460     }
   6461     *param0 = 0;
   6462 
   6463     POL_FUNCTION_TRACE(unit, "OUT");
   6464     return BCM_E_NOT_FOUND;
   6465 }
   6466 
   6467 /*
   6468  * Function:
   6469  *     bcmi_esw_policer_action_destroy
   6470  * Purpose:
   6471  *     Delete an entry from meter action table
   6472  * Parameters:
   6473  *     unit                  - (IN) unit number
   6474  *     action_id             - (IN) Action Id to be destroyed
   6475  * Returns:
   6476  *     BCM_E_XXX
   6477  */
   6478 STATIC int
   6479 bcmi_esw_policer_action_destroy(
   6480     int unit,
   6481     uint32 action_id)
   6482 {
   6483     bcm_error_t rv = BCM_E_UNAVAIL;
   6484 
   6485     POL_FUNCTION_TRACE(unit, "IN");
   6486     POL_FUNCTION_DEBUG(unit, "action_id %d", action_id);
   6487 
   6488     /* Initialization check */
   6489     CHECK_GLOBAL_METER_INIT(unit);
   6490     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6491 
   6492     if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) {
   6493         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6494                   (BSL_META_U(unit,
   6495                               "Action Id(%d) specified doesn't exist\n"),
   6496                               action_id));
   6497         return BCM_E_PARAM;
   6498     }
   6499     if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count != 0) {
   6500         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6501                   (BSL_META_U(unit,
   6502                               "Action Id(%d) specified still being used \n"),
   6503                               action_id));
   6504         return BCM_E_BUSY;
   6505     }
   6506     GLOBAL_METER_LOCK(unit);
   6507 
   6508     rv = shr_aidxres_list_free(
   6509             BCMI_ACTION_LIST_HANDLE_GET(unit), action_id);
   6510     if (BCM_FAILURE(rv)) {
   6511         GLOBAL_METER_UNLOCK(unit);
   6512         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6513                     (BSL_META_U(unit,
   6514                                 "Unable to free action handle\n")));
   6515         return (rv);
   6516     }
   6517     BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count = 0;
   6518     BCMI_ACTION_ID_BK_GET(unit, action_id).used = 0;
   6519     GLOBAL_METER_UNLOCK(unit);
   6520 
   6521     POL_FUNCTION_TRACE(unit, "OUT");
   6522     return BCM_E_NONE;
   6523 }
   6524 
   6525 /*
   6526  * Function:
   6527  *     bcmi_esw_policer_action_attach_get
   6528  * Purpose:
   6529  *     Get the action id associated with a given policer.
   6530  * Parameters:
   6531  *     unit                  - (IN) unit number
   6532  *     policer_id            - (IN) Base policer Id
   6533  *     action_id             - (OUT) action id
   6534  * Returns:
   6535  *     BCM_E_XXX
   6536  */
   6537 STATIC int
   6538 bcmi_esw_policer_action_attach_get(
   6539     int unit,
   6540     bcm_policer_t policer_id,
   6541     uint32 *action_id)
   6542 {
   6543     bcm_error_t rv = BCM_E_UNAVAIL;
   6544     bcmi_global_meter_policer_control_t *policer_control = NULL;
   6545     uint32 pol_cfg_idx;
   6546 
   6547     POL_FUNCTION_TRACE(unit, "IN");
   6548 
   6549     /* Parameter NULL error handling */
   6550     POL_CHECK_NULL_PARAMETER(unit, action_id);
   6551 
   6552     /* Initialization check */
   6553     CHECK_GLOBAL_METER_INIT(unit);
   6554     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6555 
   6556     /* validate policer id */
   6557     BCM_IF_ERROR_RETURN(
   6558         bcmi_esw_policer_validate(unit, policer_id));
   6559 
   6560     GLOBAL_METER_BK_LOCK(unit);
   6561     rv = bcmi_esw_global_meter_base_policer_get(
   6562             unit, policer_id, &policer_control);
   6563     if (BCM_FAILURE(rv)) {
   6564         GLOBAL_METER_BK_UNLOCK(unit);
   6565         LOG_ERROR(BSL_LS_BCM_POLICER,
   6566                   (BSL_META_U(unit,
   6567                               "Unable to get policer control for "
   6568                               "policer id 0x%x(%d)\n"),
   6569                               policer_id,
   6570                               policer_id));
   6571         return (rv);
   6572     }
   6573     pol_cfg_idx = policer_id - policer_control->pid;
   6574 
   6575     /* get action id */
   6576     *action_id = policer_control->pol_cfg[pol_cfg_idx].action_id;
   6577 
   6578     GLOBAL_METER_BK_UNLOCK(unit);
   6579     POL_FUNCTION_DEBUG(unit, "action_id (%d)", *action_id);
   6580 
   6581     POL_FUNCTION_TRACE(unit, "OUT");
   6582     return BCM_E_NONE;
   6583 }
   6584 
   6585 /*
   6586  * Function:
   6587  *     bcmi_esw_policer_action_detach
   6588  * Purpose:
   6589  *     Disassociate a policer action from a given policer id and
   6590  *     readjust reference count.
   6591  * Parameters:
   6592  *     unit                  - (IN) unit number
   6593  *     policer_id            - (IN) Base policer Id
   6594  *     action_id             - (IN) action id
   6595  * Returns:
   6596  *     BCM_E_XXX
   6597  */
   6598 STATIC int
   6599 bcmi_esw_policer_action_detach(
   6600     int unit,
   6601     bcm_policer_t policer_id,
   6602     uint32 action_id)
   6603 {
   6604     bcm_error_t rv = BCM_E_UNAVAIL;
   6605     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   6606     bcmi_global_meter_policer_control_t *policer_control = NULL;
   6607     int policer_index = 0;
   6608     uint32 pol_cfg_idx;
   6609     uint64 reset = COMPILER_64_INIT(0, 0);
   6610 
   6611     POL_FUNCTION_TRACE(unit, "IN");
   6612 
   6613     LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6614                 (BSL_META_U(unit,
   6615                             "Detach action_id (0x%x) on policer_id (0x%x)"),
   6616                             action_id, policer_id));
   6617 
   6618     /* Initialization check */
   6619     CHECK_GLOBAL_METER_INIT(unit);
   6620     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6621     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   6622 
   6623     if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) {
   6624         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6625                   (BSL_META_U(unit,
   6626                               "Action id is not created \n")));
   6627         return BCM_E_PARAM;
   6628     }
   6629 
   6630     /* validate policer id */
   6631     rv = bcmi_esw_policer_validate(unit, policer_id);
   6632     if (BCM_FAILURE(rv)) {
   6633         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6634                   (BSL_META_U(unit,
   6635                               "Invalid Policer Id \n")));
   6636         return (rv);
   6637     }
   6638 
   6639     GLOBAL_METER_LOCK(unit);
   6640     rv = bcmi_esw_global_meter_base_policer_get(
   6641             unit, policer_id, &policer_control);
   6642     if (BCM_FAILURE(rv)) {
   6643         GLOBAL_METER_UNLOCK(unit);
   6644         LOG_ERROR(BSL_LS_BCM_POLICER,
   6645                   (BSL_META_U(unit,
   6646                               "Unable to get policer control for "
   6647                               "policer id 0x%x(%d)\n"),
   6648                               policer_id,
   6649                               policer_id));
   6650         return (rv);
   6651     }
   6652     /* read meter table and remove action_id */
   6653     BCM_IF_ERROR_RETURN(
   6654         bcmi_esw_policer_table_index_get(unit, policer_id, &policer_index));
   6655 
   6656     /* Check if the chip specific function existed */
   6657     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_set);
   6658 
   6659     /* write action table entry */
   6660     rv = gm_dev_info->policy_action_set(unit,
   6661                                         policer_index,
   6662                                         reset,
   6663                                         reset,
   6664                                         reset);
   6665     if (BCM_FAILURE(rv)) {
   6666         GLOBAL_METER_UNLOCK(unit);
   6667         return rv;
   6668     }
   6669 
   6670     /* decrement action usage reference count */
   6671     if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count > 0) {
   6672         BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count--;
   6673     }
   6674 
   6675     pol_cfg_idx = policer_id - policer_control->pid;
   6676 
   6677     /* reset action id in policer control */
   6678     policer_control->pol_cfg[pol_cfg_idx].action_id =
   6679         BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID;
   6680     GLOBAL_METER_UNLOCK(unit);
   6681 
   6682     POL_FUNCTION_TRACE(unit, "OUT");
   6683     return BCM_E_NONE;
   6684 }
   6685 
   6686 /*
   6687  * Function:
   6688  *     bcmi_esw_policer_action_attach
   6689  * Purpose:
   6690  *     Associate a policer action with a given policer id and
   6691  *     increment action usage reference count.
   6692  * Parameters:
   6693  *     unit                  - (IN) unit number
   6694  *     policer_id            - (IN) Base policer Id
   6695  *     action_id             - (IN) action id
   6696  * Returns:
   6697  *     BCM_E_XXX
   6698  */
   6699 STATIC int
   6700 bcmi_esw_policer_action_attach(
   6701     int unit,
   6702     bcm_policer_t policer_id,
   6703     uint32 action_id)
   6704 {
   6705     bcm_error_t rv = BCM_E_UNAVAIL;
   6706     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   6707     bcmi_global_meter_policer_control_t *policer_control = NULL;
   6708     int policer_index = 0;
   6709     uint64 green_action = COMPILER_64_INIT(0, 0);
   6710     uint64 yellow_action = COMPILER_64_INIT(0, 0);
   6711     uint64 red_action = COMPILER_64_INIT(0, 0);
   6712     uint32 idx = 0, pol_cfg_idx;
   6713     bcm_policer_action_t action;
   6714     uint32 param0;
   6715 
   6716     POL_FUNCTION_TRACE(unit, "IN");
   6717     LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6718                 (BSL_META_U(unit,
   6719                             "Attach action_id(0x%x) to policer_id (0x%x)\n"),
   6720                             action_id, policer_id));
   6721 
   6722     if (action_id == BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID) {
   6723         return BCM_E_PARAM;
   6724     }
   6725 
   6726     /* Initialization check */
   6727     CHECK_GLOBAL_METER_INIT(unit);
   6728     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   6729     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   6730 
   6731     /* check if action id is allocated */
   6732     if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) {
   6733         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6734                   (BSL_META_U(unit,
   6735                               "Action Id is not created \n")));
   6736         return BCM_E_PARAM;
   6737     }
   6738 
   6739     /* Check if the chip specific function existed */
   6740     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_set);
   6741     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_get);
   6742     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_param_configure);
   6743 
   6744     /* validate policer id */
   6745     rv = bcmi_esw_policer_validate(unit, policer_id);
   6746     if (BCM_FAILURE(rv)) {
   6747         LOG_DEBUG(BSL_LS_BCM_POLICER,
   6748                   (BSL_META_U(unit,
   6749                               "Invalid Policer Id \n")));
   6750         return (rv);
   6751     }
   6752 
   6753     GLOBAL_METER_LOCK(unit);
   6754     rv = bcmi_esw_global_meter_base_policer_get(
   6755             unit, policer_id, &policer_control);
   6756     if (BCM_FAILURE(rv)) {
   6757         GLOBAL_METER_UNLOCK(unit);
   6758         LOG_ERROR(BSL_LS_BCM_POLICER,
   6759                   (BSL_META_U(unit,
   6760                               "Unable to get policer control for "
   6761                               "policer id 0x%d(%x)\n"),
   6762                               policer_id,
   6763                               policer_id));
   6764         return (rv);
   6765     }
   6766     pol_cfg_idx = policer_id - policer_control->pid;
   6767 
   6768     if (policer_control->pol_cfg[pol_cfg_idx].action_id == action_id) {
   6769         GLOBAL_METER_UNLOCK(unit);
   6770         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6771                     (BSL_META_U(unit,
   6772                                 "Action Id %d(%x) passed is the same as the "
   6773                                 "one in policer control\n"),
   6774                                 action_id, action_id));
   6775         return (BCM_E_NONE);
   6776     }
   6777 
   6778     /* set action to policy table */
   6779     BCM_IF_ERROR_RETURN(
   6780         bcmi_esw_policer_table_index_get(unit, policer_id, &policer_index));
   6781 
   6782     /* read action table entry */
   6783     rv = gm_dev_info->policy_action_get(
   6784             unit, policer_index,
   6785             &green_action, &yellow_action, &red_action);
   6786     if (BCM_FAILURE(rv)) {
   6787         GLOBAL_METER_UNLOCK(unit);
   6788         LOG_ERROR(BSL_LS_BCM_POLICER,
   6789                   (BSL_META_U(unit,
   6790                               "HW Operation failed(rv = %d)\n"),
   6791                               rv));
   6792         return rv;
   6793     }
   6794 
   6795     /* read from bk and set action to policy table */
   6796     for (idx = 0;
   6797          idx < BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count;
   6798          idx++) {
   6799         action = BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx];
   6800         param0 = BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx];
   6801 
   6802 
   6803         rv = gm_dev_info->policy_action_param_configure(
   6804                 unit, action, param0,
   6805                 &green_action, &yellow_action, &red_action);
   6806 
   6807         if (BCM_FAILURE(rv)) {
   6808             GLOBAL_METER_UNLOCK(unit);
   6809             LOG_ERROR(BSL_LS_BCM_POLICER,
   6810                       (BSL_META_U(unit,
   6811                                   "HW Operation failed(rv = %d)\n"),
   6812                                   rv));
   6813             return rv;
   6814         }
   6815     }
   6816 
   6817     /* write action table entry */
   6818     rv = gm_dev_info->policy_action_set(
   6819             unit, policer_index,
   6820             green_action, yellow_action, red_action);
   6821 
   6822     if (BCM_FAILURE(rv)) {
   6823         GLOBAL_METER_UNLOCK(unit);
   6824         LOG_ERROR(BSL_LS_BCM_POLICER,
   6825                   (BSL_META_U(unit,
   6826                               "HW Operation failed(rv = %d)\n"),
   6827                               rv));
   6828         return rv;
   6829     }
   6830 
   6831     /* increment action usage reference count */
   6832     BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count++;
   6833     policer_control->pol_cfg[pol_cfg_idx].action_id = action_id;
   6834     GLOBAL_METER_UNLOCK(unit);
   6835 
   6836     POL_FUNCTION_TRACE(unit, "OUT");
   6837     return BCM_E_NONE;
   6838 }
   6839 /* end Action API's */
   6840 #endif /* ACTION_API_SECTION */
   6841 
   6842 #ifdef BCM_WARM_BOOT_SUPPORT
   6843 
   6844 STATIC int
   6845 bcmi_esw_global_meter_policer_scache_alloc(int unit)
   6846 {
   6847     soc_scache_handle_t scache_handle;
   6848     uint8 *policer_scache = NULL;
   6849     int size = 0;
   6850     int rv;
   6851 
   6852     POL_FUNCTION_TRACE(unit, "IN");
   6853 
   6854     /* 1. tcam usage bitmap */
   6855     size += SHR_BITALLOCSIZE(BCMI_POLICER_SVC_METER_TCAM_SIZE);
   6856 
   6857     /* 2. offset_mode usage bitmap */
   6858     size += SHR_BITALLOCSIZE(BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE);
   6859 
   6860     /* 3. bcmi_policer_global_meter_action_bk_t */
   6861     size += sizeof(bcmi_policer_global_meter_action_bk_t) *
   6862             BCMI_POLICER_SVC_METER_ACTION_SIZE;
   6863 
   6864     /* 4. bcmi_policer_svm_offset_mode_bk_t */
   6865     size += sizeof(bcmi_policer_svm_offset_mode_bk_t) *
   6866             BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   6867 
   6868     /* 4.1 bcm_policer_group_mode_attr_selector_t */
   6869     size += sizeof(bcm_policer_group_mode_attr_selector_t) *
   6870             BCMI_POLICER_SVC_METER_TCAM_SIZE;
   6871 
   6872     /* 4.2 pkt_tcam_attr_bits_t */
   6873     size += sizeof(pkt_tcam_attr_bits_t) *
   6874             BCMI_POLICER_SVC_METER_TCAM_SIZE;
   6875 
   6876     /* 5.1 bcmi_global_meter_policer_control_t */
   6877     size += sizeof(bcmi_global_meter_policer_control_t) *
   6878             BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES;
   6879 
   6880     /* 5.2 bcmi_global_meter_policer_control_t->pol_cfg[no_of_policers] */
   6881     size += sizeof(bcm_policer_config_wb_t) *
   6882             BCMI_POLICER_SVC_METER_POOL_SIZE;
   6883 
   6884     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
   6885 
   6886     rv = _bcm_esw_scache_ptr_get(
   6887             unit, scache_handle, TRUE, size,
   6888             &policer_scache, BCM_WB_DEFAULT_VERSION, NULL);
   6889 
   6890     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   6891         return rv;
   6892     }
   6893     POL_FUNCTION_TRACE(unit, "OUT");
   6894     return BCM_E_NONE;
   6895 }
   6896 
   6897 /*
   6898  * Function:
   6899  *     bcmi_esw_global_meter_policer_sync
   6900  * Purpose:
   6901  *     Write policers which are created but not yet used in any
   6902  *     table to scache so that we can recover the configuration
   6903  *     on warm boot
   6904  * Parameters:
   6905  *     unit                  - (IN) unit number
   6906  * Returns:
   6907  *     BCM_E_XXX
   6908  */
   6909 STATIC int
   6910 bcmi_esw_global_meter_policer_sync(int unit)
   6911 {
   6912     int rv = BCM_E_NONE;
   6913     soc_scache_handle_t scache_handle;
   6914     bcmi_global_meter_policer_control_t *policer_control = NULL;
   6915     uint32 hash_index;      /* Entry hash  */
   6916     uint8 *policer_scache = NULL;
   6917     int offset_mode;
   6918     int count = 0;
   6919     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   6920     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   6921     uint32 bmp_size, table_size;
   6922     int i;
   6923     uint8 is_custom_group;
   6924     uint32 ref_cnt = 0;
   6925     uint32 used = 0;
   6926     bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeCount;
   6927     bcm_policer_group_mode_type_t group_mode_type =
   6928         bcmPolicerGroupModeTypeCount;
   6929     uint32 no_of_policers = 0;
   6930     uint32 no_of_attr_selectors = 0;
   6931     uint32 pkt_attr_v_cnt = 0;
   6932     bcm_policer_config_wb_t wb_pol_cfg;
   6933 
   6934     POL_FUNCTION_TRACE(unit, "IN");
   6935 
   6936     CHECK_GLOBAL_METER_INIT(unit);
   6937 
   6938     BCM_IF_ERROR_RETURN(
   6939         bcmi_esw_global_meter_policer_scache_alloc(unit));
   6940 
   6941     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
   6942 
   6943     BCM_IF_ERROR_RETURN(
   6944         _bcm_esw_scache_ptr_get(
   6945             unit, scache_handle, FALSE, 0,
   6946             &policer_scache, BCM_WB_DEFAULT_VERSION, NULL));
   6947 
   6948     if (NULL == policer_scache) {
   6949         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   6950                     (BSL_META_U(unit,
   6951                                 "SCACHE Memory not available \n")));
   6952         return BCM_E_MEMORY;
   6953     }
   6954 
   6955     bk_svm_info = BCMI_SVM_BK_GET(unit);
   6956 
   6957     /* 1. Copy tcam usage bitmap */
   6958     bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE;
   6959     sal_memcpy(policer_scache, bk_svm_info->tcam_intf_bitmap,
   6960                SHR_BITALLOCSIZE(bmp_size));
   6961     policer_scache += SHR_BITALLOCSIZE(bmp_size);
   6962 
   6963     /* 2. Copy offset_mode usage bitmap */
   6964     bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   6965     sal_memcpy(policer_scache, bk_svm_info->offset_mode_intf_bitmap,
   6966                SHR_BITALLOCSIZE(bmp_size));
   6967     policer_scache += SHR_BITALLOCSIZE(bmp_size);
   6968 
   6969     /* 3. Copy actions bk */
   6970     table_size =
   6971         sizeof(bcmi_policer_global_meter_action_bk_t) *
   6972         BCMI_POLICER_SVC_METER_ACTION_SIZE;
   6973     sal_memcpy(policer_scache, BCMI_ACTION_BK_GET(unit),
   6974                table_size);
   6975     policer_scache += table_size;
   6976 
   6977     /* 4. bcmi_policer_svm_offset_mode_bk_t */
   6978     for (offset_mode = 0;
   6979          offset_mode < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   6980          offset_mode++) {
   6981         if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode)) {
   6982             bk_svm_mode_info =
   6983                 BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   6984 
   6985             is_custom_group = bk_svm_mode_info->is_custom_group;
   6986             ref_cnt = bk_svm_mode_info->ref_cnt;
   6987             used = bk_svm_mode_info->used;
   6988             no_of_policers = bk_svm_mode_info->no_of_policers;
   6989             no_of_attr_selectors = bk_svm_mode_info->no_of_attr_selectors;
   6990             group_mode = bk_svm_mode_info->group_mode;
   6991             group_mode_type = bk_svm_mode_info->group_mode_type;
   6992             pkt_attr_v_cnt = bk_svm_mode_info->pkt_attr_v_cnt;
   6993 
   6994             sal_memcpy(policer_scache, &is_custom_group,
   6995                 sizeof(uint8));
   6996             policer_scache += sizeof(uint8);
   6997 
   6998             sal_memcpy(policer_scache, &ref_cnt,
   6999                 sizeof(uint32));
   7000             policer_scache += sizeof(uint32);
   7001 
   7002             sal_memcpy(policer_scache, &used,
   7003                 sizeof(uint32));
   7004             policer_scache += sizeof(uint32);
   7005 
   7006             sal_memcpy(policer_scache, &no_of_policers,
   7007                 sizeof(uint32));
   7008             policer_scache += sizeof(uint32);
   7009 
   7010             sal_memcpy(policer_scache, &no_of_attr_selectors,
   7011                 sizeof(uint32));
   7012             policer_scache += sizeof(uint32);
   7013 
   7014             sal_memcpy(policer_scache, &pkt_attr_v_cnt,
   7015                 sizeof(uint32));
   7016             policer_scache += sizeof(uint32);
   7017 
   7018             sal_memcpy(policer_scache, &group_mode,
   7019                 sizeof(bcm_policer_group_mode_t));
   7020             policer_scache +=
   7021                 sizeof(bcm_policer_group_mode_t);
   7022 
   7023             sal_memcpy(policer_scache, &group_mode_type,
   7024                 sizeof(bcm_policer_group_mode_type_t));
   7025             policer_scache +=
   7026                 sizeof(bcm_policer_group_mode_type_t);
   7027 
   7028             /* 4.1 Save attr_selectors info */
   7029             for (i = 0; i < no_of_attr_selectors; i++) {
   7030                 sal_memcpy(policer_scache,
   7031                            &bk_svm_mode_info->attr_selectors[i],
   7032                            sizeof(bcm_policer_group_mode_attr_selector_t));
   7033                 policer_scache += sizeof(bcm_policer_group_mode_attr_selector_t);
   7034             }
   7035 
   7036             /* 4.2 Save pkt_attr_v info */
   7037             for (i = 0; i < pkt_attr_v_cnt; i++) {
   7038                 sal_memcpy(policer_scache,
   7039                            &bk_svm_mode_info->pkt_attr_v[i],
   7040                            sizeof(pkt_tcam_attr_bits_t));
   7041                 policer_scache += sizeof(pkt_tcam_attr_bits_t);
   7042             }
   7043         }
   7044     }
   7045 
   7046     /* 5. go through policer control bookkeep structure and get policer
   7047        entries */
   7048     for (hash_index = 0; hash_index < BCMI_GLOBAL_METER_HASH_SIZE; hash_index++) {
   7049         policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index);
   7050         while ((NULL != policer_control) &&
   7051                (count < BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES)) {
   7052             /* 5.1 Save policer_control */
   7053             sal_memcpy(policer_scache, policer_control,
   7054                 sizeof(bcmi_global_meter_policer_control_t));
   7055             policer_scache += sizeof(bcmi_global_meter_policer_control_t);
   7056 
   7057             /* 5.2 Save policer_control->pol_cfg[no_of_policers] */
   7058             no_of_policers = policer_control->no_of_policers;
   7059             for (i = 0; i < no_of_policers; i++) {
   7060                 policer_config_copy_to_wb_policer_config(
   7061                     &(policer_control->pol_cfg[i]),
   7062                     &wb_pol_cfg);
   7063                 sal_memcpy(policer_scache, &wb_pol_cfg,
   7064                     sizeof(bcm_policer_config_wb_t));
   7065                 policer_scache +=
   7066                     sizeof(bcm_policer_config_wb_t);
   7067             }
   7068             count++;
   7069             policer_control = policer_control->next;
   7070         }
   7071         if (count == BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES) {
   7072             return rv;
   7073         }
   7074     }
   7075     POL_FUNCTION_TRACE(unit, "OUT");
   7076     return rv;
   7077 }
   7078 
   7079 /*
   7080  * Function:
   7081  *     bcmi_esw_global_meter_policer_recover_from_scache
   7082  * Purpose:
   7083  *     Recover policers which are not configured in HW from
   7084  *     Scache as part of warm boot
   7085  * Parameters:
   7086  *     unit                  - (IN) unit number
   7087  *     policer_scache        - (IN) scache memory pointer
   7088  * Returns:
   7089  *     BCM_E_XXX
   7090  */
   7091 STATIC int
   7092 bcmi_esw_global_meter_policer_recover_from_scache(
   7093     int unit,
   7094     uint8 *policer_scache)
   7095 {
   7096     int rv = BCM_E_NONE;
   7097     int offset_mode;
   7098     int count_index = 0;
   7099     bcmi_global_meter_policer_control_t *policer_control = NULL;
   7100     bcm_policer_t policer_id;
   7101     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   7102     bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL;
   7103     int bmp_size, table_size;
   7104     int i;
   7105     uint8 is_custom_group;
   7106     uint32 ref_cnt = 0;
   7107     uint32 used = 0;
   7108     bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeCount;
   7109     bcm_policer_group_mode_type_t group_mode_type =
   7110         bcmPolicerGroupModeTypeCount;
   7111     uint32 no_of_policers = 0;
   7112     uint32 no_of_attr_selectors = 0;
   7113     uint32 pkt_attr_v_cnt = 0;
   7114     bcm_policer_config_wb_t wb_pol_cfg;
   7115 
   7116     POL_FUNCTION_TRACE(unit, "IN");
   7117 
   7118     if (SOC_WARM_BOOT(unit)) {
   7119         if (NULL == policer_scache) {
   7120             LOG_ERROR(BSL_LS_BCM_POLICER,
   7121                       (BSL_META_U(unit,
   7122                                   "SCACHE Memory not available \n")));
   7123             return BCM_E_MEMORY;
   7124         }
   7125 
   7126         bk_svm_info = BCMI_SVM_BK_GET(unit);
   7127 
   7128         /* 1. recovery tcam usage bitmap */
   7129         bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE;
   7130         sal_memcpy(bk_svm_info->tcam_intf_bitmap, policer_scache,
   7131                    SHR_BITALLOCSIZE(bmp_size));
   7132         policer_scache += SHR_BITALLOCSIZE(bmp_size);
   7133 
   7134         /* 2. recovery offset_mode usage bitmap */
   7135         bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   7136         sal_memcpy(bk_svm_info->offset_mode_intf_bitmap, policer_scache,
   7137                    SHR_BITALLOCSIZE(bmp_size));
   7138         policer_scache += SHR_BITALLOCSIZE(bmp_size);
   7139 
   7140         /* 3. Copy actions bk */
   7141         table_size =
   7142             sizeof(bcmi_policer_global_meter_action_bk_t) *
   7143             BCMI_POLICER_SVC_METER_ACTION_SIZE;
   7144         sal_memcpy(BCMI_ACTION_BK_GET(unit), policer_scache,
   7145                    table_size);
   7146         policer_scache += table_size;
   7147 
   7148         /* Recover actions list handle */
   7149         for (i = 0; i < BCMI_POLICER_SVC_METER_ACTION_SIZE; i++) {
   7150             if (BCMI_ACTION_ID_BK_GET(unit, i).used) {
   7151                 rv = shr_aidxres_list_reserve_block(
   7152                         BCMI_ACTION_LIST_HANDLE_GET(unit), i, 1);
   7153                 BCM_IF_ERROR_RETURN(rv);
   7154             }
   7155         }
   7156 
   7157         /* 4. bcmi_policer_svm_offset_mode_bk_t */
   7158         for (offset_mode = 0;
   7159              offset_mode < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   7160              offset_mode++) {
   7161             if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode)) {
   7162                 bk_svm_mode_info =
   7163                     BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode);
   7164 
   7165                 sal_memcpy(&is_custom_group, policer_scache, sizeof(uint8));
   7166                 policer_scache += sizeof(uint8);
   7167 
   7168                 sal_memcpy(&ref_cnt, policer_scache, sizeof(uint32));
   7169                 policer_scache += sizeof(uint32);
   7170 
   7171                 sal_memcpy(&used, policer_scache, sizeof(uint32));
   7172                 policer_scache += sizeof(uint32);
   7173 
   7174                 sal_memcpy(&no_of_policers, policer_scache, sizeof(uint32));
   7175                 policer_scache += sizeof(uint32);
   7176 
   7177                 sal_memcpy(&no_of_attr_selectors, policer_scache,
   7178                     sizeof(uint32));
   7179                 policer_scache += sizeof(uint32);
   7180 
   7181                 sal_memcpy(&pkt_attr_v_cnt, policer_scache,
   7182                     sizeof(uint32));
   7183                 policer_scache += sizeof(uint32);
   7184 
   7185                 sal_memcpy(&group_mode, policer_scache,
   7186                     sizeof(bcm_policer_group_mode_t));
   7187                 policer_scache +=
   7188                     sizeof(bcm_policer_group_mode_t);
   7189 
   7190                 sal_memcpy(&group_mode_type, policer_scache,
   7191                     sizeof(bcm_policer_group_mode_type_t));
   7192                 policer_scache +=
   7193                     sizeof(bcm_policer_group_mode_type_t);
   7194 
   7195                 bk_svm_mode_info->is_custom_group = is_custom_group;
   7196                 bk_svm_mode_info->ref_cnt = ref_cnt;
   7197                 bk_svm_mode_info->used = used;
   7198                 bk_svm_mode_info->no_of_policers = no_of_policers;
   7199                 bk_svm_mode_info->no_of_attr_selectors = no_of_attr_selectors;
   7200                 bk_svm_mode_info->group_mode = group_mode;
   7201                 bk_svm_mode_info->group_mode_type = group_mode_type;
   7202                 bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_v_cnt;
   7203 
   7204                 /* 4.1 recovery attr_selectors info */
   7205                 POL_MEM_ALLOC(
   7206                     bk_svm_mode_info->attr_selectors,
   7207                     no_of_attr_selectors *
   7208                     sizeof(bcm_policer_group_mode_attr_selector_t),
   7209                     "attr selectors");
   7210                 if (NULL == bk_svm_mode_info->attr_selectors) {
   7211                     LOG_ERROR(BSL_LS_BCM_POLICER,
   7212                               (BSL_META_U(unit,
   7213                                           "Unable to allocate memory for "
   7214                                           "attr_selectors\n")));
   7215                     return BCM_E_MEMORY;
   7216                 }
   7217                 for (i = 0; i < no_of_attr_selectors; i++) {
   7218                     sal_memcpy(&bk_svm_mode_info->attr_selectors[i],
   7219                                policer_scache,
   7220                                sizeof(bcm_policer_group_mode_attr_selector_t));
   7221                     policer_scache +=
   7222                         sizeof(bcm_policer_group_mode_attr_selector_t);
   7223                 }
   7224 
   7225                 /* 4.2 recovery pkt_attr_v info */
   7226                 POL_MEM_ALLOC(
   7227                     bk_svm_mode_info->pkt_attr_v,
   7228                     bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t),
   7229                     "pkt_attr_v in offset mode instance");
   7230                 if (NULL == bk_svm_mode_info->pkt_attr_v) {
   7231                     LOG_ERROR(BSL_LS_BCM_POLICER,
   7232                               (BSL_META_U(unit,
   7233                                           "Unable to allocate memory for "
   7234                                           "pkt_attr_v\n")));
   7235                     return (BCM_E_MEMORY);
   7236                 }
   7237 
   7238                 for (i = 0; i < pkt_attr_v_cnt; i++) {
   7239                     sal_memcpy(&bk_svm_mode_info->pkt_attr_v[i],
   7240                                policer_scache,
   7241                                sizeof(pkt_tcam_attr_bits_t));
   7242                     policer_scache += sizeof(pkt_tcam_attr_bits_t);
   7243                 }
   7244             }
   7245         }
   7246 
   7247         /* 5. read from scache and create policer bookkeep data structure */
   7248         for (count_index = 0;
   7249              count_index < BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES;
   7250              count_index++) {
   7251             bcmi_global_meter_policer_control_t tmp_policer_control;
   7252 
   7253             sal_memcpy(&tmp_policer_control, policer_scache,
   7254                 sizeof(bcmi_global_meter_policer_control_t));
   7255             policer_scache += sizeof(bcmi_global_meter_policer_control_t);
   7256 
   7257             policer_id = tmp_policer_control.pid;
   7258             if ((policer_id & BCMI_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
   7259                 /* Allocate policer descriptor. */
   7260                 no_of_policers = tmp_policer_control.no_of_policers;
   7261                 policer_control = NULL;
   7262                 rv = bcmi_global_meter_policer_control_alloc(
   7263                         unit, no_of_policers, &policer_control);
   7264                 BCM_IF_ERROR_RETURN(rv);
   7265 
   7266                 /* 5.1 recovery policer_control */
   7267                 policer_control->pid = policer_id;
   7268                 policer_control->ref_count = tmp_policer_control.ref_count;
   7269                 policer_control->no_of_policers = tmp_policer_control.no_of_policers;
   7270                 policer_control->grp_mode = tmp_policer_control.grp_mode;
   7271 
   7272                 /* 5.2 recovery policer_control->pol_cfg[no_of_policers] */
   7273                 if (NULL != policer_control->pol_cfg) {
   7274                     for (i = 0; i < no_of_policers; i++) {
   7275                         sal_memcpy(&wb_pol_cfg, policer_scache,
   7276                             sizeof(bcm_policer_config_wb_t));
   7277                         policer_scache +=
   7278                             sizeof(bcm_policer_config_wb_t);
   7279                         wb_policer_config_copy_to_policer_config(
   7280                             &wb_pol_cfg,
   7281                             &(policer_control->pol_cfg[i]));
   7282                     }
   7283                 }
   7284 
   7285                 /* Insert policer into policers hash. */
   7286                 _GLOBAL_METER_HASH_INSERT(
   7287                     BCMI_POLICER_BK_GET(unit),
   7288                     policer_control,
   7289                     (policer_id & _GLOBAL_METER_HASH_MASK));
   7290                 /* Recover policer list handle */
   7291                 rv = shr_aidxres_list_alloc_block(
   7292                         BCMI_POLICER_LIST_HANDLE_GET(unit),
   7293                         no_of_policers,
   7294                         (uint32 *)&policer_id);
   7295                 BCM_IF_ERROR_RETURN(rv);
   7296             }
   7297         }
   7298 
   7299         /* Calculate the cnt/start/end */
   7300         bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE;
   7301         bk_svm_info->empty_tcam_idx_cnt = bmp_size;
   7302         bk_svm_info->valid_tcam_idx_cnt = 0;
   7303         bk_svm_info->valid_tcam_idx_start = 0;
   7304         bk_svm_info->valid_tcam_idx_end = 0;
   7305         bk_svm_info->empty_tcam_idx_start = 0;
   7306         bk_svm_info->empty_tcam_idx_end = 0;
   7307 
   7308         for (i = 0; i < bmp_size; i++) {
   7309             if (BCMI_SVM_TCAM_INTF_GET(unit, i)) {
   7310                 bk_svm_info->valid_tcam_idx_cnt++;
   7311             }
   7312 
   7313             if (BCMI_SVM_TCAM_INTF_GET(unit, i) &&
   7314                 !BCMI_OFFSET_MODE_ID_INTF_GET(
   7315                     unit, bk_svm_info->valid_tcam_idx_start)) {
   7316                 bk_svm_info->valid_tcam_idx_start = i;
   7317             }
   7318 
   7319             if (BCMI_SVM_TCAM_INTF_GET(unit, i) &&
   7320                 bk_svm_info->valid_tcam_idx_end < i) {
   7321                 bk_svm_info->valid_tcam_idx_end = i;
   7322             }
   7323 
   7324             if (!BCMI_SVM_TCAM_INTF_GET(unit, i) &&
   7325                 BCMI_OFFSET_MODE_ID_INTF_GET(
   7326                     unit, bk_svm_info->empty_tcam_idx_start)) {
   7327                 bk_svm_info->empty_tcam_idx_start = i;
   7328             }
   7329 
   7330             if (!BCMI_SVM_TCAM_INTF_GET(unit, i) &&
   7331                 bk_svm_info->empty_tcam_idx_end < i) {
   7332                 bk_svm_info->empty_tcam_idx_end = i;
   7333             }
   7334         }
   7335         bk_svm_info->empty_tcam_idx_cnt -=
   7336             bk_svm_info->valid_tcam_idx_cnt;
   7337 
   7338         bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   7339         bk_svm_info->empty_offset_mode_cnt = bmp_size;
   7340         bk_svm_info->valid_offset_mode_cnt = 0;
   7341         bk_svm_info->valid_offset_mode_start = 0;
   7342         bk_svm_info->valid_offset_mode_end = 0;
   7343         bk_svm_info->empty_offset_mode_start = 0;
   7344         bk_svm_info->empty_offset_mode_end = 0;
   7345 
   7346         for (i = 0; i < bmp_size; i++) {
   7347             if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i)) {
   7348                 bk_svm_info->valid_offset_mode_cnt++;
   7349             }
   7350 
   7351             if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) &&
   7352                 !BCMI_OFFSET_MODE_ID_INTF_GET(
   7353                     unit, bk_svm_info->valid_offset_mode_start)) {
   7354                 bk_svm_info->valid_offset_mode_start = i;
   7355             }
   7356 
   7357             if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) &&
   7358                 bk_svm_info->valid_offset_mode_end < i) {
   7359                 bk_svm_info->valid_offset_mode_end = i;
   7360             }
   7361 
   7362             if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) &&
   7363                 BCMI_OFFSET_MODE_ID_INTF_GET(
   7364                     unit, bk_svm_info->empty_offset_mode_start)) {
   7365                 bk_svm_info->empty_offset_mode_start = i;
   7366             }
   7367 
   7368             if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) &&
   7369                 bk_svm_info->empty_offset_mode_end < i) {
   7370                 bk_svm_info->empty_offset_mode_end = i;
   7371             }
   7372         }
   7373         bk_svm_info->empty_offset_mode_cnt -=
   7374             bk_svm_info->valid_offset_mode_cnt;
   7375     }
   7376     POL_FUNCTION_TRACE(unit, "OUT");
   7377     return rv;
   7378 }
   7379 
   7380 /*
   7381  * Function:
   7382  *     bcmi_esw_global_meter_reinit
   7383  * Purpose:
   7384  *     Reinit all the global meter internal data structures on warm boot
   7385  * Parameters:
   7386  *     unit                  - (IN) unit number
   7387  * Returns:
   7388  *     BCM_E_XXX
   7389  */
   7390 STATIC int
   7391 bcmi_esw_global_meter_reinit(int unit)
   7392 {
   7393     bcm_error_t rv = BCM_E_NONE;
   7394     soc_scache_handle_t scache_handle;
   7395     int stable_size;
   7396     uint8 *policer_scache;
   7397 
   7398     POL_FUNCTION_TRACE(unit, "IN");
   7399 
   7400     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   7401 
   7402     /* In case WARM BOOT level 2 store is not configured return from here. */
   7403     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
   7404         /* Warm Boot */
   7405         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
   7406 
   7407         rv = _bcm_esw_scache_ptr_get(
   7408                 unit, scache_handle, FALSE, 0,
   7409                 &policer_scache, BCM_WB_DEFAULT_VERSION, NULL);
   7410         if (rv == BCM_E_NOT_FOUND) {
   7411             /* Maybe proceed with Level 1 Warm Boot */
   7412             return BCM_E_NONE;
   7413         }
   7414 
   7415         /* go through scache and recover policer configuration */
   7416         BCM_IF_ERROR_RETURN(
   7417             bcmi_esw_global_meter_policer_recover_from_scache(unit, policer_scache));
   7418     }
   7419 
   7420     POL_FUNCTION_TRACE(unit, "OUT");
   7421     return rv;
   7422 }
   7423 #endif /* BCM_WARM_BOOT_SUPPORT */
   7424 
   7425 /*
   7426  * Function:
   7427  *     bcmi_esw_global_meter_cleanup
   7428  * Purpose:
   7429  *     Cleanup the global meter(service meter) internal data structure on
   7430  *     init failure.
   7431  * Parameters:
   7432  *     Unit - unit number
   7433  * Returns:
   7434  *     BCM_E_XXX
   7435  */
   7436 STATIC int
   7437 bcmi_esw_global_meter_cleanup(int unit)
   7438 {
   7439     int rv = BCM_E_NONE;
   7440     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   7441     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   7442     int i = 0;
   7443     bcmi_global_meter_policer_control_t *policer_control = NULL;
   7444 
   7445     POL_FUNCTION_TRACE(unit, "IN");
   7446 
   7447     CHECK_GLOBAL_METER_INIT(unit);
   7448 
   7449     bk_svm_info = BCMI_SVM_BK_GET(unit);
   7450 
   7451     POL_MEM_FREE(bk_svm_info->tcam_intf_bitmap);
   7452 
   7453     if (bk_svm_info->offset_mode_v != NULL) {
   7454         for (i = 0; i < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; i++) {
   7455             POL_MEM_FREE(bk_svm_info->offset_mode_v[i].attr_selectors);
   7456             POL_MEM_FREE(bk_svm_info->offset_mode_v[i].pkt_attr_v);
   7457         }
   7458     }
   7459     POL_MEM_FREE(bk_svm_info->offset_mode_v);
   7460     POL_MEM_FREE(bk_svm_info->offset_mode_intf_bitmap);
   7461 
   7462     /* mutex destroy */
   7463     if (NULL != bk_svm_info->mutex) {
   7464         sal_mutex_destroy(bk_svm_info->mutex);
   7465         bk_svm_info->mutex = NULL;
   7466     }
   7467 
   7468     /* mutex destroy */
   7469     if (NULL != global_meter_mutex[unit]) {
   7470         sal_mutex_destroy(global_meter_mutex[unit]);
   7471         global_meter_mutex[unit] = NULL;
   7472     }
   7473 
   7474     /* Free handles of index management for meter action */
   7475     if (NULL != BCMI_ACTION_LIST_HANDLE_GET(unit)) {
   7476         shr_aidxres_list_destroy(BCMI_ACTION_LIST_HANDLE_GET(unit));
   7477         BCMI_ACTION_LIST_HANDLE_GET(unit) = NULL;
   7478     }
   7479 
   7480     /* Free handles of index management for meter policer */
   7481     if (NULL != BCMI_POLICER_LIST_HANDLE_GET(unit)) {
   7482         shr_aidxres_list_destroy(BCMI_POLICER_LIST_HANDLE_GET(unit));
   7483         BCMI_POLICER_LIST_HANDLE_GET(unit) = NULL;
   7484     }
   7485 
   7486     /* Iterate over all hash buckets. */
   7487     for (i = 0; i < BCMI_GLOBAL_METER_HASH_SIZE; i++) {
   7488         policer_control = BCMI_POLICER_HASH_BK_GET(unit, i);
   7489         /* Destroy entries in each bucket. */
   7490         while (NULL != policer_control) {
   7491             /* De-allocate policer descriptor. */
   7492             POL_MEM_FREE(policer_control->pol_cfg);
   7493             POL_MEM_FREE(policer_control);
   7494         }
   7495     }
   7496 
   7497     POL_MEM_FREE(BCMI_POLICER_BK_GET(unit));
   7498     POL_MEM_FREE(BCMI_ACTION_BK_GET(unit));
   7499 
   7500     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   7501     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   7502 
   7503     /* Check if the chip specific function existed */
   7504     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->mem_clear);
   7505 
   7506     rv = gm_dev_info->mem_clear(unit);
   7507     BCM_IF_ERROR_RETURN(rv);
   7508 
   7509     global_meter_status[unit].initialised = FALSE;
   7510 
   7511     POL_FUNCTION_TRACE(unit, "OUT");
   7512     return rv;
   7513 }
   7514 
   7515 /*
   7516  * Function:
   7517  *     bcmi_esw_global_meter_init
   7518  * Purpose:
   7519  *     Initialise service meter data-structure
   7520  * Parameters:
   7521  *     Unit - unit number
   7522  * Returns:
   7523  *     BCM_E_XXX
   7524  */
   7525 STATIC int
   7526 bcmi_esw_global_meter_init(int unit)
   7527 {
   7528     int rv = BCM_E_NONE;
   7529     bcmi_policer_svm_bk_t *bk_svm_info = NULL;
   7530     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
   7531     uint32 global_meter_ctrl_disable = 0;
   7532     uint32 table_size;
   7533     uint32 action_size = 0;
   7534     uint32 size_bank = 0, block_factor = 0;
   7535     int i = 0;
   7536     bcm_policer_global_meter_config_t global_meter_config_v;
   7537 
   7538     POL_FUNCTION_TRACE(unit, "IN");
   7539 
   7540     if (!soc_feature(unit, soc_feature_global_meter)) {
   7541         return BCM_E_UNAVAIL;
   7542     }
   7543 
   7544     if (!soc_feature(unit, soc_feature_global_meter_v2)) {
   7545         return BCM_E_UNAVAIL;
   7546     }
   7547 
   7548     /* assert check that attr_to_bit_selector is added corrected */
   7549     (void)check_attr_to_bit_selector();
   7550 
   7551     /* Initial all unit with default value FALSE. */
   7552     if (FALSE == bcmi_global_meter_dev_info_initialized) {
   7553         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
   7554             BCM_SVM_DEV_INFO_GET(unit) = NULL;
   7555         }
   7556         bcmi_global_meter_dev_info_initialized = TRUE;
   7557     }
   7558 
   7559     /* Register driver functions */
   7560     rv = bcmi_global_meter_dev_info_init(unit);
   7561     if (BCM_FAILURE(rv)) {
   7562         LOG_ERROR(BSL_LS_BCM_POLICER,
   7563                   (BSL_META_U(unit,
   7564                               "Device info init failed (rv = %d)\n"),
   7565                               rv));
   7566         return rv;
   7567     }
   7568 
   7569     if (TRUE == global_meter_status[unit].initialised) {
   7570         bcmi_esw_global_meter_cleanup(unit);
   7571     }
   7572 
   7573     /* ******************************************** */
   7574     /*
   7575      * Check if  Service meter Block is enable or not in config.bcm
   7576      * global_meter_control = 1 means enable
   7577      * global_meter_control = 0 means disable
   7578      */
   7579     if (!soc_property_get(unit, spn_GLOBAL_METER_CONTROL, 1)) {
   7580         global_meter_ctrl_disable = BCM_POLICER_GLOBAL_METER_DISABLE;
   7581     }
   7582 
   7583     LOG_DEBUG(BSL_LS_BCM_POLICER,
   7584               (BSL_META_U(unit,
   7585                           "global_meter_ctrl_disable = %d, "
   7586                           "enable %d\n"),
   7587                           global_meter_ctrl_disable,
   7588                           global_meter_ctrl_disable ==
   7589                           BCM_POLICER_GLOBAL_METER_DISABLE ? 0 : 1
   7590                           ));
   7591 
   7592     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
   7593     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
   7594 
   7595     /* Check if the chip specific function existed */
   7596     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->svm_enable_set);
   7597 
   7598     if (BCM_POLICER_GLOBAL_METER_DISABLE == global_meter_ctrl_disable) {
   7599         rv = gm_dev_info->svm_enable_set(unit, FALSE);
   7600         BCM_IF_ERROR_RETURN(rv);
   7601         global_meter_status[unit].initialised = FALSE;
   7602         LOG_WARN(BSL_LS_BCM_POLICER,
   7603                  (BSL_META_U(unit,
   7604                              "GLOBAL METER FEATURE disabled "
   7605                              "at HW for unit %d\n"), unit));
   7606         return rv;
   7607     } else  {
   7608         rv = gm_dev_info->svm_enable_set(unit, TRUE);
   7609         BCM_IF_ERROR_RETURN(rv);
   7610     }
   7611     /* ******************************************** */
   7612 
   7613     /* ******************************************** */
   7614     /*
   7615      * Always enable SEOP metering all the time in SVM block.
   7616      * It's usable for any metering mode.
   7617      */
   7618 
   7619     /* Check if the chip specific function existed */
   7620     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->seop_enable_set);
   7621 
   7622     rv = gm_dev_info->seop_enable_set(unit, 1);
   7623     BCM_IF_ERROR_RETURN(rv);
   7624     /* ******************************************** */
   7625 
   7626     /* Initialize bookkeeping data structure */
   7627     bk_svm_info = BCMI_SVM_BK_GET(unit);
   7628 
   7629     /* Allocate usage bitmap */
   7630     table_size = BCMI_POLICER_SVC_METER_TCAM_SIZE;
   7631     if ((table_size) > (soc_mem_index_max(unit, SVC_METER_OFFSET_TCAMm) + 1))
   7632     {
   7633         LOG_ERROR(BSL_LS_BCM_POLICER,
   7634                   (BSL_META_U(unit,
   7635                               "Number of global meters exceeding "
   7636                               "its max value\n")));
   7637         return BCM_E_INTERNAL;
   7638     }
   7639 
   7640     POL_MEM_ALLOC(
   7641         bk_svm_info->tcam_intf_bitmap,
   7642         SHR_BITALLOCSIZE(table_size),
   7643         "TCAM intf_bitmap");
   7644     if (bk_svm_info->tcam_intf_bitmap == NULL) {
   7645         bcmi_esw_global_meter_cleanup(unit);
   7646         LOG_ERROR(BSL_LS_BCM_POLICER,
   7647                   (BSL_META_U(unit,
   7648                               "Unable to allocate memory for "
   7649                               "tcam_intf_bitmap\n")));
   7650         return BCM_E_MEMORY;
   7651     }
   7652 
   7653     bk_svm_info->valid_tcam_idx_cnt = 0;
   7654     bk_svm_info->valid_tcam_idx_start = 0;
   7655     bk_svm_info->valid_tcam_idx_end = 0;
   7656     bk_svm_info->empty_tcam_idx_cnt = table_size;
   7657     bk_svm_info->empty_tcam_idx_start = 0;
   7658     bk_svm_info->empty_tcam_idx_end = table_size - 1;
   7659 
   7660     /* Allocate usage bitmap */
   7661     table_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   7662     POL_MEM_ALLOC(
   7663         bk_svm_info->offset_mode_intf_bitmap,
   7664         SHR_BITALLOCSIZE(table_size),
   7665         "Offset Mode intf_bitmap");
   7666     if (bk_svm_info->offset_mode_intf_bitmap == NULL) {
   7667         bcmi_esw_global_meter_cleanup(unit);
   7668         LOG_ERROR(BSL_LS_BCM_POLICER,
   7669                   (BSL_META_U(unit,
   7670                               "Unable to allocate memory for "
   7671                               "offset_mode_intf_bitmap\n")));
   7672         return BCM_E_MEMORY;
   7673     }
   7674 
   7675 
   7676     bk_svm_info->valid_offset_mode_cnt = 0;
   7677     bk_svm_info->valid_offset_mode_start = 0;
   7678     bk_svm_info->valid_offset_mode_end = 0;
   7679     bk_svm_info->empty_offset_mode_cnt = table_size;
   7680     bk_svm_info->empty_offset_mode_start = 0;
   7681     bk_svm_info->empty_offset_mode_end = table_size - 1;
   7682 
   7683     if (bk_svm_info->mutex == NULL) {
   7684         bk_svm_info->mutex = sal_mutex_create("Global meter bk mutex");
   7685         if (bk_svm_info->mutex == NULL) {
   7686             bcmi_esw_global_meter_cleanup(unit);
   7687             LOG_ERROR(BSL_LS_BCM_POLICER,
   7688                       (BSL_META_U(unit,
   7689                                   "Unable to create bk mutex\n")));
   7690             return BCM_E_MEMORY;
   7691         }
   7692     }
   7693 
   7694     /* Init the offset table 0 such that it can be used for non-offset
   7695       based metering */
   7696     if (global_meter_mutex[unit] == NULL) {
   7697         global_meter_mutex[unit] = sal_mutex_create("Global meter mutex");
   7698         if (global_meter_mutex[unit] == NULL) {
   7699             bcmi_esw_global_meter_cleanup(unit);
   7700             LOG_ERROR(BSL_LS_BCM_POLICER,
   7701                       (BSL_META_U(unit,
   7702                                   "Unable to create mutex\n")));
   7703             return BCM_E_MEMORY;
   7704         }
   7705     }
   7706 
   7707     /* Allocate policer offset mode instance. */
   7708     table_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE;
   7709     POL_MEM_ALLOC(
   7710         bk_svm_info->offset_mode_v,
   7711         table_size * sizeof(bcmi_policer_svm_offset_mode_bk_t),
   7712         "offset mode instance");
   7713     if (NULL == bk_svm_info->offset_mode_v) {
   7714         bcmi_esw_global_meter_cleanup(unit);
   7715         LOG_ERROR(BSL_LS_BCM_POLICER,
   7716                   (BSL_META_U(unit,
   7717                               "Unable to allocate memory for "
   7718                               "offset_mode_v\n")));
   7719         return (BCM_E_MEMORY);
   7720     }
   7721     for (i = 0; i < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; i++) {
   7722         bcmi_policer_svm_offset_mode_bk_t_init(
   7723             &(bk_svm_info->offset_mode_v[i]));
   7724     }
   7725 
   7726     /* Allocate meter action management data structure */
   7727     action_size = BCMI_POLICER_SVC_METER_ACTION_SIZE;
   7728     if ((action_size) > (soc_mem_index_max(unit, SVM_POLICY_TABLEm) + 1)) {
   7729         LOG_ERROR(BSL_LS_BCM_POLICER,
   7730                   (BSL_META_U(unit,
   7731                               "Global meter actions exceeding "
   7732                               "its max value\n")));
   7733         return BCM_E_INTERNAL;
   7734     }
   7735 
   7736     POL_MEM_ALLOC(
   7737         BCMI_ACTION_BK_GET(unit),
   7738         action_size * sizeof(bcmi_policer_global_meter_action_bk_t),
   7739         "Global meter action alloc");
   7740     if (NULL == BCMI_ACTION_BK_GET(unit)) {
   7741         bcmi_esw_global_meter_cleanup(unit);
   7742         LOG_ERROR(BSL_LS_BCM_POLICER,
   7743                   (BSL_META_U(unit,
   7744                               "Unable to allocate memory for "
   7745                               "meter action\n")));
   7746         return (BCM_E_MEMORY);
   7747     }
   7748 
   7749     /* Index management for meter action */
   7750     if (NULL != BCMI_ACTION_LIST_HANDLE_GET(unit)) {
   7751         shr_aidxres_list_destroy(BCMI_ACTION_LIST_HANDLE_GET(unit));
   7752         BCMI_ACTION_LIST_HANDLE_GET(unit) = NULL;
   7753     }
   7754 
   7755     /* Create meter action */
   7756     if (shr_aidxres_list_create(
   7757                       &BCMI_ACTION_LIST_HANDLE_GET(unit),
   7758                       0, (action_size - 1),
   7759                       0, (action_size - 1),
   7760                       8,
   7761                       "global_meter_action") != BCM_E_NONE) {
   7762         bcmi_esw_global_meter_cleanup(unit);
   7763         LOG_ERROR(BSL_LS_BCM_POLICER,
   7764                   (BSL_META_U(unit,
   7765                               "Couldn't create alligned list "
   7766                               "for global meter action\n")));
   7767         return BCM_E_INTERNAL;
   7768     }
   7769 
   7770     /* Reserve the first entry in action table */
   7771     rv = shr_aidxres_list_reserve_block(
   7772             BCMI_ACTION_LIST_HANDLE_GET(unit), 0, 1);
   7773     if (BCM_FAILURE(rv)) {
   7774         bcmi_esw_global_meter_cleanup(unit);
   7775         LOG_ERROR(BSL_LS_BCM_POLICER,
   7776                   (BSL_META_U(unit,
   7777                               "Not able to reserve first entry "
   7778                               "in action table\n")));
   7779         return (rv);
   7780     }
   7781 
   7782     /* Allocate policer lookup hash. */
   7783     POL_MEM_ALLOC(
   7784         BCMI_POLICER_BK_GET(unit),
   7785         BCMI_GLOBAL_METER_HASH_SIZE *
   7786         sizeof(bcmi_global_meter_policer_control_t *),
   7787         "Global meter hash");
   7788 
   7789     if (NULL == BCMI_POLICER_BK_GET(unit)) {
   7790         bcmi_esw_global_meter_cleanup(unit);
   7791         LOG_ERROR(BSL_LS_BCM_POLICER,
   7792                   (BSL_META_U(unit,
   7793                               "Unable to allocate memory for policer bookkeep "
   7794                               "data structure\n")));
   7795         return (BCM_E_MEMORY);
   7796     }
   7797 
   7798     if (NULL != BCMI_POLICER_LIST_HANDLE_GET(unit)) {
   7799         shr_aidxres_list_destroy(BCMI_POLICER_LIST_HANDLE_GET(unit));
   7800         BCMI_POLICER_LIST_HANDLE_GET(unit) = NULL;
   7801     }
   7802 
   7803     size_bank = BCMI_POLICER_SVC_METER_POOL_SIZE;
   7804     table_size = BCMI_POLICER_SVC_METER_TCAM_SIZE;
   7805     POL_GET_LOG2(table_size, block_factor);
   7806 
   7807     /* Create it */
   7808     if (shr_aidxres_list_create(
   7809           &BCMI_POLICER_LIST_HANDLE_GET(unit),
   7810           0, (size_bank - 1),
   7811           0, (size_bank - 1),
   7812           block_factor,
   7813           "global_meter_policer") != BCM_E_NONE) {
   7814         bcmi_esw_global_meter_cleanup(unit);
   7815         LOG_ERROR(BSL_LS_BCM_POLICER,
   7816                   (BSL_META_U(unit,
   7817                               "Couldn't create alligned list for "
   7818                               "global meter policer\n")));
   7819         return BCM_E_INTERNAL;
   7820     }
   7821 
   7822     /* Reserve the first entry in policer table */
   7823     rv = shr_aidxres_list_reserve_block(
   7824             BCMI_POLICER_LIST_HANDLE_GET(unit), 0, 1);
   7825     if (BCM_FAILURE(rv)) {
   7826         bcmi_esw_global_meter_cleanup(unit);
   7827         LOG_ERROR(BSL_LS_BCM_POLICER,
   7828                   (BSL_META_U(unit,
   7829                               "Not able to reserve first entry "
   7830                               "in policer table\n")));
   7831         return (rv);
   7832     }
   7833 
   7834 #ifdef BCM_WARM_BOOT_SUPPORT
   7835     if (SOC_WARM_BOOT(unit)) {
   7836         rv = bcmi_esw_global_meter_reinit(unit);
   7837         if (BCM_FAILURE(rv)) {
   7838             bcmi_esw_global_meter_cleanup(unit);
   7839             LOG_ERROR(BSL_LS_BCM_POLICER,
   7840                       (BSL_META_U(unit,
   7841                                   "Warm boot init failed\n")));
   7842             return BCM_E_INTERNAL;
   7843         }
   7844     }
   7845 #endif /* BCM_WARM_BOOT_SUPPORT */
   7846     global_meter_status[unit].initialised = TRUE;
   7847 
   7848     LOG_VERBOSE(BSL_LS_BCM_POLICER,
   7849                 (BSL_META_U(unit,
   7850                             "GLOBAL METER FEATURE initialised\n")));
   7851     /*
   7852      * Init default HW values
   7853      */
   7854     bcm_policer_global_meter_config_t_init(&global_meter_config_v);
   7855 
   7856     /*
   7857      * Enable Global Meter Inter Frame Gap
   7858      * IFG value must be configured by switch API
   7859      * bcmSwitchMeterAdjustInterframeGap (per port)
   7860      */
   7861     global_meter_config_v.ifg_enable = 0;
   7862 
   7863     /* Set order of source tables in the case of conflict source happened. */
   7864     global_meter_config_v.source_order_count = 7;
   7865     global_meter_config_v.source_order[0] =
   7866         bcmPolicerGlobalMeterSourceFieldStageLookup;
   7867     global_meter_config_v.source_order[1] =
   7868         bcmPolicerGlobalMeterSourceDstMac;
   7869     global_meter_config_v.source_order[2] =
   7870         bcmPolicerGlobalMeterSourceSrcMac;
   7871     global_meter_config_v.source_order[3] =
   7872         bcmPolicerGlobalMeterSourceVlanTranslateFirst;
   7873     global_meter_config_v.source_order[4] =
   7874         bcmPolicerGlobalMeterSourceVlanTranslateSecond;
   7875     global_meter_config_v.source_order[5] =
   7876         bcmPolicerGlobalMeterSourceVlan;
   7877     global_meter_config_v.source_order[6] =
   7878         bcmPolicerGlobalMeterSourcePort;
   7879 
   7880     /* Sets Global Meter Configuration */
   7881     bcm_esw_policer_global_meter_config_set(unit, &global_meter_config_v);
   7882 
   7883     POL_FUNCTION_TRACE(unit, "OUT");
   7884     return rv;
   7885 }
   7886 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
   7887 
   7888 STATIC
   7889 int _bcm_esw_svc_meter_offset_mode_id_check (uint32 unit, uint32 flags,
   7890                 bcm_policer_group_mode_type_t type, uint32 total_policers,
   7891                 uint32 num_selectors,
   7892                 bcm_policer_group_mode_attr_selector_t * attr_selectors,
   7893                 uint32 *mode_id);
   7894 
   7895 STATIC
   7896 int _bcm_esw_policer_group_mode_fillup_values(int unit, uint32 flags,
   7897                 bcm_policer_group_mode_type_t type, uint32 total_policers,
   7898                 uint32 num_selectors,
   7899                 bcm_policer_group_mode_attr_selector_t *attr_selectors,
   7900                 bcm_policer_attr_selectors_t *pkt_attr_selectors);
   7901 
   7902 STATIC
   7903 int _bcm_wb_attr_selectors_copy_to_attr_selectors(
   7904                 uint32 num_selectors,
   7905                 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb,
   7906                 bcm_policer_group_mode_attr_selector_t *attr_selectors);
   7907 
   7908 STATIC
   7909 int _bcm_esw_svc_meter_compressed_modes_match(int unit,
   7910                 compressed_attr_selectors_t *compressed_attr_selectors_v,
   7911                 bcm_policer_group_mode_t group_mode,
   7912                 int8 type,
   7913                 bcm_policer_svc_meter_mode_t *svc_meter_mode);
   7914 
   7915 #ifdef BCM_WARM_BOOT_SUPPORT
   7916 STATIC
   7917 int _bcm_esw_svc_meter_wb_size_calc(int unit, int *size);
   7918 #endif
   7919 
   7920 typedef int (*_bcm_esw_svm_mem_entry_traverse_cb)(int unit,
   7921                 soc_mem_t mem, uint32 index, void *entry,
   7922                 void *user_data, uint32 *dirty);
   7923 
   7924 bcm_error_t
   7925 _bcm_esw_svm_source_traverse(int unit, soc_mem_t mem, int start_idx,
   7926                 int end_idx, _bcm_esw_svm_mem_entry_traverse_cb cb,
   7927                 void *user_data);
   7928 
   7929 /*
   7930  * Function:
   7931  *      check_global_meter_init
   7932  * Purpose:
   7933  *     To check whether the global meter module is initialized or not
   7934  * Parameters:
   7935  *     Unit                  - (IN) unit number
   7936  * Returns:
   7937  *     BCM_E_INIT
   7938  */
   7939 int _check_global_meter_init(int unit)
   7940 {
   7941     if (!global_meter_status[unit].initialised) {
   7942             return BCM_E_INIT;
   7943     } else {
   7944         return BCM_E_NONE;
   7945     }
   7946 }
   7947 
   7948 /*
   7949  * Function:
   7950  *      convert_to_bitmask
   7951  * Purpose:
   7952  *
   7953  * Parameters:
   7954  *     num - number to be converted to bistmask
   7955  * Returns:
   7956  *     bit mask for the number
   7957  */
   7958 static int convert_to_bitmask(int num)
   7959 {
   7960     int bit_mask = 0;
   7961     num = num & 0xf;
   7962     while (num > 0) {
   7963         bit_mask = bit_mask | (1 << (num-1));
   7964         num--;
   7965     }
   7966     return bit_mask;
   7967 }
   7968 
   7969 /*
   7970  * Function:
   7971  *      convert_to_mask
   7972  * Purpose:
   7973  *     Creates a mask with all the bit positon other then the positon
   7974  *     represented by num
   7975  * Parameters:
   7976  *     num -  number
   7977  * Returns:
   7978  *     BCM_E_XXX
   7979  */
   7980 static int convert_to_mask(int num)
   7981 {
   7982     int bit_mask = 0;
   7983     num = num & 0xf;
   7984     bit_mask =  ~(1 << num);
   7985     return bit_mask;
   7986 }
   7987 
   7988 /*
   7989  * Function:
   7990  *     _bcm_attr_selectors_copy_to_wb_attr_selectors
   7991  * Purpose:
   7992  *     Copy the content of attr_selectors from
   7993  *     bcm_policer_group_mode_attr_selector_t to
   7994  *     bcm_policer_group_mode_attr_selector_wb_t
   7995  * Parameters:
   7996  *     num_selectors (IN) - no. of attr_selectors for KT2/TR3/FB4 WB structure
   7997  *     attr_selectors (IN) -  bcm API attr_selectors
   7998  *     attr_selectors_wb (OUT)-  attr_selectors for KT2/TR3/FB4 WB structure
   7999  * Returns:
   8000  *     BCM_E_XXX
   8001  */
   8002 STATIC int
   8003 _bcm_attr_selectors_copy_to_wb_attr_selectors(
   8004     uint32 num_selectors,
   8005     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   8006     bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb)
   8007 {
   8008     uint32 sel = 0;
   8009 
   8010     if ((NULL == attr_selectors) ||
   8011         (NULL == attr_selectors_wb)) {
   8012         return BCM_E_PARAM;
   8013     }
   8014 
   8015     for (sel = 0; sel < num_selectors; sel++) {
   8016         attr_selectors_wb[sel].flags = attr_selectors[sel].flags;
   8017         attr_selectors_wb[sel].policer_offset = attr_selectors[sel].policer_offset;
   8018         attr_selectors_wb[sel].attr = attr_selectors[sel].attr;
   8019         attr_selectors_wb[sel].attr_value = attr_selectors[sel].attr_value;
   8020         attr_selectors_wb[sel].udf_id = attr_selectors[sel].udf_id;
   8021         attr_selectors_wb[sel].offset = attr_selectors[sel].offset;
   8022         attr_selectors_wb[sel].width = attr_selectors[sel].width;
   8023     }
   8024 
   8025     return BCM_E_NONE;
   8026 }
   8027 
   8028 /*
   8029  * Function:
   8030  *     _bcm_wb_attr_selectors_copy_to_attr_selectors
   8031  * Purpose:
   8032  *     Copy the content of attr_selectors from
   8033  *     bcm_policer_group_mode_attr_selector_wb_t to
   8034  *     bcm_policer_group_mode_attr_selector_t
   8035  * Parameters:
   8036  *     num_selectors (IN) - no. of attr_selectors for KT2/TR3/FB4 WB structure
   8037  *     attr_selectors_wb (IN) - attr_selectors for KT2/TR3/FB4 WB structure
   8038  *     attr_selectors (OUT)- bcm API attr_selectors
   8039  * Returns:
   8040  *     BCM_E_XXX
   8041  */
   8042 STATIC int
   8043 _bcm_wb_attr_selectors_copy_to_attr_selectors(
   8044     uint32 num_selectors,
   8045     bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb,
   8046     bcm_policer_group_mode_attr_selector_t *attr_selectors)
   8047 {
   8048     uint32 sel = 0;
   8049 
   8050     if (NULL == attr_selectors_wb || NULL == attr_selectors) {
   8051         return BCM_E_PARAM;
   8052     }
   8053 
   8054     for (sel = 0; sel < num_selectors; sel++) {
   8055         attr_selectors[sel].flags = attr_selectors_wb[sel].flags;
   8056         attr_selectors[sel].policer_offset = attr_selectors_wb[sel].policer_offset;
   8057         attr_selectors[sel].attr = attr_selectors_wb[sel].attr;
   8058         attr_selectors[sel].attr_value = attr_selectors_wb[sel].attr_value;
   8059         attr_selectors[sel].udf_id = attr_selectors_wb[sel].udf_id;
   8060         attr_selectors[sel].offset = attr_selectors_wb[sel].offset;
   8061         attr_selectors[sel].width = attr_selectors_wb[sel].width;
   8062     }
   8063 
   8064     return BCM_E_NONE;
   8065 }
   8066 
   8067 /*
   8068  * Function:
   8069  *     _bcm_attr_selectors_wb_attr_selectors_cmp
   8070  * Purpose:
   8071  *     compare the content of attr_selectors between
   8072  *     bcm_policer_group_mode_attr_selector_wb_t and
   8073  *     bcm_policer_group_mode_attr_selector_t
   8074  * Parameters:
   8075  *     num_selectors (IN) -  no. of attr_selectors for KT2/TR3/FB4 WB structure.
   8076  *     attr_selectors (IN) -  bcm API attr_selectors
   8077  *     attr_selectors_wb (IN) -  attr_selectors for KT2/TR3/FB4 WB structure
   8078  *     is_same (OUT) -  return if contents are all the same or not
   8079  * Returns:
   8080  *     BCM_E_XXX
   8081  */
   8082 STATIC int
   8083 _bcm_attr_selectors_wb_attr_selectors_cmp(
   8084     uint32 num_selectors,
   8085     bcm_policer_group_mode_attr_selector_t *attr_selectors,
   8086     bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb,
   8087     int *is_same)
   8088 {
   8089     uint32 sel = 0;
   8090 
   8091     if ((NULL == attr_selectors_wb) ||
   8092         (NULL == attr_selectors) ||
   8093         (NULL == is_same)) {
   8094         return BCM_E_PARAM;
   8095     }
   8096 
   8097     *is_same = TRUE;
   8098     for (sel = 0; sel < num_selectors; sel++) {
   8099         if ((attr_selectors[sel].flags !=
   8100                     attr_selectors_wb[sel].flags) ||
   8101             (attr_selectors[sel].policer_offset !=
   8102                     attr_selectors_wb[sel].policer_offset) ||
   8103             (attr_selectors[sel].attr !=
   8104                     attr_selectors_wb[sel].attr) ||
   8105             (attr_selectors[sel].attr_value !=
   8106                     attr_selectors_wb[sel].attr_value) ||
   8107             (attr_selectors[sel].udf_id !=
   8108                     attr_selectors_wb[sel].udf_id) ||
   8109             (attr_selectors[sel].offset !=
   8110                     attr_selectors_wb[sel].offset) ||
   8111             (attr_selectors[sel].width !=
   8112                     attr_selectors_wb[sel].width)) {
   8113             *is_same = FALSE;
   8114             break;
   8115         }
   8116     }
   8117     return BCM_E_NONE;
   8118 }
   8119 
   8120 /*
   8121  * Function:
   8122  *      get_max_banks_in_a_pool
   8123  * Purpose:
   8124  *     Returns the number of banks per pool
   8125  * Parameters:
   8126  *     unit - unit number
   8127  * Returns:
   8128  *     num_banks
   8129  */
   8130 STATIC
   8131 int get_max_banks_in_a_pool(int unit)
   8132 {
   8133     return BCM_SVM_DEV_ATTR(unit)->banks_per_pool;
   8134 }
   8135 
   8136 /*
   8137  * Function:
   8138  *      _bcm_policer_flow_info_t_init
   8139  * Purpose:
   8140  *     Init bcm_policer_flow_info_t
   8141  * Parameters:
   8142  *     flow_info : pointer of type _bcm_policer_flow_info_t
   8143  * Returns:
   8144  *     BCM_E_XXX
   8145  */
   8146 STATIC
   8147 int _bcm_policer_flow_info_t_init(_bcm_policer_flow_info_t *flow_info)
   8148 {
   8149     flow_info->flow_type = bcmPolicerFlowTypeNormal;
   8150     flow_info->req_alloc = FALSE;
   8151     flow_info->skip_pool = -1;
   8152     flow_info->skip_bank = -1;
   8153     flow_info->req_pool  = -1;
   8154     flow_info->req_base_offset = -1;
   8155 
   8156     return BCM_E_NONE;
   8157 }
   8158 
   8159 /*
   8160  * Function:
   8161  *      _bcm_policer_svc_meter_update_udf_selector_keys
   8162  * Purpose:
   8163  *     Internal function for updating udf selector keys
   8164  * Parameters:
   8165  *     Unit                  - (IN) unit number
   8166  *     pkt_attr_selector_key - (IN) packet attribute selector key
   8167  *     udf_pkt_attr          - (IN) UDF packet attributes
   8168  *     total_udf_bits        - (OUT) Total number of udf bits used
   8169  * Returns:
   8170  *     BCM_E_XXX
   8171  */
   8172 bcm_error_t _bcm_policer_svc_meter_update_udf_selector_keys(
   8173     int                        unit,
   8174     soc_reg_t                  pkt_attr_selector_key,
   8175     udf_pkt_attr_selectors_t   *udf_pkt_attr,
   8176     uint32                     *total_udf_bits)
   8177 {
   8178     uint64    pkt_attr_selector_key_value;
   8179     uint32    udf_valid_bits = 0;
   8180     uint8     key_bit_selector_position = 0;
   8181     uint8     mask = 0;
   8182     uint32    index = 0;
   8183 
   8184     COMPILER_64_ZERO(pkt_attr_selector_key_value);
   8185     (*total_udf_bits) = 0;
   8186     if (!(pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) &&
   8187          (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r)) {
   8188       /* Valid mem value go ahead for setting
   8189                        ING_FLEX_CTR_PKT_ATTR_SELECTOR_KEY_?r: */
   8190         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
   8191                       "Invalid memory for packet attribute selector \n")));
   8192         return BCM_E_PARAM;
   8193     }
   8194 
   8195     /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */
   8196     SOC_IF_ERROR_RETURN(soc_reg_get(unit,
   8197             pkt_attr_selector_key,
   8198             REG_PORT_ANY,
   8199             0,
   8200             &pkt_attr_selector_key_value));
   8201 
   8202     /* Next set field value for
   8203                     ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/
   8204     soc_reg64_field32_set(
   8205             unit,
   8206             pkt_attr_selector_key,
   8207             &pkt_attr_selector_key_value,
   8208             USE_UDF_KEYf,
   8209             1);
   8210     udf_valid_bits |= SVC_METER_UDF1_VALID;
   8211     udf_valid_bits |= SVC_METER_UDF2_VALID;
   8212 
   8213     soc_reg64_field32_set(
   8214             unit,
   8215             pkt_attr_selector_key,
   8216             &pkt_attr_selector_key_value,
   8217             USER_SPECIFIED_UDF_VALIDf,
   8218             udf_valid_bits);
   8219 
   8220     /* Now update selector keys
   8221      * In udf based offset generation, bit-0 is for drop.
   8222      * bit-1 to bit-32 is used for 2 16-bits udf-chunks
   8223      */
   8224     if (udf_pkt_attr->drop == 1) {
   8225         BCM_IF_ERROR_RETURN(
   8226             _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   8227                         unit,
   8228                         pkt_attr_selector_key,
   8229                         &pkt_attr_selector_key_value,
   8230                         0, /* Start bit of drop */
   8231                         1, /* width of drop */
   8232                         1,
   8233                         &key_bit_selector_position));
   8234     }
   8235     for (index = 0; index < udf_pkt_attr->total_subdiv; index++) {
   8236         mask = (1 << udf_pkt_attr->udf_subdiv[index].width) - 1;
   8237         BCM_IF_ERROR_RETURN(
   8238             _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   8239                         unit,
   8240                         pkt_attr_selector_key,
   8241                         &pkt_attr_selector_key_value,
   8242                         udf_pkt_attr->udf_subdiv[index].offset + 1, /* +1 to adjust drop bit */
   8243                         udf_pkt_attr->udf_subdiv[index].width,
   8244                         mask,
   8245                         &key_bit_selector_position));
   8246     }
   8247 
   8248     /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */
   8249     SOC_IF_ERROR_RETURN(soc_reg_set(unit,
   8250             pkt_attr_selector_key,
   8251             REG_PORT_ANY,
   8252             0,
   8253             pkt_attr_selector_key_value));
   8254     return BCM_E_NONE;
   8255 }
   8256 /*
   8257  * Function:
   8258  *      _bcm_esw_policer_get_offset_table_policer_count
   8259  * Purpose:
   8260  *    set group mode and number of policers in offset table at
   8261  *              offsets 254 and 255 - for use during warmboot
   8262  *
   8263  * Parameters:
   8264  *     Unit                  - (IN) unit number
   8265  *     offset_mode           - (IN) Offset mode
   8266  *     mode                  - (OUT) Policer group mode
   8267  *     npolicers             - (OUT) Total number of policer created
   8268  * Returns:
   8269  *     BCM_E_XXX
   8270  */
   8271 bcm_error_t _bcm_esw_policer_get_offset_table_policer_count(
   8272     int                                unit,
   8273     bcm_policer_svc_meter_mode_t       offset_mode,
   8274     bcm_policer_group_mode_t           *mode,
   8275     int                                *npolicers)
   8276 {
   8277     uint32            offset_table_entry = 0;
   8278     int               max_index = 0;
   8279     int               meter_enable;
   8280 
   8281     max_index = BCM_POLICER_SVC_METER_MAX_OFFSET;
   8282     /* First Get complete value of ING_SVM_METER_OFFSET_TABLE_?m value */
   8283     SOC_IF_ERROR_RETURN(soc_mem_read(unit,
   8284          SVM_OFFSET_TABLEm, MEM_BLOCK_ANY,
   8285          ((offset_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) |
   8286                                                         (max_index  - 1)),
   8287          &offset_table_entry));
   8288 
   8289     /* Read meter_enable first, if meter_enable=1, offsets 255,254 have
   8290         not stored npolicers and group_mode.
   8291         Also, Warmboot vesion BCM_WB_VERSION_1_1 onwards, npolices and group_mode
   8292         are stored in scache. */
   8293     soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry,
   8294                                             METER_ENABLEf, (uint32 *)&meter_enable);
   8295     if (meter_enable == 1)  {
   8296         *npolicers = 0;
   8297         *mode = 0;
   8298         return BCM_E_NONE;
   8299     }
   8300 
   8301     soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry,
   8302                                             OFFSETf, (uint32 *)npolicers);
   8303 
   8304     SOC_IF_ERROR_RETURN(soc_mem_read(unit,
   8305          SVM_OFFSET_TABLEm, MEM_BLOCK_ANY,
   8306          ((offset_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) |
   8307                                                         (max_index  - 2)),
   8308          &offset_table_entry));
   8309 
   8310     /* Read meter_enable first, if meter_enable=1, offsets 255,254 have
   8311         not stored npolicers and group_mode.
   8312         Also, Warmboot vesion BCM_WB_VERSION_1_1 onwards, npolices and group_mode
   8313         are stored in scache. */
   8314     soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry,
   8315                                             METER_ENABLEf, (uint32 *)&meter_enable);
   8316     if (meter_enable == 1)  {
   8317         *npolicers = 0;
   8318         *mode = 0;
   8319         return BCM_E_NONE;
   8320     }
   8321     soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry,
   8322                                                  OFFSETf, (uint32 *)mode);
   8323     return BCM_E_NONE;
   8324 }
   8325 
   8326 /*
   8327  * Function:
   8328  *      _bcm_esw_svm_offset_table_map_set
   8329  * Purpose:
   8330  *      Write to svm offset table.
   8331  *
   8332  * Parameters:
   8333  *     Unit                  - (IN) unit number
   8334  *     mem                   - (IN) memory
   8335  *     index                 - (IN) Entry index in memory
   8336  *     entry                 - (IN/OUT) entry buffer at mem index
   8337  *     user_data             - (IN) user data - offset map
   8338  *     dirty                 - (OUT) entry modified
   8339  * Returns:
   8340  *     BCM_E_XXX
   8341  */
   8342 STATIC
   8343 int _bcm_esw_svm_offset_table_map_set(
   8344     int unit,
   8345     soc_mem_t mem,
   8346     uint32 index,
   8347     void *entry,
   8348     void *user_data,
   8349     uint32 *dirty)
   8350 {
   8351     uint32 pool;
   8352     uint32 offset_value;
   8353     uint32 meter_enable;
   8354     offset_table_entry_t  *offset_map = NULL;
   8355 
   8356     if (user_data != NULL) {
   8357         offset_map = (offset_table_entry_t *) user_data;
   8358     }
   8359 
   8360     if (offset_map == NULL) {
   8361         pool = 0;
   8362         offset_value = 0;
   8363         meter_enable = 0;
   8364     } else {
   8365         index %= BCM_POLICER_SVC_METER_MAX_OFFSET;
   8366         pool = offset_map[index].pool;
   8367         offset_value = offset_map[index].offset;
   8368         meter_enable = offset_map[index].meter_enable;
   8369     }
   8370     /* Set POOL_OFFSETf */
   8371     soc_mem_field_set(unit,
   8372             mem, entry, POOL_OFFSETf, &pool);
   8373     /* Set OFFSETf */
   8374     soc_mem_field_set(unit,
   8375             mem, entry, OFFSETf, &offset_value);
   8376     /* Set METER_ENABLEf */
   8377     soc_mem_field_set(unit,
   8378             mem, entry, METER_ENABLEf, &meter_enable);
   8379 
   8380     *dirty = TRUE;
   8381 
   8382     return BCM_E_NONE;
   8383 }
   8384 
   8385 /*
   8386  * Function:
   8387  *      _bcm_policer_svc_meter_update_offset_table
   8388  * Purpose:
   8389  *     Internal function to update the SVM offset table
   8390  * Parameters:
   8391  *     Unit                  - (IN) unit number
   8392  *     offset_table_mem      - (IN) Offset table memory
   8393  *     svc_meter_mode        - (IN) Meter offset mode
   8394  *     offset_map            - (IN) Offset table entry map
   8395  * Returns:
   8396  *     BCM_E_XXX
   8397  */
   8398 bcm_error_t _bcm_policer_svc_meter_update_offset_table(
   8399     int                                unit,
   8400     soc_mem_t                          offset_table_mem,
   8401     bcm_policer_svc_meter_mode_t       svc_meter_mode,
   8402     offset_table_entry_t  *offset_map)
   8403 {
   8404     uint32            start_idx = 0;
   8405     uint32            end_idx = 0;
   8406     uint32            offset_table_entry = 0;
   8407     uint32            index = 0;
   8408     uint32            zero = 0;
   8409     uint32            meter_enable = 0;
   8410     if (offset_table_mem != SVM_OFFSET_TABLEm) {
   8411         /* Valid mem value go ahead for setting SVM_OFFSET_TABLEm */
   8412         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8413                   (BSL_META_U(unit,
   8414                               "Invalid table specified \n")));
   8415         return BCM_E_PARAM;
   8416     }
   8417     start_idx = (svc_meter_mode <<
   8418             BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE);
   8419     end_idx = start_idx + BCM_POLICER_SVC_METER_MAX_OFFSET - 1;
   8420 
   8421     BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   8422             offset_table_mem, start_idx, end_idx,
   8423             _bcm_esw_svm_offset_table_map_set, offset_map));
   8424 
   8425     if(svc_meter_mode == 0) {
   8426         index = 0;
   8427         meter_enable  = 1;
   8428         /*  SVM_OFFSET_TABLE_?m value */
   8429         SOC_IF_ERROR_RETURN(soc_mem_read(unit,
   8430             offset_table_mem,
   8431             MEM_BLOCK_ANY,
   8432             ((svc_meter_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE)),
   8433             &offset_table_entry));
   8434         /* Set OFFSETf */
   8435         soc_mem_field_set(
   8436             unit,
   8437             offset_table_mem,
   8438             &offset_table_entry,
   8439             OFFSETf,
   8440             &zero);
   8441        /* Set METER_ENABLEf */
   8442         soc_mem_field_set(
   8443             unit,
   8444             offset_table_mem,
   8445             &offset_table_entry,
   8446             METER_ENABLEf,
   8447             &meter_enable);
   8448         /* Finally set value for ING_SVM_OFFSET_TABLE_?m?r */
   8449         SOC_IF_ERROR_RETURN(soc_mem_write(unit,
   8450             offset_table_mem,
   8451             MEM_BLOCK_ALL,
   8452             ((svc_meter_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) | index),
   8453             &offset_table_entry));
   8454     }
   8455     return BCM_E_NONE;
   8456 }
   8457 
   8458 /*
   8459  * Function:
   8460  *      _bcm_policer_svc_meter_update_selector_keys_enable_fields
   8461  * Purpose:
   8462  *     Internal function to set selector key enabled fields
   8463  * Parameters:
   8464  *     Unit                  - (IN) unit number
   8465  *     pkt_attr_selector_key - (IN) Pkt attribute selector key
   8466  *     pkt_attr_selector_key_value - (IN) Value of selector key
   8467  *     pkt_attr_bit_position - (IN) Packet attribute bit position
   8468  *     pkt_attr_total_bits   - (IN) total number of packet attribute bits
   8469  *     current_bit_selector_position - (IN) Current bit position
   8470  * Returns:
   8471  *     BCM_E_XXX
   8472  */
   8473 bcm_error_t _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   8474     int         unit,
   8475     soc_reg_t   pkt_attr_selector_key,
   8476     uint64      *pkt_attr_selector_key_value,
   8477     uint32      pkt_attr_bit_position,
   8478     uint32      pkt_attr_total_bits,
   8479     uint8       pkt_attr_field_mask_v,
   8480     uint8       *current_bit_selector_position)
   8481 {
   8482     uint32    index = 0;
   8483     uint32    total_field_bits = 0;
   8484     uint32    field_index[8] = {0};
   8485     uint32    selector_x_en_field_name[8]= {
   8486         SELECTOR_0_ENf,
   8487         SELECTOR_1_ENf,
   8488         SELECTOR_2_ENf,
   8489         SELECTOR_3_ENf,
   8490         SELECTOR_4_ENf,
   8491         SELECTOR_5_ENf,
   8492         SELECTOR_6_ENf,
   8493         SELECTOR_7_ENf,
   8494     };
   8495     uint32    selector_for_bit_x_field_name[8]={
   8496         SELECTOR_FOR_BIT_0f,
   8497         SELECTOR_FOR_BIT_1f,
   8498         SELECTOR_FOR_BIT_2f,
   8499         SELECTOR_FOR_BIT_3f,
   8500         SELECTOR_FOR_BIT_4f,
   8501         SELECTOR_FOR_BIT_5f,
   8502         SELECTOR_FOR_BIT_6f,
   8503         SELECTOR_FOR_BIT_7f,
   8504     };
   8505 
   8506     if ((*current_bit_selector_position) +
   8507         pkt_attr_total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
   8508         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8509                   (BSL_META_U(unit,
   8510                               "Number of slector bits exceeds max allowed \n")));
   8511         return BCM_E_INTERNAL;
   8512     }
   8513 
   8514     for (index = 0; index < 8 ; index++) {
   8515         if (pkt_attr_field_mask_v & 0x1) {
   8516             field_index[total_field_bits] = index;
   8517             total_field_bits++;
   8518         }
   8519         pkt_attr_field_mask_v >>= 1;
   8520     }
   8521 
   8522     if (total_field_bits != pkt_attr_total_bits ) {
   8523         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   8524                   (BSL_META_U(unit, "Total bits exceeding not"
   8525                                     " matching with mask bits \n")));
   8526         return BCM_E_INTERNAL;
   8527     }
   8528 
   8529     for (index = 0; index < pkt_attr_total_bits; index++) {
   8530         soc_reg64_field32_set(
   8531             unit,
   8532             pkt_attr_selector_key,
   8533             pkt_attr_selector_key_value,
   8534             selector_x_en_field_name[*current_bit_selector_position],
   8535             1);
   8536         soc_reg64_field32_set(
   8537             unit,
   8538             pkt_attr_selector_key,
   8539             pkt_attr_selector_key_value,
   8540             selector_for_bit_x_field_name[*current_bit_selector_position],
   8541             pkt_attr_bit_position + field_index[index]);
   8542         (*current_bit_selector_position) += 1;
   8543     }
   8544     return BCM_E_NONE;
   8545 }
   8546 
   8547 /*
   8548  * Function:
   8549  *      bcm_policer_svc_meter_dec_mode_reference_count
   8550  * Purpose:
   8551  *     Internal function to decrement meter offset mode usage count
   8552  * Parameters:
   8553  *     Unit                  - (IN) unit number
   8554  *     svc_meter_mode        - (IN) Meter offset mode
   8555  * Returns:
   8556  *     BCM_E_XXX
   8557  */
   8558 bcm_error_t bcm_policer_svc_meter_dec_mode_reference_count(
   8559     uint32 unit,
   8560     bcm_policer_svc_meter_mode_t svc_meter_mode)
   8561 {
   8562     int rv = BCM_E_NONE;
   8563     if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) {
   8564         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8565                   (BSL_META_U(unit,
   8566                               "Wrong offset mode specified \n")));
   8567         return BCM_E_PARAM;
   8568     }
   8569     if ( global_meter_offset_mode[unit][svc_meter_mode].reference_count > 0) {
   8570        global_meter_offset_mode[unit][svc_meter_mode].reference_count--;
   8571     }
   8572     if (global_meter_offset_mode[unit][svc_meter_mode].type != -1) {
   8573         /* Deletion of the mode is done through
   8574            bcm_policer_group_mode_id_destroy */
   8575         return rv;
   8576     }
   8577     if (global_meter_offset_mode[unit][svc_meter_mode].reference_count == 0) {
   8578         rv = _bcm_esw_policer_svc_meter_delete_mode(unit, svc_meter_mode);
   8579     }
   8580     return rv;
   8581 }
   8582 
   8583 /*
   8584  * Function:
   8585  *      bcm_policer_svc_meter_inc_mode_reference_count
   8586  * Purpose:
   8587  *     Internal function to increment meter offset mode usage count
   8588  * Parameters:
   8589  *     Unit                  - (IN) unit number
   8590  *     svc_meter_mode        - (IN) Meter offset mode
   8591  * Returns:
   8592  *     BCM_E_XXX
   8593  */
   8594 bcm_error_t bcm_policer_svc_meter_inc_mode_reference_count(
   8595     uint32 unit,
   8596     bcm_policer_svc_meter_mode_t svc_meter_mode)
   8597 {
   8598     if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) {
   8599         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8600                   (BSL_META("Wrong offset mode specified \n")));
   8601         return BCM_E_PARAM;
   8602     }
   8603     global_meter_offset_mode[unit][svc_meter_mode].reference_count++;
   8604     return BCM_E_NONE;
   8605 }
   8606 
   8607 /*
   8608  * Function:
   8609  *      _bcm_policer_svc_meter_reserve_mode
   8610  * Purpose:
   8611  *     Internal function to allocate/reserve meter offset mode
   8612  * Parameters:
   8613  *     Unit                  - (IN) unit number
   8614  *     svc_meter_mode        - (IN) Meter offset mode
   8615  *     total_bits            - (IN) Total number of bits used
   8616  *     group_mode            - (IN) Policer group mode
   8617  *     meter_attr            - (IN) Meter attributes
   8618  * Returns:
   8619  *     BCM_E_XXX
   8620  */
   8621 bcm_error_t _bcm_policer_svc_meter_reserve_mode(
   8622     uint32                               unit,
   8623     bcm_policer_svc_meter_mode_t         svc_meter_mode,
   8624     bcm_policer_group_mode_t             group_mode,
   8625     bcm_policer_svc_meter_attr_t         *meter_attr)
   8626 {
   8627     if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) {
   8628         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8629                   (BSL_META("Wrong offset mode specified \n")));
   8630         return BCM_E_PARAM;
   8631     }
   8632     global_meter_offset_mode[unit][svc_meter_mode].used = 1;
   8633     global_meter_offset_mode[unit][svc_meter_mode].group_mode = group_mode;
   8634     global_meter_offset_mode[unit][svc_meter_mode].type = -1;
   8635     global_meter_offset_mode[unit][svc_meter_mode].meter_attr = *meter_attr;
   8636     return BCM_E_NONE;
   8637 }
   8638 
   8639 /*
   8640  * Function:
   8641  *      _bcm_esw_svm_pkt_compressed_attr_maps_remove
   8642  * Purpose:
   8643  *     Internal function to decrement reference count of required maps and
   8644  *     remove hardware table content if reference count becomes 0.
   8645  * Parameters:
   8646  *     Unit                  - (IN) unit number
   8647  *     compressed_attr_selectors_v - (IN) compressed attribute selectors.
   8648  * Returns:
   8649  *     BCM_E_XXX
   8650  */
   8651 STATIC
   8652 int _bcm_esw_svm_pkt_compressed_attr_maps_remove(
   8653     int unit,
   8654     compressed_attr_selectors_t *compressed_attr_selectors_v)
   8655 {
   8656     int rv = BCM_E_NONE;
   8657     uint8 *map_ref_count = NULL;
   8658     pkt_attr_bits_t *pkt_attr_bits_v = NULL;
   8659     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
   8660 
   8661     pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v;
   8662 
   8663     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
   8664 
   8665     if (cmprsd_attr_maps == NULL) {
   8666         return BCM_E_NONE;
   8667     }
   8668 
   8669     if ((pkt_attr_bits_v->cng != 0) ||
   8670         (pkt_attr_bits_v->int_pri != 0) ||
   8671         (pkt_attr_bits_v->short_int_pri != 0)) {
   8672         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map];
   8673         (*map_ref_count)--;
   8674         if (*map_ref_count == 0) {
   8675             SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   8676                         ING_SVM_PRI_CNG_MAPm, MEM_BLOCK_ALL, TRUE));
   8677             cmprsd_attr_maps->cng = 0;
   8678             cmprsd_attr_maps->int_pri = 0;
   8679             cmprsd_attr_maps->combine_cng_flags = 0;
   8680             cmprsd_attr_maps->combine_int_pri_flags = 0;
   8681         }
   8682     }
   8683     if ((pkt_attr_bits_v->vlan_format != 0) ||
   8684         (pkt_attr_bits_v->outer_dot1p != 0) ||
   8685         (pkt_attr_bits_v->inner_dot1p != 0)) {
   8686         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map];
   8687         (*map_ref_count)--;
   8688         if (*map_ref_count == 0) {
   8689             SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   8690                         ING_SVM_PKT_PRI_MAPm, MEM_BLOCK_ALL, TRUE));
   8691             cmprsd_attr_maps->vlan_format = 0;
   8692             cmprsd_attr_maps->outer_dot1p = 0;
   8693             cmprsd_attr_maps->inner_dot1p = 0;
   8694             cmprsd_attr_maps->combine_vlan_format_flags = 0;
   8695             cmprsd_attr_maps->combine_outer_dot1p_flags = 0;
   8696             cmprsd_attr_maps->combine_inner_dot1p_flags = 0;
   8697         }
   8698     }
   8699     if (pkt_attr_bits_v->ing_port != 0) {
   8700         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_port_map];
   8701         (*map_ref_count)--;
   8702         if (*map_ref_count == 0) {
   8703             SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   8704                         ING_SVM_PORT_MAPm, MEM_BLOCK_ALL, TRUE));
   8705             cmprsd_attr_maps->port = 0;
   8706             sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrPort],
   8707                         0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
   8708         }
   8709     }
   8710     if ((pkt_attr_bits_v->tos != 0) ||
   8711             (pkt_attr_bits_v->tos_ecn != 0)) {
   8712         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_tos_map];
   8713         (*map_ref_count)--;
   8714         if (*map_ref_count == 0) {
   8715             SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   8716                         ING_SVM_TOS_MAPm, MEM_BLOCK_ALL, TRUE));
   8717             cmprsd_attr_maps->tos_dscp = 0;
   8718             cmprsd_attr_maps->tos_ecn = 0;
   8719             sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosDscp],
   8720                         0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
   8721             sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosEcn],
   8722                         0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
   8723         }
   8724     }
   8725     if ((pkt_attr_bits_v->pkt_resolution != 0) ||
   8726         (pkt_attr_bits_v->svp_type != 0) ||
   8727         (pkt_attr_bits_v->drop != 0)) {
   8728         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map];
   8729         (*map_ref_count)--;
   8730         if (*map_ref_count == 0) {
   8731             SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   8732                         ING_SVM_PKT_RES_MAPm, MEM_BLOCK_ALL, TRUE));
   8733             cmprsd_attr_maps->pkt_resolution = 0;
   8734             cmprsd_attr_maps->svp_type = 0;
   8735             cmprsd_attr_maps->drop = 0;
   8736             cmprsd_attr_maps->combine_pkt_res_flags = 0;
   8737             cmprsd_attr_maps->combine_drop_flags = 0;
   8738             sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrSvpType],
   8739                         0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
   8740         }
   8741     }
   8742 
   8743     return rv;
   8744 }
   8745 
   8746 /*
   8747  * Function:
   8748  *      _bcm_policer_svc_meter_unreserve_mode
   8749  * Purpose:
   8750  *     Internal function to unreserve meter offset mode
   8751  * Parameters:
   8752  *     Unit                  - (IN) unit number
   8753  *     svc_meter_mode        - (IN) Meter offset mode
   8754  * Returns:
   8755  *     BCM_E_XXX
   8756  */
   8757 bcm_error_t _bcm_policer_svc_meter_unreserve_mode(
   8758     uint32                                  unit,
   8759     bcm_policer_svc_meter_mode_t            svc_meter_mode)
   8760 {
   8761     uint64    pkt_attr_selector_key_value;
   8762     bcm_policer_svc_meter_mode_type_t       mode_type_v;
   8763     compressed_attr_selectors_t  *compressed_attr_selectors_v = NULL;
   8764 
   8765     COMPILER_64_ZERO(pkt_attr_selector_key_value);
   8766     if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) {
   8767         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8768                   (BSL_META_U(unit,
   8769                               "Wrong offset mode specified \n")));
   8770         return BCM_E_PARAM;
   8771     }
   8772     if ( global_meter_offset_mode[unit][svc_meter_mode].used == 0) {
   8773         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8774                   (BSL_META_U(unit,
   8775                               "Wrong offset mode: Mode is not in use\n")));
   8776         return BCM_E_NOT_FOUND;
   8777     }
   8778     if ( global_meter_offset_mode[unit][svc_meter_mode].reference_count != 0) {
   8779         LOG_DEBUG(BSL_LS_BCM_POLICER,
   8780                   (BSL_META_U(unit,
   8781                               "Mode is still in use\n")));
   8782         return BCM_E_INTERNAL;
   8783     }
   8784 
   8785     /* Step1:  Reset selector keys */
   8786     SOC_IF_ERROR_RETURN(soc_reg_set(unit,
   8787         _pkt_attr_sel_key_reg[svc_meter_mode],
   8788         REG_PORT_ANY,
   8789         0,
   8790         pkt_attr_selector_key_value));
   8791 
   8792      /* Step2: Reset Offset table filling */
   8793     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
   8794         SVM_OFFSET_TABLEm,
   8795         svc_meter_mode,
   8796         NULL));
   8797     /* Step3: Cleanup based on mode */
   8798     mode_type_v = global_meter_offset_mode[unit][svc_meter_mode].\
   8799                                                     meter_attr.mode_type_v;
   8800     switch (mode_type_v) {
   8801        case uncompressed_mode:
   8802            break;
   8803        case udf_mode:
   8804            break;
   8805        case cascade_mode:
   8806            break;
   8807        case compressed_mode:
   8808        {
   8809            compressed_attr_selectors_v =
   8810                &global_meter_offset_mode[unit][svc_meter_mode].\
   8811                meter_attr.compressed_attr_selectors_v;
   8812            BCM_IF_ERROR_RETURN(_bcm_esw_svm_pkt_compressed_attr_maps_remove(
   8813                        unit, compressed_attr_selectors_v));
   8814            break;
   8815        }
   8816        case udf_cascade_mode:
   8817        case udf_cascade_with_coupling_mode:
   8818            break;
   8819        default:
   8820            LOG_DEBUG(BSL_LS_BCM_POLICER,
   8821                      (BSL_META_U(unit,
   8822                                  "Invalid offset mode\n")));
   8823            return BCM_E_PARAM;
   8824     }
   8825     /* attr_selectors is allocated memory when mode_id is created explicitly
   8826      * via _mode_id_create() API. This is the best place to free this
   8827      * memory as after this call mode is set to un-used and can be reused */
   8828     if (global_meter_offset_mode[unit][svc_meter_mode].attr_selectors != NULL) {
   8829         sal_free (global_meter_offset_mode[unit][svc_meter_mode].attr_selectors);
   8830         global_meter_offset_mode[unit][svc_meter_mode].attr_selectors = NULL;
   8831     }
   8832     sal_memset (&global_meter_offset_mode[unit][svc_meter_mode], 0,
   8833             sizeof(global_meter_offset_mode[unit][svc_meter_mode]));
   8834 
   8835     global_meter_offset_mode[unit][svc_meter_mode].used = 0;
   8836 
   8837     return BCM_E_NONE;
   8838 }
   8839 
   8840 /*
   8841  * Function:
   8842  *      _bcm_policer_svc_meter_get_available_mode
   8843  * Purpose:
   8844  *      Internal function to get a free meter offset table entry
   8845  * Parameters:
   8846  *     Unit                  - (IN) unit number
   8847  *     svc_meter_mode        - (IN) Meter offset mode
   8848  * Returns:
   8849  *     BCM_E_XXX
   8850  */
   8851 bcm_error_t _bcm_policer_svc_meter_get_available_mode(uint32 unit,
   8852     bcm_policer_svc_meter_mode_t        *svc_meter_mode)
   8853 {
   8854     uint32    mode_index = 1;
   8855     for (; mode_index < BCM_POLICER_SVC_METER_MAX_MODE; mode_index++) {
   8856         if (global_meter_offset_mode[unit][mode_index].used == 0) {
   8857             *svc_meter_mode = mode_index;
   8858             return BCM_E_NONE;
   8859         }
   8860     }
   8861     return BCM_E_FULL;
   8862 }
   8863 
   8864 typedef enum pkt_attrs_e {
   8865     pkt_attr_ip_pkt,
   8866     pkt_attr_drop,
   8867     pkt_attr_svp_group,
   8868     pkt_attr_pkt_resolution,
   8869     pkt_attr_tos,
   8870     pkt_attr_ing_port,
   8871     pkt_attr_inner_dot1p,
   8872     pkt_attr_outer_dot1p,
   8873     pkt_attr_vlan_format,
   8874     pkt_attr_int_pri,
   8875     pkt_attr_cng,
   8876     pkt_attr_short_int_pri,
   8877     pkt_attr_tos_ecn,
   8878     pkt_attr_count
   8879 } pkt_attrs_t;
   8880 
   8881 static _bcm_policer_pkt_attr_bit_pos_t  kt_pkt_attr_bit_pos[pkt_attr_count] =  {
   8882                                        {0, 0}, {1, 1}, {2, 2}, {3, 8},
   8883                                        {11,16}, {17,22}, {23,25}, {26,28},
   8884                                        {29,30}, {31,34}, {35,36}, {31,33},
   8885                                        {9,10}
   8886                                   };
   8887 #ifdef BCM_KATANA2_SUPPORT
   8888 static _bcm_policer_pkt_attr_bit_pos_t kt2_pkt_attr_bit_pos[pkt_attr_count] =  {
   8889                                        {0, 0}, {1, 1}, {2, 4}, {5, 10},
   8890                                        {13,18}, {19, 26}, {27, 29}, {30,32},
   8891                                        {33,34}, {35,38}, {39, 40}, {35,37},
   8892                                        {11,12}
   8893                                   };
   8894 static _bcm_policer_pkt_attr_bit_pos_t kt2_cmprsd_pkt_attr_bit_pos[pkt_attr_count] =  {
   8895                                        {0, 0}, {1, 1}, {2, 4}, {5, 8},
   8896                                        {11,16}, {17, 24}, {25, 27}, {28,30},
   8897                                        {31,32}, {33,36}, {37, 38}, {33,35},
   8898                                        {9,10}
   8899                                   };
   8900 #endif
   8901 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_SABER2_SUPPORT)
   8902 static _bcm_policer_pkt_attr_bit_pos_t sb2_pkt_attr_bit_pos[pkt_attr_count] =  {
   8903                                        {0, 0}, {1, 1}, {2, 4}, {5, 10},
   8904                                        {13,18}, {19, 25}, {27, 29}, {30,32},
   8905                                        {33,34}, {35,38}, {39, 40}, {35,37},
   8906                                        {11,12}
   8907                                   };
   8908 static _bcm_policer_pkt_attr_bit_pos_t sb2_cmprsd_pkt_attr_bit_pos[pkt_attr_count] =  {
   8909                                        {0, 0}, {1, 1}, {2, 4}, {5, 8},
   8910                                        {11,16}, {17, 23}, {24, 26}, {27,29},
   8911                                        {30,31}, {32,35}, {36, 37}, {32,34},
   8912                                        {9,10}
   8913                                   };
   8914 #endif
   8915 
   8916 /*
   8917  * Function:
   8918  *      _bcm_policer_svc_meter_update_selector_keys
   8919  * Purpose:
   8920  *      Update the selector keys
   8921  * Parameters:
   8922  *     Unit                  - (IN) unit number
   8923  *     mode_type_v           - (IN) Meter offset mode
   8924  *     pkt_attr_selector_key - (IN) Selector key
   8925  *     pkt_attr_bits_v       - (IN) Packet attribute bits
   8926  * Returns:
   8927  *     BCM_E_XXX
   8928  */
   8929 bcm_error_t _bcm_policer_svc_meter_update_selector_keys(
   8930     int                unit,
   8931     bcm_policer_svc_meter_mode_type_t    mode_type_v,
   8932     int8               type,
   8933     soc_reg_t          pkt_attr_selector_key,
   8934     pkt_attr_bits_t    pkt_attr_bits_v)
   8935 {
   8936     uint64   pkt_attr_selector_key_value;
   8937     uint8    current_bit_position=0;
   8938     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
   8939 
   8940     pkt_attr_bit_pos  =
   8941             BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos;
   8942 
   8943     COMPILER_64_ZERO(pkt_attr_selector_key_value);
   8944     if (!((pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) &&
   8945           (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r))) {
   8946             LOG_DEBUG(BSL_LS_BCM_POLICER,
   8947                       (BSL_META_U(unit,
   8948                                   "Invalid Key for packet attribute selector\n")));
   8949             return BCM_E_PARAM;
   8950     }
   8951     /* BCM_POLICER_SVC_METER_UDF_MODE not supported here */
   8952     if (!((mode_type_v == uncompressed_mode) ||
   8953           (mode_type_v == compressed_mode))) {
   8954             LOG_DEBUG(BSL_LS_BCM_POLICER,
   8955                       (BSL_META_U(unit,
   8956                                   "UDF mode not supported \n")));
   8957             return BCM_E_PARAM;
   8958     }
   8959 
   8960     /*
   8961      * Set bit position and mask for packet attruibutes for
   8962      * implicit mode Id and explicit mode Id for uncompressed case.
   8963      */
   8964     if ((type == -1) || (mode_type_v == uncompressed_mode)) {
   8965         pkt_attr_bits_v.ip_pkt_pos =
   8966             pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit;
   8967         pkt_attr_bits_v.ip_pkt_mask =
   8968             (1 << pkt_attr_bits_v.ip_pkt) - 1;
   8969         pkt_attr_bits_v.drop_pos =
   8970             pkt_attr_bit_pos[pkt_attr_drop].start_bit;
   8971         pkt_attr_bits_v.drop_mask =
   8972             (1 << pkt_attr_bits_v.drop) - 1;
   8973         pkt_attr_bits_v.svp_type_pos =
   8974             pkt_attr_bit_pos[pkt_attr_svp_group].start_bit;
   8975         pkt_attr_bits_v.svp_type_mask =
   8976             (1 << pkt_attr_bits_v.svp_type) - 1;
   8977         pkt_attr_bits_v.pkt_res_pos =
   8978             pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit;
   8979         pkt_attr_bits_v.pkt_res_mask =
   8980             (1 << pkt_attr_bits_v.pkt_resolution) - 1;
   8981         pkt_attr_bits_v.tos_ecn_pos =
   8982             pkt_attr_bit_pos[pkt_attr_tos_ecn].start_bit;
   8983         pkt_attr_bits_v.tos_ecn_mask =
   8984             (1 << pkt_attr_bits_v.tos_ecn) - 1;
   8985         pkt_attr_bits_v.tos_pos =
   8986             pkt_attr_bit_pos[pkt_attr_tos].start_bit;
   8987         pkt_attr_bits_v.tos_mask =
   8988             (1 << pkt_attr_bits_v.tos) - 1;
   8989         pkt_attr_bits_v.ing_port_pos =
   8990             pkt_attr_bit_pos[pkt_attr_ing_port].start_bit;
   8991         pkt_attr_bits_v.ing_port_mask =
   8992             (1 << pkt_attr_bits_v.ing_port) - 1;
   8993         pkt_attr_bits_v.inner_dot1p_pos =
   8994             pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit;
   8995         pkt_attr_bits_v.inner_dot1p_mask =
   8996             (1 << pkt_attr_bits_v.inner_dot1p) - 1;
   8997         pkt_attr_bits_v.outer_dot1p_pos =
   8998             pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit;
   8999         pkt_attr_bits_v.outer_dot1p_mask =
   9000             (1 << pkt_attr_bits_v.outer_dot1p) - 1;
   9001         pkt_attr_bits_v.vlan_format_pos =
   9002             pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit;
   9003         pkt_attr_bits_v.vlan_format_mask =
   9004             (1 << pkt_attr_bits_v.vlan_format) - 1;
   9005         if (mode_type_v == compressed_mode) {
   9006             pkt_attr_bits_v.int_pri_pos =
   9007                 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos;
   9008         } else {
   9009             pkt_attr_bits_v.int_pri_pos =
   9010                 pkt_attr_bit_pos[pkt_attr_int_pri].start_bit;
   9011         }
   9012         pkt_attr_bits_v.int_pri_mask =
   9013             (1 << pkt_attr_bits_v.int_pri) - 1;
   9014         pkt_attr_bits_v.cng_pos =
   9015             pkt_attr_bit_pos[pkt_attr_cng].start_bit;
   9016         pkt_attr_bits_v.cng_mask =
   9017             (1 << pkt_attr_bits_v.cng) - 1;
   9018         pkt_attr_bits_v.short_int_pri_pos =
   9019             pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit;
   9020         pkt_attr_bits_v.short_int_pri_mask =
   9021             (1 << pkt_attr_bits_v.short_int_pri) - 1;
   9022     }
   9023 
   9024     /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */
   9025     SOC_IF_ERROR_RETURN(soc_reg_get(unit,
   9026             pkt_attr_selector_key,
   9027             REG_PORT_ANY,
   9028             0,
   9029             &pkt_attr_selector_key_value));
   9030 
   9031     /* Next set field value for
   9032                  ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/
   9033     soc_reg64_field32_set(
   9034             unit,
   9035             pkt_attr_selector_key,
   9036             &pkt_attr_selector_key_value,
   9037             USER_SPECIFIED_UDF_VALIDf,
   9038             0);
   9039     soc_reg64_field32_set(
   9040             unit,
   9041             pkt_attr_selector_key,
   9042             &pkt_attr_selector_key_value,
   9043             USE_UDF_KEYf,
   9044             0);
   9045     if (mode_type_v == compressed_mode) {
   9046         soc_reg64_field32_set(
   9047             unit,
   9048             pkt_attr_selector_key,
   9049             &pkt_attr_selector_key_value,
   9050             USE_COMPRESSED_PKT_KEYf,
   9051             1);
   9052     } else {
   9053         soc_reg64_field32_set(
   9054             unit,
   9055             pkt_attr_selector_key,
   9056             &pkt_attr_selector_key_value,
   9057             USE_COMPRESSED_PKT_KEYf,
   9058             0);
   9059     }
   9060     if (pkt_attr_bits_v.ip_pkt != 0) {
   9061         BCM_IF_ERROR_RETURN(
   9062           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9063             unit,
   9064             pkt_attr_selector_key,
   9065             &pkt_attr_selector_key_value,
   9066             pkt_attr_bits_v.ip_pkt_pos,
   9067             pkt_attr_bits_v.ip_pkt,
   9068             pkt_attr_bits_v.ip_pkt_mask,
   9069             &current_bit_position));
   9070     }
   9071     if (pkt_attr_bits_v.drop != 0) {
   9072         BCM_IF_ERROR_RETURN(
   9073           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9074             unit,
   9075             pkt_attr_selector_key,
   9076             &pkt_attr_selector_key_value,
   9077             pkt_attr_bits_v.drop_pos,
   9078             pkt_attr_bits_v.drop,
   9079             pkt_attr_bits_v.drop_mask,
   9080             &current_bit_position));
   9081     }
   9082     if (pkt_attr_bits_v.svp_type != 0) {
   9083         BCM_IF_ERROR_RETURN(
   9084           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9085             unit,
   9086             pkt_attr_selector_key,
   9087             &pkt_attr_selector_key_value,
   9088             pkt_attr_bits_v.svp_type_pos,
   9089             pkt_attr_bits_v.svp_type,
   9090             pkt_attr_bits_v.svp_type_mask,
   9091             &current_bit_position));
   9092     }
   9093     if (pkt_attr_bits_v.pkt_resolution != 0) {
   9094         BCM_IF_ERROR_RETURN(
   9095           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9096             unit,
   9097             pkt_attr_selector_key,
   9098             &pkt_attr_selector_key_value,
   9099             pkt_attr_bits_v.pkt_res_pos,
   9100             pkt_attr_bits_v.pkt_resolution,
   9101             pkt_attr_bits_v.pkt_res_mask,
   9102             &current_bit_position));
   9103     }
   9104     if (pkt_attr_bits_v.tos_ecn != 0) {
   9105         BCM_IF_ERROR_RETURN(
   9106           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9107             unit,
   9108             pkt_attr_selector_key,
   9109             &pkt_attr_selector_key_value,
   9110             pkt_attr_bits_v.tos_ecn_pos,
   9111             pkt_attr_bits_v.tos_ecn,
   9112             pkt_attr_bits_v.tos_ecn_mask,
   9113             &current_bit_position));
   9114     }
   9115     if (pkt_attr_bits_v.tos != 0) {
   9116         BCM_IF_ERROR_RETURN(
   9117           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9118             unit,
   9119             pkt_attr_selector_key,
   9120             &pkt_attr_selector_key_value,
   9121             pkt_attr_bits_v.tos_pos,
   9122             pkt_attr_bits_v.tos,
   9123             pkt_attr_bits_v.tos_mask,
   9124             &current_bit_position));
   9125     }
   9126     if (pkt_attr_bits_v.ing_port != 0) {
   9127         BCM_IF_ERROR_RETURN(
   9128           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9129             unit,
   9130             pkt_attr_selector_key,
   9131             &pkt_attr_selector_key_value,
   9132             pkt_attr_bits_v.ing_port_pos,
   9133             pkt_attr_bits_v.ing_port,
   9134             pkt_attr_bits_v.ing_port_mask,
   9135             &current_bit_position));
   9136     }
   9137     if (pkt_attr_bits_v.inner_dot1p != 0) {
   9138         BCM_IF_ERROR_RETURN(
   9139           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9140             unit,
   9141             pkt_attr_selector_key,
   9142             &pkt_attr_selector_key_value,
   9143             pkt_attr_bits_v.inner_dot1p_pos,
   9144             pkt_attr_bits_v.inner_dot1p,
   9145             pkt_attr_bits_v.inner_dot1p_mask,
   9146             &current_bit_position));
   9147     }
   9148     if (pkt_attr_bits_v.outer_dot1p != 0) {
   9149         BCM_IF_ERROR_RETURN(
   9150           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9151             unit,
   9152             pkt_attr_selector_key,
   9153             &pkt_attr_selector_key_value,
   9154             pkt_attr_bits_v.outer_dot1p_pos,
   9155             pkt_attr_bits_v.outer_dot1p,
   9156             pkt_attr_bits_v.outer_dot1p_mask,
   9157             &current_bit_position));
   9158     }
   9159     if (pkt_attr_bits_v.vlan_format != 0) {
   9160         BCM_IF_ERROR_RETURN(
   9161           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9162             unit,
   9163             pkt_attr_selector_key,
   9164             &pkt_attr_selector_key_value,
   9165             pkt_attr_bits_v.vlan_format_pos,
   9166             pkt_attr_bits_v.vlan_format,
   9167             pkt_attr_bits_v.vlan_format_mask,
   9168             &current_bit_position));
   9169     }
   9170     if (pkt_attr_bits_v.int_pri != 0) {
   9171         BCM_IF_ERROR_RETURN(
   9172           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9173             unit,
   9174             pkt_attr_selector_key,
   9175             &pkt_attr_selector_key_value,
   9176             pkt_attr_bits_v.int_pri_pos,
   9177             pkt_attr_bits_v.int_pri,
   9178             pkt_attr_bits_v.int_pri_mask,
   9179             &current_bit_position));
   9180     }
   9181     if (pkt_attr_bits_v.cng != 0) {
   9182         BCM_IF_ERROR_RETURN(
   9183           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9184             unit,
   9185             pkt_attr_selector_key,
   9186             &pkt_attr_selector_key_value,
   9187             pkt_attr_bits_v.cng_pos,
   9188             pkt_attr_bits_v.cng,
   9189             pkt_attr_bits_v.cng_mask,
   9190             &current_bit_position));
   9191     }
   9192     if (pkt_attr_bits_v.short_int_pri != 0) {
   9193         BCM_IF_ERROR_RETURN(
   9194           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9195             unit,
   9196             pkt_attr_selector_key,
   9197             &pkt_attr_selector_key_value,
   9198             pkt_attr_bits_v.short_int_pri_pos,
   9199             pkt_attr_bits_v.short_int_pri,
   9200             pkt_attr_bits_v.short_int_pri_mask,
   9201             &current_bit_position));
   9202     }
   9203 
   9204     /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */
   9205     SOC_IF_ERROR_RETURN(soc_reg_set(unit,
   9206             pkt_attr_selector_key,
   9207             REG_PORT_ANY,
   9208             0,
   9209             pkt_attr_selector_key_value));
   9210     return BCM_E_NONE;
   9211 }
   9212 
   9213 /*
   9214  * Function:
   9215  *      _bcm_policer_svm_pkt_compressed_map_bits_get
   9216  * Purpose:
   9217  *      This internal function is used to get the number of
   9218  *      bits that can be output from the compression table.
   9219  * Parameters:
   9220  *     unit                  - (IN) unit number
   9221  *     pkt_attr              - (IN) packet attribute
   9222  * Returns:
   9223  *     Number of bits in compressed mode
   9224  */
   9225 
   9226 STATIC
   9227 int _bcm_policer_svm_pkt_compressed_map_bits_get(
   9228     int unit,
   9229     pkt_cmprsd_attrs_map_t attr_map)
   9230 {
   9231     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
   9232 
   9233     pkt_attr_bit_pos =
   9234             BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos;
   9235 
   9236     return (pkt_attr_bit_pos[attr_map].end_bit -
   9237             pkt_attr_bit_pos[attr_map].start_bit + 1);
   9238 }
   9239 
   9240 
   9241 /*
   9242  * Function:
   9243  *      _bcm_policer_svc_meter_update_selector_keys2
   9244  * Purpose:
   9245  *      Update the selector keys for compressed mode
   9246  *      taking H/w map format in account
   9247  * Parameters:
   9248  *     Unit                  - (IN) unit number
   9249  *     mode_type_v           - (IN) Meter offset mode
   9250  *     pkt_attr_selector_key - (IN) Selector key
   9251  *     pkt_attr_bits_v       - (IN) Packet attribute bits
   9252  * Returns:
   9253  *     BCM_E_XXX
   9254  */
   9255 bcm_error_t _bcm_policer_svc_meter_update_selector_keys2(
   9256     int           unit,
   9257     bcm_policer_svc_meter_mode_type_t    mode_type_v,
   9258     soc_reg_t          pkt_attr_selector_key,
   9259     pkt_attr_bits_t    pkt_attr_bits_v)
   9260 {
   9261     uint64   pkt_attr_selector_key_value;
   9262     uint8    current_bit_position=0;
   9263     uint8    mask = 0;
   9264     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_map_bit_pos = NULL;
   9265     uint32 total_bits_to_set = 0;
   9266 
   9267     pkt_attr_map_bit_pos =
   9268             BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos;
   9269 
   9270     COMPILER_64_ZERO(pkt_attr_selector_key_value);
   9271     if (!((pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) &&
   9272           (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r))) {
   9273             LOG_DEBUG(BSL_LS_BCM_POLICER,
   9274                       (BSL_META_U(unit,
   9275                                   "Invalid Key for packet attribute selector\n")));
   9276             return BCM_E_PARAM;
   9277     }
   9278     /* BCM_POLICER_SVC_METER_UDF_MODE not supported here */
   9279     if (!(mode_type_v == compressed_mode)) {
   9280             return BCM_E_PARAM;
   9281     }
   9282     /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */
   9283     SOC_IF_ERROR_RETURN(soc_reg_get(unit,
   9284             pkt_attr_selector_key,
   9285             REG_PORT_ANY,
   9286             0,
   9287             &pkt_attr_selector_key_value));
   9288 
   9289     /* Next set field value for
   9290                  ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/
   9291     soc_reg64_field32_set(
   9292             unit,
   9293             pkt_attr_selector_key,
   9294             &pkt_attr_selector_key_value,
   9295             USER_SPECIFIED_UDF_VALIDf,
   9296             0);
   9297     soc_reg64_field32_set(
   9298             unit,
   9299             pkt_attr_selector_key,
   9300             &pkt_attr_selector_key_value,
   9301             USE_UDF_KEYf,
   9302             0);
   9303     soc_reg64_field32_set(
   9304             unit,
   9305             pkt_attr_selector_key,
   9306             &pkt_attr_selector_key_value,
   9307             USE_COMPRESSED_PKT_KEYf,
   9308             1);
   9309 
   9310     if (pkt_attr_bits_v.ip_pkt != 0) {
   9311         BCM_IF_ERROR_RETURN(
   9312           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9313             unit,
   9314             pkt_attr_selector_key,
   9315             &pkt_attr_selector_key_value,
   9316             pkt_attr_map_bit_pos[pkt_attr_ip_pkt_map].start_bit,
   9317             pkt_attr_bits_v.ip_pkt,
   9318             1,
   9319             &current_bit_position));
   9320     }
   9321     if ((pkt_attr_bits_v.drop != 0) ||
   9322         (pkt_attr_bits_v.svp_type != 0) ||
   9323         (pkt_attr_bits_v.pkt_resolution != 0)) {
   9324         total_bits_to_set = pkt_attr_bits_v.drop +
   9325                             pkt_attr_bits_v.svp_type +
   9326                             pkt_attr_bits_v.pkt_resolution;
   9327         mask = (1 << total_bits_to_set) - 1;
   9328         BCM_IF_ERROR_RETURN(
   9329           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9330             unit,
   9331             pkt_attr_selector_key,
   9332             &pkt_attr_selector_key_value,
   9333             pkt_attr_map_bit_pos[pkt_attr_pkt_res_map].start_bit,
   9334             total_bits_to_set,
   9335             mask,
   9336             &current_bit_position));
   9337     }
   9338     if ((pkt_attr_bits_v.tos != 0) ||
   9339         (pkt_attr_bits_v.tos_ecn != 0)) {
   9340         total_bits_to_set = pkt_attr_bits_v.tos +
   9341                             pkt_attr_bits_v.tos_ecn;
   9342         mask = (1 << total_bits_to_set) - 1;
   9343         BCM_IF_ERROR_RETURN(
   9344            _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9345             unit,
   9346             pkt_attr_selector_key,
   9347             &pkt_attr_selector_key_value,
   9348             pkt_attr_map_bit_pos[pkt_attr_tos_map].start_bit,
   9349             total_bits_to_set,
   9350             mask,
   9351             &current_bit_position));
   9352     }
   9353     if (pkt_attr_bits_v.ing_port != 0) {
   9354         mask = (1 << pkt_attr_bits_v.ing_port) - 1;
   9355         BCM_IF_ERROR_RETURN(
   9356           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9357             unit,
   9358             pkt_attr_selector_key,
   9359             &pkt_attr_selector_key_value,
   9360             pkt_attr_map_bit_pos[pkt_attr_port_map].start_bit,
   9361             pkt_attr_bits_v.ing_port,
   9362             mask,
   9363             &current_bit_position));
   9364     }
   9365     if ((pkt_attr_bits_v.inner_dot1p != 0) ||
   9366         (pkt_attr_bits_v.outer_dot1p != 0) ||
   9367         (pkt_attr_bits_v.vlan_format != 0)) {
   9368         total_bits_to_set = pkt_attr_bits_v.inner_dot1p +
   9369                             pkt_attr_bits_v.outer_dot1p +
   9370                             pkt_attr_bits_v.vlan_format;
   9371         mask = (1 << total_bits_to_set) - 1;
   9372         BCM_IF_ERROR_RETURN(
   9373           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9374             unit,
   9375             pkt_attr_selector_key,
   9376             &pkt_attr_selector_key_value,
   9377             pkt_attr_map_bit_pos[pkt_attr_pkt_pri_map].start_bit,
   9378             total_bits_to_set,
   9379             mask,
   9380             &current_bit_position));
   9381     }
   9382     if ((pkt_attr_bits_v.int_pri != 0) ||
   9383         (pkt_attr_bits_v.cng != 0)) {
   9384         total_bits_to_set = pkt_attr_bits_v.int_pri + pkt_attr_bits_v.cng;
   9385         mask = (1 << total_bits_to_set) - 1;
   9386 
   9387         BCM_IF_ERROR_RETURN(
   9388           _bcm_policer_svc_meter_update_selector_keys_enable_fields(
   9389             unit,
   9390             pkt_attr_selector_key,
   9391             &pkt_attr_selector_key_value,
   9392             pkt_attr_map_bit_pos[pkt_attr_pri_cng_map].start_bit,
   9393             total_bits_to_set,
   9394             mask,
   9395             &current_bit_position));
   9396     }
   9397 
   9398     /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */
   9399     SOC_IF_ERROR_RETURN(soc_reg_set(unit,
   9400             pkt_attr_selector_key,
   9401             REG_PORT_ANY,
   9402             0,
   9403             pkt_attr_selector_key_value));
   9404     return BCM_E_NONE;
   9405 }
   9406 
   9407 /*
   9408  * Function:
   9409  *      _bcm_policer_svc_meter_create_cascade_mode
   9410  * Purpose:
   9411  *     Function to create an offset mode with uncompressed packet attributes
   9412  * Parameters:
   9413  *     Unit                  - (IN) unit number
   9414  *     uncompressed_attr_selectors_v - (IN) Packet attribute selectors
   9415  *     group_mode            - (IN) Policer group mode
   9416  *     num_pol               - (IN) Number of policers
   9417  *     svc_meter_mode        - (OUT) Allocated meter offset mode
   9418  *     total_bits            - (OUT) Total number of packet attribute bits
   9419  * Returns:
   9420  *     BCM_E_XXX
   9421  */
   9422 bcm_error_t _bcm_policer_svc_meter_create_cascade_mode(
   9423     int unit,
   9424     uncompressed_attr_selectors_t *uncompressed_attr_selectors_v,
   9425     bcm_policer_group_mode_t     group_mode,
   9426     int8                         type,
   9427     int                          num_pol,
   9428     bcm_policer_svc_meter_mode_t *svc_meter_mode)
   9429 {
   9430     bcm_error_t                         bcm_error_v = BCM_E_NONE;
   9431     bcm_policer_svc_meter_mode_t        bcm_policer_svc_meter_mode = 0;
   9432     pkt_attr_bits_t     pkt_attr_bits_v = {0};
   9433     uint32              total_bits_used = 0;
   9434     uint32              index = 0;
   9435     bcm_policer_svc_meter_bookkeep_mode_t   mode_info;
   9436     uncompressed_attr_selectors_t *un_attr;
   9437     int                 port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE;
   9438     int                 svp_type_attr_size = 0;
   9439 
   9440     /*check if a mode is already configured with these attributes */
   9441     for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
   9442         if (_bcm_policer_svc_meter_get_mode_info(unit,index,&mode_info)
   9443                                                          == BCM_E_NONE) {
   9444             if ((mode_info.meter_attr.mode_type_v != cascade_mode) ||
   9445                                  (group_mode != mode_info.group_mode )) {
   9446                 continue;
   9447             }
   9448             if (mode_info.no_of_policers != num_pol) {
   9449                 continue;
   9450             }
   9451             un_attr = &mode_info.meter_attr.uncompressed_attr_selectors_v;
   9452             if (un_attr->uncompressed_attr_bits_selector ==
   9453                 uncompressed_attr_selectors_v->uncompressed_attr_bits_selector) {
   9454                 *svc_meter_mode = index;
   9455                 return BCM_E_EXISTS;
   9456             }
   9457         }
   9458     }
   9459 
   9460     bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit,
   9461                                                 &bcm_policer_svc_meter_mode);
   9462     if (bcm_error_v != BCM_E_NONE) {
   9463         LOG_WARN(BSL_LS_BCM_POLICER,
   9464                  (BSL_META_U(unit, " Offset Table is full\n")));
   9465         return bcm_error_v;
   9466     }
   9467 
   9468     /* Step1: Packet Attribute selection */
   9469     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9470         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS) {
   9471         pkt_attr_bits_v.cng = BCM_POLICER_SVC_METER_CNG_ATTR_SIZE;
   9472         total_bits_used += BCM_POLICER_SVC_METER_CNG_ATTR_SIZE;
   9473     }
   9474     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9475         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS) {
   9476         pkt_attr_bits_v.int_pri = BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE ;
   9477         total_bits_used += BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE;
   9478     }
   9479     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9480         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS) {
   9481         pkt_attr_bits_v.short_int_pri = BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE;
   9482         total_bits_used += BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE;
   9483     }
   9484     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9485          BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS) {
   9486         pkt_attr_bits_v.vlan_format =
   9487                             BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE;
   9488         total_bits_used += BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE;
   9489     }
   9490     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9491         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS) {
   9492         pkt_attr_bits_v.outer_dot1p =
   9493                                BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE ;
   9494         total_bits_used += BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE;
   9495     }
   9496     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9497         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS) {
   9498             pkt_attr_bits_v.inner_dot1p =
   9499                                BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE;
   9500         total_bits_used += BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE;
   9501     }
   9502     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9503         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS) {
   9504         port_attr_size =
   9505                 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size;
   9506         pkt_attr_bits_v.ing_port = port_attr_size;
   9507         total_bits_used += port_attr_size;
   9508     }
   9509     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9510         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS) {
   9511         pkt_attr_bits_v.tos = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
   9512         total_bits_used += BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
   9513     }
   9514     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9515         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS) {
   9516         pkt_attr_bits_v.pkt_resolution =
   9517                              BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE;
   9518         total_bits_used += BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE;
   9519     }
   9520     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9521         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS) {
   9522         svp_type_attr_size =
   9523                 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size;
   9524         total_bits_used += svp_type_attr_size;
   9525         pkt_attr_bits_v.svp_type = svp_type_attr_size;
   9526     }
   9527     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9528         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS) {
   9529         pkt_attr_bits_v.drop = BCM_POLICER_SVC_METER_DROP_ATTR_SIZE;
   9530         total_bits_used += BCM_POLICER_SVC_METER_DROP_ATTR_SIZE;
   9531     }
   9532     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9533         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS) {
   9534         pkt_attr_bits_v.ip_pkt = BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE;
   9535         total_bits_used += BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE;
   9536     }
   9537     if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
   9538         LOG_DEBUG(BSL_LS_BCM_POLICER,
   9539                   (BSL_META_U(unit,
   9540                               "Key size exceeds max allowed size \n")));
   9541         return BCM_E_PARAM;
   9542     }
   9543     /* Step2: Packet Attribute filling */
   9544     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit,
   9545                uncompressed_mode, type,
   9546                _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode],
   9547                pkt_attr_bits_v));
   9548 
   9549     /* Step3: Offset table filling */
   9550     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
   9551                            SVM_OFFSET_TABLEm,
   9552                            bcm_policer_svc_meter_mode,
   9553                            &uncompressed_attr_selectors_v->offset_map[0]));
   9554 
   9555     /* Step4: Final: reserve mode and return */
   9556     *svc_meter_mode = bcm_policer_svc_meter_mode;
   9557     return BCM_E_NONE;
   9558 }
   9559 /*
   9560  * Function:
   9561  *      _bcm_policer_svc_meter_create_uncompress_mode
   9562  * Purpose:
   9563  *     Function to create an offset mode with uncompressed packet attributes
   9564  * Parameters:
   9565  *     Unit                  - (IN) unit number
   9566  *     uncompressed_attr_selectors_v - (IN) Packet attribute selectors
   9567  *     group_mode            - (IN) Policer group mode
   9568  *     svc_meter_mode        - (OUT) Allocated meter offset mode
   9569  *     total_bits            - (OUT) Total number of packet attribute bits
   9570  * Returns:
   9571  *     BCM_E_XXX
   9572  */
   9573 bcm_error_t _bcm_policer_svc_meter_create_uncompress_mode(
   9574     int unit,
   9575     uncompressed_attr_selectors_t *uncompressed_attr_selectors_v,
   9576     bcm_policer_group_mode_t     group_mode,
   9577     int8                         type,
   9578     bcm_policer_svc_meter_mode_t *svc_meter_mode)
   9579 {
   9580     bcm_error_t                         bcm_error_v = BCM_E_NONE;
   9581     bcm_policer_svc_meter_mode_t        bcm_policer_svc_meter_mode = 0;
   9582     pkt_attr_bits_t     pkt_attr_bits_v = {0};
   9583     uint32              total_bits_used = 0;
   9584     uint32              index = 0;
   9585     bcm_policer_svc_meter_bookkeep_mode_t   mode_info;
   9586     uncompressed_attr_selectors_t *un_attr;
   9587     int                 port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE;
   9588     int                 svp_type_attr_size = 0;
   9589 
   9590     /*check if a mode is already configured with these attributes */
   9591     for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
   9592         if (_bcm_policer_svc_meter_get_mode_info(unit,index,&mode_info)
   9593                                                          == BCM_E_NONE) {
   9594             if ((mode_info.meter_attr.mode_type_v != uncompressed_mode) ||
   9595                                  (group_mode != mode_info.group_mode )) {
   9596                 continue;
   9597             }
   9598             un_attr = &mode_info.meter_attr.uncompressed_attr_selectors_v;
   9599             if (un_attr->uncompressed_attr_bits_selector ==
   9600                 uncompressed_attr_selectors_v->uncompressed_attr_bits_selector) {
   9601                 *svc_meter_mode = index;
   9602                 return BCM_E_EXISTS;
   9603             }
   9604         }
   9605     }
   9606 
   9607     bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit,
   9608                                                 &bcm_policer_svc_meter_mode);
   9609     if (bcm_error_v != BCM_E_NONE) {
   9610         LOG_WARN(BSL_LS_BCM_POLICER,
   9611                  (BSL_META_U(unit,
   9612                              " Offset Table is full\n")));
   9613         return bcm_error_v;
   9614     }
   9615 
   9616     /* Step1: Packet Attribute selection */
   9617     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9618         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS) {
   9619         pkt_attr_bits_v.cng = BCM_POLICER_SVC_METER_CNG_ATTR_SIZE;
   9620         total_bits_used += BCM_POLICER_SVC_METER_CNG_ATTR_SIZE;
   9621     }
   9622     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9623         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS) {
   9624         pkt_attr_bits_v.int_pri = BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE ;
   9625         total_bits_used += BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE;
   9626     }
   9627     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9628         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS) {
   9629         pkt_attr_bits_v.short_int_pri = BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE ;
   9630         total_bits_used += BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE;
   9631     }
   9632     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9633          BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS) {
   9634         pkt_attr_bits_v.vlan_format =
   9635                             BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE;
   9636         total_bits_used += BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE;
   9637     }
   9638     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9639         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS) {
   9640         pkt_attr_bits_v.outer_dot1p =
   9641                                BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE ;
   9642         total_bits_used += BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE;
   9643     }
   9644     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9645         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS) {
   9646             pkt_attr_bits_v.inner_dot1p =
   9647                                BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE;
   9648         total_bits_used += BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE;
   9649     }
   9650     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9651         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS) {
   9652         port_attr_size =
   9653                 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size;
   9654         pkt_attr_bits_v.ing_port = port_attr_size;
   9655         total_bits_used += port_attr_size;
   9656     }
   9657     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9658         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS) {
   9659         pkt_attr_bits_v.tos = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
   9660         total_bits_used += BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
   9661     }
   9662     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9663         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS) {
   9664         pkt_attr_bits_v.tos_ecn = BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE;
   9665         total_bits_used += BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE;
   9666     }
   9667     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9668         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS) {
   9669         pkt_attr_bits_v.pkt_resolution =
   9670                              BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE;
   9671         total_bits_used += BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE;
   9672     }
   9673     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9674         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS) {
   9675         svp_type_attr_size =
   9676                 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size;
   9677         total_bits_used += svp_type_attr_size;
   9678         pkt_attr_bits_v.svp_type = svp_type_attr_size;
   9679     }
   9680     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9681         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS) {
   9682         pkt_attr_bits_v.drop = BCM_POLICER_SVC_METER_DROP_ATTR_SIZE;
   9683         total_bits_used += BCM_POLICER_SVC_METER_DROP_ATTR_SIZE;
   9684     }
   9685     if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector &
   9686         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS) {
   9687         pkt_attr_bits_v.ip_pkt = BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE;
   9688         total_bits_used += BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE;
   9689     }
   9690     if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
   9691         LOG_DEBUG(BSL_LS_BCM_POLICER,
   9692                   (BSL_META_U(unit,
   9693                               "Key size exceeds max allowed size \n")));
   9694         return BCM_E_PARAM;
   9695     }
   9696     /* Step2: Packet Attribute filling */
   9697     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit,
   9698                uncompressed_mode, type,
   9699                _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode],
   9700                pkt_attr_bits_v));
   9701 
   9702     /* Step3: Offset table filling */
   9703     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
   9704                            SVM_OFFSET_TABLEm,
   9705                            bcm_policer_svc_meter_mode,
   9706                            &uncompressed_attr_selectors_v->offset_map[0]));
   9707 
   9708     /* Step4: Final: reserve mode and return */
   9709     *svc_meter_mode = bcm_policer_svc_meter_mode;
   9710     return BCM_E_NONE;
   9711 }
   9712 
   9713 
   9714 /*
   9715  * Function:
   9716  *      _bcm_esw_svm_compressed_map_hw_write
   9717  * Purpose:
   9718  *      Write to compression table.
   9719  *
   9720  * Parameters:
   9721  *     Unit                  - (IN) unit number
   9722  *     mem                   - (IN) memory
   9723  *     index                 - (IN) Entry index in memory
   9724  *     entry                 - (IN/OUT) entry buffer at mem index
   9725  *     user_data             - (IN) user data
   9726  *     dirty                 - (OUT) dirty
   9727  * Returns:
   9728  *     BCM_E_XXX
   9729  */
   9730 STATIC
   9731 int _bcm_esw_svm_compressed_map_hw_write(int unit,
   9732         soc_mem_t mem, uint32 index,
   9733         void *entry, void *user_data, uint32 *dirty)
   9734 {
   9735     uint8 map_entry = 0;
   9736     soc_field_t field = INVALIDf;
   9737 
   9738     map_entry = ((uint8 *) user_data)[index];
   9739 
   9740     switch(mem) {
   9741         case ING_SVM_PRI_CNG_MAPm:
   9742             field = PRI_CNG_FNf;
   9743             break;
   9744         case ING_SVM_PKT_PRI_MAPm:
   9745             field = PKT_PRI_FNf;
   9746             break;
   9747         case ING_SVM_PORT_MAPm:
   9748             field = PORT_FNf;
   9749             break;
   9750         case ING_SVM_TOS_MAPm:
   9751             field = TOS_FNf;
   9752             break;
   9753         case ING_SVM_PKT_RES_MAPm:
   9754             field = PKT_RES_FNf;
   9755             break;
   9756         default:
   9757             break;
   9758     }
   9759 
   9760     if (field != INVALIDf) {
   9761         soc_mem_field32_set(unit, mem, entry, field, map_entry);
   9762         *dirty = 1;
   9763     }
   9764 
   9765     return BCM_E_NONE;
   9766 }
   9767 
   9768 /*
   9769  * Function:
   9770  *      _bcm_esw_svm_pkt_compressed_attr_maps_add
   9771  * Purpose:
   9772  *      Internal function to increment reference count of required maps and
   9773  *      and write to hardware tables if reference count becomes 1.
   9774  *
   9775  * Parameters:
   9776  *     Unit                  - (IN) unit number
   9777  *     compressed_attr_selectors_v - (IN) compressed attribute selectors.
   9778  * Returns:
   9779  *     BCM_E_XXX
   9780  */
   9781 STATIC
   9782 int _bcm_esw_svm_pkt_compressed_attr_maps_add(
   9783     int unit,
   9784     compressed_attr_selectors_t *compressed_attr_selectors_v)
   9785 {
   9786     uint8 index = 0;
   9787     uint8 *map_ref_count = NULL;
   9788     uint8 ref_counts[pkt_attr_map_count] = {0};
   9789     uint8 cmprsd_maps_to_write[pkt_attr_map_count] = {0};
   9790     pkt_attr_bits_t *pkt_attr_bits_v = NULL;
   9791     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
   9792 
   9793     pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v;
   9794 
   9795     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
   9796 
   9797     /* Get reference counts of compression tables. */
   9798     if ((pkt_attr_bits_v->cng != 0) ||
   9799             (pkt_attr_bits_v->int_pri != 0)) {
   9800         cmprsd_maps_to_write[pkt_attr_pri_cng_map] = 1;
   9801         ref_counts[pkt_attr_pri_cng_map] =
   9802             cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map];
   9803     }
   9804     if ((pkt_attr_bits_v->vlan_format != 0) ||
   9805             (pkt_attr_bits_v->outer_dot1p != 0) ||
   9806             (pkt_attr_bits_v->inner_dot1p != 0)) {
   9807         cmprsd_maps_to_write[pkt_attr_pkt_pri_map] = 1;
   9808         ref_counts[pkt_attr_pkt_pri_map] =
   9809             cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map];
   9810     }
   9811     if (pkt_attr_bits_v->ing_port != 0) {
   9812         cmprsd_maps_to_write[pkt_attr_port_map] = 1;
   9813         ref_counts[pkt_attr_port_map] =
   9814             cmprsd_attr_maps->ref_counts[pkt_attr_port_map];
   9815     }
   9816     if ((pkt_attr_bits_v->tos != 0) ||
   9817             (pkt_attr_bits_v->tos_ecn != 0)) {
   9818         cmprsd_maps_to_write[pkt_attr_tos_map] = 1;
   9819         ref_counts[pkt_attr_tos_map] =
   9820             cmprsd_attr_maps->ref_counts[pkt_attr_tos_map];
   9821     }
   9822     if ((pkt_attr_bits_v->pkt_resolution != 0) ||
   9823             (pkt_attr_bits_v->svp_type != 0) ||
   9824             (pkt_attr_bits_v->drop != 0))   {
   9825         cmprsd_maps_to_write[pkt_attr_pkt_res_map] = 1;
   9826         ref_counts[pkt_attr_pkt_res_map] =
   9827             cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map];
   9828     }
   9829 
   9830     /*
   9831      * If sharing is not allowed, fail when reference count is non-zero
   9832      * and user is trying to write to that compression table.
   9833      */
   9834     if (!soc_feature(unit, soc_feature_global_meter_compression_share)) {
   9835         for (index = pkt_attr_pri_cng_map;
   9836                 index < pkt_attr_ip_pkt_map; index++) {
   9837             if ((cmprsd_maps_to_write[index] == 1) &&
   9838                     (ref_counts[index] != 0)) {
   9839                 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Compression"
   9840                                 " tables in use and cannot be modified\n")));
   9841                 return BCM_E_PARAM;
   9842             }
   9843         }
   9844     }
   9845 
   9846     /* Update compression tables and ref counts */
   9847     if (cmprsd_maps_to_write[pkt_attr_pri_cng_map] != 0) {
   9848         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map];
   9849         if (*map_ref_count == 0) {
   9850             BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   9851                         ING_SVM_PRI_CNG_MAPm, -1, -1,
   9852                         _bcm_esw_svm_compressed_map_hw_write,
   9853                         (void *) compressed_attr_selectors_v->
   9854                         compressed_pri_cnf_attr_map_v));
   9855             cmprsd_attr_maps->cng = 1;
   9856             cmprsd_attr_maps->int_pri = 1;
   9857         }
   9858         (*map_ref_count)++;
   9859     }
   9860     if (cmprsd_maps_to_write[pkt_attr_pkt_pri_map] != 0) {
   9861         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map];
   9862         if (*map_ref_count == 0) {
   9863             BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   9864                         ING_SVM_PKT_PRI_MAPm, -1, -1,
   9865                         _bcm_esw_svm_compressed_map_hw_write,
   9866                         (void *) compressed_attr_selectors_v->
   9867                         compressed_pkt_pri_attr_map_v));
   9868             cmprsd_attr_maps->vlan_format = 1;
   9869             cmprsd_attr_maps->outer_dot1p = 1;
   9870             cmprsd_attr_maps->inner_dot1p = 1;
   9871         }
   9872         (*map_ref_count)++;
   9873     }
   9874     if (cmprsd_maps_to_write[pkt_attr_port_map] != 0) {
   9875         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_port_map];
   9876         if (*map_ref_count == 0) {
   9877             BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   9878                         ING_SVM_PORT_MAPm, -1, -1,
   9879                         _bcm_esw_svm_compressed_map_hw_write,
   9880                         (void *) compressed_attr_selectors_v->
   9881                         compressed_port_attr_map_v));
   9882             cmprsd_attr_maps->port = 1;
   9883         }
   9884         (*map_ref_count)++;
   9885     }
   9886     if (cmprsd_maps_to_write[pkt_attr_tos_map] != 0) {
   9887         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_tos_map];
   9888         if (*map_ref_count == 0) {
   9889             BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   9890                         ING_SVM_TOS_MAPm, -1, -1,
   9891                         _bcm_esw_svm_compressed_map_hw_write,
   9892                         (void *) compressed_attr_selectors_v->
   9893                         compressed_tos_attr_map_v));
   9894             cmprsd_attr_maps->tos_dscp = 1;
   9895             cmprsd_attr_maps->tos_ecn = 1;
   9896         }
   9897         (*map_ref_count)++;
   9898     }
   9899     if (cmprsd_maps_to_write[pkt_attr_pkt_res_map] != 0) {
   9900         map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map];
   9901         if (*map_ref_count == 0) {
   9902             BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit,
   9903                         ING_SVM_PKT_RES_MAPm, -1, -1,
   9904                         _bcm_esw_svm_compressed_map_hw_write,
   9905                         (void *) compressed_attr_selectors_v->
   9906                         compressed_pkt_res_attr_map_v));
   9907             cmprsd_attr_maps->pkt_resolution = 1;
   9908             cmprsd_attr_maps->svp_type = 1;
   9909             cmprsd_attr_maps->drop = 1;
   9910         }
   9911         (*map_ref_count)++;
   9912     }
   9913     return BCM_E_NONE;
   9914 }
   9915 
   9916 /*
   9917  * Function:
   9918  *      _bcm_esw_svc_meter_compressed_modes_match_for_share
   9919  * Purpose:
   9920  *      Internal function to match existing mode ids with new input selectors
   9921  *      for compressed mode when compression table sharing is enabled.
   9922  *
   9923  * Parameters:
   9924  *     Unit                  - (IN) unit number
   9925  *     compressed_attr_selectors_v - (IN) compressed attribute selectors.
   9926  *     group_mode            - (IN) New Policer Group Mode
   9927  *     type                  - (IN) New policer Group Type
   9928  *     pkt_attr_selectors    - (IN) New input attr selectors
   9929  *     svc_meter_mode        - (OUT) svc meter offset mode
   9930  * Returns:
   9931  *     BCM_E_EXISTS - If a match is found
   9932  *     BCM_E_XXX
   9933  */
   9934 STATIC
   9935 int _bcm_esw_svc_meter_compressed_modes_match_for_share(int unit,
   9936     compressed_attr_selectors_t *compressed_attr_selectors_v,
   9937     bcm_policer_group_mode_t group_mode,
   9938     int8 type,
   9939     bcm_policer_attr_selectors_t *pkt_attr_selectors,
   9940     bcm_policer_svc_meter_mode_t *svc_meter_mode)
   9941 {
   9942     bcm_error_t                     bcm_error_v=BCM_E_NONE;
   9943     uint8                           is_equal = FALSE;
   9944     uint32                          pol = 0;
   9945     uint32                          index = 0;
   9946     uint32                          npolicers = 0;
   9947     bcm_policer_attr_selectors_t    mode_pkt_attr_selectors;
   9948     bcm_policer_svc_meter_bookkeep_mode_t   *mode_info = NULL;
   9949     bcm_policer_group_mode_attr_selector_t *attr_selectors = NULL;
   9950     bcm_policer_combine_attr_t  *combine_attr_data = NULL;
   9951     bcm_policer_combine_attr_t  *mode_combine_attr_data = NULL;
   9952 
   9953     /* pkt_attr_selectors is NULL. So, it is not coming from
   9954        bcm_policer_group_mode_id_create() API. Go for default comparison. */
   9955     if (pkt_attr_selectors == NULL) {
   9956         return _bcm_esw_svc_meter_compressed_modes_match(unit,
   9957                 compressed_attr_selectors_v, group_mode,
   9958                 type, svc_meter_mode);
   9959     }
   9960     mode_info = sal_alloc(sizeof(bcm_policer_svc_meter_bookkeep_mode_t),
   9961                                                    "mode bookkeep info");
   9962     if (mode_info == NULL) {
   9963         LOG_VERBOSE(BSL_LS_BCM_POLICER,
   9964                     (BSL_META_U(unit,
   9965                                 "Failed to allocate memory for mode bookkeep "
   9966                                 "info\n")));
   9967         return BCM_E_MEMORY;
   9968     }
   9969 
   9970     for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
   9971         sal_memset(mode_info, 0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t));
   9972         if (_bcm_policer_svc_meter_get_mode_info(
   9973                              unit, index, mode_info) == BCM_E_NONE) {
   9974             /* If not compressed mode, check next. */
   9975             if (mode_info->meter_attr.mode_type_v != compressed_mode) {
   9976                 continue;
   9977             }
   9978             /* If not custom mode Id, check next. */
   9979             if (mode_info->type == -1) {
   9980                 continue;
   9981             }
   9982 
   9983             /* Compare total policers. */
   9984             if (pkt_attr_selectors->total_policers !=
   9985                         mode_info->no_of_policers) {
   9986                 continue;
   9987             }
   9988 
   9989             /* Get pkt attributes fillup info and compare */
   9990             sal_memset(&mode_pkt_attr_selectors, 0,
   9991                         sizeof(bcm_policer_attr_selectors_t));
   9992             _GLOBAL_METER_XGS3_ALLOC(attr_selectors,
   9993                         mode_info->no_of_selectors * \
   9994                         sizeof(bcm_policer_group_mode_attr_selector_t),
   9995                         "attr selectors");
   9996             bcm_error_v = _bcm_wb_attr_selectors_copy_to_attr_selectors(
   9997                             mode_info->no_of_selectors,
   9998                             mode_info->attr_selectors, attr_selectors);
   9999             if (BCM_FAILURE(bcm_error_v)) {
  10000                 sal_free(mode_info);
  10001                 sal_free(attr_selectors);
  10002                 return bcm_error_v;
  10003             }
  10004             npolicers = mode_info->no_of_policers;
  10005             _GLOBAL_METER_XGS3_ALLOC(mode_pkt_attr_selectors.combine_attr_data,
  10006                         sizeof(bcm_policer_combine_attr_t) * npolicers,
  10007                     "combine attributes");
  10008             if (mode_pkt_attr_selectors.combine_attr_data == NULL) {
  10009                 sal_free(mode_info);
  10010                 sal_free(attr_selectors);
  10011                 return BCM_E_MEMORY;
  10012             }
  10013 
  10014             bcm_error_v = _bcm_esw_policer_group_mode_fillup_values(unit, 0,
  10015                     mode_info->type, mode_info->no_of_policers,
  10016                     mode_info->no_of_selectors, &attr_selectors[0],
  10017                     &mode_pkt_attr_selectors);
  10018             if (bcm_error_v != BCM_E_NONE) {
  10019                 sal_free(mode_info);
  10020                 sal_free(attr_selectors);
  10021                 sal_free(mode_pkt_attr_selectors.combine_attr_data);
  10022                 return bcm_error_v;
  10023             }
  10024 
  10025             /* Compare attributes and values */
  10026             is_equal = TRUE;
  10027             for (pol = 0; pol < mode_info->no_of_policers; pol++) {
  10028                 combine_attr_data =
  10029                     &pkt_attr_selectors->combine_attr_data[pol];
  10030                 mode_combine_attr_data =
  10031                     &mode_pkt_attr_selectors.combine_attr_data[pol];
  10032 
  10033                 if (sal_memcmp(combine_attr_data, mode_combine_attr_data,
  10034                             sizeof(bcm_policer_combine_attr_t)) != 0) {
  10035                     is_equal = FALSE;
  10036                     break;
  10037                 }
  10038             }
  10039             if (is_equal == TRUE) {
  10040                 *svc_meter_mode = index;
  10041                 sal_free(mode_info);
  10042                 sal_free(attr_selectors);
  10043                 sal_free(mode_pkt_attr_selectors.combine_attr_data);
  10044                 return BCM_E_EXISTS;
  10045             } else {
  10046                 sal_free(attr_selectors);
  10047                 sal_free(mode_pkt_attr_selectors.combine_attr_data);
  10048                 attr_selectors = NULL;
  10049                 mode_pkt_attr_selectors.combine_attr_data = NULL;
  10050             }
  10051         }
  10052     }
  10053 
  10054     if (mode_info != NULL) {
  10055         sal_free(mode_info);
  10056     }
  10057     return BCM_E_NONE;
  10058 }
  10059 
  10060 /*
  10061  * Function:
  10062  *      _bcm_esw_svc_meter_compressed_modes_match
  10063  * Purpose:
  10064  *      Internal function to match existing mode ids with new input selectors
  10065  *      for compressed mode.
  10066  *
  10067  * Parameters:
  10068  *     Unit                  - (IN) unit number
  10069  *     compressed_attr_selectors_v - (IN) compressed attribute selectors.
  10070  *     group_mode            - (IN) New Policer Group Mode
  10071  *     type                  - (IN) New policer Group Type
  10072  *     svc_meter_mode        - (OUT) svc meter offset mode
  10073  * Returns:
  10074  *     BCM_E_EXISTS - If a match is found
  10075  *     BCM_E_XXX
  10076  */
  10077 STATIC int
  10078 _bcm_esw_svc_meter_compressed_modes_match(int unit,
  10079     compressed_attr_selectors_t *compressed_attr_selectors_v,
  10080     bcm_policer_group_mode_t group_mode,
  10081     int8 type,
  10082     bcm_policer_svc_meter_mode_t *svc_meter_mode)
  10083 {
  10084     bcm_error_t                     bcm_error_v=BCM_E_NONE;
  10085     pkt_attr_bits_t                 *config_pkt_attr = NULL;
  10086     uint32                          total_bits_used = 0;
  10087     uint32                          index = 0;
  10088     bcm_policer_svc_meter_bookkeep_mode_t   *mode_info = NULL;
  10089     pkt_attr_bits_t                 *pkt_attr_bits = NULL;
  10090     int                             port_attr_size = 0;
  10091     uint32                          pri_cng_map_in_use = 0;
  10092     uint32                          pkt_pri_map_in_use = 0;
  10093     uint32                          port_map_in_use = 0;
  10094     uint32                          tos_map_in_use = 0;
  10095     uint32                          pkt_res_map_in_use = 0;
  10096     int                             svp_type_attr_size = 0;
  10097 
  10098     mode_info = sal_alloc(sizeof(bcm_policer_svc_meter_bookkeep_mode_t),
  10099                                                    "mode bookkeep info");
  10100     if (mode_info == NULL) {
  10101         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  10102                     (BSL_META_U(unit,
  10103                                 "Failed to allocate memory for mode bookkeep "
  10104                                 "info\n")));
  10105         return BCM_E_MEMORY;
  10106     }
  10107     sal_memset(mode_info, 0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t));
  10108 
  10109     config_pkt_attr = &compressed_attr_selectors_v->pkt_attr_bits_v;
  10110 
  10111     /*check if a mode is already configured with these attributes */
  10112     for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
  10113         if (_bcm_policer_svc_meter_get_mode_info(
  10114                              unit, index, mode_info) == BCM_E_NONE) {
  10115             if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  10116                 if (mode_info->meter_attr.mode_type_v != compressed_mode) {
  10117                     continue;
  10118                 } else if ((type == -1) &&
  10119                         (mode_info->type == -1) &&
  10120                         (mode_info->group_mode != group_mode)) {
  10121                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  10122                             (BSL_META_U(unit,
  10123                                         "Some other policer group is already "
  10124                                         "using this resource\n")));
  10125                     sal_free(mode_info);
  10126                     return BCM_E_PARAM;
  10127                 }
  10128             } else {
  10129                 if ((mode_info->meter_attr.mode_type_v != compressed_mode) ||
  10130                         (group_mode != mode_info->group_mode)) {
  10131                     if (mode_info->meter_attr.mode_type_v == compressed_mode) {
  10132                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  10133                                 (BSL_META_U(unit,
  10134                                             "Some other policer group is already "
  10135                                             "using this resource\n")));
  10136                         sal_free(mode_info);
  10137                         return BCM_E_PARAM;
  10138                     }
  10139                 }
  10140             }
  10141             pkt_attr_bits = &mode_info->meter_attr.compressed_attr_selectors_v.\
  10142                                                                 pkt_attr_bits_v;
  10143             if ((pkt_attr_bits->cng == config_pkt_attr->cng) &&
  10144                 (pkt_attr_bits->int_pri == config_pkt_attr->int_pri) &&
  10145                 (pkt_attr_bits->vlan_format == config_pkt_attr->vlan_format) &&
  10146                 (pkt_attr_bits->outer_dot1p == config_pkt_attr->outer_dot1p) &&
  10147                 (pkt_attr_bits->inner_dot1p == config_pkt_attr->inner_dot1p) &&
  10148                 (pkt_attr_bits->ing_port == config_pkt_attr->ing_port) &&
  10149                 (pkt_attr_bits->tos == config_pkt_attr->tos) &&
  10150                 (pkt_attr_bits->tos_ecn == config_pkt_attr->tos_ecn) &&
  10151                 (pkt_attr_bits->pkt_resolution == config_pkt_attr->pkt_resolution) &&
  10152                 (pkt_attr_bits->svp_type == config_pkt_attr->svp_type) &&
  10153                 (pkt_attr_bits->drop == config_pkt_attr->drop) &&
  10154                 (pkt_attr_bits->ip_pkt == config_pkt_attr->ip_pkt)) {
  10155                     *svc_meter_mode = index;
  10156                     sal_free(mode_info);
  10157                     return BCM_E_EXISTS;
  10158             }
  10159             if ((pkt_attr_bits->cng != 0) ||
  10160                 (pkt_attr_bits->int_pri != 0)) {
  10161                 pri_cng_map_in_use = 1;
  10162             }
  10163             if ((pkt_attr_bits->vlan_format != 0) ||
  10164                 (pkt_attr_bits->outer_dot1p != 0) ||
  10165                 (pkt_attr_bits->inner_dot1p != 0)) {
  10166                 pkt_pri_map_in_use = 1;
  10167             }
  10168             if (pkt_attr_bits->ing_port != 0) {
  10169                 port_map_in_use = 1;
  10170             }
  10171             if ((pkt_attr_bits->tos != 0) ||
  10172                 (pkt_attr_bits->tos_ecn != 0)) {
  10173                 tos_map_in_use = 1;
  10174             }
  10175             if ((pkt_attr_bits->pkt_resolution != 0) ||
  10176                 (pkt_attr_bits->svp_type != 0) ||
  10177                 (pkt_attr_bits->drop != 0)) {
  10178                 pkt_res_map_in_use = 1;
  10179             }
  10180         }
  10181     } /* end of for */
  10182     sal_free(mode_info);
  10183 
  10184     /* Check Packet Attribute selection and compression table usage */
  10185     if (config_pkt_attr->cng != 0) {
  10186         if (config_pkt_attr->cng > BCM_POLICER_SVC_METER_CNG_ATTR_SIZE) {
  10187             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10188                       (BSL_META_U(unit,
  10189                                   "CNG attribute size exceeds max allowed size\n")));
  10190             return BCM_E_PARAM;
  10191         }
  10192         if (pri_cng_map_in_use == 1) {
  10193             bcm_error_v = BCM_E_RESOURCE;
  10194         }
  10195         total_bits_used += config_pkt_attr->cng;
  10196     }
  10197     if (config_pkt_attr->int_pri != 0) {
  10198         if (config_pkt_attr->int_pri > BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE) {
  10199             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10200                       (BSL_META_U(unit,
  10201                                   "int_pri attribute size exceeds max allowed "
  10202                                   "size\n")));
  10203             return BCM_E_PARAM;
  10204         }
  10205         if (pri_cng_map_in_use == 1) {
  10206             bcm_error_v = BCM_E_RESOURCE;
  10207         }
  10208         total_bits_used += config_pkt_attr->int_pri;
  10209     }
  10210     if (config_pkt_attr->vlan_format != 0) {
  10211         if (config_pkt_attr->vlan_format >
  10212                                 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE) {
  10213             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10214                       (BSL_META_U(unit,
  10215                                   "Vlan attribute size exceeds max allowed "
  10216                                   "size\n")));
  10217             return BCM_E_PARAM;
  10218         }
  10219         if (pkt_pri_map_in_use == 1) {
  10220             bcm_error_v = BCM_E_RESOURCE;
  10221         }
  10222         total_bits_used += config_pkt_attr->vlan_format;
  10223     }
  10224     if (config_pkt_attr->outer_dot1p != 0) {
  10225         if (config_pkt_attr->outer_dot1p >
  10226                                 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE) {
  10227             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10228                       (BSL_META_U(unit,
  10229                                   "Outer DOT1P attribute size exceeds max allowed "
  10230                                   "size\n")));
  10231             return BCM_E_PARAM;
  10232         }
  10233         if (pkt_pri_map_in_use == 1) {
  10234             bcm_error_v = BCM_E_RESOURCE;
  10235         }
  10236         total_bits_used += config_pkt_attr->outer_dot1p;
  10237     }
  10238     if (config_pkt_attr->inner_dot1p != 0) {
  10239         if (config_pkt_attr->inner_dot1p >
  10240                                 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE) {
  10241             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10242                       (BSL_META_U(unit,
  10243                                   "Inner DOT1P attribute size exceeds max allowed "
  10244                                   "size\n")));
  10245             return BCM_E_PARAM;
  10246         }
  10247         if (pkt_pri_map_in_use == 1) {
  10248             bcm_error_v = BCM_E_RESOURCE;
  10249         }
  10250         total_bits_used += config_pkt_attr->inner_dot1p;
  10251     }
  10252     if (config_pkt_attr->ing_port != 0) {
  10253         port_attr_size =
  10254                 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size;
  10255         if (config_pkt_attr->ing_port > port_attr_size) {
  10256             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10257                       (BSL_META_U(unit,
  10258                                   "port attribute size exceeds max allowed "
  10259                                   "size\n")));
  10260             return BCM_E_PARAM;
  10261         }
  10262         if (port_map_in_use == 1) {
  10263             bcm_error_v = BCM_E_RESOURCE;
  10264         }
  10265         total_bits_used += config_pkt_attr->ing_port;
  10266     }
  10267     if (config_pkt_attr->tos != 0) {
  10268         if (config_pkt_attr->tos > BCM_POLICER_SVC_METER_TOS_ATTR_SIZE) {
  10269             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10270                       (BSL_META_U(unit,
  10271                                   "TOS attribute size exceeds max allowed "
  10272                                   "size\n")));
  10273             return BCM_E_PARAM;
  10274         }
  10275         if (tos_map_in_use == 1) {
  10276             bcm_error_v = BCM_E_RESOURCE;
  10277         }
  10278         total_bits_used += config_pkt_attr->tos;
  10279     }
  10280     if (config_pkt_attr->tos_ecn != 0) {
  10281         if (config_pkt_attr->tos_ecn > BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE) {
  10282             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10283                       (BSL_META_U(unit,
  10284                                   "TOS ecn attribute size exceeds max allowed "
  10285                                   "size\n")));
  10286             return BCM_E_PARAM;
  10287         }
  10288         if (tos_map_in_use == 1) {
  10289             bcm_error_v = BCM_E_RESOURCE;
  10290         }
  10291         total_bits_used += config_pkt_attr->tos_ecn;
  10292     }
  10293     if (config_pkt_attr->pkt_resolution != 0) {
  10294         if (config_pkt_attr->pkt_resolution >
  10295                               BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE) {
  10296             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10297                       (BSL_META_U(unit,
  10298                                   "Pkt resolution attribute size exceeds max "
  10299                                   "allowed size\n")));
  10300             return BCM_E_PARAM;
  10301         }
  10302         if (pkt_res_map_in_use == 1) {
  10303             bcm_error_v = BCM_E_RESOURCE;
  10304         }
  10305         total_bits_used += config_pkt_attr->pkt_resolution;
  10306     }
  10307     if (config_pkt_attr->svp_type != 0) {
  10308         svp_type_attr_size =
  10309                 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size;
  10310         if (config_pkt_attr->svp_type > svp_type_attr_size) {
  10311             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10312                 (BSL_META_U(unit,
  10313                     "SVP type attribute size exceeds max allowed "
  10314                     "size\n")));
  10315             return BCM_E_PARAM;
  10316         }
  10317         if (pkt_res_map_in_use == 1) {
  10318             bcm_error_v = BCM_E_RESOURCE;
  10319         }
  10320         total_bits_used += config_pkt_attr->svp_type;
  10321     }
  10322     if (config_pkt_attr->drop != 0) {
  10323         if (config_pkt_attr->drop > BCM_POLICER_SVC_METER_DROP_ATTR_SIZE) {
  10324             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10325                       (BSL_META_U(unit,
  10326                                   "DROP attribute size exceeds max allowed  "
  10327                                   "size\n")));
  10328             return BCM_E_PARAM;
  10329         }
  10330         if (pkt_res_map_in_use == 1) {
  10331             bcm_error_v = BCM_E_RESOURCE;
  10332         }
  10333         total_bits_used += config_pkt_attr->drop;
  10334     }
  10335     if (config_pkt_attr->ip_pkt != 0) {
  10336         if (config_pkt_attr->ip_pkt > BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE) {
  10337             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10338                       (BSL_META_U(unit,
  10339                                   "IP pkt attribute size exceeds max allowed "
  10340                                   "size\n")));
  10341             return BCM_E_PARAM;
  10342         }
  10343         total_bits_used += config_pkt_attr->ip_pkt;
  10344     }
  10345     if (bcm_error_v == BCM_E_RESOURCE) {
  10346         LOG_DEBUG(BSL_LS_BCM_POLICER,
  10347             (BSL_META_U(unit, "Resource not available\n")));
  10348         return bcm_error_v;
  10349     }
  10350 
  10351     if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
  10352         LOG_DEBUG(BSL_LS_BCM_POLICER,
  10353                   (BSL_META_U(unit,
  10354                               "Key size exceeds max allowed  "
  10355                               "size\n")));
  10356         return BCM_E_PARAM;
  10357     }
  10358 
  10359     return BCM_E_NONE;
  10360 }
  10361 
  10362 /*
  10363  * Function:
  10364  *      _bcm_policer_svc_meter_create_compress_mode
  10365  * Purpose:
  10366  *     Function to create an offset mode with compressed packet attributes
  10367  * Parameters:
  10368  *     Unit                  - (IN) unit number
  10369  *     compressed_attr_selectors_v - (IN) Packet attribute selectors
  10370  *     group_mode            - (IN) Policer group mode
  10371  *     svc_meter_mode        - (OUT) Allocated meter offset mode
  10372  *     total_bits            - (OUT) Total number of packet attribute bits
  10373  * Returns:
  10374  *     BCM_E_XXX
  10375  */
  10376 bcm_error_t _bcm_policer_svc_meter_create_compress_mode(
  10377     int unit,
  10378     compressed_attr_selectors_t *compressed_attr_selectors_v,
  10379     bcm_policer_group_mode_t group_mode,
  10380     int8 type,
  10381     bcm_policer_attr_selectors_t *pkt_attr_selectors,
  10382     bcm_policer_svc_meter_mode_t *svc_meter_mode)
  10383 {
  10384     bcm_error_t                     bcm_error_v=BCM_E_NONE;
  10385     bcm_policer_svc_meter_mode_t    bcm_policer_svc_meter_mode = 0;
  10386     pkt_attr_bits_t                 *pkt_attr_bits_v = NULL;
  10387 
  10388     /* Step1: Match with existing mode_ids. */
  10389     if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  10390         bcm_error_v = _bcm_esw_svc_meter_compressed_modes_match_for_share(unit,
  10391                 compressed_attr_selectors_v, group_mode,
  10392                 type, pkt_attr_selectors, svc_meter_mode);
  10393     } else {
  10394         bcm_error_v = _bcm_esw_svc_meter_compressed_modes_match(unit,
  10395                 compressed_attr_selectors_v, group_mode,
  10396                 type, svc_meter_mode);
  10397     }
  10398 
  10399     if (BCM_FAILURE(bcm_error_v)) {
  10400         return bcm_error_v;
  10401     }
  10402 
  10403     bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit,
  10404                                                 &bcm_policer_svc_meter_mode);
  10405     if (bcm_error_v != BCM_E_NONE) {
  10406         return bcm_error_v;
  10407     }
  10408 
  10409     /* Step2: Verify and Fill up compression tables */
  10410     bcm_error_v = _bcm_esw_svm_pkt_compressed_attr_maps_add(unit,
  10411                             compressed_attr_selectors_v);
  10412     if (BCM_FAILURE(bcm_error_v)) {
  10413         return bcm_error_v;
  10414     }
  10415 
  10416     /* Step3: Packet Attribute Selectors filling */
  10417     pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v;
  10418 
  10419     if ((type == -1) ||
  10420             (soc_feature(unit, soc_feature_global_meter_compression_share))) {
  10421         BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit,
  10422                     compressed_mode, type,
  10423                     _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode],
  10424                     *pkt_attr_bits_v));
  10425     } else {
  10426         BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys2(unit,
  10427                  compressed_mode,
  10428                  _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode],
  10429                  *pkt_attr_bits_v));
  10430     }
  10431 
  10432     /* Step4: Offset table filling */
  10433     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
  10434                             SVM_OFFSET_TABLEm,
  10435                             bcm_policer_svc_meter_mode,
  10436                             &compressed_attr_selectors_v->offset_map[0]));
  10437 
  10438     /* Step5: Final: reserve mode and return */
  10439     *svc_meter_mode = bcm_policer_svc_meter_mode;
  10440     return BCM_E_NONE;
  10441 }
  10442 
  10443 /*
  10444  * Function:
  10445  *      _bcm_policer_svc_meter_create_udf_mode
  10446  * Purpose:
  10447  *     Function to create an offset mode with udf packet attributes
  10448  * Parameters:
  10449  *     Unit                  - (IN) unit number
  10450  *     udf_pkt_attr          - (IN) Packet attribute selectors
  10451  *     group_mode            - (IN) Policer group mode
  10452  *     svc_meter_mode        - (OUT) Allocated meter offset mode
  10453  *     total_bits            - (OUT) Total number of packet attribute bits
  10454  * Returns:
  10455  *     BCM_E_XXX
  10456  */
  10457 bcm_error_t _bcm_policer_svc_meter_create_udf_mode(
  10458     int unit,
  10459     udf_pkt_attr_selectors_t     *udf_pkt_attr,
  10460     bcm_policer_group_mode_t     group_mode,
  10461     int8                         type,
  10462     bcm_policer_svc_meter_mode_t *svc_meter_mode,
  10463     uint32                       *total_bits)
  10464 {
  10465     bcm_error_t                  bcm_error_v = BCM_E_NONE;
  10466     bcm_policer_svc_meter_mode_t bcm_policer_svc_meter_mode = 0;
  10467     uint32                       total_udf_bits = 0;
  10468     bcm_policer_svc_meter_bookkeep_mode_t   mode_info;
  10469     udf_pkt_attr_selectors_t     *udf_attr = NULL;
  10470     uint32                       index = 0;
  10471     bcm_policer_svc_meter_mode_type_t mode_type = 0;
  10472     if (type == bcmPolicerGroupModeTypeNormal) {
  10473         mode_type = udf_mode;
  10474     } else if (type == bcmPolicerGroupModeTypeCascade) {
  10475         mode_type = udf_cascade_mode;
  10476     } else {
  10477         mode_type = udf_cascade_with_coupling_mode;
  10478     }
  10479 
  10480     /*check if a mode is already configured with these attributes */
  10481     for (index = 1;index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
  10482         if (_bcm_policer_svc_meter_get_mode_info(unit, index, &mode_info) ==
  10483                                                                  BCM_E_NONE) {
  10484             if ((mode_info.meter_attr.mode_type_v != mode_type) ||
  10485                (group_mode != mode_info.group_mode )) {
  10486                 continue;
  10487             }
  10488             udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v;
  10489             if ((udf_attr->drop == udf_pkt_attr->drop) &&
  10490                 (udf_attr->total_subdiv == udf_pkt_attr->total_subdiv) &&
  10491                 (sal_memcmp(&udf_attr->udf_subdiv[0], &udf_pkt_attr->udf_subdiv[0],
  10492                     sizeof(bcm_policer_udf_sub_div_t) * SVC_METER_UDF_MAX_SUB_DIVISIONS) == 0) &&
  10493                 (udf_attr->num_selectors == udf_pkt_attr->num_selectors) &&
  10494                 (sal_memcmp(&udf_attr->offset_map[0],
  10495                             &udf_pkt_attr->offset_map[0],
  10496                             (BCM_SVC_METER_MAP_SIZE_256 * sizeof(offset_table_entry_t))) == 0)) {
  10497                 *svc_meter_mode = index;
  10498                 return BCM_E_EXISTS;
  10499             }
  10500         }
  10501     }
  10502 
  10503     bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit,
  10504                                            &bcm_policer_svc_meter_mode);
  10505     if (bcm_error_v != BCM_E_NONE) {
  10506         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  10507                                 "offset table is full \n")));
  10508         return bcm_error_v;
  10509     }
  10510     /* Step1: Packet Attribute filling */
  10511     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_udf_selector_keys(
  10512                 unit,
  10513                 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode],
  10514                 udf_pkt_attr,
  10515                 &total_udf_bits));
  10516 
  10517     /* Step2: Offset table filling */
  10518     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
  10519                         SVM_OFFSET_TABLEm,
  10520                         bcm_policer_svc_meter_mode,
  10521                         &udf_pkt_attr->offset_map[0]));
  10522 
  10523     /* Step3: Final: reserve mode and return */
  10524     *svc_meter_mode = bcm_policer_svc_meter_mode;
  10525     return BCM_E_NONE;
  10526 }
  10527 
  10528 /*
  10529  * Function:
  10530  *      _bcm_esw_policer_svc_meter_create_mode
  10531  * Purpose:
  10532  *     Function to create an Meter offset mode
  10533  * Parameters:
  10534  *     Unit                  - (IN) unit number
  10535  *     meter_attr            - (IN) Packet attribute selectors
  10536  *     group_mode            - (IN) Policer group mode
  10537  *     num_pol               - (IN) Number of policers
  10538  *     svc_meter_mode        - (OUT) Allocated meter offset mode
  10539  * Returns:
  10540  *     BCM_E_XXX
  10541  */
  10542 int _bcm_esw_policer_svc_meter_create_mode (
  10543     int unit,
  10544     bcm_policer_svc_meter_attr_t *meter_attr,
  10545     bcm_policer_group_mode_t group_mode,
  10546     int8 type,
  10547     int num_pol,
  10548     bcm_policer_attr_selectors_t *pkt_attr_selectors,
  10549     bcm_policer_svc_meter_mode_t *svc_meter_mode)
  10550 {
  10551     uint32    total_bits;
  10552     int rv = BCM_E_NONE;
  10553 
  10554     switch (meter_attr->mode_type_v)
  10555     {
  10556         case uncompressed_mode:
  10557             rv = _bcm_policer_svc_meter_create_uncompress_mode(
  10558                     unit,
  10559                     &meter_attr->uncompressed_attr_selectors_v,
  10560                     group_mode, type, svc_meter_mode);
  10561             if (BCM_FAILURE(rv) && (rv == BCM_E_EXISTS)) {
  10562                 return rv;
  10563             }
  10564             break;
  10565         case compressed_mode:
  10566             BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_compress_mode(
  10567                     unit,
  10568                     &meter_attr->compressed_attr_selectors_v,
  10569                     group_mode, type, pkt_attr_selectors, svc_meter_mode));
  10570             break;
  10571         case udf_mode:
  10572         case udf_cascade_mode:
  10573         case udf_cascade_with_coupling_mode:
  10574             BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_udf_mode(
  10575                     unit,
  10576                     &meter_attr->udf_pkt_attr_selectors_v,
  10577                     group_mode, type, svc_meter_mode, &total_bits));
  10578             break;
  10579         case cascade_mode:
  10580             BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_cascade_mode(
  10581                     unit,
  10582                     &meter_attr->uncompressed_attr_selectors_v,
  10583                     group_mode, type, num_pol, svc_meter_mode));
  10584             break;
  10585 
  10586         default:
  10587             LOG_DEBUG(BSL_LS_BCM_POLICER,
  10588                       (BSL_META_U(unit,
  10589                                   "Invalid offset mode\n")));
  10590             return BCM_E_PARAM;
  10591     }
  10592     if (BCM_FAILURE(rv) && ((rv == BCM_E_FULL) || (rv == BCM_E_PARAM))) {
  10593         return rv;
  10594     }
  10595     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_reserve_mode(unit,
  10596                                     *svc_meter_mode,
  10597                                     group_mode,
  10598                                     meter_attr));
  10599     return BCM_E_NONE;
  10600 }
  10601 
  10602 /*
  10603  * Function:
  10604  *      _bcm_esw_policer_svc_meter_delete_mode
  10605  * Purpose:
  10606  *      Delete a meter offset mode
  10607  * Parameters:
  10608  *     Unit                  - (IN) unit number
  10609  *     svc_meter_mode        - (IN) offset mode
  10610  * Returns:
  10611  *     BCM_E_XXX
  10612  */
  10613 int  _bcm_esw_policer_svc_meter_delete_mode(
  10614         int                                  unit,
  10615         bcm_policer_svc_meter_mode_t         svc_meter_mode)
  10616 {
  10617     if (svc_meter_mode == 0) {
  10618         LOG_DEBUG(BSL_LS_BCM_POLICER,
  10619                   (BSL_META_U(unit,
  10620                               "Invalid mode passed: %d \n"),
  10621                    svc_meter_mode));
  10622         return BCM_E_PARAM; /*0 is Reserved */
  10623     }
  10624     if (svc_meter_mode > (BCM_POLICER_SVC_METER_MAX_MODE - 1)) {
  10625         LOG_DEBUG(BSL_LS_BCM_POLICER,
  10626                   (BSL_META_U(unit,
  10627                               "Invalid mode passed: %d \n"),
  10628                    svc_meter_mode));
  10629         return BCM_E_PARAM; /* Exceeding max allowed value */
  10630     }
  10631     return _bcm_policer_svc_meter_unreserve_mode(unit, svc_meter_mode);
  10632 }
  10633 
  10634 /*
  10635  * Function:
  10636  *      _bcm_esw_get_policer_id_from_index_offset
  10637  * Purpose:
  10638  *      Get policer id, given the HW policer index and offset_mode
  10639  * Parameters:
  10640  *     Unit                  - (IN) unit number
  10641  *     index                 - (IN) HW policer index
  10642  *     offset_mode           - (IN) offset mode
  10643  *     pid                   - (OUT) policer Id
  10644  * Returns:
  10645  *     BCM_E_XXX
  10646  */
  10647 int _bcm_esw_get_policer_id_from_index_offset(int unit, int index,
  10648                                               int offset_mode,
  10649                                               bcm_policer_t *pid)
  10650 {
  10651     int pool=0, size_of_pool=0;
  10652 
  10653 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  10654     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  10655         return bcmi_esw_get_policer_id_from_index_offset(
  10656                 unit, index, offset_mode, pid);
  10657     }
  10658 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  10659 
  10660     size_of_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  10661     if (index > 0) {
  10662        pool = index / size_of_pool;
  10663        index = index % size_of_pool;
  10664        *pid = (((offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT) +
  10665                     (pool << _shr_popcount(size_of_pool - 1)) + index);
  10666     } else {
  10667        *pid = 0;
  10668     }
  10669     return BCM_E_NONE;
  10670 }
  10671 
  10672 /*
  10673  * Function:
  10674  *      _bcm_esw_get_policer_table_index
  10675  * Purpose:
  10676  *     Get the HW policer index, given a policer id.
  10677  * Parameters:
  10678  *     Unit                  - (IN) unit number
  10679  *     policer               - (IN) policer Id
  10680  *     index                 - (OUT) HW policer index
  10681  * Returns:
  10682  *     BCM_E_XXX
  10683  */
  10684 int _bcm_esw_get_policer_table_index(int unit, bcm_policer_t policer,
  10685                                                          int *index)
  10686 {
  10687     int rv = BCM_E_NONE;
  10688     int size_pool = 0, num_pools = 0;
  10689     int pool=0;
  10690     int offset_mask = 0;
  10691     int pool_mask = 0, pool_offset = 0;
  10692 
  10693 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  10694     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  10695         return bcmi_esw_policer_table_index_get(unit, policer, index);
  10696     }
  10697 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  10698 
  10699     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  10700     num_pools =  SOC_INFO(unit).global_meter_pools;
  10701     offset_mask = size_pool - 1;
  10702     pool_offset = _shr_popcount(offset_mask);
  10703     pool_mask = (num_pools - 1) << pool_offset;
  10704     pool = ((policer & pool_mask) >> pool_offset);
  10705     *index = ((policer & offset_mask) + (pool * size_pool));
  10706     return rv;
  10707 }
  10708 
  10709 /*
  10710  * Function:
  10711  *      _bcm_esw_get_corres_policer_for_pool
  10712  * Purpose:
  10713  *     Get the policer Id, corresponding to a given policer id and specified pool.
  10714  * Parameters:
  10715  *     Unit                  - (IN) unit number
  10716  *     policer               - (IN) policer Id
  10717  *     new_pool              - (IN) new pool for which policer Id required
  10718  *     new_policer           - (OUT) New Policer Id for given pool in policer Id octuple
  10719  * Returns:
  10720  *     BCM_E_XXX
  10721  */
  10722 int _bcm_esw_get_corres_policer_for_pool(int unit, bcm_policer_t policer, int new_pool,
  10723                                                          bcm_policer_t *new_policer)
  10724 {
  10725     int size_pool, pool_offset, offset_val;
  10726     int num_pools;
  10727 
  10728     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  10729     pool_offset = _shr_popcount(size_pool - 1);
  10730     offset_val = policer & BCM_POLICER_GLOBAL_METER_MODE_MASK;
  10731     num_pools =  SOC_INFO(unit).global_meter_pools;
  10732 
  10733     if ((new_pool < 0) || (new_pool >= num_pools)) {
  10734         return BCM_E_INTERNAL;
  10735     }
  10736 
  10737     *new_policer = offset_val + (new_pool << pool_offset) + (policer & (size_pool - 1));
  10738 
  10739     return BCM_E_NONE;
  10740 }
  10741 
  10742 /*
  10743  * Function:
  10744  *      _bcm_esw_svm_source_traverse
  10745  * Purpose:
  10746  *     Traverse through all mem entires for a mem and call callback function
  10747  * Parameters:
  10748  *     Unit                  - (IN) unit number
  10749  *     mem                   - (IN) table
  10750  *     start_idx             - (IN) Start index where table traversal to begin
  10751  *     end_idx               - (IN) Last index where table traversal to stop
  10752  *     cb                    - (IN) Callback function
  10753  *     user_data             - (IN) Argument to call back function
  10754  * Returns:
  10755  *     BCM_E_XXX
  10756  */
  10757 bcm_error_t
  10758 _bcm_esw_svm_source_traverse(int unit, soc_mem_t mem, int start_idx,
  10759             int end_idx, _bcm_esw_svm_mem_entry_traverse_cb cb, void *user_data)
  10760 {
  10761     int rv = BCM_E_NONE;
  10762     int8 *buffer = NULL;
  10763     void *entry = NULL;
  10764     uint32 idx = 0, entry_idx = 0;
  10765     int mem_min = 0, mem_max = 0;
  10766     uint32 entry_dirty = 0, blk_dirty = 0;
  10767     uint32 chunk_size = 0, mem_entry_size = 0;
  10768 
  10769     mem_min = soc_mem_index_min(unit, mem);
  10770     mem_max = soc_mem_index_max(unit, mem);
  10771 
  10772     end_idx = (end_idx < 0) ? mem_max : end_idx;
  10773     start_idx = (start_idx < 0) ? mem_min : start_idx;
  10774 
  10775     if ((start_idx > mem_max) ||
  10776             (end_idx > mem_max) ||
  10777             (start_idx > end_idx)) {
  10778         return BCM_E_PARAM;
  10779     }
  10780 
  10781     chunk_size = ((end_idx - start_idx + 1) > BCM_SVM_DMA_CHUNK_SIZE) ?
  10782                 BCM_SVM_DMA_CHUNK_SIZE : (end_idx - start_idx + 1);
  10783     mem_entry_size = SOC_MEM_WORDS(unit, mem) * sizeof(uint32);
  10784 
  10785     buffer = soc_cm_salloc(unit, mem_entry_size * chunk_size, "svm mem buffer");
  10786     if (buffer == NULL)  {
  10787         return BCM_E_MEMORY;
  10788     }
  10789     for (idx = start_idx; idx <= end_idx; idx += chunk_size) {
  10790         chunk_size = ((end_idx - idx + 1) > BCM_SVM_DMA_CHUNK_SIZE) ?
  10791                     BCM_SVM_DMA_CHUNK_SIZE : (end_idx - idx + 1);
  10792 
  10793         if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
  10794                     idx, idx + chunk_size - 1, buffer)) != SOC_E_NONE) {
  10795             break;
  10796         }
  10797         for (entry_idx = 0; entry_idx < chunk_size; entry_idx++) {
  10798             entry = soc_mem_table_idx_to_pointer(unit, mem, void *,
  10799                             buffer, entry_idx);
  10800             entry_dirty = 0;
  10801             rv = (*cb)(unit, mem, idx + entry_idx, entry, user_data, &entry_dirty);
  10802             if (BCM_FAILURE(rv)) {
  10803                 break;
  10804             }
  10805             if (entry_dirty) {
  10806                 blk_dirty = 1;
  10807             }
  10808         }
  10809         if (BCM_SUCCESS(rv) && blk_dirty) {
  10810             rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10811                     idx, idx + chunk_size - 1, buffer);
  10812         }
  10813         if (BCM_FAILURE(rv)) {
  10814             break;
  10815         }
  10816     }
  10817 
  10818     if (buffer != NULL) {
  10819         soc_cm_sfree(unit, buffer);
  10820     }
  10821     return rv;
  10822 }
  10823 
  10824 /*
  10825  * Function:
  10826  *      _bcm_esw_global_meter_cleanup
  10827  * Purpose:
  10828  *       Cleanup the global meter(service meter) internal data structure on
  10829  *       init failure.
  10830  * Parameters:
  10831  *     Unit - unit number
  10832  * Returns:
  10833  *     BCM_E_XXX
  10834  */
  10835 int
  10836 _bcm_esw_global_meter_cleanup(int unit)
  10837 {
  10838     int rv = BCM_E_NONE;
  10839     int mode = 0;
  10840     int pool_id = 0, num_pools = 0;
  10841     int num_banks_per_pool = 1, bank_id = 0, handle_id = 0;
  10842     uint64 pkt_attr_selector_key_value;
  10843     uint32 svc_meter_mode;
  10844 
  10845 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  10846     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  10847         return bcmi_esw_global_meter_cleanup(unit);
  10848     }
  10849 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  10850 
  10851     if (0 == global_meter_status[unit].initialised) {
  10852         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  10853                     (BSL_META_U(unit,
  10854                                 "Global meter feature not initialized\n")));
  10855         return rv;
  10856     }
  10857     /* mutex destroy */
  10858     if (NULL != global_meter_mutex[unit]) {
  10859         sal_mutex_destroy(global_meter_mutex[unit]);
  10860         global_meter_mutex[unit] = NULL;
  10861     }
  10862     /* Free handles of index management for meter action */
  10863     if (NULL != meter_action_list_handle[unit]) {
  10864         shr_aidxres_list_destroy(meter_action_list_handle[unit]);
  10865         meter_action_list_handle[unit] = NULL;
  10866     }
  10867     /* Free handles of index management for meter table */
  10868     num_pools = SOC_INFO(unit).global_meter_pools;
  10869     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  10870 
  10871     for (pool_id = 0; pool_id < num_pools; pool_id++) {
  10872         for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) {
  10873             handle_id = pool_id * num_banks_per_pool + bank_id;
  10874             if (NULL != meter_alloc_list_handle[unit][handle_id]) {
  10875                 shr_aidxres_list_destroy(meter_alloc_list_handle[unit][handle_id]);
  10876                 meter_alloc_list_handle[unit][handle_id] = NULL;
  10877             }
  10878         }
  10879     }
  10880     if (NULL != global_meter_policer_bookkeep[unit]) {
  10881         sal_free(global_meter_policer_bookkeep[unit]);
  10882         global_meter_policer_bookkeep[unit] = NULL;
  10883     }
  10884     if (NULL != global_meter_hz_alloc_bookkeep[unit]) {
  10885         sal_free(global_meter_hz_alloc_bookkeep[unit]);
  10886         global_meter_hz_alloc_bookkeep[unit] = NULL;
  10887     }
  10888     if (NULL != global_meter_action_bookkeep[unit]) {
  10889         sal_free(global_meter_action_bookkeep[unit]);
  10890         global_meter_action_bookkeep[unit] = NULL;
  10891     }
  10892 
  10893     /* global_meter_offset_mode[][].attr_selectors needs to be freed */
  10894     for (mode = 1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) {
  10895         if (global_meter_offset_mode[unit][mode].used == 1) {
  10896             if (global_meter_offset_mode[unit][mode].attr_selectors != NULL) {
  10897                 sal_free(global_meter_offset_mode[unit][mode].attr_selectors);
  10898                 global_meter_offset_mode[unit][mode].attr_selectors = NULL;
  10899             }
  10900         }
  10901     }
  10902     if (svm_pkt_compressed_attr_maps_g[unit] != NULL) {
  10903         sal_free(svm_pkt_compressed_attr_maps_g[unit]);
  10904         svm_pkt_compressed_attr_maps_g[unit] = NULL;
  10905     }
  10906 
  10907     if (bcm_esw_svm_control[unit] != NULL) {
  10908         sal_free(bcm_esw_svm_control[unit]);
  10909         bcm_esw_svm_control[unit] = NULL;
  10910     }
  10911 
  10912     global_meter_status[unit].initialised = 0;
  10913     SOC_IF_ERROR_RETURN(
  10914            soc_mem_clear(unit, SVM_OFFSET_TABLEm, MEM_BLOCK_ALL, TRUE));
  10915     SOC_IF_ERROR_RETURN(
  10916            soc_mem_clear(unit, SVM_METER_TABLEm, MEM_BLOCK_ALL, TRUE));
  10917     SOC_IF_ERROR_RETURN(
  10918             soc_mem_clear(unit, SVM_MACROFLOW_INDEX_TABLEm, MEM_BLOCK_ALL, TRUE));
  10919     SOC_IF_ERROR_RETURN(
  10920             soc_mem_clear(unit, SVM_POLICY_TABLEm, MEM_BLOCK_ALL, TRUE));
  10921 
  10922     COMPILER_64_ZERO(pkt_attr_selector_key_value);
  10923     for (svc_meter_mode = 1;
  10924         svc_meter_mode < BCM_POLICER_SVC_METER_MAX_MODE;
  10925         svc_meter_mode++) {
  10926         SOC_IF_ERROR_RETURN(soc_reg_set(unit,
  10927             _pkt_attr_sel_key_reg[svc_meter_mode],
  10928             REG_PORT_ANY,
  10929             0,
  10930             pkt_attr_selector_key_value));
  10931         BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
  10932                         SVM_OFFSET_TABLEm, svc_meter_mode, NULL));
  10933     }
  10934     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  10935                 (BSL_META_U(unit,
  10936                             "Clening up global meter config\n")));
  10937     return rv;
  10938 }
  10939 
  10940 #ifdef BCM_APACHE_SUPPORT
  10941 static svm_dbg_01_entry_t ap_clr_tr_tbl[32] = \
  10942 {{{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}},
  10943  {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}},
  10944  {{0x44e3}}, {{0x4444}}, {{0x44e3}}, {{0x44ee}},
  10945  {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}},
  10946  {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}},
  10947  {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}},
  10948  {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}},
  10949  {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}}};
  10950 
  10951 static svm_dbg_02_entry_t ap_clr_hier_tr_tbl[4] = {
  10952 {{0x10290435, 0x04104104, 0x29040929}},
  10953 {{0x10274435, 0x04354104, 0x28840929}},
  10954 {{0x10090435, 0x04104104, 0x29043941}},
  10955 {{0x00000000, 0x00000000, 0x00000000}},
  10956 };
  10957 
  10958 static svm_dbg_03_entry_t ap_hier_cmtd_updt_tr_tbl[32] = \
  10959 {{{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}},
  10960  {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}},
  10961  {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}},
  10962  {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}};
  10963 
  10964 /*
  10965  * Function:
  10966  *     _bcm_svm_dbg_clr_tr_tbls
  10967  * Purpose:
  10968  *    Initialize color truth table
  10969  * Parameters:
  10970  *     Unit - unit number
  10971  * Returns:
  10972  *     BCM_E_XXX
  10973  */
  10974 STATIC
  10975 int _bcm_svm_dbg_clr_tr_tbls (int unit) {
  10976     int  idx = 0, rv = BCM_E_NONE, max_idx = 0;
  10977 
  10978     max_idx = soc_mem_index_max(unit,SVM_DBG_01m);
  10979     for (idx = 0; idx < max_idx; idx++) {
  10980         rv = WRITE_SVM_DBG_01m(unit,MEM_BLOCK_ANY,idx,&ap_clr_tr_tbl[idx]);
  10981         if (BCM_FAILURE(rv)) {
  10982             return (rv);
  10983         }
  10984     }
  10985 
  10986     max_idx = soc_mem_index_max(unit,SVM_DBG_02m);
  10987     for (idx = 0; idx < max_idx; idx++) {
  10988         rv = WRITE_SVM_DBG_02m(unit,MEM_BLOCK_ANY,idx,&ap_clr_hier_tr_tbl[idx]);
  10989         if (BCM_FAILURE(rv)) {
  10990             return (rv);
  10991         }
  10992     }
  10993 
  10994     max_idx = soc_mem_index_max(unit,SVM_DBG_03m);
  10995     for (idx = 0; idx < max_idx; idx++) {
  10996         rv = WRITE_SVM_DBG_03m(unit,MEM_BLOCK_ANY,idx,
  10997                                &ap_hier_cmtd_updt_tr_tbl[idx]);
  10998         if (BCM_FAILURE(rv)) {
  10999             return (rv);
  11000         }
  11001     }
  11002 
  11003     return rv;
  11004 }
  11005 #endif /* BCM_APACHE_SUPPORT */
  11006 
  11007 /*
  11008  * Function:
  11009  *     _bcm_policer_svm_dev_attr_info_initialize
  11010  * Purpose:
  11011  *    Initialize parmas which varies across devices for
  11012  *    global service meters
  11013  * Parameters:
  11014  *     Unit - unit number
  11015  * Returns:
  11016  *     BCM_E_XXX
  11017  */
  11018 STATIC int
  11019 _bcm_policer_svm_dev_attr_info_initialize (int unit)
  11020 {
  11021 #ifdef BCM_APACHE_SUPPORT
  11022     if (SOC_IS_APACHE(unit)) {
  11023         BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 2;
  11024         BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 32;
  11025         BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size =
  11026                                 BCM_POLICER_SVC_METER_SB2_ING_PORT_ATTR_SIZE;
  11027         BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size =
  11028                                 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE;
  11029         BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &ap_pkt_res[0];
  11030         BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos =
  11031                                 &sb2_pkt_attr_bit_pos[0];
  11032         BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos =
  11033                                 &sb2_cmprsd_pkt_attr_bit_pos[0];
  11034         BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos =
  11035                                 &sb2_pkt_cmprsd_attr_map_bit_pos[0];
  11036     } else
  11037 #endif
  11038 #ifdef BCM_SABER2_SUPPORT
  11039     if (SOC_IS_SABER2(unit)) {
  11040         BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1;
  11041         BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 32;
  11042         BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size =
  11043                                 BCM_POLICER_SVC_METER_SB2_ING_PORT_ATTR_SIZE;
  11044         BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size =
  11045                                 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE;
  11046         BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &sb2_pkt_res[0];
  11047         BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos =
  11048                                 &sb2_pkt_attr_bit_pos[0];
  11049         BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos =
  11050                                 &sb2_cmprsd_pkt_attr_bit_pos[0];
  11051         BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos =
  11052                                 &sb2_pkt_cmprsd_attr_map_bit_pos[0];
  11053     } else
  11054 #endif
  11055 #ifdef BCM_KATANA2_SUPPORT
  11056     if (SOC_IS_KATANA2(unit)) {
  11057         BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1;
  11058         BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 33;
  11059         BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size =
  11060                                 BCM_POLICER_SVC_METER_KT2_ING_PORT_ATTR_SIZE;
  11061         BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size =
  11062                                 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE;
  11063         BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &kt2_pkt_res[0];
  11064         BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos =
  11065                                 &kt2_pkt_attr_bit_pos[0];
  11066         BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos =
  11067                                 &kt2_cmprsd_pkt_attr_bit_pos[0];
  11068         BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos =
  11069                                 &kt2_pkt_cmprsd_attr_map_bit_pos[0];
  11070     } else
  11071 #endif
  11072     { /* Default. KT/TR3 */
  11073         BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1;
  11074         BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos =
  11075                                 kt_pkt_attr_bit_pos[pkt_attr_int_pri].start_bit;
  11076         BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size =
  11077                                 BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE;
  11078         BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size =
  11079                                 BCM_POLICER_SVC_METER_SVP_TYPE_ATTR_SIZE;
  11080         BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &kt_pkt_res[0];
  11081         BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos =
  11082                                 &kt_pkt_attr_bit_pos[0];
  11083         BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos =
  11084                                 &kt_pkt_attr_bit_pos[0];
  11085         BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos =
  11086                                 &kt_pkt_cmprsd_attr_map_bit_pos[0];
  11087     }
  11088 
  11089 #ifdef BCM_TRIUMPH3_SUPPORT
  11090     if (SOC_IS_TRIUMPH3(unit)) {
  11091         BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &tr3_pkt_res[0];
  11092     }
  11093 #endif
  11094     return BCM_E_NONE;
  11095 }
  11096 
  11097 /*
  11098  * Function:
  11099  *     _bcm_policer_svm_source_initialize
  11100  * Purpose:
  11101  *    Initialize service metering source from various tables
  11102  * Parameters:
  11103  *     Unit - unit number
  11104  * Returns:
  11105  *     BCM_E_XXX
  11106  */
  11107 STATIC bcm_error_t
  11108 _bcm_policer_svm_source_initialize(int unit)
  11109 {
  11110     soc_mem_t table;
  11111     _bcm_policer_svm_source_type_t mem_index;
  11112 
  11113     for (mem_index = 0; mem_index < _BCM_SVM_MEM_COUNT; mem_index++) {
  11114         BCM_SVM_SOURCE(unit, mem_index).table = INVALIDm;
  11115         BCM_SVM_SOURCE(unit, mem_index).offset_mode = INVALIDf;
  11116         BCM_SVM_SOURCE(unit, mem_index).meter_index = INVALIDf;
  11117         table = INVALIDm;
  11118         switch(mem_index) {
  11119             case _BCM_SVM_MEM_PORT:
  11120                 table = PORT_TABm;
  11121                 break;
  11122             case _BCM_SVM_MEM_VLAN:
  11123                 table = VLAN_TABm;
  11124                 break;
  11125             case _BCM_SVM_MEM_VFI:
  11126                 table = VFIm;
  11127                 break;
  11128             case _BCM_SVM_MEM_SOURCE_VP:
  11129                 table = SOURCE_VPm;
  11130                 break;
  11131             case _BCM_SVM_MEM_VLAN_XLATE:
  11132                 table = VLAN_XLATEm;
  11133 #ifdef BCM_TRIUMPH3_SUPPORT
  11134                 if (SOC_IS_TRIUMPH3(unit)) {
  11135                     table = VLAN_XLATE_EXTDm;
  11136                 }
  11137 #endif
  11138                 break;
  11139             case _BCM_SVM_MEM_VFP_POLICY_TABLE:
  11140                 table = VFP_POLICY_TABLEm;
  11141                 break;
  11142             /* coverity[dead_error_begin : FALSE] */
  11143             default :
  11144                 break;
  11145         }
  11146         BCM_SVM_SOURCE(unit, mem_index).table = table;
  11147 #ifdef BCM_TRIUMPH3_SUPPORT
  11148         if (SOC_IS_TRIUMPH3(unit) && (mem_index == _BCM_SVM_MEM_VLAN_XLATE)) {
  11149             if (SOC_MEM_FIELD_VALID(unit, table,
  11150                     XLATE__SVC_METER_OFFSET_MODEf)) {
  11151                 BCM_SVM_SOURCE(unit, mem_index).offset_mode =
  11152                         XLATE__SVC_METER_OFFSET_MODEf;
  11153             }
  11154             if (SOC_MEM_FIELD_VALID(unit, table,
  11155                     XLATE__SVC_METER_INDEXf)) {
  11156                 BCM_SVM_SOURCE(unit, mem_index).meter_index =
  11157                         XLATE__SVC_METER_INDEXf;
  11158             }
  11159             continue;
  11160         }
  11161 #endif
  11162         if (SOC_MEM_FIELD_VALID(unit, table, SVC_METER_OFFSET_MODEf)) {
  11163             BCM_SVM_SOURCE(unit, mem_index).offset_mode =
  11164                     SVC_METER_OFFSET_MODEf;
  11165         }
  11166         if (SOC_MEM_FIELD_VALID(unit, table, SVC_METER_INDEXf)) {
  11167             BCM_SVM_SOURCE(unit, mem_index).meter_index =
  11168                     SVC_METER_INDEXf;
  11169         }
  11170     }
  11171     return BCM_E_NONE;
  11172 }
  11173 
  11174 /*
  11175  * Function:
  11176  *      bcm_esw_global_meter_init
  11177  * Purpose:
  11178  *     Initialise service meter data-structure
  11179  * Parameters:
  11180  *     Unit - unit number
  11181  * Returns:
  11182  *     BCM_E_XXX
  11183  */
  11184 int
  11185 bcm_esw_global_meter_init(int unit)
  11186 {
  11187     int rv = BCM_E_NONE;
  11188     uint32 service_meter_control = 0;
  11189     uint32 ing_svm_control = 0;
  11190     int mode = 0;
  11191     uint32 num_pools = 0, size_pool = 0, total_size = 0, action_size = 0;
  11192     uint32 num_banks_per_pool = 1, handle_id = 0, bank_id = 0;
  11193     uint32 size_bank = 0, block_factor = 0;
  11194     uint32 max_size_pool = 0;
  11195     uint32 pool_id = 0, index = 0;
  11196     soc_reg_t arb_reg;
  11197     soc_field_t fields[2];
  11198     uint32      vals[2] = {1,1};
  11199     int         no_fields = 0;
  11200 #ifdef BCM_WARM_BOOT_SUPPORT
  11201     int size = 0;
  11202     soc_scache_handle_t scache_handle;
  11203     uint8  *policer_state;
  11204 #endif
  11205 
  11206 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11207     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11208         return bcmi_esw_global_meter_init(unit);
  11209     }
  11210 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11211 
  11212     if (1 == global_meter_status[unit].initialised) {
  11213         _bcm_esw_global_meter_cleanup(unit);
  11214     }
  11215 
  11216     if (!soc_feature(unit, soc_feature_global_meter)) {
  11217         return BCM_E_UNAVAIL;
  11218     }
  11219 
  11220     if (!soc_property_get(unit, spn_GLOBAL_METER_CONTROL, 1)) {
  11221         service_meter_control = BCM_POLICER_GLOBAL_METER_DISABLE;
  11222     }
  11223     SOC_IF_ERROR_RETURN(soc_reg32_get( unit,
  11224         ING_SVM_CONTROLr,
  11225         REG_PORT_ANY,
  11226         0,
  11227         &ing_svm_control));
  11228 
  11229     soc_reg_field_set(unit,
  11230         ING_SVM_CONTROLr,
  11231         &ing_svm_control,
  11232         BLOCK_DISABLEf,
  11233         service_meter_control);
  11234 
  11235     SOC_IF_ERROR_RETURN(soc_reg32_set(unit,
  11236         ING_SVM_CONTROLr,
  11237         REG_PORT_ANY,
  11238         0,
  11239         ing_svm_control));
  11240 
  11241     if ( BCM_POLICER_GLOBAL_METER_DISABLE == service_meter_control) {
  11242         global_meter_status[unit].initialised = 0;
  11243         LOG_WARN(BSL_LS_BCM_POLICER,
  11244                  (BSL_META_U(unit,
  11245                              "GLOBAL METER FEATURE disabled "
  11246                              "at HW for unit %d\n"), unit));
  11247         return rv;
  11248     }
  11249 
  11250     _GLOBAL_METER_XGS3_ALLOC(bcm_esw_svm_control[unit],
  11251         sizeof(_bcm_policer_global_meter_control_t),
  11252         "global service meter control");
  11253 
  11254     rv = _bcm_policer_svm_dev_attr_info_initialize(unit);
  11255     if (BCM_FAILURE(rv))    {
  11256         _bcm_esw_global_meter_cleanup(unit);
  11257         LOG_ERROR(BSL_LS_BCM_POLICER,
  11258                 (BSL_META_U(unit,
  11259                 "Chip Specific init failed\n")));
  11260             return rv;
  11261     }
  11262     rv = _bcm_policer_svm_source_initialize(unit);
  11263     if (BCM_FAILURE(rv))    {
  11264         _bcm_esw_global_meter_cleanup(unit);
  11265         LOG_ERROR(BSL_LS_BCM_POLICER,
  11266                 (BSL_META_U(unit,
  11267                 "SVM source init failed\n")));
  11268             return rv;
  11269     }
  11270 
  11271     num_pools =  SOC_INFO(unit).global_meter_pools;
  11272     size_pool =  SOC_INFO(unit).global_meter_size_of_pool;
  11273     max_size_pool = SOC_INFO(unit).global_meter_max_size_of_pool;
  11274     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  11275     size_bank = size_pool / num_banks_per_pool;
  11276     total_size = num_pools * max_size_pool;
  11277     if ((total_size) > (soc_mem_index_max(unit, SVM_METER_TABLEm) + 1))
  11278     {
  11279         LOG_ERROR(BSL_LS_BCM_POLICER,
  11280                   (BSL_META_U(unit,
  11281                               "Number of global meters exceeding "
  11282                               "its max value\n")));
  11283         return BCM_E_INTERNAL;
  11284     }
  11285 
  11286     action_size = SOC_INFO(unit).global_meter_action_size;
  11287     if ((action_size) > (soc_mem_index_max(unit, SVM_POLICY_TABLEm) + 1))
  11288     {
  11289         LOG_ERROR(BSL_LS_BCM_POLICER,
  11290                   (BSL_META_U(unit,
  11291                               "Global meter actions exceeding "
  11292                               "its max value\n")));
  11293         return BCM_E_INTERNAL;
  11294     }
  11295 
  11296     /* Init the offset table 0 such that it can be used for non-offset
  11297       based metering */
  11298     BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit,
  11299                         SVM_OFFSET_TABLEm, 0, NULL));
  11300 
  11301     /* Initialize bookkeeping data structure */
  11302     for (mode=1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) {
  11303         sal_memset(&global_meter_offset_mode[unit][mode],
  11304                      0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t));
  11305     }
  11306 
  11307     /* Allocate global compression attr map */
  11308     _GLOBAL_METER_XGS3_ALLOC(svm_pkt_compressed_attr_maps_g[unit],
  11309                 sizeof (_bcm_policer_pkt_compressed_attr_maps_t),
  11310                 "compressed attr map");
  11311     if (NULL == svm_pkt_compressed_attr_maps_g[unit]) {
  11312         _bcm_esw_global_meter_cleanup(unit);
  11313         LOG_ERROR(BSL_LS_BCM_POLICER,
  11314                 (BSL_META_U(unit,
  11315                             "Unable to allocate memory for policer "
  11316                             "compressed attribute map data structure\n")));
  11317         return BCM_E_MEMORY;
  11318     }
  11319 
  11320      /* Allocate policer lookup hash. */
  11321     _GLOBAL_METER_XGS3_ALLOC(global_meter_policer_bookkeep[unit],
  11322                _GLOBAL_METER_HASH_SIZE * \
  11323                sizeof(_global_meter_policer_control_t *), "Global meter hash");
  11324     if (NULL == global_meter_policer_bookkeep[unit]) {
  11325         _bcm_esw_global_meter_cleanup(unit);
  11326         LOG_ERROR(BSL_LS_BCM_POLICER,
  11327                   (BSL_META_U(unit,
  11328                               "Unable to allocate memory for policer bookkeep "
  11329                               "data structure\n")));
  11330         return (BCM_E_MEMORY);
  11331     }
  11332      /* Allocate horizontal allocation management data structure */
  11333     _GLOBAL_METER_XGS3_ALLOC(global_meter_hz_alloc_bookkeep[unit],
  11334                       size_pool * sizeof(_global_meter_horizontal_alloc_t),
  11335                                             "Global meter horizontal alloc");
  11336     if (NULL == global_meter_hz_alloc_bookkeep[unit]) {
  11337         _bcm_esw_global_meter_cleanup(unit);
  11338         LOG_ERROR(BSL_LS_BCM_POLICER,
  11339                   (BSL_META_U(unit,
  11340                               "Unable to allocate memory for hz alloc bookkeep "
  11341                               "data structure\n")));
  11342         return (BCM_E_MEMORY);
  11343     }
  11344 
  11345     for (index = 0; index < size_pool; index++) {
  11346         global_meter_hz_alloc_bookkeep[unit][index].alloc_bit_map = 0xff;
  11347     }
  11348 
  11349      /* Allocate meter action management data structure */
  11350     _GLOBAL_METER_XGS3_ALLOC(global_meter_action_bookkeep[unit],
  11351                    action_size * sizeof(bcm_policer_global_meter_action_bookkeep_t),
  11352                                             "Global meter action alloc");
  11353     if (NULL == global_meter_action_bookkeep[unit]) {
  11354         _bcm_esw_global_meter_cleanup(unit);
  11355         LOG_ERROR(BSL_LS_BCM_POLICER,
  11356                   (BSL_META_U(unit,
  11357                               "Unable to allocate memory for meter action bookkeep "
  11358                               "data structure\n")));
  11359         return (BCM_E_MEMORY);
  11360     }
  11361     if (global_meter_mutex[unit] == NULL) {
  11362         global_meter_mutex[unit] = sal_mutex_create("Global meter mutex");
  11363         if (global_meter_mutex[unit] == NULL) {
  11364             _bcm_esw_global_meter_cleanup(unit);
  11365             LOG_ERROR(BSL_LS_BCM_POLICER,
  11366                       (BSL_META_U(unit,
  11367                                   "Unable to create mutex\n")));
  11368             return BCM_E_MEMORY;
  11369         }
  11370     }
  11371 
  11372     /* Index management for meter action */
  11373     if ( NULL != meter_action_list_handle[unit]) {
  11374         shr_aidxres_list_destroy(meter_action_list_handle[unit]);
  11375         meter_action_list_handle[unit] = NULL;
  11376     }
  11377     /* Create it */
  11378     if (shr_aidxres_list_create(
  11379                       &meter_action_list_handle[unit],
  11380                       0,(action_size - 1),
  11381                       0,(action_size - 1),
  11382                       8,
  11383                       "global_meter_action") != BCM_E_NONE) {
  11384         _bcm_esw_global_meter_cleanup(unit);
  11385         LOG_ERROR(BSL_LS_BCM_POLICER,
  11386                   (BSL_META_U(unit,
  11387                               "Couldn't create alligned list "
  11388                               "for global meter action\n")));
  11389         return BCM_E_INTERNAL;
  11390     }
  11391     /* Reserve the first entry in action table */
  11392     rv = shr_aidxres_list_reserve_block(
  11393                           meter_action_list_handle[unit],0,1);
  11394     if (BCM_FAILURE(rv)) {
  11395         _bcm_esw_global_meter_cleanup(unit);
  11396         LOG_ERROR(BSL_LS_BCM_POLICER,
  11397                   (BSL_META_U(unit,
  11398                               "Not able to reserve first entry "
  11399                               "in action table\n")));
  11400         return (rv);
  11401     }
  11402 
  11403     block_factor = _shr_popcount(size_bank - 1) - 1;
  11404 
  11405     /* Index management for policer */
  11406     for (pool_id = 0; pool_id < num_pools; pool_id++) {
  11407         for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) {
  11408             handle_id = pool_id * num_banks_per_pool + bank_id;
  11409             if ( NULL != meter_alloc_list_handle[unit][handle_id]) {
  11410                 shr_aidxres_list_destroy(
  11411                                meter_alloc_list_handle[unit][handle_id]);
  11412                 meter_alloc_list_handle[unit][handle_id] = NULL;
  11413             }
  11414             /* Create it */
  11415             if (shr_aidxres_list_create(
  11416                   &meter_alloc_list_handle[unit][handle_id],
  11417                   0, (size_bank - 1), 0, (size_bank - 1),
  11418                   block_factor, "global_meter_policer") != BCM_E_NONE)
  11419             {
  11420                 _bcm_esw_global_meter_cleanup(unit);
  11421                 LOG_ERROR(BSL_LS_BCM_POLICER,
  11422                           (BSL_META_U(unit,
  11423                                       "Couldn't create alligned list for "
  11424                                       "global meter policer\n")));
  11425                 return BCM_E_INTERNAL;
  11426             }
  11427         }
  11428     }
  11429 
  11430     /*
  11431      * When SVC_METER_INDEX=0 in source tables it is treated as Disabled.
  11432      * A value of 0 for SVC_METER_INDEXf is pointed to (Pool=0, Index=0) in
  11433      * SVM_METER_TABLE table as per implementation. Here, reserve the first
  11434      * entry in policer table so that user is not allotted this index. All
  11435      * other indices in the table is valid and can be used by user.
  11436      */
  11437     pool_id = 0;
  11438     handle_id = 0;
  11439     rv = shr_aidxres_list_reserve_block(
  11440             meter_alloc_list_handle[unit][handle_id], 0, 1);
  11441     if (BCM_FAILURE(rv)) {
  11442         _bcm_esw_global_meter_cleanup(unit);
  11443         LOG_ERROR(BSL_LS_BCM_POLICER,
  11444                 (BSL_META_U(unit,
  11445                             "Not able to reserve first entry "
  11446                             "in policer table\n")));
  11447         return (rv);
  11448     }
  11449     rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool_id, 0);
  11450     if (!BCM_SUCCESS(rv)) {
  11451         rv = shr_aidxres_list_free(meter_alloc_list_handle[unit]\
  11452                 [handle_id], 0);
  11453         if (!BCM_SUCCESS(rv)) {
  11454             _bcm_esw_global_meter_cleanup(unit);
  11455             LOG_DEBUG(BSL_LS_BCM_POLICER,
  11456                     (BSL_META_U(unit,
  11457                                 "Not able to reserve first entry "
  11458                                 "in policer table\n")));
  11459             return BCM_E_INTERNAL;
  11460         }
  11461     }
  11462 #ifdef BCM_APACHE_SUPPORT
  11463     if (SOC_IS_APACHE(unit)) {
  11464         rv = _bcm_svm_dbg_clr_tr_tbls(unit);
  11465         if (BCM_FAILURE(rv)) {
  11466             LOG_DEBUG(BSL_LS_BCM_POLICER,
  11467                       (BSL_META_U(unit,
  11468                                   "Failed to set color truth table\n")));
  11469             return rv;
  11470         }
  11471     }
  11472 #endif /* BCM_APACHE_SUPPORT */
  11473 
  11474 #ifdef BCM_WARM_BOOT_SUPPORT
  11475     if (SOC_WARM_BOOT(unit)) {
  11476         rv = _bcm_esw_global_meter_reinit(unit);
  11477         if (!BCM_SUCCESS(rv)) {
  11478             _bcm_esw_global_meter_cleanup(unit);
  11479             LOG_ERROR(BSL_LS_BCM_POLICER,
  11480                       (BSL_META_U(unit,
  11481                                   "Warm boot init failed\n")));
  11482             return BCM_E_INTERNAL;
  11483         }
  11484     } else { /* cold boot */
  11485         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
  11486 
  11487         BCM_IF_ERROR_RETURN(
  11488                 _bcm_esw_svc_meter_wb_size_calc(unit, &size));
  11489         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
  11490                                      size, &policer_state,
  11491                                      BCM_WB_DEFAULT_VERSION, NULL);
  11492         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  11493             LOG_DEBUG(BSL_LS_BCM_POLICER,
  11494                       (BSL_META_U(unit,
  11495                                   "Scache Memory not available\n")));
  11496             return rv;
  11497         }
  11498         rv = BCM_E_NONE;
  11499     }
  11500 #endif
  11501     global_meter_status[unit].initialised = 1;
  11502     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11503                 (BSL_META_U(unit,
  11504                             "GLOBAL METER FEATURE initialised\n")));
  11505     /* coverity[result_independent_of_operands] */
  11506     arb_reg = (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2_64r) ?
  11507                AUX_ARB_CONTROL_2_64r : AUX_ARB_CONTROL_2r);
  11508 
  11509     if (SOC_IS_TRIUMPH3(unit)) {
  11510         fields[0] = SVC_MTR_REFRESH_ENABLEf;
  11511         no_fields = 1;
  11512     } else {
  11513         fields[0] = SVM_MASTER_REFRESH_RATEf;
  11514         fields[1] = SVM_MASTER_REFRESH_ENABLEf;
  11515         no_fields = 2;
  11516     }
  11517 
  11518     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit,arb_reg,REG_PORT_ANY,\
  11519                                                 no_fields,fields,vals));
  11520 
  11521     return rv;
  11522 }
  11523 
  11524 /*
  11525  * Function:
  11526  *     _bcm_esw_is_global_policer
  11527  * Purpose:
  11528  *     Validate the given policer id
  11529  * Parameters:
  11530  *     Unit              - (IN) unit number
  11531  *     policer           - (IN) policer Id
  11532  *     is_global_policer - (OUT) is globle policer or not
  11533  * Returns:
  11534  *     BCM_E_XXX
  11535  */
  11536 int _bcm_esw_is_global_policer(
  11537     int unit,
  11538     bcm_policer_t policer_id,
  11539     int *is_global_policer)
  11540 {
  11541     POL_CHECK_NULL_PARAMETER(unit, is_global_policer);
  11542     *is_global_policer = FALSE;
  11543 
  11544 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11545     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11546         int rv = bcmi_policer_mode_id_validate(unit,
  11547             POLICER_ID_MODE_ID_GET(policer_id));
  11548         if (BCM_SUCCESS(rv)) {
  11549             *is_global_policer = TRUE;
  11550         } else {
  11551             *is_global_policer = FALSE;
  11552         }
  11553     }
  11554 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11555 
  11556 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  11557     defined(BCM_APACHE_SUPPORT)
  11558     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
  11559         int offset_mode;
  11560         offset_mode = ((policer_id & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11561                        BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11562         *is_global_policer = (offset_mode) ? TRUE : FALSE ;
  11563     }
  11564 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
  11565           BCM_APACHE_SUPPORT */
  11566 
  11567     return BCM_E_NONE;
  11568 }
  11569 
  11570 /*
  11571  * Function:
  11572  *      _bcm_esw_policer_validate
  11573  * Purpose:
  11574  *      Validate the given policer id
  11575  * Parameters:
  11576  *     Unit                  - (IN) unit number
  11577  *     policer               - (IN) policer Id
  11578  * Returns:
  11579  *     BCM_E_XXX
  11580  */
  11581 int   _bcm_esw_policer_validate(int unit, bcm_policer_t *policer)
  11582 {
  11583     int rv = BCM_E_NONE;
  11584     int index = 0;
  11585     uint32 offset_mode = 0;
  11586 
  11587 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11588     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11589         POL_CHECK_NULL_PARAMETER(unit, policer);
  11590         return bcmi_esw_policer_validate(unit, *policer);
  11591     }
  11592 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11593 
  11594     if( *policer == 0) {
  11595         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11596                     (BSL_META_U(unit,
  11597                                 "Policer id passed is 0 \n")));
  11598         return rv;
  11599     }
  11600     _bcm_esw_get_policer_table_index(unit, *policer, &index);
  11601     if (index > (soc_mem_index_max(unit, SVM_METER_TABLEm)))
  11602     {
  11603         LOG_DEBUG(BSL_LS_BCM_POLICER,
  11604                   (BSL_META_U(unit,
  11605                               "Invalid table index for SVM_POLICY_TABLE\n")));
  11606         return BCM_E_PARAM;
  11607     }
  11608     offset_mode = ((*policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11609                                   BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11610     if (offset_mode >= 1) {
  11611         offset_mode = offset_mode - 1;
  11612     }
  11613     if (offset_mode > BCM_POLICER_SVC_METER_MAX_MODE)
  11614     {
  11615         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11616                     (BSL_META_U(unit,
  11617                                 "Invalid Offset mode \n")));
  11618         return BCM_E_PARAM;
  11619 
  11620     }
  11621     return rv;
  11622 }
  11623 
  11624 /*
  11625  * Function:
  11626  *      _bcm_global_meter_macro_policer_validate
  11627  * Purpose:
  11628  *      Validate if given policer is configured in the system and
  11629  *      qualify as MACRO policer
  11630  * Parameters:
  11631  *     unit                  - (IN) unit number
  11632  *     policer               - (IN) policer Id
  11633  * Returns:
  11634  *     BCM_E_NONE
  11635  *     BCM_E_CONFIG
  11636  *     BCM_E_NOT_FOUND
  11637  */
  11638 STATIC int
  11639 _bcm_global_meter_macro_policer_validate(int unit, bcm_policer_t policer)
  11640 {
  11641     int rv = BCM_E_NONE;
  11642     uint32 offset_mode = 0;
  11643     _global_meter_policer_control_t *policer_control = NULL;
  11644 
  11645     rv = _bcm_global_meter_policer_get(unit, policer, &policer_control);
  11646     if ((rv != BCM_E_NONE) || (policer_control == NULL)) {
  11647         return BCM_E_NOT_FOUND;
  11648     }
  11649     offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11650                                   BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11651 
  11652     /* Validate policer control */
  11653     if ((offset_mode > 1) ||
  11654         (policer_control->no_of_policers != 1) ||
  11655         (policer_control->grp_mode != bcmPolicerGroupModeSingle) ||
  11656         (policer_control->direction != GLOBAL_METER_ALLOC_VERTICAL)) {
  11657         rv = BCM_E_CONFIG;
  11658     }
  11659     return rv;
  11660 }
  11661 
  11662 /*
  11663  * Function:
  11664  *      _bcm_esw_policer_increment_ref_count
  11665  * Purpose:
  11666  *      Increment the policer usage reference count
  11667  * Parameters:
  11668  *     unit                  - (IN) unit number
  11669  *     policer               - (IN) policer Id
  11670  * Returns:
  11671  *     BCM_E_XXX
  11672  */
  11673 int  _bcm_esw_policer_increment_ref_count(int unit, bcm_policer_t policer)
  11674 {
  11675     int rv = BCM_E_NONE;
  11676     int offset_mode = 0;
  11677     _global_meter_policer_control_t *policer_control = NULL;
  11678 
  11679 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11680     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11681         return bcmi_esw_policer_increment_ref_count(unit, policer);
  11682     }
  11683 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11684 
  11685     /* validate policer id */
  11686     rv = _bcm_esw_policer_validate(unit, &policer);
  11687     if (BCM_FAILURE(rv)) {
  11688         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11689                     (BSL_META_U(unit,
  11690                                 "Invalid policer id passed: %x \n"),
  11691                      policer));
  11692         return (rv);
  11693     }
  11694     offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11695                    BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11696     if (offset_mode >= 1) {
  11697         offset_mode = offset_mode - 1;
  11698     }
  11699     GLOBAL_METER_LOCK(unit);
  11700     if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v ==
  11701         cascade_mode) ||
  11702         (global_meter_offset_mode[unit][offset_mode].type ==
  11703                 bcmPolicerGroupModeTypeCascade) ||
  11704         (global_meter_offset_mode[unit][offset_mode].type ==
  11705                 bcmPolicerGroupModeTypeCascadeWithCoupling)) {
  11706         /*
  11707          * SDK alway allocates 8 policer IDs in cascaded mode,
  11708          * and each policer is configurable for the purpose of
  11709          * bandwidth sharing.
  11710          */
  11711         rv = _bcm_global_meter_policer_get(unit, policer, &policer_control);
  11712     } else {
  11713         rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control);
  11714     }
  11715     if (BCM_FAILURE(rv)) {
  11716         GLOBAL_METER_UNLOCK(unit);
  11717         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11718                     (BSL_META_U(unit,
  11719                                 "Unable to get policer control for policer "
  11720                                 "id %d\n"), policer));
  11721         return (rv);
  11722     }
  11723     policer_control->ref_count++;
  11724     GLOBAL_METER_UNLOCK(unit);
  11725     return rv;
  11726 }
  11727 
  11728 /*
  11729  * Function:
  11730  *      _bcm_esw_policer_decrement_ref_count
  11731  * Purpose:
  11732  *     Decrement the policer usage refernce count
  11733  * Parameters:
  11734  *     unit                  - (IN) unit number
  11735  *     policer               - (IN) policer Id
  11736  * Returns:
  11737  *     BCM_E_XXX
  11738  */
  11739 int  _bcm_esw_policer_decrement_ref_count(int unit, bcm_policer_t policer)
  11740 {
  11741     int rv = BCM_E_NONE;
  11742     int offset_mode = 0;
  11743     _global_meter_policer_control_t *policer_control = NULL;
  11744 
  11745 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11746     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11747         return bcmi_esw_policer_decrement_ref_count(unit, policer);
  11748     }
  11749 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11750 
  11751     /* validate policer id */
  11752     rv = _bcm_esw_policer_validate(unit, &policer);
  11753     if (BCM_FAILURE(rv)) {
  11754         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11755                     (BSL_META_U(unit,
  11756                                 "Invalid policer id passed: %x \n"),
  11757                      policer));
  11758         return (rv);
  11759     }
  11760     offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11761                    BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11762     if (offset_mode >= 1) {
  11763         offset_mode = offset_mode - 1;
  11764     }
  11765     GLOBAL_METER_LOCK(unit);
  11766     if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v ==
  11767         cascade_mode) ||
  11768         (global_meter_offset_mode[unit][offset_mode].type ==
  11769                 bcmPolicerGroupModeTypeCascade) ||
  11770         (global_meter_offset_mode[unit][offset_mode].type ==
  11771                 bcmPolicerGroupModeTypeCascadeWithCoupling)) {
  11772         /*
  11773          * SDK alway allocates 8 policer IDs in cascaded mode,
  11774          * and each policer is configurable for the purpose of
  11775          * bandwidth sharing.
  11776          */
  11777         rv = _bcm_global_meter_policer_get(unit, policer, &policer_control);
  11778     } else {
  11779         rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control);
  11780     }
  11781     if (BCM_FAILURE(rv)) {
  11782         GLOBAL_METER_UNLOCK(unit);
  11783         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11784                     (BSL_META_U(unit,
  11785                                 "Unable to get policer control for policer "
  11786                                 "id %d\n"), policer));
  11787         return (rv);
  11788     }
  11789     if (policer_control->ref_count > 0) {
  11790         policer_control->ref_count--;
  11791     }
  11792     GLOBAL_METER_UNLOCK(unit);
  11793     return rv;
  11794 }
  11795 
  11796 /*
  11797  * Function:
  11798  *      _bcm_policer_svm_source_index_get
  11799  * Purpose:
  11800  *     Get the Enum value corresponding to memory table
  11801  * Parameters:
  11802  *     unit                  - (IN) unit number
  11803  *     table                 - (IN) Memory table
  11804  *     mem_index             - (OUT) Corresponding Enum
  11805  *                              in _bcm_policer_svm_source_type_t
  11806  * Returns:
  11807  *     BCM_E_XXX
  11808  */
  11809 bcm_error_t
  11810 _bcm_policer_svm_source_index_get(int unit, soc_mem_t table,
  11811                                 _bcm_policer_svm_source_type_t *mem_index)
  11812 {
  11813     switch (table) {
  11814         case PORT_TABm:
  11815             *mem_index = _BCM_SVM_MEM_PORT;
  11816             break;
  11817         case VLAN_TABm:
  11818             *mem_index = _BCM_SVM_MEM_VLAN;
  11819             break;
  11820         case VFIm:
  11821             *mem_index = _BCM_SVM_MEM_VFI;
  11822             break;
  11823         case SOURCE_VPm:
  11824             *mem_index = _BCM_SVM_MEM_SOURCE_VP;
  11825             break;
  11826 #ifdef BCM_TRIUMPH3_SUPPORT
  11827         case VLAN_XLATE_EXTDm:
  11828             /* passthru */
  11829             /* coverity[fallthrough: FALSE] */
  11830 #endif
  11831         case VLAN_XLATEm:
  11832             *mem_index = _BCM_SVM_MEM_VLAN_XLATE;
  11833             break;
  11834         case VFP_POLICY_TABLEm :
  11835             *mem_index = _BCM_SVM_MEM_VFP_POLICY_TABLE;
  11836             break;
  11837         default :
  11838             return BCM_E_INTERNAL;
  11839     }
  11840     return BCM_E_NONE;
  11841 }
  11842 
  11843 /*
  11844  * Function:
  11845  *      _bcm_esw_add_policer_to_table
  11846  * Purpose:
  11847  *      Add policer id to the table entry specified
  11848  * Parameters:
  11849  *     unit                  - (IN) unit number
  11850  *     policer               - (IN) policer Id
  11851  *     table                 - (IN) Table to which the entry needs to be added
  11852  *     index                 - (IN) index in the table
  11853  *     data                  - (IN) Data to be written
  11854  * Returns:
  11855  *     BCM_E_XXX
  11856  */
  11857 int _bcm_esw_add_policer_to_table(int unit,bcm_policer_t policer,
  11858                                soc_mem_t table, int index, void *data)
  11859 {
  11860     int offset_mode = 0;
  11861     int rv = BCM_E_NONE;
  11862     bcm_policer_t current_policer = 0;
  11863     _bcm_policer_svm_source_type_t mem_index = 0;
  11864 
  11865 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11866     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11867         return bcmi_esw_add_policer_to_table(unit,
  11868                   policer, table, index, data);
  11869     }
  11870 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11871 
  11872     if (soc_feature(unit, soc_feature_global_meter)) {
  11873          /* validate policer id */
  11874         rv = _bcm_esw_policer_validate(unit, &policer);
  11875         if (BCM_FAILURE(rv)) {
  11876             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11877                         (BSL_META_U(unit,
  11878                                     "Invalid policer id passed: %x \n"),
  11879                          policer));
  11880             return (rv);
  11881         }
  11882         rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index);
  11883         if (BCM_FAILURE(rv)) {
  11884             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11885                     (BSL_META_U(unit,
  11886                                 "Unable to read the table entry %d at "
  11887                                 "index %d \n"), table, index));
  11888             return (rv);
  11889         }
  11890         /* updating VFP_POLICY_TABLEm is handled in field module */
  11891         if (mem_index != _BCM_SVM_MEM_VFP_POLICY_TABLE) {
  11892             if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) {
  11893                 return BCM_E_INTERNAL;
  11894             }
  11895             rv = _bcm_esw_get_policer_from_table(unit, table, index, data,
  11896                     &current_policer, 1);
  11897             if (BCM_FAILURE(rv)) {
  11898                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11899                         (BSL_META_U(unit,
  11900                                     "Unable to read the table entry %d at "
  11901                                     "index %d \n"), table, index));
  11902                 return (rv);
  11903             }
  11904             if (policer == current_policer) {
  11905                 /* Nothing to do */
  11906                 return BCM_E_NONE;
  11907             }
  11908             /* Set policer id */
  11909             if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
  11910                 offset_mode =
  11911                     ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  11912                      BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  11913                 if (offset_mode >= 1) {
  11914                     offset_mode = offset_mode - 1;
  11915                 }
  11916                 if (offset_mode >=
  11917                         (soc_mem_index_count(unit,SVM_OFFSET_TABLEm) >>
  11918                          BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE))  {
  11919                     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11920                             (BSL_META_U(unit,
  11921                                         "Offset mode for the policer "
  11922                                         "exceeds max allowed value \n")));
  11923                     return BCM_E_PARAM;
  11924                 }
  11925                 _bcm_esw_get_policer_table_index(unit, policer, &index);
  11926             } else {
  11927                 index = 0;
  11928                 offset_mode = 0;
  11929             }
  11930             if (index >= soc_mem_index_count(unit, SVM_METER_TABLEm))  {
  11931                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  11932                         (BSL_META_U(unit,
  11933                                     "Invalid table index passed for "
  11934                                     "SVM_METER_TABLE\n")));
  11935                 return BCM_E_PARAM;
  11936             }
  11937             soc_mem_field32_set(unit,table, data,
  11938                     BCM_SVM_SOURCE(unit, mem_index).offset_mode, offset_mode);
  11939             soc_mem_field32_set(unit,table, data,
  11940                     BCM_SVM_SOURCE(unit, mem_index).meter_index, index);
  11941 
  11942         }
  11943         /* decrement current policer if any */
  11944         if ((current_policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
  11945             rv = _bcm_esw_policer_decrement_ref_count(unit, current_policer);
  11946             BCM_IF_ERROR_RETURN(rv);
  11947         }
  11948         /* increment new policer  */
  11949         if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
  11950             rv = _bcm_esw_policer_increment_ref_count(unit, policer);
  11951             BCM_IF_ERROR_RETURN(rv);
  11952         }
  11953     }
  11954     return rv;
  11955 }
  11956 
  11957 /*
  11958  * Function:
  11959  *     _bcm_esw_policer_offset_mode_get
  11960  * Purpose:
  11961  *     Get the offset_mode with given a policer id.
  11962  * Parameters:
  11963  *     Unit                  - (IN) unit number
  11964  *     policer_id            - (IN) policer Id
  11965  *     offset_mode                 - (OUT) HW policer index
  11966  * Returns:
  11967  *     BCM_E_XXX
  11968  */
  11969 int
  11970 _bcm_esw_policer_offset_mode_get(
  11971     int unit,
  11972     bcm_policer_t policer_id,
  11973     int *offset_mode)
  11974 {
  11975     int rv = BCM_E_UNAVAIL;
  11976 
  11977 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  11978     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  11979         return bcmi_esw_policer_offset_mode_get(unit,
  11980                   policer_id, offset_mode);
  11981     }
  11982 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  11983     return rv;
  11984 }
  11985 
  11986 /*
  11987  * Function:
  11988  *      _bcm_esw_get_policer_from_table
  11989  * Purpose:
  11990  *      Read the policer id configured in the given table
  11991  * Parameters:
  11992  *     unit                  - (IN) unit number
  11993  *     table                 - (IN) Table from which the entry needs to be got
  11994  *     index                 - (IN) index in the table
  11995  *     data                  - (IN) Data to be written
  11996  *     policer               - (OUT) policer Id
  11997  *     skip_read             - (IN) Skip reading the policer entry
  11998  * Returns:
  11999  *     BCM_E_XXX
  12000  */
  12001 int _bcm_esw_get_policer_from_table(int unit, soc_mem_t table, int index,
  12002                                     void *data, bcm_policer_t *policer,
  12003                                                          int skip_read)
  12004 {
  12005     int rv = BCM_E_NONE;
  12006     int offset = 0;
  12007     _bcm_policer_svm_source_type_t mem_index;
  12008 
  12009 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12010     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12011         return bcmi_esw_get_policer_from_table(unit,
  12012                   table, index, data, policer, skip_read);
  12013     }
  12014 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12015 
  12016     if (soc_feature(unit, soc_feature_global_meter)) {
  12017         
  12018         if (!global_meter_status[unit].initialised && SOC_WARM_BOOT(unit)) {
  12019             return rv;
  12020         }
  12021         if (!skip_read) {
  12022             rv = soc_mem_read(unit, table, MEM_BLOCK_ANY, index, data);
  12023             BCM_IF_ERROR_RETURN(rv);
  12024         }
  12025         if (table == SVM_MACROFLOW_INDEX_TABLEm) {
  12026             if (SOC_MEM_FIELD_VALID(unit, table, MACROFLOW_INDEXf)) {
  12027                 index = soc_mem_field32_get(unit, table, data,
  12028                         MACROFLOW_INDEXf);
  12029             }
  12030         } else {
  12031             rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index);
  12032             if (BCM_FAILURE(rv)) {
  12033                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  12034                         (BSL_META_U(unit,
  12035                                 "Unable to read the table entry %d at "
  12036                                 "index %d \n"), table, index));
  12037                 return (rv);
  12038             }
  12039             if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) {
  12040                 return BCM_E_INTERNAL;
  12041             }
  12042             offset = soc_mem_field32_get(unit, table, data,
  12043                         BCM_SVM_SOURCE(unit,mem_index).offset_mode);
  12044             index = soc_mem_field32_get(unit, table, data,
  12045                         BCM_SVM_SOURCE(unit,mem_index).meter_index);
  12046         }
  12047         _bcm_esw_get_policer_id_from_index_offset(unit, index,
  12048                                                           offset, policer);
  12049     } else {
  12050         return BCM_E_UNAVAIL;
  12051     }
  12052     return rv;
  12053 }
  12054 
  12055 /*
  12056  * Function:
  12057  *      _bcm_esw_reset_policer_from_table
  12058  * Purpose:
  12059  *      Remove the policer id configured from a table and re-adjust
  12060  *      policer usage reference count.
  12061  * Parameters:
  12062  *     unit                  - (IN) unit number
  12063  *     policer               - (IN) policer Id
  12064  *     table                 - (IN) Table in which an entry needs to be reset
  12065  *     index                 - (IN) index in the table
  12066  *     data                  - (IN) Data to be written
  12067  * Returns:
  12068  *     BCM_E_XXX
  12069  */
  12070 int _bcm_esw_reset_policer_from_table(int unit, bcm_policer_t policer,
  12071                                       int table, int index, void *data)
  12072 {
  12073 
  12074     int rv = BCM_E_NONE;
  12075     rv = _bcm_esw_delete_policer_from_table(unit, policer, table, index, data);
  12076     if (BCM_FAILURE(rv)) {
  12077         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12078                   (BSL_META_U(unit,
  12079                               "Unable to delete policer from table %d at "
  12080                               "index %d \n"), table, index));
  12081         return (rv);
  12082     }
  12083     rv = soc_mem_write(unit, table, MEM_BLOCK_ANY, index, data);
  12084     return rv;
  12085 }
  12086 
  12087 /*
  12088  * Function:
  12089  *      _bcm_esw_delete_policer_from_table
  12090  * Purpose:
  12091  *      Remove the policer id configured from a table and re-adjust
  12092  *      policer usage reference count
  12093  * Parameters:
  12094  *     unit                  - (IN) unit number
  12095  *     policer               - (IN) policer Id
  12096  *     table                 - (IN) Table in which an entry needs to be deleted
  12097  *     index                 - (IN) index in the table
  12098  *     data                  - (IN) Data to be written
  12099  * Returns:
  12100  *     BCM_E_XXX
  12101  */
  12102 int _bcm_esw_delete_policer_from_table(int unit, bcm_policer_t policer,
  12103                                     soc_mem_t table, int index, void *data)
  12104 {
  12105     int rv = BCM_E_NONE;
  12106     bcm_policer_t current_policer = 0;
  12107     int offset_mode = 0;
  12108     _bcm_policer_svm_source_type_t mem_index;
  12109 
  12110 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12111     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12112         return bcmi_esw_delete_policer_from_table(unit,
  12113                   policer, table, index, data);
  12114     }
  12115 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12116 
  12117     if (soc_feature(unit, soc_feature_global_meter)) {
  12118          /* validate policer id */
  12119         rv = _bcm_esw_policer_validate(unit, &policer);
  12120         if (BCM_FAILURE(rv)) {
  12121             LOG_DEBUG(BSL_LS_BCM_POLICER,
  12122                       (BSL_META_U(unit,
  12123                                   "Invalid policer id passed: %x \n"),
  12124                        policer));
  12125             return (rv);
  12126         }
  12127         rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index);
  12128         if (BCM_FAILURE(rv)) {
  12129             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  12130                     (BSL_META_U(unit,
  12131                                 "Unable to read the table entry %d at "
  12132                                 "index %d \n"), table, index));
  12133             return (rv);
  12134         }
  12135         /* Deleting VFP_POLICY_TABLEm is handled in field module */
  12136         if (mem_index != _BCM_SVM_MEM_VFP_POLICY_TABLE) {
  12137             if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) {
  12138                 return BCM_E_INTERNAL;
  12139             }
  12140             rv =  _bcm_esw_get_policer_from_table(unit, table, index, data,
  12141                     &current_policer, 0);
  12142             if (BCM_FAILURE(rv)) {
  12143                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  12144                         (BSL_META_U(unit,
  12145                                     "Unable to read the policer from table "
  12146                                     "%d at index %d\n"), table, index));
  12147                 return (rv);
  12148             }
  12149             if (current_policer != policer) {
  12150                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  12151                         (BSL_META_U(unit,
  12152                                     "Policer Id passed is different from the "
  12153                                     "one that is configured in the table. configured value is \
  12154                                     %d \n"), current_policer));
  12155                 return BCM_E_INTERNAL;
  12156             }
  12157             offset_mode = index = 0;
  12158             soc_mem_field32_set(unit,table, data,
  12159                     BCM_SVM_SOURCE(unit, mem_index).offset_mode, offset_mode);
  12160             soc_mem_field32_set(unit,table, data,
  12161                     BCM_SVM_SOURCE(unit, mem_index).meter_index, index);
  12162         }
  12163         /* decrement current policer if any */
  12164         if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
  12165             rv = _bcm_esw_policer_decrement_ref_count(unit, policer);
  12166             BCM_IF_ERROR_RETURN(rv);
  12167         }
  12168     }
  12169     return rv;
  12170 }
  12171 
  12172 /*
  12173  * Function:
  12174  *      _bcm_policer_svc_meter_get_mode_info
  12175  * Purpose:
  12176  *      Get the info related to a configured offset mode
  12177  * Parameters:
  12178  *     unit                  - (IN) unit number
  12179  *     meter_mode_v          - (IN) Meter offset mode
  12180  *     mode_info             - (OUT) Info of the configured mode
  12181  * Returns:
  12182  *     BCM_E_XXX
  12183  */
  12184 
  12185 bcm_error_t _bcm_policer_svc_meter_get_mode_info(
  12186                 int                                     unit,
  12187                 bcm_policer_svc_meter_mode_t            meter_mode_v,
  12188                 bcm_policer_svc_meter_bookkeep_mode_t   *mode_info
  12189                 )
  12190 {
  12191     if (!((meter_mode_v >= 1) &&
  12192                     (meter_mode_v < BCM_POLICER_SVC_METER_MAX_MODE))) {
  12193         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12194                   (BSL_META_U(unit,
  12195                               "Invalid offset mode %d  \n"), meter_mode_v));
  12196         return BCM_E_PARAM;
  12197     }
  12198     if (global_meter_offset_mode[unit][meter_mode_v].used == 0) {
  12199         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12200                   (BSL_META_U(unit,
  12201                               "Passed mode is not used \n")));
  12202         return BCM_E_NOT_FOUND;
  12203     }
  12204     *mode_info = global_meter_offset_mode[unit][meter_mode_v];
  12205     return BCM_E_NONE;
  12206 }
  12207 
  12208 
  12209 /* ACTION API's */
  12210 
  12211 /*
  12212  * Function:
  12213  *      bcm_esw_policer_action_create
  12214  * Purpose:
  12215  *       Create a new action entry in meter action table
  12216  * Parameters:
  12217  *     unit                  - (IN) unit number
  12218  *     action_id             - (OUT) Action Id created
  12219  * Returns:
  12220  *     BCM_E_XXX
  12221  */
  12222 int bcm_esw_policer_action_create(
  12223     int unit,
  12224     uint32 *action_id)
  12225 {
  12226     int rv = BCM_E_NONE;
  12227 
  12228 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12229     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12230         return bcmi_esw_policer_action_create(unit, action_id);
  12231     }
  12232 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12233 
  12234     if (!soc_feature(unit, soc_feature_global_meter)) {
  12235         return BCM_E_UNAVAIL;
  12236     }
  12237 
  12238     if (action_id == NULL)  {
  12239         return (BCM_E_PARAM);
  12240     }
  12241 
  12242     CHECK_GLOBAL_METER_INIT(unit);
  12243     rv = shr_aidxres_list_alloc_block(
  12244                  meter_action_list_handle[unit], 1, (uint32 *)action_id);
  12245     if (BCM_FAILURE(rv)) {
  12246         LOG_ERROR(BSL_LS_BCM_POLICER,
  12247                   (BSL_META_U(unit,
  12248                               "Unable to allocate a handle for new "
  12249                               "action\n")));
  12250         return (rv);
  12251     }
  12252     global_meter_action_bookkeep[unit][*action_id].used = 1;
  12253     return rv;
  12254 }
  12255 
  12256 /*
  12257  * Function:
  12258  *     bcm_esw_policer_action_add
  12259  * Purpose:
  12260  *     Add an entry to meter action table
  12261  * Parameters:
  12262  *     unit                  - (IN) unit number
  12263  *     action_id             - (IN) Action Id created
  12264  *     action                - (IN) Action to be added
  12265  *     action_id             - (IN) Parameter associated with action
  12266  * Returns:
  12267  *     BCM_E_XXX
  12268  */
  12269 int bcm_esw_policer_action_add(
  12270     int unit,
  12271     uint32 action_id,
  12272     bcm_policer_action_t action,
  12273     uint32 param0)
  12274 {
  12275     int rv = BCM_E_NONE;
  12276     svm_policy_table_entry_t meter_action;
  12277     uint32 green_action[1] = {0}, yellow_action[1] = {0}, red_action[1] = {0};
  12278 
  12279 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12280     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12281         return bcmi_esw_policer_action_add(unit, action_id, action, param0);
  12282     }
  12283 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12284 
  12285     if (!soc_feature(unit, soc_feature_global_meter)) {
  12286         return BCM_E_UNAVAIL;
  12287     }
  12288 
  12289     if (global_meter_action_bookkeep[unit][action_id].used != 1) {
  12290         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12291                   (BSL_META_U(unit,
  12292                               "Action id is not created \n")));
  12293         return BCM_E_PARAM;
  12294     }
  12295 
  12296     GLOBAL_METER_LOCK(unit);
  12297     /* read action table entry */
  12298     rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action);
  12299     if (BCM_FAILURE(rv)) {
  12300         GLOBAL_METER_UNLOCK(unit);
  12301         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12302                   (BSL_META_U(unit,
  12303                               "Unable to read SVM_POLICY_TABLE for given "
  12304                               "action id \n")));
  12305         return (rv);
  12306     }
  12307     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, G_ACTIONSf,
  12308                                                       &green_action[0]);
  12309     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, Y_ACTIONSf,
  12310                                                      &yellow_action[0]);
  12311     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, R_ACTIONSf,
  12312                                                         &red_action[0]);
  12313 
  12314 
  12315     switch (action) {
  12316        case bcmPolicerActionGpDrop :
  12317            SHR_BITSET(green_action,
  12318                               BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS);
  12319            break;
  12320 
  12321        case bcmPolicerActionYpDrop :
  12322            SHR_BITSET(yellow_action,
  12323                              BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS);
  12324            break;
  12325 
  12326        case bcmPolicerActionRpDrop :
  12327            SHR_BITSET(red_action,
  12328                             BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS);
  12329            break;
  12330 
  12331        case bcmPolicerActionGpEcnNew :
  12332            if (param0 > 0x3) {
  12333                GLOBAL_METER_UNLOCK(unit);
  12334                LOG_ERROR(BSL_LS_BCM_POLICER,
  12335                          (BSL_META_U(unit,
  12336                                      "Invalid value for ECN  \n")));
  12337                return BCM_E_PARAM;
  12338            }
  12339            SHR_BITCLR_RANGE(green_action,
  12340                             BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2);
  12341            green_action[0] = green_action[0] |
  12342                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS);
  12343            SHR_BITSET(green_action,
  12344                           BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS);
  12345            break;
  12346 
  12347        case bcmPolicerActionYpEcnNew :
  12348            if (param0 > 0x3) {
  12349                GLOBAL_METER_UNLOCK(unit);
  12350                LOG_ERROR(BSL_LS_BCM_POLICER,
  12351                          (BSL_META_U(unit,
  12352                                      "Invalid value for ECN  \n")));
  12353                return BCM_E_PARAM;
  12354            }
  12355            SHR_BITCLR_RANGE(yellow_action,
  12356                             BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2);
  12357            yellow_action[0] = yellow_action[0] |
  12358                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS);
  12359            SHR_BITSET(yellow_action,
  12360                           BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS);
  12361            break;
  12362 
  12363        case bcmPolicerActionRpEcnNew :
  12364            if (param0 > 0x3) {
  12365                GLOBAL_METER_UNLOCK(unit);
  12366                LOG_ERROR(BSL_LS_BCM_POLICER,
  12367                          (BSL_META_U(unit,
  12368                                      "Invalid value for ECN  \n")));
  12369                return BCM_E_PARAM;
  12370            }
  12371            SHR_BITCLR_RANGE(red_action,
  12372                             BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2);
  12373            red_action[0] = red_action[0] |
  12374                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS);
  12375            SHR_BITSET(red_action,
  12376                          BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS);
  12377            break;
  12378 
  12379        case bcmPolicerActionGpCngNew :
  12380            if (param0 > 0x3) {
  12381                GLOBAL_METER_UNLOCK(unit);
  12382                LOG_ERROR(BSL_LS_BCM_POLICER,
  12383                          (BSL_META_U(unit,
  12384                                      "Invalid value for CNG  \n")));
  12385                return BCM_E_PARAM;
  12386            }
  12387            SHR_BITCLR_RANGE(green_action,
  12388                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2);
  12389            green_action[0] = green_action[0] |
  12390                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS);
  12391            break;
  12392 
  12393        case bcmPolicerActionYpCngNew :
  12394            if (param0 > 0x3) {
  12395                GLOBAL_METER_UNLOCK(unit);
  12396                LOG_ERROR(BSL_LS_BCM_POLICER,
  12397                          (BSL_META_U(unit,
  12398                                      "Invalid value for CNG  \n")));
  12399                return BCM_E_PARAM;
  12400            }
  12401            SHR_BITCLR_RANGE(yellow_action,
  12402                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2);
  12403            yellow_action[0] = yellow_action[0] |
  12404                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS);
  12405            break;
  12406 
  12407        case bcmPolicerActionRpCngNew :
  12408            if (param0 > 0x3) {
  12409                GLOBAL_METER_UNLOCK(unit);
  12410                LOG_ERROR(BSL_LS_BCM_POLICER,
  12411                          (BSL_META_U(unit,
  12412                                      "Invalid value for CNG  \n")));
  12413                return BCM_E_PARAM;
  12414            }
  12415            SHR_BITCLR_RANGE(red_action,
  12416                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2);
  12417            red_action[0] = red_action[0] |
  12418                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS);
  12419            break;
  12420 
  12421        case bcmPolicerActionGpDscpNew:
  12422            if (param0 > 0x3f) {
  12423                GLOBAL_METER_UNLOCK(unit);
  12424                LOG_ERROR(BSL_LS_BCM_POLICER,
  12425                          (BSL_META_U(unit,
  12426                                      "Invalid value for DSCP  \n")));
  12427                return BCM_E_PARAM;
  12428            }
  12429            SHR_BITCLR_RANGE(green_action,
  12430                       BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6);
  12431            green_action[0] = green_action[0] |
  12432                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS);
  12433            SHR_BITSET(green_action,
  12434                          BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS);
  12435            break;
  12436 
  12437        case bcmPolicerActionYpDscpNew:
  12438            if (param0 > 0x3f) {
  12439                GLOBAL_METER_UNLOCK(unit);
  12440                LOG_ERROR(BSL_LS_BCM_POLICER,
  12441                          (BSL_META_U(unit,
  12442                                      "Invalid value for DSCP  \n")));
  12443                return BCM_E_PARAM;
  12444            }
  12445            SHR_BITCLR_RANGE(yellow_action,
  12446                       BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6);
  12447            yellow_action[0] = yellow_action[0] |
  12448                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS);
  12449            SHR_BITSET(yellow_action,
  12450                           BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS);
  12451            break;
  12452 
  12453        case bcmPolicerActionRpDscpNew:
  12454            if (param0 > 0x3f) {
  12455                GLOBAL_METER_UNLOCK(unit);
  12456                LOG_ERROR(BSL_LS_BCM_POLICER,
  12457                          (BSL_META_U(unit,
  12458                                      "Invalid value for DSCP  \n")));
  12459                return BCM_E_PARAM;
  12460            }
  12461            SHR_BITCLR_RANGE(red_action,
  12462                       BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6);
  12463            red_action[0] = red_action[0] |
  12464                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS);
  12465            SHR_BITSET(red_action,
  12466                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS);
  12467            break;
  12468 
  12469        case bcmPolicerActionGpPrioIntNew :
  12470            if (param0 > 0xf) {
  12471                GLOBAL_METER_UNLOCK(unit);
  12472                LOG_ERROR(BSL_LS_BCM_POLICER,
  12473                          (BSL_META_U(unit,
  12474                                      "Invalid value for int pri\n")));
  12475                return BCM_E_PARAM;
  12476            }
  12477            SHR_BITCLR_RANGE(green_action,
  12478                       BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4);
  12479            green_action[0] = green_action[0] |
  12480                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS);
  12481            SHR_BITSET(green_action,
  12482                        BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS);
  12483            break;
  12484 
  12485        case bcmPolicerActionYpPrioIntNew :
  12486            if (param0 > 0xf) {
  12487                GLOBAL_METER_UNLOCK(unit);
  12488                LOG_ERROR(BSL_LS_BCM_POLICER,
  12489                          (BSL_META_U(unit,
  12490                                      "Invalid value for int pri\n")));
  12491                return BCM_E_PARAM;
  12492            }
  12493            SHR_BITCLR_RANGE(yellow_action,
  12494                       BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4);
  12495            yellow_action[0] = yellow_action[0] |
  12496                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS);
  12497            SHR_BITSET(yellow_action,
  12498                       BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS);
  12499            break;
  12500 
  12501        case bcmPolicerActionRpPrioIntNew :
  12502            if (param0 > 0xf) {
  12503                GLOBAL_METER_UNLOCK(unit);
  12504                LOG_ERROR(BSL_LS_BCM_POLICER,
  12505                          (BSL_META_U(unit,
  12506                                      "Invalid value for int pri\n")));
  12507                return BCM_E_PARAM;
  12508            }
  12509            SHR_BITCLR_RANGE(red_action,
  12510                       BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4);
  12511            red_action[0] = red_action[0] |
  12512                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS);
  12513            SHR_BITSET(red_action,
  12514                       BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS);
  12515            break;
  12516 
  12517 
  12518        case bcmPolicerActionGpVlanPrioNew :
  12519            if (param0 > 0x7) {
  12520                GLOBAL_METER_UNLOCK(unit);
  12521                LOG_ERROR(BSL_LS_BCM_POLICER,
  12522                          (BSL_META_U(unit,
  12523                                      "Invalid value for vlan pri\n")));
  12524                return BCM_E_PARAM;
  12525            }
  12526            SHR_BITCLR_RANGE(green_action,
  12527                       BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3);
  12528            green_action[0] = green_action[0] |
  12529                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS);
  12530            SHR_BITSET(green_action,
  12531                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS);
  12532            break;
  12533 
  12534        case bcmPolicerActionYpVlanPrioNew :
  12535            if (param0 > 0x7) {
  12536                GLOBAL_METER_UNLOCK(unit);
  12537                LOG_ERROR(BSL_LS_BCM_POLICER,
  12538                          (BSL_META_U(unit,
  12539                                      "Invalid value for vlan pri\n")));
  12540                return BCM_E_PARAM;
  12541            }
  12542            SHR_BITCLR_RANGE(yellow_action,
  12543                       BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3);
  12544            yellow_action[0] = yellow_action[0] |
  12545                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS);
  12546            SHR_BITSET(yellow_action,
  12547                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS);
  12548            break;
  12549 
  12550        case bcmPolicerActionRpVlanPrioNew :
  12551            if (param0 > 0x7) {
  12552                GLOBAL_METER_UNLOCK(unit);
  12553                LOG_ERROR(BSL_LS_BCM_POLICER,
  12554                          (BSL_META_U(unit,
  12555                                      "Invalid value for vlan pri\n")));
  12556                return BCM_E_PARAM;
  12557            }
  12558            SHR_BITCLR_RANGE(red_action,
  12559                       BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3);
  12560            red_action[0] = red_action[0] |
  12561                    (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS);
  12562            SHR_BITSET(red_action,
  12563                         BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS);
  12564            break;
  12565 
  12566        default:
  12567           GLOBAL_METER_UNLOCK(unit);
  12568           LOG_ERROR(BSL_LS_BCM_POLICER,
  12569                     (BSL_META_U(unit,
  12570                                 "Unsupported Action specified\n")));
  12571           return BCM_E_PARAM;
  12572     }
  12573 
  12574     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, G_ACTIONSf,
  12575                                                     &green_action[0]);
  12576     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, Y_ACTIONSf,
  12577                                                    &yellow_action[0]);
  12578     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, R_ACTIONSf,
  12579                                                       &red_action[0]);
  12580 
  12581     rv = WRITE_SVM_POLICY_TABLEm(unit,MEM_BLOCK_ANY,action_id, &meter_action);
  12582     if (BCM_FAILURE(rv)) {
  12583         GLOBAL_METER_UNLOCK(unit);
  12584         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12585                   (BSL_META_U(unit,
  12586                               "Unable to write to SVM_POLICY_TABLE at location "
  12587                               "specified by action_id \n")));
  12588         return (rv);
  12589     }
  12590     GLOBAL_METER_UNLOCK(unit);
  12591     return rv;
  12592 }
  12593 
  12594 /*
  12595  * Function:
  12596  *     bcm_esw_policer_action_destroy
  12597  * Purpose:
  12598  *     Delete an entry from meter action table
  12599  * Parameters:
  12600  *     unit                  - (IN) unit number
  12601  *     action_id             - (IN) Action Id to be destroyed
  12602  * Returns:
  12603  *     BCM_E_XXX
  12604  */
  12605 int bcm_esw_policer_action_destroy(
  12606     int unit,
  12607     uint32 action_id)
  12608 {
  12609     int rv = BCM_E_NONE;
  12610     uint32 reset=0;
  12611     svm_policy_table_entry_t meter_action;
  12612 
  12613 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12614     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12615         return bcmi_esw_policer_action_destroy(unit, action_id);
  12616     }
  12617 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12618 
  12619     if (!soc_feature(unit, soc_feature_global_meter)) {
  12620         return BCM_E_UNAVAIL;
  12621     }
  12622 
  12623     if (global_meter_action_bookkeep[unit][action_id].used != 1)
  12624     {
  12625         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12626                   (BSL_META_U(unit,
  12627                               "Action Id specified doesn't exist\n")));
  12628         return BCM_E_PARAM;
  12629     }
  12630 
  12631     if (global_meter_action_bookkeep[unit]\
  12632                                   [action_id].reference_count != 0)
  12633     {
  12634         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12635                   (BSL_META_U(unit,
  12636                               "Action Id specified still being used \n")));
  12637         return BCM_E_BUSY;
  12638     }
  12639     GLOBAL_METER_LOCK(unit);
  12640     /* read action table entry */
  12641     rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action);
  12642     if (BCM_FAILURE(rv)) {
  12643         GLOBAL_METER_UNLOCK(unit);
  12644         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12645                   (BSL_META_U(unit,
  12646                               "Unable to read SVM_POLICY_TABLE at location "
  12647                               "specified by action_id \n")));
  12648         return (rv);
  12649     }
  12650 
  12651     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, G_ACTIONSf, &reset);
  12652     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, Y_ACTIONSf, &reset);
  12653     soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, R_ACTIONSf, &reset);
  12654 
  12655     rv = WRITE_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action);
  12656     if (BCM_FAILURE(rv)) {
  12657         GLOBAL_METER_UNLOCK(unit);
  12658         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12659                   (BSL_META_U(unit,
  12660                               "Unable to write to SVM_POLICY_TABLE at location "
  12661                               "specified by action_id \n")));
  12662         return (rv);
  12663     }
  12664 
  12665     rv = shr_aidxres_list_free(meter_action_list_handle[unit], action_id);
  12666     if (BCM_FAILURE(rv)) {
  12667         GLOBAL_METER_UNLOCK(unit);
  12668         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  12669                     (BSL_META_U(unit,
  12670                                 "Unable to free action handle \n")));
  12671         return (rv);
  12672     }
  12673     GLOBAL_METER_UNLOCK(unit);
  12674     global_meter_action_bookkeep[unit][action_id].used = 0;
  12675     return rv;
  12676 
  12677 }
  12678 
  12679 /*
  12680  * Function:
  12681  *      bcm_esw_policer_action_get
  12682  * Purpose:
  12683  *     get action parameter for a given action
  12684  * Parameters:
  12685  *     unit                  - (IN) unit number
  12686  *     action_id             - (IN) Action Id
  12687  *     action                - (IN) Action for which param is needed
  12688  *     param0                - (OUT) Parameter associated with action id
  12689  * Returns:
  12690  *     BCM_E_XXX
  12691  */
  12692 int bcm_esw_policer_action_get(
  12693     int unit,
  12694     uint32 action_id,
  12695     bcm_policer_action_t action,
  12696     uint32   *param0)
  12697 {
  12698     int rv = BCM_E_NONE;
  12699     svm_policy_table_entry_t meter_action;
  12700     uint32 green_action = 0, yellow_action = 0, red_action = 0;
  12701 
  12702 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  12703     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  12704         return bcmi_esw_policer_action_get(unit, action_id, action, param0);
  12705     }
  12706 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  12707 
  12708     if (!soc_feature(unit, soc_feature_global_meter)) {
  12709         return BCM_E_UNAVAIL;
  12710     }
  12711 
  12712     if (global_meter_action_bookkeep[unit][action_id].used != 1)
  12713     {
  12714         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12715                   (BSL_META_U(unit,
  12716                               "Action Id specified doesn't exist\n")));
  12717         return BCM_E_PARAM;
  12718     }
  12719     GLOBAL_METER_LOCK(unit);
  12720     /* read action table entry */
  12721     rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action);
  12722     if (BCM_FAILURE(rv)) {
  12723         GLOBAL_METER_UNLOCK(unit);
  12724         LOG_DEBUG(BSL_LS_BCM_POLICER,
  12725                   (BSL_META_U(unit,
  12726                               "Unable to read SVM_POLICY_TABLE at location "
  12727                               "specified by action_id \n")));
  12728         return (rv);
  12729     }
  12730     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, G_ACTIONSf,
  12731                                                          &green_action);
  12732     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, Y_ACTIONSf,
  12733                                                          &yellow_action);
  12734     soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, R_ACTIONSf,
  12735                                                            &red_action);
  12736 
  12737     switch (action) {
  12738         case bcmPolicerActionGpEcnNew :
  12739             *param0 = (green_action & BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK);
  12740             break;
  12741 
  12742         case bcmPolicerActionGpDscpNew:
  12743             *param0 = (green_action &
  12744                             BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2;
  12745             break;
  12746 
  12747         case bcmPolicerActionGpVlanPrioNew:
  12748             *param0 = (green_action &
  12749                               BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >>
  12750                               BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS;
  12751             break;
  12752 
  12753         case bcmPolicerActionGpPrioIntNew:
  12754             *param0 = (green_action &
  12755                              BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >>
  12756                              BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ;
  12757             break;
  12758 
  12759        case bcmPolicerActionGpCngNew :
  12760             *param0 = (green_action &
  12761                              BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >>
  12762                              BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ;
  12763             break;
  12764 
  12765         case bcmPolicerActionYpEcnNew :
  12766             *param0 = (yellow_action &
  12767                                   BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK);
  12768             break;
  12769 
  12770         case bcmPolicerActionYpDscpNew:
  12771             *param0 = (yellow_action &
  12772                             BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2;
  12773             break;
  12774 
  12775         case bcmPolicerActionYpVlanPrioNew:
  12776             *param0 = (yellow_action &
  12777                                BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >>
  12778                                  BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS;
  12779             break;
  12780 
  12781         case bcmPolicerActionYpPrioIntNew:
  12782             *param0 = (yellow_action &
  12783                               BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >>
  12784                               BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ;
  12785             break;
  12786 
  12787        case bcmPolicerActionYpCngNew :
  12788             *param0 = (yellow_action &
  12789                              BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >>
  12790                              BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ;
  12791             break;
  12792 
  12793         case bcmPolicerActionRpEcnNew :
  12794             *param0 = (red_action & BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK);
  12795             break;
  12796 
  12797         case bcmPolicerActionRpDscpNew:
  12798             *param0 = (red_action &
  12799                              BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2;
  12800             break;
  12801 
  12802         case bcmPolicerActionRpVlanPrioNew:
  12803             *param0 = (red_action &
  12804                                BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >>
  12805                                BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS;
  12806             break;
  12807 
  12808         case bcmPolicerActionRpPrioIntNew:
  12809             *param0 = (red_action &
  12810                              BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >>
  12811                              BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ;
  12812             break;
  12813 
  12814        case bcmPolicerActionRpCngNew :
  12815             *param0 = (red_action &
  12816                              BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >>
  12817                              BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ;
  12818             break;
  12819 
  12820         default:
  12821             LOG_ERROR(BSL_LS_BCM_POLICER,
  12822                       (BSL_META_U(unit,
  12823                                   "Unsupported Action specified\n")));
  12824             rv = BCM_E_PARAM;
  12825             break;
  12826     }
  12827     GLOBAL_METER_UNLOCK(unit);
  12828     return rv;
  12829 }
  12830 
  12831 /* end Action API's */
  12832 
  12833 
  12834 /* POLICER API's */
  12835 /*
  12836  * Function:
  12837  *      _bcm_global_meter_free_allocated_policer_on_error
  12838  * Purpose:
  12839  *      Clean up the internal data structure in case of error.
  12840  * Parameters:
  12841  *     unit                  - (IN) unit number
  12842  *     numbers               - (IN) Number of policer to be freed
  12843  *     offset                - (IN) Offset w.r.t base policer
  12844  *     policer_index         - (IN) Base policer id
  12845  * Returns:
  12846  *     BCM_E_XXX
  12847  */
  12848 int _bcm_global_meter_free_allocated_policer_on_error(int unit,
  12849                                            uint32 numbers, uint8 *offset,
  12850                                                   uint32 policer_index)
  12851 {
  12852 
  12853     int rv = BCM_E_NONE;
  12854     int index    =0;
  12855     int pool  =  0;
  12856     int size_pool;
  12857     int num_banks_per_pool = 1, index_bank = 0;
  12858     int handle_id = 0, bank_id = 0;
  12859 
  12860     size_pool = SOC_INFO(unit).global_meter_max_size_of_pool;
  12861     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  12862     bank_id = (policer_index & (size_pool - 1)) / num_banks_per_pool;
  12863     index_bank = (policer_index & (size_pool - 1)) % num_banks_per_pool;
  12864 
  12865     for (index = 0;index < numbers; index++) {
  12866         if (index) {
  12867             pool = offset[0] + offset[index];
  12868         } else {
  12869             pool = offset[0];
  12870         }
  12871 
  12872         handle_id = pool * num_banks_per_pool + bank_id;
  12873         rv = shr_aidxres_list_free(
  12874                          meter_alloc_list_handle[unit][handle_id], index_bank);
  12875         if (!BCM_SUCCESS(rv)) {
  12876             LOG_DEBUG(BSL_LS_BCM_POLICER,
  12877                       (BSL_META_U(unit,
  12878                                   "Unable to free policer handle \n")));
  12879             return BCM_E_INTERNAL;
  12880         }
  12881 
  12882         rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, pool, policer_index);
  12883         if (!BCM_SUCCESS(rv)) {
  12884             LOG_DEBUG(BSL_LS_BCM_POLICER,
  12885                       (BSL_META_U(unit,
  12886                                   "Unable to free policer handle \n")));
  12887             return BCM_E_INTERNAL;
  12888         }
  12889     }
  12890     return rv;
  12891 }
  12892 
  12893 static int
  12894 max_groups_per_octuple (int unit)
  12895 {
  12896     return (soc_feature(unit, soc_feature_global_meter_mef_10dot3) ? 4 : 2);
  12897 }
  12898 
  12899 /*
  12900  * Function:
  12901  *      _bcm_gloabl_meter_alloc_horizontally
  12902  * Purpose:
  12903  *      Allocate a set of policers such that each of the policers
  12904  *      created have the same index but differnt pool number.
  12905  * Parameters:
  12906  *     unit                  - (IN) unit number
  12907  *     numbers               - (IN) Number of policer to be allocated
  12908  *     pid                   - (OUT) Base policer id
  12909  *     offset                - (OUT) Offset w.r.t base policer
  12910  * Returns:
  12911  *     BCM_E_XXX
  12912  */
  12913 int _bcm_gloabl_meter_alloc_horizontally(int unit, int *numbers,
  12914                                          bcm_policer_t *pid,
  12915                                          uint8 *offset)
  12916 {
  12917     int rv = BCM_E_NONE;
  12918      _global_meter_horizontal_alloc_t *alloc_control;
  12919     uint32 allocated_policer = 0;
  12920     int max_index = 0, max_pool = 0, index = 0, map = 0, pool = 0;
  12921     int policers_available = 0;
  12922     int skip_index = 0;
  12923     int bank_size = 0, handle_id = 0, bank_index = 0;
  12924     int num_banks_per_pool = get_max_banks_in_a_pool(unit);
  12925 
  12926     max_index =  SOC_INFO(unit).global_meter_size_of_pool;
  12927     max_pool = SOC_INFO(unit).global_meter_pools;
  12928     bank_size = max_index / num_banks_per_pool;
  12929 
  12930     alloc_control = global_meter_hz_alloc_bookkeep[unit];
  12931     for (index = 1; index < max_index; index++) {
  12932         skip_index = 0;
  12933         allocated_policer = 0;
  12934         if (alloc_control[index].no_of_groups_allocated ==
  12935             max_groups_per_octuple(unit)) {
  12936             continue;
  12937         } else if (alloc_control[index].no_of_groups_allocated > 0) {
  12938         /* check if we have enough free policers to allocate */
  12939             map = alloc_control[index].alloc_bit_map;
  12940             if (alloc_control[index].first_bit_to_use > 0) {
  12941                 map = map &
  12942                 (convert_to_bitmask(alloc_control[index].first_bit_to_use - 1));
  12943                 policers_available = _shr_popcount(map);
  12944             } else {
  12945                 policers_available = 0;
  12946             }
  12947             if (policers_available >= *numbers) {
  12948                 offset[0] = 0;
  12949             /* Use shared aligned index management to allocate policers */
  12950                 for (pool = 0; pool <= alloc_control[index].first_bit_to_use;
  12951                                                                     pool++) {
  12952                     handle_id = pool * num_banks_per_pool + index / bank_size;
  12953                     bank_index = index % bank_size;
  12954 
  12955                     rv = shr_aidxres_list_reserve_block(
  12956                       meter_alloc_list_handle[unit][handle_id], bank_index, 1);
  12957                     if (!BCM_SUCCESS(rv)) {
  12958                         if (allocated_policer) {
  12959                        /* free all the allocated policers */
  12960                            rv = _bcm_global_meter_free_allocated_policer_on_error(unit,
  12961                                               allocated_policer, offset, index);
  12962 
  12963                            skip_index = 1;
  12964                            allocated_policer = 0;
  12965                         }
  12966                         continue;
  12967                     }
  12968                     rv = _bcm_global_meter_reserve_bloc_horizontally(unit,
  12969                                                               pool, index);
  12970                     if (!BCM_SUCCESS(rv)) {
  12971                         rv = shr_aidxres_list_free(
  12972                             meter_alloc_list_handle[unit][handle_id], bank_index);
  12973                         if (!BCM_SUCCESS(rv)) {
  12974                             LOG_DEBUG(BSL_LS_BCM_POLICER,
  12975                                       (BSL_META_U(unit,
  12976                                                   "Unable to free policer "
  12977                                                   "handle \n")));
  12978                             return BCM_E_INTERNAL;
  12979                         }
  12980                         continue;
  12981                     }
  12982                     if (allocated_policer) {
  12983                         offset[allocated_policer] = pool - offset[0];
  12984                     } else {
  12985                         offset[allocated_policer] = pool;
  12986                     }
  12987                     allocated_policer++;
  12988                     if (allocated_policer == *numbers) {
  12989                        alloc_control[index].last_bit_to_use =
  12990                                          alloc_control[index].first_bit_to_use;
  12991                        alloc_control[index].first_bit_to_use = pool;
  12992                        break;
  12993                     }
  12994 
  12995                 }
  12996                 if (allocated_policer != *numbers) {
  12997                      /* free all the allocated policers */
  12998                     rv = _bcm_global_meter_free_allocated_policer_on_error(
  12999                                      unit, allocated_policer, offset, index);
  13000                     if (skip_index == 0 ) {
  13001                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13002                                   (BSL_META_U(unit,
  13003                                               "Unable to free policer "
  13004                                               "handle \n")));
  13005                         return BCM_E_INTERNAL;
  13006                     }
  13007                 } else if( allocated_policer == *numbers) {
  13008                     *pid = index;
  13009                     alloc_control[index].no_of_groups_allocated++;
  13010                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13011                               (BSL_META_U(unit,
  13012                                           "Allocated base policer with "
  13013                                           "index %x \n"), index));
  13014                     return BCM_E_NONE;
  13015                 }
  13016             }
  13017             map = alloc_control[index].alloc_bit_map;
  13018             map = map &
  13019                    ~(convert_to_bitmask(alloc_control[index].last_bit_to_use));
  13020             policers_available = _shr_popcount(map);
  13021             if (policers_available >= *numbers) {
  13022             /* Use shared aligned index management to allocate policers */
  13023                 for (pool = alloc_control[index].last_bit_to_use + 1;
  13024                                               pool < max_pool; pool++) {
  13025                     handle_id = pool * num_banks_per_pool + index / bank_size;
  13026                     bank_index = index % bank_size;
  13027 
  13028                     rv = shr_aidxres_list_reserve_block(
  13029                      meter_alloc_list_handle[unit][handle_id], bank_index, 1);
  13030                     if (!BCM_SUCCESS(rv)) {
  13031                         if (allocated_policer) {
  13032                        /* free all the allocated policers */
  13033                            rv = _bcm_global_meter_free_allocated_policer_on_error(unit,
  13034                                               allocated_policer, offset, index);
  13035 
  13036                            skip_index = 1;
  13037                            allocated_policer = 0;
  13038                         }
  13039                         continue;
  13040                     }
  13041                     rv = _bcm_global_meter_reserve_bloc_horizontally(unit,
  13042                                                                pool, index);
  13043                     if (!BCM_SUCCESS(rv)) {
  13044                         rv = shr_aidxres_list_free(
  13045                             meter_alloc_list_handle[unit][handle_id], bank_index);
  13046                         if (!BCM_SUCCESS(rv)) {
  13047                             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13048                                       (BSL_META_U(unit,
  13049                                                   "Unable to free policer "
  13050                                                   "handle \n")));
  13051                             return BCM_E_INTERNAL;
  13052                         }
  13053                         continue;
  13054                     }
  13055                     if (allocated_policer) {
  13056                         offset[allocated_policer] = pool - offset[0];
  13057                     } else {
  13058                         offset[allocated_policer] = pool;
  13059                     }
  13060                     allocated_policer++;
  13061                     if (allocated_policer == *numbers) {
  13062                        alloc_control[index].first_bit_to_use =
  13063                                          alloc_control[index].last_bit_to_use;
  13064                        alloc_control[index].last_bit_to_use = offset[0];
  13065                        break;
  13066                     }
  13067                 }
  13068                 if (allocated_policer != *numbers) {
  13069                      /* free all the allocated policers */
  13070                     rv = _bcm_global_meter_free_allocated_policer_on_error(
  13071                                      unit, allocated_policer, offset, index);
  13072                     if (skip_index == 0 ) {
  13073                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13074                                   (BSL_META_U(unit,
  13075                                               "Unable to free policer "
  13076                                               "handle \n")));
  13077                         return BCM_E_INTERNAL;
  13078                     }
  13079                 } else if( allocated_policer == *numbers) {
  13080                     *pid = index;
  13081                     alloc_control[index].no_of_groups_allocated++;
  13082                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13083                               (BSL_META_U(unit,
  13084                                           "Allocated base policer with "
  13085                                           "index %x \n"), index));
  13086                     return BCM_E_NONE;
  13087                 }
  13088             }
  13089         } else {   /* No Cascade group assigned */
  13090             map = alloc_control[index].alloc_bit_map;
  13091             policers_available = _shr_popcount(map);
  13092             if (policers_available < *numbers) {
  13093                 continue;
  13094             }
  13095             offset[0] = 0;
  13096             /* Use shared aligned index management to allocate policers */
  13097             for (pool = 0; pool < max_pool; pool++) {
  13098                 handle_id = pool * num_banks_per_pool + index / bank_size;
  13099                 bank_index = index % bank_size;
  13100 
  13101                 rv = shr_aidxres_list_reserve_block(
  13102                      meter_alloc_list_handle[unit][handle_id], bank_index, 1);
  13103                 if (!BCM_SUCCESS(rv)) {
  13104                     if (allocated_policer) {
  13105                        /* free all the allocated policers */
  13106                        rv = _bcm_global_meter_free_allocated_policer_on_error(unit,
  13107                                               allocated_policer, offset, index);
  13108 
  13109                        skip_index = 1;
  13110                        allocated_policer = 0;
  13111                     }
  13112                     continue;
  13113                 }
  13114                 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool,
  13115                                                                       index);
  13116                 if (!BCM_SUCCESS(rv)) {
  13117                     rv = shr_aidxres_list_free(
  13118                             meter_alloc_list_handle[unit][handle_id], bank_index);
  13119                     if (!BCM_SUCCESS(rv)) {
  13120                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13121                                   (BSL_META_U(unit,
  13122                                               "Unable to free policer "
  13123                                               "handle \n")));
  13124                         return BCM_E_INTERNAL;
  13125                     }
  13126                     continue;
  13127                 }
  13128                 if (allocated_policer == 0) {
  13129                     alloc_control[index].first_bit_to_use = pool;
  13130                     offset[allocated_policer]=pool;
  13131                 } else {
  13132                     offset[allocated_policer] = pool - offset[0];
  13133                 }
  13134                 allocated_policer++;
  13135                 if (allocated_policer == *numbers) {
  13136                    alloc_control[index].last_bit_to_use = pool;
  13137                    break;
  13138                 }
  13139             }
  13140             if (allocated_policer != *numbers) {
  13141                  /* free all the allocated policers */
  13142                 rv = _bcm_global_meter_free_allocated_policer_on_error(unit,
  13143                                               allocated_policer, offset, index);
  13144                 if (skip_index == 0) {
  13145                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13146                               (BSL_META_U(unit,
  13147                                           "Unable to free policer "
  13148                                           "handle \n")));
  13149                     return BCM_E_INTERNAL;
  13150                 }
  13151             } else if( allocated_policer == *numbers) {
  13152                 *pid = index;
  13153                 alloc_control[index].no_of_groups_allocated++;
  13154                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  13155                           (BSL_META_U(unit,
  13156                                       "Allocated base policer with index %x \n"),
  13157                            index));
  13158                 return BCM_E_NONE;
  13159             }
  13160         }
  13161     }
  13162     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13163               (BSL_META_U(unit,
  13164                           "Unable to allocate policer as table is full  \n")));
  13165     return BCM_E_FULL;
  13166 }
  13167 
  13168 /*
  13169  * Function:
  13170  *      _bcm_global_meter_reserve_bloc_horizontally
  13171  * Purpose:
  13172  *      reset the bit in the inernal data structure corresponding
  13173  *      to the policer that is being reserved.
  13174  * Parameters:
  13175  *     unit                  - (IN) unit number
  13176  *     pool_id               - (IN) polier pool number
  13177  *     pid                   - (IN) policer id
  13178  * Returns:
  13179  *     BCM_E_XXX
  13180  */
  13181 
  13182 int _bcm_global_meter_reserve_bloc_horizontally(int unit, int pool_id,
  13183                                            bcm_policer_t pid)
  13184 {
  13185     int rv = BCM_E_NONE;
  13186     global_meter_hz_alloc_bookkeep[unit][pid].alloc_bit_map \
  13187                        &= convert_to_mask(pool_id);
  13188     return rv;
  13189 }
  13190 
  13191 /*
  13192  * Function:
  13193  *      _bcm_esw_get_policer_control
  13194  * Purpose:
  13195  *     Get the policer control data sructure for a given pool, offset mode
  13196  *     and index in the pool.
  13197  * Parameters:
  13198  *     unit                  - (IN) unit number
  13199  *     pid                   - (IN) policer id
  13200  *     pool                  - (IN) polier pool number
  13201  *     offset_mode           - (IN) meter offset mode
  13202  *     policer_control       - (OUT) polier control info
  13203  * Returns:
  13204  *     BCM_E_XXX
  13205  */
  13206 
  13207 int _bcm_esw_get_policer_control(int unit, bcm_policer_t pid,
  13208                                  int pool, int offset_mode,
  13209               _global_meter_policer_control_t **policer_control)
  13210 {
  13211     int rv = BCM_E_NONE;
  13212     bcm_policer_t policer_id = 0;
  13213     int size_pool = 0;
  13214     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  13215     policer_id = (((offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT) +
  13216                     (pool << _shr_popcount(size_pool - 1)) + pid);
  13217     rv = _bcm_global_meter_policer_get(unit, policer_id, policer_control);
  13218     return rv;
  13219 }
  13220 
  13221 /*
  13222  * Function:
  13223  *      _bcm_gloabl_meter_free_horizontally
  13224  * Purpose:
  13225  *      Free the bits in the inernal data structure corresponding
  13226  *      to set of policer that is being destroyed.
  13227  * Parameters:
  13228  *     unit                  - (IN) unit number
  13229  *     pool_id               - (IN) polier pool number
  13230  *     pid                   - (IN) policer id
  13231  *     numbers               - (IN) Number of policers to be freed
  13232  *     offset                - (IN) offset w.r.t pid
  13233  * Returns:
  13234  *     BCM_E_XXX
  13235  */
  13236 
  13237 int _bcm_gloabl_meter_free_horizontally(int unit, int pool_id,
  13238                                          bcm_policer_t pid,
  13239                                          int numbers, uint8 offset[8])
  13240 {
  13241     int rv = BCM_E_NONE;
  13242     int index = 0;
  13243      _global_meter_horizontal_alloc_t *alloc_control;
  13244     int num_pol = 0;
  13245     int actual_pool = 0;
  13246     _global_meter_policer_control_t *policer_control = NULL;
  13247     alloc_control = global_meter_hz_alloc_bookkeep[unit];
  13248     actual_pool = pool_id;
  13249     for (index = 0; index < numbers; index++)
  13250     {
  13251         if (index > 0) {
  13252            actual_pool = pool_id + offset[index];
  13253         }
  13254         alloc_control[pid].alloc_bit_map |=
  13255                              ((~convert_to_mask(actual_pool)) & 0xFF);
  13256     }
  13257     if ((numbers > 1) && (alloc_control[pid].no_of_groups_allocated)) {
  13258         alloc_control[pid].no_of_groups_allocated--;
  13259         if (alloc_control[pid].no_of_groups_allocated == 1) {
  13260             if (pool_id + offset[index - 1] ==
  13261                                  alloc_control[pid].first_bit_to_use) {
  13262                 rv = _bcm_esw_get_policer_control(unit, pid,
  13263                                      alloc_control[pid].last_bit_to_use,
  13264                                          0, &policer_control);
  13265                 if (!BCM_SUCCESS(rv)) {
  13266                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13267                               (BSL_META_U(unit,
  13268                                           "Unable to get policer control for pid "
  13269                                           "%x\n"), pid));
  13270                     return rv;
  13271                 }
  13272                 alloc_control[pid].first_bit_to_use =
  13273                                         alloc_control[pid].last_bit_to_use;
  13274                 num_pol = policer_control->no_of_policers;
  13275                 if (num_pol > 0 ) {
  13276                     pool_id = policer_control->offset[0] +
  13277                           policer_control->offset[num_pol-1];
  13278                     alloc_control[pid].last_bit_to_use = pool_id;
  13279                 } else {
  13280                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13281                               (BSL_META_U(unit,
  13282                                           "Number of policers in policer control "
  13283                                           "structure is 0\n")));
  13284                     return BCM_E_INTERNAL;
  13285                 }
  13286             } else if (pool_id == alloc_control[pid].last_bit_to_use) {
  13287                 alloc_control[pid].last_bit_to_use =
  13288                                        alloc_control[pid].first_bit_to_use;
  13289                 rv = _bcm_esw_get_policer_control(unit, pid,
  13290                                      alloc_control[pid].first_bit_to_use,
  13291                                          0, &policer_control);
  13292                 if (!BCM_SUCCESS(rv)) {
  13293                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13294                               (BSL_META_U(unit,
  13295                                           "Unable to get policer control for pid "
  13296                                           "%x\n"), pid));
  13297                     return rv;
  13298                 }
  13299                 num_pol = policer_control->no_of_policers;
  13300                 if (num_pol > 0 ) {
  13301                     pool_id = policer_control->offset[0];
  13302                     alloc_control[pid].first_bit_to_use = pool_id;
  13303                 } else {
  13304                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13305                               (BSL_META_U(unit,
  13306                                           "Number of policers in policer control "
  13307                                           "structure is 0\n")));
  13308                     return BCM_E_INTERNAL;
  13309                 }
  13310             }
  13311         }
  13312     }
  13313     return rv;
  13314 }
  13315 
  13316 /*
  13317  * Function:
  13318  *      _bcm_gloabl_meter_unreserve_bloc_horizontally
  13319  * Purpose:
  13320  *      Free the bit in the inernal data structure corresponding
  13321  *      to the policer that is being destroyed.
  13322  * Parameters:
  13323  *     unit                  - (IN) unit number
  13324  *     pool_id               - (IN) polier pool number
  13325  *     pid                   - (IN) policer id
  13326  * Returns:
  13327  *     BCM_E_XXX
  13328  */
  13329 int _bcm_gloabl_meter_unreserve_bloc_horizontally(int unit, int pool_id,
  13330                                            bcm_policer_t pid)
  13331 {
  13332     int rv = BCM_E_NONE;
  13333 
  13334     global_meter_hz_alloc_bookkeep[unit][pid].alloc_bit_map \
  13335         |= (~convert_to_mask(pool_id) & 0xFF);
  13336     return rv;
  13337 }
  13338 
  13339 /*
  13340  * Function:
  13341  *      _global_meter_reserve_policer_id
  13342  * Purpose:
  13343  *      Reserve a given policer id.
  13344  * Parameters:
  13345  *     unit                  - (IN) unit number
  13346  *     direction             - (IN) Horizontal/Vertical
  13347  *     numbers               - (IN) Number of policers to be reserved
  13348  *     pid                   - (IN) base policer id
  13349  *     pid_offset            - (IN) Offset w.r.t base policer
  13350  * Returns:
  13351  * Returns:
  13352  * Returns:
  13353  *     BCM_E_XXX
  13354  */
  13355 int _global_meter_reserve_policer_id(int unit, int direction, int numbers,
  13356                                              bcm_policer_t pid,
  13357                                              uint8 *pid_offset)
  13358 {
  13359     int rv = BCM_E_NONE;
  13360     uint32 index = 0, free_index = 0;
  13361     int pool = 0, pol_index = 0, pool_id = 0;
  13362     int offset_mask = 0;
  13363     int size_pool = 0, num_pools = 0;
  13364     int pool_mask = 0, pool_offset = 0;
  13365     int bank_size  = 0, bank_index = 0, num_banks_per_pool = 1;
  13366     int handle_id = 0;
  13367 
  13368     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  13369     num_pools =  SOC_INFO(unit).global_meter_pools;
  13370     offset_mask = size_pool - 1;
  13371     pool_offset = _shr_popcount(offset_mask);
  13372     pool_mask = (num_pools - 1) << pool_offset;
  13373 
  13374     pool = (pid & pool_mask) >> pool_offset;
  13375     pol_index = pid & offset_mask;
  13376 
  13377     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  13378     bank_size = size_pool / num_banks_per_pool;
  13379     handle_id = pool * num_banks_per_pool + pol_index / bank_size;
  13380     bank_index = pol_index % bank_size;
  13381 
  13382     if (direction == GLOBAL_METER_ALLOC_VERTICAL) {
  13383         if (soc_feature(unit,
  13384                     soc_feature_global_meter_compaction_support)) {
  13385 
  13386             rv = shr_aidxres_list_reserve(
  13387                     meter_alloc_list_handle[unit][handle_id],
  13388                     bank_index, bank_index + numbers - 1);
  13389         } else {
  13390             rv = shr_aidxres_list_reserve_block(
  13391                     meter_alloc_list_handle[unit][handle_id],
  13392                     bank_index, numbers);
  13393         }
  13394         if (!BCM_SUCCESS(rv)) {
  13395             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13396                       (BSL_META_U(unit,
  13397                                   "Unable to reserve policer in shared index "
  13398                                   "management\n")));
  13399             return BCM_E_INTERNAL;
  13400         }
  13401         for (index = 0; index < numbers; index++) {
  13402             rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool,
  13403                                                             pol_index + index);
  13404             if (!BCM_SUCCESS(rv)) {
  13405                 rv = shr_aidxres_list_free(
  13406                      meter_alloc_list_handle[unit][handle_id], bank_index);
  13407                 if (!BCM_SUCCESS(rv)) {
  13408                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13409                               (BSL_META_U(unit,
  13410                                           "Unable to free policer in shared "
  13411                                           "index management\n")));
  13412                     return BCM_E_INTERNAL;
  13413                 }
  13414                 for (free_index = 0; free_index < index; free_index++) {
  13415                     rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit,
  13416                                                       pool, pol_index+index);
  13417                     if (!BCM_SUCCESS(rv)) {
  13418                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13419                                   (BSL_META_U(unit,
  13420                                               "Unable to free policer in hz "
  13421                                               "index management\n")));
  13422                         return BCM_E_INTERNAL;
  13423                     }
  13424                 }
  13425             }
  13426         }
  13427 
  13428     } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  13429         for (index = 0; index < numbers; index++) {
  13430             if (index > 0) {
  13431                 pool_id = pool + pid_offset[index];
  13432             }
  13433             handle_id = pool_id * num_banks_per_pool + pol_index / bank_size;
  13434             bank_index = pol_index % bank_size;
  13435 
  13436             rv = shr_aidxres_list_reserve_block(
  13437                     meter_alloc_list_handle[unit][handle_id], bank_index, 1);
  13438             if (!BCM_SUCCESS(rv)) {
  13439                 for (free_index = 0; free_index < index; free_index++) {
  13440                     pool_id = pool + pid_offset[free_index];
  13441                     handle_id = pool_id * num_banks_per_pool + pol_index / bank_size;
  13442                     bank_index = pol_index % bank_size;
  13443 
  13444                     rv = shr_aidxres_list_free(
  13445                             meter_alloc_list_handle[unit][handle_id], bank_index);
  13446 
  13447                     if (BCM_SUCCESS(rv)) {
  13448                         rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit,
  13449                                     pool_id, pol_index);
  13450                     }
  13451                     if (BCM_FAILURE(rv)) {
  13452                         break;
  13453                     }
  13454                 }
  13455                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  13456                         (BSL_META_U(unit,
  13457                                     "Unable to reserve policer in shared "
  13458                                     "index management\n")));
  13459                 return BCM_E_INTERNAL;
  13460             }
  13461             rv = _bcm_global_meter_reserve_bloc_horizontally(unit,
  13462                              pool_id, pol_index);
  13463             if (!BCM_SUCCESS(rv)) {
  13464                 rv = shr_aidxres_list_free(
  13465                         meter_alloc_list_handle[unit][handle_id], bank_index);
  13466                 if (!BCM_SUCCESS(rv)) {
  13467                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13468                               (BSL_META_U(unit,
  13469                                           "Unable to free policer in "
  13470                                           "index management\n")));
  13471                     return BCM_E_INTERNAL;
  13472                 }
  13473                 for (free_index=0; free_index < index; free_index++) {
  13474                     rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit,
  13475                                                      pool_id, pol_index);
  13476                     if (!BCM_SUCCESS(rv)) {
  13477                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13478                                   (BSL_META_U(unit,
  13479                                               "Unable to free policer in hz "
  13480                                               "index management\n")));
  13481                         return BCM_E_INTERNAL;
  13482                     }
  13483                 }
  13484             }
  13485         }
  13486     } else {
  13487         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13488                   (BSL_META_U(unit,
  13489                               "Invalid direction for policer allocation \n")));
  13490         return BCM_E_INTERNAL;
  13491     }
  13492     return rv;
  13493 }
  13494 
  13495 /*
  13496  * Function:
  13497  *      _global_meter_policer_id_alloc
  13498  * Purpose:
  13499  *     Allocate a new policer.
  13500  * Parameters:
  13501  *     unit                  - (IN) unit number
  13502  *     direction             - (IN) Horizontal/Vertical
  13503  *     numbers               - (IN/OUT) Number of policers
  13504  *     pid                   - (OUT) base policer id
  13505  *     flow_info             - (IN) information about flow type and skip pool
  13506  *     pid_offset            - (OUT) Offset w.r.t base policer
  13507  * Returns:
  13508  *     BCM_E_XXX
  13509  */
  13510 int _global_meter_policer_id_alloc(int unit, int direction, int *numbers,
  13511                                     bcm_policer_t *pid,
  13512                                     _bcm_policer_flow_info_t *flow_info,
  13513                                     uint8 *pid_offset)
  13514 {
  13515     int rv = BCM_E_NONE;
  13516     uint32 index = 0, no_of_pools_checked = 0;
  13517     static uint32 pool = 0;
  13518     int size_pool = 0, num_pools = 0;
  13519     int bank_size = 0, bank_index = 0;
  13520     int meter_allocated = 0;
  13521     _bcm_policer_flow_type_t flow_type;
  13522     int skip_pool, skip_bank, bank_id = 0;
  13523     int num_banks_per_pool = 1, handle_id = 0;
  13524 
  13525     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  13526     num_pools =  SOC_INFO(unit).global_meter_pools;
  13527 
  13528     flow_type = flow_info->flow_type;
  13529     skip_pool = flow_info->skip_pool;
  13530     skip_bank = flow_info->skip_bank;
  13531 
  13532     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  13533     bank_size = size_pool / num_banks_per_pool;
  13534 
  13535     if (direction == GLOBAL_METER_ALLOC_VERTICAL) {
  13536         if ((flow_type == bcmPolicerFlowTypeMacro) ||
  13537                 (flow_type == bcmPolicerFlowTypeNormal)) {
  13538             no_of_pools_checked = 0;
  13539             for ( ;no_of_pools_checked < num_pools; pool++) {
  13540                 if (pool >= num_pools) {
  13541                     pool = 0;
  13542                 }
  13543                 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) {
  13544 
  13545                     /* For Macro flow use only one bank */
  13546                     if (flow_type == bcmPolicerFlowTypeMacro) {
  13547                         if (bank_id > 0) {
  13548                             break;
  13549                         }
  13550                     }
  13551                     handle_id = pool * num_banks_per_pool + bank_id;
  13552                     rv = shr_aidxres_list_alloc_block(
  13553                             (meter_alloc_list_handle[unit][handle_id]),
  13554                             *numbers, (uint32 *)&bank_index);
  13555 
  13556                     if (BCM_SUCCESS(rv)) {
  13557                         meter_allocated = 1;
  13558                         (*pid) = bank_size * bank_id + bank_index;
  13559                         break;
  13560                     }
  13561                 }
  13562                 if (meter_allocated == 1) {
  13563                     break;
  13564                 }
  13565                 no_of_pools_checked++;
  13566             }
  13567         } else {
  13568             /* flow_type == bcmPolicerFlowTypeMicro */
  13569             if (soc_feature(unit, soc_feature_global_meter_macro_micro_same_pool)) {
  13570                 /* If this soc feature is defined, it means that micro and macro
  13571                  * meter must reside in same pool but different bank. A pool is
  13572                  * divided into 2 banks.*/
  13573 
  13574                 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) {
  13575                     if (skip_bank == bank_id) {
  13576                         continue;
  13577                     }
  13578 
  13579                     /* micro flow must be in the same pool as Macro flow (skip_pool) */
  13580                     pool = skip_pool;
  13581                     handle_id = skip_pool * num_banks_per_pool + bank_id;
  13582                     rv = shr_aidxres_list_alloc_block(
  13583                             (meter_alloc_list_handle[unit][handle_id]),
  13584                             *numbers, (uint32 *)&bank_index);
  13585 
  13586                     if (BCM_SUCCESS(rv)) {
  13587                         meter_allocated = 1;
  13588                         (*pid) = bank_size * bank_id + bank_index;
  13589                         break;
  13590                     }
  13591                 }
  13592             } else {
  13593                 /* macro-micro meter must reside in different pools */
  13594                 no_of_pools_checked = 0;
  13595                 for ( ;no_of_pools_checked < num_pools; pool++) {
  13596                     for (bank_id =0; bank_id < num_banks_per_pool; bank_id++) {
  13597 
  13598                         if (pool >= num_pools) {
  13599                             pool = 0;
  13600                         }
  13601 
  13602                         if (pool == skip_pool) {
  13603                             no_of_pools_checked++;
  13604                             continue;
  13605                         }
  13606 
  13607                         handle_id = pool * num_banks_per_pool + bank_id;
  13608                         rv = shr_aidxres_list_alloc_block(
  13609                                 (meter_alloc_list_handle[unit][handle_id]),
  13610                                 *numbers, (uint32 *)&bank_index);
  13611 
  13612                         if (BCM_SUCCESS(rv)) {
  13613                             meter_allocated = 1;
  13614                             (*pid) = bank_size * bank_id + bank_index;
  13615                             break;
  13616                         }
  13617                     }
  13618                     if (meter_allocated == 1) {
  13619                         break;
  13620                     }
  13621                     no_of_pools_checked++;
  13622                 }
  13623             }
  13624         }
  13625 
  13626         if (meter_allocated == 0) {
  13627             return BCM_E_FULL;
  13628         } else {
  13629             /* add code to set bits in horizontal allocation datastruture */
  13630             for (index = 0; index < *numbers; index++) {
  13631                 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool,
  13632                         ((*pid)+index));
  13633                 if (!BCM_SUCCESS(rv)) {
  13634                     for (index = 0; index < *numbers; index++) {
  13635                         rv = shr_aidxres_list_free(
  13636                                 meter_alloc_list_handle[unit][handle_id],
  13637                                 bank_index + index);
  13638                     }
  13639                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  13640                             (BSL_META_U(unit,
  13641                                         "Unable to free policer in "
  13642                                         "index management\n")));
  13643                     return BCM_E_INTERNAL;
  13644                 }
  13645             }
  13646             /* Add pool id to make complete policer id */
  13647             *pid = *pid | (pool << _shr_popcount(size_pool - 1));
  13648             pool++;
  13649             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13650                     (BSL_META_U(unit,
  13651                                 "allocated policer with pid %x \n"),
  13652                      *pid));
  13653 
  13654             return rv;
  13655         }
  13656     } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  13657 
  13658         /* alloc horizontally */
  13659         rv = _bcm_gloabl_meter_alloc_horizontally(unit, numbers, pid,
  13660                 pid_offset);
  13661         if (!BCM_SUCCESS(rv)) {
  13662             return BCM_E_FULL;
  13663         }
  13664         *pid |= (*pid_offset << _shr_popcount(size_pool - 1));
  13665         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13666                 (BSL_META_U(unit,
  13667                             "allocated policer with pid %x \n"),
  13668                  *pid));
  13669     }
  13670     return rv;
  13671 }
  13672 /*
  13673  * Function:
  13674  *      _bcm_global_meter_max_rate_set
  13675  * Purpose:
  13676  *      get CIR/EIR max value.
  13677  * Parameters:
  13678  *     rate                - (IN) CIR/EIR
  13679  *     refreshmax          - (IN) refresh_max value
  13680  *     max_rate            - (OUT) CIR/EIR max value
  13681  * Returns:
  13682  *     BCM_E_XXX
  13683  */
  13684 void _bcm_global_meter_max_rate_set(uint32 rate,
  13685                                    uint32 refreshmax, uint32 *max_rate) {
  13686     if (rate == 0) {
  13687         *max_rate = 0;
  13688     }
  13689     if (refreshmax == GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT) {
  13690         *max_rate = 0xffffffff;
  13691     } else {
  13692         *max_rate = (rate * refresh_max[refreshmax]) / 100;
  13693     }
  13694 }
  13695 
  13696 /*
  13697  * Function:
  13698  *      _bcm_global_meter_read_config_from_hw
  13699  * Purpose:
  13700  *       Read policer configuration form the HW table entry.
  13701  * Parameters:
  13702  *     unit                  - (IN) unit number
  13703  *     policer_id            - (IN) policer id
  13704  *     pol_cfg               - (OUT) policer configuration
  13705  * Returns:
  13706  *     BCM_E_XXX
  13707  */
  13708 int _bcm_global_meter_read_config_from_hw(int unit,
  13709                                           bcm_policer_t policer_id,
  13710                                           bcm_policer_config_t *pol_cfg)
  13711 {
  13712 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  13713     svm_meter_table_entry_t data;
  13714     int rv = BCM_E_NONE;
  13715     uint32    refresh_rate = 0;    /* Policer refresh rate.    */
  13716     uint32    granularity = 0;     /* Policer granularity.     */
  13717     uint32  mode = 0, mode_modifier = 0, coupling = 0;
  13718     uint32 bucket_count = 0, bucket_size = 0;
  13719     int index = 0, cascade_index = 0;
  13720     uint32 refreshmax = 0;
  13721     uint32    chain = 0;
  13722     uint32 pkt_bytes = 0;
  13723     _global_meter_policer_control_t *policer_control = NULL;
  13724      uint32 flags=0;
  13725 
  13726     /* read HW register */
  13727     _bcm_esw_get_policer_table_index(unit, policer_id, &index);
  13728     rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,index, &data);
  13729     if (!BCM_SUCCESS(rv)) {
  13730         LOG_DEBUG(BSL_LS_BCM_POLICER,
  13731                   (BSL_META_U(unit,
  13732                               "Unable to read SVM METER TABLE at index %d "
  13733                               "\n"), index));
  13734         return rv;
  13735     }
  13736     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) {
  13737         soc_SVM_METER_TABLEm_field_get(unit, &data, COUPLING_FLAGf, &coupling);
  13738     }
  13739     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) {
  13740         soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODIFIERf,
  13741                                                      &mode_modifier);
  13742         if (mode_modifier == 0) {
  13743             pol_cfg->flags = BCM_POLICER_COLOR_BLIND;
  13744         } else {
  13745             pol_cfg->flags = 0; /* color aware */
  13746         }
  13747     }
  13748     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) {
  13749         soc_SVM_METER_TABLEm_field_get(unit, &data, PKT_BYTESf,
  13750                                                      &pkt_bytes);
  13751         if (pkt_bytes == 0) {
  13752             pol_cfg->flags |= BCM_POLICER_MODE_BYTES;
  13753         } else {
  13754             pol_cfg->flags |= BCM_POLICER_MODE_PACKETS;
  13755         }
  13756 
  13757     }
  13758     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  13759         soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODEf, &mode);
  13760         switch (mode) {
  13761 
  13762             case GLOBAL_METER_MODE_DEFAULT:
  13763                 if (mode_modifier) {
  13764                     pol_cfg->mode = bcmPolicerModePassThrough;
  13765                 } else {
  13766                     pol_cfg->mode = bcmPolicerModeGreen;
  13767                 }
  13768                 break;
  13769 
  13770             case GLOBAL_METER_MODE_SR_TCM:
  13771                 pol_cfg->mode = bcmPolicerModeSrTcm;
  13772                 break;
  13773 
  13774             case GLOBAL_METER_MODE_SR_TCM_MODIFIED:
  13775                 pol_cfg->mode = bcmPolicerModeSrTcmModified;
  13776                 break;
  13777 
  13778             case GLOBAL_METER_MODE_TR_TCM:
  13779                 pol_cfg->mode = bcmPolicerModeTrTcm;
  13780                 break;
  13781 
  13782             case GLOBAL_METER_MODE_TR_TCM_MODIFIED:
  13783                 pol_cfg->mode = bcmPolicerModeTrTcmDs;
  13784                 if (coupling) {
  13785                    pol_cfg->mode = bcmPolicerModeCoupledTrTcmDs;
  13786                 }
  13787                 break;
  13788 
  13789             case GLOBAL_METER_MODE_CASCADE:
  13790                 pol_cfg->mode = bcmPolicerModeCascade;
  13791                 if (coupling) {
  13792                    pol_cfg->mode = bcmPolicerModeCoupledCascade;
  13793                 }
  13794                 break;
  13795 
  13796             default:
  13797                 break;
  13798         }
  13799     }
  13800 
  13801     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_BUCKETCOUNTf)) {
  13802         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETCOUNTf,
  13803                                                            &bucket_count);
  13804     }
  13805     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_REFRESHCOUNTf)) {
  13806         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHCOUNTf,
  13807                                                            &refresh_rate);
  13808     }
  13809     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_BUCKETSIZEf)) {
  13810         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETSIZEf,
  13811                                                              &bucket_size);
  13812     }
  13813     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) {
  13814        soc_SVM_METER_TABLEm_field_get(unit, &data, METER_GRANf,&granularity);
  13815     }
  13816     soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHMAXf,
  13817                                                                &refreshmax);
  13818     flags =  _BCM_XGS_METER_FLAG_GRANULARITY |
  13819                         _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
  13820 
  13821     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  13822         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
  13823     }
  13824     if (pol_cfg->mode == bcmPolicerModeCoupledCascade) {
  13825         rv = _bcm_xgs_bucket_encoding_to_kbits
  13826             (refresh_rate, bucket_size, granularity,
  13827                     flags,
  13828              &pol_cfg->pkbits_sec, &pol_cfg->pkbits_burst);
  13829         if (!BCM_SUCCESS(rv)) {
  13830             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13831                       (BSL_META_U(unit,
  13832                                   "Unable to translate rate in kbps to bucket size "
  13833                                   "and granularity \n")));
  13834             return rv;
  13835         }
  13836         _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec,
  13837                                         refreshmax, &pol_cfg->max_pkbits_sec);
  13838     } else {
  13839         rv = _bcm_xgs_bucket_encoding_to_kbits
  13840             (refresh_rate, bucket_size, granularity,
  13841                     flags,
  13842              &pol_cfg->ckbits_sec, &pol_cfg->ckbits_burst);
  13843         if (!BCM_SUCCESS(rv)) {
  13844             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13845                       (BSL_META_U(unit,
  13846                                   "Unable to translate rate in kbps to bucket size "
  13847                                   "and granularity \n")));
  13848             return rv;
  13849        }
  13850         _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec,
  13851                                         refreshmax, &pol_cfg->max_ckbits_sec);
  13852     }
  13853 
  13854     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) {
  13855         soc_SVM_METER_TABLEm_field_get(unit, &data,
  13856                          METER_SHARING_MODEf, &pol_cfg->sharing_mode);
  13857     }
  13858     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) {
  13859         soc_SVM_METER_TABLEm_field_get(unit,
  13860               &data, POLICY_TABLE_INDEXf, &pol_cfg->action_id);
  13861     }
  13862 
  13863     if (mode == GLOBAL_METER_MODE_CASCADE) {
  13864         soc_SVM_METER_TABLEm_field_get(unit, &data, START_OF_CHAINf, &chain);
  13865         if (chain) {
  13866             pol_cfg->flags |= BCM_POLICER_BW_SHARING_GROUP_START;
  13867         }
  13868         soc_SVM_METER_TABLEm_field_get(unit, &data, END_OF_CHAINf, &chain);
  13869         if (chain) {
  13870             pol_cfg->flags |= BCM_POLICER_BW_SHARING_GROUP_END;
  13871         }
  13872     }
  13873 
  13874     if (pol_cfg->mode == bcmPolicerModeCoupledCascade) {
  13875         rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  13876         if (BCM_FAILURE(rv)) {
  13877             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13878                       (BSL_META_U(unit,
  13879                                   "Unable to get policer control for the policer Id "
  13880                                   "passed  \n")));
  13881             return (rv);
  13882         }
  13883 
  13884         rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit,
  13885                                     policer_id, policer_control, &cascade_index);
  13886         BCM_IF_ERROR_RETURN(rv);
  13887         rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  13888                                                       cascade_index, &data);
  13889         if (!BCM_SUCCESS(rv)) {
  13890             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13891                       (BSL_META_U(unit,
  13892                                   "Unable to read SVM METER TABLE at index %d "
  13893                                   "\n"), cascade_index));
  13894            return rv;
  13895         }
  13896 
  13897         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHMAXf,
  13898                                                                &refreshmax);
  13899         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETCOUNTf,
  13900                                                         &bucket_count);
  13901         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHCOUNTf,
  13902                                                         &refresh_rate);
  13903         soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETSIZEf,
  13904                                                         &bucket_size);
  13905         rv = _bcm_xgs_bucket_encoding_to_kbits
  13906             (refresh_rate, bucket_size, granularity,
  13907              _BCM_XGS_METER_FLAG_GRANULARITY |
  13908                   _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER,
  13909              &pol_cfg->ckbits_sec, &pol_cfg->ckbits_burst);
  13910         if (!BCM_SUCCESS(rv)) {
  13911             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13912                       (BSL_META_U(unit,
  13913                                   "Unable to translate rate in kbps to bucket size "
  13914                                   "and granularity \n")));
  13915             return rv;
  13916         }
  13917         _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec,
  13918                                         refreshmax, &pol_cfg->max_ckbits_sec);
  13919     } else {
  13920         soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_REFRESHMAXf,
  13921                                                                &refreshmax);
  13922         soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_BUCKETCOUNTf,
  13923                                                         &bucket_count);
  13924         soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_REFRESHCOUNTf,
  13925                                                         &refresh_rate);
  13926         soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_BUCKETSIZEf,
  13927                                                         &bucket_size);
  13928         rv = _bcm_xgs_bucket_encoding_to_kbits
  13929             (refresh_rate, bucket_size, granularity,
  13930              _BCM_XGS_METER_FLAG_GRANULARITY |
  13931                   _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER,
  13932              &pol_cfg->pkbits_sec, &pol_cfg->pkbits_burst);
  13933         if (!BCM_SUCCESS(rv)) {
  13934             LOG_DEBUG(BSL_LS_BCM_POLICER,
  13935                       (BSL_META_U(unit,
  13936                                   "Unable to translate rate in kbps to bucket size "
  13937                                   "and granularity \n")));
  13938             return rv;
  13939         }
  13940         _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec,
  13941                                         refreshmax, &pol_cfg->max_pkbits_sec);
  13942     }
  13943 
  13944     return rv;
  13945 #else
  13946     return BCM_E_UNAVAIL;
  13947 #endif
  13948 }
  13949 
  13950 #if defined(BCM_APACHE_SUPPORT)
  13951 STATIC int
  13952 _bcm_global_meter_get_pool_from_policerId (int unit,
  13953                                            bcm_policer_t policer_id)
  13954 {
  13955     int size_pool = 0, num_pools = 0;
  13956     int offset_mask = 0;
  13957     int pool_mask = 0, pool_offset = 0;
  13958 
  13959     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  13960     num_pools =  SOC_INFO(unit).global_meter_pools;
  13961     offset_mask = size_pool - 1;
  13962     pool_offset = _shr_popcount(offset_mask);
  13963     pool_mask = (num_pools - 1) << pool_offset;
  13964 
  13965     return ((policer_id & pool_mask) >> pool_offset);
  13966 }
  13967 #endif
  13968 
  13969 /*
  13970  * Function:
  13971  *      _bcm_global_meter_read_config_from_hw_mef_10dot3
  13972  * Purpose:
  13973  *       Read policer configuration form the HW table entry.
  13974  * Parameters:
  13975  *     unit                  - (IN) unit number
  13976  *     policer_id            - (IN) policer id
  13977  *     pol_cfg               - (OUT) policer configuration
  13978  * Returns:
  13979  *     BCM_E_XXX
  13980  */
  13981 int
  13982 _bcm_global_meter_read_config_from_hw_mef_10dot3 (int unit,
  13983                                                   bcm_policer_t policer_id,
  13984                                                   bcm_policer_config_t *pol_cfg)
  13985 {
  13986 #if defined(BCM_APACHE_SUPPORT)
  13987     svm_meter_table_entry_t svm_entry;
  13988     int                     rv = BCM_E_NONE;
  13989     uint32                  refresh_rate = 0;    /* Policer refresh rate.    */
  13990     uint32                  granularity = 0;     /* Policer granularity.     */
  13991     uint32                  mode = 0, mode_modifier = 0, coupling = 0;
  13992     uint32                  bucket_count = 0, bucket_size = 0;
  13993     int                     index = 0, cascade_index = 0;
  13994     uint32                  refreshmax = 0, c_e = 0;
  13995     uint32                  pkt_bytes = 0, flags = 0;
  13996     uint32                  nxt_c = 0, nxt_e = 0, pair_e = 0;
  13997     uint32                  nxt_c_valid = 0, nxt_e_valid = 0, pair_e_valid = 0;
  13998     int                     gcf_mode = 0;
  13999     bcm_policer_t           corres_policer = 0;
  14000     _global_meter_policer_control_t *policer_control = NULL;
  14001 
  14002     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  14003     if (BCM_FAILURE(rv)) {
  14004         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14005                   (BSL_META_U(unit,
  14006                               "Unable to get policer control for the policer Id "
  14007                               "passed  \n")));
  14008         return (rv);
  14009     }
  14010 
  14011     /* read HW register */
  14012     _bcm_esw_get_policer_table_index(unit, policer_id, &index);
  14013     rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,index, &svm_entry);
  14014     if (!BCM_SUCCESS(rv)) {
  14015         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14016                   (BSL_META_U(unit,
  14017                               "Unable to read SVM METER TABLE at index %d "
  14018                               "\n"), index));
  14019         return rv;
  14020     }
  14021 
  14022     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COUPLING_FLAGf, &coupling);
  14023 
  14024     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_MODIFIERf,
  14025                                    &mode_modifier);
  14026     if (mode_modifier == 0) {
  14027         pol_cfg->flags = BCM_POLICER_COLOR_BLIND;
  14028     } else {
  14029         pol_cfg->flags = 0; /* color aware */
  14030     }
  14031 
  14032     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, PKT_BYTESf, &pkt_bytes);
  14033     if (pkt_bytes == 0) {
  14034         pol_cfg->flags |= BCM_POLICER_MODE_BYTES;
  14035     } else {
  14036         pol_cfg->flags |= BCM_POLICER_MODE_PACKETS;
  14037     }
  14038 
  14039     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  14040         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_MODEf, &mode);
  14041         switch (mode) {
  14042 
  14043             case GLOBAL_METER_MODE_DEFAULT:
  14044                 if (mode_modifier) {
  14045                     pol_cfg->mode = bcmPolicerModePassThrough;
  14046                 } else {
  14047                     pol_cfg->mode = bcmPolicerModeGreen;
  14048                 }
  14049                 break;
  14050 
  14051             case GLOBAL_METER_MODE_SR_TCM:
  14052                 pol_cfg->mode = bcmPolicerModeSrTcm;
  14053                 break;
  14054 
  14055             case GLOBAL_METER_MODE_SR_TCM_MODIFIED:
  14056                 pol_cfg->mode = bcmPolicerModeSrTcmModified;
  14057                 break;
  14058 
  14059             case GLOBAL_METER_MODE_TR_TCM:
  14060                 pol_cfg->mode = bcmPolicerModeTrTcm;
  14061                 break;
  14062 
  14063             case GLOBAL_METER_MODE_TR_TCM_MODIFIED:
  14064                 pol_cfg->mode = bcmPolicerModeTrTcmDs;
  14065                 if (coupling) {
  14066                    pol_cfg->mode = bcmPolicerModeCoupledTrTcmDs;
  14067                 }
  14068                 break;
  14069 
  14070             case GLOBAL_METER_MODE_CASCADE:
  14071                 pol_cfg->mode = bcmPolicerModeCascade;
  14072                 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm,
  14073                                         METER_PAIR_EXCESS_BUCKET_VALIDf)) {
  14074                     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14075                                                    METER_PAIR_EXCESS_BUCKET_VALIDf,
  14076                                                    &pair_e_valid);
  14077                 }
  14078                 if (pair_e_valid == 1) {
  14079                     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm,
  14080                                             METER_PAIR_EXCESS_BUCKETf)) {
  14081                         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14082                                                        METER_PAIR_EXCESS_BUCKETf,
  14083                                                        &pair_e);
  14084                     }
  14085 
  14086                     gcf_mode = 0;
  14087                     if ((policer_control->grp_mode == bcmPolicerGroupModeCascade) ||
  14088                          (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade) ||
  14089                          (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) {
  14090                         /* Group is non-gcf mode */
  14091                         gcf_mode = 0;
  14092                         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14093                                         COMMITTED_EXCESSf, &c_e);
  14094                         if (c_e == 1) {
  14095                             /* this policer is coupled cascade */
  14096                             pol_cfg->mode = bcmPolicerModeCoupledCascade;
  14097                         }
  14098                     } else if ((policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  14099                             (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  14100                         /* Group is GCF mode */
  14101                         gcf_mode = 1;
  14102                         pol_cfg->mode = bcmPolicerModeCoupledCascade;
  14103                         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14104                                         COMMITTED_EXCESSf, &c_e);
  14105                     }
  14106                 }
  14107                 break;
  14108 
  14109             default:
  14110                 break;
  14111         }
  14112     }
  14113 
  14114     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_BUCKETCOUNTf,
  14115                                    &bucket_count);
  14116 
  14117     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_REFRESHCOUNTf,
  14118                                    &refresh_rate);
  14119 
  14120     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_BUCKETSIZEf,
  14121                                    &bucket_size);
  14122 
  14123     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_GRANf,&granularity);
  14124 
  14125     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_REFRESHMAXf,
  14126                                    &refreshmax);
  14127 
  14128     flags =  _BCM_XGS_METER_FLAG_GRANULARITY |
  14129              _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
  14130     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  14131         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
  14132     }
  14133 
  14134     rv = _bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucket_size,
  14135                                            granularity, flags,
  14136                                            &pol_cfg->ckbits_sec,
  14137                                            &pol_cfg->ckbits_burst);
  14138     if (!BCM_SUCCESS(rv)) {
  14139         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14140                   (BSL_META_U(unit,
  14141                               "Unable to translate rate in kbps to bucket size "
  14142                               "and granularity \n")));
  14143         return rv;
  14144     }
  14145     _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec,
  14146                                    refreshmax, &pol_cfg->max_ckbits_sec);
  14147 
  14148     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14149                                    METER_SHARING_MODEf,
  14150                                    &pol_cfg->sharing_mode);
  14151 
  14152     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, POLICY_TABLE_INDEXf,
  14153                                    &pol_cfg->action_id);
  14154 
  14155     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14156                                    NXT_EXCESS_BUCKET_VALIDf,
  14157                                    &nxt_e_valid);
  14158     if ((gcf_mode == 0) && (nxt_e_valid == 1)) {
  14159         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14160                                        NXT_EXCESS_BUCKETf,
  14161                                        &nxt_e);
  14162         rv = _bcm_esw_get_corres_policer_for_pool(unit,  policer_id, nxt_e, &corres_policer);
  14163         BCM_IF_ERROR_RETURN(rv);
  14164         pol_cfg->npoflow_policer_id = corres_policer;
  14165     }
  14166 
  14167     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14168                                    NXT_COMMITTED_BUCKET_VALIDf,
  14169                                    &nxt_c_valid);
  14170     if ((gcf_mode == 0) && (nxt_c_valid == 1)) {
  14171         soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14172                                        NXT_COMMITTED_BUCKETf,
  14173                                        &nxt_c);
  14174         rv = _bcm_esw_get_corres_policer_for_pool(unit,  policer_id, nxt_c, &corres_policer);
  14175         BCM_IF_ERROR_RETURN(rv);
  14176         pol_cfg->ncoflow_policer_id = corres_policer;
  14177     }
  14178 
  14179     if (pol_cfg->mode == bcmPolicerModeCoupledCascade) {
  14180         if (gcf_mode == 1) {
  14181             /* Get the next Committed bucket / Excess bucket */
  14182             if (c_e == 0) {
  14183                 /* One of the pools from 0-2. Next Commit pool is set in nxt_c
  14184                    and Next Excess pool will be same */
  14185                 if (nxt_c_valid == 1) {
  14186                     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry,
  14187                                     NXT_COMMITTED_BUCKETf,
  14188                                     &nxt_c);
  14189                     rv = _bcm_esw_get_corres_policer_for_pool(unit,  policer_id, nxt_c, &corres_policer);
  14190                     BCM_IF_ERROR_RETURN(rv);
  14191                     pol_cfg->ncoflow_policer_id = corres_policer;
  14192                     pol_cfg->npoflow_policer_id = corres_policer;
  14193                 }
  14194             }
  14195             rv = _bcm_global_meter_get_coupled_cascade_policer_index(unit,
  14196                                     policer_id, policer_control, &cascade_index);
  14197         } else {
  14198             /* Group is configured as cascade but this policer mode is coupled cascade */
  14199             /* Excess bucket of this policer is stored in pool of nxt_c */
  14200             rv = _bcm_esw_get_corres_policer_for_pool(unit,  policer_id, nxt_c, &corres_policer);
  14201             BCM_IF_ERROR_RETURN(rv);
  14202             rv = _bcm_esw_get_policer_table_index(unit, corres_policer, &cascade_index);
  14203         }
  14204         BCM_IF_ERROR_RETURN(rv);
  14205         rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  14206                           cascade_index, &svm_entry);
  14207         if (!BCM_SUCCESS(rv)) {
  14208             LOG_DEBUG(BSL_LS_BCM_POLICER,
  14209                       (BSL_META_U(unit,
  14210                                   "Unable to read SVM METER TABLE at index %d "
  14211                                   "\n"), cascade_index));
  14212            return rv;
  14213         }
  14214     }
  14215     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_REFRESHMAXf,
  14216                                    &refreshmax);
  14217     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_BUCKETCOUNTf,
  14218                                    &bucket_count);
  14219     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_REFRESHCOUNTf,
  14220                                    &refresh_rate);
  14221     soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_BUCKETSIZEf,
  14222                                    &bucket_size);
  14223     rv = _bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucket_size, granularity,
  14224      _BCM_XGS_METER_FLAG_GRANULARITY | _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER,
  14225                                            &pol_cfg->pkbits_sec,
  14226                                            &pol_cfg->pkbits_burst);
  14227     if (!BCM_SUCCESS(rv)) {
  14228         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14229                   (BSL_META_U(unit,
  14230                               "Unable to translate rate in kbps to bucket size "
  14231                               "and granularity \n")));
  14232         return rv;
  14233     }
  14234     _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec,
  14235                                    refreshmax, &pol_cfg->max_pkbits_sec);
  14236 
  14237     return rv;
  14238 #else
  14239     return BCM_E_UNAVAIL;
  14240 #endif
  14241 }
  14242 
  14243 /*
  14244  * Function:
  14245  *      _bcm_esw_policer_action_detach
  14246  * Purpose:
  14247  *     Internal function to Disassociate a policer action from a given
  14248  *     policer id and readjust reference count.
  14249  * Parameters:
  14250  *     unit                  - (IN) unit number
  14251  *     policer_id            - (IN) policer id
  14252  *     action_id             - (IN) Action ID
  14253  * Returns:
  14254  *     BCM_E_XXX
  14255  */
  14256 int _bcm_esw_policer_action_detach(int unit, bcm_policer_t policer_id,
  14257                                 uint32 action_id)
  14258 {
  14259     int rv = BCM_E_NONE;
  14260     svm_meter_table_entry_t meter_entry;
  14261     _global_meter_policer_control_t *policer_control = NULL;
  14262     int policer_index = 0;
  14263     uint32 policy_index = 0;
  14264     int index = 0;
  14265     if (!soc_feature(unit, soc_feature_global_meter)) {
  14266         return BCM_E_UNAVAIL;
  14267     }
  14268     CHECK_GLOBAL_METER_INIT(unit);
  14269     /* validate policer id */
  14270     rv = _bcm_esw_policer_validate(unit, &policer_id);
  14271     if (BCM_FAILURE(rv)) {
  14272         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14273                   (BSL_META_U(unit,
  14274                               "Invalid Policer Id \n")));
  14275         return (rv);
  14276     }
  14277     /* validate action id */
  14278     if (action_id > soc_mem_index_max(unit, SVM_POLICY_TABLEm)) {
  14279         LOG_ERROR(BSL_LS_BCM_POLICER,
  14280                   (BSL_META_U(unit,
  14281                               "Invalid Action Id \n")));
  14282         return BCM_E_PARAM;
  14283     }
  14284     GLOBAL_METER_LOCK(unit);
  14285 
  14286     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  14287     if (BCM_FAILURE(rv)) {
  14288         GLOBAL_METER_UNLOCK(unit);
  14289         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14290                   (BSL_META_U(unit,
  14291                               "Unable to get policer control for the policer Id "
  14292                               "passed  \n")));
  14293         return (rv);
  14294     }
  14295     /*  read meter table and remove action_id*/
  14296     _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index);
  14297     rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index,
  14298                                                           &meter_entry);
  14299     if (BCM_FAILURE(rv)) {
  14300         GLOBAL_METER_UNLOCK(unit);
  14301         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14302                   (BSL_META_U(unit,
  14303                               "Unable to read SVM_METER_TABLE entry \n")));
  14304         return (rv);
  14305     }
  14306     /* set action to 0 */
  14307     soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf,
  14308                                                            &policy_index);
  14309 
  14310     /* Write to HW*/
  14311     rv = WRITE_SVM_METER_TABLEm(unit,MEM_BLOCK_ANY, policer_index,
  14312                                                             &meter_entry);
  14313     if (BCM_FAILURE(rv)) {
  14314         GLOBAL_METER_UNLOCK(unit);
  14315         LOG_DEBUG(BSL_LS_BCM_POLICER,
  14316                   (BSL_META_U(unit,
  14317                               "Unable to write SVM_METER_TABLE entry \n")));
  14318         return (rv);
  14319     }
  14320     /* in case of cascade with coupling we need to configure the second set
  14321        as well */
  14322     if ((policer_control->grp_mode ==                           \
  14323          bcmPolicerGroupModeIntPriCascadeWithCoupling) ||
  14324         (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) {
  14325 
  14326         rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit,
  14327                                       policer_id, policer_control, &index);
  14328         /*  read meter table and remove action_id*/
  14329         rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, index,
  14330                                    &meter_entry);
  14331         if (BCM_FAILURE(rv)) {
  14332             GLOBAL_METER_UNLOCK(unit);
  14333             LOG_DEBUG(BSL_LS_BCM_POLICER,
  14334                       (BSL_META_U(unit,
  14335                                   "Unable to read SVM_METER_TABLE entry \n")));
  14336             return (rv);
  14337         }
  14338         /* set action to 0 */
  14339         soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf,
  14340                                        &policy_index);
  14341         /* write to hW */
  14342         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index,
  14343                            &meter_entry);
  14344         if (BCM_FAILURE(rv)) {
  14345             LOG_DEBUG(BSL_LS_BCM_POLICER,
  14346                       (BSL_META_U(unit,
  14347                                   "Unable to write SVM_METER_TABLE entry \n")));
  14348             GLOBAL_METER_UNLOCK(unit);
  14349             return (rv);
  14350         }
  14351     }
  14352 
  14353    /* decrement action usage reference count */
  14354     if (global_meter_action_bookkeep[unit][action_id].reference_count > 0) {
  14355         global_meter_action_bookkeep[unit][action_id].reference_count--;
  14356     }
  14357     /* reset action id in policer control */
  14358     policer_control->action_id = 0;
  14359     GLOBAL_METER_UNLOCK(unit);
  14360     return rv;
  14361 }
  14362 
  14363 
  14364 /*
  14365  * Function:
  14366  *      _bcm_global_meter_refresh_max_get
  14367  * Purpose:
  14368  *      get refresh max value.
  14369  * Parameters:
  14370  *     rate                - (IN) CIR/EIR
  14371  *     max_rate            - (IN) CIRmax/EIRmax
  14372  *     refreshmax          - (OUT) REFRESH_MAX value
  14373  * Returns:
  14374  *     BCM_E_XXX
  14375  */
  14376 int _bcm_global_meter_refresh_max_get(uint32 rate,
  14377                                       uint32 max_rate, uint32 *refreshmax) {
  14378     int found = 0;
  14379     int multiplier = 0, i = 0;
  14380     if (rate == 0 && max_rate > 0) {
  14381         *refreshmax = GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT;
  14382     } else if (rate >= max_rate) {
  14383         *refreshmax = 0;
  14384     } else {
  14385         multiplier = ((max_rate * 100) / rate);
  14386         while ((refresh_max[i] != 0) && (found == 0)) {
  14387             if (refresh_max[i] == multiplier) {
  14388                 *refreshmax = i;
  14389                 found = 1;
  14390             } else if ((refresh_max[i] >  multiplier) && (i > 0)) {
  14391                 if (((refresh_max[i - 1] + refresh_max[i]) / 2) >= multiplier) {
  14392                     *refreshmax = (i - 1);
  14393                 } else {
  14394                     *refreshmax = i;
  14395                 }
  14396                 found = 1;
  14397             }
  14398             i++;
  14399         }
  14400         if (found == 0) {
  14401             *refreshmax = GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT;
  14402         }
  14403     }
  14404     return BCM_E_NONE;
  14405 }
  14406 
  14407 
  14408 /*
  14409  * Function:
  14410  *      _bcm_global_meter_write_config_to_hw
  14411  * Purpose:
  14412  *      Write policer configuraton to meter table.
  14413  * Parameters:
  14414  *     unit                  - (IN) unit number
  14415  *     pol_cfg               - (IN) policer configuration
  14416  *     policer_id            - (IN) policer id
  14417  *     policer_control       - (IN) Policer control info
  14418  * Returns:
  14419  *     BCM_E_XXX
  14420  */
  14421 int  _bcm_global_meter_write_config_to_hw(int unit,
  14422                                           bcm_policer_config_t *pol_cfg,
  14423                                           bcm_policer_t policer_id,
  14424                   _global_meter_policer_control_t *policer_control)
  14425 {
  14426 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  14427     int rv = BCM_E_NONE;
  14428     svm_meter_table_entry_t data;
  14429     uint32 flags=0;
  14430     uint32    c_bucketsize = 0, e_bucketsize = 0;  /* Bucket size.       */
  14431     uint32    c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate.*/
  14432     uint32    granularity = 0;     /* Policer granularity.     */
  14433     uint32    refresh_bitsize;     /* Number of bits for the
  14434                                       refresh rate field.      */
  14435     uint32    bucket_max_bitsize;  /* Number of bits for the
  14436                                       bucket max field.        */
  14437     uint32 c_bucketcount = 0, e_bucketcount=0,  bucket_cnt_bitsize = 0;
  14438     uint32 mode = 0, mode_modifier = 0;
  14439     uint32 coupling = 0, policy_index = 0;
  14440     uint32  c_refreshmax = 0, e_refreshmax = 0;
  14441     int index = 0;
  14442     uint32 current_action_id = 0;
  14443     bcm_policer_t  macro_meter_policer = 0;
  14444     int macro_flow_meter_index = 0;
  14445     svm_macroflow_index_table_entry_t macro_flow_entry;
  14446     uint32 start_of_chain = 0, end_of_chain = 0;
  14447     uint32 pkt_bytes = 0;
  14448     int incr_reqd = 0;
  14449     /* read HW register */
  14450     _bcm_esw_get_policer_table_index(unit, policer_id, &index);
  14451     rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &data);
  14452     BCM_IF_ERROR_RETURN(rv);
  14453     policy_index = pol_cfg->action_id;
  14454 
  14455     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) {
  14456         soc_SVM_METER_TABLEm_field_get(unit,
  14457               &data, POLICY_TABLE_INDEXf, &current_action_id);
  14458         if( policy_index != current_action_id ) {
  14459             if(current_action_id != 0) {
  14460                 /* detach the existing action and
  14461                  * decrement reference count
  14462                  */
  14463                 _bcm_esw_policer_action_detach(unit, policer_id,
  14464                                                current_action_id);
  14465             }
  14466             soc_SVM_METER_TABLEm_field_set(unit, &data,
  14467                                            POLICY_TABLE_INDEXf, &policy_index);
  14468             if (policy_index != 0) {
  14469                 incr_reqd = 1;
  14470             }
  14471         }
  14472     }
  14473 
  14474     flags = _BCM_XGS_METER_FLAG_GRANULARITY |
  14475                                  _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
  14476 
  14477     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  14478         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
  14479     } else {
  14480         flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE;
  14481     }
  14482     refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14483                                                      COMMITTED_REFRESHCOUNTf);
  14484     bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14485                                                      COMMITTED_BUCKETSIZEf);
  14486 
  14487     /* Calculate policer bucket size/refresh_rate/granularity. */
  14488     if (pol_cfg->pkbits_sec > pol_cfg->ckbits_sec) {
  14489         rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec,
  14490                                             pol_cfg->pkbits_burst,
  14491                                             flags, refresh_bitsize,
  14492                                             bucket_max_bitsize,
  14493                                             &c_refresh_rate, &c_bucketsize,
  14494                                             &granularity);
  14495         BCM_IF_ERROR_RETURN(rv);
  14496         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
  14497                                             pol_cfg->ckbits_sec,
  14498                                              pol_cfg->ckbits_burst,
  14499                                              flags, refresh_bitsize,
  14500                                              bucket_max_bitsize,
  14501                                              &c_refresh_rate, &c_bucketsize,
  14502                                              &granularity);
  14503         BCM_IF_ERROR_RETURN(rv);
  14504     }  else {
  14505          rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->ckbits_sec,
  14506                                             pol_cfg->ckbits_burst,
  14507                                             flags, refresh_bitsize,
  14508                                             bucket_max_bitsize,
  14509                                             &c_refresh_rate, &c_bucketsize,
  14510                                             &granularity);
  14511         BCM_IF_ERROR_RETURN(rv);
  14512     }
  14513 
  14514      /* Calculate initial backet count.
  14515      * bucket size << (bit count diff - 1(sign) -1 (overflow))  - 1
  14516      */
  14517     bucket_cnt_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14518                                               COMMITTED_BUCKETCOUNTf);
  14519     if (c_bucketsize == 0 && c_refresh_rate == 0) {
  14520         /* Committed should always be out of profile */
  14521         c_bucketcount = (1 << bucket_cnt_bitsize) - 1;
  14522     } else if (c_bucketsize) {
  14523         c_bucketcount =
  14524             (c_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2))  - 1;
  14525         c_bucketcount &= ((1 << bucket_cnt_bitsize) - 1);
  14526     } else {
  14527         c_bucketcount = 0;
  14528     }
  14529     rv =_bcm_global_meter_refresh_max_get(pol_cfg->ckbits_sec,
  14530                                         pol_cfg->max_ckbits_sec, &c_refreshmax);
  14531     BCM_IF_ERROR_RETURN(rv);
  14532 
  14533     if (pol_cfg->mode == bcmPolicerModeCoupledCascade) {
  14534         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHMAXf,
  14535                                                              &e_refreshmax);
  14536         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETCOUNTf,
  14537                                                             &e_bucketcount);
  14538         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHCOUNTf,
  14539                                                              &e_refresh_rate);
  14540         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETSIZEf,
  14541                                                                &e_bucketsize);
  14542     } else {
  14543         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf,
  14544                                                              &c_refreshmax);
  14545         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf,
  14546                                                              &c_bucketcount);
  14547         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf,
  14548                                                              &c_refresh_rate);
  14549         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf,
  14550                                                                &c_bucketsize);
  14551     }
  14552 
  14553     refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14554                                                          EXCESS_REFRESHCOUNTf);
  14555     bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14556                                                            EXCESS_BUCKETSIZEf);
  14557 
  14558     if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) {
  14559         rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec,
  14560                                             pol_cfg->pkbits_burst,
  14561                                             flags, refresh_bitsize,
  14562                                             bucket_max_bitsize,
  14563                                             &e_refresh_rate, &e_bucketsize,
  14564                                             &granularity);
  14565 
  14566     } else {
  14567         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
  14568                                             pol_cfg->pkbits_sec,
  14569                                             pol_cfg->pkbits_burst,
  14570                                             flags, refresh_bitsize,
  14571                                             bucket_max_bitsize,
  14572                                             &e_refresh_rate, &e_bucketsize,
  14573                                             &granularity);
  14574     }
  14575     BCM_IF_ERROR_RETURN(rv);
  14576      /* Calculate initial backet count.
  14577      * bucket size << (bit count diff - 1(sign) -1 (overflow))  - 1
  14578      */
  14579     bucket_cnt_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14580                                               EXCESS_BUCKETCOUNTf);
  14581     if (e_bucketsize == 0 && e_refresh_rate == 0) {
  14582         /* Excess should always be out of profile */
  14583         e_bucketcount = (1 << bucket_cnt_bitsize) - 1;
  14584     } else if (e_bucketsize) {
  14585         e_bucketcount =
  14586             (e_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2))  - 1;
  14587         e_bucketcount &= ((1 << bucket_cnt_bitsize) - 1);
  14588     } else {
  14589         e_bucketcount = 0;
  14590     }
  14591     /* Set HW register */
  14592 
  14593     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) {
  14594         soc_SVM_METER_TABLEm_field_set(unit, &data, METER_GRANf, &granularity);
  14595     }
  14596 
  14597     rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec,
  14598                                       pol_cfg->max_pkbits_sec, &e_refreshmax);
  14599     BCM_IF_ERROR_RETURN(rv);
  14600 
  14601     if (pol_cfg->mode == bcmPolicerModeCoupledCascade) {
  14602         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf,
  14603                                                              &e_refreshmax);
  14604         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf,
  14605                                                           &e_bucketcount);
  14606         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf,
  14607                                                              &e_refresh_rate);
  14608         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf,
  14609                                                                  &e_bucketsize);
  14610     } else {
  14611         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHMAXf,
  14612                                                              &e_refreshmax);
  14613         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETCOUNTf,
  14614                                                           &e_bucketcount);
  14615         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHCOUNTf,
  14616                                                              &e_refresh_rate);
  14617         soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETSIZEf,
  14618                                                                  &e_bucketsize);
  14619     }
  14620     /* PKT/BYTE - by default BYTE counter */
  14621     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) {
  14622         if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  14623             pkt_bytes = 1;
  14624             soc_SVM_METER_TABLEm_field_set(unit, &data, PKT_BYTESf, &pkt_bytes);
  14625         }
  14626     }
  14627     /* MIN/MAX/MIN_MAX */
  14628     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) {
  14629         soc_SVM_METER_TABLEm_field_set(unit, &data, METER_SHARING_MODEf,
  14630                                                  &pol_cfg->sharing_mode);
  14631     }
  14632     if (pol_cfg->flags & BCM_POLICER_COLOR_BLIND) {
  14633         mode_modifier = 0; /* color blind */
  14634     } else {
  14635         mode_modifier = 1; /* color aware */
  14636     }
  14637 
  14638     switch (pol_cfg->mode) {
  14639         case bcmPolicerModeGreen:
  14640             mode = GLOBAL_METER_MODE_DEFAULT;
  14641             mode_modifier = 0;
  14642             break;
  14643 
  14644         case bcmPolicerModePassThrough:
  14645             mode = GLOBAL_METER_MODE_DEFAULT;
  14646             mode_modifier = 1;
  14647             break;
  14648 
  14649         case bcmPolicerModeSrTcm:
  14650             mode = GLOBAL_METER_MODE_SR_TCM;
  14651             break;
  14652 
  14653         case bcmPolicerModeSrTcmModified:
  14654             mode = GLOBAL_METER_MODE_SR_TCM_MODIFIED;
  14655             break;
  14656 
  14657         case bcmPolicerModeTrTcm:
  14658             mode = GLOBAL_METER_MODE_TR_TCM;
  14659             break;
  14660 
  14661         case bcmPolicerModeTrTcmDs:
  14662             mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED;
  14663             break;
  14664 
  14665         case bcmPolicerModeCoupledTrTcmDs:
  14666             mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED;
  14667             coupling = 1;
  14668             break;
  14669 
  14670         case bcmPolicerModeCascade:
  14671             mode = GLOBAL_METER_MODE_CASCADE;
  14672             coupling = 0;
  14673             break;
  14674 
  14675         case bcmPolicerModeCoupledCascade:
  14676             mode = GLOBAL_METER_MODE_CASCADE;
  14677             coupling = 1;
  14678             break;
  14679 
  14680         default:
  14681            LOG_DEBUG(BSL_LS_BCM_POLICER,
  14682                      (BSL_META_U(unit,
  14683                                  "Invalid policer mode \n")));
  14684            return BCM_E_PARAM;
  14685            break;
  14686      }
  14687     /* SRTCM TrTcm Modified SrTcm, Modified TrTcm, cascade, default */
  14688     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  14689         soc_SVM_METER_TABLEm_field_set(unit, &data, METER_MODEf, &mode);
  14690     }
  14691     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) {
  14692         soc_SVM_METER_TABLEm_field_set(unit, &data, METER_MODIFIERf,
  14693                                                         &mode_modifier);
  14694     }
  14695     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) {
  14696         soc_SVM_METER_TABLEm_field_set(unit, &data, COUPLING_FLAGf, &coupling);
  14697     }
  14698     /* Read START/END of the chain info and set table accordingly */
  14699     if (mode == GLOBAL_METER_MODE_CASCADE) {
  14700         if (pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_START) {
  14701             start_of_chain = 1;
  14702         }
  14703         if (pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) {
  14704             end_of_chain = 1;
  14705         }
  14706     }
  14707     soc_SVM_METER_TABLEm_field_set(unit, &data,
  14708                                             START_OF_CHAINf, &start_of_chain);
  14709     soc_SVM_METER_TABLEm_field_set(unit, &data, END_OF_CHAINf, &end_of_chain);
  14710 
  14711     /* write to hW */
  14712     rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &data);
  14713     BCM_IF_ERROR_RETURN(rv);
  14714     /* increment action usage reference count */
  14715     if (incr_reqd) {
  14716         global_meter_action_bookkeep[unit][policy_index].reference_count++;
  14717     }
  14718     /* in case of cascade with coupling we need to configure the second set
  14719        as well */
  14720     if ((coupling == 1) && (mode == GLOBAL_METER_MODE_CASCADE)) {
  14721         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf,
  14722                                                              &c_refreshmax);
  14723         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf,
  14724                                                           &c_bucketcount);
  14725         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf,
  14726                                                              &c_refresh_rate);
  14727         soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf,
  14728                                                                   &c_bucketsize);
  14729         rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit,
  14730                                       policer_id, policer_control, &index);
  14731         /* write to hW */
  14732         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  14733                                                              index, &data);
  14734         if (!BCM_SUCCESS(rv)) {
  14735             LOG_DEBUG(BSL_LS_BCM_POLICER,
  14736                       (BSL_META_U(unit,
  14737                                   "Unable to configure the cascaded pair of "
  14738                                   "policers \n")));
  14739             return rv;
  14740         }
  14741     }
  14742     if (pol_cfg->flags & BCM_POLICER_MIXED_MICRO_MACRO) {
  14743         rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  14744                                          index, &macro_flow_entry);
  14745         if (!(BCM_SUCCESS(rv))) {
  14746             LOG_DEBUG(BSL_LS_BCM_COMMON,
  14747                       (BSL_META_U(unit,
  14748                                   "Unable to access macro flow table at the index provided\n")));
  14749             return rv;
  14750         }
  14751 
  14752         soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *) &macro_flow_entry,
  14753                            MACROFLOW_INDEXf, (uint32 *)&macro_flow_meter_index);
  14754         if (macro_flow_meter_index > 0) {
  14755             _bcm_esw_get_policer_id_from_index_offset(unit,
  14756                                macro_flow_meter_index, 0, &macro_meter_policer);
  14757             rv = _bcm_esw_policer_decrement_ref_count(unit,
  14758                                                       macro_meter_policer);
  14759             if (BCM_FAILURE(rv)) {
  14760                 LOG_DEBUG(BSL_LS_BCM_COMMON,
  14761                           (BSL_META_U(unit,
  14762                                       "%u : Unable to decrement ref count"),
  14763                            macro_flow_meter_index));
  14764                 return rv;
  14765             }
  14766             macro_flow_meter_index = 0; /* clear macro flow index entry */
  14767             soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, &macro_flow_entry,
  14768                            MACROFLOW_INDEXf, (uint32 *)&macro_flow_meter_index);
  14769             rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  14770                                           index, &macro_flow_entry);
  14771             if (!(BCM_SUCCESS(rv))) {
  14772                 LOG_DEBUG(BSL_LS_BCM_COMMON, \
  14773                           (BSL_META_U(unit,
  14774                                       "Unable to write to macro flow table at index \
  14775                                       provided\n")));
  14776                 return rv;
  14777             }
  14778         }
  14779     }
  14780 
  14781     return rv;
  14782 #else
  14783     return BCM_E_UNAVAIL;
  14784 #endif
  14785 }
  14786 
  14787 /*
  14788  * Function:
  14789  *      _bcm_global_meter_write_config_mef_10dot3_to_hw
  14790  * Purpose:
  14791  *      Write policer configuraton to meter table.
  14792  * Parameters:
  14793  *     unit                  - (IN) unit number
  14794  *     pol_cfg               - (IN) policer configuration
  14795  *     policer_id            - (IN) policer id
  14796  *     policer_control       - (IN) Policer control info
  14797  * Returns:
  14798  *     BCM_E_XXX
  14799  */
  14800 int
  14801 _bcm_global_meter_write_config_mef_10dot3_to_hw (int unit,
  14802                                                  bcm_policer_config_t *pol_cfg,
  14803                                                  bcm_policer_t policer_id,
  14804                               _global_meter_policer_control_t *policer_control)
  14805 {
  14806 #if defined(BCM_APACHE_SUPPORT)
  14807     int       rv = BCM_E_NONE;
  14808     uint32    flags=0;
  14809     uint32    c_bucketsize = 0, e_bucketsize = 0;  /* Bucket size.       */
  14810     uint32    c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */
  14811     uint32    granularity = 0;     /* Policer granularity.     */
  14812     uint32    refresh_bitsize;     /* Number of bits for the
  14813                                       refresh rate field.      */
  14814     uint32    bucket_max_bitsize;  /* Number of bits for the
  14815                                       bucket max field.        */
  14816     uint32    mode = 0, mode_modifier = 0;
  14817     uint32    coupling = 0, policy_index = 0;
  14818     uint32    c_refreshmax = 0, e_refreshmax = 0;
  14819     int       index = 0, pool = 0, pair_index = 0;
  14820     uint32    current_action_id = 0;
  14821     uint32    pkt_bytes = 0;
  14822     uint32    nc_pool_valid = 0, nc_pool = 0, ne_pool_valid = 0, ne_pool = 0;
  14823     uint32    c_e = 0, pair_exc = 0, pair_exc_valid = 0;
  14824     bcm_policer_t                     macro_meter_policer = 0;
  14825     int                               macro_flow_meter_index = 0;
  14826     svm_macroflow_index_table_entry_t macro_flow_entry;
  14827     svm_meter_table_entry_t           svm_entry;
  14828     int incr_reqd = 0;
  14829 
  14830     pool = _bcm_global_meter_get_pool_from_policerId(unit, policer_id);
  14831     /* read HW register */
  14832     _bcm_esw_get_policer_table_index(unit, policer_id, &index);
  14833     rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &svm_entry);
  14834     BCM_IF_ERROR_RETURN(rv);
  14835 
  14836     policy_index = pol_cfg->action_id;
  14837     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) {
  14838         soc_SVM_METER_TABLEm_field_get(unit,
  14839               &svm_entry, POLICY_TABLE_INDEXf, &current_action_id);
  14840         if( policy_index != current_action_id ) {
  14841             if(current_action_id != 0) {
  14842                 /* detach the existing action and
  14843                  * decrement reference count
  14844                  */
  14845                 _bcm_esw_policer_action_detach(unit, policer_id,
  14846                                                current_action_id);
  14847             }
  14848             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  14849                                            POLICY_TABLE_INDEXf, &policy_index);
  14850             if(policy_index != 0) {
  14851                 incr_reqd = 1;
  14852             }
  14853         }
  14854     }
  14855 
  14856     flags = _BCM_XGS_METER_FLAG_GRANULARITY |
  14857                                  _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
  14858 
  14859     if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  14860         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
  14861     } else {
  14862         flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE;
  14863     }
  14864 
  14865     refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14866                                            COMMITTED_REFRESHCOUNTf);
  14867     bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14868                                               COMMITTED_BUCKETSIZEf);
  14869 
  14870     if (pol_cfg->mode == bcmPolicerModeTrTcm) {
  14871         /* SW-WAR: In this mode CIR and PIR need swapping */
  14872         uint32 tmp;
  14873         tmp = pol_cfg->pkbits_sec;
  14874         pol_cfg->pkbits_sec = pol_cfg->ckbits_sec;
  14875         pol_cfg->ckbits_sec = tmp;
  14876     }
  14877 
  14878     /* Calculate policer bucket size/refresh_rate/granularity. */
  14879     if (pol_cfg->pkbits_sec > pol_cfg->ckbits_sec) {
  14880         rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec,
  14881                                             pol_cfg->pkbits_burst,
  14882                                             flags, refresh_bitsize,
  14883                                             bucket_max_bitsize,
  14884                                             &c_refresh_rate, &c_bucketsize,
  14885                                             &granularity);
  14886         BCM_IF_ERROR_RETURN(rv);
  14887 
  14888         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
  14889                                              pol_cfg->ckbits_sec,
  14890                                              pol_cfg->ckbits_burst,
  14891                                              flags, refresh_bitsize,
  14892                                              bucket_max_bitsize,
  14893                                              &c_refresh_rate, &c_bucketsize,
  14894                                              &granularity);
  14895         BCM_IF_ERROR_RETURN(rv);
  14896     }  else {
  14897          rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->ckbits_sec,
  14898                                                 pol_cfg->ckbits_burst,
  14899                                                 flags, refresh_bitsize,
  14900                                                 bucket_max_bitsize,
  14901                                                 &c_refresh_rate, &c_bucketsize,
  14902                                                 &granularity);
  14903         BCM_IF_ERROR_RETURN(rv);
  14904     }
  14905 
  14906     rv =_bcm_global_meter_refresh_max_get(pol_cfg->ckbits_sec,
  14907                                           pol_cfg->max_ckbits_sec,
  14908                                           &c_refreshmax);
  14909     BCM_IF_ERROR_RETURN(rv);
  14910 
  14911 
  14912     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_REFRESHMAXf,
  14913                                    &c_refreshmax);
  14914     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_REFRESHCOUNTf,
  14915                                    &c_refresh_rate);
  14916     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_BUCKETSIZEf,
  14917                                    &c_bucketsize);
  14918 
  14919 
  14920     refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14921                                            EXCESS_REFRESHCOUNTf);
  14922 
  14923     bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  14924                                               EXCESS_BUCKETSIZEf);
  14925 
  14926     if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) {
  14927         rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec,
  14928                                             pol_cfg->pkbits_burst,
  14929                                             flags, refresh_bitsize,
  14930                                             bucket_max_bitsize,
  14931                                             &e_refresh_rate, &e_bucketsize,
  14932                                             &granularity);
  14933 
  14934     } else {
  14935         rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
  14936                                             pol_cfg->pkbits_sec,
  14937                                             pol_cfg->pkbits_burst,
  14938                                             flags, refresh_bitsize,
  14939                                             bucket_max_bitsize,
  14940                                             &e_refresh_rate, &e_bucketsize,
  14941                                             &granularity);
  14942     }
  14943     BCM_IF_ERROR_RETURN(rv);
  14944 
  14945     /* Set HW register */
  14946     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) {
  14947         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_GRANf, &granularity);
  14948     }
  14949 
  14950     rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec,
  14951                                            pol_cfg->max_pkbits_sec,
  14952                                            &e_refreshmax);
  14953     BCM_IF_ERROR_RETURN(rv);
  14954 
  14955     if ((policer_control->grp_mode == \
  14956          bcmPolicerGroupModeIntPriCascadeWithCoupling) ||
  14957         (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) {
  14958         
  14959     } else { /* non-GCF mode */
  14960         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHMAXf,
  14961                                        &e_refreshmax);
  14962         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHCOUNTf,
  14963                                        &e_refresh_rate);
  14964         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_BUCKETSIZEf,
  14965                                        &e_bucketsize);
  14966     }
  14967 
  14968     /* PKT/BYTE - by default BYTE counter */
  14969     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) {
  14970         if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  14971             pkt_bytes = 1;
  14972             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, PKT_BYTESf, &pkt_bytes);
  14973         }
  14974     }
  14975     /* MIN/MAX/MIN_MAX */
  14976     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) {
  14977         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_SHARING_MODEf,
  14978                                                  &pol_cfg->sharing_mode);
  14979     }
  14980     if (pol_cfg->flags & BCM_POLICER_COLOR_BLIND) {
  14981         mode_modifier = 0; /* color blind */
  14982     } else {
  14983         mode_modifier = 1; /* color aware */
  14984     }
  14985 
  14986     switch (pol_cfg->mode) {
  14987         case bcmPolicerModeGreen:
  14988             mode = GLOBAL_METER_MODE_DEFAULT;
  14989             mode_modifier = 0;
  14990             break;
  14991 
  14992         case bcmPolicerModePassThrough:
  14993             mode = GLOBAL_METER_MODE_DEFAULT;
  14994             mode_modifier = 1;
  14995             break;
  14996 
  14997         case bcmPolicerModeSrTcm:
  14998             mode = GLOBAL_METER_MODE_SR_TCM;
  14999             break;
  15000 
  15001         case bcmPolicerModeSrTcmModified:
  15002             /* This mode is not supported in APACHE */
  15003             return BCM_E_PARAM;
  15004 
  15005         case bcmPolicerModeTrTcm:
  15006             mode = GLOBAL_METER_MODE_TR_TCM;
  15007             break;
  15008 
  15009         case bcmPolicerModeTrTcmDs:
  15010             mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED;
  15011             break;
  15012 
  15013         case bcmPolicerModeCoupledTrTcmDs:
  15014             mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED;
  15015             coupling = 1;
  15016             break;
  15017 
  15018         case bcmPolicerModeCascade:
  15019             mode = GLOBAL_METER_MODE_CASCADE;
  15020             /* If policer is part of non-GCF chain, adjust overflow params */
  15021             if ((policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade)
  15022                 || (policer_control->grp_mode == bcmPolicerGroupModeCascade)
  15023                 || (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) {
  15024                 /* Check if next committed pool is supplied */
  15025                 if (pol_cfg->ncoflow_policer_id != 0) {
  15026                     nc_pool = _bcm_global_meter_get_pool_from_policerId(unit,
  15027                                                    pol_cfg->ncoflow_policer_id);
  15028                 } else {
  15029                     nc_pool =  pool + 1;
  15030                 }
  15031 
  15032                 /* Check if next excess pool is supplied */
  15033                 if (pol_cfg->npoflow_policer_id != 0) {
  15034                     ne_pool = _bcm_global_meter_get_pool_from_policerId(unit,
  15035                                                   pol_cfg->npoflow_policer_id);
  15036                 } else {
  15037                     ne_pool = pool + 1;
  15038                 }
  15039 
  15040                 if (ne_pool < nc_pool) {
  15041                     /* Excess pool is high priority than commit pool
  15042                        Shouldn't happen */
  15043                     return BCM_E_PARAM;
  15044                 }
  15045 
  15046                 if ((pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) ||
  15047                     ((SOC_INFO(unit).global_meter_pools -1 ) == pool)) {
  15048                     /* Last policer in chain, make next committed and
  15049                        excess pools invalid */
  15050                     nc_pool_valid = nc_pool = 0;
  15051                     ne_pool_valid = ne_pool = 0;
  15052                     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15053                                                    NXT_COMMITTED_BUCKET_VALIDf,
  15054                                                    &nc_pool_valid);
  15055                     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15056                                                    NXT_EXCESS_BUCKET_VALIDf,
  15057                                                    &ne_pool_valid);
  15058                 }
  15059 
  15060                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15061                                                NXT_COMMITTED_BUCKETf,
  15062                                                &nc_pool);
  15063                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15064                                                NXT_EXCESS_BUCKETf,
  15065                                                &ne_pool);
  15066             } /* group mode check */
  15067             break;
  15068 
  15069         case bcmPolicerModeCoupledCascade:
  15070             mode = GLOBAL_METER_MODE_CASCADE;
  15071             /* If policer is part of non-GCF chain, adjust overflow params */
  15072             if ((policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade)
  15073                 || (policer_control->grp_mode == bcmPolicerGroupModeCascade)
  15074                 || (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) {
  15075                 /* Enable COMMITEED_EXCESS in HW */
  15076                 c_e = 1;
  15077                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15078                                                COMMITTED_EXCESSf, &c_e);
  15079                 nc_pool_valid = 1; /* Already in HW during group config */
  15080                 nc_pool = pool;    /* Implicit requirement */
  15081                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15082                                                NXT_COMMITTED_BUCKETf,
  15083                                                &nc_pool);
  15084 
  15085                 /* Check if next excess pool is supplied */
  15086                 if (pol_cfg->npoflow_policer_id != 0) {
  15087                     ne_pool = _bcm_global_meter_get_pool_from_policerId(unit,
  15088                                                   pol_cfg->npoflow_policer_id);
  15089                 } else {
  15090                     ne_pool = pool + 1;
  15091                 }
  15092 
  15093                 if ((pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) ||
  15094                     ((SOC_INFO(unit).global_meter_pools -1 ) == pool)) {
  15095                     /* Last policer is chain, disable excess pool validity */
  15096                     ne_pool = 0;
  15097                     ne_pool_valid = 0;
  15098                     soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15099                                                    NXT_EXCESS_BUCKET_VALIDf,
  15100                                                    &ne_pool_valid);
  15101                 }
  15102                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15103                                                NXT_EXCESS_BUCKETf,
  15104                                                &ne_pool);
  15105             } /* End - "if" group mode check */
  15106             break;
  15107 
  15108         default:
  15109            LOG_DEBUG(BSL_LS_BCM_POLICER,
  15110                      (BSL_META_U(unit,
  15111                                  "Invalid policer mode \n")));
  15112            return BCM_E_PARAM;
  15113            break;
  15114      }
  15115     /* SRTCM TrTcm Modified SrTcm, Modified TrTcm, cascade, default */
  15116     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  15117         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODEf, &mode);
  15118     }
  15119     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) {
  15120         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODIFIERf,
  15121                                                         &mode_modifier);
  15122     }
  15123     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) {
  15124         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COUPLING_FLAGf, &coupling);
  15125     }
  15126 
  15127     if ((policer_control->grp_mode != \
  15128          bcmPolicerGroupModeIntPriCascadeWithCoupling) &&
  15129         (policer_control->grp_mode != bcmPolicerGroupModeCascadeWithCoupling)) {
  15130         /* Set METER_PAIR_EXCESS for all other modes here */
  15131         pair_exc_valid = 1;
  15132         pair_exc = pool;
  15133         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15134                                        METER_PAIR_EXCESS_BUCKETf,
  15135                                        &pair_exc);
  15136         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  15137                                        METER_PAIR_EXCESS_BUCKET_VALIDf,
  15138                                        &pair_exc_valid);
  15139     }
  15140 
  15141     /* write to hW */
  15142     rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &svm_entry);
  15143     BCM_IF_ERROR_RETURN(rv);
  15144     /* increment action usage reference count */
  15145     if (incr_reqd) {
  15146         global_meter_action_bookkeep[unit][policy_index].reference_count++;
  15147     }
  15148     /* in case of cascade with coupling we need to configure the second set
  15149        as well - GCF Mode */
  15150     if ((policer_control->grp_mode == \
  15151          bcmPolicerGroupModeIntPriCascadeWithCoupling) ||
  15152         (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) {
  15153         rv = _bcm_global_meter_get_coupled_cascade_policer_index(unit,
  15154                                       policer_id, policer_control, &pair_index);
  15155         BCM_IF_ERROR_RETURN(rv);
  15156 
  15157         rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  15158                           pair_index, &svm_entry);
  15159         BCM_IF_ERROR_RETURN(rv);
  15160 
  15161         policy_index = pol_cfg->action_id;
  15162         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) {
  15163             soc_SVM_METER_TABLEm_field_get(unit,
  15164               &svm_entry, POLICY_TABLE_INDEXf, &current_action_id);
  15165             /* detach the existing action and decrement reference count */
  15166             if (current_action_id) {
  15167                 _bcm_esw_policer_action_detach(unit, policer_id,
  15168                                                current_action_id);
  15169             }
  15170             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, POLICY_TABLE_INDEXf,
  15171                                            &policy_index);
  15172         }
  15173 
  15174         flags = _BCM_XGS_METER_FLAG_GRANULARITY |
  15175                                  _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER;
  15176 
  15177         refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  15178                                                EXCESS_REFRESHCOUNTf);
  15179 
  15180         bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm,
  15181                                                   EXCESS_BUCKETSIZEf);
  15182 
  15183         if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) {
  15184             rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec,
  15185                                                    pol_cfg->pkbits_burst,
  15186                                                    flags, refresh_bitsize,
  15187                                                    bucket_max_bitsize,
  15188                                                    &e_refresh_rate,
  15189                                                    &e_bucketsize,
  15190                                                    &granularity);
  15191 
  15192         } else {
  15193             rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity(
  15194                 pol_cfg->pkbits_sec,
  15195                 pol_cfg->pkbits_burst,
  15196                 flags, refresh_bitsize,
  15197                 bucket_max_bitsize,
  15198                 &e_refresh_rate, &e_bucketsize,
  15199                 &granularity);
  15200         }
  15201         BCM_IF_ERROR_RETURN(rv);
  15202 
  15203         /* Set HW register */
  15204         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) {
  15205             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_GRANf, &granularity);
  15206         }
  15207 
  15208         rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec,
  15209                                                pol_cfg->max_pkbits_sec,
  15210                                                &e_refreshmax);
  15211         BCM_IF_ERROR_RETURN(rv);
  15212 
  15213         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHMAXf,
  15214                                        &e_refreshmax);
  15215         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHCOUNTf,
  15216                                        &e_refresh_rate);
  15217         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_BUCKETSIZEf,
  15218                                        &e_bucketsize);
  15219         /* PKT/BYTE - by default BYTE counter */
  15220         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) {
  15221             if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) {
  15222                 pkt_bytes = 1;
  15223                 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, PKT_BYTESf, &pkt_bytes);
  15224             }
  15225         }
  15226 
  15227         mode = GLOBAL_METER_MODE_CASCADE;
  15228 
  15229         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  15230             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODEf, &mode);
  15231         }
  15232         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) {
  15233             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODIFIERf,
  15234                                            &mode_modifier);
  15235         }
  15236 
  15237         /* write to hW */
  15238         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  15239                            pair_index, &svm_entry);
  15240         if (!BCM_SUCCESS(rv)) {
  15241             LOG_DEBUG(BSL_LS_BCM_POLICER,
  15242                       (BSL_META_U(unit,
  15243                                   "Unable to configure the cascaded pair of "
  15244                                   "policers \n")));
  15245             return rv;
  15246         }
  15247     } /* end if for GCF mode check */
  15248 
  15249     if (pol_cfg->flags & BCM_POLICER_MIXED_MICRO_MACRO) {
  15250         rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  15251                                              index, &macro_flow_entry);
  15252         if (!(BCM_SUCCESS(rv))) {
  15253             LOG_DEBUG(BSL_LS_BCM_COMMON,
  15254                       (BSL_META_U(unit,
  15255                                   "Unable to access macro flow table at the index provided\n")));
  15256             return rv;
  15257         }
  15258 
  15259         soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *) &macro_flow_entry,
  15260                            MACROFLOW_INDEXf, (uint32 *)&macro_flow_meter_index);
  15261         if (macro_flow_meter_index > 0) {
  15262             _bcm_esw_get_policer_id_from_index_offset(unit,
  15263                                macro_flow_meter_index, 0, &macro_meter_policer);
  15264             rv = _bcm_esw_policer_decrement_ref_count(unit,
  15265                                                       macro_meter_policer);
  15266             if (BCM_FAILURE(rv)) {
  15267                 LOG_DEBUG(BSL_LS_BCM_COMMON,
  15268                           (BSL_META_U(unit,
  15269                                       "%u : Unable to decrement ref count"),
  15270                            macro_flow_meter_index));
  15271                 return rv;
  15272             }
  15273             macro_flow_meter_index = 0; /* clear macro flow index entry */
  15274             soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, &macro_flow_entry,
  15275                            MACROFLOW_INDEXf, (uint32 *)&macro_flow_meter_index);
  15276             rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  15277                                           index, &macro_flow_entry);
  15278             if (!(BCM_SUCCESS(rv))) {
  15279                 LOG_DEBUG(BSL_LS_BCM_COMMON, \
  15280                           (BSL_META_U(unit,
  15281                                       "Unable to write to macro flow table at index \
  15282                                       provided\n")));
  15283                 return rv;
  15284             }
  15285         }
  15286     }
  15287 
  15288     return rv;
  15289 #else
  15290     return BCM_E_UNAVAIL;
  15291 #endif
  15292 }
  15293 /*
  15294  * Function:
  15295  *      _bcm_global_meter_get_coupled_cascade_policer_index
  15296  * Purpose:
  15297  *      In case of cascade with coupling get the index of the coupled
  15298  *      pair
  15299  * Parameters:
  15300  *     unit                  - (IN) unit number
  15301  *     policer_id            - (IN) policer id
  15302  *     policer_control       - (IN) Policer control info
  15303  *     new_index             - (OUT) Policer index
  15304  * Returns:
  15305  *     BCM_E_XXX
  15306  */
  15307 int _bcm_global_meter_get_coupled_cascade_policer_index(int unit,
  15308                                           bcm_policer_t policer_id,
  15309                   _global_meter_policer_control_t *policer_control,
  15310                    int *new_index)
  15311 {
  15312 
  15313     int rv = BCM_E_NONE;
  15314     int offset1 = 0, pool1 = 0, pool2 = 0;
  15315     int new_offset = 0;
  15316     int size_pool = 0, num_pools = 0;
  15317     int index = 0, index_max = 0;
  15318     int offset_mask = 0;
  15319     int pool_mask = 0, pool_offset = 0;
  15320     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  15321     num_pools =  SOC_INFO(unit).global_meter_pools;
  15322     offset_mask = size_pool - 1;
  15323     pool_offset = _shr_popcount(offset_mask);
  15324     pool_mask = (num_pools - 1) << pool_offset;
  15325 
  15326     offset1 = policer_control->pid & offset_mask;
  15327 
  15328     pool1 = (policer_control->pid & pool_mask) >> pool_offset;
  15329     pool2 = (policer_id & pool_mask) >> pool_offset;
  15330 
  15331     if (!soc_feature(unit ,soc_feature_global_meter_mef_10dot3)) {
  15332         index_max = policer_control->no_of_policers/2;
  15333         if (pool1 == pool2) {
  15334             new_offset = policer_control->offset[index_max];
  15335             *new_index = offset1 + (new_offset * size_pool);
  15336             return rv;
  15337         }
  15338         for (index = 1; index < index_max; index++) {
  15339             if ((pool1 + policer_control->offset[index]) == pool2) {
  15340                 if ((index_max + index) < MAX_POLICER_OFFSETS) {
  15341                 new_offset = policer_control->offset[index_max + index];
  15342                 *new_index = offset1 + (new_offset * size_pool);
  15343                 } else {
  15344                     return BCM_E_RESOURCE;
  15345                 }
  15346             }
  15347         }
  15348     } else { /* MEF 10.3 onward device */
  15349         new_offset = pool2 + 4;
  15350         /* In GCF mode, SDK assumes its always chain of 4 policers.
  15351          * Not much choice left but to carry on this legacy assumption
  15352          * as no GCF mode functionality change is expected in MEF10.3
  15353          */
  15354         *new_index = offset1 + (new_offset * size_pool);
  15355     }
  15356 
  15357     return rv;
  15358 }
  15359 
  15360 /*
  15361  * Function:
  15362  *      _bcm_global_meter_base_policer_get
  15363  * Purpose:
  15364  *      Get the internal data structure for a given polier id if
  15365  *      it is base policer.
  15366  * Parameters:
  15367  *     unit                  - (IN) unit number
  15368  *     pid                   - (IN) policer id
  15369  *     policer_p             - (OUT) Policer control info
  15370  * Returns:
  15371  *     BCM_E_XXX
  15372  */
  15373 int _bcm_global_meter_base_policer_get(int unit, bcm_policer_t pid,
  15374                          _global_meter_policer_control_t **policer_p)
  15375 {
  15376     _global_meter_policer_control_t *global_meter_pl = NULL;
  15377     uint32 hash_index;      /* Entry hash.  */
  15378     /* Input parameters check. */
  15379     if (NULL == policer_p) {
  15380         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15381                   (BSL_META_U(unit,
  15382                               "Policer control is null \n")));
  15383         return (BCM_E_PARAM);
  15384     }
  15385     hash_index = pid & _GLOBAL_METER_HASH_MASK;
  15386     global_meter_pl  =  global_meter_policer_bookkeep[unit][hash_index];
  15387     while (NULL != global_meter_pl) {
  15388         /* Match entry id. */
  15389         if (global_meter_pl->pid == pid) {
  15390             *policer_p = global_meter_pl;
  15391             return (BCM_E_NONE);
  15392         }
  15393         global_meter_pl = global_meter_pl->next;
  15394     }
  15395     /* Policer with pid == pid was not found. */
  15396     return (BCM_E_NOT_FOUND);
  15397 }
  15398 
  15399 /*
  15400  * Function:
  15401  *      _bcm_global_meter_policer_get
  15402  * Purpose:
  15403  *      Get the internal control data structure for a given policer id.
  15404  * Parameters:
  15405  *     unit                  - (IN) unit number
  15406  *     pid                   - (IN) policer id
  15407  *     policer_p             - (OUT) Policer control info
  15408  * Returns:
  15409  *     BCM_E_XXX
  15410  */
  15411 
  15412 int _bcm_global_meter_policer_get(int unit, bcm_policer_t pid,
  15413                          _global_meter_policer_control_t **policer_p)
  15414 {
  15415     _global_meter_policer_control_t *global_meter_pl = NULL;
  15416     uint32 hash_index;      /* Entry hash */
  15417     int offset1 = 0, offset2 = 0;
  15418     int pool1 = 0, pool2 = 0;
  15419     uint32 index = 0, index_max = 0;
  15420     int rv = BCM_E_NONE;
  15421     int hash_max = 0;
  15422     int offset_mask = 0;
  15423     int size_pool = 0, num_pools = 0;
  15424     int pool_mask = 0, pool_offset = 0;
  15425     /* Input parameters check. */
  15426     if (NULL == policer_p) {
  15427         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15428                   (BSL_META_U(unit,
  15429                               "Policer control is null \n")));
  15430         return (BCM_E_PARAM);
  15431     }
  15432     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  15433     num_pools =  SOC_INFO(unit).global_meter_pools;
  15434     offset_mask = size_pool - 1;
  15435     pool_offset = _shr_popcount(offset_mask);
  15436     pool_mask = (num_pools - 1) << pool_offset;
  15437 
  15438     rv = _bcm_global_meter_base_policer_get(unit, pid, policer_p);
  15439     if (BCM_E_NOT_FOUND == rv) {
  15440         hash_max = pid & _GLOBAL_METER_HASH_MASK;
  15441         for (hash_index=0; hash_index <= hash_max; hash_index++) {
  15442             global_meter_pl  =
  15443                       global_meter_policer_bookkeep[unit][hash_index];
  15444             while (NULL != global_meter_pl) {
  15445                 offset1 = global_meter_pl->pid & offset_mask;
  15446                 offset2 = pid & offset_mask;
  15447 
  15448                 pool1 = (global_meter_pl->pid & pool_mask) >> pool_offset;
  15449                 pool2 = (pid & pool_mask) >> pool_offset;
  15450 
  15451                 /* in case of cascade policers, only pool number is diferent */
  15452                 if (global_meter_pl->direction ==
  15453                                                GLOBAL_METER_ALLOC_HORIZONTAL) {
  15454                     if (offset1 == offset2) {
  15455                         index_max = global_meter_pl->no_of_policers;
  15456                         for (index = 1; index < index_max; index++) {
  15457                             if ((pool1 + global_meter_pl->offset[index]) ==
  15458                                                                      pool2) {
  15459                                 *policer_p = global_meter_pl;
  15460                                  return (BCM_E_NONE);
  15461                             }
  15462                         }
  15463                     }
  15464                 } else {
  15465                     if (pool1 == pool2) {
  15466                         if (offset2 > offset1 && offset2 <
  15467                                 (offset1 + global_meter_pl->no_of_policers)) {
  15468                             *policer_p = global_meter_pl;
  15469                              return (BCM_E_NONE);
  15470                         }
  15471                     }
  15472 
  15473                 }
  15474                 global_meter_pl = global_meter_pl->next;
  15475             }
  15476         }
  15477         /* Policer with pid == pid was not found. */
  15478         return (BCM_E_NOT_FOUND);
  15479     } else {
  15480         return rv;
  15481     }
  15482     return BCM_E_NONE;
  15483 }
  15484 
  15485 /*
  15486  * Function:
  15487  *      _bcm_esw_global_meter_policer_get
  15488  * Purpose:
  15489  *      Get the configuration info for a given policer id
  15490  * Parameters:
  15491  *     unit                  - (IN) unit number
  15492  *     pid                   - (IN) policer id
  15493  *     policer_p             - (OUT) Policer control info
  15494  * Returns:
  15495  *     BCM_E_XXX
  15496  */
  15497 int _bcm_esw_global_meter_policer_get(int unit, bcm_policer_t policer_id,
  15498                    bcm_policer_config_t *pol_cfg)
  15499 {
  15500     int rv = BCM_E_NONE;
  15501     _global_meter_policer_control_t *policer_control = NULL;
  15502 
  15503 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  15504     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  15505         return bcmi_esw_global_meter_policer_get(unit,
  15506                 policer_id, pol_cfg);
  15507     }
  15508 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  15509 
  15510     /* validate policer id */
  15511     rv = _bcm_esw_policer_validate(unit, &policer_id);
  15512     if (BCM_FAILURE(rv)) {
  15513         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15514                   (BSL_META_U(unit,
  15515                               "Invalid policer id %x  \n"),
  15516                    policer_id));
  15517         return (rv);
  15518     }
  15519     GLOBAL_METER_LOCK(unit);
  15520    /* we come here from bcm_esw_policer_get,
  15521       only when policer id indicates : global meter */
  15522     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  15523     if (BCM_SUCCESS(rv)) {
  15524         rv = (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) ?
  15525             _bcm_global_meter_read_config_from_hw_mef_10dot3(unit, policer_id,
  15526                                                              pol_cfg) :
  15527             _bcm_global_meter_read_config_from_hw(unit, policer_id, pol_cfg);
  15528 
  15529         if (BCM_FAILURE(rv)) {
  15530             LOG_DEBUG(BSL_LS_BCM_POLICER,
  15531                       (BSL_META_U(unit,
  15532                                   "Unable to read policer config from hw %x\n"),
  15533                        policer_id));
  15534             GLOBAL_METER_UNLOCK(unit);
  15535             return (rv);
  15536         }
  15537     }
  15538     GLOBAL_METER_UNLOCK(unit);
  15539     return rv;
  15540 }
  15541 
  15542 /*
  15543  * Function:
  15544  *      _bcm_global_meter_min_burst_size_set
  15545  * Purpose:
  15546  *     If the passed burst size is less than the minimum required, set it to
  15547  *     minimum required value.
  15548  * Parameters:
  15549  *     unit                  - (IN) unit number
  15550  *     policer_id            - (IN) policer id
  15551  *     pol_cfg               - (IN) Policer control info
  15552  * Returns:
  15553  *     BCM_E_XXX
  15554  */
  15555 
  15556 int _bcm_global_meter_min_burst_size_set(bcm_policer_config_t *pol_cfg)
  15557 {
  15558     uint32 min_burst = 0;
  15559     /* min burst should be
  15560        max (MTU size + metering rate * refresh interval,
  15561                                     2 * metering rate * refresh interval) */
  15562 
  15563     min_burst = (MIN_BURST_MULTIPLE *
  15564                  ((pol_cfg->ckbits_sec * METER_REFRESH_INTERVAL) /
  15565                                     CONVERT_SECOND_TO_MICROSECOND));
  15566     if (min_burst > pol_cfg->ckbits_burst) {
  15567         LOG_ERROR(BSL_LS_BCM_POLICER,
  15568                   (BSL_META("Commited burst is less than the minimum required "
  15569                             "value.  \n")));
  15570         return (BCM_E_PARAM);
  15571     }
  15572     min_burst = (MIN_BURST_MULTIPLE *
  15573                  ((pol_cfg->pkbits_sec * METER_REFRESH_INTERVAL) /
  15574                                     CONVERT_SECOND_TO_MICROSECOND));
  15575     if (min_burst > pol_cfg->pkbits_burst) {
  15576         LOG_ERROR(BSL_LS_BCM_POLICER,
  15577                   (BSL_META("Peak burst is less than the minimum required "
  15578                             "value.  \n")));
  15579         return (BCM_E_PARAM);
  15580     }
  15581     return (BCM_E_NONE);
  15582 }
  15583 
  15584 /*
  15585  * Function:
  15586  *      _bcm_esw_global_meter_policer_set
  15587  * Purpose:
  15588  *     Configure the parmeters for a policer already created.
  15589  * Parameters:
  15590  *     unit                  - (IN) unit number
  15591  *     policer_id            - (IN) policer id
  15592  *     pol_cfg               - (IN) Policer control info
  15593  * Returns:
  15594  *     BCM_E_XXX
  15595  */
  15596 
  15597 int _bcm_esw_global_meter_policer_set(int unit, bcm_policer_t policer_id,
  15598                    bcm_policer_config_t *pol_cfg)
  15599 {
  15600     int rv = BCM_E_NONE;
  15601     _global_meter_policer_control_t *policer_control = NULL;
  15602 
  15603 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  15604     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  15605         return bcmi_esw_global_meter_policer_set(unit,
  15606                 policer_id, pol_cfg);
  15607     }
  15608 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  15609 
  15610     /* validate policer id */
  15611     rv = _bcm_esw_policer_validate(unit, &policer_id);
  15612     if (BCM_FAILURE(rv)) {
  15613         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15614                   (BSL_META_U(unit,
  15615                               "Invalid policer id %x  \n"),
  15616                    policer_id));
  15617         return (rv);
  15618     }
  15619     GLOBAL_METER_LOCK(unit);
  15620 
  15621    /* we come here from bcm_esw_policer_get,
  15622       only when policer id indicates : global meter */
  15623     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  15624     if (BCM_SUCCESS(rv)) {
  15625        /* Check whether the burst size is >= min required. If not, set it
  15626           to minimum required value */
  15627         rv = _bcm_global_meter_min_burst_size_set(pol_cfg);
  15628 
  15629         /* Add code to write this to HW */
  15630         if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  15631             rv =  _bcm_global_meter_write_config_mef_10dot3_to_hw(unit, pol_cfg,
  15632                                             policer_id, policer_control);
  15633         } else {
  15634             rv = _bcm_global_meter_write_config_to_hw(unit, pol_cfg,
  15635                                                   policer_id, policer_control);
  15636         }
  15637         if (BCM_FAILURE(rv)) {
  15638             LOG_DEBUG(BSL_LS_BCM_POLICER,
  15639                       (BSL_META_U(unit,
  15640                                   "Unable to write policer config to hw %x\n"),
  15641                        policer_id));
  15642             GLOBAL_METER_UNLOCK(unit);
  15643             return (rv);
  15644         }
  15645     }
  15646     GLOBAL_METER_UNLOCK(unit);
  15647     return rv;
  15648 }
  15649 
  15650 /*
  15651  * Function:
  15652  *      _bcm_esw_global_meter_policer_destroy_all
  15653  * Purpose:
  15654  *      Destroy all the policers.
  15655  * Parameters:
  15656  *     unit                  - (IN) unit number
  15657  * Returns:
  15658  *     BCM_E_XXX
  15659  */
  15660 int _bcm_esw_global_meter_policer_destroy_all(int unit)
  15661 {
  15662 
  15663     int rv = BCM_E_NONE;
  15664     int idx = 0;
  15665     _global_meter_policer_control_t *policer_control = NULL;
  15666 
  15667 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  15668     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  15669         return bcmi_esw_global_meter_policer_destroy_all(unit);
  15670     }
  15671 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  15672 
  15673     if (global_meter_status[unit].initialised == 0) {
  15674         return rv;
  15675     }
  15676     if (global_meter_mutex[unit] != NULL) {
  15677         GLOBAL_METER_LOCK(unit);
  15678     }
  15679     /* Iterate over all hash buckets. */
  15680     for (idx = 0; idx < _GLOBAL_METER_HASH_SIZE; idx++) {
  15681         policer_control = global_meter_policer_bookkeep[unit][idx];
  15682         /* Destroy entries in each bucket. */
  15683         while (NULL != policer_control) {
  15684             rv = _bcm_esw_global_meter_policer_destroy2(unit, policer_control);
  15685             if (BCM_FAILURE(rv)) {
  15686                 break;
  15687             }
  15688             policer_control = global_meter_policer_bookkeep[unit][idx];
  15689         }
  15690         if (BCM_FAILURE(rv)) {
  15691             break;
  15692         }
  15693     }
  15694     if (global_meter_mutex[unit] != NULL) {
  15695         GLOBAL_METER_UNLOCK(unit);
  15696     }
  15697     return rv;
  15698 }
  15699 
  15700 /*
  15701  * Function:
  15702  *      _bcm_esw_global_meter_policer_traverse
  15703  * Purpose:
  15704  *     Traverse through all the policers that are configured and
  15705  *     call the given call back function with policer configuration.
  15706  * Parameters:
  15707  *     unit                  - (IN) unit number
  15708  *     cb                    - (IN) Call back function
  15709  *     user_data             - (OUT) Data for callback function
  15710  * Returns:
  15711  *     BCM_E_XXX
  15712  */
  15713 int  _bcm_esw_global_meter_policer_traverse(int unit,
  15714                bcm_policer_traverse_cb cb,  void *user_data)
  15715 {
  15716     int rv = BCM_E_NONE;
  15717     int idx = 0;
  15718     bcm_policer_config_t    cfg;      /* Policer configuration.         */
  15719     _global_meter_policer_control_t *policer_control = NULL;
  15720 
  15721 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  15722     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  15723         return bcmi_esw_global_meter_policer_traverse(unit, cb, user_data);
  15724     }
  15725 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  15726 
  15727     /* Iterate over all hash buckets. */
  15728     for (idx = 0; idx < _GLOBAL_METER_HASH_SIZE; idx++) {
  15729         policer_control = global_meter_policer_bookkeep[unit][idx];
  15730         /* Destroy entries in each bucket. */
  15731         while (NULL != policer_control) {
  15732             rv = _bcm_esw_global_meter_policer_get(unit, policer_control->pid,
  15733                                                                          &cfg);
  15734             if (BCM_FAILURE(rv)) {
  15735                 break;
  15736             }
  15737             rv = (*cb)(unit, policer_control->pid, &cfg, user_data);
  15738             if (BCM_FAILURE(rv)) {
  15739                 break;
  15740             }
  15741             policer_control = policer_control->next;
  15742         }
  15743         if (BCM_FAILURE(rv)) {
  15744             break;
  15745         }
  15746     }
  15747     return rv;
  15748 }
  15749 
  15750 /*
  15751  * Function:
  15752  *      _bcm_esw_global_meter_policer_destroy
  15753  * Purpose:
  15754  *     Destroys a policer and readjusts action
  15755  *     usage reference count and policer allocation management data struture.
  15756  * Parameters:
  15757  *     unit                  - (IN) unit number
  15758  *     policer_id            - (IN) policer id
  15759  * Returns:
  15760  *     BCM_E_XXX
  15761  */
  15762 int _bcm_esw_global_meter_policer_destroy(int unit, bcm_policer_t policer_id)
  15763 {
  15764     int rv = BCM_E_NONE;
  15765     _global_meter_policer_control_t *policer_control = NULL;
  15766 
  15767 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  15768     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  15769         return bcmi_esw_global_meter_policer_destroy(unit, policer_id);
  15770     }
  15771 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  15772 
  15773     if (!soc_feature(unit, soc_feature_global_meter)) {
  15774         return BCM_E_UNAVAIL;
  15775     }
  15776     /* validate policer id */
  15777     rv = _bcm_esw_policer_validate(unit, &policer_id);
  15778     if (BCM_FAILURE(rv)) {
  15779         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  15780                     (BSL_META_U(unit,
  15781                                 "Invalid policer id %x  \n"),
  15782                      policer_id));
  15783         return (rv);
  15784     }
  15785     GLOBAL_METER_LOCK(unit);
  15786     rv = _bcm_global_meter_base_policer_get(unit,
  15787                                    policer_id, &policer_control);
  15788     if (BCM_FAILURE(rv)) {
  15789         GLOBAL_METER_UNLOCK(unit);
  15790         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  15791                     (BSL_META_U(unit,
  15792                                 "Unable to get policer control for policer id %x\n"),
  15793                      policer_id));
  15794         return (rv);
  15795     }
  15796     rv = _bcm_esw_global_meter_policer_destroy2(unit, policer_control);
  15797     GLOBAL_METER_UNLOCK(unit);
  15798     return rv;
  15799 }
  15800 
  15801 /*
  15802  * Function:
  15803  *      _bcm_esw_global_meter_policer_destroy2
  15804  * Purpose:
  15805  *     Internal function that destroys a policer and readjusts action
  15806  *     usage reference count and policer allocation management data struture.
  15807  * Parameters:
  15808  *     unit                  - (IN) unit number
  15809  *     policer_id            - (IN) policer id
  15810  *     policer_control       - (IN) policer control info
  15811  * Returns:
  15812  *     BCM_E_XXX
  15813  */
  15814 int _bcm_esw_global_meter_policer_destroy2(int unit,
  15815                _global_meter_policer_control_t *policer_control)
  15816 {
  15817     int index = 0;
  15818     uint32 pool = 0, pid = 0, numbers = 0;
  15819     int rv=BCM_E_NONE;
  15820     int offset_mode = 0;
  15821     int pool_id = 0;
  15822     int offset_mask = 0;
  15823     int size_pool = 0, num_pools = 0;
  15824     int pool_mask = 0, pool_offset = 0;
  15825     int bank_size = 0, num_banks_per_pool = 1, bank_index = 0;
  15826     int handle_id = 0;
  15827     bcm_policer_t  macro_meter_policer = 0;
  15828     int macro_flow_meter_index = 0;
  15829     svm_macroflow_index_table_entry_t   *buf;
  15830     svm_macroflow_index_table_entry_t   *entry;
  15831     int entry_mem_size;    /* Size of table entry. */
  15832     int entry_index = 0;
  15833     int entry_index_max = 0;
  15834     int entry_modified = 0;
  15835     svm_meter_table_entry_t svm_meter_entry;
  15836     svm_meter_table_entry_t *svm_meter_buf;
  15837     int base_index = 0;
  15838     int offset = 0;
  15839 
  15840     /* Make sure policer is not attached to any entry. */
  15841     if (0 != policer_control->ref_count) {
  15842         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15843                   (BSL_META_U(unit,
  15844                               "Policer is still in use  \n")));
  15845         return (BCM_E_BUSY);
  15846     }
  15847     if (global_meter_action_bookkeep[unit]\
  15848                              [policer_control->action_id].reference_count > 0)
  15849     {
  15850         global_meter_action_bookkeep[unit]\
  15851                                [policer_control->action_id].reference_count--;
  15852     }
  15853     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  15854     num_pools =  SOC_INFO(unit).global_meter_pools;
  15855     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  15856     offset_mask = size_pool - 1;
  15857     pool_offset = _shr_popcount(offset_mask);
  15858     pool_mask = (num_pools - 1) << pool_offset;
  15859 
  15860     pid = policer_control->pid & offset_mask;
  15861     pool = (policer_control->pid & pool_mask) >> pool_offset;
  15862     numbers = policer_control->no_of_policers;
  15863     bank_size = size_pool / num_banks_per_pool;
  15864 
  15865     offset_mode =
  15866              ((policer_control->pid & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  15867                                     BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  15868     if (offset_mode >= 1) {
  15869         offset_mode = offset_mode - 1;
  15870     }
  15871 
  15872     /*  get the HW index for the policer to be deleted */
  15873     rv = _bcm_esw_get_policer_table_index(unit, policer_control->pid,
  15874                                                      &base_index);
  15875     if (BCM_FAILURE(rv)) {
  15876         LOG_DEBUG(BSL_LS_BCM_POLICER,
  15877                   (BSL_META_U(unit,
  15878                               "Unable to Get policer index for "
  15879                               "policer \n")));
  15880         return rv;
  15881     }
  15882 
  15883     /* check horizontal or vertical allocation and then free the policer */
  15884     if (policer_control->direction == GLOBAL_METER_ALLOC_VERTICAL) {
  15885 
  15886         handle_id = (pool * num_banks_per_pool) + (pid / bank_size);
  15887         bank_index = pid % bank_size;
  15888 
  15889         if (soc_feature(unit, soc_feature_global_meter_compaction_support)) {
  15890             for (offset = 0; offset < numbers; offset++) {
  15891                 rv = shr_aidxres_list_free(
  15892                         meter_alloc_list_handle[unit][handle_id],
  15893                         bank_index + offset);
  15894                 if (BCM_FAILURE(rv)) {
  15895                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  15896                             (BSL_META_U(unit, "Unable to free policer"
  15897                                         " shared index handle\n")));
  15898                     return rv;
  15899                 }
  15900             }
  15901         } else {
  15902             rv = shr_aidxres_list_free(
  15903                     meter_alloc_list_handle[unit][handle_id], bank_index);
  15904         }
  15905         if (BCM_FAILURE(rv)) {
  15906             LOG_DEBUG(BSL_LS_BCM_POLICER,
  15907                       (BSL_META_U(unit,
  15908                                   "Unable to free policer handle\n")));
  15909             return (rv);
  15910         }
  15911         for (index = 0; index < numbers; index++) {
  15912             rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit,
  15913                                                     pool, pid+index);
  15914             if (!BCM_SUCCESS(rv)) {
  15915                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  15916                           (BSL_META_U(unit,
  15917                                       "Unable to free policer handle in hz "
  15918                                       "index management\n")));
  15919                 return BCM_E_INTERNAL;
  15920             }
  15921         }
  15922 
  15923         entry_mem_size = sizeof(svm_meter_table_entry_t);
  15924         entry_index_max = base_index + numbers - 1;
  15925         svm_meter_buf = soc_cm_salloc(unit, entry_mem_size * numbers,
  15926                             "svm meter table entry");
  15927         if (svm_meter_buf == NULL) {
  15928             return BCM_E_MEMORY;
  15929         }
  15930         sal_memset(svm_meter_buf, 0, entry_mem_size * numbers);
  15931 
  15932         rv = soc_mem_write_range(unit, SVM_METER_TABLEm,
  15933                                   MEM_BLOCK_ALL, base_index,
  15934                                   entry_index_max, svm_meter_buf);
  15935         if (svm_meter_buf != NULL) {
  15936             soc_cm_sfree(unit, svm_meter_buf);
  15937         }
  15938         if (BCM_FAILURE(rv)) {
  15939             return rv;
  15940         }
  15941     } else if (policer_control->direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  15942         pool_id = pool;
  15943         sal_memset(&svm_meter_entry, 0, sizeof(svm_meter_entry));
  15944         for (index = 0;index < numbers; index++) {
  15945             if (index > 0) {
  15946                 pool_id = pool + policer_control->offset[index];
  15947             }
  15948             handle_id = (pool_id * num_banks_per_pool) + (pid / bank_size);
  15949             bank_index = pid % bank_size;
  15950             rv = shr_aidxres_list_free(
  15951                    meter_alloc_list_handle[unit][handle_id], bank_index);
  15952             if (BCM_FAILURE(rv)) {
  15953                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  15954                           (BSL_META_U(unit,
  15955                                       "Unable to free policer handle\n")));
  15956                 return (rv);
  15957             }
  15958             rv = WRITE_SVM_METER_TABLEm (unit, MEM_BLOCK_ALL,
  15959                                     base_index + (pool_id * size_pool),
  15960                                     &svm_meter_entry);
  15961             if (BCM_FAILURE(rv)) {
  15962                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  15963                           (BSL_META_U(unit,
  15964                                       "Unable to write to memory\n")));
  15965                 return (rv);
  15966             }
  15967 
  15968         }
  15969         rv = _bcm_gloabl_meter_free_horizontally(unit, pool, pid, numbers,
  15970                                                       policer_control->offset);
  15971         if (BCM_FAILURE(rv)) {
  15972             LOG_DEBUG(BSL_LS_BCM_POLICER,
  15973                       (BSL_META_U(unit,
  15974                                   "Unable to free policer handle in hz "
  15975                                   "index management\n")));
  15976             return (rv);
  15977         }
  15978     }
  15979 
  15980    /* Delete policer from policers hash. */
  15981     _GLOBAL_METER_HASH_REMOVE(global_meter_policer_bookkeep[unit],
  15982                    _global_meter_policer_control_t,
  15983                    policer_control, (pid & _GLOBAL_METER_HASH_MASK));
  15984     /* decrement mode reference count  */
  15985     if (offset_mode) {
  15986         bcm_policer_svc_meter_dec_mode_reference_count(unit, offset_mode);
  15987     }
  15988 
  15989     index = base_index;
  15990 
  15991     /* Write the index of the macro-meter at "micro_flow_index" location
  15992            of SVM_MACROFLOW_INDEX_TABLE */
  15993     if (policer_control->direction == GLOBAL_METER_ALLOC_VERTICAL) {
  15994 
  15995         entry_mem_size = sizeof(svm_macroflow_index_table_entry_t);
  15996         entry_index_max = index + numbers - 1;
  15997 
  15998         /* Allocate buffer to store the DMAed table entries. */
  15999         buf = soc_cm_salloc(unit, entry_mem_size * numbers,
  16000                               "svm macro flow index table entry buffer");
  16001         if (NULL == buf) {
  16002             return (BCM_E_MEMORY);
  16003         }
  16004         /* Initialize the entry buffer. */
  16005         sal_memset(buf, 0, sizeof(entry_mem_size) * numbers);
  16006 
  16007         /* Read the table entries into the buffer. */
  16008         rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  16009                                 MEM_BLOCK_ALL, index,
  16010                                 entry_index_max, buf);
  16011         if (BCM_FAILURE(rv)) {
  16012             if (buf) {
  16013                 soc_cm_sfree(unit, buf);
  16014             }
  16015             return rv;
  16016         }
  16017 
  16018         /* Iterate over the table entries. */
  16019         for (entry_index = 0; entry_index < numbers; entry_index++) {
  16020             entry = soc_mem_table_idx_to_pointer(unit,
  16021                               SVM_MACROFLOW_INDEX_TABLEm,
  16022                               svm_macroflow_index_table_entry_t *,
  16023                               buf, entry_index);
  16024             soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *)entry,
  16025                            MACROFLOW_INDEXf, (uint32 *)&macro_flow_meter_index);
  16026             if (macro_flow_meter_index > 0) {
  16027                 _bcm_esw_get_policer_id_from_index_offset(unit,
  16028                                macro_flow_meter_index, 0, &macro_meter_policer);
  16029                 rv = _bcm_esw_policer_decrement_ref_count(unit,
  16030                                                       macro_meter_policer);
  16031                 if (BCM_FAILURE(rv)) {
  16032                     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  16033                                 (BSL_META_U(unit,
  16034                                             "Unable to decrement ref count "
  16035                                             "for macro meter provided\n")));
  16036                     if (buf) {
  16037                         soc_cm_sfree(unit, buf);
  16038                     }
  16039                     return rv;
  16040                 }
  16041                 macro_flow_meter_index = 0; /* clear macro flow index entry */
  16042                 soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm,
  16043                                      (void *)entry, MACROFLOW_INDEXf,
  16044                                      (uint32 *)&macro_flow_meter_index);
  16045                 entry_modified = 1;
  16046             }
  16047         }
  16048         if (entry_modified) {
  16049             if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  16050                                   MEM_BLOCK_ALL, index,
  16051                                   entry_index_max, buf)) < 0) {
  16052                 if (BCM_FAILURE(rv)) {
  16053                          LOG_VERBOSE(BSL_LS_BCM_POLICER,
  16054                                      (BSL_META_U(unit,
  16055                                                  "Unable to write to macro flow "
  16056                                                  "index table at index provided\n")));
  16057                     if (buf) {
  16058                         soc_cm_sfree(unit, buf);
  16059                     }
  16060                     return rv;
  16061                 }
  16062             }
  16063         }
  16064         if (buf) {
  16065             soc_cm_sfree(unit, buf);
  16066         }
  16067     }
  16068     /* De-allocate policer descriptor. */
  16069     sal_free(policer_control);
  16070 
  16071     return rv;
  16072 }
  16073 
  16074 /*
  16075  * Function:
  16076  *      _bcm_esw_global_meter_set_cascade_info_to_hw
  16077  * Purpose:
  16078  *      In case of cascade meter, write configuration info that is
  16079  *      specific to cascade meters to HW
  16080  * Parameters:
  16081  *     unit                  - (IN) unit number
  16082  *     numbers               - (IN) Number of policers
  16083  *     policer_id            - (IN) base policer id
  16084  *     mode                  - (IN) policer group mode
  16085  *     pid_offset            - (IN) Offset w.r.t base policer
  16086  * Returns:
  16087  *     BCM_E_XXX
  16088  */
  16089 int _bcm_esw_global_meter_set_cascade_info_to_hw(int unit,int  numbers,
  16090                           bcm_policer_t policer_id,
  16091                           bcm_policer_group_mode_t mode, uint8 *pid_offset)
  16092 {
  16093     int rv = BCM_E_NONE;
  16094     svm_meter_table_entry_t data;
  16095     int index = 0;
  16096     uint32 start_of_chain = 0, end_of_chain = 0, meter_mode = 0;
  16097     uint32 coupling_flag = 0;
  16098     int size_pool;
  16099     int policer_index = 0;
  16100     int table_offset = 0;
  16101     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  16102 
  16103     _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index);
  16104 
  16105     for (index=0; index < numbers; index++) {
  16106         if (index > 0) {
  16107             table_offset = policer_index + (pid_offset[index] * size_pool);
  16108         } else {
  16109             table_offset = policer_index;
  16110         }
  16111         /* read HW register */
  16112         rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  16113                                                   table_offset,  &data);
  16114         if (BCM_FAILURE(rv)) {
  16115             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16116                       (BSL_META_U(unit,
  16117                                   "Unable to read SVC METER TABLE at "
  16118                                   "offset %d\n"), table_offset));
  16119             return (rv);
  16120         }
  16121         switch (mode) {
  16122             case bcmPolicerGroupModeCascade:
  16123             case bcmPolicerGroupModeIntPriCascade:
  16124             case bcmPolicerGroupModeCascadeDroppedPktExclude:
  16125                 if (index == 0) {
  16126                     end_of_chain = 1;
  16127                 } else {
  16128                     end_of_chain = 0;
  16129                 }
  16130                 if (index == (numbers - 1)) {
  16131                     start_of_chain = 1;
  16132                 } else {
  16133                     start_of_chain = 0;
  16134                 }
  16135                 meter_mode = 1;
  16136                 coupling_flag = 0;
  16137                 break;
  16138 
  16139 
  16140             case bcmPolicerGroupModeCascadeWithCoupling:
  16141             case bcmPolicerGroupModeIntPriCascadeWithCoupling:
  16142                 if ((index == 0) || (index == (numbers / 2))) {
  16143                     end_of_chain = 1;
  16144                 } else {
  16145                     end_of_chain = 0;
  16146                 }
  16147                 if ((index == (numbers - 1)) || (index == ((numbers/2) - 1))) {
  16148                     start_of_chain = 1;
  16149                 } else {
  16150                     start_of_chain = 0;
  16151                 }
  16152                 meter_mode = 1;
  16153                 coupling_flag = 1;
  16154                 break;
  16155 
  16156             default:
  16157                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  16158                           (BSL_META_U(unit,
  16159                                       "Invalid mode passed \n")));
  16160                 return BCM_E_NONE;
  16161                 break;
  16162         }
  16163         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, START_OF_CHAINf)) {
  16164             soc_SVM_METER_TABLEm_field_set(unit, &data,
  16165                                             START_OF_CHAINf, &start_of_chain);
  16166         }
  16167         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, END_OF_CHAINf)) {
  16168             soc_SVM_METER_TABLEm_field_set(unit, &data,
  16169                                                END_OF_CHAINf, &end_of_chain);
  16170         }
  16171         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  16172             soc_SVM_METER_TABLEm_field_set(unit, &data,
  16173                                                     METER_MODEf, &meter_mode);
  16174         }
  16175         if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) {
  16176             soc_SVM_METER_TABLEm_field_set(unit, &data,
  16177                                              COUPLING_FLAGf, &coupling_flag);
  16178         }
  16179         /* write to hW */
  16180         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  16181                                                          table_offset, &data);
  16182         if (BCM_FAILURE(rv)) {
  16183             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16184                       (BSL_META_U(unit,
  16185                                   "Unable to write SVC METER TABLE at "
  16186                                   "offset %d\n"), table_offset));
  16187             return (rv);
  16188         }
  16189     }
  16190     return rv;
  16191 }
  16192 
  16193 /*
  16194  * Function:
  16195  *      _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw
  16196  * Purpose:
  16197  *      In case of MEF 10.3 cascade meter, write configuration info that is
  16198  *      specific to cascade meters to HW
  16199  * Parameters:
  16200  *     unit                  - (IN) unit number
  16201  *     numbers               - (IN) Number of policers
  16202  *     policer_id            - (IN) base policer id
  16203  *     mode                  - (IN) policer group mode
  16204  *     pid_offset            - (IN) Offset w.r.t base policer
  16205  * Returns:
  16206  *     BCM_E_XXX
  16207  */
  16208 int
  16209 _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw (int unit,
  16210                                                          int  numbers,
  16211                                                        bcm_policer_t policer_id,
  16212                                                   bcm_policer_group_mode_t mode,
  16213                                                          uint8 *pid_offset)
  16214 {
  16215     int     rv = BCM_E_NONE;
  16216     int     pool = 0;
  16217     uint32  nxt_c = 0, nxt_e = 0, c_e = 0, pair_e = 0;
  16218     uint32  nxt_c_valid = 0, nxt_e_valid = 0, pair_e_valid = 0;
  16219     uint32  meter_mode = 0;
  16220     int     size_pool;
  16221     int     policer_index = 0;
  16222     int     table_offset = 0;
  16223     svm_meter_table_entry_t svm_entry;
  16224 
  16225     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  16226     _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index);
  16227 
  16228     for (pool = 0; pool < numbers; pool++) {
  16229         if (pool > 0) {
  16230             table_offset = policer_index + (pid_offset[pool] * size_pool);
  16231         } else {
  16232             table_offset = policer_index;
  16233         }
  16234 
  16235         /* read HW register */
  16236         rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  16237                           table_offset,  &svm_entry);
  16238         if (BCM_FAILURE(rv)) {
  16239             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16240                       (BSL_META_U(unit,
  16241                                   "Unable to read SVC METER TABLE at "
  16242                                   "offset %d\n"), table_offset));
  16243             return (rv);
  16244         }
  16245 
  16246         meter_mode = 1;
  16247 
  16248         switch (mode) {
  16249         case bcmPolicerGroupModeCascade:
  16250         case bcmPolicerGroupModeIntPriCascade:
  16251         case bcmPolicerGroupModeCascadeDroppedPktExclude:
  16252         {
  16253             /* For non GCF mode, overflow fields need to be over written
  16254              * during individual policer_set if policer mode is passed
  16255              * as CoupledCascaded
  16256              */
  16257             c_e  = 0;
  16258             nxt_c_valid  = 1; /* Should the last C_Valid always be true? */
  16259             nxt_e_valid = (pool == (numbers -1)) ? 0 : 1;
  16260             nxt_c  = nxt_e = (pool == (numbers -1)) ? 0 : pool + 1;
  16261         }
  16262         break;
  16263 
  16264         case bcmPolicerGroupModeCascadeWithCoupling: /* Pass through */
  16265         case bcmPolicerGroupModeIntPriCascadeWithCoupling:
  16266         {
  16267             /* Set GCF configuration, it is 2 stage process
  16268              *     Stage 1 - Set committed cascaded chain
  16269              *     Stage 2 - Set excess cascaded chain
  16270              */
  16271 
  16272             if (pool < 4) {
  16273                 /* Stage 1 - committed chain */
  16274                 c_e          =  (pool == (numbers/2 -1)) ? 1 : 0;
  16275                 nxt_c_valid  = 1;
  16276                 nxt_c        = pool + 1;
  16277                 nxt_e_valid  = 0;
  16278                 nxt_e        = 0;
  16279                 pair_e_valid = 1;
  16280                 pair_e       = pool + 4;
  16281             } else {
  16282                 /* Stage 2 - excess chain */
  16283                 c_e          = 0;
  16284                 nxt_c_valid  = 0;
  16285                 nxt_c        = 0;
  16286                 nxt_e_valid  = (pool == (numbers -1)) ? 0 : 1;
  16287                 nxt_e        = (pool == (numbers -1)) ? 0 : pool + 1;
  16288                 pair_e_valid = 0;
  16289                 pair_e       = 0;
  16290             }
  16291 
  16292             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16293                                            METER_PAIR_EXCESS_BUCKETf,
  16294                                            &pair_e);
  16295             soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16296                                            METER_PAIR_EXCESS_BUCKET_VALIDf,
  16297                                            &pair_e_valid);
  16298         }
  16299         break;
  16300 
  16301         default:
  16302             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16303                       (BSL_META_U(unit,
  16304                                   "Invalid mode passed \n")));
  16305             return BCM_E_NONE;
  16306         }
  16307 
  16308         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16309                                        NXT_EXCESS_BUCKETf,
  16310                                        &nxt_e);
  16311         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16312                                        NXT_EXCESS_BUCKET_VALIDf,
  16313                                        &nxt_e_valid);
  16314 
  16315         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16316                                        NXT_COMMITTED_BUCKETf,
  16317                                        &nxt_c);
  16318         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16319                                        NXT_COMMITTED_BUCKET_VALIDf,
  16320                                        &nxt_c_valid);
  16321 
  16322         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16323                                        COMMITTED_EXCESSf,
  16324                                        &c_e);
  16325 
  16326         soc_SVM_METER_TABLEm_field_set(unit, &svm_entry,
  16327                                        METER_MODEf, &meter_mode);
  16328 
  16329         /* write to hW */
  16330         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  16331                            table_offset, &svm_entry);
  16332         if (BCM_FAILURE(rv)) {
  16333             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16334                       (BSL_META_U(unit,
  16335                                   "Unable to write SVC METER TABLE at "
  16336                                   "offset %d\n"), table_offset));
  16337             return (rv);
  16338         }
  16339     } /* End for loop */
  16340 
  16341     return rv;
  16342 }
  16343 
  16344 /*
  16345  * Function:
  16346  *      _bcm_esw_policer_set_offset_table_map_to_increasing_value
  16347  * Purpose:
  16348  *     Set first n entires of the offset table with a incremental value.
  16349  *     starting from 0
  16350  * Parameters:
  16351  *     num_offsets           - (IN) Number of offsets
  16352  *     offset_map            - (IN/OUT) Offset Map
  16353  * Returns:
  16354  *     BCM_E_XXX
  16355  */
  16356 int _bcm_esw_policer_set_offset_table_map_to_increasing_value(uint32 num_offsets,
  16357                                offset_table_entry_t *offset_map)
  16358 {
  16359     int rv = BCM_E_NONE;
  16360     int i = 0;
  16361     if (num_offsets >= BCM_SVC_METER_MAP_SIZE_256) {
  16362         LOG_DEBUG(BSL_LS_BCM_POLICER,
  16363                   (BSL_META("Number of offsets passed is more than map table "
  16364                             "size %d\n"), num_offsets));
  16365         return BCM_E_INTERNAL;
  16366     }
  16367     for(i = 0; i < num_offsets; i++) {
  16368         offset_map[i].offset= i;
  16369         offset_map[i].meter_enable = 1;
  16370     }
  16371     return rv;
  16372 }
  16373 
  16374 /*
  16375  * Function:
  16376  *      _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool
  16377  * Purpose:
  16378  *     Set first n entires of the offset table with a specified value.
  16379  * Parameters:
  16380  *     unit                  - (IN) unit number
  16381  *     Coupling              - (IN) Coupling flag
  16382  *     num_offsets           - (IN) Number of offsets
  16383  *     value                 - (IN) Value to be set
  16384  *     offset_map            - (IN/OUT) Offset Map
  16385  * Returns:
  16386  *     BCM_E_XXX
  16387  */
  16388 int _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(int unit,
  16389                                int coupling,
  16390                                uint32 num_offsets,
  16391                                uint32 value,
  16392                                offset_table_entry_t *offset_map)
  16393 {
  16394     int rv = BCM_E_NONE;
  16395     int i = 0, j = 0;
  16396     int pool_offset_limit;
  16397 
  16398     pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 :
  16399                                         BCM_POLICER_GLOBAL_METER_MAX_POOL;
  16400     if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) {
  16401         LOG_DEBUG(BSL_LS_BCM_POLICER,
  16402                   (BSL_META("Number of offsets passed is more than map table "
  16403                             "size %d\n"), num_offsets));
  16404         return BCM_E_INTERNAL;
  16405     }
  16406     if (num_offsets) {
  16407         if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  16408             /* pre MEF 10.3 device */
  16409             i = num_offsets - 1;
  16410             for(; i >= 0; i--) {
  16411                 if (coupling) {
  16412                     offset_map[j].pool = j + 4;
  16413                 } else {
  16414                     offset_map[j].pool = j;
  16415                 }
  16416                 offset_map[j].offset= value;
  16417                 offset_map[j].meter_enable = 1;
  16418                 j++;
  16419             }
  16420         } else {
  16421             /* MEF 10.3 onward device */
  16422             for (j = 0; j < num_offsets; j++) {
  16423                 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending))  {
  16424                     offset_map[j].pool = pool_offset_limit - j - 1;
  16425                 } else {
  16426                     offset_map[j].pool = j;
  16427                 }
  16428                 offset_map[j].offset= value;
  16429                 offset_map[j].meter_enable = 1;
  16430             }
  16431         }
  16432     }
  16433     return rv;
  16434 }
  16435 
  16436 /*
  16437  * Function:
  16438  *      _bcm_esw_policer_set_offset_table_map_flex_pool
  16439  * Purpose:
  16440  *     Set first n entires of the offset table with a specified value.
  16441  * Parameters:
  16442  *     unit                  - (IN) unit number
  16443  *     Coupling              - (IN) Coupling flag
  16444  *     num_offsets           - (IN) Number of offsets
  16445  *     pool_offset           - (IN) Values to be set as offsets
  16446  *     offset_map            - (IN/OUT) Offset Map
  16447  * Returns:
  16448  *     BCM_E_XXX
  16449  */
  16450 int _bcm_esw_policer_set_offset_table_map_flex_pool(int unit,
  16451                                int coupling,
  16452                                uint32 num_offsets,
  16453                                uint32 *pool_offset,
  16454                                offset_table_entry_t *offset_map)
  16455 {
  16456     int rv = BCM_E_NONE;
  16457     int i = 0, j = 0;
  16458     int pool_offset_limit;
  16459 
  16460     if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) {
  16461         LOG_DEBUG(BSL_LS_BCM_POLICER,
  16462                   (BSL_META("Number of offsets passed is more than map table "
  16463                             "size %d\n"), num_offsets));
  16464         return BCM_E_INTERNAL;
  16465     }
  16466 
  16467     pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 :
  16468                                         BCM_POLICER_GLOBAL_METER_MAX_POOL;
  16469 
  16470     if (num_offsets) {
  16471         if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  16472             i = num_offsets - 1;
  16473             for(; i >= 0; i--) {
  16474                 if (coupling) {
  16475                     offset_map[j].pool = pool_offset[j] + 4;
  16476                 } else {
  16477                     offset_map[j].pool = pool_offset[j];
  16478                 }
  16479                 offset_map[j].offset= 0;
  16480                 offset_map[j].meter_enable = 1;
  16481                 j++;
  16482             }
  16483         } else {
  16484             /* MEF 10.3 onward devices */
  16485             for (j = 0; j < num_offsets; j++) {
  16486                 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending))  {
  16487                     offset_map[j].pool = pool_offset_limit - pool_offset[j] - 1;
  16488                 } else {
  16489                     offset_map[j].pool = pool_offset[j];
  16490                 }
  16491                 offset_map[j].offset = 0;
  16492                 offset_map[j].meter_enable = 1;
  16493             }
  16494         }
  16495     }
  16496     return rv;
  16497 }
  16498 
  16499 /*
  16500  * Function:
  16501  *      _bcm_esw_policer_set_offset_table_map_to_a_value
  16502  * Purpose:
  16503  *     Set first n entires of the offset table with a specified value.
  16504  * Parameters:
  16505  *     num_offsets           - (IN) Number of offsets
  16506  *     value                 - (IN) Value to be set
  16507  *     offset_map            - (IN/OUT) Offset Map
  16508  * Returns:
  16509  *     BCM_E_XXX
  16510  */
  16511 int _bcm_esw_policer_set_offset_table_map_to_a_value(uint32 num_offsets,
  16512                                uint32 value,
  16513                                offset_table_entry_t *offset_map)
  16514 {
  16515     int rv = BCM_E_NONE;
  16516     int i = 0;
  16517     if (num_offsets >= BCM_SVC_METER_MAP_SIZE_256) {
  16518         LOG_DEBUG(BSL_LS_BCM_POLICER,
  16519                   (BSL_META("Number of offsets passed is more than map table "
  16520                             "size %d\n"), num_offsets));
  16521         return BCM_E_INTERNAL;
  16522     }
  16523     for(i = 0; i < num_offsets; i++) {
  16524         offset_map[i].offset= value;
  16525         offset_map[i].meter_enable = 1;
  16526     }
  16527     return rv;
  16528 }
  16529 
  16530 /*
  16531  * Function:
  16532  *      _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool
  16533  * Purpose:
  16534  *     Create the map of offset table with varying pool of policers that needs
  16535  *     to be written to different offsets
  16536  * Parameters:
  16537  *     unit                  - (IN) unit number
  16538  *     Coupling              - (IN) Coupling flag
  16539  *     num_offsets           - (IN) Number of offsets
  16540  *     table_offset          - (IN) Offset positons
  16541  *     pool_offset           - (IN) Values to be set as offsets
  16542  *     offset_map            - (IN/OUT) Offset Map
  16543  * Returns:
  16544  *     BCM_E_XXX
  16545  */
  16546 
  16547 int _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool(int unit,
  16548                                int coupling,
  16549                                uint32 num_offsets,
  16550                                uint32 *table_offset,
  16551                                uint32 *pool_offset,
  16552                                offset_table_entry_t *offset_map)
  16553 {
  16554     int rv = BCM_E_NONE;
  16555     int i = 0, j = 0;
  16556     int pool_offset_limit;
  16557 
  16558     if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) {
  16559         LOG_DEBUG(BSL_LS_BCM_POLICER,
  16560                   (BSL_META("Number of offsets passed is more than map table "
  16561                             "size %d\n"), num_offsets));
  16562         return BCM_E_INTERNAL;
  16563     }
  16564 
  16565     pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 :
  16566                                         BCM_POLICER_GLOBAL_METER_MAX_POOL;
  16567 
  16568     if (num_offsets) {
  16569         if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  16570             i = num_offsets - 1;
  16571             for(j = 0; j <= i; j++) {
  16572                 if ((table_offset[j] >= BCM_SVC_METER_MAP_SIZE_256) ||
  16573                         (pool_offset[j] >= pool_offset_limit)) {
  16574                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  16575                             (BSL_META("Offset/pool passed is out of range "
  16576                                       "size %d %d\n"), table_offset[j], pool_offset[j]));
  16577                     return BCM_E_PARAM;
  16578                 }
  16579 
  16580                 if (coupling) {
  16581                     offset_map[table_offset[j]].pool = pool_offset[j] + 4;
  16582                 } else {
  16583                     offset_map[table_offset[j]].pool = pool_offset[j];
  16584                 }
  16585                 offset_map[table_offset[j]].offset= 0;
  16586                 offset_map[table_offset[j]].meter_enable = 1;
  16587             }
  16588         } else {
  16589             /* MEF 10.3 onward devices */
  16590             for (j = 0; j < num_offsets; j++) {
  16591                 if ((table_offset[j] >= BCM_SVC_METER_MAP_SIZE_256) ||
  16592                         (pool_offset[j] >= pool_offset_limit)) {
  16593                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  16594                             (BSL_META("Offset/pool passed is out of range "
  16595                                       "size %d %d\n"), table_offset[j], pool_offset[j]));
  16596                     return BCM_E_PARAM;
  16597                 }
  16598 
  16599                 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending))  {
  16600                     offset_map[table_offset[j]].pool = pool_offset_limit - pool_offset[j] - 1;
  16601                 } else {
  16602                     offset_map[table_offset[j]].pool = pool_offset[j];
  16603                 }
  16604                 offset_map[table_offset[j]].offset = 0;
  16605                 offset_map[table_offset[j]].meter_enable = 1;
  16606             }
  16607         }
  16608     }
  16609     return rv;
  16610 }
  16611 
  16612 /*
  16613  * Function:
  16614  *      _bcm_esw_policer_set_offset_table_map
  16615  * Purpose:
  16616  *     Create the map of policer offsets that needs to be written to offset
  16617  *     table
  16618  * Parameters:
  16619  *     num_offsets           - (IN) Number of offsets
  16620  *     table_offset          - (IN) Offset positons
  16621  *     value                 - (IN) Values to be set
  16622  *     offset_map            - (IN/OUT) Offset Map
  16623  * Returns:
  16624  *     BCM_E_XXX
  16625  */
  16626 int _bcm_esw_policer_set_offset_table_map(uint32 num_offsets,
  16627                                uint32 *table_offset,
  16628                                uint32 *value,
  16629                                offset_table_entry_t *offset_map)
  16630 {
  16631     int rv = BCM_E_NONE;
  16632     int i = 0;
  16633     for(i = 0; i < num_offsets; i++) {
  16634         if ((table_offset[i] >= BCM_SVC_METER_MAP_SIZE_256) ||
  16635                (value[i] >= BCM_SVC_METER_MAP_SIZE_256)) {
  16636             LOG_DEBUG(BSL_LS_BCM_POLICER,
  16637                       (BSL_META("Offset/value passed is more than map table "
  16638                                 "size %d %d\n"), table_offset[i], value[i]));
  16639             return BCM_E_INTERNAL;
  16640         }
  16641         offset_map[table_offset[i]].offset= value[i];
  16642         offset_map[table_offset[i]].meter_enable = 1;
  16643     }
  16644     return rv;
  16645 }
  16646 
  16647 /*
  16648  * Function:
  16649  *      _bcm_esw_policer_group_set_mode_and_map
  16650  * Purpose:
  16651  *
  16652  * Parameters:
  16653  *     unit                  - (IN) unit number
  16654  *     mode                  - (IN) Policer group mode
  16655  *     npolicers             - (IN) Number of policers
  16656  *     direction             - (IN) Horizontal/Vertical
  16657  *     mode_attr             - (IN) Offset mode attributes
  16658  * Returns:
  16659  *     BCM_E_XXX
  16660  */
  16661 int _bcm_esw_policer_group_set_mode_and_map( int unit,
  16662                                bcm_policer_group_mode_t mode,
  16663                                int *npolicers, bcm_policer_map_t *mapping,
  16664                                uint32 *direction,
  16665                                bcm_policer_svc_meter_attr_t *mode_attr)
  16666 {
  16667     int rv = BCM_E_NONE;
  16668     int num_pools = 0;
  16669     uint32 table_offset[16] = { 0 };
  16670     uint32 value[16] = { 0 };
  16671     pkt_attr_bits_t  *pkt_attr = NULL;
  16672     uint32                   map_index = 0;
  16673     compressed_pkt_res_attr_map_t *pkt_res_map = NULL;
  16674     compressed_pri_cnf_attr_map_t  *pri_cnf_map = NULL;
  16675     offset_table_entry_t   *offset_map = NULL;
  16676     uint32                  type = 0;
  16677     uint32                  offset = 0;
  16678     uint8                   *pkt_res = NULL;
  16679     int                     no_entries_to_populate = 0;
  16680     int                     shift_bits = 0;
  16681     int                     index_max = 0;
  16682     int                     i = 0;
  16683     uint8 *val = NULL;
  16684 
  16685     mode_attr->mode_type_v = uncompressed_mode;
  16686     num_pools =  SOC_INFO(unit).global_meter_pools;
  16687     if (mapping != NULL) {
  16688         val  = mapping->offset_map;
  16689     }
  16690 
  16691     if (BCM_SVM_DEV_ATTR(unit)->pkt_resolution != NULL) {
  16692         pkt_res = BCM_SVM_DEV_ATTR(unit)->pkt_resolution;
  16693     } else {
  16694         /*
  16695          * Other devices do not support service meters, return error.
  16696          */
  16697         return (BCM_E_UNAVAIL);
  16698     }
  16699 
  16700     switch (mode) {
  16701         /* A single policer used for all traffic types */
  16702         case bcmPolicerGroupModeSingle:
  16703         {
  16704             *npolicers = 1;
  16705             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  16706                       FP_RESOLUTION_MAX, 0,
  16707                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16708             BCM_IF_ERROR_RETURN(rv);
  16709             break;
  16710         }
  16711         /* ********************************************************************/
  16712          /* A dedicated policer per traffic type Unicast,multicast,broadcast  */
  16713          /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT                   */
  16714          /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT*/
  16715          /* 3) L2BC_PKT|                                                      */
  16716          /* *******************************************************************/
  16717         case bcmPolicerGroupModeTrafficType:
  16718         {
  16719             *npolicers = 3;
  16720             mode_attr->uncompressed_attr_selectors_v.\
  16721                       uncompressed_attr_bits_selector =
  16722                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16723                 table_offset[0] = pkt_res[KNOWN_L2UC_PKT];
  16724                 table_offset[1] = pkt_res[KNOWN_L3UC_PKT];
  16725                 table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT];
  16726                 table_offset[3] = pkt_res[KNOWN_L2MC_PKT];
  16727                 table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT];
  16728                 table_offset[5] = pkt_res[L2BC_PKT];
  16729                 table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT];
  16730                 table_offset[7] = pkt_res[UNKNOWN_IPMC_PKT];
  16731                 table_offset[8] = pkt_res[KNOWN_IPMC_PKT];
  16732                 value[3] = 1;
  16733                 value[4] = 1;
  16734                 value[5] = 2;
  16735                 value[7] = 1;
  16736                 value[8] = 1;
  16737 
  16738             rv =  _bcm_esw_policer_set_offset_table_map(9, &table_offset[0],
  16739                       &value[0],
  16740                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16741             BCM_IF_ERROR_RETURN(rv);
  16742             break;
  16743         }
  16744          /************************************************************** */
  16745          /* A pair of policers where the base policer is used for dlf and */
  16746          /* the other is used for all traffic types                       */
  16747          /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT)                                */
  16748          /* 2) UNKNOWN_PKT | CONTROL_PKT|BPDU_PKT|L2BC_PKT|L2UC_PKT|      */
  16749          /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|            */
  16750          /*    UNKNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|          */
  16751          /*    UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|         */
  16752          /*    KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|          */
  16753          /*    UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                   */
  16754          /* ************************************************************* */
  16755 
  16756         case bcmPolicerGroupModeDlfAll:
  16757         {
  16758             *npolicers = 2;
  16759             mode_attr->uncompressed_attr_selectors_v.\
  16760                      uncompressed_attr_bits_selector =
  16761                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16762             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  16763                       FP_RESOLUTION_MAX, 1,
  16764                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16765             BCM_IF_ERROR_RETURN(rv);
  16766             table_offset[0] = pkt_res[UNKNOWN_L2UC_PKT];
  16767             value[0] = 0;
  16768             rv =  _bcm_esw_policer_set_offset_table_map(1, &table_offset[0],
  16769                       &value[0],
  16770                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16771             BCM_IF_ERROR_RETURN(rv);
  16772             break;
  16773         }
  16774          /* ******************************************************* */
  16775          /* A dedicated policer for unknown unicast, known unicast, */
  16776          /* multicast, broadcast                                    */
  16777          /* 1) UNKNOWN_L3UC_PKT                                     */
  16778          /* 2) L2UC_PKT | KNOWN_L3UC_PKT                            */
  16779          /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT |                    */
  16780          /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                    */
  16781          /* 4) L2BC_PKT                                             */
  16782          /* ******************************************************* */
  16783         case bcmPolicerGroupModeTyped:
  16784         {
  16785             *npolicers = 4;
  16786             mode_attr->uncompressed_attr_selectors_v.\
  16787                       uncompressed_attr_bits_selector =
  16788                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16789             table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT];
  16790             table_offset[1] = pkt_res[KNOWN_L3UC_PKT];
  16791             table_offset[2] = pkt_res[KNOWN_L2UC_PKT];
  16792             table_offset[3] = pkt_res[KNOWN_L2MC_PKT];
  16793             table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT];
  16794             table_offset[5] = pkt_res[L2BC_PKT];
  16795             table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT];
  16796             table_offset[7] = pkt_res[UNKNOWN_IPMC_PKT];
  16797             table_offset[8] = pkt_res[KNOWN_IPMC_PKT];
  16798             value[1] = 1;
  16799             value[2] = 1;
  16800             value[3] = 2;
  16801             value[4] = 2;
  16802             value[5] = 3;
  16803             value[7] = 2;
  16804             value[8] = 2;
  16805             rv =  _bcm_esw_policer_set_offset_table_map(9, &table_offset[0],
  16806                       &value[0],
  16807                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16808             BCM_IF_ERROR_RETURN(rv);
  16809             break;
  16810         }
  16811          /* ******************************************************* */
  16812          /* A dedicated policer for unknown unicast, known unicast, */
  16813          /* multicast, broadcast and one for all traffic(not already*/
  16814          /* counted)                                                */
  16815          /* 1) UNKNOWN_L3UC_PKT                                     */
  16816          /* 2) L2UC_PKT | KNOWN_L3UC_PKT                            */
  16817          /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                      */
  16818          /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                    */
  16819          /* 4) L2BC_PKT                                             */
  16820          /* 5) UNKNOWN_PKT|CONTROL_PKT|BPDU_PKT|L2DLF_PKT|          */
  16821          /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_MPLS_PKT |     */
  16822          /*    KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT */
  16823          /*    KNOWN_MIM_PKT|UNKNOWN_MIM_PKT|                       */
  16824          /*    KNOWN_MPLS_MULTICAST_PKT                             */
  16825          /* ******************************************************* */
  16826         case bcmPolicerGroupModeTypedAll:
  16827         {
  16828             *npolicers = 5;
  16829             mode_attr->uncompressed_attr_selectors_v.\
  16830                       uncompressed_attr_bits_selector =
  16831                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16832             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  16833                       FP_RESOLUTION_MAX, 4,
  16834                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16835             BCM_IF_ERROR_RETURN(rv);
  16836             table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT];
  16837             table_offset[1] = pkt_res[KNOWN_L3UC_PKT];
  16838             table_offset[2] = pkt_res[KNOWN_L2UC_PKT];
  16839             table_offset[3] = pkt_res[KNOWN_L2MC_PKT];
  16840             table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT];
  16841             table_offset[5] = pkt_res[L2BC_PKT];
  16842             table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT];
  16843             table_offset[7] = pkt_res[KNOWN_IPMC_PKT];
  16844             table_offset[8] = pkt_res[UNKNOWN_IPMC_PKT];
  16845             value[1] = 1;
  16846             value[2] = 1;
  16847             value[3] = 2;
  16848             value[4] = 2;
  16849             value[5] = 3;
  16850             value[7] = 2;
  16851             value[8] = 2;
  16852             rv =  _bcm_esw_policer_set_offset_table_map(9, &table_offset[0],
  16853                       &value[0],
  16854                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16855             BCM_IF_ERROR_RETURN(rv);
  16856             break;
  16857         }
  16858         /* **************************************************************   */
  16859          /* A single policer used for all traffic types with an additional   */
  16860          /* policer for control traffic                                      */
  16861          /* 1) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|L2DLF_PKT|                      */
  16862          /*    UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|               */
  16863          /*    UNKNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|             */
  16864          /*    UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|            */
  16865          /*    KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|             */
  16866          /*    UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                      */
  16867          /* 2) CONTROL_PKT|BPDU_PKT                                          */
  16868          /* **************************************************************   */
  16869         case bcmPolicerGroupModeSingleWithControl:
  16870         {
  16871             *npolicers = 2;
  16872             mode_attr->uncompressed_attr_selectors_v.\
  16873                       uncompressed_attr_bits_selector =
  16874                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16875             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  16876                       FP_RESOLUTION_MAX, 0,
  16877                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16878             BCM_IF_ERROR_RETURN(rv);
  16879             table_offset[0] = pkt_res[CONTROL_PKT];
  16880             table_offset[1] = pkt_res[BPDU_PKT];
  16881             value[0] = 1;
  16882             value[1] = 1;
  16883             rv =  _bcm_esw_policer_set_offset_table_map(2, &table_offset[0],
  16884                       &value[0],
  16885                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16886             BCM_IF_ERROR_RETURN(rv);
  16887             break;
  16888         }
  16889          /* ********************************************************  */
  16890          /* A dedicated policer per traffic type unicast, multicast,  */
  16891          /* broadcast with an additional counter for control traffic  */
  16892          /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT           */
  16893          /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|                       */
  16894          /*    KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT                      */
  16895          /* 3) L2BC_PKT|                                              */
  16896          /* 4) CONTROL_PKT|BPDU_PKT                                   */
  16897          /* ********************************************************  */
  16898         case bcmPolicerGroupModeTrafficTypeWithControl:
  16899         {
  16900             *npolicers = 4;
  16901             mode_attr->uncompressed_attr_selectors_v.\
  16902                       uncompressed_attr_bits_selector =
  16903                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16904             table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT];
  16905             table_offset[1] = pkt_res[KNOWN_L3UC_PKT];
  16906             table_offset[2] = pkt_res[KNOWN_L2UC_PKT];
  16907             table_offset[3] = pkt_res[KNOWN_L2MC_PKT];
  16908             table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT];
  16909             table_offset[5] = pkt_res[L2BC_PKT];
  16910             table_offset[6] = pkt_res[CONTROL_PKT];
  16911             table_offset[7] = pkt_res[BPDU_PKT];
  16912             table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT];
  16913             table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT];
  16914             table_offset[10] = pkt_res[KNOWN_IPMC_PKT];
  16915             value[3] = 1;
  16916             value[4] = 1;
  16917             value[5] = 2;
  16918             value[6] = 3;
  16919             value[7] = 3;
  16920             value[9] = 1;
  16921             value[10] = 1;
  16922             rv =  _bcm_esw_policer_set_offset_table_map(11, &table_offset[0],
  16923                       &value[0],
  16924                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16925             BCM_IF_ERROR_RETURN(rv);
  16926             break;
  16927         }
  16928          /* ************************************************************** */
  16929          /* A set of 3 policers where the base policer is used for control,*/
  16930          /* the next one for dlf and the other counter is used for all     */
  16931          /* traffic types                                                  */
  16932          /* 1) CONTROL_PKT|BPDU_PKT                                        */
  16933          /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT)                                 */
  16934          /* 3) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|                              */
  16935          /*   UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT|              */
  16936          /*   UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT|                             */
  16937          /*   UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT|           */
  16938          /*   KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|            */
  16939          /*   UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT                     */
  16940          /* ************************************************************** */
  16941         case bcmPolicerGroupModeDlfAllWithControl:
  16942         {
  16943             *npolicers = 3;
  16944             mode_attr->uncompressed_attr_selectors_v.\
  16945                       uncompressed_attr_bits_selector =
  16946                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16947             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  16948                       FP_RESOLUTION_MAX, 2,
  16949                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16950             BCM_IF_ERROR_RETURN(rv);
  16951             table_offset[0] = pkt_res[CONTROL_PKT];
  16952             table_offset[1] = pkt_res[BPDU_PKT];
  16953             table_offset[2] = pkt_res[UNKNOWN_L2UC_PKT];
  16954             value[2] = 1;
  16955             rv =  _bcm_esw_policer_set_offset_table_map(3, &table_offset[0],
  16956                       &value[0],
  16957                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  16958             BCM_IF_ERROR_RETURN(rv);
  16959             break;
  16960         }
  16961          /* **************************************************************** */
  16962          /* A dedicated policer for control, unknown unicast, known unicast, */
  16963          /* multicast, broadcast                                             */
  16964          /* 1) CONTROL_PKT|BPDU_PKT                                          */
  16965          /* 2) UNKNOWN_L3UC_PKT                                              */
  16966          /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                               */
  16967          /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|                              */
  16968          /*    KNOWN_IPMC_PKT| UNKNOWN_IPMC_PKT                              */
  16969          /* 5) L2BC_PKT                                                      */
  16970          /* **************************************************************** */
  16971         case bcmPolicerGroupModeTypedWithControl:
  16972         {
  16973             *npolicers = 5;
  16974             mode_attr->uncompressed_attr_selectors_v.\
  16975                       uncompressed_attr_bits_selector =
  16976                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  16977             table_offset[0] = pkt_res[CONTROL_PKT];
  16978             table_offset[1] = pkt_res[BPDU_PKT];
  16979             table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT];
  16980             table_offset[3] = pkt_res[KNOWN_L2UC_PKT];
  16981             table_offset[4] = pkt_res[KNOWN_L3UC_PKT];
  16982             table_offset[5] = pkt_res[KNOWN_L2MC_PKT];
  16983             table_offset[6] = pkt_res[UNKNOWN_L2MC_PKT];
  16984             table_offset[7] = pkt_res[L2BC_PKT];
  16985             table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT];
  16986             table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT];
  16987             table_offset[10] = pkt_res[KNOWN_IPMC_PKT];
  16988             value[2] = 1;
  16989             value[3] = 2;
  16990             value[4] = 2;
  16991             value[5] = 3;
  16992             value[6] = 3;
  16993             value[7] = 4;
  16994             value[8] = 1;
  16995             value[9] = 3;
  16996             value[10] = 3;
  16997             rv =  _bcm_esw_policer_set_offset_table_map(11, &table_offset[0],
  16998                       &value[0],
  16999                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17000             BCM_IF_ERROR_RETURN(rv);
  17001             break;
  17002         }
  17003         /* ***************************************************************** */
  17004          /* A dedicated policer for control, unknown unicast, known unicast,  */
  17005          /* multicast, broadcast and one for all traffic (not already policed)*/
  17006          /* 1) CONTROL_PKT|BPDU_PKT                                           */
  17007          /* 2) UNKNOWN_L3UC_PKT                                               */
  17008          /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                                */
  17009          /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT*/
  17010          /* 5) L2BC_PKT                                                       */
  17011          /* 6) UNKNOWN_PKT|L2DLF_PKT|UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT          */
  17012          /*    KNOWN_MPLS_PKT | KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|          */
  17013          /*    UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|UNKNOWN_MIM_PKT|                */
  17014          /*    KNOWN_MPLS_MULTICAST_PKT                                       */
  17015          /* ***************************************************************** */
  17016         case bcmPolicerGroupModeTypedAllWithControl:
  17017         {
  17018             *npolicers = 6;
  17019             mode_attr->uncompressed_attr_selectors_v.\
  17020                       uncompressed_attr_bits_selector =
  17021                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  17022             rv =  _bcm_esw_policer_set_offset_table_map_to_a_value(
  17023                       FP_RESOLUTION_MAX, 5,
  17024                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17025             BCM_IF_ERROR_RETURN(rv);
  17026             table_offset[0] = pkt_res[CONTROL_PKT];
  17027             table_offset[1] = pkt_res[BPDU_PKT];
  17028             table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT];
  17029             table_offset[3] = pkt_res[KNOWN_L2UC_PKT];
  17030             table_offset[4] = pkt_res[KNOWN_L3UC_PKT];
  17031             table_offset[5] = pkt_res[KNOWN_L2MC_PKT];
  17032             table_offset[6] = pkt_res[UNKNOWN_L2MC_PKT];
  17033             table_offset[7] = pkt_res[L2BC_PKT];
  17034             table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT];
  17035             table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT];
  17036             table_offset[10] = pkt_res[KNOWN_IPMC_PKT];
  17037             value[2] = 1;
  17038             value[3] = 2;
  17039             value[4] = 2;
  17040             value[5] = 3;
  17041             value[6] = 3;
  17042             value[7] = 4;
  17043             value[8] = 1;
  17044             value[9] = 3;
  17045             value[10] = 3;
  17046             rv =  _bcm_esw_policer_set_offset_table_map(11, &table_offset[0],
  17047                       &value[0],
  17048                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17049             BCM_IF_ERROR_RETURN(rv);
  17050             break;
  17051         }
  17052         /* ******************************************************** */
  17053         /* A set of 8(2^3) policers selected based on outer Vlan pri*/
  17054         /* outer_dot1p; 3 bits 1..8                                 */
  17055         /* ******************************************************** */
  17056 
  17057         case bcmPolicerGroupModeDot1P:
  17058         {
  17059             *npolicers = 8;
  17060             mode_attr->uncompressed_attr_selectors_v.\
  17061                       uncompressed_attr_bits_selector =
  17062                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS;
  17063             if (mapping == NULL) {
  17064                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17065                         *npolicers,
  17066                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17067             } else {
  17068                 for (i = 0; i < mapping->count; i++) {
  17069                     table_offset[i] = i;
  17070                     value[i] = *val;
  17071                     val++;
  17072                 }
  17073                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17074                                                             &table_offset[0],
  17075                                                             &value[0],
  17076                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17077             }
  17078 
  17079             BCM_IF_ERROR_RETURN(rv);
  17080             break;
  17081         }
  17082         /* ******************************************************** */
  17083         /* A set of 8(2^3) policers selected based on inner Vlan pri*/
  17084         /* inner_dot1p; 3 bits 1..8                                 */
  17085         /* ******************************************************** */
  17086 
  17087         case bcmPolicerGroupModeInnerDot1P:
  17088         {
  17089             *npolicers = 8;
  17090             mode_attr->uncompressed_attr_selectors_v.\
  17091                       uncompressed_attr_bits_selector =
  17092                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS;
  17093             if (mapping == NULL) {
  17094                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17095                        *npolicers,
  17096                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17097             } else {
  17098                 for (i = 0; i < mapping->count; i++) {
  17099                     table_offset[i] = i;
  17100                     value[i] = *val;
  17101                     val++;
  17102                 }
  17103                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17104                                                             &table_offset[0],
  17105                                                             &value[0],
  17106                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17107             }
  17108 
  17109             BCM_IF_ERROR_RETURN(rv);
  17110             break;
  17111         }
  17112         /* **************************************************** */
  17113         /* A set of 16(2^4) policers based on internal priority */
  17114         /* 1..16 INT_PRI bits: 4bits                            */
  17115         /* **************************************************** */
  17116         case bcmPolicerGroupModeIntPri:
  17117         {
  17118             *npolicers = 16;
  17119             mode_attr->uncompressed_attr_selectors_v.\
  17120                       uncompressed_attr_bits_selector =
  17121                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS;
  17122             if (mapping == NULL) {
  17123                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17124                         *npolicers,
  17125                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17126             } else {
  17127                 for (i = 0; i < mapping->count; i++) {
  17128                     table_offset[i] = i;
  17129                     value[i] = *val;
  17130                     val++;
  17131                 }
  17132                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17133                                                             &table_offset[0],
  17134                                                             &value[0],
  17135                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17136             }
  17137             BCM_IF_ERROR_RETURN(rv);
  17138             break;
  17139         }
  17140         /* ********************************************************** */
  17141         /* set of 64 policers(2^(4+2)) based on Internal priority+CNG */
  17142         /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits                    */
  17143         /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits                    */
  17144         /* ********************************************************** */
  17145         case bcmPolicerGroupModeIntPriCng:
  17146         {
  17147             *npolicers = 64;
  17148             mode_attr->uncompressed_attr_selectors_v.\
  17149                       uncompressed_attr_bits_selector =
  17150                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS |
  17151                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS;
  17152             if (mapping == NULL) {
  17153                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17154                        *npolicers,
  17155                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17156             } else {
  17157                 for (i = 0; i < mapping->count; i++) {
  17158                     table_offset[i] = i;
  17159                     value[i] = *val;
  17160                     val++;
  17161                 }
  17162                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17163                                                             &table_offset[0],
  17164                                                             &value[0],
  17165                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17166             }
  17167             BCM_IF_ERROR_RETURN(rv);
  17168             break;
  17169         }
  17170         /* ********************************************************** */
  17171         /* set of 8 policers(2^3) based on Internal priority          */
  17172         /* 1..8 INT_PRI bits: 3bits                                  */
  17173         /* ********************************************************** */
  17174         case bcmPolicerGroupModeShortIntPri:
  17175         {
  17176             *npolicers = 8;
  17177             mode_attr->uncompressed_attr_selectors_v.\
  17178                       uncompressed_attr_bits_selector =
  17179                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS;
  17180             if (mapping == NULL) {
  17181                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17182                       8,
  17183                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17184             } else {
  17185                 for (i = 0; i < mapping->count; i++) {
  17186                     table_offset[i] = i;
  17187                     value[i] = *val;
  17188                     val++;
  17189                 }
  17190                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17191                                                             &table_offset[0],
  17192                                                             &value[0],
  17193                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17194             }
  17195 
  17196             BCM_IF_ERROR_RETURN(rv);
  17197             break;
  17198         }
  17199          /* ****************************************** */
  17200          /* A set of 2 policers(2^1) based on SVP type */
  17201          /* 1..2 (SVP 1 bit). In case of KT2, SVP is 3 */
  17202          /* 3 bits and hence no of policers is 8       */
  17203          /* ********************************************/
  17204         case bcmPolicerGroupModeSvpType:
  17205         {
  17206             *npolicers = (1 << BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size);
  17207             mode_attr->uncompressed_attr_selectors_v.\
  17208                    uncompressed_attr_bits_selector =
  17209                      BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS;
  17210             if (mapping == NULL) {
  17211                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17212                        *npolicers,
  17213                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17214             } else {
  17215                 for (i = 0; i < mapping->count; i++) {
  17216                     table_offset[i] = i;
  17217                     value[i] = *val;
  17218                     val++;
  17219                 }
  17220                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17221                                 &table_offset[0], &value[0],
  17222                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17223             }
  17224             BCM_IF_ERROR_RETURN(rv);
  17225             break;
  17226         }
  17227 
  17228          /* ******************************************** */
  17229          /* A set of 64 policers(2^6) based on DSCP bits */
  17230          /* 1..64 (6 bits from TOS 8 bits)               */
  17231          /* ******************************************** */
  17232         case bcmPolicerGroupModeDscp:
  17233 
  17234         {
  17235             *npolicers = 64;
  17236             mode_attr->uncompressed_attr_selectors_v.\
  17237                         uncompressed_attr_bits_selector =
  17238                       BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS;
  17239             if (mapping == NULL) {
  17240                 rv =  _bcm_esw_policer_set_offset_table_map_to_increasing_value(
  17241                        *npolicers,
  17242                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17243             } else {
  17244                 for (i = 0; i < mapping->count; i++) {
  17245                     table_offset[i] = i;
  17246                     value[i] = *val;
  17247                     val++;
  17248                 }
  17249                 rv =  _bcm_esw_policer_set_offset_table_map(*npolicers,
  17250                                 &table_offset[0], &value[0],
  17251                       &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17252             }
  17253             BCM_IF_ERROR_RETURN(rv);
  17254             break;
  17255         }
  17256          /* ******************************************** */
  17257          /* A set of n policers based on user input */
  17258          /* ******************************************** */
  17259         case bcmPolicerGroupModeCascade:
  17260             if ((*npolicers > num_pools) || (*npolicers == 0 )) {
  17261                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17262                             (BSL_META_U(unit,
  17263                                         "Invalid number of Policers \n")));
  17264                 return BCM_E_PARAM;
  17265             }
  17266             *npolicers = 8;  /* Numbers of meters in a cascade chain is 8 */
  17267             *direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  17268             mode_attr->mode_type_v = cascade_mode;
  17269             mode_attr->uncompressed_attr_selectors_v.\
  17270                       uncompressed_attr_bits_selector =
  17271                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS;
  17272             if (mapping == NULL) {
  17273                 rv =  _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(
  17274                         unit, 0, *npolicers, 0,
  17275                         &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17276             } else {
  17277                 for (i = 0; i < mapping->count; i++) {
  17278                     table_offset[i] = i;
  17279                     value[i] = *val;
  17280                     val++;
  17281                 }
  17282                 rv =  _bcm_esw_policer_set_offset_table_map_flex_pool(
  17283                        unit, 0, *npolicers, &value[0] ,
  17284                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17285            }
  17286            BCM_IF_ERROR_RETURN(rv);
  17287            break;
  17288            /* ************************************************************* */
  17289            /* A set of n policers based on user input, with dropped packets */ 
  17290            /* not eligible for metering                                     */
  17291            /* ************************************************************* */
  17292         case bcmPolicerGroupModeCascadeDroppedPktExclude:
  17293            if ((*npolicers > num_pools) || (*npolicers == 0 )) {
  17294                LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17295                        (BSL_META_U(unit,
  17296                                    "Invalid number of Policers \n")));
  17297                return BCM_E_PARAM;
  17298            }
  17299            *npolicers = 8;  /* Numbers of meters in a cascade chain is 8 */
  17300            *direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  17301            mode_attr->mode_type_v = cascade_mode;
  17302            mode_attr->uncompressed_attr_selectors_v.\
  17303                uncompressed_attr_bits_selector =
  17304                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS |
  17305                BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS;
  17306            if (mapping == NULL) {
  17307                for (i = 0; i < *npolicers; i++) {
  17308                    table_offset[i] = i*2;
  17309                    value[i] = i;
  17310                }
  17311            } else {
  17312                for (i = 0; i < mapping->count; i++) {
  17313                    table_offset[i] = i*2;
  17314                    value[i] = *val;
  17315                    val++;
  17316                }
  17317            }
  17318            rv =  _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool(
  17319                                  unit, 0, *npolicers, &table_offset[0], &value[0],
  17320                             &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17321            BCM_IF_ERROR_RETURN(rv);
  17322            break;
  17323          /* ******************************************** */
  17324          /* A set of n policers based on user input based on IntPri*/
  17325          /* ******************************************** */
  17326         case bcmPolicerGroupModeIntPriCascade:
  17327         {
  17328             if ((*npolicers > num_pools) || (*npolicers == 0 )) {
  17329                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17330                             (BSL_META_U(unit,
  17331                                         "Invalid number of Policers \n")));
  17332                 return BCM_E_PARAM;
  17333             }
  17334             *npolicers = 8;  /* Numbers of meters in a cascade chain is 8 */
  17335             *direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  17336             mode_attr->mode_type_v = cascade_mode;
  17337             mode_attr->uncompressed_attr_selectors_v.\
  17338                       uncompressed_attr_bits_selector =
  17339                       BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS;
  17340             if (mapping == NULL) {
  17341                 rv =  _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(
  17342                           unit, 0, *npolicers, 0,
  17343                           &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17344             } else {
  17345                 for (i = 0; i < mapping->count; i++) {
  17346                     table_offset[i] = i;
  17347                     value[i] = *val;
  17348                     val++;
  17349                 }
  17350                 rv =  _bcm_esw_policer_set_offset_table_map_flex_pool(
  17351                        unit, 0, *npolicers, &value[0] ,
  17352                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17353             }
  17354 
  17355             BCM_IF_ERROR_RETURN(rv);
  17356             break;
  17357         }
  17358 
  17359          /* ******************************************** */
  17360          /* A set of n policers based on user input */
  17361          /* ******************************************** */
  17362         case bcmPolicerGroupModeCascadeWithCoupling:
  17363         {
  17364             if ((*npolicers > 0 ) &&
  17365                  ((*npolicers * 2) <= num_pools)) {
  17366                 *direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  17367                 *npolicers = 8; /* Allocate all the 8 policers */
  17368             } else {
  17369                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17370                             (BSL_META_U(unit,
  17371                                         "Invalid number of Policers \n")));
  17372                 return BCM_E_PARAM;
  17373             }
  17374             mode_attr->mode_type_v = cascade_mode;
  17375             mode_attr->uncompressed_attr_selectors_v.\
  17376                       uncompressed_attr_bits_selector =
  17377                   BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS;
  17378             if (mapping == NULL) {
  17379                 rv =  _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(
  17380                         unit, 1, *npolicers/2, 0,
  17381                         &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17382             } else {
  17383                 for (i = 0; i < mapping->count; i++) {
  17384                     table_offset[i] = i;
  17385                     value[i] = *val;
  17386                     val++;
  17387                 }
  17388                 rv =  _bcm_esw_policer_set_offset_table_map_flex_pool(
  17389                        unit, 1, *npolicers/2, &value[0] ,
  17390                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17391             }
  17392 
  17393             BCM_IF_ERROR_RETURN(rv);
  17394             break;
  17395         }
  17396          /* ******************************************** */
  17397          /* A set of n policers based on user input */
  17398          /* ******************************************** */
  17399         case bcmPolicerGroupModeIntPriCascadeWithCoupling:
  17400         {
  17401             if ((*npolicers > 0 ) &&
  17402                  ((*npolicers * 2) <= num_pools)) {
  17403                 *direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  17404                 *npolicers = 8;
  17405             } else {
  17406                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17407                             (BSL_META_U(unit,
  17408                                         "Invalid number of Policers \n")));
  17409                 return BCM_E_PARAM;
  17410             }
  17411             mode_attr->mode_type_v = cascade_mode;
  17412             mode_attr->uncompressed_attr_selectors_v.\
  17413                       uncompressed_attr_bits_selector =
  17414                       BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS;
  17415             if (mapping == NULL) {
  17416                 rv =  _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(
  17417                         unit, 1, *npolicers/2, 0,
  17418                         &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17419             } else {
  17420                 for (i = 0; i < mapping->count; i++) {
  17421                     table_offset[i] = i;
  17422                     value[i] = *val;
  17423                     val++;
  17424                 }
  17425                 rv =  _bcm_esw_policer_set_offset_table_map_flex_pool(
  17426                        unit, 1, *npolicers/2, &value[0] ,
  17427                        &mode_attr->uncompressed_attr_selectors_v.offset_map[0]);
  17428             }
  17429 
  17430             BCM_IF_ERROR_RETURN(rv);
  17431             break;
  17432         }
  17433 
  17434          /* ************************************************************** */
  17435          /* N+1 policers where in the base counter is used for dlf and next N */
  17436          /* are used as per Cos                                            */
  17437          /* 1) L2_DLF(UNKNOWN_L2UC_PKT)                                    */
  17438          /* 2..17) INT_PRI bits: 4bits                                     */
  17439          /* ************************************************************** */
  17440         case bcmPolicerGroupModeDlfIntPri:
  17441         {
  17442             *npolicers = 17;
  17443             mode_attr->mode_type_v = compressed_mode;
  17444             pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v;
  17445             pkt_attr->pkt_resolution = 1;
  17446             pkt_attr->int_pri = 4;
  17447 
  17448             /* Reset pkt_resolution map */
  17449             pkt_res_map =  &mode_attr->compressed_attr_selectors_v.\
  17450                                              compressed_pkt_res_attr_map_v[0];
  17451             index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm);
  17452             for (map_index = 0; map_index <= index_max; map_index++) {
  17453                 pkt_res_map[map_index] = 0;
  17454             }
  17455             /* set pkt_resoltion map for DLF to 1.
  17456              * PKT_RES_MAPm == [ pkt_res | svp_type | drop ]
  17457              * So, Don't care for bits corresponding to svp_type and drop */
  17458             shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1;
  17459             no_entries_to_populate = (1 << shift_bits);
  17460 
  17461             for (offset = 0; offset < no_entries_to_populate; offset++) {
  17462                 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + \
  17463                                                       offset] = 1 << shift_bits;
  17464             }
  17465             /* Reset pri_cnf map */
  17466             pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\
  17467                                              compressed_pri_cnf_attr_map_v[0];
  17468             index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm);
  17469             for (map_index = 0; map_index <= index_max; map_index++) {
  17470                pri_cnf_map[map_index] = 0;
  17471             }
  17472             /* set pri_cnf map for  16 policers */
  17473             for (offset = 0; offset < 4; offset++) {
  17474                 for (map_index = 0; map_index < 16; map_index++) {
  17475                     pri_cnf_map[offset << 4 | map_index] = map_index;
  17476                 }
  17477             }
  17478 
  17479             /* Reset all Offset table fields */
  17480             offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0];
  17481             for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256;
  17482                                                                 map_index++) {
  17483                 offset_map[map_index].offset = 0;
  17484                 offset_map[map_index].meter_enable = 0;
  17485             }
  17486              /* Set DLF policer indexes considering INT_PRI bits don't care */
  17487             for(map_index = 0; map_index < 16; map_index++) {
  17488                 offset_map[(map_index << 1) | 1].offset = 0;
  17489                 offset_map[(map_index << 1) | 1].meter_enable = 1;
  17490             }
  17491             /* Set Int pri policer indexes considering DLF=0 */
  17492             for(map_index = 0; map_index < 16; map_index++) {
  17493                 offset_map[map_index << 1].offset = map_index + 1;
  17494                 offset_map[map_index << 1].meter_enable = 1;
  17495             }
  17496             break;
  17497         }
  17498          /* *************************************************************** */
  17499          /* A dedicated policer for unknown unicast, known unicast,         */
  17500          /* multicast,broadcast and N internal priority policers for traffic*/
  17501          /* (not already policed)                                           */
  17502          /* 1) UNKNOWN_L3UC_PKT                                             */
  17503          /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT                              */
  17504          /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                              */
  17505          /* 4) L2BC_PKT                                                     */
  17506          /* 5..20) INT_PRI bits: 4bits                                      */
  17507          /* *************************************************************** */
  17508         case bcmPolicerGroupModeTypedIntPri:
  17509         {
  17510             *npolicers = 20;
  17511             mode_attr->mode_type_v = compressed_mode;
  17512             pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v;
  17513             pkt_attr->pkt_resolution = 3;
  17514             pkt_attr->int_pri = 4;
  17515             /* Reset pkt_resolution map */
  17516             pkt_res_map =  &mode_attr->compressed_attr_selectors_v.\
  17517                                              compressed_pkt_res_attr_map_v[0];
  17518             index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm);
  17519             for (map_index = 0; map_index <= index_max; map_index++) {
  17520                 pkt_res_map[map_index] = 0;
  17521             }
  17522             /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ]
  17523              * So, Don't care for bits corresponding to svp_type and drop */
  17524             shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1;
  17525             no_entries_to_populate = (1 << shift_bits);
  17526 
  17527             for (offset = 0; offset < no_entries_to_populate; offset++) {
  17528                 pkt_res_map[(pkt_res[UNKNOWN_L3UC_PKT] << shift_bits) + offset]
  17529                                                               = 1 << shift_bits;
  17530                 pkt_res_map[(pkt_res[KNOWN_L2UC_PKT] << shift_bits) + offset]
  17531                                                               = 2 << shift_bits;
  17532                 pkt_res_map[(pkt_res[KNOWN_L3UC_PKT] << shift_bits) + offset]
  17533                                                               = 2 << shift_bits;
  17534                 pkt_res_map[(pkt_res[KNOWN_L2MC_PKT] << shift_bits) + offset]
  17535                                                               = 3 << shift_bits;
  17536                 pkt_res_map[(pkt_res[UNKNOWN_L2MC_PKT] << shift_bits) + offset]
  17537                                                               = 3 << shift_bits;
  17538                 pkt_res_map[(pkt_res[L2BC_PKT] << shift_bits) + offset]
  17539                                                               = 4 << shift_bits;
  17540                 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + offset]
  17541                                                               = 1 << shift_bits;
  17542             }
  17543             /* Reset pri_cng map */
  17544             pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\
  17545                                              compressed_pri_cnf_attr_map_v[0];
  17546             index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm);
  17547             for (map_index = 0; map_index <= index_max; map_index++) {
  17548                 pri_cnf_map[map_index] = 0;
  17549             }
  17550             /* set pri_cnf map for  16 policers */
  17551             for (map_index = 0; map_index < 16; map_index++) {
  17552                 pri_cnf_map[map_index] = map_index;
  17553             }
  17554 
  17555             /* Reset all Offset table fields */
  17556             offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0];
  17557             for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256;
  17558                                                                 map_index++) {
  17559                 offset_map[map_index].offset = 0;
  17560                 offset_map[map_index].meter_enable = 0;
  17561             }
  17562             /* Set Int pri policer indexes considering Type fields = 0 */
  17563             for(map_index = 0; map_index < 16; map_index++) {
  17564                 for(type = 0; type < 8; type++) {
  17565                    offset_map[type + (8 * map_index)].offset = map_index + 4;
  17566                    offset_map[type + (8 * map_index)].meter_enable = 1;
  17567                }
  17568             }
  17569              /* Set Type based indexes considering INT_PRI bits don't care */
  17570             for(type = 0; type < 4; type++) {
  17571                 for(map_index = 0; map_index < 16; map_index++) {
  17572                     offset_map[(map_index << 3) | (type + 1)].offset = type;
  17573                     offset_map[(map_index << 3) | (type + 1)].meter_enable = 1;
  17574                 }
  17575             }
  17576             break;
  17577         }
  17578          /* ************************************************************* */
  17579          /* N+2 policers where the base policers is used for control, the  */
  17580          /* next one for dlf and next N are used per Cos                  */
  17581          /* 1) CONTROL_PKT|BPDU_PKT                                       */
  17582          /* 2) L2_DLF                                                     */
  17583          /* 3..18) INT_PRI bits: 4bits                                    */
  17584          /* ************************************************************* */
  17585         case bcmPolicerGroupModeDlfIntPriWithControl:
  17586         {
  17587             *npolicers = 18;
  17588             mode_attr->mode_type_v = compressed_mode;
  17589             pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v;
  17590             pkt_attr->pkt_resolution = 2;
  17591             pkt_attr->int_pri = 4;
  17592             /* Reset pkt_resolution map */
  17593             pkt_res_map =  &mode_attr->compressed_attr_selectors_v.\
  17594                                              compressed_pkt_res_attr_map_v[0];
  17595             index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm);
  17596             for (map_index = 0; map_index <= index_max; map_index++) {
  17597                 pkt_res_map[map_index] = 0;
  17598             }
  17599             /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ]
  17600              * So, Don't care for bits corresponding to svp_type and drop */
  17601             shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1;
  17602             no_entries_to_populate = (1 << shift_bits);
  17603 
  17604             /* set pkt_resolution map */
  17605             for (offset = 0; offset < no_entries_to_populate; offset++) {
  17606                 pkt_res_map[(pkt_res[CONTROL_PKT] << shift_bits) + offset]
  17607                                                            = 1 << shift_bits;
  17608                 pkt_res_map[(pkt_res[BPDU_PKT] << shift_bits) + offset]
  17609                                                            = 1 << shift_bits;
  17610                 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + offset]
  17611                                                            = 2 << shift_bits;
  17612             }
  17613             /* Reset pri_cng map */
  17614             pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\
  17615                                              compressed_pri_cnf_attr_map_v[0];
  17616             index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm);
  17617             for (map_index = 0; map_index <= index_max; map_index++) {
  17618                 pri_cnf_map[map_index] = 0;
  17619             }
  17620             /* set pri_cnf map for 16 policers */
  17621             for (map_index = 0; map_index < 16; map_index++) {
  17622                 pri_cnf_map[map_index] = map_index;
  17623             }
  17624 
  17625             /* Reset all Offset table fields */
  17626             offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0];
  17627             for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256;
  17628                                                                 map_index++) {
  17629                 offset_map[map_index].offset = 0;
  17630                 offset_map[map_index].meter_enable = 0;
  17631             }
  17632             /* Set Int pri policer indexes considering Type fields = 0 */
  17633             for(map_index = 0; map_index < 16; map_index++) {
  17634                for(type = 0; type < 4; type++) {
  17635                    offset_map[type + (4 * map_index)].offset = map_index + 2;
  17636                    offset_map[type + (4 * map_index)].meter_enable = 1;
  17637                }
  17638             }
  17639              /* Set Type based indexes considering INT_PRI bits don't care */
  17640             for(type = 0; type < 2; type++) {
  17641                 for(map_index = 0; map_index < 16; map_index++) {
  17642                     offset_map[(map_index << 2) | (type + 1)].offset = type;
  17643                     offset_map[(map_index << 2) | (type + 1)].meter_enable = 1;
  17644                 }
  17645             }
  17646             break;
  17647         }
  17648         /* *************************************************************** */
  17649          /* A dedicated counter for control, unknown unicast, known unicast */
  17650          /* , multicast, broadcast and N internal priority counters for     */
  17651          /* traffic (not already counted)                                   */
  17652          /* 1) CONTROL_PKT|BPDU_PKT                                         */
  17653          /* 2) UNKNOWN_L3UC_PKT                                             */
  17654          /* 3) L2UC_PKT | KNOWN_L3UC_PKT                                    */
  17655          /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT                              */
  17656          /* 5) L2BC_PKT                                                     */
  17657          /* 6..21) INT_PRI bits: 4bits                                      */
  17658          /* *************************************************************** */
  17659         case bcmPolicerGroupModeTypedIntPriWithControl:
  17660         {
  17661             *npolicers = 21;
  17662             mode_attr->mode_type_v = compressed_mode;
  17663             pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v;
  17664             pkt_attr->pkt_resolution = 3;
  17665             pkt_attr->int_pri = 4;
  17666             /* Reset pkt_resolution map */
  17667             pkt_res_map =  &mode_attr->compressed_attr_selectors_v.\
  17668                                              compressed_pkt_res_attr_map_v[0];
  17669             index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm);
  17670             for (map_index = 0; map_index <= index_max; map_index++) {
  17671                 pkt_res_map[map_index] = 0;
  17672             }
  17673             /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ]
  17674              * So, Don't care for bits corresponding to svp_type and drop */
  17675             shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1;
  17676             no_entries_to_populate = (1 << shift_bits);
  17677 
  17678             /* set pkt_resolution map */
  17679             for (offset = 0; offset < no_entries_to_populate; offset++) {
  17680                 pkt_res_map[(pkt_res[CONTROL_PKT] << shift_bits) + offset]
  17681                                                              = 1 << shift_bits;
  17682                 pkt_res_map[(pkt_res[BPDU_PKT] << shift_bits) + offset]
  17683                                                              = 1 << shift_bits;
  17684                 pkt_res_map[(pkt_res[UNKNOWN_L3UC_PKT] << shift_bits)+ offset]
  17685                                                              = 2 << shift_bits;
  17686                 pkt_res_map[(pkt_res[KNOWN_L2UC_PKT] << shift_bits) + offset]
  17687                                                              = 3 << shift_bits;
  17688                 pkt_res_map[(pkt_res[KNOWN_L3UC_PKT] << shift_bits) + offset]
  17689                                                              = 3 << shift_bits;
  17690                 pkt_res_map[(pkt_res[KNOWN_L2MC_PKT] << shift_bits) + offset]
  17691                                                              = 4 << shift_bits;
  17692                 pkt_res_map[(pkt_res[UNKNOWN_L2MC_PKT] << shift_bits) + offset]
  17693                                                              = 4 << shift_bits;
  17694                 pkt_res_map[(pkt_res[L2BC_PKT] << shift_bits) + offset]
  17695                                                              = 5 << shift_bits;
  17696                 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits)+ offset]
  17697                                                              = 2 << shift_bits;
  17698             }
  17699             /* Reset pri_cnf map */
  17700             pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\
  17701                                              compressed_pri_cnf_attr_map_v[0];
  17702             index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm);
  17703             for (map_index = 0; map_index <= index_max; map_index++) {
  17704                 pri_cnf_map[map_index] = 0;
  17705             }
  17706             /* set pri_cnf map for  16 policers */
  17707             for (map_index = 0; map_index < 16; map_index++) {
  17708                 pri_cnf_map[map_index] = map_index;
  17709             }
  17710 
  17711             /* Reset all Offset table fields */
  17712             offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0];
  17713             for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256;
  17714                                                                 map_index++) {
  17715                 offset_map[map_index].offset = 0;
  17716                 offset_map[map_index].meter_enable = 0;
  17717             }
  17718             /* Set Int pri policer indexes considering Type fields = 0 */
  17719             for(map_index = 0; map_index < 16; map_index++) {
  17720                 for(type = 0; type < 8; type++) {
  17721                     offset_map[type + (8 * map_index)].offset = map_index + 5;
  17722                     offset_map[type + (8 * map_index)].meter_enable = 1;
  17723                 }
  17724             }
  17725              /* Set Type based indexes considering INT_PRI bits don't care */
  17726             for(type = 0; type < 5; type++) {
  17727                 for(map_index = 0; map_index < 16; map_index++) {
  17728                     offset_map[(map_index << 3) | (type + 1)].offset = type;
  17729                     offset_map[(map_index << 3) | (type + 1)].meter_enable = 1;
  17730                 }
  17731             }
  17732             break;
  17733         }
  17734 
  17735         default:
  17736             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17737                         (BSL_META_U(unit,
  17738                                     "Invalid policer group mode\n")));
  17739             return BCM_E_PARAM;
  17740 
  17741     }
  17742     return rv;
  17743 }
  17744 
  17745 /*
  17746  * Function:
  17747  *      _bcm_esw_policer_group_create
  17748  * Purpose:
  17749  *      Create a group of policers based on the mode.
  17750  * Parameters:
  17751  *     unit                  - (IN) unit number
  17752  *     mode                  - (IN) Policer group mode
  17753  *     flow_info             - (IN) Information regarding flow type and skip pool
  17754  *     offset_map            - (IN) Attr_value to policer_offset mapping
  17755  *     policer_id            - (OUT) Base policer id
  17756  *     npolicers             - (OUT) Number of policers
  17757  * Returns:
  17758  *     BCM_E_XXX
  17759  */
  17760 int _bcm_esw_policer_group_create(int unit, bcm_policer_group_mode_t mode,
  17761                                    _bcm_policer_flow_info_t *flow_info,
  17762                                    bcm_policer_map_t *offset_map,
  17763                                    bcm_policer_t *policer_id, int *npolicers)
  17764 {
  17765     int rv = BCM_E_NONE;
  17766     uint32 direction = 0;
  17767     int index = 0;
  17768     bcm_policer_svc_meter_mode_t offset_mode = 0;
  17769     uint8 pid_offset[BCM_POLICER_GLOBAL_METER_MAX_POOL] = {0};
  17770     _global_meter_policer_control_t *policer_control = NULL;
  17771     bcm_policer_svc_meter_attr_t *mode_attr = NULL;
  17772     int offset_mask = 0;
  17773 
  17774     if (!soc_feature(unit, soc_feature_global_meter)) {
  17775         return BCM_E_UNAVAIL;
  17776     }
  17777     if (soc_feature(unit, soc_feature_global_meter_compaction_support)) {
  17778         return BCM_E_UNAVAIL;
  17779     }
  17780 
  17781     mode_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t),"meter mode attr");
  17782     if ( mode_attr == NULL) {
  17783         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17784                     (BSL_META_U(unit,
  17785                                 "Failed to allocate memory for svc meter attr \n")));
  17786         return BCM_E_MEMORY;
  17787     }
  17788     sal_memset(mode_attr, 0, sizeof(bcm_policer_svc_meter_attr_t));
  17789 
  17790     direction = GLOBAL_METER_ALLOC_VERTICAL;
  17791 
  17792     rv = _bcm_esw_policer_group_set_mode_and_map(unit, mode, npolicers, offset_map,
  17793                                                   &direction, mode_attr);
  17794     if (!(BCM_SUCCESS(rv))) {
  17795         sal_free(mode_attr);
  17796         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17797                     (BSL_META_U(unit,
  17798                                 "Failed to set mode and map\n")));
  17799         return rv;
  17800     }
  17801 
  17802     GLOBAL_METER_LOCK(unit);
  17803 
  17804     if (((direction == GLOBAL_METER_ALLOC_VERTICAL) && (*npolicers > 1)) ||
  17805         ((direction == GLOBAL_METER_ALLOC_HORIZONTAL))) {
  17806         rv = _bcm_esw_policer_svc_meter_create_mode(unit, mode_attr, mode,
  17807                                         -1, *npolicers, NULL, &offset_mode);
  17808         if (BCM_FAILURE(rv) && (rv != BCM_E_EXISTS)) {
  17809             GLOBAL_METER_UNLOCK(unit);
  17810             sal_free(mode_attr);
  17811             return rv;
  17812         } else {
  17813              global_meter_offset_mode[unit][offset_mode].no_of_policers =
  17814                                                                *npolicers;
  17815         }
  17816     }
  17817     sal_free(mode_attr);
  17818     rv = _global_meter_policer_id_alloc(unit, direction, npolicers,
  17819                             policer_id, flow_info, &pid_offset[0]);
  17820     if (!(BCM_SUCCESS(rv))) {
  17821         GLOBAL_METER_UNLOCK(unit);
  17822         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17823                     (BSL_META_U(unit,
  17824                                 "Failed to allocate policer\n")));
  17825         return rv;
  17826     }
  17827     offset_mask = SOC_INFO(unit).global_meter_max_size_of_pool - 1;
  17828 
  17829     /* Allocate policer descriptor. */
  17830     _GLOBAL_METER_XGS3_ALLOC(policer_control,
  17831              sizeof (_global_meter_policer_control_t), "Global meter policer");
  17832     if (NULL == policer_control) {
  17833         _bcm_global_meter_free_allocated_policer_on_error(unit, *npolicers,
  17834                              &pid_offset[0], (*policer_id & offset_mask));
  17835         GLOBAL_METER_UNLOCK(unit);
  17836         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  17837                     (BSL_META_U(unit,
  17838                                 "Unable to allocate memeory for policer control \n")));
  17839         return (BCM_E_MEMORY);
  17840     }
  17841 
  17842     /* Add mode info to the policer index */
  17843     *policer_id |= (offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT;
  17844 
  17845     /* Set policer configuration */
  17846     policer_control->direction = direction;
  17847     policer_control->pid = *policer_id;
  17848     policer_control->grp_mode = mode;
  17849     policer_control->no_of_policers =  *npolicers;
  17850 
  17851     if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  17852         index = 0;
  17853         do {
  17854             policer_control->offset[index] = pid_offset[index];
  17855             index++;
  17856         } while (index < (*npolicers));
  17857 
  17858         if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  17859             rv = _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw(unit,
  17860                                *npolicers, *policer_id, mode, &pid_offset[0]);
  17861         } else {
  17862             rv = _bcm_esw_global_meter_set_cascade_info_to_hw(unit,
  17863                                *npolicers, *policer_id, mode, &pid_offset[0]);
  17864         }
  17865         if (!(BCM_SUCCESS(rv))) {
  17866             /* free all the allocated policers */
  17867             _bcm_global_meter_free_allocated_policer_on_error(unit, *npolicers,
  17868                              &pid_offset[0], (*policer_id & offset_mask));
  17869             /* De-allocate policer descriptor. */
  17870             sal_free(policer_control);
  17871             GLOBAL_METER_UNLOCK(unit);
  17872             return rv;
  17873         }
  17874     }
  17875     if ((mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  17876         (mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  17877         *npolicers = *npolicers / 2;
  17878     }
  17879     /* increment mode reference count for new policer  */
  17880     if (offset_mode) {
  17881         rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, offset_mode);
  17882         if (!(BCM_SUCCESS(rv))) {
  17883             /* free all the allocated policers */
  17884             _bcm_global_meter_free_allocated_policer_on_error(unit,*npolicers,
  17885                              &pid_offset[0], (*policer_id & offset_mask));
  17886             /* De-allocate policer descriptor. */
  17887             sal_free(policer_control);
  17888             GLOBAL_METER_UNLOCK(unit);
  17889             return rv;
  17890         }
  17891     }
  17892 
  17893 
  17894     /* Insert policer into policers hash. */
  17895     _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit],
  17896                               policer_control,
  17897                               (*policer_id & _GLOBAL_METER_HASH_MASK));
  17898 
  17899     GLOBAL_METER_UNLOCK(unit);
  17900     LOG_DEBUG(BSL_LS_BCM_POLICER,
  17901               (BSL_META_U(unit,
  17902                           "create policer with id %x\n"),
  17903                *policer_id));
  17904 
  17905     return rv;
  17906 }
  17907 
  17908 /*
  17909  * Function:
  17910  *      bcm_esw_policer_envelop_create
  17911  * Purpose:
  17912  *      Create a single policer in Envelop mode. The policer created is
  17913  *      micro or a macro meter depending on the configuration.
  17914  * Parameters:
  17915  *     unit                  - (IN) unit number
  17916  *     flags                 - (IN) Indicates micro/macro flow policer
  17917  *     macro_flow_policer_id - (IN) macro flow policer id
  17918  *     policer_id            - (OUT) policer Id
  17919  * Returns:
  17920  *     BCM_E_XXX
  17921  */
  17922 int bcm_esw_policer_envelop_create(int unit, uint32 flags,
  17923                                    bcm_policer_t macro_flow_policer_id,
  17924                                    bcm_policer_t *policer_id)
  17925 {
  17926     int rv = BCM_E_NONE;
  17927     int index = 0;
  17928     int micro_flow_index = 0;
  17929     int pool = 0;
  17930     int numbers = 1;
  17931     svm_macroflow_index_table_entry_t macro_flow_entry;
  17932     int size_pool = 0, num_pools = 0;
  17933     int pool_mask = 0, pool_offset = 0;
  17934     _bcm_policer_flow_info_t flow_info;
  17935     int bank_size = 0, num_banks_per_pool = 1;
  17936 
  17937 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  17938     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  17939         return bcmi_esw_policer_envelop_create(unit,
  17940               flags, macro_flow_policer_id, policer_id);
  17941     }
  17942 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  17943 
  17944     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  17945     num_pools =  SOC_INFO(unit).global_meter_pools;
  17946     pool_offset = _shr_popcount(size_pool - 1);
  17947     pool_mask = (num_pools - 1) << pool_offset;
  17948     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  17949     bank_size = size_pool / num_banks_per_pool;
  17950 
  17951     _bcm_policer_flow_info_t_init(&flow_info);
  17952     if (flags == BCM_POLICER_GLOBAL_METER_ENVELOP_MACRO_FLOW) {
  17953         flow_info.flow_type = bcmPolicerFlowTypeMacro;
  17954         rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle,
  17955                    &flow_info, NULL, policer_id, &numbers);
  17956         if (!(BCM_SUCCESS(rv))) {
  17957             LOG_DEBUG(BSL_LS_BCM_POLICER,
  17958                       (BSL_META_U(unit,
  17959                                   "Unable to create macro flow policer\n")));
  17960             return rv;
  17961         }
  17962     } else if (flags == BCM_POLICER_GLOBAL_METER_ENVELOP_MICRO_FLOW) {
  17963         /* validate macroflow policer id */
  17964         rv = _bcm_esw_policer_validate(unit, &macro_flow_policer_id);
  17965         if (!(BCM_SUCCESS(rv))) {
  17966             LOG_DEBUG(BSL_LS_BCM_POLICER,
  17967                       (BSL_META_U(unit,
  17968                                   "Invalid policer Id passed\n")));
  17969             return rv;
  17970         }
  17971         rv = _bcm_esw_get_policer_table_index(unit, macro_flow_policer_id,
  17972                                                                    &index);
  17973         if (!(BCM_SUCCESS(rv))) {
  17974             LOG_DEBUG(BSL_LS_BCM_POLICER,
  17975                       (BSL_META_U(unit,
  17976                                   "Unable to Get policer index for macro flow "
  17977                                   "policer \n")));
  17978             return rv;
  17979         }
  17980         pool = (macro_flow_policer_id & pool_mask) >> pool_offset;
  17981         flow_info.flow_type = bcmPolicerFlowTypeMicro;
  17982         flow_info.skip_pool = pool;
  17983         flow_info.skip_bank = (macro_flow_policer_id & (size_pool - 1)) / bank_size;
  17984         rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle, &flow_info,
  17985                                                 NULL, policer_id, &numbers);
  17986         if (!(BCM_SUCCESS(rv))) {
  17987             LOG_DEBUG(BSL_LS_BCM_POLICER,
  17988                       (BSL_META_U(unit,
  17989                                   "Unable to create micro flow policer\n")));
  17990             return rv;
  17991         }
  17992         rv = _bcm_esw_policer_increment_ref_count(unit, macro_flow_policer_id);
  17993         if (!(BCM_SUCCESS(rv))) {
  17994             LOG_DEBUG(BSL_LS_BCM_POLICER,
  17995                       (BSL_META_U(unit,
  17996                                   "Unable to increment ref count for  micro flow "
  17997                                   "policer\n")));
  17998             return rv;
  17999         }
  18000         /*  get the HW index for the micro flow policer created */
  18001         rv = _bcm_esw_get_policer_table_index(unit, *policer_id,
  18002                                                            &micro_flow_index);
  18003         if (!(BCM_SUCCESS(rv))) {
  18004             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18005                       (BSL_META_U(unit,
  18006                                   "Unable to Get policer index for micro flow "
  18007                                   "policer \n")));
  18008             return rv;
  18009         }
  18010         /* Write the index of the macro-meter at "micro_flow_index" location
  18011            of SVM_MACROFLOW_INDEX_TABLE */
  18012         rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  18013                                          micro_flow_index, &macro_flow_entry);
  18014         if (!(BCM_SUCCESS(rv))) {
  18015             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18016                         (BSL_META_U(unit,
  18017                                     "Unable to access macro flow table at the index "
  18018                                     "provided\n")));
  18019             return rv;
  18020         }
  18021         if (SOC_MEM_FIELD_VALID(unit, SVM_MACROFLOW_INDEX_TABLEm,
  18022                                                            MACROFLOW_INDEXf)) {
  18023             soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, &macro_flow_entry,
  18024                                            MACROFLOW_INDEXf, (uint32 *)&index);
  18025         }
  18026         rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY,
  18027                                           micro_flow_index, &macro_flow_entry);
  18028         if (!(BCM_SUCCESS(rv))) {
  18029             LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18030                         (BSL_META_U(unit,
  18031                                     "Unable to write to macro flow table at index "
  18032                                     "provided\n")));
  18033             return rv;
  18034         }
  18035     } else {
  18036         LOG_ERROR(BSL_LS_BCM_POLICER,
  18037                   (BSL_META_U(unit,
  18038                               "Invalid flag passed \n")));
  18039         return BCM_E_PARAM;
  18040     }
  18041     return rv;
  18042 }
  18043 
  18044 /*
  18045  * Function:
  18046  *      bcm_esw_policer_group_create
  18047  * Purpose:
  18048  *      Create a group of policers based on the mode.
  18049  * Parameters:
  18050  *     unit                  - (IN) unit number
  18051  *     mode                  - (IN) policer group mode
  18052  *     policer_id            - (OUT)Base policer Id
  18053  *     npolicers             - (OUT) Number of policers created
  18054  * Returns:
  18055  *     BCM_E_XXX
  18056  */
  18057 int bcm_esw_policer_group_create(int unit, bcm_policer_group_mode_t mode,
  18058                                    bcm_policer_t *policer_id, int *npolicers)
  18059 {
  18060     int rv = BCM_E_NONE;
  18061     int num_pools = 0;
  18062     _bcm_policer_flow_info_t flow_info;
  18063     num_pools =  SOC_INFO(unit).global_meter_pools;
  18064 
  18065     _bcm_policer_flow_info_t_init(&flow_info);
  18066     flow_info.flow_type = bcmPolicerFlowTypeNormal;
  18067     flow_info.skip_pool = num_pools;
  18068 
  18069 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  18070     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  18071         rv = bcmi_esw_policer_group_create(unit, mode, &flow_info, NULL,
  18072                 policer_id, npolicers);
  18073     } else
  18074 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  18075     {
  18076         rv = _bcm_esw_policer_group_create(unit, mode, &flow_info, NULL,
  18077                 policer_id, npolicers);
  18078     }
  18079     if (BCM_FAILURE(rv)) {
  18080         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18081                     (BSL_META_U(unit,
  18082                                 "Unable to create policer with "
  18083                                 "given mode(%d)\n"),
  18084                      mode));
  18085         return (rv);
  18086     }
  18087     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18088                 (BSL_META_U(unit,
  18089                             "Created policer group of %d with base policer %x \n"),
  18090                  *npolicers, *policer_id));
  18091     return rv;
  18092 }
  18093 
  18094 /*
  18095  * Function:
  18096  *      bcm_esw_policer_group_create
  18097  * Purpose:
  18098  *      Create a group of policers based on the mode.
  18099  * Parameters:
  18100  *     unit                  - (IN) unit number
  18101  *     mode                  - (IN) policer group mode
  18102  *     policer_id            - (OUT)Base policer Id
  18103  *     npolicers             - (OUT) Number of policers created
  18104  * Returns:
  18105  *     BCM_E_XXX
  18106  */
  18107 int bcm_esw_policer_group_create_with_map(int unit,
  18108                                           bcm_policer_group_mode_t mode,
  18109                                           bcm_policer_map_t *offset_map,
  18110                                           bcm_policer_t *policer_id,
  18111                                           int *num_policers)
  18112 {
  18113     int rv = BCM_E_NONE;
  18114     int num_pools = 0;
  18115     _bcm_policer_flow_info_t flow_info;
  18116     num_pools =  SOC_INFO(unit).global_meter_pools;
  18117 
  18118     _bcm_policer_flow_info_t_init(&flow_info);
  18119     flow_info.flow_type = bcmPolicerFlowTypeNormal;
  18120     flow_info.skip_pool = num_pools;
  18121 
  18122 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  18123     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  18124         rv = bcmi_esw_policer_group_create(unit, mode, &flow_info, offset_map,
  18125                 policer_id, num_policers);
  18126     } else
  18127 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  18128     {
  18129         rv = _bcm_esw_policer_group_create(unit, mode, &flow_info, offset_map,
  18130                 policer_id, num_policers);
  18131     }
  18132 
  18133     if (BCM_FAILURE(rv)) {
  18134         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18135                     (BSL_META_U(unit,
  18136                                 "Unable to create policer for given mode %d \n"),
  18137                      mode));
  18138         return (rv);
  18139     }
  18140     LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18141                 (BSL_META_U(unit,
  18142                             "Created policer group of %d with base policer %x \n"),
  18143                  *num_policers, *policer_id));
  18144     return rv;
  18145 }
  18146 
  18147 /*
  18148  * Function:
  18149  *      bcm_esw_policer_envelop_group_create
  18150  * Purpose:
  18151  *      Create a group of policers based on the mode.
  18152  * Parameters:
  18153  *     unit                  - (IN) unit number
  18154  *     flags                 - (IN) Indicates micro/macro flow policer
  18155  *     mode                  - (IN) policer group mode
  18156  *     macro_flow_policer_id - (IN) macro flow policer id
  18157  *     policer_id            - (OUT)Base policer Id
  18158  *     npolicers             - (OUT) Number of policers created
  18159  * Returns:
  18160  *     BCM_E_XXX
  18161  */
  18162 int bcm_esw_policer_envelop_group_create(int unit, uint32 flag,
  18163                                      bcm_policer_group_mode_t mode,
  18164                                      bcm_policer_t macro_flow_policer_id,
  18165                                      bcm_policer_t *policer_id,
  18166                                      int *npolicers)
  18167 {
  18168     int rv = BCM_E_NONE;
  18169     int index = 0;
  18170     int micro_flow_index = 0;
  18171     int pool = 0;
  18172     int numbers = 1;
  18173     int size_pool = 0, num_pools = 0;
  18174     int pool_mask = 0, pool_offset = 0;
  18175     svm_macroflow_index_table_entry_t   *buf;
  18176     svm_macroflow_index_table_entry_t   *entry;
  18177     int entry_mem_size;    /* Size of table entry. */
  18178     int entry_index = 0;
  18179     int entry_index_max = 0;
  18180     _bcm_policer_flow_info_t flow_info;
  18181     int bank_size, num_banks_per_pool = 1;
  18182 
  18183 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  18184     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  18185         return bcmi_esw_policer_envelop_group_create(unit,
  18186             flag, mode, macro_flow_policer_id, policer_id, npolicers);
  18187     }
  18188 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  18189 
  18190     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  18191     num_pools =  SOC_INFO(unit).global_meter_pools;
  18192     pool_offset = _shr_popcount(size_pool - 1);
  18193     pool_mask = (num_pools - 1) << pool_offset;
  18194     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  18195     bank_size = size_pool / num_banks_per_pool;
  18196     _bcm_policer_flow_info_t_init(&flow_info);
  18197 
  18198     if (flag == BCM_POLICER_GLOBAL_METER_ENVELOP_MACRO_FLOW) {
  18199         flow_info.flow_type = bcmPolicerFlowTypeMacro;
  18200         flow_info.skip_pool = num_pools;
  18201         rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle,
  18202                     &flow_info,  NULL, policer_id, &numbers);
  18203         if (!(BCM_SUCCESS(rv))) {
  18204             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18205                       (BSL_META_U(unit,
  18206                                   "Unable to create macro flow policer\n")));
  18207             return rv;
  18208         }
  18209     } else if (flag == BCM_POLICER_GLOBAL_METER_ENVELOP_MICRO_FLOW) {
  18210 
  18211         if ((mode == bcmPolicerGroupModeCascade) ||
  18212             (mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  18213             (mode == bcmPolicerGroupModeCascadeDroppedPktExclude) ||
  18214             (mode == bcmPolicerGroupModeIntPriCascade) ||
  18215             (mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  18216             LOG_ERROR(BSL_LS_BCM_POLICER,
  18217                       (BSL_META_U(unit,
  18218                                   "Unable to create micro flow policers "
  18219                                   "due to unsupported mode\n")));
  18220             return (BCM_E_PARAM);
  18221         }
  18222         /* validate macroflow policer id */
  18223         rv = _bcm_esw_policer_validate(unit, &macro_flow_policer_id);
  18224         if (!(BCM_SUCCESS(rv))) {
  18225             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18226                       (BSL_META_U(unit,
  18227                                   "Invalid policer Id passed\n")));
  18228             return rv;
  18229         }
  18230         rv = _bcm_esw_get_policer_table_index(unit, macro_flow_policer_id,
  18231                                                                    &index);
  18232         if (BCM_FAILURE(rv)) {
  18233             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18234                       (BSL_META_U(unit,
  18235                                   "Unable to Get policer index for macro flow "
  18236                                   "policer \n")));
  18237             return rv;
  18238         }
  18239 
  18240         pool = (macro_flow_policer_id & pool_mask) >> pool_offset;
  18241 
  18242         flow_info.flow_type = bcmPolicerFlowTypeMicro;
  18243         flow_info.skip_pool = pool;
  18244         flow_info.skip_bank = (macro_flow_policer_id & (size_pool - 1)) / bank_size;
  18245         rv = _bcm_esw_policer_group_create(unit, mode, &flow_info,
  18246                                            NULL, policer_id, &numbers);
  18247         if (BCM_FAILURE(rv)) {
  18248             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18249                       (BSL_META_U(unit,
  18250                                   "Unable to create micro flow policers\n")));
  18251             return rv;
  18252         }
  18253         /*  get the HW index for the micro flow policer created */
  18254         rv = _bcm_esw_get_policer_table_index(unit, *policer_id,
  18255                                                            &micro_flow_index);
  18256         if (BCM_FAILURE(rv)) {
  18257             LOG_DEBUG(BSL_LS_BCM_POLICER,
  18258                       (BSL_META_U(unit,
  18259                                   "Unable to Get policer index for micro flow "
  18260                                   "policer \n")));
  18261             return rv;
  18262         }
  18263         /* Write the index of the macro-meter at "micro_flow_index" location
  18264            of SVM_MACROFLOW_INDEX_TABLE */
  18265 
  18266         entry_mem_size = sizeof(svm_macroflow_index_table_entry_t);
  18267         entry_index_max = micro_flow_index + numbers - 1;
  18268         /* Allocate buffer to store the DMAed table entries. */
  18269         buf = soc_cm_salloc(unit, entry_mem_size * numbers,
  18270                               "svm macro flow index table entry buffer");
  18271         if (NULL == buf) {
  18272             return (BCM_E_MEMORY);
  18273         }
  18274         /* Initialize the entry buffer. */
  18275         sal_memset(buf, 0, sizeof(entry_mem_size) * numbers);
  18276 
  18277         /* Read the table entries into the buffer. */
  18278         rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  18279                                 MEM_BLOCK_ALL, micro_flow_index,
  18280                                 entry_index_max, buf);
  18281         if (BCM_FAILURE(rv)) {
  18282             if (buf) {
  18283                 soc_cm_sfree(unit, buf);
  18284             }
  18285             return rv;
  18286         }
  18287 
  18288         /* Iterate over the table entries. */
  18289         for (entry_index = 0; entry_index < numbers; entry_index++) {
  18290             entry = soc_mem_table_idx_to_pointer(unit,
  18291                                   SVM_MACROFLOW_INDEX_TABLEm,
  18292                                   svm_macroflow_index_table_entry_t *,
  18293                                   buf, entry_index);
  18294             soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm,
  18295                            (void *)entry, MACROFLOW_INDEXf, (uint32 *)&index);
  18296             rv = _bcm_esw_policer_increment_ref_count(unit,
  18297                                                       macro_flow_policer_id);
  18298             if (BCM_FAILURE(rv)) {
  18299                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  18300                           (BSL_META_U(unit,
  18301                                       "Unable to increment ref count for micro flow "
  18302                                       "policer\n")));
  18303                 if (buf) {
  18304                     soc_cm_sfree(unit, buf);
  18305                 }
  18306                 return rv;
  18307             }
  18308         }
  18309         if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  18310                                       MEM_BLOCK_ALL, micro_flow_index,
  18311                                       entry_index_max, buf)) < 0) {
  18312             if (BCM_FAILURE(rv)) {
  18313                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  18314                             (BSL_META_U(unit,
  18315                                         "Unable to write to macro flow table at index "
  18316                                         "provided\n")));
  18317                 if (buf) {
  18318                     soc_cm_sfree(unit, buf);
  18319                 }
  18320                 return rv;
  18321             }
  18322         }
  18323         if (buf) {
  18324             soc_cm_sfree(unit, buf);
  18325         }
  18326     } else {
  18327         LOG_ERROR(BSL_LS_BCM_POLICER,
  18328                   (BSL_META_U(unit,
  18329                               "Invalid flag passed \n")));
  18330         return BCM_E_PARAM;
  18331     }
  18332     *npolicers = numbers;
  18333     return rv;
  18334 }
  18335 
  18336 
  18337 
  18338 int
  18339 _bcm_esw_policer_udf_group_set_offset_map(
  18340    int unit,
  18341    bcm_policer_group_mode_type_t type,
  18342    uint32 npolicers,
  18343    uint32 num_selectors,
  18344    bcm_policer_group_mode_attr_selector_t *attr_selectors,
  18345    bcm_policer_svc_meter_attr_t *mode_attr)
  18346 {
  18347     int rv = BCM_E_NONE;
  18348     int num_pools = 0;
  18349     offset_table_entry_t   *offset_map = NULL;
  18350     int i = 0;
  18351     uint32 value[256] = { 0 };
  18352     uint32 table_offset[256] = { 0 };
  18353     num_pools =  SOC_INFO(unit).global_meter_pools;
  18354 
  18355     offset_map =  &mode_attr->udf_pkt_attr_selectors_v.offset_map[0];
  18356 
  18357     switch (type) {
  18358         case bcmPolicerGroupModeTypeNormal:
  18359             for (i = 0; i < num_selectors; i++) {
  18360                offset_map[attr_selectors[i].attr_value].offset
  18361                                        = attr_selectors[i].policer_offset;
  18362                offset_map[attr_selectors[i].attr_value].meter_enable = 1;
  18363             }
  18364             break;
  18365 
  18366         case bcmPolicerGroupModeTypeCascade:
  18367             for (i = 0; i < num_selectors; i++) {
  18368                 if (attr_selectors[i].policer_offset >= num_pools) {
  18369                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18370                                 "Invalid policer offset \n")));
  18371                     return BCM_E_PARAM;
  18372                 }
  18373                 value[i] = attr_selectors[i].policer_offset;
  18374                 table_offset[i] = attr_selectors[i].attr_value;
  18375             }
  18376             rv = _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool(
  18377                                              unit, 0, num_selectors, &table_offset[0],
  18378                                              &value[0], offset_map);
  18379             BCM_IF_ERROR_RETURN(rv);
  18380             break;
  18381 
  18382         case bcmPolicerGroupModeTypeCascadeWithCoupling:
  18383             for (i = 0; i < num_selectors; i++) {
  18384                 if (attr_selectors[i].policer_offset >= num_pools/2) {
  18385                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18386                       "Invalid policer offset \n")));
  18387                     return BCM_E_PARAM;
  18388                 }
  18389                 value[i] = attr_selectors[i].policer_offset;
  18390                 table_offset[i] = attr_selectors[i].attr_value;
  18391             }
  18392             rv = _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool(
  18393                                              unit, 1, num_selectors, &table_offset[0],
  18394                                              &value[0], offset_map);
  18395             BCM_IF_ERROR_RETURN(rv);
  18396             break;
  18397 
  18398         default :
  18399             rv =  BCM_E_PARAM;
  18400 
  18401     }
  18402     return rv;
  18403 }
  18404 
  18405 /*
  18406  * Function:
  18407  *      _bcm_esw_svc_meter_offset_map_update
  18408  * Purpose:
  18409  *      Update offset map based on attributes
  18410  * Parameters:
  18411  *     unit                  - (IN) unit number
  18412  *     attr                  - (IN/OUT) Offset mode attributes
  18413  *     offset                - (IN) Index in Offset Map
  18414  *     policer_offset        - (IN) value to be updated
  18415  * Returns:
  18416  *     NONE
  18417  */
  18418 STATIC int
  18419  _bcm_esw_svc_meter_offset_map_update(
  18420      uint32 unit,
  18421      bcm_policer_svc_meter_attr_t *attr,
  18422      bcm_policer_group_mode_t group_mode,
  18423      uint32 offset,
  18424      uint32 policer_offset)
  18425 {
  18426     uint8 pool = 0;
  18427     uint8 pool_offset_limit = 0;
  18428     uint8 dir = 0;
  18429     uint8 coupling_offset = 0;
  18430     offset_table_entry_t *offset_map_ptr = NULL;
  18431 
  18432     switch (attr->mode_type_v) {
  18433         case udf_mode:
  18434         case udf_cascade_mode:
  18435         case udf_cascade_with_coupling_mode:
  18436             offset_map_ptr =
  18437                 &(attr->udf_pkt_attr_selectors_v.offset_map[0]);
  18438             break;
  18439         case compressed_mode:
  18440             offset_map_ptr =
  18441                 &(attr->compressed_attr_selectors_v.offset_map[0]);
  18442             break;
  18443         case uncompressed_mode:
  18444             offset_map_ptr =
  18445                 &(attr->uncompressed_attr_selectors_v.offset_map[0]);
  18446             break;
  18447         default :
  18448             break;
  18449     }
  18450     if (offset_map_ptr != NULL) {
  18451         if (group_mode == bcmPolicerGroupModeSingle) {
  18452             if ((offset_map_ptr[offset].meter_enable == 1) &&
  18453                     (offset_map_ptr[offset].offset != policer_offset)) {
  18454                 LOG_ERROR(BSL_LS_BCM_POLICER,
  18455                         (BSL_META_U(unit,
  18456                                     "Policer offset(%d) is overwriting policer"
  18457                                     " offset(%d) at index = %d\n"), policer_offset,
  18458                          offset_map_ptr[offset].offset, offset));
  18459                 return BCM_E_CONFIG;
  18460             }
  18461             offset_map_ptr[offset].offset = policer_offset;
  18462             offset_map_ptr[offset].pool = 0;
  18463             offset_map_ptr[offset].meter_enable = 1;
  18464         } else {
  18465             if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  18466                 coupling_offset = 0;
  18467             } else {
  18468                 coupling_offset =
  18469                     (group_mode == bcmPolicerGroupModeCascade) ? 0 : 4;
  18470             }
  18471             if (soc_feature(unit,
  18472                         soc_feature_global_meter_pool_priority_descending)) {
  18473                 pool_offset_limit = (group_mode == bcmPolicerGroupModeCascade) ?
  18474                     (BCM_POLICER_GLOBAL_METER_MAX_POOL - 1) :
  18475                     (BCM_POLICER_GLOBAL_METER_MAX_POOL/2 - 1);
  18476                 dir = -1;
  18477             } else {
  18478                 pool_offset_limit = 0;
  18479                 dir = 1;
  18480             }
  18481             pool = pool_offset_limit + dir * policer_offset + coupling_offset;
  18482             if ((offset_map_ptr[offset].meter_enable == 1) &&
  18483                     (offset_map_ptr[offset].pool != pool)) {
  18484                 uint32  curr_pol_offset = 0;
  18485                 curr_pol_offset = offset_map_ptr[offset].pool;
  18486                 curr_pol_offset -= (coupling_offset + pool_offset_limit);
  18487                 curr_pol_offset /= dir;
  18488                 LOG_ERROR(BSL_LS_BCM_POLICER,
  18489                         (BSL_META_U(unit,
  18490                                     "Policer offset(%d) is overwriting policer"
  18491                                     " offset(%d) at index = %d\n"), policer_offset,
  18492                          curr_pol_offset, offset));
  18493                 return BCM_E_CONFIG;
  18494             }
  18495             offset_map_ptr[offset].offset = 0;
  18496             offset_map_ptr[offset].pool = pool;
  18497             offset_map_ptr[offset].meter_enable = 1;
  18498         }
  18499     }
  18500     return BCM_E_NONE;
  18501 }
  18502 
  18503 /*
  18504  * Function:
  18505  *      _bcm_esw_svc_meter_offset_mode_id_check
  18506  * Purpose:
  18507  *      Check if given attribute selectors list is already
  18508  *      configured or not
  18509  * Parameters:
  18510  *     unit                  - (IN) unit number
  18511  *     flags                 - (IN) flags
  18512  *     type                  - (IN) type of group mode
  18513  *     total_policers        - (IN) total policers
  18514  *     num_selectors         - (IN) number of selectors
  18515  *     attr_selectors        - (IN) list of attributes selectors
  18516  *     mode_id               - (OUT) pointer to offset mode index
  18517  * Returns:
  18518  *     BCM_E_XXX
  18519  */
  18520 STATIC int
  18521 _bcm_esw_svc_meter_offset_mode_id_check(
  18522     uint32 unit,
  18523     uint32 flags,
  18524     bcm_policer_group_mode_type_t type,
  18525     uint32 total_policers,
  18526     uint32 num_selectors,
  18527     bcm_policer_group_mode_attr_selector_t *attr_selectors,
  18528     uint32 *mode_id)
  18529 {
  18530     uint32 index = 0;
  18531     int rv = BCM_E_NONE;
  18532     int is_same = FALSE;
  18533     bcm_policer_svc_meter_bookkeep_mode_t  mode_info;
  18534 
  18535     /* Loop through all offset mode index and find match */
  18536     for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) {
  18537         if (_bcm_policer_svc_meter_get_mode_info(unit, index, &mode_info)
  18538                                                          == BCM_E_NONE) {
  18539             if (mode_info.type != type) {
  18540                 continue;
  18541             }
  18542 
  18543             /* check num selectors */
  18544             if (mode_info.no_of_selectors == num_selectors) {
  18545                 if (mode_info.attr_selectors != NULL) {
  18546                     rv = _bcm_attr_selectors_wb_attr_selectors_cmp(
  18547                             num_selectors, attr_selectors,
  18548                             mode_info.attr_selectors, &is_same);
  18549                     BCM_IF_ERROR_RETURN(rv);
  18550                     if (is_same == TRUE) {
  18551                         /* all the selectors are the same */
  18552                         *mode_id = index;
  18553                         return BCM_E_EXISTS;
  18554                     }
  18555                 }
  18556             }
  18557         }
  18558     }
  18559     return BCM_E_NONE;
  18560 }
  18561 
  18562 /*
  18563  * Function:
  18564  *      _bcm_policer_svc_meter_group_offset_mode_info_update
  18565  * Purpose:
  18566  *      update offset mode info
  18567  * Parameters:
  18568  *     unit                  - (IN) unit number
  18569  *     mode                  - (IN) offset mode index
  18570  *     num_selectors         - (IN) number of selectors
  18571  *     attr_selectors        - (IN) list of attributes selectors
  18572  * Returns:
  18573  *     BCM_E_XXX
  18574  */
  18575 int _bcm_policer_svc_meter_group_offset_mode_info_update (
  18576             int unit,
  18577             bcm_policer_svc_meter_mode_t mode,
  18578             int8 type,
  18579             int num_selectors,
  18580             bcm_policer_group_mode_attr_selector_t *attr_selectors)
  18581 {
  18582     int rv = BCM_E_NONE;
  18583 
  18584     if ((num_selectors == 0) || (attr_selectors == NULL)) {
  18585         /* Free if allocated */
  18586         if (global_meter_offset_mode[unit][mode].attr_selectors !=
  18587                 NULL) {
  18588             sal_free(global_meter_offset_mode[unit][mode].attr_selectors);
  18589         }
  18590         global_meter_offset_mode[unit][mode].attr_selectors = NULL;
  18591     } else {
  18592         global_meter_offset_mode[unit][mode].type = type;
  18593         global_meter_offset_mode[unit][mode].no_of_selectors = num_selectors;
  18594 
  18595         global_meter_offset_mode[unit][mode].attr_selectors =
  18596             sal_alloc(num_selectors *
  18597                     sizeof(bcm_policer_group_mode_attr_selector_t),
  18598                     "attr selectors");
  18599         if (NULL == global_meter_offset_mode[unit][mode].attr_selectors) {
  18600             return BCM_E_MEMORY;
  18601         }
  18602         rv = _bcm_attr_selectors_copy_to_wb_attr_selectors(
  18603                 num_selectors, attr_selectors,
  18604                 global_meter_offset_mode[unit][mode].attr_selectors);
  18605         BCM_IF_ERROR_RETURN(rv);
  18606     }
  18607     return BCM_E_NONE;
  18608 }
  18609 
  18610 /*
  18611  * Function:
  18612  *      _bcm_esw_policer_group_udf_mode_fillup_values
  18613  * Purpose:
  18614  *      Fill up temporary structures in appropriate order for efficient
  18615  *      management of user input
  18616  * Parameters:
  18617  *     unit                  - (IN) unit number
  18618  *     flags                 - (IN) flags
  18619  *     type                  - (IN) type of group mode
  18620  *     total_policers        - (IN) total policers
  18621  *     num_selectors         - (IN) number of selectors
  18622  *     attr_selectors        - (IN) list of attributes selectors
  18623  *     udf_attr_selectors    - (OUT) fill up this structure
  18624  * Returns:
  18625  *     BCM_E_XXX
  18626  */
  18627 STATIC int
  18628 _bcm_esw_policer_group_udf_mode_fillup_values (
  18629             int unit,
  18630             uint32 flags,
  18631             bcm_policer_group_mode_type_t type,
  18632             uint32 total_policers,
  18633             uint32 num_selectors,
  18634             bcm_policer_group_mode_attr_selector_t *attr_selectors,
  18635             bcm_policer_udf_attr_selectors_t *udf_attr_selectors)
  18636 {
  18637     int rv = BCM_E_NONE;
  18638     uint32 sel = 0;
  18639     uint32 index = 0;
  18640     uint32 drop =0;
  18641     int udf_id = 0;
  18642     uint32 offset = 0, width = 0, attr_value = 0, policer_offset = 0;
  18643     uint32 is_subdiv_new = 0, subdiv_first_bit = 0, subdiv_last_bit = 0;
  18644     uint32 selectors = 0, udf_subdiv_present = 0;
  18645     bcm_policer_group_mode_attr_t attr;
  18646     bcm_policer_udf_pkt_combine_attr_t *udf_combine_attr_data = NULL;
  18647 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  18648     bcmi_xgs4_udf_offset_info_t *udf_offset_node = NULL;
  18649     int grp_udf_id = -1;
  18650 #endif
  18651 
  18652     for (sel = 0; sel < num_selectors; sel++) {
  18653         policer_offset = attr_selectors[sel].policer_offset;
  18654         attr = attr_selectors[sel].attr;
  18655         attr_value = attr_selectors[sel].attr_value;
  18656         udf_id = attr_selectors[sel].udf_id;
  18657         offset = attr_selectors[sel].offset;
  18658         width = attr_selectors[sel].width;
  18659 
  18660         if (policer_offset >= total_policers) {
  18661             return BCM_E_PARAM;
  18662         }
  18663 
  18664         switch(attr) {
  18665             case bcmPolicerGroupModeAttrUdf :
  18666             {
  18667                 if (!(attr_selectors[sel].flags &
  18668                                 BCM_POLICER_ATTR_WIDTH_OFFSET)) {
  18669                     return (BCM_E_PARAM);
  18670                 }
  18671 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  18672                 /* Validate UDF Id passed */
  18673                 if (grp_udf_id == -1) {
  18674                     rv = bcmi_xgs4_udf_offset_node_get(unit,
  18675                                 attr_selectors[sel].udf_id, &udf_offset_node);
  18676                     if (BCM_FAILURE(rv)) {
  18677                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18678                                 "Failed to get info related to UDF Id \n")));
  18679                         return rv;
  18680                     }
  18681 
  18682                     /* Matching node not found */
  18683                     if (udf_offset_node == NULL) {
  18684                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18685                                 "Failed to get info related to UDF Id \n")));
  18686                         return BCM_E_NOT_FOUND;
  18687                     }
  18688 
  18689                     if (!((udf_offset_node->hw_bmap & 0x1) ||
  18690                                     (udf_offset_node->hw_bmap & 0x2))) {
  18691                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18692                             "UDF is not properly configured for policer use\n")));
  18693                         return BCM_E_PARAM;
  18694                     }
  18695                     grp_udf_id = udf_id;
  18696                 } else if (udf_id != grp_udf_id) {
  18697                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18698                         "Mismatch of UDFs in two attribute selectors\n")));
  18699                     return BCM_E_PARAM;
  18700                 }
  18701 #endif
  18702                 /* width = 0 means ING_SVM_PKT_ATTR_SELECTOR_KEY_Xr is not
  18703                  * updated with required values, makes no sense */
  18704                 if ((width > 8) || (width <= 0)) {
  18705                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18706                         "Invalid width passed for UDF \n")));
  18707                     return BCM_E_PARAM;
  18708                 }
  18709                 /* offset value range from 0 to 31 */
  18710                 if (offset >= SVC_METER_UDF1_MAX_BIT_POSITION) {
  18711                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18712                         "Invalid offset passed for UDF \n")));
  18713                     return (BCM_E_PARAM);
  18714                 }
  18715                 /* offset+width should not exceed 32 - size of (UDF0 + UDF1)
  18716                  * For eg. if offset=31, width can be 1 (selecting msb
  18717                  * of udf1) making sum 32 */
  18718                 if ((offset + width) > SVC_METER_UDF1_MAX_BIT_POSITION) {
  18719                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18720                         "Invalid offset and width pair passed for UDF \n")));
  18721                     return (BCM_E_PARAM);
  18722                 }
  18723                 /* Verify that given offset-width does not overlap
  18724                  * 0-not used, 1-start offset in udf, 2-rest bits upto width */
  18725                 if (udf_attr_selectors->udf_bits[offset] == 0) {
  18726                     is_subdiv_new = 1;
  18727                 }
  18728                 subdiv_first_bit = offset;
  18729                 subdiv_last_bit = offset + width - 1;
  18730                 if (subdiv_last_bit >= SVC_METER_UDF1_MAX_BIT_POSITION) {
  18731                     subdiv_last_bit = SVC_METER_UDF1_MAX_BIT_POSITION - 1;
  18732                 }
  18733                 for (index = subdiv_first_bit; index <= subdiv_last_bit; index++) {
  18734                     if (index == subdiv_first_bit) {
  18735                         if (is_subdiv_new == 1) {
  18736                             udf_attr_selectors->udf_bits[index] = 1;
  18737                         } else if (udf_attr_selectors->udf_bits[index] != 1) {
  18738                             rv = BCM_E_PARAM;
  18739                             break;
  18740                         }
  18741                     } else {
  18742                         if (((is_subdiv_new == 1) &&
  18743                                 (udf_attr_selectors->udf_bits[index] != 0)) ||
  18744                                 ((is_subdiv_new == 0) &&
  18745                                 (udf_attr_selectors->udf_bits[index] != 2))) {
  18746                             rv = BCM_E_PARAM;
  18747                             break;
  18748                         } else {
  18749                             udf_attr_selectors->udf_bits[index] = 2;
  18750                         }
  18751                     }
  18752                 }
  18753                 if ((rv == BCM_E_NONE) &&
  18754                     (index != SVC_METER_UDF1_MAX_BIT_POSITION) &&
  18755                     (udf_attr_selectors->udf_bits[index] == 2)) {
  18756                     rv = BCM_E_PARAM;
  18757                 }
  18758                 if (BCM_FAILURE(rv)) {
  18759                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18760                         "Overlapped offset/width pair for UDF not allowed\n")));
  18761                     return rv;
  18762                 }
  18763                 /* Attribute value should not exceed size as given in width */
  18764                 if (attr_value >= (1 << width)) {
  18765                     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18766                         "Attribute value passed exceeds range of 'width' bits\n")));
  18767                     return BCM_E_PARAM;
  18768                 }
  18769 
  18770                 if (is_subdiv_new == 1) {
  18771                     index = udf_attr_selectors->total_subdiv;
  18772                     udf_attr_selectors->udf_subdiv[index].udf_id = udf_id;
  18773                     udf_attr_selectors->udf_subdiv[index].offset = offset;
  18774                     udf_attr_selectors->udf_subdiv[index].width = width;
  18775                     udf_attr_selectors->total_subdiv = index + 1;
  18776                     is_subdiv_new = 0;
  18777                 }
  18778                 udf_combine_attr_data =
  18779                     &(udf_attr_selectors->combine_attr_data[policer_offset]);
  18780                 selectors = udf_combine_attr_data->selectors;
  18781                 udf_combine_attr_data->udf_subdiv[selectors].udf_id = udf_id;
  18782                 udf_combine_attr_data->udf_subdiv[selectors].offset = offset;
  18783                 udf_combine_attr_data->udf_subdiv[selectors].width = width;
  18784                 udf_combine_attr_data->attr_value[selectors] = attr_value;
  18785                 udf_combine_attr_data->selectors = selectors + 1;
  18786                 break;
  18787             }
  18788             case bcmPolicerGroupModeAttrDrop :
  18789             {
  18790                 udf_attr_selectors->drop = 1;
  18791                 udf_combine_attr_data =
  18792                     &(udf_attr_selectors->combine_attr_data[policer_offset]);
  18793                 drop = attr_selectors[sel].attr_value;
  18794                 switch(drop) {
  18795                     case 0:
  18796                         udf_combine_attr_data->drop_flags =
  18797                                             _BCM_POLICER_DROP_DISABLE;
  18798                         break;
  18799                     case 1:
  18800                         udf_combine_attr_data->drop_flags =
  18801                                             _BCM_POLICER_DROP_ENABLE;
  18802                         break;
  18803                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  18804                         udf_combine_attr_data->drop_flags =
  18805                                             _BCM_POLICER_DROP_DISABLE |
  18806                                             _BCM_POLICER_DROP_ENABLE;
  18807                         break;
  18808                     default :
  18809                         return BCM_E_PARAM;
  18810                 }
  18811                 break;
  18812             }
  18813             default :
  18814                 return BCM_E_PARAM;
  18815         }
  18816     }
  18817 
  18818     /* All policer offset must have atleast 1 selector for each sub-division*/
  18819     for (policer_offset = 0; policer_offset < total_policers; policer_offset++) {
  18820         udf_combine_attr_data = &(udf_attr_selectors->combine_attr_data[policer_offset]);
  18821         if (udf_attr_selectors->drop) {
  18822             if (udf_combine_attr_data->drop_flags == 0) {
  18823                 return BCM_E_PARAM;
  18824             }
  18825         }
  18826         for (index = 0; index < udf_attr_selectors->total_subdiv; index++) {
  18827             udf_subdiv_present = 0;
  18828             for (selectors = 0; udf_combine_attr_data->selectors; selectors++) {
  18829                 if (udf_attr_selectors->udf_subdiv[index].offset == \
  18830                         udf_combine_attr_data->udf_subdiv[selectors].offset) {
  18831                     udf_subdiv_present = 1;
  18832                     break;
  18833                 }
  18834             }
  18835             if (udf_subdiv_present == 0) {
  18836                 return BCM_E_PARAM;
  18837             }
  18838         }
  18839     }
  18840     return BCM_E_NONE;
  18841 }
  18842 
  18843 /*
  18844  * Function:
  18845  *      _bcm_esw_policer_group_mode_fillup_values
  18846  * Purpose:
  18847  *      Fill up temporary structures in appropriate order for efficient
  18848  *      management of user input
  18849  * Parameters:
  18850  *     unit                  - (IN) unit number
  18851  *     flags                 - (IN) flags
  18852  *     type                  - (IN) type of group mode
  18853  *     total_policers        - (IN) total policers
  18854  *     num_selectors         - (IN) number of selectors
  18855  *     attr_selectors        - (IN) list of attributes selectors
  18856  *     pkt_attr_selectors    - (OUT) fill up this structure
  18857  * Returns:
  18858  *     BCM_E_XXX
  18859  */
  18860 STATIC int
  18861 _bcm_esw_policer_group_mode_fillup_values (
  18862             int unit,
  18863             uint32 flags,
  18864             bcm_policer_group_mode_type_t type,
  18865             uint32 total_policers,
  18866             uint32 num_selectors,
  18867             bcm_policer_group_mode_attr_selector_t *attr_selectors,
  18868             bcm_policer_attr_selectors_t *pkt_attr_selectors)
  18869 {
  18870     uint32 sel = 0, pol_offset = 0;
  18871     uint32 attr_value = 0;
  18872     uint32 value = 0, max_value = 0;
  18873     uint32 attr_size = 0;
  18874     uint32 index = 0;
  18875     uint32 prio_range_first = 0, prio_range_last = 0;
  18876     bcm_policer_group_mode_attr_t attr;
  18877     bcm_policer_combine_attr_t *combine_attr_data = NULL;
  18878 
  18879     for (sel = 0; sel < num_selectors; sel++) {
  18880         pol_offset = attr_selectors[sel].policer_offset;
  18881         attr = attr_selectors[sel].attr;
  18882         attr_value = attr_selectors[sel].attr_value;
  18883         if (pol_offset >= total_policers) {
  18884             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18885                             "Bad Param : sel=%d : offset (%d) more than"
  18886                             " total_policer=%d \n"),
  18887                         sel, pol_offset, total_policers));
  18888             return BCM_E_PARAM;
  18889         }
  18890         combine_attr_data =
  18891             &pkt_attr_selectors->combine_attr_data[pol_offset];
  18892         switch(attr) {
  18893             case bcmPolicerGroupModeAttrFieldIngressColor :
  18894                 pkt_attr_selectors->cng = 1;
  18895                 switch(attr_value) {
  18896                     case bcmColorGreen :
  18897                         combine_attr_data->cng_flags |=
  18898                             _BCM_POLICER_COLOR_GREEN;
  18899                         break;
  18900                     case bcmColorYellow :
  18901                         combine_attr_data->cng_flags |=
  18902                             _BCM_POLICER_COLOR_YELLOW;
  18903                         break;
  18904                     case bcmColorRed :
  18905                         combine_attr_data->cng_flags |=
  18906                             _BCM_POLICER_COLOR_RED;
  18907                         break;
  18908                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  18909                         combine_attr_data->cng_flags |=
  18910                             (_BCM_POLICER_COLOR_GREEN |
  18911                              _BCM_POLICER_COLOR_YELLOW |
  18912                              _BCM_POLICER_COLOR_RED);
  18913                         break;
  18914                     default :
  18915                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18916                                         "BAD PARAM(cng) : sel=%d "
  18917                                         "offset=%d, attr=%d value=%d \n"),
  18918                                     sel, pol_offset, attr, attr_value));
  18919                         return BCM_E_PARAM;
  18920                 }
  18921                 pkt_attr_selectors->combine_cng_flags |=
  18922                         combine_attr_data->cng_flags;
  18923                 break;
  18924 
  18925             case bcmPolicerGroupModeAttrIntPri :
  18926                 pkt_attr_selectors->int_pri = 1;
  18927                 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) {
  18928                     prio_range_first = _BCM_POLICER_PKT_PRI0;
  18929                     prio_range_last = _BCM_POLICER_PKT_PRI15;
  18930                 } else if (attr_value <= _BCM_POLICER_PKT_PRI15) {
  18931                     prio_range_first = prio_range_last = attr_value;
  18932                 } else {
  18933                        LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18934                                         "BAD PARAM(int_pri) : sel=%d "
  18935                                         "offset=%d, attr=%d value=%d \n"),
  18936                                     sel, pol_offset, attr, attr_value));
  18937                         return BCM_E_PARAM;
  18938                 }
  18939                 for (index = prio_range_first; index <= prio_range_last; index++) {
  18940                     combine_attr_data->int_pri_flags |= (1 << index);
  18941                 }
  18942                 pkt_attr_selectors->combine_int_pri_flags |=
  18943                         combine_attr_data->int_pri_flags;
  18944                 break;
  18945 
  18946             case bcmPolicerGroupModeAttrVlan:
  18947                 pkt_attr_selectors->vlan_format = 1;
  18948                 switch(attr_value) {
  18949                     case bcmPolicerGroupModeAttrVlanUnTagged :
  18950                         combine_attr_data->vlan_format_flags |=
  18951                             _BCM_POLICER_VLAN_FORMAT_UNTAGGED;
  18952                         break;
  18953                     case bcmPolicerGroupModeAttrVlanInnerTag :
  18954                         combine_attr_data->vlan_format_flags |=
  18955                             _BCM_POLICER_VLAN_FORMAT_INNER;
  18956                         break;
  18957                     case bcmPolicerGroupModeAttrVlanOuterTag :
  18958                         combine_attr_data->vlan_format_flags |=
  18959                             _BCM_POLICER_VLAN_FORMAT_OUTER;
  18960                         break;
  18961                     case bcmPolicerGroupModeAttrVlanStackedTag :
  18962                         combine_attr_data->vlan_format_flags |=
  18963                             _BCM_POLICER_VLAN_FORMAT_BOTH;
  18964                         break;
  18965                     case bcmPolicerGroupModeAttrVlanAll :
  18966                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  18967                         combine_attr_data->vlan_format_flags |=
  18968                             (_BCM_POLICER_VLAN_FORMAT_UNTAGGED |
  18969                              _BCM_POLICER_VLAN_FORMAT_INNER |
  18970                              _BCM_POLICER_VLAN_FORMAT_OUTER |
  18971                              _BCM_POLICER_VLAN_FORMAT_BOTH);
  18972                         break;
  18973                     default :
  18974                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18975                                         "BAD PARAM(vlan_format) : sel=%d "
  18976                                         "offset=%d, attr=%d value=%d \n"),
  18977                                     sel, pol_offset, attr, attr_value));
  18978                         return BCM_E_PARAM;
  18979                 }
  18980                 pkt_attr_selectors->combine_vlan_format_flags |=
  18981                         combine_attr_data->vlan_format_flags;
  18982                 break;
  18983 
  18984             case bcmPolicerGroupModeAttrOuterPri:
  18985                 pkt_attr_selectors->outer_dot1p = 1;
  18986                 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) {
  18987                     prio_range_first = _BCM_POLICER_PKT_PRI0;
  18988                     prio_range_last = _BCM_POLICER_PKT_PRI7;
  18989                 } else if (attr_value <= _BCM_POLICER_PKT_PRI7) {
  18990                     prio_range_first = prio_range_last = attr_value;
  18991                 } else {
  18992                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  18993                                         "BAD PARAM(outer_dot1p) : sel=%d "
  18994                                         "offset=%d, attr=%d value=%d \n"),
  18995                                     sel, pol_offset, attr, attr_value));
  18996                         return BCM_E_PARAM;
  18997                 }
  18998                 for (index = prio_range_first; index <= prio_range_last; index++) {
  18999                     combine_attr_data->outer_dot1p_flags |= (1 << index);
  19000                 }
  19001                 pkt_attr_selectors->combine_outer_dot1p_flags |=
  19002                         combine_attr_data->outer_dot1p_flags;
  19003                 break;
  19004 
  19005             case bcmPolicerGroupModeAttrInnerPri :
  19006                 pkt_attr_selectors->inner_dot1p = 1;
  19007                 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) {
  19008                     prio_range_first = _BCM_POLICER_PKT_PRI0;
  19009                     prio_range_last = _BCM_POLICER_PKT_PRI7;
  19010                 } else if (attr_value <= _BCM_POLICER_PKT_PRI7) {
  19011                     prio_range_first = prio_range_last = attr_value;
  19012                 } else {
  19013                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19014                                         "BAD PARAM(inner_dot1p) : sel=%d "
  19015                                         "offset=%d, attr=%d value=%d \n"),
  19016                                     sel, pol_offset, attr, attr_value));
  19017                         return BCM_E_PARAM;
  19018                 }
  19019                 for (index = prio_range_first; index <= prio_range_last; index++) {
  19020                     combine_attr_data->inner_dot1p_flags |= (1 << index);
  19021                 }
  19022                 pkt_attr_selectors->combine_inner_dot1p_flags |=
  19023                         combine_attr_data->inner_dot1p_flags;
  19024                 break;
  19025 
  19026             case bcmPolicerGroupModeAttrPort :
  19027                 pkt_attr_selectors->port = 1;
  19028                 max_value =  soc_mem_index_max(unit, ING_SVM_PORT_MAPm);
  19029                 switch (attr_value) {
  19030                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19031                         for (value = 0; value <= max_value; value++) {
  19032                             _BCM_POLICER_VALUE_SET(combine_attr_data->
  19033                                     value_array[_bcmPolicerAttrPort], value);
  19034                             _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19035                                     combine_value_array[_bcmPolicerAttrPort], value);
  19036                         }
  19037                         break;
  19038                     default :
  19039                         if (attr_value > max_value) {
  19040                             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19041                                             "BAD PARAM(port) : sel=%d "
  19042                                             "offset=%d, attr=%d value=%d \n"),
  19043                                         sel, pol_offset, attr, attr_value));
  19044                             return BCM_E_PARAM;
  19045                         }
  19046                         _BCM_POLICER_VALUE_SET (combine_attr_data->
  19047                                 value_array[_bcmPolicerAttrPort], attr_value);
  19048                         _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19049                                 combine_value_array[_bcmPolicerAttrPort], attr_value);
  19050                 }
  19051                 break;
  19052             case bcmPolicerGroupModeAttrTosDscp :
  19053                 pkt_attr_selectors->tos_dscp = 1;
  19054                 attr_size = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
  19055                 max_value = (1 << attr_size) - 1;
  19056                 switch (attr_value) {
  19057                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19058                         for (value = 0; value <= max_value; value++) {
  19059                             _BCM_POLICER_VALUE_SET (combine_attr_data->
  19060                                     value_array[_bcmPolicerAttrTosDscp], value);
  19061                             _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19062                                     combine_value_array[_bcmPolicerAttrTosDscp], value);
  19063                         }
  19064                         break;
  19065                     default :
  19066                         if (attr_value > max_value) {
  19067                             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19068                                             "BAD PARAM(tos_dscp) : sel=%d "
  19069                                             "offset=%d, attr=%d value=%d \n"),
  19070                                         sel, pol_offset, attr, attr_value));
  19071                             return BCM_E_PARAM;
  19072                         }
  19073                         _BCM_POLICER_VALUE_SET (combine_attr_data->
  19074                                 value_array[_bcmPolicerAttrTosDscp], attr_value);
  19075                         _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19076                                 combine_value_array[_bcmPolicerAttrTosDscp], attr_value);
  19077                 }
  19078                 break;
  19079             case bcmPolicerGroupModeAttrTosEcn :
  19080                 pkt_attr_selectors->tos_ecn = 1;
  19081                 attr_size = BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE;
  19082                 max_value = (1 << attr_size) - 1;
  19083                 switch (attr_value) {
  19084                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19085                         for (value = 0; value <= max_value; value++) {
  19086                             _BCM_POLICER_VALUE_SET (combine_attr_data->
  19087                                     value_array[_bcmPolicerAttrTosEcn], value);
  19088                             _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19089                                     combine_value_array[_bcmPolicerAttrTosEcn], value);
  19090                         }
  19091                         break;
  19092                     default :
  19093                         if (attr_value > max_value) {
  19094                             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19095                                             "BAD PARAM(tos_ecn) : sel=%d "
  19096                                             "offset=%d, attr=%d value=%d \n"),
  19097                                         sel, pol_offset, attr, attr_value));
  19098                             return BCM_E_PARAM;
  19099                         }
  19100                         _BCM_POLICER_VALUE_SET(combine_attr_data->
  19101                                 value_array[_bcmPolicerAttrTosEcn], attr_value);
  19102                         _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19103                                 combine_value_array[_bcmPolicerAttrTosEcn], attr_value);
  19104                 }
  19105                 break;
  19106             case bcmPolicerGroupModeAttrPktType :
  19107                 pkt_attr_selectors->pkt_resolution = 1;
  19108                 switch(attr_value) {
  19109                     case bcmPolicerGroupModeAttrPktTypeUnknown :
  19110                         combine_attr_data->pkt_resolution_flags |=
  19111                             _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT;
  19112                         break;
  19113                     case bcmPolicerGroupModeAttrPktTypeControl :
  19114                         combine_attr_data->pkt_resolution_flags |=
  19115                             _BCM_POLICER_PKT_TYPE_CONTROL_PKT;
  19116                         break;
  19117                     case bcmPolicerGroupModeAttrPktTypeOAM :
  19118                         combine_attr_data->pkt_resolution_flags |=
  19119                             _BCM_POLICER_PKT_TYPE_OAM_PKT;
  19120                         break;
  19121                     case bcmPolicerGroupModeAttrPktTypeBFD :
  19122                         combine_attr_data->pkt_resolution_flags |=
  19123                             _BCM_POLICER_PKT_TYPE_BFD_PKT;
  19124                         break;
  19125                     case bcmPolicerGroupModeAttrPktTypeBPDU :
  19126                         combine_attr_data->pkt_resolution_flags |=
  19127                             _BCM_POLICER_PKT_TYPE_BPDU_PKT;
  19128                         break;
  19129                     case bcmPolicerGroupModeAttrPktTypeICNM :
  19130                         combine_attr_data->pkt_resolution_flags |=
  19131                             _BCM_POLICER_PKT_TYPE_ICNM_PKT;
  19132                         break;
  19133                     case bcmPolicerGroupModeAttrPktType1588 :
  19134                         combine_attr_data->pkt_resolution_flags |=
  19135                             _BCM_POLICER_PKT_TYPE_PKT_IS_1588;
  19136                         break;
  19137                     case bcmPolicerGroupModeAttrPktTypeKnownL2UC :
  19138                         combine_attr_data->pkt_resolution_flags |=
  19139                             _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT;
  19140                         break;
  19141                     case bcmPolicerGroupModeAttrPktTypeUnknownL2UC :
  19142                         combine_attr_data->pkt_resolution_flags |=
  19143                             _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT;
  19144                         break;
  19145                     case bcmPolicerGroupModeAttrPktTypeL2BC :
  19146                         combine_attr_data->pkt_resolution_flags |=
  19147                             _BCM_POLICER_PKT_TYPE_L2BC_PKT;
  19148                         break;
  19149                     case bcmPolicerGroupModeAttrPktTypeKnownL2MC :
  19150                         combine_attr_data->pkt_resolution_flags |=
  19151                             _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT;
  19152                         break;
  19153                     case bcmPolicerGroupModeAttrPktTypeUnknownL2MC :
  19154                         combine_attr_data->pkt_resolution_flags |=
  19155                             _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT;
  19156                         break;
  19157                     case bcmPolicerGroupModeAttrPktTypeKnownL3UC :
  19158                         combine_attr_data->pkt_resolution_flags |=
  19159                             _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT;
  19160                         break;
  19161                     case bcmPolicerGroupModeAttrPktTypeUnknownL3UC :
  19162                         combine_attr_data->pkt_resolution_flags |=
  19163                             _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT;
  19164                         break;
  19165                     case bcmPolicerGroupModeAttrPktTypeKnownIPMC :
  19166                         combine_attr_data->pkt_resolution_flags |=
  19167                             _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT;
  19168                         break;
  19169                     case bcmPolicerGroupModeAttrPktTypeUnknownIPMC :
  19170                         combine_attr_data->pkt_resolution_flags |=
  19171                             _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT;
  19172                         break;
  19173                     case bcmPolicerGroupModeAttrPktTypeKnownMplsL2 :
  19174                         combine_attr_data->pkt_resolution_flags |=
  19175                             _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT;
  19176                         break;
  19177                     case bcmPolicerGroupModeAttrPktTypeKnownMplsL3 :
  19178                         combine_attr_data->pkt_resolution_flags |=
  19179                             _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT;
  19180                         break;
  19181                     case bcmPolicerGroupModeAttrPktTypeKnownMpls :
  19182                         combine_attr_data->pkt_resolution_flags |=
  19183                             _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT;
  19184                         break;
  19185                     case bcmPolicerGroupModeAttrPktTypeUnknownMpls :
  19186                         combine_attr_data->pkt_resolution_flags |=
  19187                             _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT;
  19188                         break;
  19189                     case bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast :
  19190                         combine_attr_data->pkt_resolution_flags |=
  19191                             _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT;
  19192                         break;
  19193                     case bcmPolicerGroupModeAttrPktTypeKnownMim :
  19194                         combine_attr_data->pkt_resolution_flags |=
  19195                             _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT;
  19196                         break;
  19197                     case bcmPolicerGroupModeAttrPktTypeUnknownMim :
  19198                         combine_attr_data->pkt_resolution_flags |=
  19199                             _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT;
  19200                         break;
  19201                     case bcmPolicerGroupModeAttrPktTypeKnownTrill :
  19202                         combine_attr_data->pkt_resolution_flags |=
  19203                             _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT;
  19204                         break;
  19205                     case bcmPolicerGroupModeAttrPktTypeUnknownTrill :
  19206                         combine_attr_data->pkt_resolution_flags |=
  19207                             _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT;
  19208                         break;
  19209                     case bcmPolicerGroupModeAttrPktTypeKnownNiv :
  19210                         combine_attr_data->pkt_resolution_flags |=
  19211                             _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT;
  19212                         break;
  19213                     case bcmPolicerGroupModeAttrPktTypeUnknownNiv :
  19214                         combine_attr_data->pkt_resolution_flags |=
  19215                             _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT;
  19216                         break;
  19217                     case bcmPolicerGroupModeAttrPktTypeAll :
  19218                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19219                         combine_attr_data->pkt_resolution_flags |=
  19220                             (_BCM_POLICER_PKT_TYPE_UNKNOWN_PKT |
  19221                              _BCM_POLICER_PKT_TYPE_CONTROL_PKT |
  19222                              _BCM_POLICER_PKT_TYPE_OAM_PKT |
  19223                              _BCM_POLICER_PKT_TYPE_BFD_PKT |
  19224                              _BCM_POLICER_PKT_TYPE_BPDU_PKT |
  19225                              _BCM_POLICER_PKT_TYPE_ICNM_PKT |
  19226                              _BCM_POLICER_PKT_TYPE_PKT_IS_1588 |
  19227                              _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT |
  19228                              _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT |
  19229                              _BCM_POLICER_PKT_TYPE_L2BC_PKT |
  19230                              _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT |
  19231                              _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT |
  19232                              _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT |
  19233                              _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT |
  19234                              _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT |
  19235                              _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT |
  19236                              _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT |
  19237                              _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT |
  19238                              _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT |
  19239                              _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT |
  19240                              _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT |
  19241                              _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT |
  19242                              _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT |
  19243                              _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT |
  19244                              _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT |
  19245                              _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT |
  19246                              _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT);
  19247                         break;
  19248                     default :
  19249                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19250                                         "BAD PARAM(port) : sel=%d "
  19251                                         "offset=%d, attr=%d value=%d \n"),
  19252                                     sel, pol_offset, attr, attr_value));
  19253                         return BCM_E_PARAM;
  19254                 }
  19255                 pkt_attr_selectors->combine_pkt_res_flags |=
  19256                         combine_attr_data->pkt_resolution_flags;
  19257                 break;
  19258 
  19259             case bcmPolicerGroupModeAttrIngNetworkGroup :
  19260                 pkt_attr_selectors->svp_type = 1;
  19261                 attr_size = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size;
  19262                 max_value = (1 << attr_size) - 1;
  19263                 switch (attr_value) {
  19264                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19265                         for (value = 0; value <= max_value; value++) {
  19266                             _BCM_POLICER_VALUE_SET (combine_attr_data->
  19267                                     value_array[_bcmPolicerAttrSvpType], value);
  19268                             _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19269                                     combine_value_array[_bcmPolicerAttrSvpType], value);
  19270                         }
  19271                         break;
  19272                     default :
  19273                         if (attr_value > max_value) {
  19274                             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19275                                             "BAD PARAM(svm_group) : sel=%d "
  19276                                             "offset=%d, attr=%d value=%d \n"),
  19277                                         sel, pol_offset, attr, attr_value));
  19278                             return BCM_E_PARAM;
  19279                         }
  19280                         _BCM_POLICER_VALUE_SET (combine_attr_data->
  19281                                 value_array[_bcmPolicerAttrSvpType], attr_value);
  19282                         _BCM_POLICER_VALUE_SET(pkt_attr_selectors->
  19283                                 combine_value_array[_bcmPolicerAttrSvpType], attr_value);
  19284                 }
  19285                 break;
  19286 
  19287             case bcmPolicerGroupModeAttrDrop :
  19288                 pkt_attr_selectors->drop = 1;
  19289                 switch(attr_value) {
  19290                     case 0 :
  19291                         combine_attr_data->drop_flags |=
  19292                             _BCM_POLICER_DROP_DISABLE;
  19293                         break;
  19294                     case 1 :
  19295                         combine_attr_data->drop_flags |=
  19296                             _BCM_POLICER_DROP_ENABLE;
  19297                         break;
  19298                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19299                         combine_attr_data->drop_flags |=
  19300                             (_BCM_POLICER_DROP_DISABLE |
  19301                              _BCM_POLICER_DROP_ENABLE);
  19302                         break;
  19303                     default :
  19304                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19305                                         "BAD PARAM(drop) : sel=%d "
  19306                                         "offset=%d, attr=%d value=%d \n"),
  19307                                     sel, pol_offset, attr, attr_value));
  19308                         return BCM_E_PARAM;
  19309                 }
  19310                 pkt_attr_selectors->combine_drop_flags |=
  19311                         combine_attr_data->drop_flags;
  19312                 break;
  19313 
  19314             case bcmPolicerGroupModeAttrPacketTypeIp :
  19315                 pkt_attr_selectors->ip_pkt = 1;
  19316                 switch(attr_value) {
  19317                     case 0 :
  19318                         combine_attr_data->ip_pkt_flags |=
  19319                             _BCM_POLICER_IP_PKT_DISABLE;
  19320                         break;
  19321                     case 1 :
  19322                         combine_attr_data->ip_pkt_flags |=
  19323                             _BCM_POLICER_IP_PKT_ENABLE;
  19324                         break;
  19325                     case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES :
  19326                         combine_attr_data->ip_pkt_flags |=
  19327                             (_BCM_POLICER_IP_PKT_DISABLE |
  19328                              _BCM_POLICER_IP_PKT_ENABLE);
  19329                         break;
  19330                     default :
  19331                         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19332                                         "BAD PARAM(ip_pkt) : sel=%d "
  19333                                         "offset=%d, attr=%d value=%d \n"),
  19334                                     sel, pol_offset, attr, attr_value));
  19335                         return BCM_E_PARAM;
  19336                 }
  19337                 pkt_attr_selectors->combine_ip_pkt_flags |=
  19338                         combine_attr_data->ip_pkt_flags;
  19339                 break;
  19340 
  19341             default :
  19342                 return BCM_E_PARAM;
  19343         }
  19344         combine_attr_data = NULL;
  19345     }
  19346 
  19347     /* Check that all policer offset have all configured attributes */
  19348     for (pol_offset = 0; pol_offset < total_policers; pol_offset++) {
  19349         if (pkt_attr_selectors->cng) {
  19350             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19351                     cng_flags == 0) {
  19352                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19353                                 "color : combination issue... Check"
  19354                                 "params and assign dummy value\n")));
  19355                 return BCM_E_PARAM;
  19356             }
  19357         }
  19358         if (pkt_attr_selectors->int_pri) {
  19359             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19360                     int_pri_flags == 0) {
  19361                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19362                                 "int_pri : combination issue... Check"
  19363                                 "params and assign dummy value\n")));
  19364                 return BCM_E_PARAM;
  19365             }
  19366         }
  19367         if (pkt_attr_selectors->vlan_format) {
  19368             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19369                     vlan_format_flags == 0) {
  19370                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19371                                 "vlan_format : combination issue... Check"
  19372                                 "params and assign dummy value\n")));
  19373                 return BCM_E_PARAM;
  19374             }
  19375         }
  19376         if (pkt_attr_selectors->outer_dot1p) {
  19377             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19378                     outer_dot1p_flags == 0) {
  19379                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19380                                 "outer_dot1p : combination issue... Check"
  19381                                 "params and assign dummy value\n")));
  19382                 return BCM_E_PARAM;
  19383             }
  19384         }
  19385         if (pkt_attr_selectors->inner_dot1p) {
  19386             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19387                     inner_dot1p_flags == 0) {
  19388                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19389                                 "inner_dot1p : combination issue... Check"
  19390                                 "params and assign dummy value\n")));
  19391                 return BCM_E_PARAM;
  19392             }
  19393         }
  19394         if (pkt_attr_selectors->port) {
  19395             for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) {
  19396                 if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19397                         value_array[_bcmPolicerAttrPort][index] != 0) {
  19398                     break;
  19399                 }
  19400             }
  19401             if (index == _BCM_POLICER_BIT_ARRAY_SIZE) {
  19402                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19403                                 "ing_port : combination issue... Check"
  19404                                 "params and assign dummy value\n")));
  19405                 return BCM_E_PARAM;
  19406             }
  19407         }
  19408         if (pkt_attr_selectors->tos_dscp) {
  19409             for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) {
  19410                 if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19411                         value_array[_bcmPolicerAttrTosDscp][index] != 0) {
  19412                     break;
  19413                 }
  19414             }
  19415             if (index == _BCM_POLICER_BIT_ARRAY_SIZE) {
  19416                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19417                                 "tos_dscp : combination issue... Check"
  19418                                 "params and assign dummy value\n")));
  19419                 return BCM_E_PARAM;
  19420             }
  19421         }
  19422         if (pkt_attr_selectors->tos_ecn) {
  19423             for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) {
  19424                 if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19425                         value_array[_bcmPolicerAttrTosEcn][index] != 0) {
  19426                     break;
  19427                 }
  19428             }
  19429             if (index == _BCM_POLICER_BIT_ARRAY_SIZE) {
  19430                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19431                                 "tos_ecn : combination issue... Check"
  19432                                 "params and assign dummy value\n")));
  19433                 return BCM_E_PARAM;
  19434             }
  19435         }
  19436         if (pkt_attr_selectors->pkt_resolution) {
  19437             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19438                     pkt_resolution_flags == 0) {
  19439                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19440                                 "pkt_res : combination issue... Check"
  19441                                 "params and assign dummy value\n")));
  19442                 return BCM_E_PARAM;
  19443             }
  19444         }
  19445         if (pkt_attr_selectors->svp_type) {
  19446             for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) {
  19447                 if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19448                         value_array[_bcmPolicerAttrSvpType][index] != 0) {
  19449                     break;
  19450                 }
  19451             }
  19452             if (index == _BCM_POLICER_BIT_ARRAY_SIZE) {
  19453                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19454                                 "svp_type : combination issue... Check"
  19455                                 "params and assign dummy value\n")));
  19456                 return BCM_E_PARAM;
  19457             }
  19458         }
  19459         if (pkt_attr_selectors->drop) {
  19460             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19461                     drop_flags == 0) {
  19462                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19463                                 "drop : combination issue... Check"
  19464                                 "params and assign dummy value\n")));
  19465                 return BCM_E_PARAM;
  19466             }
  19467         }
  19468         if (pkt_attr_selectors->ip_pkt) {
  19469             if (pkt_attr_selectors->combine_attr_data[pol_offset].
  19470                     ip_pkt_flags == 0) {
  19471                 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  19472                                 "ip_pkt : combination issue... Check"
  19473                                 "params and assign dummy value\n")));
  19474                 return BCM_E_PARAM;
  19475             }
  19476         }
  19477     }
  19478     pkt_attr_selectors->total_policers = total_policers;
  19479     pkt_attr_selectors->total_selectors = num_selectors;
  19480     return BCM_E_NONE;
  19481 }
  19482 
  19483 /*
  19484  * Function:
  19485  *      _bcm_policer_group_mode_offset_map_generate
  19486  * Purpose:
  19487  *      This internal function is used to calculate final offset locations
  19488  *      in offset_map where policer_offset needs to be put
  19489  * Parameters:
  19490  *     unit                  - (IN) unit number
  19491  *     meter_attr            - (IN/OUT) Meter attributes
  19492  *     group_mode            - (IN) group mode of policer group
  19493  *     policer_policers      - (IN) policer offset
  19494  *     offset_array          - (IN) 2D array which stores shifted attr_values
  19495  * Returns:
  19496  *     NONE
  19497  */
  19498 STATIC
  19499 int _bcm_policer_group_mode_offset_map_generate(
  19500     int unit,
  19501     bcm_policer_svc_meter_attr_t *meter_attr,
  19502     bcm_policer_group_mode_t group_mode,
  19503     int pol_offset,
  19504     uint8 **offset_array)
  19505 {
  19506     int rv = BCM_E_NONE;
  19507     uint32 offset = 0, final_offset = 0;
  19508     uint32 count = 0, row = 0, index = 0;
  19509     uint32 stack_offset[SVC_METER_MAX_SELECTOR_BITS] = {0};
  19510     uint32 stack_index[SVC_METER_MAX_SELECTOR_BITS] = {0};
  19511     uint32 top = 0;
  19512 
  19513     /* To generate final offset index at which policer_offset value
  19514      * needs to be written in SVM_OFFSET_TABLE, attr_value belonging to
  19515      * different sub-groups have AND relationship.
  19516      * Following code block generate final offset using OR operator as
  19517      * the caller function already left-shifted values by required number
  19518      * of bits.
  19519      * At offset_array[X][0], count of (left-shifted) attr_values
  19520      * is stored. Actual attr_value is stored from index 1.
  19521      * 'top' is index in stack at which next data is inserted.
  19522      * 'row' denotes moving row-wise in offset_array[][]. Each row in
  19523      * offset_array[][] denotes different sub-group for attr_value
  19524      * stack_offset[row] stores ORed offset computed at till [row-1] (from 0)
  19525      * stack_index[row] stores the index in offset_array[X] upto
  19526      * which, we have used is used to calculate offset in this row.
  19527      */
  19528     /* Example : For offset_array
  19529      * offset_array[0] = {2,   0, 1}
  19530      * offset_array[1] = {3,   2, 3, 4}
  19531      * offset_array[2] = {1,   5}
  19532      * offset_array[3] = {2,   6, 7}
  19533      * offset_array[4] = {0}
  19534      * Final_offsets calculated
  19535      *               =  0|2|5|6, 0|2|5|7, 0|3|5|6, 0|3|5|7,
  19536      *                  0|4|5|6, 0|4|5|7, 1|2|5|6, 1|2|5|7,
  19537      *                  1|3|5|6, 1|3|5|7, 1|4|5|6, 1|4|5|7,
  19538      */
  19539     /* Insert default value in stack, both stack_offset[] and stack_index[]
  19540      * is initialized with 0 as none of the index is used to compute offset
  19541      */
  19542     if (offset_array[0][0] != 0) {
  19543         stack_offset[top] = 0;
  19544         stack_index[top] = 0;
  19545         top++;
  19546     }
  19547 
  19548     while (top != 0) {
  19549         row = top - 1;
  19550         /* Get data from Stack */
  19551         index = stack_index[row];
  19552         offset = stack_offset[row];
  19553 
  19554         if (index == offset_array[row][0]) {
  19555             /* All attr_values at this row is used up to calculate
  19556              * offset, go back one row */
  19557             /* Intentionally left blank */
  19558             ;
  19559         }
  19560         else if ((row < (SVC_METER_MAX_SELECTOR_BITS - 1))
  19561                             && (offset_array[row + 1][0] != 0)) {
  19562             /* Next row have data, push current row to stack */
  19563             stack_offset[top] = offset |
  19564                         offset_array[row][index + 1];
  19565             stack_index[top] = 0;
  19566             top++;
  19567             continue;
  19568         } else {
  19569             /* This is last row which have data. Need to compute final
  19570              * index and populate offset_map */
  19571             for (count = 0;
  19572                     count < offset_array[row][0];
  19573                     count++) {
  19574                 final_offset = offset | offset_array[row][ count + 1];
  19575                 rv = _bcm_esw_svc_meter_offset_map_update(unit,
  19576                         meter_attr, group_mode, final_offset, pol_offset);
  19577                 BCM_IF_ERROR_RETURN(rv);
  19578             }
  19579         }
  19580         /* Pop last row */
  19581         top--;
  19582         if (top != 0) {
  19583             /* Increment index for this row */
  19584             row = top - 1;
  19585             stack_index[row] = stack_index[row] + 1;
  19586         }
  19587     }
  19588 
  19589     return BCM_E_NONE;
  19590 }
  19591 
  19592 /*
  19593  * Function:
  19594  *      _bcm_policer_svm_pkt_attr_bits_get
  19595  * Purpose:
  19596  *      This internal function is used to get the number of
  19597  *      bits required for attribute in uncompressed mode
  19598  * Parameters:
  19599  *     unit                  - (IN) unit number
  19600  *     pkt_attr              - (IN) packet attribute
  19601  * Returns:
  19602  *     Number of bits in uncompressed mode
  19603  */
  19604 
  19605 STATIC
  19606 int _bcm_policer_svm_pkt_attr_bits_get(
  19607     int unit,
  19608     pkt_attrs_t pkt_attr)
  19609 {
  19610     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
  19611 
  19612     pkt_attr_bit_pos =
  19613             BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos;
  19614 
  19615     return (pkt_attr_bit_pos[pkt_attr].end_bit -
  19616             pkt_attr_bit_pos[pkt_attr].start_bit + 1);
  19617 }
  19618 
  19619 /*
  19620  * Function:
  19621  *      _bcm_policer_svm_cmprsd_pkt_attr_bits_get
  19622  * Purpose:
  19623  *      This internal function is used to get the number of
  19624  *      bits required for attribute in compressed mode
  19625  * Parameters:
  19626  *     unit                  - (IN) unit number
  19627  *     pkt_attr              - (IN) packet attribute
  19628  * Returns:
  19629  *     Number of bits in uncompressed mode
  19630  */
  19631 
  19632 STATIC
  19633 int _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  19634     int unit,
  19635     pkt_attrs_t pkt_attr)
  19636 {
  19637     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
  19638 
  19639     pkt_attr_bit_pos =
  19640             BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos;
  19641 
  19642     return (pkt_attr_bit_pos[pkt_attr].end_bit -
  19643             pkt_attr_bit_pos[pkt_attr].start_bit + 1);
  19644 }
  19645 
  19646 /*
  19647  * Function:
  19648  *      _bcm_policer_num_of_bits_get
  19649  * Purpose:
  19650  *      This internal function is used to determine number
  19651  *      of bits required for the given value
  19652  * Parameters:
  19653  *     value                  - (IN) number
  19654  * Returns:
  19655  *     Number of bits
  19656  */
  19657 STATIC
  19658 uint8 _bcm_policer_num_of_bits_get(uint8 values)
  19659 {
  19660     if (values <= 2) {
  19661         return 1;
  19662     }
  19663     if (values <= 4) {
  19664         return 2;
  19665     }
  19666     if (values <= 8) {
  19667         return 3;
  19668     }
  19669     if (values <= 16) {
  19670         return 4;
  19671     }
  19672     if (values <= 32) {
  19673         return 5;
  19674     }
  19675     if (values <= 64) {
  19676         return 6;
  19677     }
  19678     if (values <= 128) {
  19679         return 7;
  19680     }
  19681 
  19682     return 8;
  19683 }
  19684 
  19685 /*
  19686  * Function:
  19687  *      _bcm_esw_svm_pkt_compressed_attr_maps_match
  19688  * Purpose:
  19689  *      This internal function is used to match attributes and its
  19690  *      corresponding values with global compressed attr maps. If the
  19691  *      matchin creteria is not satisfied, error is returned. Else
  19692  *      combined attr selectors are updated with global attr value flags
  19693  *      for further processing.
  19694  * Parameters:
  19695  *     uint                   - (IN) Unit number
  19696  *     pkt_attr_selectors     - (IN/OUT) packet attribute selectors
  19697  * Returns:
  19698  *     BCM_E_PARAM, if match fails
  19699  *     BCM_E_XXX
  19700  */
  19701 STATIC
  19702 int _bcm_esw_svm_pkt_compressed_attr_maps_validate(
  19703     int unit,
  19704     bcm_policer_attr_selectors_t *pkt_attr_selectors)
  19705 {
  19706     int rv = BCM_E_NONE;
  19707     uint32 i = 0;
  19708     uint32 combine_flags1 = 0;
  19709     uint32 combine_flags2 = 0;
  19710     uint32 combine_flags3 = 0;
  19711     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
  19712 
  19713     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
  19714 
  19715     if ((pkt_attr_selectors->cng != 0) ||
  19716             (pkt_attr_selectors->int_pri != 0)) {
  19717         /* If ref_count is non-zero, match attribute values. */
  19718         if (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map] != 0) {
  19719             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_cng_flags,
  19720                     &cmprsd_attr_maps->combine_cng_flags,
  19721                     0, 32, &combine_flags1);
  19722             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_int_pri_flags,
  19723                     &cmprsd_attr_maps->combine_int_pri_flags,
  19724                     0, 32, &combine_flags2);
  19725 
  19726             if ((combine_flags1 !=
  19727                         cmprsd_attr_maps->combine_cng_flags) ||
  19728                     (combine_flags2 !=
  19729                      cmprsd_attr_maps->combine_int_pri_flags)) {
  19730                 return BCM_E_PARAM;
  19731             }
  19732             /* Update combined flags */
  19733             pkt_attr_selectors->combine_cng_flags = combine_flags1;
  19734             pkt_attr_selectors->combine_int_pri_flags = combine_flags2;
  19735         }
  19736     }
  19737 
  19738     if ((pkt_attr_selectors->vlan_format != 0) ||
  19739             (pkt_attr_selectors->outer_dot1p) ||
  19740             (pkt_attr_selectors->inner_dot1p)) {
  19741         /* If ref_count is non-zero, match attribute values. */
  19742         if (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map] != 0) {
  19743             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_vlan_format_flags,
  19744                     &cmprsd_attr_maps->combine_vlan_format_flags,
  19745                     0, 32, &combine_flags1);
  19746             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_outer_dot1p_flags,
  19747                     &cmprsd_attr_maps->combine_outer_dot1p_flags,
  19748                     0, 32, &combine_flags2);
  19749             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_inner_dot1p_flags,
  19750                     &cmprsd_attr_maps->combine_inner_dot1p_flags,
  19751                     0, 32, &combine_flags3);
  19752 
  19753             if ((combine_flags1 !=
  19754                         cmprsd_attr_maps->combine_vlan_format_flags) ||
  19755                     (combine_flags2 !=
  19756                      cmprsd_attr_maps->combine_outer_dot1p_flags) ||
  19757                     (combine_flags3 !=
  19758                      cmprsd_attr_maps->combine_inner_dot1p_flags)) {
  19759                 return BCM_E_PARAM;
  19760             }
  19761             /* Update combined flags */
  19762             pkt_attr_selectors->combine_vlan_format_flags = combine_flags1;
  19763             pkt_attr_selectors->combine_outer_dot1p_flags = combine_flags2;
  19764             pkt_attr_selectors->combine_inner_dot1p_flags = combine_flags3;
  19765         }
  19766     }
  19767 
  19768     if (pkt_attr_selectors->port != 0) {
  19769         /* If ref_count is non-zero, match attribute values */
  19770         if (cmprsd_attr_maps->ref_counts[pkt_attr_port_map] != 0) {
  19771             for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19772                 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array
  19773                         [_bcmPolicerAttrPort][i],
  19774                         &cmprsd_attr_maps->combine_value_array
  19775                         [_bcmPolicerAttrPort][i],
  19776                         0, 32, & combine_flags1);
  19777                 if (combine_flags1 != cmprsd_attr_maps->combine_value_array
  19778                         [_bcmPolicerAttrPort][i]) {
  19779                     return BCM_E_PARAM;
  19780                 }
  19781                 /* Update combined flags */
  19782                 pkt_attr_selectors->combine_value_array
  19783                     [_bcmPolicerAttrPort][i] = combine_flags1;
  19784             }
  19785         }
  19786     }
  19787 
  19788     if ((pkt_attr_selectors->tos_dscp != 0) ||
  19789             (pkt_attr_selectors->tos_ecn)) {
  19790         /* If ref_count is non-zero, match attribute values. */
  19791         if (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map] != 0) {
  19792             for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19793                 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array
  19794                         [_bcmPolicerAttrTosDscp][i],
  19795                         &cmprsd_attr_maps->combine_value_array
  19796                         [_bcmPolicerAttrTosDscp][i],
  19797                         0, 32, & combine_flags1);
  19798                 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array
  19799                         [_bcmPolicerAttrTosEcn][i],
  19800                         &cmprsd_attr_maps->combine_value_array
  19801                         [_bcmPolicerAttrTosEcn][i],
  19802                         0, 32, & combine_flags2);
  19803                 if ((combine_flags1 != cmprsd_attr_maps->combine_value_array
  19804                             [_bcmPolicerAttrTosDscp][i]) ||
  19805                         (combine_flags2 != cmprsd_attr_maps->combine_value_array
  19806                          [_bcmPolicerAttrTosEcn][i])) {
  19807                     return BCM_E_PARAM;
  19808                 }
  19809                 /* Update combined flags */
  19810                 pkt_attr_selectors->combine_value_array
  19811                     [_bcmPolicerAttrTosDscp][i] = combine_flags1;
  19812                 pkt_attr_selectors->combine_value_array
  19813                     [_bcmPolicerAttrTosEcn][i] = combine_flags2;
  19814             }
  19815         }
  19816     }
  19817 
  19818     if ((pkt_attr_selectors->pkt_resolution != 0) ||
  19819             (pkt_attr_selectors->svp_type) ||
  19820             (pkt_attr_selectors->drop)) {
  19821         /* If ref_count is non-zero, match */
  19822         if (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map] != 0) {
  19823             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_pkt_res_flags,
  19824                     &cmprsd_attr_maps->combine_pkt_res_flags,
  19825                     0, 32, &combine_flags1);
  19826             SHR_BITOR_RANGE(&pkt_attr_selectors->combine_drop_flags,
  19827                     &cmprsd_attr_maps->combine_drop_flags,
  19828                     0, 32, &combine_flags2);
  19829             if ((combine_flags1 != cmprsd_attr_maps->combine_pkt_res_flags) ||
  19830                     (combine_flags2 != cmprsd_attr_maps->combine_drop_flags)) {
  19831                 return BCM_E_PARAM;
  19832             }
  19833             for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19834                 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array
  19835                         [_bcmPolicerAttrSvpType][i],
  19836                         &cmprsd_attr_maps->combine_value_array
  19837                         [_bcmPolicerAttrSvpType][i],
  19838                         0, 32, & combine_flags3);
  19839                 if (combine_flags3 != cmprsd_attr_maps->combine_value_array
  19840                         [_bcmPolicerAttrSvpType][i]) {
  19841                     return BCM_E_PARAM;
  19842                 }
  19843                 /* Update combined flags */
  19844                 pkt_attr_selectors->combine_value_array
  19845                     [_bcmPolicerAttrSvpType][i] = combine_flags3;
  19846             }
  19847             /* Update combine_xxx_flags */
  19848             pkt_attr_selectors->combine_pkt_res_flags = combine_flags1;
  19849             pkt_attr_selectors->combine_drop_flags = combine_flags2;
  19850         }
  19851     }
  19852 
  19853     return rv;
  19854 }
  19855 
  19856 /*
  19857  * Function:
  19858  *      _bcm_esw_svm_pkt_compressed_attr_maps_update
  19859  * Purpose:
  19860  *      This internal function is used to update global compressed attr maps
  19861  *      with pkt attr selectors.
  19862  * Parameters:
  19863  *     uint                   - (IN) Unit number
  19864  *     pkt_attr_selectors     - (IN) packet attribute selectors
  19865  * Returns:
  19866  *     BCM_E_XXX
  19867  */
  19868 STATIC
  19869 int _bcm_esw_svm_pkt_compressed_attr_maps_update(
  19870     int unit,
  19871     bcm_policer_attr_selectors_t *pkt_attr_selectors)
  19872 {
  19873     int rv = BCM_E_NONE;
  19874     uint32 i = 0;
  19875     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
  19876 
  19877     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
  19878 
  19879     if (pkt_attr_selectors->cng) {
  19880         cmprsd_attr_maps->combine_cng_flags =
  19881             pkt_attr_selectors->combine_cng_flags;
  19882     }
  19883     if (pkt_attr_selectors->int_pri != 0) {
  19884         cmprsd_attr_maps->combine_int_pri_flags =
  19885             pkt_attr_selectors->combine_int_pri_flags;
  19886     }
  19887     if (pkt_attr_selectors->vlan_format != 0) {
  19888         cmprsd_attr_maps->combine_vlan_format_flags =
  19889             pkt_attr_selectors->combine_vlan_format_flags;
  19890     }
  19891     if (pkt_attr_selectors->outer_dot1p != 0) {
  19892         cmprsd_attr_maps->combine_outer_dot1p_flags =
  19893             pkt_attr_selectors->combine_outer_dot1p_flags;
  19894     }
  19895     if (pkt_attr_selectors->inner_dot1p != 0) {
  19896         cmprsd_attr_maps->combine_inner_dot1p_flags =
  19897             pkt_attr_selectors->combine_inner_dot1p_flags;
  19898     }
  19899     if (pkt_attr_selectors->port != 0) {
  19900         for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19901             cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrPort][i] =
  19902                 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrPort][i];
  19903         }
  19904     }
  19905     if (pkt_attr_selectors->tos_dscp != 0) {
  19906         for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19907             cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosDscp][i] =
  19908                 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrTosDscp][i];
  19909         }
  19910     }
  19911     if (pkt_attr_selectors->tos_ecn != 0) {
  19912         for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19913             cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosEcn][i] =
  19914                 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrTosEcn][i];
  19915         }
  19916     }
  19917     if (pkt_attr_selectors->pkt_resolution != 0) {
  19918         cmprsd_attr_maps->combine_pkt_res_flags =
  19919             pkt_attr_selectors->combine_pkt_res_flags;
  19920     }
  19921     if (pkt_attr_selectors->svp_type != 0) {
  19922         for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  19923             cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrSvpType][i] =
  19924                 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrSvpType][i];
  19925         }
  19926     }
  19927     if (pkt_attr_selectors->drop != 0) {
  19928         cmprsd_attr_maps->combine_drop_flags =
  19929             pkt_attr_selectors->combine_drop_flags;
  19930     }
  19931     if (pkt_attr_selectors->ip_pkt != 0) {
  19932         cmprsd_attr_maps->combine_ip_pkt_flags =
  19933             pkt_attr_selectors->combine_ip_pkt_flags;
  19934     }
  19935 
  19936     return rv;
  19937 }
  19938 
  19939 /*
  19940  * Function:
  19941  *      _bcm_esw_policer_group_mode_id_associate
  19942  * Purpose:
  19943  *      This function is used to
  19944  *      1. Create offset map for compressed or uncompressed mode
  19945  *       based on number of bits required for the given input selectors
  19946  *      2. Reserve svm meter mode and update h/w register/table
  19947  * Parameters:
  19948  *     unit                  - (IN) unit number
  19949  *     flags                 - (IN) flags
  19950  *     type                  - (IN) type of group mode
  19951  *     pkt_attr_selectors    - (IN) stores data about selectors
  19952  *     mode_id               - (OUT) mode which used by policer group
  19953  * Returns:
  19954  *     BCM_E_XXX
  19955  */
  19956 STATIC
  19957 bcm_error_t _bcm_esw_policer_group_mode_id_associate(
  19958     int unit,
  19959     uint32 flags,
  19960     uint32 type,
  19961     bcm_policer_attr_selectors_t *pkt_attr_selectors,
  19962     uint32 *mode_id)
  19963 {
  19964     int rv = BCM_E_NONE;
  19965     uint8 invalid_index0 = FALSE;
  19966     uint8 invalid_index1 = FALSE;
  19967     uint8 invalid_index2 = FALSE;
  19968     uint8 unused_found = FALSE;
  19969     uint32 pol_offset = 0;
  19970     uint32 total_bits = 0;
  19971     uint32 shift_by_bits = 0;
  19972     uint32 cng_bits = 0;
  19973     uint32 int_pri_bits = 0;
  19974     uint32 vlan_format_bits = 0;
  19975     uint32 outer_dot1p_bits = 0;
  19976     uint32 inner_dot1p_bits = 0;
  19977     uint32 ing_port_bits = 0;
  19978     uint32 pkt_res_bits = 0;
  19979     uint32 svp_type_bits = 0;
  19980     uint32 drop_bits = 0;
  19981     uint32 ip_pkt_bits = 0;
  19982     uint32 tos_dscp_bits = 0;
  19983     uint32 tos_ecn_bits = 0;
  19984     uint32 max_bits = 0;
  19985     uint32 loop = 0;
  19986     uint32 temp_count = 0;
  19987     uint32 value = 0;
  19988     uint32 invalid_map_value = 0;
  19989     uint32 logical_group_bits = 0;
  19990     uint32 values = 0, values_max = 0;
  19991     uint32 index0 = 0, index1 = 0, index2 = 0;
  19992     uint32 final_index = 0, final_mapped_value = 0;
  19993     uint32 mapped_value0 = 0, mapped_value1 = 0, mapped_value2 = 0;
  19994     uint32 cng_cmprsd_bits = 0;
  19995     uint32 int_pri_cmprsd_bits = 0;
  19996     uint32 vlan_format_cmprsd_bits = 0;
  19997     uint32 outer_dot1p_cmprsd_bits = 0;
  19998     uint32 inner_dot1p_cmprsd_bits = 0;
  19999     uint32 ing_port_cmprsd_bits = 0, ing_port_attrs = 0;
  20000     uint32 pkt_res_cmprsd_bits = 0;
  20001     uint32 svp_type_cmprsd_bits = 0, svp_type_attrs = 0;
  20002     uint32 drop_cmprsd_bits = 0;
  20003     uint32 ip_pkt_cmprsd_bits = 0;
  20004     uint32 tos_dscp_cmprsd_bits = 0, tos_dscp_attrs = 0;
  20005     uint32 tos_ecn_cmprsd_bits = 0, tos_ecn_attrs = 0;
  20006     uint8 *pkt_res = NULL;
  20007     uint8 *map_array[bcmPolicerGroupModeAttrCount] = {NULL};
  20008     uint8 *offset_array[SVC_METER_MAX_SELECTOR_BITS] = {NULL};
  20009     uncompressed_attr_selectors_t *uncmprsd_attr_selectors = NULL;
  20010     compressed_attr_selectors_t *cmprsd_attr_selectors = NULL;
  20011     bcm_policer_svc_meter_attr_t *meter_attr = NULL;
  20012     bcm_policer_group_mode_t group_mode;
  20013     bcm_policer_combine_attr_t  *combine_attr_data = NULL;
  20014     _bcm_policer_pkt_attr_bit_pos_t *cmprsd_pkt_attr_bit_pos = NULL;
  20015 
  20016     if (BCM_SVM_DEV_ATTR(unit)->pkt_resolution != NULL) {
  20017         pkt_res = BCM_SVM_DEV_ATTR(unit)->pkt_resolution;
  20018     } else {
  20019         return (BCM_E_UNAVAIL);
  20020     }
  20021 
  20022     meter_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t),
  20023             "meter mode attr");
  20024     if (meter_attr == NULL) {
  20025         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  20026                 (BSL_META_U(unit,
  20027                             "Failed to allocate memory for meter attr\n")));
  20028         return BCM_E_MEMORY;
  20029     }
  20030     sal_memset(meter_attr, 0, sizeof(bcm_policer_svc_meter_attr_t));
  20031 
  20032     /* bcm_policer_group_mode_t should be based on type */
  20033     if (type == bcmPolicerGroupModeTypeNormal) {
  20034         group_mode = bcmPolicerGroupModeSingle;
  20035     } else if (type == bcmPolicerGroupModeTypeCascade) {
  20036         group_mode = bcmPolicerGroupModeCascade;
  20037     } else {  /* type == bcmPolicerGroupModeTypeCascadeWithCoupling */
  20038         group_mode = bcmPolicerGroupModeCascadeWithCoupling;
  20039     }
  20040 
  20041     /* Calcuate total bits req. to determine compressed/uncompressed mode */
  20042     if (pkt_attr_selectors->cng == 1) {
  20043         total_bits += (cng_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20044                     unit, pkt_attr_cng));
  20045     }
  20046     if (pkt_attr_selectors->int_pri == 1) {
  20047         total_bits += (int_pri_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20048                     unit, pkt_attr_int_pri));
  20049     }
  20050     if (pkt_attr_selectors->vlan_format == 1) {
  20051         total_bits += (vlan_format_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20052                     unit, pkt_attr_vlan_format));
  20053     }
  20054     if (pkt_attr_selectors->outer_dot1p == 1) {
  20055         total_bits += (outer_dot1p_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20056                     unit, pkt_attr_outer_dot1p));
  20057     }
  20058     if (pkt_attr_selectors->inner_dot1p == 1) {
  20059         total_bits += (inner_dot1p_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20060                     unit, pkt_attr_inner_dot1p));
  20061     }
  20062     if (pkt_attr_selectors->port == 1) {
  20063         total_bits += (ing_port_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20064                     unit, pkt_attr_ing_port));
  20065     }
  20066     if (pkt_attr_selectors->tos_dscp == 1) {
  20067         total_bits += (tos_dscp_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20068                     unit, pkt_attr_tos));
  20069     }
  20070     if (pkt_attr_selectors->tos_ecn == 1) {
  20071         total_bits += (tos_ecn_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20072                     unit, pkt_attr_tos_ecn));
  20073     }
  20074     if (pkt_attr_selectors->pkt_resolution == 1) {
  20075         total_bits += (pkt_res_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20076                     unit, pkt_attr_pkt_resolution));
  20077     }
  20078     if (pkt_attr_selectors->svp_type == 1) {
  20079         total_bits += (svp_type_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20080                     unit, pkt_attr_drop));
  20081     }
  20082     if (pkt_attr_selectors->drop == 1) {
  20083         total_bits += (drop_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20084                     unit, pkt_attr_drop));
  20085     }
  20086     if (pkt_attr_selectors->ip_pkt == 1) {
  20087         total_bits += (ip_pkt_bits = _bcm_policer_svm_pkt_attr_bits_get(
  20088                     unit, pkt_attr_ip_pkt));
  20089     }
  20090 
  20091     if (total_bits <= BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
  20092         /* Mode : Uncompressed */
  20093         uncmprsd_attr_selectors = &(meter_attr->uncompressed_attr_selectors_v);
  20094         meter_attr->mode_type_v = uncompressed_mode;
  20095 
  20096         /* Fill uncompressed_attr_bits_selector */
  20097         if (pkt_attr_selectors->cng == 1) {
  20098             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20099                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS;
  20100         }
  20101         if (pkt_attr_selectors->int_pri == 1) {
  20102             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20103                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS;
  20104         }
  20105         if (pkt_attr_selectors->vlan_format == 1) {
  20106             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20107                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS;
  20108         }
  20109         if (pkt_attr_selectors->outer_dot1p == 1) {
  20110             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20111                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS;
  20112         }
  20113         if (pkt_attr_selectors->inner_dot1p == 1) {
  20114             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20115                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS;
  20116         }
  20117         if (pkt_attr_selectors->port == 1) {
  20118             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20119                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS;
  20120         }
  20121         if (pkt_attr_selectors->tos_dscp == 1) {
  20122             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20123                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS;
  20124         }
  20125         if (pkt_attr_selectors->tos_ecn == 1) {
  20126             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20127                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS;
  20128         }
  20129         if (pkt_attr_selectors->pkt_resolution == 1) {
  20130             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20131                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS;
  20132         }
  20133         if (pkt_attr_selectors->svp_type == 1) {
  20134             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20135                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS;
  20136         }
  20137         if (pkt_attr_selectors->drop == 1) {
  20138             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20139                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS;
  20140         }
  20141         if (pkt_attr_selectors->ip_pkt == 1) {
  20142             uncmprsd_attr_selectors->uncompressed_attr_bits_selector |=
  20143                 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS;
  20144         }
  20145 
  20146         /* Fill offset_map field of uncompressed_attr_selectors_v */
  20147         /* Step 1 Reset all values in offset_map */
  20148         sal_memset(uncmprsd_attr_selectors->offset_map, 0,
  20149                 sizeof (uncmprsd_attr_selectors->offset_map));
  20150 
  20151         for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  20152             offset_array[loop] = (uint8 *) sal_alloc(
  20153                     BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1,"offset_array");
  20154             if (offset_array[loop] == NULL) {
  20155                 rv = BCM_E_MEMORY;
  20156                 break;
  20157             }
  20158         }
  20159         if (BCM_FAILURE(rv)) {
  20160             /* Free offset_array */
  20161             for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  20162                 if (offset_array[loop] != NULL) {
  20163                     sal_free(offset_array[loop]);
  20164                 }
  20165             }
  20166             sal_free(meter_attr);
  20167             return rv;
  20168         }
  20169 
  20170         /* Step 2 Calculate offset value for each policer_offset  */
  20171         for (pol_offset = 0;
  20172                 pol_offset < pkt_attr_selectors->total_policers;
  20173                 pol_offset++ ) {
  20174             combine_attr_data =
  20175                 &pkt_attr_selectors->combine_attr_data[pol_offset];
  20176             /* Step 2.1 : Reset offset_array */
  20177             for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  20178                 sal_memset(offset_array[loop], 0,
  20179                         BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1);
  20180             }
  20181             loop = 0;
  20182 
  20183             /* Step 2.2 : Parse through each attr type and save values */
  20184             if ((pkt_attr_selectors->cng == 1) &&
  20185                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20186                 shift_by_bits = int_pri_bits +
  20187                     vlan_format_bits +
  20188                     outer_dot1p_bits +
  20189                     inner_dot1p_bits +
  20190                     ing_port_bits +
  20191                     tos_dscp_bits +
  20192                     tos_ecn_bits +
  20193                     pkt_res_bits +
  20194                     svp_type_bits +
  20195                     drop_bits +
  20196                     ip_pkt_bits;
  20197 
  20198                 temp_count = offset_array[loop][0];
  20199                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_GREEN) {
  20200                     offset_array[loop][temp_count + 1] = (0 << shift_by_bits);
  20201                     temp_count++;
  20202                 }
  20203                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_YELLOW) {
  20204                     offset_array[loop][temp_count + 1] = (1 << shift_by_bits);
  20205                     temp_count++;
  20206                 }
  20207                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_RED) {
  20208                     offset_array[loop][temp_count + 1] = (3 << shift_by_bits);
  20209                     temp_count++;
  20210                 }
  20211                 offset_array[loop][0] = temp_count;
  20212                 loop++;
  20213             }
  20214             if ((pkt_attr_selectors->int_pri == 1) &&
  20215                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20216                 shift_by_bits = vlan_format_bits +
  20217                     outer_dot1p_bits +
  20218                     inner_dot1p_bits +
  20219                     ing_port_bits +
  20220                     tos_dscp_bits +
  20221                     tos_ecn_bits +
  20222                     pkt_res_bits +
  20223                     svp_type_bits +
  20224                     drop_bits +
  20225                     ip_pkt_bits;
  20226 
  20227                 temp_count = offset_array[loop][0];
  20228                 for(index0 = _BCM_POLICER_PKT_PRI0;
  20229                         index0 <= _BCM_POLICER_PKT_PRI15; index0++) {
  20230                     if (combine_attr_data->int_pri_flags & (1 << index0)) {
  20231                         offset_array[loop][temp_count + 1] =
  20232                             (index0 << shift_by_bits);
  20233                         temp_count++;
  20234                     }
  20235                 }
  20236                 offset_array[loop][0] = temp_count;
  20237                 loop++;
  20238             }
  20239             if ((pkt_attr_selectors->vlan_format == 1) &&
  20240                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20241                 shift_by_bits = outer_dot1p_bits +
  20242                     inner_dot1p_bits +
  20243                     ing_port_bits +
  20244                     tos_dscp_bits +
  20245                     tos_ecn_bits +
  20246                     pkt_res_bits +
  20247                     svp_type_bits +
  20248                     drop_bits +
  20249                     ip_pkt_bits;
  20250                 temp_count = offset_array[loop][0];
  20251                 if(combine_attr_data->vlan_format_flags &
  20252                         _BCM_POLICER_VLAN_FORMAT_UNTAGGED) {
  20253                     offset_array[loop][temp_count + 1] = (0 << shift_by_bits);
  20254                     temp_count++;
  20255                 }
  20256                 if(combine_attr_data->vlan_format_flags &
  20257                         _BCM_POLICER_VLAN_FORMAT_INNER) {
  20258                     offset_array[loop][temp_count + 1] = (1 << shift_by_bits);
  20259                     temp_count++;
  20260                 }
  20261                 if(combine_attr_data->vlan_format_flags &
  20262                         _BCM_POLICER_VLAN_FORMAT_OUTER) {
  20263                     offset_array[loop][temp_count + 1] = (2 << shift_by_bits);
  20264                     temp_count++;
  20265                 }
  20266                 if(combine_attr_data->vlan_format_flags &
  20267                         _BCM_POLICER_VLAN_FORMAT_BOTH) {
  20268                     offset_array[loop][temp_count + 1] = (3 << shift_by_bits);
  20269                     temp_count++;
  20270                 }
  20271                 offset_array[loop][0] = temp_count;
  20272                 loop++;
  20273             }
  20274             if ((pkt_attr_selectors->outer_dot1p == 1) &&
  20275                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20276                 shift_by_bits = inner_dot1p_bits +
  20277                     ing_port_bits +
  20278                     tos_dscp_bits +
  20279                     tos_ecn_bits +
  20280                     pkt_res_bits +
  20281                     svp_type_bits +
  20282                     drop_bits +
  20283                     ip_pkt_bits;
  20284                 temp_count = offset_array[loop][0];
  20285                 for(index0 = _BCM_POLICER_PKT_PRI0;
  20286                         index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  20287                     if (combine_attr_data->outer_dot1p_flags & (1 << index0)) {
  20288                         offset_array[loop][temp_count + 1] = (index0 << shift_by_bits);
  20289                         temp_count++;
  20290                     }
  20291                 }
  20292                 offset_array[loop][0] = temp_count;
  20293                 loop++;
  20294             }
  20295             if ((pkt_attr_selectors->inner_dot1p == 1) &&
  20296                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20297                 shift_by_bits = ing_port_bits +
  20298                     tos_dscp_bits +
  20299                     tos_ecn_bits +
  20300                     pkt_res_bits +
  20301                     svp_type_bits +
  20302                     drop_bits +
  20303                     ip_pkt_bits;
  20304                 temp_count = offset_array[loop][0];
  20305                 for(index0 = _BCM_POLICER_PKT_PRI0;
  20306                         index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  20307                     if (combine_attr_data->inner_dot1p_flags & (1 << index0)) {
  20308                         offset_array[loop][temp_count + 1] = (index0 << shift_by_bits);
  20309                         temp_count++;
  20310                     }
  20311                 }
  20312                 offset_array[loop][0] = temp_count;
  20313                 loop++;
  20314             }
  20315             if ((pkt_attr_selectors->port == 1) &&
  20316                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20317                 shift_by_bits = tos_dscp_bits +
  20318                     tos_ecn_bits +
  20319                     pkt_res_bits +
  20320                     svp_type_bits +
  20321                     drop_bits +
  20322                     ip_pkt_bits;
  20323                 ing_port_attrs = soc_mem_index_max(unit, ING_SVM_PORT_MAPm) + 1;
  20324                 for (index0 = 0; index0 < ing_port_attrs; index0++) {
  20325                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  20326                                 value_array[_bcmPolicerAttrPort], index0)) {
  20327                         temp_count = offset_array[loop][0];
  20328                         offset_array[loop][temp_count + 1] = index0 << shift_by_bits;
  20329                         offset_array[loop][0] =  temp_count + 1;
  20330                     }
  20331                 }
  20332                 loop++;
  20333             }
  20334             if ((pkt_attr_selectors->tos_dscp == 1) &&
  20335                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20336                 shift_by_bits = tos_ecn_bits +
  20337                     pkt_res_bits +
  20338                     svp_type_bits +
  20339                     drop_bits +
  20340                     ip_pkt_bits;
  20341                 tos_dscp_attrs = 1 << tos_dscp_bits;
  20342                 for (index0 = 0; index0 < tos_dscp_attrs; index0++) {
  20343                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  20344                                 value_array[_bcmPolicerAttrTosDscp], index0)) {
  20345                         temp_count = offset_array[loop][0];
  20346                         offset_array[loop][temp_count + 1] = index0 << shift_by_bits;
  20347                         offset_array[loop][0] =  temp_count + 1;
  20348                     }
  20349                 }
  20350                 loop++;
  20351             }
  20352             if ((pkt_attr_selectors->tos_ecn == 1) &&
  20353                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20354                 shift_by_bits = pkt_res_bits +
  20355                     svp_type_bits +
  20356                     drop_bits +
  20357                     ip_pkt_bits;
  20358                 tos_ecn_attrs = 1 << tos_ecn_bits;
  20359                 for (index0 = 0; index0 < tos_ecn_attrs; index0++) {
  20360                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  20361                                 value_array[_bcmPolicerAttrTosEcn], index0)) {
  20362                         temp_count = offset_array[loop][0];
  20363                         offset_array[loop][temp_count + 1] = index0 << shift_by_bits;
  20364                         offset_array[loop][0] =  temp_count + 1;
  20365                     }
  20366                 }
  20367                 loop++;
  20368             }
  20369             if ((pkt_attr_selectors->pkt_resolution == 1) &&
  20370                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20371                 shift_by_bits = svp_type_bits +
  20372                     drop_bits +
  20373                     ip_pkt_bits;
  20374                 temp_count = offset_array[loop][0];
  20375                 if (combine_attr_data->pkt_resolution_flags &
  20376                         _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) {
  20377                     offset_array[loop][temp_count + 1] =
  20378                         (pkt_res[UNKNOWN_PKT] << shift_by_bits);
  20379                     temp_count++;
  20380                 }
  20381                 if (combine_attr_data->pkt_resolution_flags &
  20382                         _BCM_POLICER_PKT_TYPE_CONTROL_PKT) {
  20383                     offset_array[loop][temp_count + 1] =
  20384                         (pkt_res[CONTROL_PKT] << shift_by_bits);
  20385                     temp_count++;
  20386                 }
  20387                 if (combine_attr_data->pkt_resolution_flags &
  20388                         _BCM_POLICER_PKT_TYPE_OAM_PKT) {
  20389                     offset_array[loop][temp_count + 1] =
  20390                         (pkt_res[OAM_PKT] << shift_by_bits);
  20391                     temp_count++;
  20392                 }
  20393                 if (combine_attr_data->pkt_resolution_flags &
  20394                         _BCM_POLICER_PKT_TYPE_BFD_PKT) {
  20395                     offset_array[loop][temp_count + 1] =
  20396                         (pkt_res[BFD_PKT] << shift_by_bits);
  20397                     temp_count++;
  20398                 }
  20399                 if (combine_attr_data->pkt_resolution_flags &
  20400                         _BCM_POLICER_PKT_TYPE_BPDU_PKT) {
  20401                     offset_array[loop][temp_count + 1] =
  20402                         (pkt_res[BPDU_PKT] << shift_by_bits);
  20403                     temp_count++;
  20404                 }
  20405                 if (combine_attr_data->pkt_resolution_flags &
  20406                         _BCM_POLICER_PKT_TYPE_ICNM_PKT) {
  20407                     offset_array[loop][temp_count + 1] =
  20408                         (pkt_res[ICNM_PKT] << shift_by_bits);
  20409                     temp_count++;
  20410                 }
  20411                 if (combine_attr_data->pkt_resolution_flags &
  20412                         _BCM_POLICER_PKT_TYPE_PKT_IS_1588) {
  20413                     offset_array[loop][temp_count + 1] =
  20414                         (pkt_res[PKT_IS_1588] << shift_by_bits);
  20415                     temp_count++;
  20416                 }
  20417                 if (combine_attr_data->pkt_resolution_flags &
  20418                         _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) {
  20419                     offset_array[loop][temp_count + 1] =
  20420                         (pkt_res[KNOWN_L2UC_PKT] << shift_by_bits);
  20421                     temp_count++;
  20422                 }
  20423                 if (combine_attr_data->pkt_resolution_flags &
  20424                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) {
  20425                     offset_array[loop][temp_count + 1] =
  20426                         (pkt_res[UNKNOWN_L2UC_PKT] << shift_by_bits);
  20427                     temp_count++;
  20428                 }
  20429                 if (combine_attr_data->pkt_resolution_flags &
  20430                         _BCM_POLICER_PKT_TYPE_L2BC_PKT) {
  20431                     offset_array[loop][temp_count + 1] =
  20432                         (pkt_res[L2BC_PKT] << shift_by_bits);
  20433                     temp_count++;
  20434                 }
  20435                 if (combine_attr_data->pkt_resolution_flags &
  20436                         _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) {
  20437                     offset_array[loop][temp_count + 1] =
  20438                         (pkt_res[KNOWN_L2MC_PKT] << shift_by_bits);
  20439                     temp_count++;
  20440                 }
  20441                 if (combine_attr_data->pkt_resolution_flags &
  20442                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) {
  20443                     offset_array[loop][temp_count + 1] =
  20444                         (pkt_res[UNKNOWN_L2MC_PKT] << shift_by_bits);
  20445                     temp_count++;
  20446                 }
  20447                 if (combine_attr_data->pkt_resolution_flags &
  20448                         _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) {
  20449                     offset_array[loop][temp_count + 1] =
  20450                         (pkt_res[KNOWN_L3UC_PKT] << shift_by_bits);
  20451                     temp_count++;
  20452                 }
  20453                 if (combine_attr_data->pkt_resolution_flags &
  20454                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) {
  20455                     offset_array[loop][temp_count + 1] =
  20456                         (pkt_res[UNKNOWN_L3UC_PKT] << shift_by_bits);
  20457                     temp_count++;
  20458                 }
  20459                 if (combine_attr_data->pkt_resolution_flags &
  20460                         _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) {
  20461                     offset_array[loop][temp_count + 1] =
  20462                         (pkt_res[KNOWN_IPMC_PKT] << shift_by_bits);
  20463                     temp_count++;
  20464                 }
  20465                 if (combine_attr_data->pkt_resolution_flags &
  20466                         _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) {
  20467                     offset_array[loop][temp_count + 1] =
  20468                         (pkt_res[UNKNOWN_IPMC_PKT] << shift_by_bits);
  20469                     temp_count++;
  20470                 }
  20471                 if (combine_attr_data->pkt_resolution_flags &
  20472                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) {
  20473                     offset_array[loop][temp_count + 1] =
  20474                         (pkt_res[KNOWN_MPLS_L2_PKT] << shift_by_bits);
  20475                     temp_count++;
  20476                 }
  20477                 if (combine_attr_data->pkt_resolution_flags &
  20478                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) {
  20479                     offset_array[loop][temp_count + 1] =
  20480                         (pkt_res[KNOWN_MPLS_L3_PKT] << shift_by_bits);
  20481                     temp_count++;
  20482                 }
  20483                 if (combine_attr_data->pkt_resolution_flags &
  20484                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) {
  20485                     offset_array[loop][temp_count + 1] =
  20486                         (pkt_res[KNOWN_MPLS_PKT] << shift_by_bits);
  20487                     temp_count++;
  20488                 }
  20489                 if (combine_attr_data->pkt_resolution_flags &
  20490                         _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) {
  20491                     offset_array[loop][temp_count + 1] =
  20492                         (pkt_res[UNKNOWN_MPLS_PKT] << shift_by_bits);
  20493                     temp_count++;
  20494                 }
  20495                 if (combine_attr_data->pkt_resolution_flags &
  20496                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) {
  20497                     offset_array[loop][temp_count + 1] =
  20498                         (pkt_res[KNOWN_MPLS_MULTICAST_PKT] << shift_by_bits);
  20499                     temp_count++;
  20500                 }
  20501                 if (combine_attr_data->pkt_resolution_flags &
  20502                         _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) {
  20503                     offset_array[loop][temp_count + 1] =
  20504                         (pkt_res[KNOWN_MIM_PKT] << shift_by_bits);
  20505                     temp_count++;
  20506                 }
  20507                 if (combine_attr_data->pkt_resolution_flags &
  20508                         _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) {
  20509                     offset_array[loop][temp_count + 1] =
  20510                         (pkt_res[UNKNOWN_MIM_PKT] << shift_by_bits);
  20511                     temp_count++;
  20512                 }
  20513                 if (combine_attr_data->pkt_resolution_flags &
  20514                         _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) {
  20515                     offset_array[loop][temp_count + 1] =
  20516                         (pkt_res[KNOWN_TRILL_PKT] << shift_by_bits);
  20517                     temp_count++;
  20518                 }
  20519                 if (combine_attr_data->pkt_resolution_flags &
  20520                         _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) {
  20521                     offset_array[loop][temp_count + 1] =
  20522                         (pkt_res[UNKNOWN_TRILL_PKT] << shift_by_bits);
  20523                     temp_count++;
  20524                 }
  20525                 if (combine_attr_data->pkt_resolution_flags &
  20526                         _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) {
  20527                     offset_array[loop][temp_count + 1] =
  20528                         (pkt_res[KNOWN_NIV_PKT] << shift_by_bits);
  20529                     temp_count++;
  20530                 }
  20531                 if (combine_attr_data->pkt_resolution_flags &
  20532                         _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) {
  20533                     offset_array[loop][temp_count + 1] =
  20534                         (pkt_res[UNKNOWN_NIV_PKT] << shift_by_bits);
  20535                     temp_count++;
  20536                 }
  20537                 offset_array[loop][0] = temp_count;
  20538                 loop++;
  20539             }
  20540             if ((pkt_attr_selectors->svp_type == 1) &&
  20541                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20542                 shift_by_bits = drop_bits +
  20543                     ip_pkt_bits;
  20544                 svp_type_attrs = 1 << svp_type_bits;
  20545                 for (index0 = 0; index0 < svp_type_attrs; index0++) {
  20546                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  20547                                 value_array[_bcmPolicerAttrSvpType], index0)) {
  20548                         temp_count = offset_array[loop][0];
  20549                         offset_array[loop][temp_count + 1] = index0 <<
  20550                             shift_by_bits;
  20551                         offset_array[loop][0] =  temp_count + 1;
  20552                     }
  20553                 }
  20554                 loop++;
  20555             }
  20556             if ((pkt_attr_selectors->drop == 1) &&
  20557                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20558                 shift_by_bits = ip_pkt_bits;
  20559                 temp_count = offset_array[loop][0];
  20560                 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_DISABLE) {
  20561                     offset_array[loop][temp_count + 1] = (0 << shift_by_bits);
  20562                     temp_count++;
  20563                 }
  20564                 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_ENABLE) {
  20565                     offset_array[loop][temp_count + 1] = (1 << shift_by_bits);
  20566                     temp_count++;
  20567                 }
  20568                 offset_array[loop][0] = temp_count;
  20569                 loop++;
  20570             }
  20571             if ((pkt_attr_selectors->ip_pkt == 1) &&
  20572                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  20573                 shift_by_bits = 0;
  20574                 temp_count = offset_array[loop][0];
  20575                 if (combine_attr_data->ip_pkt_flags &
  20576                         _BCM_POLICER_IP_PKT_DISABLE) {
  20577                     offset_array[loop][temp_count + 1] = (0 << shift_by_bits);
  20578                     temp_count++;
  20579                 }
  20580                 if (combine_attr_data->ip_pkt_flags &
  20581                         _BCM_POLICER_IP_PKT_ENABLE) {
  20582                     offset_array[loop][temp_count + 1] = (1 << shift_by_bits);
  20583                     temp_count++;
  20584                 }
  20585                 offset_array[loop][0] = temp_count;
  20586                 loop++;
  20587             }
  20588 
  20589             /* Step 2.3 : compute final offset value */
  20590             rv = _bcm_policer_group_mode_offset_map_generate(unit,
  20591                     meter_attr, group_mode, pol_offset, offset_array);
  20592             if (rv != BCM_E_NONE) {
  20593                 break;
  20594             }
  20595         }
  20596     } else {
  20597         /* Mode : Compressed */
  20598         meter_attr->mode_type_v = compressed_mode;
  20599         cmprsd_attr_selectors = &(meter_attr->compressed_attr_selectors_v);
  20600 
  20601         cng_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20602                 unit, pkt_attr_cng);
  20603 
  20604         int_pri_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20605                 unit, pkt_attr_int_pri);
  20606 
  20607         vlan_format_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20608                 unit, pkt_attr_vlan_format);
  20609 
  20610         outer_dot1p_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20611                 unit, pkt_attr_outer_dot1p);
  20612 
  20613         inner_dot1p_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20614                 unit, pkt_attr_inner_dot1p);
  20615 
  20616         tos_dscp_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20617                 unit, pkt_attr_tos);
  20618         tos_dscp_attrs = 1 << tos_dscp_bits;
  20619 
  20620         tos_ecn_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20621                 unit, pkt_attr_tos_ecn);
  20622         tos_ecn_attrs = 1 << tos_ecn_bits;
  20623 
  20624         pkt_res_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20625                 unit, pkt_attr_pkt_resolution);
  20626 
  20627         svp_type_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20628                 unit, pkt_attr_svp_group);
  20629         svp_type_attrs = 1 << svp_type_bits;
  20630 
  20631         drop_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20632                 unit, pkt_attr_drop);
  20633 
  20634         ip_pkt_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(unit,
  20635                 pkt_attr_ip_pkt);
  20636 
  20637         ing_port_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(
  20638                 unit, pkt_attr_ing_port);
  20639         /* Number of port is device dependent. So, get the size from h/w */
  20640         ing_port_attrs = soc_mem_index_max(unit, ING_SVM_PORT_MAPm) + 1;
  20641 
  20642         cmprsd_pkt_attr_bit_pos =
  20643             BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos;
  20644 
  20645         /*
  20646          * If compression tables sharing is supported, match packet
  20647          * attributes and it corresponding values to global compression maps.
  20648          */
  20649         if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  20650             rv = _bcm_esw_svm_pkt_compressed_attr_maps_validate(unit,
  20651                     pkt_attr_selectors);
  20652             if (BCM_FAILURE(rv)) {
  20653                 sal_free(meter_attr);
  20654                 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Sharing of"
  20655                                 " Compression tables are not possible"
  20656                                 " with given input attribute selectors\n")));
  20657                 return rv;
  20658             }
  20659         }
  20660 
  20661         sal_memset(map_array, 0, sizeof(uint8 *) * bcmPolicerGroupModeAttrCount);
  20662 
  20663         /* Step 1 : Create a separate map for each attribute type */
  20664         /* 0XFF means that index is not in use */
  20665         if (pkt_attr_selectors->cng == 1) {
  20666             _GLOBAL_METER_XGS3_ALLOC(
  20667                     map_array[bcmPolicerGroupModeAttrFieldIngressColor],
  20668                     256 + 1, "cng map_array values");
  20669 
  20670             sal_memset(map_array[bcmPolicerGroupModeAttrFieldIngressColor],
  20671                     0xFF, 256);
  20672             temp_count = 0;
  20673             if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_GREEN) {
  20674                 map_array[bcmPolicerGroupModeAttrFieldIngressColor][0] = temp_count;
  20675                 temp_count++;
  20676             }
  20677             if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_YELLOW) {
  20678                 map_array[bcmPolicerGroupModeAttrFieldIngressColor][1] = temp_count;
  20679                 temp_count++;
  20680             }
  20681             if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_RED) {
  20682                 map_array[bcmPolicerGroupModeAttrFieldIngressColor][3] = temp_count;
  20683                 temp_count++;
  20684             }
  20685             map_array[bcmPolicerGroupModeAttrFieldIngressColor][256] = temp_count;
  20686         }
  20687         if (pkt_attr_selectors->int_pri == 1) {
  20688             _GLOBAL_METER_XGS3_ALLOC(
  20689                     map_array[bcmPolicerGroupModeAttrIntPri],
  20690                     256 + 1, "int_pri map_array values");
  20691 
  20692             sal_memset(map_array[bcmPolicerGroupModeAttrIntPri],
  20693                     0xFF, 256);
  20694             temp_count = 0;
  20695             for (index0 = _BCM_POLICER_PKT_PRI0;
  20696                     index0 <= _BCM_POLICER_PKT_PRI15; index0++) {
  20697                 if (pkt_attr_selectors->combine_int_pri_flags & (1 << index0)) {
  20698                     map_array[bcmPolicerGroupModeAttrIntPri][index0] = temp_count;
  20699                     temp_count++;
  20700                 }
  20701             }
  20702             map_array[bcmPolicerGroupModeAttrIntPri][256] = temp_count;
  20703         }
  20704         if (pkt_attr_selectors->vlan_format == 1) {
  20705             _GLOBAL_METER_XGS3_ALLOC(
  20706                     map_array[bcmPolicerGroupModeAttrVlan],
  20707                     256 + 1, "vlan_format map_array values");
  20708 
  20709             sal_memset(map_array[bcmPolicerGroupModeAttrVlan],
  20710                     0xFF, 256);
  20711             temp_count = 0;
  20712             if(pkt_attr_selectors->combine_vlan_format_flags &
  20713                     _BCM_POLICER_VLAN_FORMAT_UNTAGGED) {
  20714                 map_array[bcmPolicerGroupModeAttrVlan][0] = temp_count;
  20715                 temp_count++;
  20716             }
  20717             if(pkt_attr_selectors->combine_vlan_format_flags &
  20718                     _BCM_POLICER_VLAN_FORMAT_INNER) {
  20719                 map_array[bcmPolicerGroupModeAttrVlan][1] = temp_count;
  20720                 temp_count++;
  20721             }
  20722             if(pkt_attr_selectors->combine_vlan_format_flags &
  20723                     _BCM_POLICER_VLAN_FORMAT_OUTER) {
  20724                 map_array[bcmPolicerGroupModeAttrVlan][2] = temp_count;
  20725                 temp_count++;
  20726             }
  20727             if(pkt_attr_selectors->combine_vlan_format_flags &
  20728                     _BCM_POLICER_VLAN_FORMAT_BOTH) {
  20729                 map_array[bcmPolicerGroupModeAttrVlan][3] = temp_count;
  20730                 temp_count++;
  20731             }
  20732             map_array[bcmPolicerGroupModeAttrVlan][256] = temp_count;
  20733         }
  20734         if (pkt_attr_selectors->outer_dot1p == 1) {
  20735             _GLOBAL_METER_XGS3_ALLOC(
  20736                     map_array[bcmPolicerGroupModeAttrOuterPri],
  20737                     256 + 1, "outer_dot1p map_array values");
  20738 
  20739             sal_memset(map_array[bcmPolicerGroupModeAttrOuterPri],
  20740                     0xFF, 256);
  20741             temp_count = 0;
  20742             for (index0 = _BCM_POLICER_PKT_PRI0;
  20743                     index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  20744                 if (pkt_attr_selectors->combine_outer_dot1p_flags & (1 << index0)) {
  20745                     map_array[bcmPolicerGroupModeAttrOuterPri][index0] = temp_count;
  20746                     temp_count++;
  20747                 }
  20748             }
  20749             map_array[bcmPolicerGroupModeAttrOuterPri][256] = temp_count;
  20750         }
  20751         if (pkt_attr_selectors->inner_dot1p == 1) {
  20752             _GLOBAL_METER_XGS3_ALLOC(
  20753                     map_array[bcmPolicerGroupModeAttrInnerPri],
  20754                     256 + 1, "inner_dot1p map_array values");
  20755 
  20756             sal_memset(map_array[bcmPolicerGroupModeAttrInnerPri],
  20757                     0xFF, 256);
  20758             temp_count = 0;
  20759             for (index0 = _BCM_POLICER_PKT_PRI0;
  20760                     index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  20761                 if (pkt_attr_selectors->combine_inner_dot1p_flags & (1 << index0)) {
  20762                     map_array[bcmPolicerGroupModeAttrInnerPri][index0] = temp_count;
  20763                     temp_count++;
  20764                 }
  20765             }
  20766             map_array[bcmPolicerGroupModeAttrInnerPri][256] = temp_count;
  20767         }
  20768         if (pkt_attr_selectors->port == 1) {
  20769             _GLOBAL_METER_XGS3_ALLOC(
  20770                     map_array[bcmPolicerGroupModeAttrPort],
  20771                     256 + 1, "port map_array values");
  20772 
  20773             sal_memset(map_array[bcmPolicerGroupModeAttrPort],
  20774                     0xFF, 256);
  20775             temp_count = 0;
  20776             for (value = 0; value < ing_port_attrs; value++) {
  20777                 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors->
  20778                             combine_value_array[_bcmPolicerAttrPort], value)) {
  20779                     map_array[bcmPolicerGroupModeAttrPort][value] = temp_count;
  20780                     temp_count++;
  20781                 }
  20782             }
  20783             map_array[bcmPolicerGroupModeAttrPort][256] = temp_count;
  20784         }
  20785         if (pkt_attr_selectors->tos_dscp == 1) {
  20786             _GLOBAL_METER_XGS3_ALLOC(
  20787                     map_array[bcmPolicerGroupModeAttrTosDscp],
  20788                     256 + 1, "tos_dscp map_array values");
  20789 
  20790             sal_memset(map_array[bcmPolicerGroupModeAttrTosDscp],
  20791                     0xFF, 256);
  20792             temp_count = 0;
  20793             for (value = 0; value < tos_dscp_attrs; value++) {
  20794                 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors->
  20795                             combine_value_array[_bcmPolicerAttrTosDscp], value)) {
  20796                     map_array[bcmPolicerGroupModeAttrTosDscp][value] = temp_count;
  20797                     temp_count++;
  20798                 }
  20799             }
  20800             map_array[bcmPolicerGroupModeAttrTosDscp][256] = temp_count;
  20801         }
  20802         if (pkt_attr_selectors->tos_ecn == 1) {
  20803             _GLOBAL_METER_XGS3_ALLOC(
  20804                     map_array[bcmPolicerGroupModeAttrTosEcn],
  20805                     256 + 1, "tos_ecn map_array values");
  20806 
  20807             sal_memset(map_array[bcmPolicerGroupModeAttrTosEcn],
  20808                     0xFF, 256);
  20809             temp_count = 0;
  20810             for (value = 0; value < tos_ecn_attrs; value++) {
  20811                 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors->
  20812                             combine_value_array[_bcmPolicerAttrTosEcn], value)) {
  20813                     map_array[bcmPolicerGroupModeAttrTosEcn][value] = temp_count;
  20814                     temp_count++;
  20815                 }
  20816             }
  20817             map_array[bcmPolicerGroupModeAttrTosEcn][256] = temp_count;
  20818         }
  20819         if (pkt_attr_selectors->pkt_resolution == 1) {
  20820             _GLOBAL_METER_XGS3_ALLOC(
  20821                     map_array[bcmPolicerGroupModeAttrPktType],
  20822                     256 + 1, "pkt_res map_array values");
  20823 
  20824             sal_memset(map_array[bcmPolicerGroupModeAttrPktType],
  20825                     0xFF, 256);
  20826             temp_count = 0;
  20827             if (pkt_attr_selectors->combine_pkt_res_flags &
  20828                     _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) {
  20829                 map_array[bcmPolicerGroupModeAttrPktType]
  20830                     [pkt_res[UNKNOWN_PKT]] = temp_count;
  20831                 temp_count++;
  20832             }
  20833             if (pkt_attr_selectors->combine_pkt_res_flags &
  20834                     _BCM_POLICER_PKT_TYPE_CONTROL_PKT) {
  20835                 map_array[bcmPolicerGroupModeAttrPktType]
  20836                     [pkt_res[CONTROL_PKT]] = temp_count;
  20837                 temp_count++;
  20838             }
  20839             if (pkt_attr_selectors->combine_pkt_res_flags &
  20840                     _BCM_POLICER_PKT_TYPE_OAM_PKT) {
  20841                 map_array[bcmPolicerGroupModeAttrPktType]
  20842                     [pkt_res[OAM_PKT]] = temp_count;
  20843                 temp_count++;
  20844             }
  20845             if (pkt_attr_selectors->combine_pkt_res_flags &
  20846                     _BCM_POLICER_PKT_TYPE_BFD_PKT) {
  20847                 map_array[bcmPolicerGroupModeAttrPktType]
  20848                     [pkt_res[BFD_PKT]] = temp_count;
  20849                 temp_count++;
  20850             }
  20851             if (pkt_attr_selectors->combine_pkt_res_flags &
  20852                     _BCM_POLICER_PKT_TYPE_BPDU_PKT) {
  20853                 map_array[bcmPolicerGroupModeAttrPktType]
  20854                     [pkt_res[BPDU_PKT]] = temp_count;
  20855                 temp_count++;
  20856             }
  20857             if (pkt_attr_selectors->combine_pkt_res_flags &
  20858                     _BCM_POLICER_PKT_TYPE_ICNM_PKT) {
  20859                 map_array[bcmPolicerGroupModeAttrPktType]
  20860                     [pkt_res[ICNM_PKT]] = temp_count;
  20861                 temp_count++;
  20862             }
  20863             if (pkt_attr_selectors->combine_pkt_res_flags &
  20864                     _BCM_POLICER_PKT_TYPE_PKT_IS_1588) {
  20865                 map_array[bcmPolicerGroupModeAttrPktType]
  20866                     [pkt_res[PKT_IS_1588]] = temp_count;
  20867                 temp_count++;
  20868             }
  20869             if (pkt_attr_selectors->combine_pkt_res_flags &
  20870                     _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) {
  20871                 map_array[bcmPolicerGroupModeAttrPktType]
  20872                     [pkt_res[KNOWN_L2UC_PKT]] = temp_count;
  20873                 temp_count++;
  20874             }
  20875             if (pkt_attr_selectors->combine_pkt_res_flags &
  20876                     _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) {
  20877                 map_array[bcmPolicerGroupModeAttrPktType]
  20878                     [pkt_res[UNKNOWN_L2UC_PKT]] = temp_count;
  20879                 temp_count++;
  20880             }
  20881             if (pkt_attr_selectors->combine_pkt_res_flags &
  20882                     _BCM_POLICER_PKT_TYPE_L2BC_PKT) {
  20883                 map_array[bcmPolicerGroupModeAttrPktType]
  20884                     [pkt_res[L2BC_PKT]] = temp_count;
  20885                 temp_count++;
  20886             }
  20887             if (pkt_attr_selectors->combine_pkt_res_flags &
  20888                     _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) {
  20889                 map_array[bcmPolicerGroupModeAttrPktType]
  20890                     [pkt_res[KNOWN_L2MC_PKT]] = temp_count;
  20891                 temp_count++;
  20892             }
  20893             if (pkt_attr_selectors->combine_pkt_res_flags &
  20894                     _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) {
  20895                 map_array[bcmPolicerGroupModeAttrPktType]
  20896                     [pkt_res[UNKNOWN_L2MC_PKT]] = temp_count;
  20897                 temp_count++;
  20898             }
  20899             if (pkt_attr_selectors->combine_pkt_res_flags &
  20900                     _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) {
  20901                 map_array[bcmPolicerGroupModeAttrPktType]
  20902                     [pkt_res[KNOWN_L3UC_PKT]] = temp_count;
  20903                 temp_count++;
  20904             }
  20905             if (pkt_attr_selectors->combine_pkt_res_flags &
  20906                     _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) {
  20907                 map_array[bcmPolicerGroupModeAttrPktType]
  20908                     [pkt_res[UNKNOWN_L3UC_PKT]] = temp_count;
  20909                 temp_count++;
  20910             }
  20911             if (pkt_attr_selectors->combine_pkt_res_flags &
  20912                     _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) {
  20913                 map_array[bcmPolicerGroupModeAttrPktType]
  20914                     [pkt_res[KNOWN_IPMC_PKT]] = temp_count;
  20915                 temp_count++;
  20916             }
  20917             if (pkt_attr_selectors->combine_pkt_res_flags &
  20918                     _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) {
  20919                 map_array[bcmPolicerGroupModeAttrPktType]
  20920                     [pkt_res[UNKNOWN_IPMC_PKT]] = temp_count;
  20921                 temp_count++;
  20922             }
  20923             if (pkt_attr_selectors->combine_pkt_res_flags &
  20924                     _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) {
  20925                 map_array[bcmPolicerGroupModeAttrPktType]
  20926                     [pkt_res[KNOWN_MPLS_L2_PKT]] = temp_count;
  20927                 temp_count++;
  20928             }
  20929             if (pkt_attr_selectors->combine_pkt_res_flags &
  20930                     _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) {
  20931                 map_array[bcmPolicerGroupModeAttrPktType]
  20932                     [pkt_res[KNOWN_MPLS_L3_PKT]] = temp_count;
  20933                 temp_count++;
  20934             }
  20935             if (pkt_attr_selectors->combine_pkt_res_flags &
  20936                     _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) {
  20937                 map_array[bcmPolicerGroupModeAttrPktType]
  20938                     [pkt_res[KNOWN_MPLS_PKT]] = temp_count;
  20939                 temp_count++;
  20940             }
  20941             if (pkt_attr_selectors->combine_pkt_res_flags &
  20942                     _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) {
  20943                 map_array[bcmPolicerGroupModeAttrPktType]
  20944                     [pkt_res[UNKNOWN_MPLS_PKT]] = temp_count;
  20945                 temp_count++;
  20946             }
  20947             if (pkt_attr_selectors->combine_pkt_res_flags &
  20948                     _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) {
  20949                 map_array[bcmPolicerGroupModeAttrPktType]
  20950                     [pkt_res[KNOWN_MPLS_MULTICAST_PKT]] = temp_count;
  20951                 temp_count++;
  20952             }
  20953             if (pkt_attr_selectors->combine_pkt_res_flags &
  20954                     _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) {
  20955                 map_array[bcmPolicerGroupModeAttrPktType]
  20956                     [pkt_res[KNOWN_MIM_PKT]] = temp_count;
  20957                 temp_count++;
  20958             }
  20959             if (pkt_attr_selectors->combine_pkt_res_flags &
  20960                     _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) {
  20961                 map_array[bcmPolicerGroupModeAttrPktType]
  20962                     [pkt_res[UNKNOWN_MIM_PKT]] = temp_count;
  20963                 temp_count++;
  20964             }
  20965             if (pkt_attr_selectors->combine_pkt_res_flags &
  20966                     _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) {
  20967                 map_array[bcmPolicerGroupModeAttrPktType]
  20968                     [pkt_res[KNOWN_TRILL_PKT]] = temp_count;
  20969                 temp_count++;
  20970             }
  20971             if (pkt_attr_selectors->combine_pkt_res_flags &
  20972                     _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) {
  20973                 map_array[bcmPolicerGroupModeAttrPktType]
  20974                     [pkt_res[UNKNOWN_TRILL_PKT]] = temp_count;
  20975                 temp_count++;
  20976             }
  20977             if (pkt_attr_selectors->combine_pkt_res_flags &
  20978                     _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) {
  20979                 map_array[bcmPolicerGroupModeAttrPktType]
  20980                     [pkt_res[KNOWN_NIV_PKT]] = temp_count;
  20981                 temp_count++;
  20982             }
  20983             if (pkt_attr_selectors->combine_pkt_res_flags &
  20984                     _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) {
  20985                 map_array[bcmPolicerGroupModeAttrPktType]
  20986                     [pkt_res[UNKNOWN_NIV_PKT]] = temp_count;
  20987                 temp_count++;
  20988             }
  20989             map_array[bcmPolicerGroupModeAttrPktType][256] = temp_count;
  20990         }
  20991         if (pkt_attr_selectors->svp_type == 1) {
  20992             _GLOBAL_METER_XGS3_ALLOC(
  20993                     map_array[bcmPolicerGroupModeAttrIngNetworkGroup],
  20994                     256 + 1, "svp_type map_array values");
  20995 
  20996             sal_memset(map_array[bcmPolicerGroupModeAttrIngNetworkGroup],
  20997                     0xFF, 256);
  20998             temp_count = 0;
  20999             for (value = 0; value < svp_type_attrs; value++) {
  21000                 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors->
  21001                             combine_value_array[_bcmPolicerAttrSvpType], value)) {
  21002                     map_array[bcmPolicerGroupModeAttrIngNetworkGroup][value] = temp_count;
  21003                     temp_count++;
  21004                 }
  21005             }
  21006             map_array[bcmPolicerGroupModeAttrIngNetworkGroup][256] = temp_count;
  21007         }
  21008         if (pkt_attr_selectors->drop == 1) {
  21009             _GLOBAL_METER_XGS3_ALLOC(
  21010                     map_array[bcmPolicerGroupModeAttrDrop],
  21011                     256 + 1, "drop map_array values");
  21012 
  21013             sal_memset(map_array[bcmPolicerGroupModeAttrDrop],
  21014                     0xFF, 256);
  21015             temp_count = 0;
  21016             if (pkt_attr_selectors->combine_drop_flags & _BCM_POLICER_DROP_DISABLE) {
  21017                 map_array[bcmPolicerGroupModeAttrDrop][0] = temp_count;
  21018                 temp_count++;
  21019             }
  21020             if (pkt_attr_selectors->combine_drop_flags & _BCM_POLICER_DROP_ENABLE) {
  21021                 map_array[bcmPolicerGroupModeAttrDrop][1] = temp_count;
  21022                 temp_count++;
  21023             }
  21024             map_array[bcmPolicerGroupModeAttrDrop][256] = temp_count;
  21025         }
  21026         if (pkt_attr_selectors->ip_pkt == 1) {
  21027             _GLOBAL_METER_XGS3_ALLOC(
  21028                     map_array[bcmPolicerGroupModeAttrPacketTypeIp],
  21029                     256 + 1, "ip_pkt map_array values");
  21030 
  21031             sal_memset(map_array[bcmPolicerGroupModeAttrDrop],
  21032                     0xFF, 256);
  21033             temp_count = 0;
  21034             if (pkt_attr_selectors->combine_ip_pkt_flags &
  21035                     _BCM_POLICER_IP_PKT_DISABLE) {
  21036                 map_array[bcmPolicerGroupModeAttrPacketTypeIp][0] = temp_count;
  21037                 temp_count++;
  21038             }
  21039             if (pkt_attr_selectors->combine_ip_pkt_flags &
  21040                     _BCM_POLICER_IP_PKT_ENABLE) {
  21041                 map_array[bcmPolicerGroupModeAttrPacketTypeIp][1] = temp_count;
  21042                 temp_count++;
  21043             }
  21044             map_array[bcmPolicerGroupModeAttrPacketTypeIp][256] = temp_count;
  21045         }
  21046 
  21047         /*
  21048          * Step 2: Calculate total bits required.
  21049          * In service meter, compressed mode is handled via compression
  21050          * hardware tables. These compression tables are mapped to one or
  21051          * more packet attributes.
  21052          * Total bits required for the compressed mode is calculated per
  21053          * compression table (Logical groups).
  21054          * For Each Logical Group,
  21055          * 1. Based on number of attribute values per attribute belonging
  21056          *     to that logical group, required bits are calculated per
  21057          *     attribute.
  21058          * 2. To represent invalid scenario, one more value is required per
  21059          *     logical group. For anyone of attribute in this logical group,
  21060          *     if the bits calculated can accomodate this extra value i.e
  21061          *     number formed by this many bits is more that number of values
  21062          *     required in that attribute, this extra value can be be used in
  21063          *     invalid scenario.
  21064          * 3. If none of the attributes in this logical table have spare value
  21065          *     then increment in number of bits for one of the attibute is
  21066          *     required to represent invalid scenario.
  21067          * 4. If bits for no attribute could be incremented, then no extra
  21068          *     value is required for the logical group as all indices
  21069          *     are valid. This scenario is highly unlikely.
  21070          * 5. Total bits for the logical group is again compared with the
  21071          *     maximum number of bits that the compression table can support.
  21072          *
  21073          * If total bits calucated for all logical groups exceed 8, then we
  21074          * cannot use even compressed mode.
  21075          */
  21076         /* Logical Group-1 cng / int_pri */
  21077         if ((map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) ||
  21078             (map_array[bcmPolicerGroupModeAttrIntPri] != NULL)) {
  21079             unused_found = FALSE;
  21080             if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) {
  21081                 values = map_array[bcmPolicerGroupModeAttrFieldIngressColor][256];
  21082                 cng_cmprsd_bits = _bcm_policer_num_of_bits_get(values);
  21083                 values_max = 1 << cng_cmprsd_bits;
  21084                 unused_found = (values < values_max) ? TRUE : unused_found;
  21085             }
  21086             if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) {
  21087                 values = map_array[bcmPolicerGroupModeAttrIntPri][256];
  21088                 int_pri_cmprsd_bits = _bcm_policer_num_of_bits_get(values);
  21089                 values_max = 1 << int_pri_cmprsd_bits;
  21090                 unused_found = (values < values_max) ? TRUE : unused_found;
  21091             }
  21092             if (!unused_found) {
  21093                 if ((cng_cmprsd_bits != 0) &&
  21094                         (cng_cmprsd_bits < cng_bits)) {
  21095                     cng_cmprsd_bits++;
  21096                 } else if ((int_pri_cmprsd_bits != 0) &&
  21097                         (int_pri_cmprsd_bits < int_pri_bits)) {
  21098                     int_pri_cmprsd_bits++;
  21099                 } else {
  21100                     /*
  21101                      * All values are valid for each attribute in this
  21102                      * logical group. Hence, increment is not required.
  21103                      */
  21104                     ;
  21105                 }
  21106             }
  21107             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21108                     unit, pkt_attr_pri_cng_map);
  21109             if (logical_group_bits < (cng_cmprsd_bits + int_pri_cmprsd_bits)) {
  21110                 rv = BCM_E_PARAM;
  21111             }
  21112         }
  21113 
  21114         /* Logical Group-2 vlan format / outer_dot1p /inner_dot1p */
  21115         if ((map_array[bcmPolicerGroupModeAttrVlan] != NULL) ||
  21116             (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) ||
  21117             (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL)) {
  21118             unused_found = FALSE;
  21119             if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) {
  21120                 values = map_array[bcmPolicerGroupModeAttrVlan][256];
  21121                 vlan_format_cmprsd_bits =
  21122                         _bcm_policer_num_of_bits_get(values);
  21123                 values_max = 1 << vlan_format_cmprsd_bits;
  21124                 unused_found = (values < values_max) ? TRUE : unused_found;
  21125             }
  21126             if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) {
  21127                 values = map_array[bcmPolicerGroupModeAttrOuterPri][256];
  21128                 outer_dot1p_cmprsd_bits =
  21129                         _bcm_policer_num_of_bits_get(values);
  21130                 values_max = 1 << outer_dot1p_cmprsd_bits;
  21131                 unused_found = (values < values_max) ? TRUE : unused_found;
  21132             }
  21133             if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) {
  21134                 values = map_array[bcmPolicerGroupModeAttrInnerPri][256];
  21135                 inner_dot1p_cmprsd_bits =
  21136                         _bcm_policer_num_of_bits_get(values);
  21137                 values_max = 1 << inner_dot1p_cmprsd_bits;
  21138                 unused_found = (values < values_max) ? TRUE : unused_found;
  21139             }
  21140             if (!unused_found) {
  21141                 if ((vlan_format_cmprsd_bits != 0) &&
  21142                         (vlan_format_cmprsd_bits < vlan_format_bits)) {
  21143                     vlan_format_cmprsd_bits++;
  21144                 } else if ((outer_dot1p_cmprsd_bits != 0) &&
  21145                         (outer_dot1p_cmprsd_bits < outer_dot1p_bits)) {
  21146                     outer_dot1p_cmprsd_bits++;
  21147                 } else if ((inner_dot1p_cmprsd_bits != 0) &&
  21148                         (inner_dot1p_cmprsd_bits < inner_dot1p_bits)) {
  21149                     inner_dot1p_cmprsd_bits++;
  21150                 } else {
  21151                     /*
  21152                      * All values are valid for each attribute in this
  21153                      * logical group. Hence, increment is not required.
  21154                      */
  21155                     ;
  21156                 }
  21157             }
  21158             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21159                     unit, pkt_attr_pkt_pri_map);
  21160             if (logical_group_bits < (vlan_format_cmprsd_bits +
  21161                         outer_dot1p_cmprsd_bits + inner_dot1p_cmprsd_bits)) {
  21162                 rv = BCM_E_PARAM;
  21163             }
  21164         }
  21165 
  21166         /* Logical Group-3 port */
  21167         if (map_array[bcmPolicerGroupModeAttrPort] != NULL) {
  21168             ing_port_cmprsd_bits = _bcm_policer_num_of_bits_get(
  21169                         map_array[bcmPolicerGroupModeAttrPort][256] + 1);
  21170             if (ing_port_cmprsd_bits > ing_port_bits) {
  21171                 ing_port_cmprsd_bits = ing_port_bits;
  21172             }
  21173         }
  21174 
  21175         /* Logical Group-4 tos_dscp / tos_ecn */
  21176         if ((map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) ||
  21177             (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL)) {
  21178             unused_found = FALSE;
  21179             if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) {
  21180                 values = map_array[bcmPolicerGroupModeAttrTosDscp][256];
  21181                 tos_dscp_cmprsd_bits =
  21182                         _bcm_policer_num_of_bits_get(values);
  21183                 values_max = 1 << tos_dscp_cmprsd_bits;
  21184                 unused_found = (values < values_max) ? TRUE : unused_found;
  21185             }
  21186             if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) {
  21187                 values = map_array[bcmPolicerGroupModeAttrTosEcn][256];
  21188                 tos_ecn_cmprsd_bits =
  21189                         _bcm_policer_num_of_bits_get(values);
  21190                 values_max = 1 << tos_ecn_cmprsd_bits;
  21191                 unused_found = (values < values_max) ? TRUE : unused_found;
  21192             }
  21193             if (!unused_found) {
  21194                 if ((tos_dscp_cmprsd_bits != 0) &&
  21195                         (tos_dscp_cmprsd_bits < tos_dscp_bits)) {
  21196                     tos_dscp_cmprsd_bits++;
  21197                 } else if ((tos_ecn_cmprsd_bits != 0) &&
  21198                         (tos_ecn_cmprsd_bits < tos_ecn_bits)) {
  21199                     tos_ecn_cmprsd_bits++;
  21200                 } else {
  21201                     /*
  21202                      * All values are valid for each attribute in this
  21203                      * logical group. Hence, increment is not required.
  21204                      */
  21205                     ;
  21206                 }
  21207             }
  21208             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21209                     unit, pkt_attr_tos_map);
  21210             if (logical_group_bits < (tos_dscp_cmprsd_bits +
  21211                         tos_ecn_cmprsd_bits)) {
  21212                 rv = BCM_E_PARAM;
  21213             }
  21214         }
  21215 
  21216         /* Logical Group-5 pkt_resolution / network group(svp type) / drop */
  21217         if ((map_array[bcmPolicerGroupModeAttrPktType] != NULL) ||
  21218             (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) ||
  21219             (map_array[bcmPolicerGroupModeAttrDrop] != NULL)) {
  21220             unused_found = FALSE;
  21221             if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) {
  21222                 values = map_array[bcmPolicerGroupModeAttrPktType][256];
  21223                 pkt_res_cmprsd_bits =
  21224                         _bcm_policer_num_of_bits_get(values);
  21225                 values_max = 1 << pkt_res_cmprsd_bits;
  21226                 unused_found = (values < values_max) ? TRUE : unused_found;
  21227             }
  21228             if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) {
  21229                 values = map_array[bcmPolicerGroupModeAttrIngNetworkGroup][256];
  21230                 svp_type_cmprsd_bits =
  21231                         _bcm_policer_num_of_bits_get(values);
  21232                 values_max = 1 << svp_type_cmprsd_bits;
  21233                 unused_found = (values < values_max) ? TRUE : unused_found;
  21234             }
  21235             if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) {
  21236                 values = map_array[bcmPolicerGroupModeAttrDrop][256];
  21237                 drop_cmprsd_bits =
  21238                         _bcm_policer_num_of_bits_get(values);
  21239                 values_max = 1 << drop_cmprsd_bits;
  21240                 unused_found = (values < values_max) ? TRUE : unused_found;
  21241             }
  21242             if (!unused_found) {
  21243                 if ((pkt_res_cmprsd_bits != 0) &&
  21244                         (pkt_res_cmprsd_bits < pkt_res_bits)) {
  21245                     pkt_res_cmprsd_bits++;
  21246                 } else if ((svp_type_cmprsd_bits != 0) &&
  21247                         (svp_type_cmprsd_bits < svp_type_bits)) {
  21248                     svp_type_cmprsd_bits++;
  21249                 } else if ((drop_cmprsd_bits != 0) &&
  21250                         (drop_cmprsd_bits < drop_bits)) {
  21251                     drop_cmprsd_bits++;
  21252                 } else {
  21253                     /*
  21254                      * All values are valid for each attribute in this
  21255                      * logical group. Hence, increment is not required.
  21256                      */
  21257                     ;
  21258                 }
  21259             }
  21260             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21261                     unit, pkt_attr_pkt_res_map);
  21262             if (logical_group_bits < (pkt_res_cmprsd_bits +
  21263                         svp_type_cmprsd_bits + drop_cmprsd_bits)) {
  21264                 rv = BCM_E_PARAM;
  21265             }
  21266         }
  21267 
  21268         if (map_array[bcmPolicerGroupModeAttrPacketTypeIp] != NULL) {
  21269             ip_pkt_cmprsd_bits = _bcm_policer_num_of_bits_get(
  21270                     map_array[bcmPolicerGroupModeAttrPacketTypeIp][256]);
  21271             if (ip_pkt_cmprsd_bits > ip_pkt_bits) {
  21272                 ip_pkt_cmprsd_bits = ip_pkt_cmprsd_bits;
  21273             }
  21274         }
  21275 
  21276         total_bits = cng_cmprsd_bits + int_pri_cmprsd_bits +
  21277             vlan_format_cmprsd_bits + outer_dot1p_cmprsd_bits +
  21278             inner_dot1p_cmprsd_bits + ing_port_cmprsd_bits +
  21279             tos_dscp_cmprsd_bits + tos_ecn_cmprsd_bits +
  21280             pkt_res_cmprsd_bits + svp_type_cmprsd_bits +
  21281             drop_cmprsd_bits + ip_pkt_cmprsd_bits;
  21282 
  21283         if (total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
  21284             /* Free map_array */
  21285             for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) {
  21286                 if (map_array[loop] != NULL) {
  21287                     sal_free(map_array[loop]);
  21288                 }
  21289             }
  21290             sal_free(meter_attr);
  21291             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Number of bits"
  21292                             " required is more than 8 even for compressed mode\n")));
  21293             return BCM_E_PARAM;
  21294         }
  21295 
  21296         /*
  21297          * Step 3 : Filling up Logical Groups
  21298          * For Each Logical Group,
  21299          * 1. Loop though each value of all attributes
  21300          * 2. If value is not part of attribute selector, all indices formed
  21301          *     for that attribute value is marked as Invalid.
  21302          * 3. Invalid value is derived by setting all bits to 1.
  21303          * 4. Else, final value at the index is calculated via left shift
  21304          *     operation on values present in map_aray[] and number of
  21305          *     bits required.
  21306          */
  21307         /* Logical Group-1 cng / int_pri */
  21308         if ((pkt_attr_selectors->cng == 1) ||
  21309                 (pkt_attr_selectors->int_pri == 1)) {
  21310             if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) {
  21311                 max_bits = cng_cmprsd_bits;
  21312                 cmprsd_attr_selectors->pkt_attr_bits_v.cng = max_bits;
  21313                 cmprsd_attr_selectors->pkt_attr_bits_v.cng_mask =
  21314                     (1 << max_bits) - 1;
  21315                 cmprsd_attr_selectors->pkt_attr_bits_v.cng_pos =
  21316                     cmprsd_pkt_attr_bit_pos[pkt_attr_cng].start_bit;
  21317             }
  21318             if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) {
  21319                 max_bits = int_pri_cmprsd_bits;
  21320                     cmprsd_attr_selectors->pkt_attr_bits_v.int_pri = max_bits;
  21321                 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri_mask =
  21322                     (1 << max_bits) - 1;
  21323                 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri_pos =
  21324                     cmprsd_pkt_attr_bit_pos[pkt_attr_int_pri].start_bit;
  21325             }
  21326             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21327                     unit, pkt_attr_pri_cng_map);
  21328             invalid_map_value = (1 << logical_group_bits) - 1;
  21329 
  21330             mapped_value0 = mapped_value1 = 0;
  21331             for (index0 = 0; index0 < (1 << cng_bits); index0++) {
  21332                 invalid_index0 = FALSE;
  21333                 if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) {
  21334                     if (map_array[bcmPolicerGroupModeAttrFieldIngressColor]
  21335                             [index0] == 0xFF) {
  21336                         invalid_index0 = TRUE;
  21337                     } else {
  21338                         mapped_value0 = map_array
  21339                             [bcmPolicerGroupModeAttrFieldIngressColor][index0];
  21340                     }
  21341                 }
  21342                 for (index1 = 0; index1 < (1 << int_pri_bits); index1++) {
  21343                     invalid_index1 = FALSE;
  21344                     if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) {
  21345                         if (map_array[bcmPolicerGroupModeAttrIntPri]
  21346                                 [index1] == 0xFF) {
  21347                             invalid_index1 = TRUE;
  21348                         } else {
  21349                             mapped_value1 = map_array
  21350                                 [bcmPolicerGroupModeAttrIntPri][index1];
  21351                         }
  21352                     }
  21353                     final_index = (index0 << int_pri_bits) + index1;
  21354                     if (invalid_index0 || invalid_index1) {
  21355                         final_mapped_value = invalid_map_value;
  21356                     } else if (soc_feature(unit,
  21357                                 soc_feature_global_meter_compression_share)) {
  21358                         final_mapped_value = (mapped_value0 << int_pri_bits) +
  21359                             mapped_value1;
  21360                     } else {
  21361                         final_mapped_value =
  21362                             (mapped_value0 << int_pri_cmprsd_bits) +
  21363                             mapped_value1;
  21364                     }
  21365                     cmprsd_attr_selectors->compressed_pri_cnf_attr_map_v
  21366                         [final_index] = final_mapped_value;
  21367                 }
  21368             }
  21369         }
  21370 
  21371         /* Logical Group-2 vlan format / outer_dot1p /inner_dot1p */
  21372         if ((pkt_attr_selectors->vlan_format == 1) ||
  21373                 (pkt_attr_selectors->outer_dot1p == 1) ||
  21374                 (pkt_attr_selectors->inner_dot1p == 1)) {
  21375             if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) {
  21376                 max_bits = vlan_format_cmprsd_bits;
  21377                 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format = max_bits;
  21378                 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format_mask =
  21379                     (1 << max_bits) - 1;
  21380                 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format_pos =
  21381                     cmprsd_pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit;
  21382             }
  21383             if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) {
  21384                 max_bits = outer_dot1p_cmprsd_bits;
  21385                 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p = max_bits;
  21386                 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p_mask =
  21387                     (1 << max_bits) - 1;
  21388                 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p_pos =
  21389                     cmprsd_pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit;
  21390             }
  21391             if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) {
  21392                 max_bits = inner_dot1p_cmprsd_bits;
  21393                 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p = max_bits;
  21394                 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p_mask =
  21395                     (1 << max_bits) - 1;
  21396                 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p_pos =
  21397                     cmprsd_pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit;
  21398             }
  21399 
  21400             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21401                     unit, pkt_attr_pkt_pri_map);
  21402             invalid_map_value = (1 << logical_group_bits) - 1;
  21403 
  21404             mapped_value0 = mapped_value1 = mapped_value2 = 0;
  21405             for (index0 = 0; index0 < (1 << vlan_format_bits); index0++) {
  21406                 invalid_index0 = FALSE;
  21407                 if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) {
  21408                     if (map_array[bcmPolicerGroupModeAttrVlan][index0] == 0xFF) {
  21409                         invalid_index0 = TRUE;
  21410                     } else {
  21411                         mapped_value0 =
  21412                             map_array[bcmPolicerGroupModeAttrVlan][index0];
  21413                     }
  21414                 }
  21415                 for (index1 = 0; index1 < (1 << outer_dot1p_bits); index1++) {
  21416                     invalid_index1 = FALSE;
  21417                     if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) {
  21418                         if (map_array[bcmPolicerGroupModeAttrOuterPri][index1] == 0xFF) {
  21419                             invalid_index1 = TRUE;
  21420                         } else {
  21421                             mapped_value1 = map_array
  21422                                 [bcmPolicerGroupModeAttrOuterPri][index1];
  21423                         }
  21424                     }
  21425                     for (index2 = 0; index2 < (1 << inner_dot1p_bits); index2++) {
  21426                         invalid_index2 = FALSE;
  21427                         if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) {
  21428                             if (map_array[bcmPolicerGroupModeAttrInnerPri]
  21429                                     [index2] == 0xFF) {
  21430                                 invalid_index2 = TRUE;
  21431                             } else {
  21432                                 mapped_value2 = map_array
  21433                                     [bcmPolicerGroupModeAttrInnerPri][index2];
  21434                             }
  21435                         }
  21436                         final_index = (index0 << (outer_dot1p_bits + inner_dot1p_bits)) +
  21437                             (index1 << inner_dot1p_bits) + index2;
  21438                         if (invalid_index0 || invalid_index1 || invalid_index2) {
  21439                             final_mapped_value = invalid_map_value;
  21440                         } else if (soc_feature(unit,
  21441                                     soc_feature_global_meter_compression_share)) {
  21442                             final_mapped_value = (mapped_value0 <<
  21443                                     (outer_dot1p_bits + inner_dot1p_bits)) +
  21444                                 (mapped_value1 << inner_dot1p_bits) + mapped_value2;
  21445                         } else {
  21446                             final_mapped_value = (mapped_value0 <<
  21447                                     (outer_dot1p_cmprsd_bits +
  21448                                      inner_dot1p_cmprsd_bits)) +
  21449                                 (mapped_value1 << inner_dot1p_cmprsd_bits) +
  21450                                 mapped_value2;
  21451                         }
  21452                         cmprsd_attr_selectors->compressed_pkt_pri_attr_map_v[final_index] =
  21453                             final_mapped_value;
  21454                     }
  21455                 }
  21456             }
  21457         }
  21458 
  21459         /* Logical Group-3 port */
  21460         if (pkt_attr_selectors->port == 1) {
  21461             if (map_array[bcmPolicerGroupModeAttrPort] != NULL) {
  21462                 max_bits = ing_port_cmprsd_bits;
  21463                 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port = max_bits;
  21464                 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port_mask =
  21465                     (1 << max_bits) - 1;
  21466                 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port_pos =
  21467                     cmprsd_pkt_attr_bit_pos[pkt_attr_ing_port].start_bit;
  21468                 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21469                         unit, pkt_attr_port_map);
  21470                 invalid_map_value = (1 << logical_group_bits) - 1;
  21471 
  21472                 mapped_value0 = 0;
  21473                 /* Use ing_port_attrs as it is device dependent */
  21474                 for (index0 =0; index0 < ing_port_attrs; index0++ ) {
  21475                     invalid_index0 = FALSE;
  21476                     if (map_array[bcmPolicerGroupModeAttrPort][index0] == 0xFF) {
  21477                         invalid_index0 = TRUE;
  21478                     } else {
  21479                         mapped_value0 =
  21480                             map_array[bcmPolicerGroupModeAttrPort][index0];
  21481                     }
  21482                     final_index = index0;
  21483                     if (invalid_index0) {
  21484                         final_mapped_value = invalid_map_value;
  21485                     } else {
  21486                         final_mapped_value = mapped_value0;
  21487                     }
  21488                     cmprsd_attr_selectors->compressed_port_attr_map_v
  21489                         [final_index] = final_mapped_value;
  21490                 }
  21491             }
  21492         }
  21493 
  21494         /* Logical Group-4 tos_dscp / tos_ecn */
  21495         if ((pkt_attr_selectors->tos_dscp == 1) ||
  21496                 (pkt_attr_selectors->tos_ecn == 1)) {
  21497             if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) {
  21498                 max_bits = tos_dscp_cmprsd_bits;
  21499                 cmprsd_attr_selectors->pkt_attr_bits_v.tos = max_bits;
  21500                 cmprsd_attr_selectors->pkt_attr_bits_v.tos_mask =
  21501                     (1 << max_bits) - 1;
  21502                 cmprsd_attr_selectors->pkt_attr_bits_v.tos_pos =
  21503                     cmprsd_pkt_attr_bit_pos[pkt_attr_tos].start_bit;
  21504             }
  21505             if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) {
  21506                 max_bits = tos_ecn_cmprsd_bits;
  21507                 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn = max_bits;
  21508                 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn_mask =
  21509                     (1 << max_bits) - 1;
  21510                 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn_pos =
  21511                     cmprsd_pkt_attr_bit_pos[pkt_attr_tos_ecn].start_bit;
  21512             }
  21513             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21514                 unit, pkt_attr_tos_map);
  21515             invalid_map_value = (1 << logical_group_bits) - 1;
  21516 
  21517             mapped_value0 = mapped_value1 = 0;
  21518             for (index0 = 0; index0 < (1 << tos_dscp_bits); index0++) {
  21519                 invalid_index0 = FALSE;
  21520                 if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) {
  21521                     if (map_array[bcmPolicerGroupModeAttrTosDscp][index0] == 0xFF) {
  21522                         invalid_index0 = TRUE;
  21523                     } else {
  21524                         mapped_value0 =
  21525                             map_array[bcmPolicerGroupModeAttrTosDscp][index0];
  21526                     }
  21527                 }
  21528                 for (index1 = 0; index1 < (1 << tos_ecn_bits); index1++) {
  21529                     invalid_index1 = FALSE;
  21530                     if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) {
  21531                         if (map_array[bcmPolicerGroupModeAttrTosEcn][index1] == 0xFF) {
  21532                             invalid_index1 = TRUE;
  21533                         } else {
  21534                             mapped_value1 = map_array
  21535                                 [bcmPolicerGroupModeAttrTosEcn][index1];
  21536                         }
  21537                     }
  21538                     final_index = (index0 << tos_ecn_bits) + index1;
  21539                     if (invalid_index0 || invalid_index1) {
  21540                         final_mapped_value = invalid_map_value;
  21541                     } else if (soc_feature(unit,
  21542                                 soc_feature_global_meter_compression_share)) {
  21543                         final_mapped_value = (mapped_value0 <<
  21544                                 tos_ecn_bits) + mapped_value1;
  21545                     } else {
  21546                         final_mapped_value = (mapped_value0 <<
  21547                                 tos_ecn_cmprsd_bits) + mapped_value1;
  21548                     }
  21549                     cmprsd_attr_selectors->compressed_tos_attr_map_v
  21550                         [final_index] = final_mapped_value;
  21551                 }
  21552             }
  21553         }
  21554 
  21555         /* Logical Group-5 pkt_resolution / network group(svp type) / drop */
  21556         if ((pkt_attr_selectors->pkt_resolution == 1) ||
  21557                 (pkt_attr_selectors->svp_type == 1) ||
  21558                 (pkt_attr_selectors->drop ==1)) {
  21559             if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) {
  21560                 max_bits = pkt_res_cmprsd_bits;
  21561                 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_resolution = max_bits;
  21562                 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_res_mask =
  21563                     (1 << max_bits) - 1;
  21564                 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_res_pos =
  21565                     cmprsd_pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit;
  21566             }
  21567             if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) {
  21568                 max_bits = svp_type_cmprsd_bits;
  21569                 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type = max_bits;
  21570                 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type_mask =
  21571                     (1 << max_bits) - 1;
  21572                 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type_pos =
  21573                     cmprsd_pkt_attr_bit_pos[pkt_attr_svp_group].start_bit;
  21574             }
  21575             if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) {
  21576                 max_bits = drop_cmprsd_bits;
  21577                 cmprsd_attr_selectors->pkt_attr_bits_v.drop = max_bits;
  21578                 cmprsd_attr_selectors->pkt_attr_bits_v.drop_mask =
  21579                     (1 << max_bits) - 1;
  21580                 cmprsd_attr_selectors->pkt_attr_bits_v.drop_pos =
  21581                     cmprsd_pkt_attr_bit_pos[pkt_attr_drop].start_bit;
  21582             }
  21583 
  21584             logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get(
  21585                 unit, pkt_attr_pkt_res_map);
  21586             invalid_map_value = (1 << logical_group_bits) - 1;
  21587 
  21588             /*
  21589              * pkt_res_bits in compressed and uncompressed mode is different
  21590              * and map_array is populated based on bit positions of pkt_type
  21591              * in Hw and are not sequential. Use pkt_res_bits of uncompressed
  21592              * mode to cover all bit positions.
  21593              */
  21594             pkt_res_bits = _bcm_policer_svm_pkt_attr_bits_get(
  21595                     unit, pkt_attr_pkt_resolution);
  21596 
  21597             mapped_value0 = mapped_value1 = mapped_value2 = 0;
  21598             for (index0 = 0; index0 < (1 << pkt_res_bits); index0++) {
  21599                 invalid_index0 = FALSE;
  21600                 if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) {
  21601                     if (map_array[bcmPolicerGroupModeAttrPktType][index0] == 0xFF) {
  21602                         invalid_index0 = TRUE;
  21603                     } else {
  21604                         mapped_value0 = map_array
  21605                             [bcmPolicerGroupModeAttrPktType][index0];
  21606                     }
  21607                 }
  21608                 for (index1 = 0; index1 < (1 << svp_type_bits); index1++) {
  21609                     invalid_index1 = FALSE;
  21610                     if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) {
  21611                         if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup][index1] == 0xFF) {
  21612                             invalid_index1 = TRUE;
  21613                         } else {
  21614                             mapped_value1 = map_array
  21615                                 [bcmPolicerGroupModeAttrIngNetworkGroup][index1];
  21616                         }
  21617                     }
  21618                     for (index2 = 0; index2 < (1 << drop_bits); index2++) {
  21619                         invalid_index2 = FALSE;
  21620                         if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) {
  21621                             if (map_array[bcmPolicerGroupModeAttrDrop][index2] == 0xFF) {
  21622                                 invalid_index2 = TRUE;
  21623                             } else {
  21624                                 mapped_value2 = map_array
  21625                                     [bcmPolicerGroupModeAttrDrop][index2];
  21626                             }
  21627                         }
  21628                         final_index = (index0 << (svp_type_bits + drop_bits)) +
  21629                             (index1 << drop_bits) + index2;
  21630                         if (invalid_index0 || invalid_index1 || invalid_index2) {
  21631                             final_mapped_value = invalid_map_value;
  21632                         } else if (soc_feature(unit,
  21633                                 soc_feature_global_meter_compression_share)) {
  21634                             final_mapped_value =
  21635                                     (mapped_value0 << (svp_type_bits + drop_bits)) +
  21636                                     (mapped_value1 << drop_bits) + mapped_value2;
  21637                         } else {
  21638                             final_mapped_value =
  21639                                 (mapped_value0 << (svp_type_cmprsd_bits +
  21640                                                    drop_cmprsd_bits)) +
  21641                                 (mapped_value1 << drop_cmprsd_bits) +
  21642                                 mapped_value2;
  21643                         }
  21644                         cmprsd_attr_selectors->compressed_pkt_res_attr_map_v
  21645                             [final_index] = final_mapped_value;
  21646                     }
  21647                 }
  21648             }
  21649         }
  21650 
  21651         if (pkt_attr_selectors->ip_pkt == 1) {
  21652             max_bits = ip_pkt_cmprsd_bits;
  21653             cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt = max_bits;
  21654             cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt_mask =
  21655                 (1 << max_bits) - 1;
  21656             cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt_pos =
  21657                 cmprsd_pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit;
  21658         }
  21659 
  21660         /* Step 4 : Compute offset_map */
  21661         /* Fill offset_map field of uncompressed_attr_selectors_v */
  21662         /* Step 4.1 : Reset all values in offset_map */
  21663         sal_memset(cmprsd_attr_selectors->offset_map, 0,
  21664                 sizeof (cmprsd_attr_selectors->offset_map));
  21665 
  21666         for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  21667             offset_array[loop] =
  21668                 (uint8 *) sal_alloc(BCM_SVC_METER_MAP_SIZE_256 + 1,
  21669                         "offset_array");
  21670             if (offset_array[loop] == NULL) {
  21671                 rv = BCM_E_MEMORY;
  21672                 break;
  21673             }
  21674         }
  21675         if (BCM_FAILURE(rv)) {
  21676             /* Free offset_array */
  21677             for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  21678                 if (offset_array[loop] != NULL) {
  21679                     sal_free(offset_array[loop]);
  21680                 }
  21681             }
  21682             /* free map_array */
  21683             for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) {
  21684                 if (map_array[loop] != NULL) {
  21685                     sal_free(map_array[loop]);
  21686                 }
  21687             }
  21688             sal_free(meter_attr);
  21689             return rv;
  21690         }
  21691 
  21692         /* Step 4.2 : Calculate offset value for each pol_offset  */
  21693         for (pol_offset = 0;
  21694                 pol_offset < pkt_attr_selectors->total_policers ;
  21695                 pol_offset++ ) {
  21696             combine_attr_data =
  21697                 &pkt_attr_selectors->combine_attr_data[pol_offset];
  21698             /* Step 4.2.1 : Reset offset_array */
  21699             for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  21700                 sal_memset(offset_array[loop], 0,
  21701                         BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1);
  21702             }
  21703             loop = 0;
  21704 
  21705             /* Step 4.2.2 : Parse each attr types and save values */
  21706             if ((pkt_attr_selectors->cng == 1) &&
  21707                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21708                 shift_by_bits = int_pri_cmprsd_bits +
  21709                     vlan_format_cmprsd_bits +
  21710                     outer_dot1p_cmprsd_bits +
  21711                     inner_dot1p_cmprsd_bits +
  21712                     ing_port_cmprsd_bits +
  21713                     tos_dscp_cmprsd_bits +
  21714                     tos_ecn_cmprsd_bits +
  21715                     pkt_res_cmprsd_bits +
  21716                     svp_type_cmprsd_bits +
  21717                     drop_cmprsd_bits +
  21718                     ip_pkt_cmprsd_bits;
  21719 
  21720                 temp_count = offset_array[loop][0];
  21721                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_GREEN) {
  21722                     offset_array[loop][temp_count + 1] =
  21723                         (map_array[bcmPolicerGroupModeAttrFieldIngressColor][0] <<
  21724                          shift_by_bits);
  21725                     temp_count++;
  21726                 }
  21727                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_YELLOW) {
  21728                     offset_array[loop][temp_count + 1] =
  21729                         (map_array[bcmPolicerGroupModeAttrFieldIngressColor][1] <<
  21730                          shift_by_bits);
  21731                     temp_count++;
  21732                 }
  21733                 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_RED) {
  21734                     offset_array[loop][temp_count + 1] =
  21735                         (map_array[bcmPolicerGroupModeAttrFieldIngressColor][3] <<
  21736                          shift_by_bits);
  21737                     temp_count++;
  21738                 }
  21739                 offset_array[loop][0] = temp_count;
  21740                 loop++;
  21741             }
  21742             if ((pkt_attr_selectors->int_pri == 1) &&
  21743                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21744                 shift_by_bits = vlan_format_cmprsd_bits +
  21745                     outer_dot1p_cmprsd_bits +
  21746                     inner_dot1p_cmprsd_bits +
  21747                     ing_port_cmprsd_bits +
  21748                     tos_dscp_cmprsd_bits +
  21749                     tos_ecn_cmprsd_bits +
  21750                     pkt_res_cmprsd_bits +
  21751                     svp_type_cmprsd_bits +
  21752                     drop_cmprsd_bits +
  21753                     ip_pkt_cmprsd_bits;
  21754 
  21755                 temp_count = offset_array[loop][0];
  21756                 for (index0 = _BCM_POLICER_PKT_PRI0;
  21757                         index0 <= _BCM_POLICER_PKT_PRI15; index0++) {
  21758                     if(combine_attr_data->int_pri_flags & (1 << index0)) {
  21759                         offset_array[loop][temp_count + 1] =
  21760                             (map_array[bcmPolicerGroupModeAttrIntPri][index0] <<
  21761                              shift_by_bits);
  21762                         temp_count++;
  21763                     }
  21764                 }
  21765                 offset_array[loop][0] = temp_count;
  21766                 loop++;
  21767             }
  21768             if ((pkt_attr_selectors->vlan_format == 1) &&
  21769                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21770                 shift_by_bits = outer_dot1p_cmprsd_bits +
  21771                     inner_dot1p_cmprsd_bits +
  21772                     ing_port_cmprsd_bits +
  21773                     tos_dscp_cmprsd_bits +
  21774                     tos_ecn_cmprsd_bits +
  21775                     pkt_res_cmprsd_bits +
  21776                     svp_type_cmprsd_bits +
  21777                     drop_cmprsd_bits +
  21778                     ip_pkt_cmprsd_bits;
  21779 
  21780                 temp_count = offset_array[loop][0];
  21781                 if(combine_attr_data->vlan_format_flags &
  21782                         _BCM_POLICER_VLAN_FORMAT_UNTAGGED) {
  21783                     offset_array[loop][temp_count + 1] =
  21784                         (map_array[bcmPolicerGroupModeAttrVlan][0] <<
  21785                          shift_by_bits);
  21786                     temp_count++;
  21787                 }
  21788                 if(combine_attr_data->vlan_format_flags &
  21789                         _BCM_POLICER_VLAN_FORMAT_INNER) {
  21790                     offset_array[loop][temp_count + 1] =
  21791                         (map_array[bcmPolicerGroupModeAttrVlan][1] <<
  21792                          shift_by_bits);
  21793                     temp_count++;
  21794                 }
  21795                 if(combine_attr_data->vlan_format_flags &
  21796                         _BCM_POLICER_VLAN_FORMAT_OUTER) {
  21797                     offset_array[loop][temp_count + 1] =
  21798                         (map_array[bcmPolicerGroupModeAttrVlan][2] <<
  21799                          shift_by_bits);
  21800                     temp_count++;
  21801                 }
  21802                 if(combine_attr_data->vlan_format_flags &
  21803                         _BCM_POLICER_VLAN_FORMAT_BOTH) {
  21804                     offset_array[loop][temp_count + 1] =
  21805                         (map_array[bcmPolicerGroupModeAttrVlan][3] <<
  21806                          shift_by_bits);
  21807                     temp_count++;
  21808                 }
  21809                 offset_array[loop][0] = temp_count;
  21810                 loop++;
  21811             }
  21812             if ((pkt_attr_selectors->outer_dot1p == 1) &&
  21813                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21814                 shift_by_bits = inner_dot1p_cmprsd_bits +
  21815                     ing_port_cmprsd_bits +
  21816                     tos_dscp_cmprsd_bits +
  21817                     tos_ecn_cmprsd_bits +
  21818                     pkt_res_cmprsd_bits +
  21819                     svp_type_cmprsd_bits +
  21820                     drop_cmprsd_bits +
  21821                     ip_pkt_cmprsd_bits;
  21822 
  21823                 temp_count = offset_array[loop][0];
  21824                 for (index0 = _BCM_POLICER_PKT_PRI0;
  21825                         index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  21826                     if(combine_attr_data->outer_dot1p_flags & (1 << index0)) {
  21827                         offset_array[loop][temp_count + 1] =
  21828                             (map_array[bcmPolicerGroupModeAttrOuterPri][index0] <<
  21829                              shift_by_bits);
  21830                         temp_count++;
  21831                     }
  21832                 }
  21833                 offset_array[loop][0] = temp_count;
  21834                 loop++;
  21835             }
  21836             if ((pkt_attr_selectors->inner_dot1p == 1) &&
  21837                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21838                 shift_by_bits = ing_port_cmprsd_bits +
  21839                     tos_dscp_cmprsd_bits +
  21840                     tos_ecn_cmprsd_bits +
  21841                     pkt_res_cmprsd_bits +
  21842                     svp_type_cmprsd_bits +
  21843                     drop_cmprsd_bits +
  21844                     ip_pkt_cmprsd_bits;
  21845 
  21846                 temp_count = offset_array[loop][0];
  21847                 for (index0 = _BCM_POLICER_PKT_PRI0;
  21848                         index0 <= _BCM_POLICER_PKT_PRI7; index0++) {
  21849                     if(combine_attr_data->inner_dot1p_flags & (1 << index0)) {
  21850                         offset_array[loop][temp_count + 1] =
  21851                             (map_array[bcmPolicerGroupModeAttrInnerPri][index0] <<
  21852                              shift_by_bits);
  21853                         temp_count++;
  21854                     }
  21855                 }
  21856                 offset_array[loop][0] = temp_count;
  21857                 loop++;
  21858             }
  21859             if ((pkt_attr_selectors->port == 1) &&
  21860                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21861                 shift_by_bits = tos_dscp_cmprsd_bits +
  21862                     tos_ecn_cmprsd_bits +
  21863                     pkt_res_cmprsd_bits +
  21864                     svp_type_cmprsd_bits +
  21865                     drop_cmprsd_bits +
  21866                     ip_pkt_cmprsd_bits;
  21867 
  21868                 for (index0 = 0; index0 < ing_port_attrs; index0++) {
  21869                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  21870                                 value_array[_bcmPolicerAttrPort], index0)) {
  21871                         temp_count = offset_array[loop][0];
  21872                         offset_array[loop][temp_count + 1] =
  21873                             map_array[bcmPolicerGroupModeAttrPort][index0] <<
  21874                             shift_by_bits;
  21875                         offset_array[loop][0] =  temp_count + 1;
  21876                     }
  21877                 }
  21878                 loop++;
  21879             }
  21880             if ((pkt_attr_selectors->tos_dscp == 1) &&
  21881                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21882                 shift_by_bits = tos_ecn_cmprsd_bits +
  21883                     pkt_res_cmprsd_bits +
  21884                     svp_type_cmprsd_bits +
  21885                     drop_cmprsd_bits +
  21886                     ip_pkt_cmprsd_bits;
  21887 
  21888                 for (index0 = 0; index0 < tos_dscp_attrs; index0++) {
  21889                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  21890                                 value_array[_bcmPolicerAttrTosDscp], index0)) {
  21891                         temp_count = offset_array[loop][0];
  21892                         offset_array[loop][temp_count + 1] =
  21893                             map_array[bcmPolicerGroupModeAttrTosDscp][index0] <<
  21894                             shift_by_bits;
  21895                         offset_array[loop][0] =  temp_count + 1;
  21896                     }
  21897                 }
  21898                 loop++;
  21899             }
  21900             if ((pkt_attr_selectors->tos_ecn == 1) &&
  21901                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21902                 shift_by_bits = pkt_res_cmprsd_bits +
  21903                     svp_type_cmprsd_bits +
  21904                     drop_cmprsd_bits +
  21905                     ip_pkt_cmprsd_bits;
  21906 
  21907                 for (index0 = 0; index0 < tos_ecn_attrs; index0++) {
  21908                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  21909                                 value_array[_bcmPolicerAttrTosEcn], index0)) {
  21910                         temp_count = offset_array[loop][0];
  21911                         offset_array[loop][temp_count + 1] =
  21912                             map_array[bcmPolicerGroupModeAttrTosEcn][index0] <<
  21913                             shift_by_bits;
  21914                         offset_array[loop][0] =  temp_count + 1;
  21915                     }
  21916                 }
  21917                 loop++;
  21918             }
  21919             if ((pkt_attr_selectors->pkt_resolution == 1) &&
  21920                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  21921                 shift_by_bits = svp_type_cmprsd_bits +
  21922                     drop_cmprsd_bits +
  21923                     ip_pkt_cmprsd_bits;
  21924 
  21925                 temp_count = offset_array[loop][0];
  21926                 if (combine_attr_data->pkt_resolution_flags &
  21927                         _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) {
  21928                     offset_array[loop][temp_count + 1] =
  21929                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_PKT]] <<
  21930                          shift_by_bits);
  21931                     temp_count++;
  21932                 }
  21933                 if (combine_attr_data->pkt_resolution_flags &
  21934                         _BCM_POLICER_PKT_TYPE_CONTROL_PKT) {
  21935                     offset_array[loop][temp_count + 1] =
  21936                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[CONTROL_PKT]] <<
  21937                          shift_by_bits);
  21938                     temp_count++;
  21939                 }
  21940                 if (combine_attr_data->pkt_resolution_flags &
  21941                         _BCM_POLICER_PKT_TYPE_OAM_PKT) {
  21942                     offset_array[loop][temp_count + 1] =
  21943                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[OAM_PKT]] <<
  21944                          shift_by_bits);
  21945                     temp_count++;
  21946                 }
  21947                 if (combine_attr_data->pkt_resolution_flags &
  21948                         _BCM_POLICER_PKT_TYPE_BFD_PKT) {
  21949                     offset_array[loop][temp_count + 1] =
  21950                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[BFD_PKT]] <<
  21951                          shift_by_bits);
  21952                     temp_count++;
  21953                 }
  21954                 if (combine_attr_data->pkt_resolution_flags &
  21955                         _BCM_POLICER_PKT_TYPE_BPDU_PKT) {
  21956                     offset_array[loop][temp_count + 1] =
  21957                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[BPDU_PKT]] <<
  21958                          shift_by_bits);
  21959                     temp_count++;
  21960                 }
  21961                 if (combine_attr_data->pkt_resolution_flags &
  21962                         _BCM_POLICER_PKT_TYPE_ICNM_PKT) {
  21963                     offset_array[loop][temp_count + 1] =
  21964                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[ICNM_PKT]] <<
  21965                          shift_by_bits);
  21966                     temp_count++;
  21967                 }
  21968                 if (combine_attr_data->pkt_resolution_flags &
  21969                         _BCM_POLICER_PKT_TYPE_PKT_IS_1588) {
  21970                     offset_array[loop][temp_count + 1] =
  21971                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[PKT_IS_1588]] <<
  21972                          shift_by_bits);
  21973                     temp_count++;
  21974                 }
  21975                 if (combine_attr_data->pkt_resolution_flags &
  21976                         _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) {
  21977                     offset_array[loop][temp_count + 1] =
  21978                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L2UC_PKT]] <<
  21979                          shift_by_bits);
  21980                     temp_count++;
  21981                 }
  21982                 if (combine_attr_data->pkt_resolution_flags &
  21983                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) {
  21984                     offset_array[loop][temp_count + 1] =
  21985                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L2UC_PKT]] <<
  21986                          shift_by_bits);
  21987                     temp_count++;
  21988                 }
  21989                 if (combine_attr_data->pkt_resolution_flags &
  21990                         _BCM_POLICER_PKT_TYPE_L2BC_PKT) {
  21991                     offset_array[loop][temp_count + 1] =
  21992                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[L2BC_PKT]] <<
  21993                          shift_by_bits);
  21994                     temp_count++;
  21995                 }
  21996                 if (combine_attr_data->pkt_resolution_flags &
  21997                         _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) {
  21998                     offset_array[loop][temp_count + 1] =
  21999                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L2MC_PKT]] <<
  22000                          shift_by_bits);
  22001                     temp_count++;
  22002                 }
  22003                 if (combine_attr_data->pkt_resolution_flags &
  22004                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) {
  22005                     offset_array[loop][temp_count + 1] =
  22006                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L2MC_PKT]] <<
  22007                          shift_by_bits);
  22008                     temp_count++;
  22009                 }
  22010                 if (combine_attr_data->pkt_resolution_flags &
  22011                         _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) {
  22012                     offset_array[loop][temp_count + 1] =
  22013                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L3UC_PKT]] <<
  22014                          shift_by_bits);
  22015                     temp_count++;
  22016                 }
  22017                 if (combine_attr_data->pkt_resolution_flags &
  22018                         _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) {
  22019                     offset_array[loop][temp_count + 1] =
  22020                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L3UC_PKT]] <<
  22021                          shift_by_bits);
  22022                     temp_count++;
  22023                 }
  22024                 if (combine_attr_data->pkt_resolution_flags &
  22025                         _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) {
  22026                     offset_array[loop][temp_count + 1] =
  22027                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_IPMC_PKT]] <<
  22028                          shift_by_bits);
  22029                     temp_count++;
  22030                 }
  22031                 if (combine_attr_data->pkt_resolution_flags &
  22032                         _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) {
  22033                     offset_array[loop][temp_count + 1] =
  22034                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_IPMC_PKT]] <<
  22035                          shift_by_bits);
  22036                     temp_count++;
  22037                 }
  22038                 if (combine_attr_data->pkt_resolution_flags &
  22039                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) {
  22040                     offset_array[loop][temp_count + 1] =
  22041                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_L2_PKT]] <<
  22042                          shift_by_bits);
  22043                     temp_count++;
  22044                 }
  22045                 if (combine_attr_data->pkt_resolution_flags &
  22046                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) {
  22047                     offset_array[loop][temp_count + 1] =
  22048                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_L3_PKT]] <<
  22049                          shift_by_bits);
  22050                     temp_count++;
  22051                 }
  22052                 if (combine_attr_data->pkt_resolution_flags &
  22053                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) {
  22054                     offset_array[loop][temp_count + 1] =
  22055                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_PKT]] <<
  22056                          shift_by_bits);
  22057                     temp_count++;
  22058                 }
  22059                 if (combine_attr_data->pkt_resolution_flags &
  22060                         _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) {
  22061                     offset_array[loop][temp_count + 1] =
  22062                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_MPLS_PKT]] <<
  22063                          shift_by_bits);
  22064                     temp_count++;
  22065                 }
  22066                 if (combine_attr_data->pkt_resolution_flags &
  22067                         _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) {
  22068                     offset_array[loop][temp_count + 1] =
  22069                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_MULTICAST_PKT]] <<
  22070                          shift_by_bits);
  22071                     temp_count++;
  22072                 }
  22073                 if (combine_attr_data->pkt_resolution_flags &
  22074                         _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) {
  22075                     offset_array[loop][temp_count + 1] =
  22076                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MIM_PKT]] <<
  22077                          shift_by_bits);
  22078                     temp_count++;
  22079                 }
  22080                 if (combine_attr_data->pkt_resolution_flags &
  22081                         _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) {
  22082                     offset_array[loop][temp_count + 1] =
  22083                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_MIM_PKT]] <<
  22084                          shift_by_bits);
  22085                     temp_count++;
  22086                 }
  22087                 if (combine_attr_data->pkt_resolution_flags &
  22088                         _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) {
  22089                     offset_array[loop][temp_count + 1] =
  22090                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_TRILL_PKT]] <<
  22091                          shift_by_bits);
  22092                     temp_count++;
  22093                 }
  22094                 if (combine_attr_data->pkt_resolution_flags &
  22095                         _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) {
  22096                     offset_array[loop][temp_count + 1] =
  22097                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_TRILL_PKT]] <<
  22098                          shift_by_bits);
  22099                     temp_count++;
  22100                 }
  22101                 if (combine_attr_data->pkt_resolution_flags &
  22102                         _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) {
  22103                     offset_array[loop][temp_count + 1] =
  22104                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_NIV_PKT]] <<
  22105                          shift_by_bits);
  22106                     temp_count++;
  22107                 }
  22108                 if (combine_attr_data->pkt_resolution_flags &
  22109                         _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) {
  22110                     offset_array[loop][temp_count + 1] =
  22111                         (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_NIV_PKT]] <<
  22112                          shift_by_bits);
  22113                     temp_count++;
  22114                 }
  22115                 offset_array[loop][0] = temp_count;
  22116                 loop++;
  22117             }
  22118             if ((pkt_attr_selectors->svp_type == 1) &&
  22119                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  22120                 shift_by_bits = drop_cmprsd_bits +
  22121                     ip_pkt_cmprsd_bits;
  22122 
  22123                 for (index0 = 0; index0 < svp_type_attrs; index0++) {
  22124                     if (_BCM_POLICER_VALUE_GET(combine_attr_data->
  22125                                 value_array[_bcmPolicerAttrSvpType], index0)) {
  22126                         temp_count = offset_array[loop][0];
  22127                         offset_array[loop][temp_count + 1] =
  22128                             map_array[bcmPolicerGroupModeAttrIngNetworkGroup][index0] <<
  22129                             shift_by_bits;
  22130                         offset_array[loop][0] =  temp_count + 1;
  22131                     }
  22132                 }
  22133                 loop++;
  22134             }
  22135             if ((pkt_attr_selectors->drop == 1) &&
  22136                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  22137                 shift_by_bits = ip_pkt_cmprsd_bits;
  22138 
  22139                 temp_count = offset_array[loop][0];
  22140                 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_DISABLE) {
  22141                     offset_array[loop][temp_count + 1] =
  22142                         (map_array[bcmPolicerGroupModeAttrDrop][0] <<
  22143                          shift_by_bits);
  22144                     temp_count++;
  22145                 }
  22146                 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_ENABLE) {
  22147                     offset_array[loop][temp_count + 1] =
  22148                         (map_array[bcmPolicerGroupModeAttrDrop][1] <<
  22149                          shift_by_bits);
  22150                     temp_count++;
  22151                 }
  22152                 offset_array[loop][0] = temp_count;
  22153                 loop++;
  22154             }
  22155             if ((pkt_attr_selectors->ip_pkt == 1) &&
  22156                     (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) {
  22157                 shift_by_bits = 0;
  22158                 temp_count = offset_array[loop][0];
  22159                 if (combine_attr_data->ip_pkt_flags & _BCM_POLICER_IP_PKT_DISABLE) {
  22160                     offset_array[loop][temp_count + 1] =
  22161                         (map_array[bcmPolicerGroupModeAttrPacketTypeIp][0] <<
  22162                          shift_by_bits);
  22163                     temp_count++;
  22164                 }
  22165                 if (combine_attr_data->ip_pkt_flags & _BCM_POLICER_IP_PKT_ENABLE) {
  22166                     offset_array[loop][temp_count + 1] =
  22167                         (map_array[bcmPolicerGroupModeAttrPacketTypeIp][1] <<
  22168                          shift_by_bits);
  22169                     temp_count++;
  22170                 }
  22171                 offset_array[loop][0] = temp_count;
  22172                 loop++;
  22173             }
  22174 
  22175             /* Step 4.2.3 : compute final offset value */
  22176             rv = _bcm_policer_group_mode_offset_map_generate(unit,
  22177                     meter_attr, group_mode, pol_offset, offset_array);
  22178             if (rv != BCM_E_NONE) {
  22179                 break;
  22180             }
  22181         }
  22182     }
  22183 
  22184     if (BCM_FAILURE(rv)) {
  22185         goto cleanup;
  22186     }
  22187 
  22188     GLOBAL_METER_LOCK(unit);
  22189     rv = _bcm_esw_policer_svc_meter_create_mode (unit, meter_attr, group_mode,
  22190             type, pkt_attr_selectors->total_policers, pkt_attr_selectors, mode_id);
  22191     GLOBAL_METER_UNLOCK(unit);
  22192 
  22193 cleanup:
  22194 
  22195     /* Free map_array */
  22196     for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) {
  22197         if (map_array[loop] != NULL) {
  22198             sal_free(map_array[loop]);
  22199         }
  22200     }
  22201     /* Free offset_array */
  22202     for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  22203         if (offset_array[loop] != NULL) {
  22204             sal_free(offset_array[loop]);
  22205         }
  22206     }
  22207 
  22208     /* Free meter_attr */
  22209     if (meter_attr != NULL) {
  22210         sal_free(meter_attr);
  22211     }
  22212 
  22213     if ((rv == BCM_E_EXISTS) &&
  22214             (soc_feature(unit, soc_feature_global_meter_compression_share))) {
  22215         rv = BCM_E_NONE;
  22216     }
  22217 
  22218     return rv;
  22219 }
  22220 
  22221 /*
  22222  * Function:
  22223  *      _bcm_policer_custom_group_mode_id_create
  22224  * Purpose:
  22225  *      This function is used to configure customnized group mode
  22226  * Parameters:
  22227  *     unit                  - (IN) unit number
  22228  *     flags                 - (IN) flags
  22229  *     type                  - (IN) type of group mode
  22230  *     total_policers        - (IN) total policers
  22231  *     num_selectors         - (IN) number of selectors
  22232  *     attr_selectors        - (IN) list of attributes selectors
  22233  *     mode_id               - (OUT) pointer to offset mode index
  22234  * Returns:
  22235  *     BCM_E_XXX
  22236  */
  22237 int
  22238 _bcm_policer_custom_group_mode_id_create(
  22239     int unit,
  22240     uint32 flags,
  22241     bcm_policer_group_mode_type_t type,
  22242     uint32 total_policers,
  22243     uint32 num_selectors,
  22244     bcm_policer_group_mode_attr_selector_t *attr_selectors,
  22245     uint32 *mode_id)
  22246 {
  22247     int rv = BCM_E_NONE;
  22248     bcm_policer_attr_selectors_t pkt_attr_selectors;
  22249     uint32 npolicers = 0;
  22250 
  22251     npolicers = total_policers;
  22252     if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) {
  22253         npolicers = total_policers/2;
  22254     }
  22255 
  22256     /* Check if mode info already exists */
  22257     rv = _bcm_esw_svc_meter_offset_mode_id_check(unit, flags, type,
  22258             total_policers, num_selectors, attr_selectors, mode_id);
  22259     BCM_IF_ERROR_RETURN(rv);
  22260 
  22261     sal_memset(&pkt_attr_selectors, 0, sizeof(bcm_policer_attr_selectors_t));
  22262     pkt_attr_selectors.combine_attr_data =
  22263             sal_alloc(sizeof(bcm_policer_combine_attr_t) * npolicers,
  22264             "combine attributes");
  22265     if (pkt_attr_selectors.combine_attr_data == NULL) {
  22266         return BCM_E_MEMORY;
  22267     }
  22268     sal_memset(pkt_attr_selectors.combine_attr_data, 0,
  22269             sizeof(bcm_policer_combine_attr_t) * npolicers);
  22270 
  22271     rv = _bcm_esw_policer_group_mode_fillup_values (unit, flags, type,
  22272                 npolicers, num_selectors, attr_selectors, &pkt_attr_selectors);
  22273     if (rv != BCM_E_NONE) {
  22274         sal_free(pkt_attr_selectors.combine_attr_data);
  22275         return rv;
  22276     }
  22277 
  22278     rv = _bcm_esw_policer_group_mode_id_associate(unit, flags,
  22279                 type, &pkt_attr_selectors, mode_id);
  22280     if (rv != BCM_E_NONE) {
  22281         sal_free(pkt_attr_selectors.combine_attr_data);
  22282         return rv;
  22283     }
  22284 
  22285     GLOBAL_METER_LOCK(unit);
  22286     /* In case of group type is cascade/cascadewithcoupling, total_policers
  22287      * must be set to 8. This requirement is due to the fact that in these
  22288      * two cases, meter index allocation is one complete octuple */
  22289     if ((type == bcmPolicerGroupModeTypeCascade) ||
  22290             (type == bcmPolicerGroupModeTypeCascadeWithCoupling)) {
  22291         global_meter_offset_mode[unit][*mode_id].no_of_policers = 8;
  22292     } else {
  22293         global_meter_offset_mode[unit][*mode_id].no_of_policers =
  22294                                                         total_policers;
  22295     }
  22296     rv = _bcm_policer_svc_meter_group_offset_mode_info_update (unit, *mode_id,
  22297                     type, num_selectors, attr_selectors);
  22298     if (BCM_FAILURE(rv)) {
  22299         _bcm_policer_svc_meter_unreserve_mode (unit, *mode_id);
  22300         GLOBAL_METER_UNLOCK(unit);
  22301         return rv;
  22302     }
  22303     /* Update compressed attribute maps */
  22304     if (global_meter_offset_mode[unit][*mode_id].meter_attr.mode_type_v ==
  22305                 compressed_mode) {
  22306         (void) _bcm_esw_svm_pkt_compressed_attr_maps_update(unit,
  22307                         &pkt_attr_selectors);
  22308     }
  22309     GLOBAL_METER_UNLOCK(unit);
  22310     return rv;
  22311 }
  22312 
  22313 /*
  22314  * Function:
  22315  *      _bcm_esw_policer_udf_custom_group_create
  22316  * Purpose:
  22317  *      This function is used to configure udf based
  22318  *      group mode
  22319  * Parameters:
  22320  *     unit                  - (IN) unit number
  22321  *     flags                 - (IN) flags
  22322  *     type                  - (IN) type of group mode
  22323  *     total_policers        - (IN) total policers
  22324  *     num_selectors         - (IN) number of selectors
  22325  *     attr_selectors        - (IN) list of attributes selectors
  22326  *     mode_id               - (OUT) pointer to offset mode index
  22327  * Returns:
  22328  *     BCM_E_XXX
  22329  */
  22330 int
  22331 _bcm_esw_policer_udf_custom_group_create(
  22332     int unit,
  22333     uint32 flags,
  22334     bcm_policer_group_mode_type_t type,
  22335     uint32 total_policers,
  22336     uint32 num_selectors,
  22337     bcm_policer_group_mode_attr_selector_t *attr_selectors,
  22338     uint32 *mode_id)
  22339 {
  22340     int rv = BCM_E_NONE;
  22341     bcm_policer_udf_attr_selectors_t udf_attr_selectors;
  22342     bcm_policer_udf_pkt_combine_attr_t *udf_combine_data = NULL;
  22343     bcm_policer_udf_sub_div_t dummy_data;
  22344 
  22345     bcm_policer_svc_meter_attr_t *meter_attr = NULL;
  22346     bcm_policer_group_mode_t group_mode;
  22347     bcm_policer_svc_meter_mode_type_t mode_type_v;
  22348     uint32 npolicers = 0;
  22349 
  22350     uint8 shift_by_bits_array[SVC_METER_UDF1_MAX_BIT_POSITION] = {0};
  22351     int8 loop_index_array[SVC_METER_UDF1_MAX_BIT_POSITION] = {-1};
  22352     uint8 *offset_array[SVC_METER_MAX_SELECTOR_BITS] = {NULL};
  22353     uint32 sorted = 0, total_bits = 0, shift_by_bits = 0;
  22354     uint32 index0 = 0, index1 = 0;
  22355     uint32 loop_index = 0, loop =0;
  22356     uint32 offset = 0, total_offsets = 0;
  22357     uint32 pol_offset = 0;
  22358 
  22359     npolicers = total_policers;
  22360     if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) {
  22361         npolicers = total_policers/2;
  22362     }
  22363 
  22364     /* Check if mode info already exists */
  22365     rv = _bcm_esw_svc_meter_offset_mode_id_check(unit, flags, type,
  22366                 total_policers, num_selectors, attr_selectors, mode_id);
  22367     BCM_IF_ERROR_RETURN(rv);
  22368 
  22369     sal_memset (&udf_attr_selectors, 0,
  22370             sizeof(bcm_policer_udf_attr_selectors_t));
  22371     udf_attr_selectors.combine_attr_data =
  22372             sal_alloc(sizeof(bcm_policer_udf_pkt_combine_attr_t) * npolicers,
  22373             "combine attributes");
  22374 
  22375     if (udf_attr_selectors.combine_attr_data == NULL) {
  22376         return BCM_E_MEMORY;
  22377     }
  22378     sal_memset(udf_attr_selectors.combine_attr_data, 0,
  22379             sizeof(bcm_policer_udf_pkt_combine_attr_t) * npolicers);
  22380 
  22381     rv = _bcm_esw_policer_group_udf_mode_fillup_values (unit, flags, type,
  22382                 npolicers, num_selectors, attr_selectors, &udf_attr_selectors);
  22383     if (rv != BCM_E_NONE) {
  22384         sal_free(udf_attr_selectors.combine_attr_data);
  22385         return rv;
  22386     }
  22387 
  22388     /* Below block of code is intended to sort the input offset/width
  22389      * in ascending order of udf offsets numerically.
  22390      * 'total_bits' required is also calculated to check if creating mode
  22391      * with given attr_selectors is possible or not.
  22392      * Also, shift bits needs to be calculated which is later used to
  22393      * generate offset to be indexed for SVM_OFFSET_TABLE
  22394      */
  22395     sorted = total_bits = shift_by_bits = 0;
  22396     if (udf_attr_selectors.drop) {
  22397         total_bits++;
  22398         shift_by_bits = 1;
  22399     }
  22400     /* Loop through lower offset to higher offset index to calculate shift */
  22401     for (index0 = 0; index0 < SVC_METER_UDF1_MAX_BIT_POSITION; index0++) {
  22402         if (udf_attr_selectors.udf_bits[index0] == 1) {
  22403             for (index1 = sorted; index1 < udf_attr_selectors.total_subdiv; index1++) {
  22404                 if (udf_attr_selectors.udf_subdiv[index1].offset == index0) {
  22405                     /* Swap to rearrange */
  22406                     sal_memcpy(&dummy_data, &udf_attr_selectors.udf_subdiv[index1],
  22407                                 sizeof (bcm_policer_udf_sub_div_t));
  22408                     sal_memcpy(&udf_attr_selectors.udf_subdiv[index1],
  22409                                 &udf_attr_selectors.udf_subdiv[sorted],
  22410                                 sizeof(bcm_policer_udf_sub_div_t));
  22411                     sal_memcpy(&udf_attr_selectors.udf_subdiv[sorted], &dummy_data,
  22412                                         sizeof (bcm_policer_udf_sub_div_t));
  22413                     total_bits += udf_attr_selectors.udf_subdiv[sorted].width;
  22414                     shift_by_bits_array[index0] = shift_by_bits;
  22415                     shift_by_bits += udf_attr_selectors.udf_subdiv[sorted].width;
  22416                     sorted++;
  22417                     break;
  22418                 }
  22419             }
  22420         }
  22421     }
  22422 
  22423     if (total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) {
  22424         sal_free(udf_attr_selectors.combine_attr_data);
  22425         return BCM_E_PARAM;
  22426     }
  22427 
  22428     meter_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t),"meter mode attr");
  22429     if ( meter_attr == NULL) {
  22430         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22431                       "Failed to allocate memory for svc meter attr \n")));
  22432         sal_free(udf_attr_selectors.combine_attr_data);
  22433         return BCM_E_MEMORY;
  22434     }
  22435     sal_memset (meter_attr, 0, sizeof(bcm_policer_svc_meter_attr_t));
  22436 
  22437     /* bcm_policer_group_mode_t should be based on type */
  22438     if (type == bcmPolicerGroupModeTypeNormal) {
  22439         mode_type_v = udf_mode;
  22440         group_mode = bcmPolicerGroupModeSingle;
  22441     } else if (type == bcmPolicerGroupModeTypeCascade) {
  22442         mode_type_v = udf_cascade_mode;
  22443         group_mode = bcmPolicerGroupModeCascade;
  22444     } else {  /* type == bcmPolicerGroupModeTypeCascadeWithCoupling */
  22445         mode_type_v = udf_cascade_with_coupling_mode;
  22446         group_mode = bcmPolicerGroupModeCascadeWithCoupling;
  22447     }
  22448     meter_attr->udf_pkt_attr_selectors_v.num_selectors = num_selectors;
  22449     meter_attr->udf_pkt_attr_selectors_v.udf_id = attr_selectors[0].udf_id;
  22450     meter_attr->mode_type_v = mode_type_v;
  22451 
  22452     if (udf_attr_selectors.drop == 1) {
  22453         meter_attr->udf_pkt_attr_selectors_v.drop = 1;
  22454     }
  22455     if (udf_attr_selectors.total_subdiv > 0) {
  22456         meter_attr->udf_pkt_attr_selectors_v.total_subdiv =
  22457                                         udf_attr_selectors.total_subdiv;
  22458         sal_memcpy(&meter_attr->udf_pkt_attr_selectors_v.udf_subdiv[0],
  22459                     &udf_attr_selectors.udf_subdiv[0],
  22460                     sizeof(udf_attr_selectors.udf_subdiv));
  22461     }
  22462 
  22463     for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  22464         offset_array[loop] =
  22465                     (uint8 *) sal_alloc(BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1,
  22466                                 "offset_array");
  22467         if (offset_array[loop] == NULL) {
  22468             rv = BCM_E_MEMORY;
  22469             break;
  22470         }
  22471     }
  22472     if (BCM_FAILURE(rv)) {
  22473         for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  22474             if (offset_array[loop] != NULL) {
  22475                 sal_free(offset_array[loop]);
  22476             }
  22477         }
  22478         sal_free(meter_attr);
  22479         sal_free(udf_attr_selectors.combine_attr_data);
  22480         return rv;
  22481     }
  22482     /* Loop through all policer offset and compute offset map */
  22483     for (pol_offset = 0; pol_offset < npolicers; pol_offset++) {
  22484         sal_memset(&loop_index_array[0], -1, sizeof (loop_index_array));
  22485         for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  22486             sal_memset(offset_array[loop], 0,
  22487                     BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1);
  22488         }
  22489         loop = loop_index = 0;
  22490         udf_combine_data = &udf_attr_selectors.combine_attr_data[pol_offset];
  22491         /* Loop through all udf sub-division per policer offset */
  22492         for (index1 = 0; index1 < udf_combine_data->selectors; index1++) {
  22493             offset = udf_combine_data->udf_subdiv[index1].offset;
  22494             /* Get loop_index */
  22495             if (loop_index_array[offset] == -1) {
  22496                 loop_index_array[offset] = loop_index;
  22497                 loop_index++;
  22498             }
  22499             loop = loop_index_array[offset];
  22500 
  22501             /* get current count */
  22502             total_offsets = offset_array[loop][0];
  22503             /* Save the value */
  22504             offset_array[loop][total_offsets + 1] =
  22505                 udf_combine_data->attr_value[index1] << shift_by_bits_array[offset];
  22506             offset_array[loop][0] = total_offsets + 1;
  22507         }
  22508         if (udf_attr_selectors.drop == 1) {
  22509             loop = loop_index;
  22510             total_offsets = offset_array[loop][0];
  22511             if ((udf_combine_data->drop_flags & _BCM_POLICER_DROP_DISABLE) != 0) {
  22512                 offset_array[loop][total_offsets + 1] = 0;
  22513                 total_offsets++;
  22514             }
  22515             if ((udf_combine_data->drop_flags & _BCM_POLICER_DROP_ENABLE) != 0) {
  22516                 offset_array[loop][total_offsets + 1] = 1;
  22517                 total_offsets++;
  22518             }
  22519             offset_array[loop][0] = total_offsets;
  22520         }
  22521 
  22522         /* Make final offset calculation */
  22523         rv = _bcm_policer_group_mode_offset_map_generate(unit, meter_attr,
  22524                 group_mode, pol_offset, offset_array);
  22525         if (rv != BCM_E_NONE) {
  22526             break;
  22527         }
  22528     }
  22529 
  22530     for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) {
  22531         if (offset_array[loop] != NULL) {
  22532             sal_free(offset_array[loop]);
  22533         }
  22534     }
  22535     if (udf_attr_selectors.combine_attr_data != NULL) {
  22536         sal_free(udf_attr_selectors.combine_attr_data);
  22537     }
  22538 
  22539     GLOBAL_METER_LOCK(unit);
  22540     rv = _bcm_esw_policer_svc_meter_create_mode (unit, meter_attr, group_mode,
  22541                type, total_policers, NULL, mode_id);
  22542     if (BCM_FAILURE(rv) && (rv != BCM_E_EXISTS)) {
  22543         GLOBAL_METER_UNLOCK(unit);
  22544         sal_free(meter_attr);
  22545         return rv;
  22546     } else if (rv == BCM_E_EXISTS) {
  22547         GLOBAL_METER_UNLOCK(unit);
  22548         sal_free(meter_attr);
  22549         return BCM_E_NONE;
  22550     } else {
  22551         /* In case of group type is cascade/cascadewithcoupling, total_policers
  22552          * must be set to 8. This requirement is due to the fact that in these
  22553          * two cases, meter index allocation is whole octuple */
  22554         if ((type == bcmPolicerGroupModeTypeCascade) ||
  22555                 (type == bcmPolicerGroupModeTypeCascadeWithCoupling)) {
  22556             global_meter_offset_mode[unit][*mode_id].no_of_policers = 8;
  22557         } else {
  22558             global_meter_offset_mode[unit][*mode_id].no_of_policers =
  22559                     total_policers;
  22560         }
  22561 
  22562         rv = _bcm_policer_svc_meter_group_offset_mode_info_update (unit,
  22563                 *mode_id, type, num_selectors, attr_selectors);
  22564         if (BCM_FAILURE(rv)) {
  22565             _bcm_policer_svc_meter_unreserve_mode (unit, *mode_id);
  22566             GLOBAL_METER_UNLOCK(unit);
  22567             sal_free(meter_attr);
  22568             return rv;
  22569         }
  22570     }
  22571     GLOBAL_METER_UNLOCK(unit);
  22572     sal_free(meter_attr);
  22573     return rv;
  22574 }
  22575 
  22576 /*
  22577  * Function:
  22578  *      bcm_esw_policer_group_mode_id_create
  22579  * Purpose:
  22580  *     Create Customized Policer Group mode for given Policer Attributes
  22581  * Parameters:
  22582  *     unit                  - (IN) unit number
  22583  *     flags                 - (IN) flags
  22584  *     type                  - (IN) modes of policer group creation -
  22585  *                                  normal/cascade/cascade with coupling.
  22586  *     total_policers        - (IN) Total Policers in Policer Group Mode
  22587  *     num_selectors         - (IN) Number of Selectors for policer Group Mode
  22588  *     attr_selectors        - (IN) Attribute Selectors for Policer Group Mode
  22589  *     mode_id               - (OUT) Created mode Id for Policer Group Mode
  22590  * Returns:
  22591  *     BCM_E_XXX
  22592  */
  22593 int
  22594 bcm_esw_policer_group_mode_id_create(
  22595     int unit,
  22596     uint32 flags,
  22597     bcm_policer_group_mode_type_t type,
  22598     uint32 total_policers,
  22599     uint32 num_selectors,
  22600     bcm_policer_group_mode_attr_selector_t *attr_selectors,
  22601     uint32 *mode_id)
  22602 {
  22603     int rv = BCM_E_NONE;
  22604     int num_pools = 0;
  22605     uint32 index = 0;
  22606     int8 custom_group_udf_type = -1;
  22607 
  22608 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  22609     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  22610         return bcmi_esw_policer_group_mode_id_create(unit,
  22611                   flags, type, total_policers, num_selectors,
  22612                   attr_selectors, mode_id);
  22613     }
  22614 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  22615 
  22616     num_pools =  SOC_INFO(unit).global_meter_pools;
  22617 
  22618     if (!soc_feature(unit, soc_feature_global_meter)) {
  22619         return BCM_E_UNAVAIL;
  22620     }
  22621 
  22622     if (type >= bcmPolicerGroupModeTypeCount) {
  22623         return (BCM_E_PARAM);
  22624     }
  22625 
  22626     /* Attribute selectors are used for selecting one of the policers created in
  22627      * policer group. For total_policer=1 there is just one policer.
  22628      * Hence, attribute selectors have no significance.
  22629      * All other IN parameters are set fixed to avoid any confusion
  22630      * while fetching group policer config via bcm_policer_group_mode_id_get()
  22631      */
  22632     if (total_policers == 1) {
  22633         if ((type == bcmPolicerGroupModeTypeNormal) &&
  22634                 (attr_selectors == NULL) &&
  22635                 (num_selectors == 0)) {
  22636             *mode_id = 1;
  22637             return (BCM_E_NONE);
  22638         } else if ((type != bcmPolicerGroupModeTypeNormal) ||
  22639                 !soc_feature(unit,
  22640                     soc_feature_global_meter_compaction_support)) {
  22641             LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Single policer"
  22642                             " with ModeType Not Normal is not allowed\n")));
  22643             return (BCM_E_PARAM);
  22644         }
  22645     }
  22646 
  22647     if ((total_policers == 0) || (num_selectors == 0)) {
  22648         return (BCM_E_PARAM);
  22649     }
  22650     if ((type == bcmPolicerGroupModeTypeNormal) && (total_policers > 256)) {
  22651         return (BCM_E_PARAM);
  22652     }
  22653     if ((type == bcmPolicerGroupModeTypeCascade)
  22654                     && (total_policers > num_pools)) {
  22655         return (BCM_E_PARAM);
  22656     }
  22657     if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) {
  22658         if (total_policers > (num_pools/2)) {
  22659             return (BCM_E_PARAM);
  22660         }
  22661         total_policers = 8;
  22662     }
  22663 
  22664     if (attr_selectors == NULL) {
  22665         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22666                   "Packet attributes selector(s) is(are) not provided\n")));
  22667         return (BCM_E_PARAM);
  22668     }
  22669 
  22670     /* loop through attr_selectors[x].attr to determine correct internal API call */
  22671     for (index = 0; index < num_selectors; index++) {
  22672         if (attr_selectors[index].attr == bcmPolicerGroupModeAttrUdf) {
  22673             if (custom_group_udf_type == 0) {
  22674                 rv = BCM_E_PARAM;
  22675                 break;
  22676             }
  22677             custom_group_udf_type = 1;
  22678         } else if (attr_selectors[index].attr != bcmPolicerGroupModeAttrDrop) {
  22679             if (custom_group_udf_type == 1) {
  22680                 rv = BCM_E_PARAM;
  22681                 break;
  22682             }
  22683             custom_group_udf_type = 0;
  22684         }
  22685     }
  22686     if (rv == BCM_E_PARAM) {
  22687         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22688                   "Mix of UDF and other attributes not allowed\n")));
  22689         return rv;
  22690     }
  22691 
  22692     if (custom_group_udf_type == 0) {
  22693         rv = _bcm_policer_custom_group_mode_id_create(unit, flags, type,
  22694                                         total_policers, num_selectors,
  22695                                         attr_selectors, mode_id);
  22696     } else {
  22697         rv = _bcm_esw_policer_udf_custom_group_create(unit, flags, type,
  22698                                         total_policers, num_selectors,
  22699                                         attr_selectors, mode_id);
  22700     }
  22701     if (rv == BCM_E_EXISTS) {
  22702         if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  22703             *mode_id = *mode_id + 1;
  22704         }
  22705         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22706                   "  policer group mode id exists, mode id 8x%x\n"), *mode_id));
  22707         return (rv);
  22708     } else if (BCM_FAILURE(rv)) {
  22709         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22710                   "Unable to create policer group  \n")));
  22711          return (rv);
  22712     }
  22713     *mode_id = *mode_id + 1;
  22714     LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22715                       "Created policer group with mode id 0x%x \n"), *mode_id));
  22716     return rv;
  22717 
  22718 }
  22719 
  22720 /*
  22721  * Function:
  22722  *      bcm_esw_policer_group_mode_id_destroy
  22723  * Purpose:
  22724  *     Destroy Customized Policer Group mode with given mode_id.
  22725  * Parameters:
  22726  *     unit                  - (IN) unit number
  22727  *     mode_id               - (IN) Created mode Id for Policer Group Mode
  22728  * Returns:
  22729  *     BCM_E_XXX
  22730  */
  22731 int
  22732 bcm_esw_policer_group_mode_id_destroy(
  22733     int unit,
  22734     uint32 mode_id)
  22735 {
  22736     bcm_policer_svc_meter_bookkeep_mode_t   mode_info;
  22737     int rv = BCM_E_NONE;
  22738 
  22739 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  22740     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  22741         return bcmi_esw_policer_group_mode_id_destroy(unit, mode_id);
  22742     }
  22743 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  22744 
  22745     if (!soc_feature(unit, soc_feature_global_meter)) {
  22746         return BCM_E_UNAVAIL;
  22747     }
  22748     if ((mode_id == 0) || (mode_id > BCM_POLICER_SVC_METER_MAX_MODE)) {
  22749         return (BCM_E_PARAM);
  22750     }
  22751     mode_id -= 1;
  22752     if (mode_id == 0) {
  22753         return (BCM_E_NONE);
  22754     }
  22755 
  22756     sal_memset(&mode_info, 0, sizeof(mode_info));
  22757     rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id, &mode_info);
  22758     BCM_IF_ERROR_RETURN(rv);
  22759 
  22760     if (mode_info.reference_count > 0) {
  22761         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  22762                       "Policer group mode is still in use   \n")));
  22763         return (BCM_E_BUSY);
  22764     } else {
  22765         rv = _bcm_esw_policer_svc_meter_delete_mode(unit, mode_id);
  22766     }
  22767     return rv;
  22768 }
  22769 
  22770 /*
  22771  * Function:
  22772  *      bcm_esw_policer_group_mode_id_get
  22773  * Purpose:
  22774  *     Retrieves Customized Policer Group mode Attributes for given mode_id.
  22775  * Parameters:
  22776  *     unit                  - (IN) unit number
  22777  *     mode_id               - (IN) Created mode Id for Policer Group Mode
  22778  *     num_selectors         - (IN) Number of Selectors for policer Group Mode
  22779  *     flags                 - (OUT) flags
  22780  *     type                  - (OUT) modes of policer group creation -
  22781  *                                   normal/cascade/cascade with coupling.
  22782  *     total_policers        - (OUT) Total Policers in Policer Group Mode
  22783  *     attr_selectors        - (OUT) Attribute Selectors for Policer Group Mode
  22784  *     actual_num_selectors  - (OUT) Actual Number of Selectors for Policer
  22785  *                                   Group Mode
  22786  * Returns:
  22787  *     BCM_E_XXX
  22788  */
  22789 int
  22790 bcm_esw_policer_group_mode_id_get(
  22791     int unit,
  22792     uint32 mode_id,
  22793     uint32 num_selectors,
  22794     uint32 *flags,
  22795     bcm_policer_group_mode_type_t *type,
  22796     uint32 *total_policers,
  22797     bcm_policer_group_mode_attr_selector_t *attr_selectors,
  22798     uint32 *actual_num_selectors)
  22799 {
  22800     int rv = BCM_E_NONE;
  22801     bcm_policer_svc_meter_bookkeep_mode_t   mode_info;
  22802     udf_pkt_attr_selectors_t     *udf_attr = NULL;
  22803     int  i, j;
  22804     int pool_offset_limit;
  22805     bcm_policer_svc_meter_mode_type_t mode_type_v;
  22806 
  22807 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  22808     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  22809         return bcmi_esw_policer_group_mode_id_get(unit,
  22810                   mode_id, num_selectors, flags, type, total_policers,
  22811                   attr_selectors, actual_num_selectors);
  22812     }
  22813 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  22814 
  22815     if (!soc_feature(unit, soc_feature_global_meter)) {
  22816         return BCM_E_UNAVAIL;
  22817     }
  22818     if ((mode_id == 0) || (mode_id > BCM_POLICER_SVC_METER_MAX_MODE)) {
  22819         return (BCM_E_PARAM);
  22820     }
  22821     if (mode_id == 1) {
  22822         *flags = 0;
  22823         *type = bcmPolicerGroupModeTypeNormal;
  22824         *actual_num_selectors = 0;
  22825         *total_policers = 1;
  22826         return BCM_E_NONE;
  22827     }
  22828 
  22829     sal_memset (&mode_info, 0, sizeof(mode_info));
  22830     rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id - 1, &mode_info);
  22831     BCM_IF_ERROR_RETURN(rv);
  22832 
  22833     *total_policers = mode_info.no_of_policers;
  22834     if (mode_info.group_mode == bcmPolicerGroupModeCascadeWithCoupling) {
  22835         *total_policers = mode_info.no_of_policers / 2;
  22836     }
  22837 
  22838     *flags =  0;
  22839     mode_type_v = mode_info.meter_attr.mode_type_v;
  22840     if ((mode_info.type != -1) &&
  22841         (mode_info.attr_selectors != NULL)) {
  22842         *type = mode_info.type;
  22843         *actual_num_selectors = mode_info.no_of_selectors;
  22844 
  22845         if (mode_info.attr_selectors != NULL) {
  22846             rv =  _bcm_wb_attr_selectors_copy_to_attr_selectors(
  22847                         mode_info.no_of_selectors,
  22848                         mode_info.attr_selectors, attr_selectors);
  22849             BCM_IF_ERROR_RETURN(rv);
  22850         }
  22851         return BCM_E_NONE;
  22852     }
  22853 
  22854     switch (mode_type_v) {
  22855         case udf_mode:
  22856         {
  22857             udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v;
  22858             *type = bcmPolicerGroupModeTypeNormal;
  22859             *actual_num_selectors = mode_info.no_of_selectors;
  22860             if (num_selectors > *actual_num_selectors) {
  22861                  num_selectors = *actual_num_selectors;
  22862             }
  22863             j = 0;
  22864             for (i = 0; i < BCM_SVC_METER_MAP_SIZE_256; i++)   {
  22865                 if (udf_attr->offset_map[i].meter_enable == 1)  {
  22866                     attr_selectors[j].attr_value = i;
  22867                     attr_selectors[j].policer_offset =
  22868                             udf_attr->offset_map[i].offset;
  22869                     attr_selectors[j].udf_id = udf_attr->udf_id;
  22870                     attr_selectors[j].width = udf_attr->udf_subdiv[0].width;
  22871                     attr_selectors[j].flags |= BCM_POLICER_ATTR_WIDTH_OFFSET;
  22872                     attr_selectors[j].attr = bcmPolicerGroupModeAttrUdf;
  22873                     attr_selectors[j].offset = udf_attr->udf_subdiv[0].offset;
  22874 
  22875                     j++;
  22876                 }
  22877             }
  22878             break;
  22879         }
  22880         case udf_cascade_mode:
  22881         case udf_cascade_with_coupling_mode:
  22882         {
  22883             udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v;
  22884             pool_offset_limit =
  22885                     (mode_info.group_mode == bcmPolicerGroupModeCascade) ?
  22886                     BCM_POLICER_GLOBAL_METER_MAX_POOL :
  22887                     BCM_POLICER_GLOBAL_METER_MAX_POOL/2;
  22888             *type = (mode_type_v == udf_cascade_mode) ?
  22889                     bcmPolicerGroupModeTypeCascade :
  22890                     bcmPolicerGroupModeTypeCascadeWithCoupling;
  22891             *actual_num_selectors = mode_info.no_of_selectors;
  22892             if (num_selectors > *actual_num_selectors) {
  22893                  num_selectors = *actual_num_selectors;
  22894             }
  22895             j = 0;
  22896             for (i = 0; i < BCM_SVC_METER_MAP_SIZE_256; i++)   {
  22897                 if (udf_attr->offset_map[i].meter_enable == 1)  {
  22898                     attr_selectors[j].attr_value = i;
  22899                     attr_selectors[j].udf_id = udf_attr->udf_id;
  22900                     attr_selectors[j].width = udf_attr->udf_subdiv[0].width;
  22901                     attr_selectors[j].flags |= BCM_POLICER_ATTR_WIDTH_OFFSET;
  22902                     attr_selectors[j].attr = bcmPolicerGroupModeAttrUdf;
  22903                     attr_selectors[j].offset = udf_attr->udf_subdiv[0].offset;
  22904 
  22905                     if (soc_feature(unit,
  22906                             soc_feature_global_meter_pool_priority_descending)) {
  22907                         attr_selectors[j].policer_offset = (pool_offset_limit -
  22908                                 udf_attr->offset_map[i].pool - 1);
  22909                     } else {
  22910                         attr_selectors[j].policer_offset =
  22911                                 udf_attr->offset_map[i].pool;
  22912                     }
  22913                     j++;
  22914                 }
  22915             }
  22916             break;
  22917         }
  22918         default:
  22919             return BCM_E_UNAVAIL;
  22920             break;
  22921     }
  22922     return BCM_E_NONE;
  22923 }
  22924 
  22925 STATIC int
  22926 _global_meter_policer_group_alloc(
  22927     int unit,
  22928     int direction,
  22929     int numbers,
  22930     bcm_policer_t *pid,
  22931     _bcm_policer_flow_info_t *flow_info,
  22932     uint8 *pid_offset)
  22933 {
  22934     int rv = BCM_E_NONE;
  22935     int index = 0;
  22936     int base_idx = 0;
  22937     int num_pools = 0;
  22938     int size_pool = 0;
  22939     int req_bank = 0;
  22940     int bank_size = 0;
  22941     int num_banks_per_pool = 0;
  22942     bcm_policer_t policer_id = 0;
  22943 
  22944     num_pools =  SOC_INFO(unit).global_meter_pools;
  22945     size_pool = SOC_INFO(unit).global_meter_max_size_of_pool;
  22946     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  22947     bank_size = size_pool / num_banks_per_pool;
  22948 
  22949     if (flow_info->req_alloc == TRUE) {
  22950         if (flow_info->req_pool >= num_pools) {
  22951             return BCM_E_PARAM;
  22952         }
  22953         base_idx = (flow_info->req_pool * size_pool);
  22954         base_idx += flow_info->req_base_offset;
  22955 
  22956         rv = _bcm_esw_get_policer_id_from_index_offset(unit,
  22957                 base_idx, flow_info->mode_id, &policer_id);
  22958         BCM_IF_ERROR_RETURN(rv);
  22959 
  22960         if (direction == GLOBAL_METER_ALLOC_VERTICAL) {
  22961             /* Check Boundary condition */
  22962             if ((flow_info->req_base_offset + numbers) > size_pool) {
  22963                 rv = BCM_E_RESOURCE;
  22964                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  22965                         (BSL_META_U(unit, "Number of policers in requested"
  22966                                     " group exceeds pool size with given"
  22967                                     " base offset.\n")));
  22968             } else if (flow_info->flow_type == bcmPolicerFlowTypeMicro) {
  22969                 /* Check Micro policer conditions */
  22970                 req_bank = flow_info->req_base_offset / bank_size;
  22971 
  22972                 if (soc_feature(unit,
  22973                             soc_feature_global_meter_macro_micro_same_pool)) {
  22974                     if ((flow_info->req_pool != flow_info->skip_pool) ||
  22975                             ((flow_info->req_pool == flow_info->skip_pool) &&
  22976                              (req_bank == flow_info->skip_bank))) {
  22977                         rv = BCM_E_PARAM;
  22978                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  22979                                 (BSL_META_U(unit, "Micro policer cannot be"
  22980                                             " present in same"
  22981                                             " bank as macropolicer.\n")));
  22982                     }
  22983                 } else {
  22984                     if (flow_info->req_pool == flow_info->skip_pool) {
  22985                         rv = BCM_E_PARAM;
  22986                         LOG_DEBUG(BSL_LS_BCM_POLICER,
  22987                                 (BSL_META_U(unit, "Micro policer cannot be"
  22988                                             " present in same"
  22989                                             " pool as macropolicer.\n")));
  22990                     }
  22991                 }
  22992             }
  22993         } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  22994             /* Check Boundary condition */
  22995             if (flow_info->req_base_offset >= size_pool) {
  22996                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  22997                         (BSL_META_U(unit, "Number of policers in requested"
  22998                                     " group exceeds pool size with given"
  22999                                     " base offset.\n")));
  23000                 rv = BCM_E_RESOURCE;
  23001             } else if (flow_info->req_pool != 0) {
  23002                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  23003                         (BSL_META_U(unit, "ModeType cascade and"
  23004                                     " CascadeWithCoupling should"
  23005                                     " have pool set to 0.\n")));
  23006                 rv = BCM_E_PARAM;
  23007             }
  23008             for (index = 0; index < 8; index++) {
  23009                 pid_offset[index] = index;
  23010             }
  23011         }
  23012         BCM_IF_ERROR_RETURN(rv);
  23013 
  23014         rv =  _global_meter_reserve_policer_id(unit,
  23015                 direction, numbers, policer_id, &pid_offset[0]);
  23016         if (rv == BCM_E_INTERNAL) {
  23017             rv = BCM_E_RESOURCE;
  23018         }
  23019     } else {
  23020         rv = _global_meter_policer_id_alloc(unit, direction,
  23021                 &numbers, &policer_id, flow_info, &pid_offset[0]);
  23022     }
  23023 
  23024     *pid = policer_id;
  23025 
  23026     return rv;
  23027 }
  23028 
  23029 /* Create custom policer group */
  23030 int
  23031 _bcm_esw_policer_custom_group_id_create(
  23032     int unit,
  23033     uint32 flags,
  23034     uint32 mode_id,
  23035     bcm_policer_t macro_flow_policer_id,
  23036     bcm_policer_group_info_t *policer_group_info)
  23037 {
  23038     int rv = BCM_E_NONE;
  23039     int num_banks_per_pool = 0;
  23040     int index = 0;
  23041     int size_pool = 0, num_pools = 0;
  23042     int pool_mask = 0, pool_offset = 0;
  23043     int micro_flow_index = 0;
  23044     int macro_flow_index = 0;
  23045     int npolicers = 0;
  23046     int pool_id = 0;
  23047     int bank_size = 0;
  23048     int offset_mask = 0;
  23049     int skip_pool = 0, skip_bank = 0;
  23050     int req_alloc = FALSE;
  23051     int req_pool = 0, req_base_offset = 0;
  23052     int entry_mem_size = 0;
  23053     int entry_index = 0;
  23054     int entry_index_max = 0;
  23055     uint32 direction = 0;
  23056     bcm_policer_t policer_id = 0;
  23057     bcm_policer_group_mode_t mode = 0;
  23058     bcm_policer_svc_meter_bookkeep_mode_t *mode_info = NULL;
  23059     _global_meter_policer_control_t *policer_control = NULL;
  23060     uint8 pid_offset[BCM_POLICER_GLOBAL_METER_MAX_POOL] = {0};
  23061     _bcm_policer_flow_type_t flow_type = bcmPolicerFlowTypeNormal;
  23062     _bcm_policer_flow_info_t flow_info;
  23063     svm_macroflow_index_table_entry_t *buf = NULL;
  23064     svm_macroflow_index_table_entry_t *entry = NULL;
  23065 
  23066     if (!soc_feature(unit, soc_feature_global_meter)) {
  23067         return BCM_E_UNAVAIL;
  23068     }
  23069 
  23070     if ((mode_id == 0) ||
  23071             (mode_id > BCM_POLICER_SVC_METER_MAX_MODE) ||
  23072             (policer_group_info == NULL)) {
  23073         return (BCM_E_PARAM);
  23074     }
  23075 
  23076     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  23077     num_pools =  SOC_INFO(unit).global_meter_pools;
  23078     offset_mask = size_pool - 1;
  23079     pool_offset = _shr_popcount(offset_mask);
  23080     pool_mask = (num_pools - 1) << pool_offset;
  23081 
  23082     (void) _bcm_policer_flow_info_t_init(&flow_info);
  23083     num_banks_per_pool = get_max_banks_in_a_pool(unit);
  23084     bank_size = size_pool / num_banks_per_pool;
  23085 
  23086     if (soc_feature(unit,
  23087                 soc_feature_global_meter_compaction_support)) {
  23088         if ((policer_group_info->pool_id == 0) &&
  23089                 (policer_group_info->base_offset == 0)) {
  23090             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23091                     (BSL_META_U(unit,
  23092                                 "pool id 0 and base offset 0 "
  23093                                 " is reserved and cannot be used\n")));
  23094             return BCM_E_PARAM;
  23095         }
  23096         req_alloc = TRUE;
  23097         req_pool = policer_group_info->pool_id;
  23098         req_base_offset = policer_group_info->base_offset;
  23099     } else {
  23100         req_alloc = FALSE;
  23101         req_pool = num_pools;
  23102         req_base_offset = size_pool;
  23103     }
  23104 
  23105     _GLOBAL_METER_XGS3_ALLOC(mode_info,
  23106          sizeof (bcm_policer_svc_meter_bookkeep_mode_t), "mode bookkeep info");
  23107     if (mode_info == NULL) {
  23108         LOG_DEBUG(BSL_LS_BCM_POLICER,
  23109                 (BSL_META_U(unit, "Failure to allocate memory.\n")));
  23110         return (BCM_E_MEMORY);
  23111     }
  23112 
  23113     mode_id -= 1;
  23114     if (mode_id == 0) {
  23115         npolicers = 1;
  23116     } else {
  23117         rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id, mode_info);
  23118         if (rv != BCM_E_NONE) {
  23119             sal_free(mode_info);
  23120             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23121                     (BSL_META_U(unit, "Mode Id get failed.\n")));
  23122             return rv;
  23123         }
  23124         /* Allow only when Group mode Id is created explicitly */
  23125         if (mode_info->type == -1) {
  23126             sal_free(mode_info);
  23127             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23128                     (BSL_META_U(unit, "Mode Id is not created.\n")));
  23129             return BCM_E_PARAM;
  23130         }
  23131         npolicers = mode_info->no_of_policers;
  23132     }
  23133 
  23134     direction = GLOBAL_METER_ALLOC_VERTICAL;
  23135     mode = bcmPolicerGroupModeSingle;
  23136     if (npolicers !=  1) {
  23137         if (mode_info->group_mode == bcmPolicerGroupModeCascade) {
  23138             direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  23139             mode = bcmPolicerGroupModeCascade;
  23140         } else if (mode_info->group_mode ==
  23141                 bcmPolicerGroupModeCascadeWithCoupling) {
  23142             direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  23143             mode = bcmPolicerGroupModeCascadeWithCoupling;
  23144         }
  23145     }
  23146 
  23147     /* Free mode_info */
  23148     if (mode_info != NULL) {
  23149         sal_free(mode_info);
  23150     }
  23151 
  23152     if (macro_flow_policer_id > 0) {
  23153         skip_pool = (macro_flow_policer_id & pool_mask) >> pool_offset;
  23154         skip_bank = (macro_flow_policer_id & offset_mask) / bank_size;
  23155         flow_type = bcmPolicerFlowTypeMicro;
  23156     } else {
  23157         skip_pool = num_pools;
  23158         skip_bank = num_banks_per_pool;
  23159         flow_type = bcmPolicerFlowTypeNormal;
  23160     }
  23161     /* Validate flowtype */
  23162     if (flow_type == bcmPolicerFlowTypeMicro) {
  23163         /* Validate Mode */
  23164         if ((mode == bcmPolicerGroupModeCascade) ||
  23165                 (mode == bcmPolicerGroupModeCascadeWithCoupling)) {
  23166             LOG_ERROR(BSL_LS_BCM_POLICER,
  23167                     (BSL_META_U(unit,
  23168                                 "Unable to create micro flow policers "
  23169                                 "due to unsupported mode\n")));
  23170             return (BCM_E_PARAM);
  23171         }
  23172 
  23173         /* Validate Macro policer */
  23174         rv = _bcm_esw_policer_validate(unit, &macro_flow_policer_id);
  23175         if (!(BCM_SUCCESS(rv))) {
  23176             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23177                     (BSL_META_U(unit,
  23178                                 "Invalid Macro policer Id passed\n")));
  23179             return rv;
  23180         }
  23181         rv = _bcm_global_meter_macro_policer_validate(unit,
  23182                                             macro_flow_policer_id);
  23183         if (!(BCM_SUCCESS(rv))) {
  23184             LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23185                               "Macro flow policer Id = %d is not found or"
  23186                               " not configured properly to be used as macro"
  23187                               " policer\n"), macro_flow_policer_id));
  23188             return rv;
  23189         }
  23190         rv = _bcm_esw_get_policer_table_index(unit,
  23191                 macro_flow_policer_id, &macro_flow_index);
  23192         if (!(BCM_SUCCESS(rv))) {
  23193             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23194                     (BSL_META_U(unit,
  23195                                 "Unable to Get policer index for macro flow "
  23196                                 "policer \n")));
  23197             return rv;
  23198         }
  23199     }
  23200 
  23201     /* Populate flow info */
  23202     flow_info.mode_id = mode_id;
  23203     flow_info.flow_type = flow_type;
  23204     flow_info.req_alloc = req_alloc;
  23205     flow_info.skip_pool = skip_pool;
  23206     flow_info.skip_bank = skip_bank;
  23207     flow_info.req_pool  = req_pool;
  23208     flow_info.req_base_offset = req_base_offset;
  23209 
  23210     GLOBAL_METER_LOCK(unit);
  23211     rv = _global_meter_policer_group_alloc(unit,
  23212                 direction, npolicers, &policer_id,
  23213                 &flow_info, &pid_offset[0]);
  23214     if (!(BCM_SUCCESS(rv))) {
  23215         GLOBAL_METER_UNLOCK(unit);
  23216         LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23217                         "Failed to allocate policer   \n")));
  23218         return rv;
  23219     }
  23220     offset_mask = SOC_INFO(unit).global_meter_max_size_of_pool - 1;
  23221 
  23222     /* Allocate policer descriptor. */
  23223     _GLOBAL_METER_XGS3_ALLOC(policer_control,
  23224             sizeof (_global_meter_policer_control_t), "Global meter policer");
  23225 
  23226     if (NULL == policer_control) {
  23227         _bcm_global_meter_free_allocated_policer_on_error(unit, npolicers,
  23228                 &pid_offset[0], (policer_id & offset_mask));
  23229         GLOBAL_METER_UNLOCK(unit);
  23230         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23231                         "Unable to allocate memeory for policer control   \n")));
  23232         return (BCM_E_MEMORY);
  23233     }
  23234 
  23235     /* Add mode info to the policer index */
  23236     policer_id |= (mode_id + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT;
  23237 
  23238     /* Set policer configuration */
  23239     policer_control->direction = direction;
  23240     policer_control->pid = policer_id;
  23241     policer_control->no_of_policers =  npolicers;
  23242     policer_control->grp_mode = mode;
  23243 
  23244     if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  23245         index = 0;
  23246         do {
  23247             policer_control->offset[index] = pid_offset[index];
  23248             index++;
  23249         } while (index < (npolicers));
  23250 
  23251         if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) {
  23252             rv = _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw(unit,
  23253                     npolicers, policer_id, mode, &pid_offset[0]);
  23254         } else {
  23255             rv = _bcm_esw_global_meter_set_cascade_info_to_hw(unit,
  23256                     npolicers, policer_id, mode, &pid_offset[0]);
  23257         }
  23258 
  23259         if (!(BCM_SUCCESS(rv))) {
  23260             /* free all the allocated policers */
  23261             _bcm_global_meter_free_allocated_policer_on_error(unit, npolicers,
  23262                     &pid_offset[0], (policer_id & offset_mask));
  23263             /* De-allocate policer descriptor. */
  23264             sal_free(policer_control);
  23265             GLOBAL_METER_UNLOCK(unit);
  23266             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23267                     (BSL_META_U(unit, "Failed to create cascade chain"
  23268                                 " in meter table.\n")));
  23269             return rv;
  23270         }
  23271     }
  23272 
  23273     /* increment mode reference count for new policer  */
  23274     if (mode_id) {
  23275         rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, mode_id);
  23276         if (!(BCM_SUCCESS(rv))) {
  23277             /* free all the allocated policers */
  23278             _bcm_global_meter_free_allocated_policer_on_error(unit,npolicers,
  23279                     &pid_offset[0], (policer_id & offset_mask));
  23280             /* De-allocate policer descriptor. */
  23281             sal_free(policer_control);
  23282             GLOBAL_METER_UNLOCK(unit);
  23283             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23284                     (BSL_META_U(unit, "Failed to update reference"
  23285                                 " for group mode id.\n")));
  23286             return rv;
  23287         }
  23288     }
  23289     if (mode == bcmPolicerGroupModeCascadeWithCoupling) {
  23290         npolicers = npolicers / 2;
  23291     }
  23292 
  23293    /* Insert policer into policers hash. */
  23294     _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit],
  23295                    policer_control, (policer_id & _GLOBAL_METER_HASH_MASK));
  23296 
  23297     /* Configure SVM_MACROFLOW_INDEX table */
  23298     if (flow_type == bcmPolicerFlowTypeMicro) {
  23299         /* get the HW index for the micro flow policer created */
  23300         rv = _bcm_esw_get_policer_table_index(unit, policer_id,
  23301                                                     &micro_flow_index);
  23302         if (BCM_FAILURE(rv)) {
  23303             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23304                       (BSL_META_U(unit,
  23305                                   "Unable to Get policer index for micro flow "
  23306                                   "policer \n")));
  23307             goto cleanup;
  23308         }
  23309         entry_mem_size = sizeof(svm_macroflow_index_table_entry_t);
  23310         entry_index_max = micro_flow_index + npolicers - 1;
  23311         /* Allocate buffer to store the DMAed table entries. */
  23312         buf = soc_cm_salloc(unit, entry_mem_size * npolicers,
  23313                               "svm macro flow index table entry buffer");
  23314         if (NULL == buf) {
  23315             rv = BCM_E_MEMORY;
  23316             LOG_DEBUG(BSL_LS_BCM_POLICER,
  23317                     (BSL_META_U(unit, "Failed to allocate memory"
  23318                                 " for macroflow index table.\n")));
  23319             goto cleanup;
  23320         }
  23321         /* Initialize the entry buffer. */
  23322         sal_memset(buf, 0, sizeof(entry_mem_size) * npolicers);
  23323 
  23324         /* Read the table entries into the buffer. */
  23325         rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  23326                                 MEM_BLOCK_ALL, micro_flow_index,
  23327                                 entry_index_max, buf);
  23328         if (BCM_FAILURE(rv)) {
  23329             goto cleanup;
  23330         }
  23331 
  23332         /* Iterate over the table entries. */
  23333         for (entry_index = 0; entry_index < npolicers; entry_index++) {
  23334             entry = soc_mem_table_idx_to_pointer(unit,
  23335                                   SVM_MACROFLOW_INDEX_TABLEm,
  23336                                   svm_macroflow_index_table_entry_t *,
  23337                                   buf, entry_index);
  23338             soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm,
  23339                            (void *)entry, MACROFLOW_INDEXf,
  23340                            (uint32 *)&macro_flow_index);
  23341             rv = _bcm_esw_policer_increment_ref_count(unit,
  23342                                                       macro_flow_policer_id);
  23343             if (BCM_FAILURE(rv)) {
  23344                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  23345                           (BSL_META_U(unit,
  23346                                       "Unable to increment ref count for micro flow "
  23347                                       "policer\n")));
  23348                 goto cleanup;
  23349             }
  23350         }
  23351         if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm,
  23352                                       MEM_BLOCK_ALL, micro_flow_index,
  23353                                       entry_index_max, buf)) < 0) {
  23354             if (BCM_FAILURE(rv)) {
  23355                 LOG_VERBOSE(BSL_LS_BCM_POLICER,
  23356                             (BSL_META_U(unit,
  23357                                         "Unable to write to macro flow table at index "
  23358                                         "provided\n")));
  23359                 goto cleanup;
  23360             }
  23361         }
  23362     }
  23363 
  23364 cleanup:
  23365 
  23366     GLOBAL_METER_UNLOCK(unit);
  23367 
  23368     if (buf) {
  23369         soc_cm_sfree(unit, buf);
  23370     }
  23371 
  23372     if (rv != BCM_E_NONE) {
  23373         (void) _bcm_esw_global_meter_policer_destroy(unit, policer_id);
  23374         LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23375                         "create failed with error=%d\n"), rv));
  23376     } else {
  23377         /* Fill up policer group info */
  23378         (void) _bcm_esw_get_policer_table_index(unit, policer_id, &index);
  23379         pool_id = (policer_id & pool_mask) >> pool_offset;
  23380 
  23381         policer_group_info->policer_id = policer_id;
  23382         policer_group_info->mode_id = (mode_id + 1);
  23383         policer_group_info->mode = mode;
  23384         policer_group_info->base_offset = index - (size_pool * pool_id);
  23385 
  23386         if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) {
  23387             policer_group_info->direction =
  23388                 bcmPolicerGroupDirectionHorizontal;
  23389             policer_group_info->pool_id = 0;
  23390             policer_group_info->num_policers = npolicers;
  23391             policer_group_info->num_offset_reserved = 8;
  23392             policer_group_info->macro_policer_id = 0;
  23393         } else {
  23394             policer_group_info->pool_id = (uint32) pool_id;
  23395             policer_group_info->direction =
  23396                 bcmPolicerGroupDirectionVertical;
  23397             policer_group_info->num_policers = npolicers;
  23398             policer_group_info->num_offset_reserved = npolicers;
  23399             policer_group_info->macro_policer_id = macro_flow_policer_id;
  23400         }
  23401 
  23402         LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23403                         "create policer with id %x \n"), policer_id));
  23404     }
  23405     return rv;
  23406 }
  23407 
  23408 /*
  23409  * Function:
  23410  *      bcm_esw_policer_custom_group_create
  23411  * Purpose:
  23412  *      Create a group of policers based on the mode.
  23413  * Parameters:
  23414  *     unit                  - (IN) unit number
  23415  *     flags                 - (IN) flags
  23416  *     mode_id               - (IN) Created Mode Id for Policer Group Mode
  23417  *     macro_flow_policer_id - (IN) Is an optional parameter and needs to be
  23418  *                                  passed only while creating the micro flow
  23419  *                                  policers of a hierarchical groupi
  23420  *                                  (2 stage policers).
  23421  *     policer_id            - (OUT)Base policer Id
  23422  *     npolicers             - (OUT) Number of policers created
  23423  * Returns:
  23424  *     BCM_E_XXX
  23425  */
  23426 int
  23427 bcm_esw_policer_custom_group_create(
  23428     int unit,
  23429     uint32 flags,
  23430     uint32 mode_id,
  23431     bcm_policer_t macro_flow_policer_id,
  23432     bcm_policer_t *policer_id,
  23433     uint32 *npolicers)
  23434 {
  23435     bcm_policer_group_info_t policer_group_info;
  23436 
  23437 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  23438     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  23439         return bcmi_esw_policer_custom_group_create(unit,
  23440                 flags, mode_id, macro_flow_policer_id, policer_id, npolicers);
  23441     }
  23442 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  23443 
  23444     if (soc_feature(unit, soc_feature_global_meter_compaction_support)) {
  23445         return BCM_E_UNAVAIL;
  23446     }
  23447 
  23448     bcm_policer_group_info_t_init(&policer_group_info);
  23449 
  23450     BCM_IF_ERROR_RETURN(_bcm_esw_policer_custom_group_id_create(unit,
  23451                 flags, mode_id, macro_flow_policer_id, &policer_group_info));
  23452 
  23453     *policer_id = policer_group_info.policer_id;
  23454     *npolicers = policer_group_info.num_policers;
  23455 
  23456     return BCM_E_NONE;
  23457 }
  23458 
  23459 /*
  23460  * Function:
  23461  *     bcm_esw_policer_group_get
  23462  * Purpose:
  23463  *     Get the list of policer members for a given policer group represented
  23464  *     by its base policer id
  23465  * Parameters:
  23466  *     unit                  - (IN) unit number
  23467  *     policer_id            - (IN) Base policer Id
  23468  *     member_max            - (IN) Maximum number of policers to return in
  23469  *                              the member_array parameter
  23470  *     member_array          - (OUT) Place to store policer members of the
  23471  *                              given policer group represented by its base_policer_id.
  23472  *                              Memory need to be allocated by the end user before
  23473  *                              calling the API
  23474  *     member_count          - (OUT) Place to store total number of policers
  23475  *                              configured in the given policer group represented
  23476  *                              by base_policer_id
  23477 
  23478  * Returns:
  23479  *     BCM_E_XXX
  23480  */
  23481 int bcm_esw_policer_group_get (
  23482     int unit,
  23483     bcm_policer_t base_policer_id,
  23484     int member_max,
  23485     bcm_policer_t *member_array,
  23486     int *member_count)
  23487 {
  23488     int rv = BCM_E_NONE;
  23489     int index, policer_offset, indices_to_fill;
  23490     _global_meter_policer_control_t *policer_control = NULL;
  23491 
  23492 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  23493     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  23494         return bcmi_esw_policer_group_get(unit,
  23495             base_policer_id, member_max, member_array, member_count);
  23496     }
  23497 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  23498 
  23499     if (!soc_feature(unit, soc_feature_global_meter)) {
  23500         return BCM_E_UNAVAIL;
  23501     }
  23502     CHECK_GLOBAL_METER_INIT(unit);
  23503 
  23504     /* verify arguments */
  23505     if ((base_policer_id == 0) || (member_count == NULL)) {
  23506         return BCM_E_PARAM;
  23507     }
  23508     if ((member_max > 0) && (member_array == NULL)) {
  23509         return BCM_E_PARAM;
  23510     }
  23511 
  23512     rv = _bcm_esw_policer_validate(unit, &base_policer_id);
  23513     BCM_IF_ERROR_RETURN(rv);
  23514 
  23515     GLOBAL_METER_LOCK(unit);
  23516     rv = _bcm_global_meter_base_policer_get(unit, base_policer_id, &policer_control);
  23517     if (BCM_FAILURE(rv)) {
  23518         GLOBAL_METER_UNLOCK(unit);
  23519         LOG_DEBUG(BSL_LS_BCM_POLICER,
  23520                   (BSL_META_U(unit,
  23521                               "Unable to get policer control for the policer Id "
  23522                               "passed  \n")));
  23523         return (rv);
  23524     }
  23525 
  23526     if ((policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  23527         (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  23528         *member_count = policer_control->no_of_policers/2;
  23529     } else {
  23530         *member_count = policer_control->no_of_policers;
  23531     }
  23532 
  23533     if (member_max <= 0) {
  23534         GLOBAL_METER_UNLOCK(unit);
  23535         return rv;
  23536     }
  23537 
  23538     indices_to_fill = (member_max < *member_count) ? member_max : *member_count;
  23539 
  23540     switch(policer_control->grp_mode) {
  23541         case bcmPolicerGroupModeCascade:
  23542         case bcmPolicerGroupModeCascadeWithCoupling:
  23543         case bcmPolicerGroupModeCascadeDroppedPktExclude:
  23544         case bcmPolicerGroupModeIntPriCascade:
  23545         case bcmPolicerGroupModeIntPriCascadeWithCoupling:
  23546         {
  23547             for (index = 0; index < indices_to_fill; index++) {
  23548                 /* policer_control->offset[] stores offset/pool from 0 to 7 */
  23549                 if (soc_feature(unit,
  23550                         soc_feature_global_meter_pool_priority_descending)) {
  23551                     policer_offset = *member_count - index - 1;
  23552                 } else {
  23553                     policer_offset = index;
  23554                 }
  23555 
  23556                 member_array[index] = base_policer_id +
  23557                             (policer_control->offset[policer_offset] *
  23558                             SOC_INFO(unit).global_meter_max_size_of_pool);
  23559             }
  23560             break;
  23561         }
  23562         default:
  23563         {
  23564             /* For every other modes, member policers are in same pool */
  23565             for (index = 0; index < indices_to_fill; index++) {
  23566                 member_array[index] = base_policer_id + index;
  23567             }
  23568             break;
  23569         }
  23570     }
  23571     GLOBAL_METER_UNLOCK(unit);
  23572 
  23573     return BCM_E_NONE;
  23574 }
  23575 
  23576 STATIC int
  23577 _bcm_global_meter_copy_horizontally(
  23578     int unit,
  23579     bcm_policer_group_info_t *old_policer_group_info,
  23580     bcm_policer_group_info_t *new_policer_group_info)
  23581 {
  23582     int rv = BCM_E_NONE;
  23583     int noffsets = 0;
  23584     int index = 0;
  23585     int entry_index = 0;
  23586     int size_pool = 0;
  23587     uint32 action_id = 0;
  23588     uint32 old_base_idx = 0, old_pool_id = 0;
  23589     uint32 new_base_idx = 0, new_pool_id = 0;
  23590     soc_mem_t mem = SVM_METER_TABLEm;
  23591     svm_meter_table_entry_t entry_buf;
  23592 
  23593     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  23594     noffsets = old_policer_group_info->num_offset_reserved;
  23595 
  23596     old_base_idx = old_policer_group_info->pool_id * size_pool +
  23597         old_policer_group_info->base_offset;
  23598     old_pool_id = 0;
  23599 
  23600     new_base_idx = old_policer_group_info->pool_id * size_pool +
  23601         new_policer_group_info->base_offset;
  23602     new_pool_id = 0;
  23603 
  23604     mem = SVM_METER_TABLEm;
  23605     for (index = 0; index < noffsets; index++) {
  23606         entry_index = old_base_idx + (index + old_pool_id) * size_pool;
  23607 
  23608         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, entry_index, &entry_buf);
  23609         BCM_IF_ERROR_RETURN(rv);
  23610 
  23611         action_id = soc_mem_field32_get(unit,
  23612                 mem, &entry_buf, POLICY_TABLE_INDEXf);
  23613 
  23614         if (global_meter_action_bookkeep[unit][action_id].used == 1) {
  23615             global_meter_action_bookkeep[unit][action_id].reference_count++;
  23616         }
  23617 
  23618         entry_index = new_base_idx + (index + new_pool_id) * size_pool;
  23619         rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, entry_index, &entry_buf);
  23620         BCM_IF_ERROR_RETURN(rv);
  23621     }
  23622 
  23623     return rv;
  23624 }
  23625 
  23626 STATIC int
  23627 _bcm_global_meter_copy_vertically(
  23628     int unit,
  23629     bcm_policer_group_info_t *old_policer_group_info,
  23630     bcm_policer_group_info_t *new_policer_group_info)
  23631 {
  23632     int rv = BCM_E_NONE;
  23633     int noffsets = 0;
  23634     int entry_index = 0;
  23635     int size_pool = 0;
  23636     int write_required = FALSE;
  23637     int macroflow_index = 0;
  23638     uint32 action_id = 0;
  23639     uint32 old_base_idx = 0;
  23640     uint32 new_base_idx = 0;
  23641     soc_mem_t mem = INVALIDm;
  23642     bcm_policer_t macroflow_policer = 0;
  23643     bcm_policer_t old_macroflow_policer = 0;
  23644     svm_meter_table_entry_t *buffer = NULL;
  23645     svm_meter_table_entry_t *entry_buf = NULL;
  23646     svm_macroflow_index_table_entry_t *macroflow_buffer = NULL;
  23647     svm_macroflow_index_table_entry_t *macroflow_entry_buf = NULL;
  23648 
  23649     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  23650     noffsets = old_policer_group_info->num_offset_reserved;
  23651     old_macroflow_policer = old_policer_group_info->macro_policer_id;
  23652 
  23653     old_base_idx = old_policer_group_info->pool_id * size_pool +
  23654         old_policer_group_info->base_offset;
  23655     new_base_idx = new_policer_group_info->pool_id * size_pool +
  23656         new_policer_group_info->base_offset;
  23657 
  23658     /* Update SVM_MACROFLOW_INDEX table */
  23659     macroflow_buffer = soc_cm_salloc(unit,
  23660             sizeof(svm_macroflow_index_table_entry_t) * noffsets,
  23661             "svm macroflow mem buffer");
  23662     if (NULL == macroflow_buffer) {
  23663         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23664                       "Failed to allocate memory for Macroflow buffer\n")));
  23665         return (BCM_E_MEMORY);
  23666     }
  23667 
  23668     /* Initialize the entry buffer. */
  23669     sal_memset(macroflow_buffer, 0,
  23670         sizeof(svm_macroflow_index_table_entry_t) * noffsets);
  23671 
  23672     mem = SVM_MACROFLOW_INDEX_TABLEm;
  23673 
  23674     /* Read the table entries into the buffer. */
  23675     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
  23676             old_base_idx, old_base_idx + noffsets - 1,
  23677             macroflow_buffer);
  23678     if (BCM_FAILURE(rv)) {
  23679         if (macroflow_buffer != NULL) {
  23680             soc_cm_sfree(unit, macroflow_buffer);
  23681         }
  23682         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23683                       "Failed to read Macroflow Index table\n")));
  23684         return rv;
  23685     }
  23686 
  23687     /* Loop through each Macroflow Index */
  23688     for (entry_index = 0; entry_index < noffsets; entry_index++) {
  23689         macroflow_entry_buf = soc_mem_table_idx_to_pointer(unit,
  23690                 mem, svm_macroflow_index_table_entry_t *,
  23691                 macroflow_buffer, entry_index);
  23692 
  23693         macroflow_index = soc_mem_field32_get(unit, mem,
  23694                 macroflow_entry_buf, MACROFLOW_INDEXf);
  23695         if (macroflow_index > 0) {
  23696             (void) _bcm_esw_get_policer_id_from_index_offset(unit,
  23697                     macroflow_index, 0, &macroflow_policer);
  23698             if (macroflow_policer != old_macroflow_policer) {
  23699                 soc_mem_field32_set(unit, mem, macroflow_entry_buf,
  23700                         MACROFLOW_INDEXf, (uint32) macroflow_index);
  23701                 write_required = TRUE;
  23702                 /* Decrement count for old macro policer */
  23703                 rv = _bcm_esw_policer_decrement_ref_count(unit,
  23704                         old_macroflow_policer);
  23705                 /* Increment count for new macor policer */
  23706                 if (BCM_SUCCESS(rv)) {
  23707                     rv = _bcm_esw_policer_increment_ref_count(unit,
  23708                             macroflow_policer);
  23709                 }
  23710                 if (BCM_FAILURE(rv)) {
  23711                     LOG_DEBUG(BSL_LS_BCM_COMMON,
  23712                             (BSL_META_U(unit,
  23713                                         "%u : Unable to increment ref count"),
  23714                              macroflow_index));
  23715                     goto cleanup;
  23716                 }
  23717             }
  23718         }
  23719     }
  23720 
  23721     /* Write back at new location */
  23722     if (write_required == TRUE) {
  23723         rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  23724                 new_base_idx, new_base_idx + noffsets - 1, macroflow_buffer);
  23725     }
  23726 
  23727     if (macroflow_buffer != NULL) {
  23728         soc_cm_sfree(unit, macroflow_buffer);
  23729         macroflow_buffer = NULL;
  23730     }
  23731     BCM_IF_ERROR_RETURN(rv);
  23732 
  23733     buffer = soc_cm_salloc(unit,
  23734             sizeof(svm_meter_table_entry_t) * noffsets, "svm mem buffer");
  23735     if (NULL == buffer) {
  23736         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23737                       "Failed to allocate memory for SVM buffer\n")));
  23738         return (BCM_E_MEMORY);
  23739     }
  23740 
  23741     mem = SVM_METER_TABLEm;
  23742 
  23743     /* Initialize the entry buffer. */
  23744     sal_memset(buffer, 0, sizeof(svm_meter_table_entry_t) * noffsets);
  23745 
  23746     /* Read the table entries into the buffer. */
  23747     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
  23748             old_base_idx, old_base_idx + noffsets - 1, buffer);
  23749     if (BCM_FAILURE(rv)) {
  23750         if (buffer) {
  23751             soc_cm_sfree(unit, buffer);
  23752         }
  23753         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23754                       "Failed to read meter table\n")));
  23755         return rv;
  23756     }
  23757 
  23758     for (entry_index = 0; entry_index < noffsets; entry_index++) {
  23759         entry_buf = soc_mem_table_idx_to_pointer(unit, mem,
  23760                 svm_meter_table_entry_t *, buffer, entry_index);
  23761 
  23762         action_id = soc_mem_field32_get(unit,
  23763                 mem, entry_buf, POLICY_TABLE_INDEXf);
  23764 
  23765         if (global_meter_action_bookkeep[unit][action_id].used == 1) {
  23766             global_meter_action_bookkeep[unit][action_id].reference_count++;
  23767         }
  23768     }
  23769 
  23770     rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  23771             new_base_idx, new_base_idx + noffsets - 1, buffer);
  23772 
  23773 cleanup:
  23774 
  23775     if (macroflow_buffer != NULL) {
  23776         soc_cm_sfree(unit, macroflow_buffer);
  23777         macroflow_buffer = NULL;
  23778     }
  23779     if (buffer != NULL) {
  23780         soc_cm_sfree(unit, buffer);
  23781         buffer = NULL;
  23782     }
  23783 
  23784     return rv;
  23785 }
  23786 
  23787 /*
  23788  * Function:
  23789  *      bcm_esw_policer_custom_group_id_create
  23790  * Purpose:
  23791  *      Create a group of policers using mode id.
  23792  * Parameters:
  23793  *     unit                  - (IN) unit number
  23794  *     flags                 - (IN) flags
  23795  *     mode_id               - (IN) Created Mode Id for Policer Group Mode
  23796  *     macro_flow_policer_id - (IN) Is an optional parameter and needs to be
  23797  *                                  passed only while creating the micro flow
  23798  *                                  policers of a hierarchical groupi
  23799  *                                  (2 stage policers).
  23800  *     policer_group_info    - (INOUT) Policer group info.
  23801  * Returns:
  23802  *     BCM_E_XXX
  23803  */
  23804 int
  23805 bcm_esw_policer_custom_group_id_create(
  23806     int unit,
  23807     uint32 flags,
  23808     uint32 mode_id,
  23809     bcm_policer_t macro_flow_policer_id,
  23810     bcm_policer_group_info_t *policer_group_info)
  23811 {
  23812     int rv = BCM_E_UNAVAIL;
  23813 
  23814     if (soc_feature(unit, soc_feature_global_meter_compaction_support)) {
  23815         rv = _bcm_esw_policer_custom_group_id_create(unit,
  23816                 flags, mode_id, macro_flow_policer_id, policer_group_info);
  23817     }
  23818 
  23819     return rv;
  23820 }
  23821 
  23822 /*
  23823  * Function:
  23824  *      bcm_esw_policer_custom_group_id_copy
  23825  * Purpose:
  23826  *      Copy all policer offsets in the old policer group
  23827  *      to new hardware indices.
  23828  * Parameters:
  23829  *     unit                   - (IN) unit number.
  23830  *     old_policer_group_info - (IN) Policer group info for old location.
  23831  *     new_policer_group_info - (INOUT) Policer group info for new location.
  23832  * Returns:
  23833  *     BCM_E_XXX
  23834  */
  23835 int
  23836 bcm_esw_policer_custom_group_id_copy(
  23837     int unit,
  23838     bcm_policer_group_info_t *old_policer_group_info,
  23839     bcm_policer_group_info_t *new_policer_group_info)
  23840 {
  23841     int rv = BCM_E_NONE;
  23842     bcm_policer_t policer_id = 0;
  23843     int size_pool = 0, base_idx = 0;
  23844     _global_meter_policer_control_t *policer_control = NULL;
  23845 
  23846     if ((old_policer_group_info == NULL) ||
  23847             (new_policer_group_info == NULL)) {
  23848         return BCM_E_PARAM;
  23849     }
  23850 
  23851     if (!soc_feature(unit,
  23852                 soc_feature_global_meter_compaction_support)) {
  23853         return BCM_E_UNAVAIL;
  23854     }
  23855 
  23856     if(new_policer_group_info->mode_id !=
  23857             old_policer_group_info->mode_id) {
  23858         return BCM_E_CONFIG;
  23859     }
  23860     if (sal_memcmp(old_policer_group_info,
  23861                 new_policer_group_info,
  23862                 sizeof(bcm_policer_group_info_t)) == 0) {
  23863         return BCM_E_NONE;
  23864     }
  23865 
  23866     size_pool = SOC_INFO(unit).global_meter_max_size_of_pool;
  23867     base_idx = (old_policer_group_info->pool_id * size_pool);
  23868     base_idx += old_policer_group_info->base_offset;
  23869     _bcm_esw_get_policer_id_from_index_offset(unit,
  23870             base_idx,
  23871             old_policer_group_info->mode_id-1,&policer_id);
  23872 
  23873     if (_bcm_global_meter_base_policer_get(unit, policer_id,
  23874                 &policer_control) == BCM_E_NOT_FOUND) {
  23875         return BCM_E_PARAM;
  23876     }
  23877 
  23878     if ((policer_control != NULL) &&
  23879             (old_policer_group_info->policer_id !=
  23880              policer_control->pid)) {
  23881         return BCM_E_PARAM;
  23882     }
  23883 
  23884     /* Create custom group */
  23885     rv = _bcm_esw_policer_custom_group_id_create(unit,
  23886             0, old_policer_group_info->mode_id,
  23887             old_policer_group_info->macro_policer_id,
  23888             new_policer_group_info);
  23889     BCM_IF_ERROR_RETURN(rv);
  23890 
  23891     /* Copy policer config from  old to new location */
  23892     if (old_policer_group_info->direction ==
  23893             bcmPolicerGroupDirectionHorizontal) {
  23894         rv = _bcm_global_meter_copy_horizontally(unit,
  23895                 old_policer_group_info, new_policer_group_info);
  23896     } else if (old_policer_group_info->direction ==
  23897             bcmPolicerGroupDirectionVertical) {
  23898         rv = _bcm_global_meter_copy_vertically(unit,
  23899                 old_policer_group_info, new_policer_group_info);
  23900     }
  23901 
  23902     if (BCM_FAILURE(rv)) {
  23903         LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit,
  23904                       "Failed to copy policer to new offsets\n")));
  23905         (void) _bcm_esw_global_meter_policer_destroy(unit,
  23906                 new_policer_group_info->policer_id);
  23907     }
  23908     return rv;
  23909 }
  23910 
  23911 /*
  23912  * Function:
  23913  *      bcm_esw_policer_action_attach_get
  23914  * Purpose:
  23915  *     Get the action id associated with a given policer.
  23916  * Parameters:
  23917  *     unit                  - (IN) unit number
  23918  *     policer_id            - (IN) Base policer Id
  23919  *     action_id             - (OUT) action id
  23920  * Returns:
  23921  *     BCM_E_XXX
  23922  */
  23923 int bcm_esw_policer_action_attach_get(int unit, bcm_policer_t policer_id,
  23924                                 uint32 *action_id)
  23925 {
  23926     int rv = BCM_E_NONE;
  23927     svm_meter_table_entry_t meter_entry;
  23928     _global_meter_policer_control_t *policer_control = NULL;
  23929     int policer_index = 0;
  23930 
  23931 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  23932     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  23933         return bcmi_esw_policer_action_attach_get(unit, policer_id, action_id);
  23934     }
  23935 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  23936 
  23937     if (!soc_feature(unit, soc_feature_global_meter)) {
  23938         return BCM_E_UNAVAIL;
  23939     }
  23940     CHECK_GLOBAL_METER_INIT(unit);
  23941     /* validate policer id */
  23942     rv = _bcm_esw_policer_validate(unit, &policer_id);
  23943     if (BCM_FAILURE(rv)) {
  23944         return (rv);
  23945     }
  23946     GLOBAL_METER_LOCK(unit);
  23947     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  23948     if (BCM_FAILURE(rv)) {
  23949         GLOBAL_METER_UNLOCK(unit);
  23950         LOG_DEBUG(BSL_LS_BCM_POLICER,
  23951                   (BSL_META_U(unit,
  23952                               "Unable to get policer control for the policer Id "
  23953                               "passed  \n")));
  23954         return (rv);
  23955     }
  23956     /*  read meter table action_id*/
  23957     _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index);
  23958     rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index,
  23959                                                             &meter_entry);
  23960     if (BCM_FAILURE(rv)) {
  23961         GLOBAL_METER_UNLOCK(unit);
  23962         LOG_DEBUG(BSL_LS_BCM_POLICER,
  23963                   (BSL_META_U(unit,
  23964                               "Unable to read SVM_METER_TABLE entry \n")));
  23965         return (rv);
  23966     }
  23967     /* get action id */
  23968     soc_SVM_METER_TABLEm_field_get(unit, &meter_entry, POLICY_TABLE_INDEXf,
  23969                                                                  action_id);
  23970     GLOBAL_METER_UNLOCK(unit);
  23971     return rv;
  23972 }
  23973 
  23974 /*
  23975  * Function:
  23976  *      bcm_esw_policer_action_detach
  23977  * Purpose:
  23978  *     Disassociate a policer action from a given policer id and
  23979  *     readjust reference count.
  23980  * Parameters:
  23981  *     unit                  - (IN) unit number
  23982  *     policer_id            - (IN) Base policer Id
  23983  *     action_id             - (IN) action id
  23984  * Returns:
  23985  *     BCM_E_XXX
  23986  */
  23987 int bcm_esw_policer_action_detach(int unit, bcm_policer_t policer_id,
  23988                                 uint32 action_id)
  23989 {
  23990 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  23991     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  23992         return bcmi_esw_policer_action_detach(unit, policer_id, action_id);
  23993     }
  23994 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  23995     return _bcm_esw_policer_action_detach(unit, policer_id, action_id);
  23996 }
  23997 
  23998 /*
  23999  * Function:
  24000  *      bcm_esw_policer_action_attach
  24001  * Purpose:
  24002  *     Associate a policer action with a given policer id and
  24003  *     increment action usage reference count.
  24004  * Parameters:
  24005  *     unit                  - (IN) unit number
  24006  *     policer_id            - (IN) Base policer Id
  24007  *     action_id             - (IN) action id
  24008  * Returns:
  24009  *     BCM_E_XXX
  24010  */
  24011 
  24012 int bcm_esw_policer_action_attach(int unit, bcm_policer_t policer_id,
  24013                                 uint32 action_id)
  24014 {
  24015     int rv = BCM_E_NONE;
  24016     svm_meter_table_entry_t meter_entry;
  24017     _global_meter_policer_control_t *policer_control = NULL;
  24018     int policer_index = 0;
  24019     int index = 0;
  24020 
  24021 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  24022     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  24023         return bcmi_esw_policer_action_attach(unit, policer_id, action_id);
  24024     }
  24025 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  24026 
  24027     if (!soc_feature(unit, soc_feature_global_meter)) {
  24028         return BCM_E_UNAVAIL;
  24029     }
  24030     CHECK_GLOBAL_METER_INIT(unit);
  24031     /* validate policer id */
  24032     rv = _bcm_esw_policer_validate(unit, &policer_id);
  24033     if (BCM_FAILURE(rv)) {
  24034         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24035                   (BSL_META_U(unit,
  24036                               "Invalid Policer Id \n")));
  24037         return (rv);
  24038     }
  24039     /* validate action id */
  24040     if (action_id > soc_mem_index_max(unit, SVM_POLICY_TABLEm)) {
  24041         LOG_ERROR(BSL_LS_BCM_POLICER,
  24042                   (BSL_META_U(unit,
  24043                               "Invalid Action Id \n")));
  24044         return BCM_E_PARAM;
  24045     }
  24046 
  24047     GLOBAL_METER_LOCK(unit);
  24048     rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control);
  24049     if (BCM_FAILURE(rv)) {
  24050         GLOBAL_METER_UNLOCK(unit);
  24051         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24052                   (BSL_META_U(unit,
  24053                               "Unable to get policer control for the policer Id "
  24054                               "passed  \n")));
  24055         return (rv);
  24056     }
  24057 
  24058     if (policer_control->action_id == action_id) {
  24059         GLOBAL_METER_UNLOCK(unit);
  24060         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  24061                     (BSL_META_U(unit,
  24062                                 "Action Id passed is different from the one in "
  24063                                 "policer control-%x\n"), policer_control->action_id));
  24064         return (BCM_E_NONE);
  24065     }
  24066     /* check if action id is allocated */
  24067     if (global_meter_action_bookkeep[unit][action_id].used !=1)
  24068     {
  24069         GLOBAL_METER_UNLOCK(unit);
  24070         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24071                   (BSL_META_U(unit,
  24072                               "Action Id is not created \n")));
  24073         return BCM_E_PARAM;
  24074     }
  24075     /*  read meter table and add action_id*/
  24076     _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index);
  24077     rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index,
  24078                                                              &meter_entry);
  24079     if (BCM_FAILURE(rv)) {
  24080         GLOBAL_METER_UNLOCK(unit);
  24081         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24082                   (BSL_META_U(unit,
  24083                               "Unable to read SVM_METER_TABLE entry \n")));
  24084         return (rv);
  24085     }
  24086     soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf,
  24087                                                                  &action_id);
  24088     /* detach the existing action and decrement reference count */
  24089     if (policer_control->action_id) {
  24090         _bcm_esw_policer_action_detach(unit, policer_id,
  24091                                                 policer_control->action_id);
  24092     }
  24093     /* Write to HW*/
  24094     rv = WRITE_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index,
  24095                                                                  &meter_entry);
  24096     if (BCM_FAILURE(rv)) {
  24097         GLOBAL_METER_UNLOCK(unit);
  24098         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24099                   (BSL_META_U(unit,
  24100                               "Unable to write SVM_METER_TABLE entry \n")));
  24101         return (rv);
  24102     }
  24103     /* in case of cascade with coupling we need to configure the second set
  24104        as well */
  24105     if ((policer_control->grp_mode == \
  24106          bcmPolicerGroupModeIntPriCascadeWithCoupling) ||
  24107         (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) {
  24108         rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit,
  24109                                      policer_id, policer_control, &index);
  24110         rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, index,
  24111                                    &meter_entry);
  24112         if (BCM_FAILURE(rv)) {
  24113             GLOBAL_METER_UNLOCK(unit);
  24114             LOG_DEBUG(BSL_LS_BCM_POLICER,
  24115                       (BSL_META_U(unit,
  24116                                   "Unable to read SVM_METER_TABLE entry \n")));
  24117             return (rv);
  24118         }
  24119         soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf,
  24120                                        &action_id);
  24121         /* write to hW */
  24122         rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index,
  24123                                                             &meter_entry);
  24124         if (BCM_FAILURE(rv)) {
  24125             LOG_DEBUG(BSL_LS_BCM_POLICER,
  24126                       (BSL_META_U(unit,
  24127                                   "Unable to write SVM_METER_TABLE entry \n")));
  24128             GLOBAL_METER_UNLOCK(unit);
  24129         return (rv);
  24130        }
  24131     }
  24132    /* increment action usage reference count */
  24133     global_meter_action_bookkeep[unit][action_id].reference_count++;
  24134     policer_control->action_id = action_id;
  24135     GLOBAL_METER_UNLOCK(unit);
  24136     return rv;
  24137 }
  24138 
  24139 /*
  24140  * Function:
  24141  *      bcm_esw_policer_global_meter_config_set
  24142  * Purpose:
  24143  *      Set the Global Meter Configuration
  24144  * Parameters:
  24145  *      unit - (IN) Unit number
  24146  *      config - (IN) Global Meter Configuration
  24147  * Returns:
  24148  *      BCM_E_xxx
  24149  */
  24150 int bcm_esw_policer_global_meter_config_set(
  24151     int unit,
  24152     bcm_policer_global_meter_config_t *config)
  24153 {
  24154     int rv = BCM_E_UNAVAIL;
  24155 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  24156     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
  24157 
  24158     POL_FUNCTION_TRACE(unit, "IN");
  24159 
  24160     /* Parameter NULL error handling */
  24161     POL_CHECK_NULL_PARAMETER(unit, config);
  24162 
  24163     (void)bcmi_global_meter_dump_config(unit, "[set]", config);
  24164 
  24165     if (1 < config->ifg_enable) {
  24166         return BCM_E_PARAM;
  24167     }
  24168 
  24169     /* Initialization check */
  24170     CHECK_GLOBAL_METER_INIT(unit);
  24171     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
  24172 
  24173     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
  24174     /* Check if the chip specific function existed */
  24175     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->ifg_set);
  24176 
  24177     GLOBAL_METER_LOCK(unit);
  24178     rv = gm_dev_info->ifg_set(unit, config->ifg_enable);
  24179     if (BCM_FAILURE(rv)) {
  24180         GLOBAL_METER_UNLOCK(unit);
  24181         LOG_ERROR(BSL_LS_BCM_POLICER,
  24182                   (BSL_META_U(unit,
  24183                               "ifg_set failed(rv = %d)\n"),
  24184                               rv));
  24185         return rv;
  24186     }
  24187 
  24188     /* Check if the chip specific function existed */
  24189     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->source_order_set);
  24190 
  24191     rv = gm_dev_info->source_order_set(unit,
  24192                                        config->source_order,
  24193                                        config->source_order_count);
  24194     if (BCM_FAILURE(rv)) {
  24195         GLOBAL_METER_UNLOCK(unit);
  24196         LOG_ERROR(BSL_LS_BCM_POLICER,
  24197                   (BSL_META_U(unit,
  24198                               "source_order_set failed(rv = %d)\n"),
  24199                               rv));
  24200         return rv;
  24201     }
  24202     GLOBAL_METER_UNLOCK(unit);
  24203 
  24204     POL_FUNCTION_TRACE(unit, "OUT");
  24205 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  24206     return rv;
  24207 }
  24208 
  24209 /*
  24210  * Function:
  24211  *      bcm_esw_policer_global_meter_config_get
  24212  * Purpose:
  24213  *      Get the Global Meter Configuration
  24214  * Parameters:
  24215  *      unit - (IN) Unit number
  24216  *      config - (OUT) Global Meter Configuration
  24217  * Returns:
  24218  *      BCM_E_xxx
  24219  */
  24220 int bcm_esw_policer_global_meter_config_get(
  24221     int unit,
  24222     bcm_policer_global_meter_config_t *config)
  24223 {
  24224     int rv = BCM_E_UNAVAIL;
  24225 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  24226     const bcmi_global_meter_dev_info_t *gm_dev_info = NULL;
  24227 
  24228     POL_FUNCTION_TRACE(unit, "IN");
  24229 
  24230     /* Parameter NULL error handling */
  24231     POL_CHECK_NULL_PARAMETER(unit, config);
  24232 
  24233     /* Initialization check */
  24234     CHECK_GLOBAL_METER_INIT(unit);
  24235     CHECK_GLOBAL_METER_DEV_INFO_INIT(unit);
  24236 
  24237     gm_dev_info = BCM_SVM_DEV_INFO_GET(unit);
  24238 
  24239     /* Check if the chip specific function existed */
  24240     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->ifg_get);
  24241 
  24242     GLOBAL_METER_LOCK(unit);
  24243 
  24244     rv = gm_dev_info->ifg_get(unit, &config->ifg_enable);
  24245     if (BCM_FAILURE(rv)) {
  24246         GLOBAL_METER_UNLOCK(unit);
  24247         LOG_ERROR(BSL_LS_BCM_POLICER,
  24248                   (BSL_META_U(unit,
  24249                               "HW Operation failed(rv = %d)\n"),
  24250                               rv));
  24251         return rv;
  24252     }
  24253 
  24254     /* Check if the chip specific function existed */
  24255     POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->source_order_get);
  24256 
  24257     rv = gm_dev_info->source_order_get(unit,
  24258                                        config->source_order_count,
  24259                                        config->source_order);
  24260 
  24261     if (BCM_FAILURE(rv)) {
  24262         GLOBAL_METER_UNLOCK(unit);
  24263         LOG_ERROR(BSL_LS_BCM_POLICER,
  24264                   (BSL_META_U(unit,
  24265                               "HW Operation failed(rv = %d)\n"),
  24266                               rv));
  24267         return rv;
  24268     }
  24269     GLOBAL_METER_UNLOCK(unit);
  24270     (void)bcmi_global_meter_dump_config(unit, "[get]", config);
  24271 
  24272     POL_FUNCTION_TRACE(unit, "OUT");
  24273 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  24274     return rv;
  24275 }
  24276 /* END POLICER API's */
  24277 
  24278 #ifdef BCM_WARM_BOOT_SUPPORT
  24279 
  24280 /*
  24281  * Function:
  24282  *     _bcm_esw_svc_meter_wb_size_calc
  24283  * Purpose:
  24284  *    Calculates scache size for policer module.
  24285  * Parameters:
  24286  *     Unit       - (IN) unit number
  24287  *     size       - (OUT) scache size
  24288  * Returns:
  24289  *     BCM_E_XXX
  24290  */
  24291 STATIC int
  24292 _bcm_esw_svc_meter_wb_size_calc(int unit, int *size)
  24293 {
  24294     int temp_size = 0;
  24295 
  24296     /* BCM_WB_VERSION_1_0 */
  24297     temp_size = sizeof(int32) * BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES;
  24298 
  24299     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1)   {
  24300         /*
  24301          * Following fields of global_meter_offset_mode needs to be saved in
  24302          * scache. no_of_policer, group_mode and
  24303          * meter_attr.udf_pkt_attr_selectors_v.udf_id. Rest all fields can be
  24304          * recovered from hardware.
  24305          */
  24306         temp_size += (sizeof(uint32) * BCM_POLICER_SVC_METER_MAX_MODE * 3);
  24307     }
  24308     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
  24309         /*
  24310          * Support for non-continuous bit selection in Udf mode.
  24311          * we need to store attr_selectors information for each group
  24312          * offset mode.
  24313          */
  24314         temp_size += (sizeof(bcm_policer_group_mode_attr_selectors_info_t) *
  24315                 BCM_GLOBAL_METER_MAX_SCACHEABLE_GROUP_MODE);
  24316     }
  24317     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) {
  24318         /*
  24319          * Support for sharing of compression tables.
  24320          * A global structure is maintained to save current status of
  24321          * of compression table which includes reference counts, attribute
  24322          * values flag (bitmap) per attribute. This structure is saved in
  24323          * scache as it cannot be recovered from hardware tables.
  24324          * Structure to save - _bcm_policer_pkt_compressed_attr_maps_t
  24325          */
  24326 
  24327         if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  24328             temp_size += sizeof(uint32);    /* combine_cng_flags */
  24329             temp_size += sizeof(uint32);    /* combine_int_pri_flags */
  24330             temp_size += sizeof(uint32);    /* combine_vlan_format_flags */
  24331             temp_size += sizeof(uint32);    /* combine_outer_dot1p_flags */
  24332             temp_size += sizeof(uint32);    /* combine_inner_dot1p_flags */
  24333             temp_size += sizeof(uint32);    /* combine_pkt_res_flags */
  24334             temp_size += sizeof(uint32);    /* combine_drop_flags */
  24335             temp_size += sizeof(uint32);    /* combine_ip_pkt_flags */
  24336 
  24337             /* Attributes which are Array */
  24338             temp_size += sizeof(uint32);    /* Array Size */
  24339             temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE;
  24340             /* _bcmPolicerAttrPort */
  24341             temp_size += sizeof(uint32);    /* Array Size */
  24342             temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE;
  24343             /* _bcmPolicerAttrTosDscp */
  24344             temp_size += sizeof(uint32);    /* Array Size */
  24345             temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE;
  24346             /* _bcmPolicerAttrTosEcn */
  24347             temp_size += sizeof(uint32);    /* Array Size */
  24348             temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE;
  24349             /* _bcmPolicerAttrSvpType */
  24350         }
  24351     }
  24352 
  24353     *size = temp_size;
  24354 
  24355     return BCM_E_NONE;
  24356 }
  24357 
  24358 /*
  24359  * Function:
  24360  *      _bcm_esw_policer_config_from_meter_table
  24361  * Purpose:
  24362  *     For a given policer, read the configuraton info from meter table
  24363  * Parameters:
  24364  *     unit                  - (IN) unit number
  24365  *     policer               - (IN) Base policer Id
  24366  *     policer_control       - (OUT) Policer control info
  24367  * Returns:
  24368  *     BCM_E_XXX
  24369  */
  24370 int _bcm_esw_policer_config_from_meter_table(int unit, bcm_policer_t policer,
  24371                            _global_meter_policer_control_t *policer_control)
  24372 {
  24373     svm_meter_table_entry_t data;
  24374     int index = 0, numbers = 0;
  24375     uint32 mode = 0, coupling_flag = 0, pool = 0;
  24376     bcm_policer_svc_meter_mode_t meter_mode;
  24377     uint32 pol_index = 0, offset_mode = 0;
  24378     uint32 end_of_chain = 0, first_end_of_chain = 0;
  24379     int rv = BCM_E_NONE;
  24380     int policer_index = 0;
  24381     int size_pool = 0, num_pools = 0;
  24382     int pool_mask = 0, pool_offset = 0;
  24383     int offset_mask = 0;
  24384     int multi_chain = 0;
  24385     uint32 action_id = 0;
  24386 
  24387     size_pool =  SOC_INFO(unit).global_meter_max_size_of_pool;
  24388     num_pools =  SOC_INFO(unit).global_meter_pools;
  24389     offset_mask = size_pool - 1;
  24390     pool_offset = _shr_popcount(offset_mask);
  24391     pool_mask = (num_pools - 1) << pool_offset;
  24392 
  24393     offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >>
  24394                    BCM_POLICER_GLOBAL_METER_MODE_SHIFT);
  24395     if (offset_mode >= 1) {
  24396         offset_mode = offset_mode - 1;
  24397         if ((offset_mode) &&
  24398            (global_meter_offset_mode[unit][offset_mode].no_of_policers == 0)) {
  24399             return rv;
  24400         }
  24401     }
  24402     if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v ==
  24403         cascade_mode) ||
  24404         (global_meter_offset_mode[unit][offset_mode].type ==
  24405                 bcmPolicerGroupModeTypeCascade) ||
  24406         (global_meter_offset_mode[unit][offset_mode].type ==
  24407                 bcmPolicerGroupModeTypeCascadeWithCoupling)) {
  24408         /*
  24409          * Get the base policer ID for cascaded mode, then SDK will
  24410          * recover policer_control stuct according to the base policer ID
  24411          */
  24412         policer = (policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) |
  24413                   (policer & offset_mask);
  24414         multi_chain = 1;
  24415     }
  24416    /* Lets first try to get policer_control */
  24417     if (multi_chain == 1) {
  24418         rv = _bcm_global_meter_policer_get(unit, policer, &policer_control);
  24419     } else {
  24420         rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control);
  24421     }
  24422     if (BCM_SUCCESS(rv)) {
  24423         return rv;
  24424     }
  24425    /* read meter table to get policer configuration */
  24426     _bcm_esw_get_policer_table_index(unit, policer, &policer_index);
  24427     rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  24428                                                     policer_index, &data);
  24429     BCM_IF_ERROR_RETURN(rv);
  24430     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) {
  24431         soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODEf, &mode);
  24432     }
  24433     if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) {
  24434        soc_SVM_METER_TABLEm_field_get(unit, &data, COUPLING_FLAGf,
  24435                                                          &coupling_flag);
  24436    }
  24437    pool = (policer & pool_mask) >> pool_offset;
  24438    /* Allocate policer descriptor. */
  24439     _GLOBAL_METER_XGS3_ALLOC(policer_control,
  24440        sizeof (_global_meter_policer_control_t), "Global meter policer");
  24441    if (NULL == policer_control) {
  24442         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24443                   (BSL_META_U(unit,
  24444                               "Unable to allocate memory for Policer control data "
  24445                               "structure\n")));
  24446        return (BCM_E_MEMORY);
  24447    }
  24448 
  24449    if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) {
  24450        soc_SVM_METER_TABLEm_field_get(unit,
  24451                       &data, POLICY_TABLE_INDEXf, &action_id);
  24452         /* increment action usage reference count */
  24453        if (action_id) {
  24454             policer_control->action_id = action_id;
  24455             global_meter_action_bookkeep[unit]\
  24456                        [policer_control->action_id].reference_count++;
  24457        }
  24458    }
  24459 
  24460     /* Set the grp_mode for policer control. In case offset_mode=0,
  24461      * global_meter_offset_mode[0][0].group_mode will have by
  24462      * default 0 (bcmPolicerGroupModeSingle) */
  24463     policer_control->grp_mode =
  24464             global_meter_offset_mode[unit][offset_mode].group_mode;
  24465 
  24466     if((soc_feature(unit, soc_feature_global_meter_mef_10dot3)) &&
  24467             (mode == GLOBAL_METER_MODE_CASCADE)) {
  24468         /* Handling recovery of Cascade/Coupledcascade Mode in Apache
  24469          * octuple is allocated for cascade/coupledcascade group mode */
  24470         policer_control->direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  24471         policer_control->pid = policer;
  24472         policer_control->offset[0] = pool;
  24473         if ((policer_control->grp_mode ==
  24474                 bcmPolicerGroupModeCascadeWithCoupling) ||
  24475             (policer_control->grp_mode ==
  24476                 bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  24477             end_of_chain = 4;
  24478         }
  24479         pol_index = policer_index;
  24480         for (index = pool + 1; index < num_pools; index++) {
  24481             policer_control->offset[index] = index;
  24482 
  24483             if (index == end_of_chain) {
  24484                 first_end_of_chain = 1;
  24485             }
  24486             /* increment action usage reference count */
  24487             /* In case of cascade coupled, use only one chain */
  24488             if (first_end_of_chain == 0) {
  24489                 /* Read index to get policy_index, if any */
  24490                 policer_index = pol_index + (index << _shr_popcount(size_pool - 1));
  24491                 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  24492                                     policer_index, &data);
  24493                 if (!BCM_SUCCESS(rv)) {
  24494                     sal_free(policer_control);
  24495                     LOG_DEBUG(BSL_LS_BCM_POLICER,
  24496                         (BSL_META_U(unit,
  24497                                     "Unable to read SVM meter table at "
  24498                                     "index %x\n"), policer_index));
  24499                     return rv;
  24500                 }
  24501                 action_id = 0;
  24502                 soc_SVM_METER_TABLEm_field_get(unit, &data,
  24503                                 POLICY_TABLE_INDEXf, &action_id);
  24504                 if (action_id != 0) {
  24505                     global_meter_action_bookkeep[unit]\
  24506                             [action_id].reference_count++;
  24507                 }
  24508             }
  24509         }
  24510         policer_control->no_of_policers = index;
  24511     } else if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3) &&
  24512             (mode == GLOBAL_METER_MODE_CASCADE)) {
  24513        policer_control->direction = GLOBAL_METER_ALLOC_HORIZONTAL;
  24514        policer_control->pid = policer;
  24515        policer_control->offset[numbers] = 0;
  24516        numbers++;
  24517        pol_index = policer_index;
  24518        for (index = pool + 1; index < num_pools; index++) {
  24519            policer_index = pol_index + (index << _shr_popcount(size_pool - 1));
  24520            rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,
  24521                                                    policer_index, &data);
  24522            if (!BCM_SUCCESS(rv)) {
  24523                sal_free(policer_control);
  24524                LOG_DEBUG(BSL_LS_BCM_POLICER,
  24525                          (BSL_META_U(unit,
  24526                                      "Unable to read SVM meter table at "
  24527                                      "index %x\n"), policer_index));
  24528                return rv;
  24529            }
  24530            /* increment action usage reference count */
  24531            /* In case of cascade coupled, use only one chain */
  24532            if (first_end_of_chain == 0) {
  24533                 action_id = 0;
  24534                 soc_SVM_METER_TABLEm_field_get(unit, &data,
  24535                             POLICY_TABLE_INDEXf, &action_id);
  24536                 if (action_id != 0) {
  24537                     global_meter_action_bookkeep[unit]\
  24538                             [action_id].reference_count++;
  24539                 }
  24540            }
  24541            soc_SVM_METER_TABLEm_field_get(unit, &data,
  24542                                         END_OF_CHAINf, &end_of_chain);
  24543            soc_SVM_METER_TABLEm_field_get(unit, &data,
  24544                                               METER_MODEf, &meter_mode);
  24545            if ((meter_mode == GLOBAL_METER_MODE_CASCADE) &&
  24546                                                    (end_of_chain != 1)) {
  24547                policer_control->offset[numbers] = index - pool;
  24548            }
  24549            if (!(coupling_flag) &&
  24550                   (meter_mode == GLOBAL_METER_MODE_CASCADE) &&
  24551                   (end_of_chain == 1)) {
  24552                policer_control->offset[numbers] = index - pool;
  24553                if (!multi_chain) {
  24554                    /*
  24555                     * In cascaded mode there may be multi chains in one policer
  24556                     * group, and each policer group contains 8 policer IDs. SDK
  24557                     * should recover all these 8 policer IDs.
  24558                     */
  24559                    index = num_pools;
  24560                }
  24561            }
  24562            if ((coupling_flag) &&
  24563                            (meter_mode == GLOBAL_METER_MODE_CASCADE) &&
  24564                            (end_of_chain) && (first_end_of_chain)) {
  24565                policer_control->offset[numbers] = index - pool;
  24566                index = num_pools;
  24567            }
  24568            if ((coupling_flag) &&
  24569                        (meter_mode == GLOBAL_METER_MODE_CASCADE) &&
  24570                        (end_of_chain) && (first_end_of_chain == 0)) {
  24571                policer_control->offset[numbers] = index - pool;
  24572                first_end_of_chain = 1;
  24573            }
  24574            numbers++;
  24575        } /* end of for */
  24576        policer_control->no_of_policers = numbers;
  24577     } else if (offset_mode >= 1) {
  24578        policer_control->direction = GLOBAL_METER_ALLOC_VERTICAL;
  24579        policer_control->pid = policer;
  24580        /* add code to get the number of policers for this mode */
  24581        policer_control->no_of_policers =
  24582        global_meter_offset_mode[unit][offset_mode].no_of_policers;
  24583     } else {
  24584        policer_control->direction = GLOBAL_METER_ALLOC_VERTICAL;
  24585        policer_control->pid = policer;
  24586        policer_control->no_of_policers = 1;
  24587     }
  24588     rv =  _global_meter_reserve_policer_id(unit, policer_control->direction,
  24589                                             policer_control->no_of_policers,
  24590                                         policer, &policer_control->offset[0]);
  24591     if (!BCM_SUCCESS(rv)) {
  24592          /* De-allocate policer descriptor. */
  24593         sal_free(policer_control);
  24594         LOG_DEBUG(BSL_LS_BCM_POLICER,
  24595                   (BSL_META_U(unit,
  24596                               "Unable to allocate policers with base id %x\n"),
  24597                    policer));
  24598         return BCM_E_INTERNAL;
  24599     }
  24600     /* Insert policer into policers hash. */
  24601     _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit],
  24602                  policer_control,(policer & _GLOBAL_METER_HASH_MASK));
  24603     /* increment mode reference count for new policer  */
  24604     if (offset_mode) {
  24605         rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, offset_mode);
  24606     }
  24607     return rv;
  24608 }
  24609 
  24610 /*
  24611  * Function:
  24612  *      _bcm_esw_policer_config_reinit_from_table
  24613  * Purpose:
  24614  *     Read entry from table and re-init policer if present
  24615  * Parameters:
  24616  *     unit                  - (IN) unit number
  24617  *     mem                   - (IN) table
  24618  *     index                 - (IN) Index in table for entry
  24619  *     entry                 - (IN) one entry in table
  24620  *     user_data             - (IN) data passed by calling function
  24621  *     dirty                 - (OUT) Set if entry is modified
  24622  * Returns:
  24623  *     BCM_E_XXX
  24624  */
  24625 STATIC int
  24626 _bcm_esw_policer_config_reinit_from_table(int unit, soc_mem_t mem, uint32 index,
  24627                                         void *entry, void *user_data, uint32 *dirty)
  24628 {
  24629     int rv = BCM_E_NONE;
  24630     bcm_policer_t policer;
  24631     uint32 offset_mode = 0, meter_index = 0;
  24632     _bcm_policer_svm_source_type_t mem_index;
  24633     _global_meter_policer_control_t *policer_control = NULL;
  24634 
  24635     if (entry == NULL) {
  24636         return BCM_E_INTERNAL;
  24637     }
  24638     _bcm_policer_svm_source_index_get(unit, mem, &mem_index);
  24639     if (mem == SVM_MACROFLOW_INDEX_TABLEm) {
  24640         offset_mode = meter_index = 0;
  24641         if (SOC_MEM_FIELD_VALID(unit, mem, MACROFLOW_INDEXf)) {
  24642             meter_index = soc_mem_field32_get(unit, mem, entry,
  24643                     MACROFLOW_INDEXf);
  24644         }
  24645     } else {
  24646         offset_mode = soc_mem_field32_get(unit, mem, entry,
  24647                 BCM_SVM_SOURCE(unit, mem_index).offset_mode);
  24648         meter_index = soc_mem_field32_get(unit, mem, entry,
  24649                 BCM_SVM_SOURCE(unit, mem_index).meter_index);
  24650     }
  24651     _bcm_esw_get_policer_id_from_index_offset(unit, meter_index,
  24652             offset_mode, &policer);
  24653     if (policer != 0) {
  24654         policer_control = NULL;
  24655         rv = _bcm_esw_policer_config_from_meter_table(unit, policer,
  24656                 policer_control);
  24657         if (BCM_SUCCESS(rv)) {
  24658             rv = _bcm_esw_policer_increment_ref_count(unit, policer);
  24659         }
  24660     }
  24661     return rv;
  24662 }
  24663 
  24664 /*
  24665  * Function:
  24666  *      _bcm_esw_svm_action_reinit_from_table
  24667  * Purpose:
  24668  *       Called via a svm table traversal function to reinit action if present
  24669  * Parameters:
  24670  *     unit                  - (IN) unit number
  24671  *     mem                   - (IN) memory
  24672  *     index                 - (IN) Index in Memory
  24673  *     entry                 - (IN) Buffer of mem entry at index in Memory
  24674  *     user_data             - (IN) user specific info
  24675  *     dirty                 - (OUT) Is entry modified
  24676  * Returns:
  24677  *     BCM_E_XXX
  24678  */
  24679 STATIC int
  24680 _bcm_esw_svm_action_reinit_from_table(int unit, soc_mem_t mem, uint32 index,
  24681         void *entry, void *user_data, uint32 *dirty)
  24682 {
  24683     int rv = BCM_E_NONE;
  24684     uint32 green_action[1] = {0}, yellow_action[1] = {0}, red_action[1] = {0};
  24685 
  24686     soc_SVM_POLICY_TABLEm_field_get(unit, entry, G_ACTIONSf, &green_action[0]);
  24687     soc_SVM_POLICY_TABLEm_field_get(unit, entry, Y_ACTIONSf, &yellow_action[0]);
  24688     soc_SVM_POLICY_TABLEm_field_get(unit, entry, R_ACTIONSf, &red_action[0]);
  24689 
  24690     if ((green_action[0] > 0) || (yellow_action[0] > 0) ||
  24691             (red_action[0] > 0) ||
  24692             (global_meter_action_bookkeep[unit][index].reference_count != 0))
  24693     {
  24694         global_meter_action_bookkeep[unit][index].used = 1;
  24695         /* Reserve the the action table entry */
  24696         rv = shr_aidxres_list_reserve_block(
  24697                 meter_action_list_handle[unit], index, 1);
  24698         if (BCM_FAILURE(rv)) {
  24699             LOG_DEBUG(BSL_LS_BCM_POLICER,
  24700                     (BSL_META_U(unit,
  24701                                 "Unable to reserve action id %d in "
  24702                                 "index management list\n"), index));
  24703             return (rv);
  24704         }
  24705     }
  24706     return rv;
  24707 }
  24708 
  24709 /*
  24710  * Function:
  24711  *      _bcm_policer_config_reinit
  24712  * Purpose:
  24713  *     go through all the table entries that support service meter
  24714  *     and get policer configuration for those policers that are
  24715  *     configured in HW to rebuild SDK internal data strutcure on
  24716  *     warm boot.
  24717  * Parameters:
  24718  *     unit                  - (IN) unit number
  24719  * Returns:
  24720  *     BCM_E_XXX
  24721  */
  24722 int _bcm_policer_config_reinit(int unit)
  24723 {
  24724     int rv = BCM_E_NONE;
  24725     soc_mem_t table;
  24726     _bcm_policer_svm_source_type_t mem_index;
  24727 
  24728     for (mem_index = 0; mem_index < _BCM_SVM_MEM_COUNT; mem_index++) {
  24729         table = BCM_SVM_SOURCE(unit, mem_index).table;
  24730         if (table == INVALIDm) {
  24731             continue;
  24732         }
  24733         rv = _bcm_esw_svm_source_traverse (unit, table, -1, -1,
  24734                 _bcm_esw_policer_config_reinit_from_table, NULL);
  24735         BCM_IF_ERROR_RETURN(rv);
  24736     }
  24737 
  24738     if (BCM_SUCCESS(rv)) {
  24739         table = SVM_MACROFLOW_INDEX_TABLEm;
  24740         rv = _bcm_esw_svm_source_traverse (unit, table, -1, -1,
  24741                 _bcm_esw_policer_config_reinit_from_table, NULL);
  24742     }
  24743     return rv;
  24744 }
  24745 
  24746 /*
  24747  * Function:
  24748  *      _bcm_esw_global_meter_uncompressed_offset_mode_reinit
  24749  * Purpose:
  24750  *      Recover un-coompessed offset mode information from HW and re-configure
  24751  *      SDK data structures on warm boot
  24752  * Parameters:
  24753  *     unit                  - (IN) unit number
  24754  *     mode                  - (IN) meter offset mode
  24755  *     selector_count        - (IN) Number of selectors
  24756  *     selector_for_bit_x_en_field_value - (IN) selector field enable
  24757  *     selector_for_bit_x_field_value    - (IN) selector field
  24758  * Returns:
  24759  *     BCM_E_XXX
  24760  */
  24761 int _bcm_esw_global_meter_uncompressed_offset_mode_reinit(
  24762                                  int unit,
  24763                                  int mode,
  24764                                  uint32 selector_count,
  24765                                  uint32  selector_for_bit_x_en_field_value[8],
  24766                                  uint32  selector_for_bit_x_field_value[8])
  24767 {
  24768     uint32  uncompressed_attr_bits_selector = 0;
  24769     uint32  index = 0;
  24770     int rv = BCM_E_NONE;
  24771     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
  24772     int                 port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE;
  24773 
  24774     pkt_attr_bit_pos = BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos;
  24775 
  24776     global_meter_offset_mode[unit][mode].used = 1;
  24777     global_meter_offset_mode[unit][mode].reference_count = 0;
  24778     global_meter_offset_mode[unit][mode].meter_attr.mode_type_v =
  24779                                                   uncompressed_mode;
  24780     for (uncompressed_attr_bits_selector = 0, index = 0; index < 8; index++)
  24781     {
  24782         if (selector_for_bit_x_en_field_value[index] != 0)
  24783         {
  24784             if ( selector_for_bit_x_field_value[index] ==
  24785                                pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit)
  24786             {
  24787                  uncompressed_attr_bits_selector |=
  24788                        BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS;
  24789                  continue;
  24790             }
  24791             if ( selector_for_bit_x_field_value[index] ==
  24792                                pkt_attr_bit_pos[pkt_attr_drop].start_bit)
  24793             {
  24794                  uncompressed_attr_bits_selector |=
  24795                         BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS;
  24796                  continue;
  24797             }
  24798             if (( selector_for_bit_x_field_value[index] ==
  24799                         pkt_attr_bit_pos[pkt_attr_svp_group].start_bit)  &&
  24800                ( selector_for_bit_x_field_value[index] <=
  24801                         pkt_attr_bit_pos[pkt_attr_svp_group].end_bit))
  24802             {
  24803                  uncompressed_attr_bits_selector |=
  24804                     BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS;
  24805                  continue;
  24806             }
  24807             if (( selector_for_bit_x_field_value[index] >=
  24808                         pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit) &&
  24809                ( selector_for_bit_x_field_value[index] <=
  24810                         pkt_attr_bit_pos[pkt_attr_pkt_resolution].end_bit))
  24811 
  24812             {
  24813                  uncompressed_attr_bits_selector |=
  24814                                BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE;
  24815                  continue;
  24816             }
  24817             if (( selector_for_bit_x_field_value[index] >=
  24818                                pkt_attr_bit_pos[pkt_attr_tos].start_bit) &&
  24819                ( selector_for_bit_x_field_value[index] <=
  24820                                pkt_attr_bit_pos[pkt_attr_tos].end_bit))
  24821             {
  24822                  uncompressed_attr_bits_selector |=
  24823                                         BCM_POLICER_SVC_METER_TOS_ATTR_SIZE;
  24824                  continue;
  24825             }
  24826             if (( selector_for_bit_x_field_value[index] >=
  24827                              pkt_attr_bit_pos[pkt_attr_ing_port].start_bit) &&
  24828                ( selector_for_bit_x_field_value[index] <=
  24829                              pkt_attr_bit_pos[pkt_attr_ing_port].end_bit))
  24830             {
  24831                 port_attr_size =
  24832                         BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size;
  24833                 uncompressed_attr_bits_selector |= port_attr_size;
  24834                 continue;
  24835             }
  24836             if (( selector_for_bit_x_field_value[index] >=
  24837                           pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit) &&
  24838                ( selector_for_bit_x_field_value[index] <=
  24839                           pkt_attr_bit_pos[pkt_attr_inner_dot1p].end_bit))
  24840             {
  24841                 uncompressed_attr_bits_selector |=
  24842                                 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE;
  24843                 continue;
  24844             }
  24845             if (( selector_for_bit_x_field_value[index] >=
  24846                            pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit) &&
  24847                ( selector_for_bit_x_field_value[index] <=
  24848                            pkt_attr_bit_pos[pkt_attr_outer_dot1p].end_bit))
  24849             {
  24850                 uncompressed_attr_bits_selector |=
  24851                                 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE;
  24852                 continue;
  24853             }
  24854             if (( selector_for_bit_x_field_value[index] >=
  24855                            pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit) &&
  24856                ( selector_for_bit_x_field_value[index] <=
  24857                            pkt_attr_bit_pos[pkt_attr_vlan_format].end_bit))
  24858             {
  24859                 uncompressed_attr_bits_selector |=
  24860                                 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE;
  24861                 continue;
  24862             }
  24863             if (( selector_for_bit_x_field_value[index] >=
  24864                                pkt_attr_bit_pos[pkt_attr_int_pri].start_bit) &&
  24865                ( selector_for_bit_x_field_value[index] <=
  24866                                pkt_attr_bit_pos[pkt_attr_int_pri].end_bit))
  24867             {
  24868                 uncompressed_attr_bits_selector |=
  24869                                    BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE;
  24870                 continue;
  24871             }
  24872             if (( selector_for_bit_x_field_value[index] >=
  24873                                pkt_attr_bit_pos[pkt_attr_cng].start_bit) &&
  24874                ( selector_for_bit_x_field_value[index] <=
  24875                                pkt_attr_bit_pos[pkt_attr_cng].end_bit))
  24876             {
  24877                 uncompressed_attr_bits_selector |=
  24878                                           BCM_POLICER_SVC_METER_CNG_ATTR_SIZE;
  24879                 continue;
  24880             }
  24881             if (( selector_for_bit_x_field_value[index] >=
  24882                                pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit) &&
  24883                ( selector_for_bit_x_field_value[index] <=
  24884                                pkt_attr_bit_pos[pkt_attr_short_int_pri].end_bit))
  24885             {
  24886                 uncompressed_attr_bits_selector |=
  24887                                    BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE;
  24888                 continue;
  24889             }
  24890 
  24891         }
  24892     }
  24893     global_meter_offset_mode[unit][mode].meter_attr.\
  24894           uncompressed_attr_selectors_v.uncompressed_attr_bits_selector =
  24895                                               uncompressed_attr_bits_selector;
  24896     return rv;
  24897 }
  24898 
  24899 /*
  24900  * Function:
  24901  *      _bcm_esw_global_meter_compressed_offset_mode_reinit
  24902  * Purpose:
  24903  *      Recover Compessed offset mode information from HW and re-configure SDK
  24904  *      data structures on warm boot
  24905  *
  24906  * Parameters:
  24907  *     unit                  - (IN) unit number
  24908  *     mode                  - (IN) meter offset mode
  24909  *     selector_count        - (IN) Number of selectors
  24910  *     selector_for_bit_x_en_field_value - (IN) selector field enable
  24911  *     selector_for_bit_x_field_value    - (IN) selector field
  24912  * Returns:
  24913  *     BCM_E_XXX
  24914  */
  24915 int _bcm_esw_global_meter_compressed_offset_mode_reinit(
  24916                                  int unit,
  24917                                  int mode,
  24918                                  uint32 selector_count,
  24919                                  uint32  selector_for_bit_x_en_field_value[8],
  24920                                  uint32  selector_for_bit_x_field_value[8])
  24921 {
  24922     uint32  index = 0;
  24923     int rv = BCM_E_NONE;
  24924     compressed_attr_selectors_t *comp_pkt_attr_sel;
  24925     pkt_attr_bits_t *pkt_attr_bits;
  24926     _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL;
  24927     int                     index_max = 0;
  24928 
  24929     pkt_attr_bit_pos =
  24930             BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos;
  24931 
  24932     global_meter_offset_mode[unit][mode].used = 1;
  24933     global_meter_offset_mode[unit][mode].reference_count = 0;
  24934     global_meter_offset_mode[unit][mode].meter_attr.mode_type_v =
  24935                                                      compressed_mode;
  24936     pkt_attr_bits = &(global_meter_offset_mode[unit][mode].meter_attr.\
  24937                        compressed_attr_selectors_v.pkt_attr_bits_v);
  24938     comp_pkt_attr_sel = &(global_meter_offset_mode[unit][mode].meter_attr.\
  24939                                                compressed_attr_selectors_v);
  24940     for (index = 0; index < 8; index++)
  24941     {
  24942         if (selector_for_bit_x_en_field_value[index] != 0)
  24943         {
  24944             if ( selector_for_bit_x_field_value[index] ==
  24945                                pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit)
  24946             {
  24947                  pkt_attr_bits->ip_pkt = 1;
  24948                  continue;
  24949             }
  24950             if ( selector_for_bit_x_field_value[index] ==
  24951                                pkt_attr_bit_pos[pkt_attr_drop].start_bit)
  24952             {
  24953                  pkt_attr_bits->drop = 1;
  24954                  continue;
  24955             }
  24956             if (( selector_for_bit_x_field_value[index] >=
  24957                         pkt_attr_bit_pos[pkt_attr_svp_group].start_bit) &&
  24958                ( selector_for_bit_x_field_value[index] <=
  24959                         pkt_attr_bit_pos[pkt_attr_svp_group].end_bit))
  24960             {
  24961                  pkt_attr_bits->svp_type++ ;
  24962                  continue;
  24963             }
  24964             if (( selector_for_bit_x_field_value[index] >=
  24965                         pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit) &&
  24966                ( selector_for_bit_x_field_value[index] <=
  24967                         pkt_attr_bit_pos[pkt_attr_pkt_resolution].end_bit))
  24968 
  24969             {
  24970                  pkt_attr_bits->pkt_resolution++;
  24971                  continue;
  24972             }
  24973             if (( selector_for_bit_x_field_value[index] >=
  24974                                pkt_attr_bit_pos[pkt_attr_tos].start_bit) &&
  24975                ( selector_for_bit_x_field_value[index] <=
  24976                                pkt_attr_bit_pos[pkt_attr_tos].end_bit))
  24977             {
  24978                  pkt_attr_bits->tos++;
  24979                  continue;
  24980             }
  24981             if (( selector_for_bit_x_field_value[index] >=
  24982                              pkt_attr_bit_pos[pkt_attr_ing_port].start_bit) &&
  24983                ( selector_for_bit_x_field_value[index] <=
  24984                              pkt_attr_bit_pos[pkt_attr_ing_port].end_bit))
  24985             {
  24986                  pkt_attr_bits->ing_port++;
  24987                  continue;
  24988             }
  24989             if (( selector_for_bit_x_field_value[index] >=
  24990                           pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit) &&
  24991                ( selector_for_bit_x_field_value[index] <=
  24992                           pkt_attr_bit_pos[pkt_attr_inner_dot1p].end_bit))
  24993             {
  24994                  pkt_attr_bits->inner_dot1p++;
  24995                  continue;
  24996             }
  24997             if (( selector_for_bit_x_field_value[index] >=
  24998                            pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit) &&
  24999                ( selector_for_bit_x_field_value[index] <=
  25000                            pkt_attr_bit_pos[pkt_attr_outer_dot1p].end_bit))
  25001             {
  25002                  pkt_attr_bits->outer_dot1p++;
  25003                  continue;
  25004             }
  25005             if (( selector_for_bit_x_field_value[index] >=
  25006                            pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit) &&
  25007                ( selector_for_bit_x_field_value[index] <=
  25008                            pkt_attr_bit_pos[pkt_attr_vlan_format].end_bit))
  25009             {
  25010                  pkt_attr_bits->vlan_format++;
  25011                  continue;
  25012             }
  25013             if (( selector_for_bit_x_field_value[index] >=
  25014                                pkt_attr_bit_pos[pkt_attr_int_pri].start_bit) &&
  25015                ( selector_for_bit_x_field_value[index] <=
  25016                                pkt_attr_bit_pos[pkt_attr_int_pri].end_bit))
  25017             {
  25018                  pkt_attr_bits->int_pri++;
  25019                  continue;
  25020             }
  25021             if (( selector_for_bit_x_field_value[index] >=
  25022                                pkt_attr_bit_pos[pkt_attr_cng].start_bit) &&
  25023                ( selector_for_bit_x_field_value[index] <=
  25024                                pkt_attr_bit_pos[pkt_attr_cng].end_bit))
  25025             {
  25026                  pkt_attr_bits->cng++;
  25027                  continue;
  25028             }
  25029             if (( selector_for_bit_x_field_value[index] >=
  25030                                pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit) &&
  25031                ( selector_for_bit_x_field_value[index] <=
  25032                                pkt_attr_bit_pos[pkt_attr_short_int_pri].end_bit))
  25033             {
  25034                  pkt_attr_bits->short_int_pri++;
  25035                  continue;
  25036             }
  25037 
  25038         }
  25039     }
  25040 
  25041     if ((pkt_attr_bits->cng) || (pkt_attr_bits->int_pri))
  25042     {
  25043         index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm);
  25044         for (index = 0; index <= index_max; index++) {
  25045             SOC_IF_ERROR_RETURN(soc_mem_read(
  25046                 unit,
  25047                 ING_SVM_PRI_CNG_MAPm,
  25048                 MEM_BLOCK_ANY,
  25049                 index,
  25050                 &comp_pkt_attr_sel->compressed_pri_cnf_attr_map_v[index]));
  25051         }
  25052     }
  25053     if ((pkt_attr_bits->vlan_format) || (pkt_attr_bits->outer_dot1p) ||
  25054                                                (pkt_attr_bits->inner_dot1p))
  25055     {
  25056         index_max = soc_mem_index_max(unit, ING_SVM_PKT_PRI_MAPm);
  25057         for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) {
  25058             SOC_IF_ERROR_RETURN(soc_mem_read(
  25059                 unit,
  25060                 ING_SVM_PKT_PRI_MAPm,
  25061                 MEM_BLOCK_ANY,
  25062                 index,
  25063                 &comp_pkt_attr_sel->compressed_pkt_pri_attr_map_v[index]));
  25064         }
  25065     }
  25066 
  25067     if ((pkt_attr_bits->ing_port))
  25068     {
  25069         index_max = soc_mem_index_max(unit, ING_SVM_PORT_MAPm);
  25070         for (index = 0; index <= index_max; index++) {
  25071             SOC_IF_ERROR_RETURN(soc_mem_read(
  25072                 unit,
  25073                 ING_SVM_PORT_MAPm,
  25074                 MEM_BLOCK_ANY,
  25075                 index,
  25076                 &comp_pkt_attr_sel->compressed_port_attr_map_v[index]));
  25077         }
  25078     }
  25079 
  25080     if (pkt_attr_bits->tos)
  25081     {
  25082         index_max = soc_mem_index_max(unit, ING_SVM_TOS_MAPm);
  25083         for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) {
  25084             SOC_IF_ERROR_RETURN(soc_mem_read(
  25085                 unit,
  25086                 ING_SVM_TOS_MAPm,
  25087                 MEM_BLOCK_ANY,
  25088                 index,
  25089                 &comp_pkt_attr_sel->compressed_tos_attr_map_v[index]));
  25090         }
  25091     }
  25092 
  25093     if ((pkt_attr_bits->pkt_resolution) || (pkt_attr_bits->svp_type) ||
  25094                                                 (pkt_attr_bits->drop))
  25095     {
  25096         index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm);
  25097         for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) {
  25098             SOC_IF_ERROR_RETURN(soc_mem_read(
  25099                 unit,
  25100                 ING_SVM_PKT_RES_MAPm,
  25101                 MEM_BLOCK_ANY,
  25102                 index,
  25103                 &comp_pkt_attr_sel->compressed_pkt_res_attr_map_v[index]));
  25104         }
  25105     }
  25106     return rv;
  25107 }
  25108 
  25109 /*
  25110  * Function:
  25111  *      _bcm_esw_global_meter_udf_offset_mode_reinit
  25112  * Purpose:
  25113  *      Recover UDF offset mode information from HW and re-configure SDK
  25114  *      data structures on warm boot
  25115  * Parameters:
  25116  *     unit                  - (IN) unit number
  25117  *     mode                  - (IN) meter offset mode
  25118  *     selector_count        - (IN) Number of selectors
  25119  *     selector_for_bit_x_en_field_value - (IN) selector field enable
  25120  *     selector_for_bit_x_field_value    - (IN) selector field
  25121  * Returns:
  25122  *     BCM_E_XXX
  25123  */
  25124 int _bcm_esw_global_meter_udf_offset_mode_reinit(
  25125                                  int unit,
  25126                                  int mode,
  25127                                  uint32 selector_count,
  25128                                  uint32  selector_for_bit_x_en_field_value[8],
  25129                                  uint32  selector_for_bit_x_field_value[8])
  25130 {
  25131     int rv = BCM_E_NONE;
  25132     uint16  udf0 = 0;
  25133     uint16  udf1 = 0;
  25134     uint32  index = 0;
  25135     udf_pkt_attr_selectors_t *udf_attr = NULL;
  25136     svm_offset_table_entry_t   *buf;
  25137     svm_offset_table_entry_t   *entry;
  25138     int     entry_index = 0;
  25139     uint32 offset, pool_offset, meter_enable;
  25140 
  25141     udf_attr =
  25142       &global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v;
  25143     if (selector_for_bit_x_field_value[0] == 0) {
  25144         udf_attr->drop = 1;
  25145         index++;
  25146     }
  25147     for (udf0 = 0, udf1 = 0; index < 8; index++) {
  25148         if (selector_for_bit_x_field_value[index] != 0) {
  25149             udf_attr->udf_subdiv[0].width += 1;
  25150             if ( selector_for_bit_x_field_value[index] <= 16) {
  25151                  udf0 |= (1 << (selector_for_bit_x_field_value[index] - 1));
  25152             } else {
  25153                  udf1 |= (1 << (selector_for_bit_x_field_value[index]- 16 - 1));
  25154             }
  25155         }
  25156     }
  25157 
  25158     global_meter_offset_mode[unit][mode].used = 1;
  25159     global_meter_offset_mode[unit][mode].reference_count = 0;
  25160     global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = udf_mode;
  25161     global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v.\
  25162                                                udf_pkt_attr_bits_v.udf0 = udf0;
  25163     global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v.\
  25164                                                udf_pkt_attr_bits_v.udf1 = udf1;
  25165 
  25166     udf_attr->total_subdiv = 1;
  25167     offset = (udf_attr->drop == 1) ?
  25168             selector_for_bit_x_field_value[1] : selector_for_bit_x_field_value[0];
  25169     /* Since udf0 bits start from bit-1 in the selector bit vector */
  25170     udf_attr->udf_subdiv[0].offset = offset - 1;
  25171 
  25172     /* Allocate buffer to store the DMAed table entries. */
  25173     buf = soc_cm_salloc(unit, sizeof(svm_offset_table_entry_t) * 256,
  25174                               "svm macro flow index table entry buffer");
  25175     if (NULL == buf) {
  25176         return (BCM_E_MEMORY);
  25177     }
  25178     /* Initialize the entry buffer. */
  25179     sal_memset(buf, 0, sizeof(svm_offset_table_entry_t) * 256);
  25180 
  25181     /* Read the table entries into the buffer. */
  25182     rv = soc_mem_read_range(unit, SVM_OFFSET_TABLEm,
  25183                                 MEM_BLOCK_ALL,
  25184                     ((mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE)),
  25185                     ((mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) + 256),
  25186                     buf);
  25187     if (BCM_FAILURE(rv)) {
  25188         if (buf) {
  25189              soc_cm_sfree(unit, buf);
  25190         }
  25191         return rv;
  25192     }
  25193 
  25194     /* Iterate over the table entries. */
  25195     for (entry_index = 0; entry_index < 256; entry_index++) {
  25196         entry = soc_mem_table_idx_to_pointer(unit,
  25197                               SVM_OFFSET_TABLEm,
  25198                               svm_offset_table_entry_t *,
  25199                               buf, entry_index);
  25200         soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, OFFSETf, &offset);
  25201         soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, POOL_OFFSETf, &pool_offset);
  25202         soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, METER_ENABLEf, &meter_enable);
  25203 
  25204         udf_attr->offset_map[entry_index].offset = offset;
  25205         udf_attr->offset_map[entry_index].pool = pool_offset;
  25206         udf_attr->offset_map[entry_index].meter_enable = meter_enable;
  25207 
  25208         if(udf_attr->offset_map[entry_index].meter_enable == 1) {
  25209             udf_attr->num_selectors += 1;
  25210         }
  25211     }
  25212     if (buf) {
  25213         soc_cm_sfree(unit, buf);
  25214     }
  25215     return rv;
  25216 }
  25217 
  25218 /*
  25219  * Function:
  25220  *      _bcm_esw_svm_pkt_compressed_attr_maps_reference
  25221  * Purpose:
  25222  *      Update reference count of compression attr maps after recover.
  25223  * Parameters:
  25224  *     unit                  - (IN) unit number
  25225  *     compressed_attr_selectors_v - (IN) compressed attribute selectors.
  25226  *     pkt_attr_selectors    - (IN) Packet attribute selectors
  25227  * Returns:
  25228  *     BCM_E_XXX
  25229  */
  25230 int _bcm_esw_svm_pkt_compressed_attr_maps_reference(int unit,
  25231     compressed_attr_selectors_t *compressed_attr_selectors_v,
  25232     bcm_policer_attr_selectors_t *pkt_attr_selectors)
  25233 {
  25234     pkt_attr_bits_t *pkt_attr_bits_v = NULL;
  25235     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
  25236 
  25237     pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v;
  25238     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
  25239 
  25240     if (cmprsd_attr_maps == NULL) {
  25241         return BCM_E_NONE;
  25242     }
  25243 
  25244     /* update reference count for policer group created via group_mode */
  25245     if (pkt_attr_bits_v != NULL) {
  25246         if ((pkt_attr_bits_v->cng != 0) ||
  25247                 (pkt_attr_bits_v->int_pri != 0)) {
  25248             (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map])++;
  25249             cmprsd_attr_maps->cng = 1;
  25250             cmprsd_attr_maps->int_pri = 1;
  25251         }
  25252         if ((pkt_attr_bits_v->vlan_format != 0) ||
  25253                 (pkt_attr_bits_v->outer_dot1p != 0) ||
  25254                 (pkt_attr_bits_v->inner_dot1p != 0)) {
  25255             (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map])++;
  25256             cmprsd_attr_maps->vlan_format = 1;
  25257             cmprsd_attr_maps->outer_dot1p = 1;
  25258             cmprsd_attr_maps->inner_dot1p = 1;
  25259         }
  25260         if (pkt_attr_bits_v->ing_port != 0) {
  25261             (cmprsd_attr_maps->ref_counts[pkt_attr_port_map])++;
  25262             cmprsd_attr_maps->port = 1;
  25263         }
  25264         if ((pkt_attr_bits_v->tos != 0) ||
  25265                 (pkt_attr_bits_v->tos_ecn != 0)) {
  25266             (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map])++;
  25267             cmprsd_attr_maps->tos_dscp = 1;
  25268             cmprsd_attr_maps->tos_ecn = 1;
  25269         }
  25270         if ((pkt_attr_bits_v->pkt_resolution != 0) ||
  25271                 (pkt_attr_bits_v->svp_type != 0) ||
  25272                 (pkt_attr_bits_v->drop != 0))   {
  25273             (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map])++;
  25274             cmprsd_attr_maps->pkt_resolution = 1;
  25275             cmprsd_attr_maps->svp_type = 1;
  25276             cmprsd_attr_maps->drop = 1;
  25277         }
  25278     } else if (pkt_attr_selectors != NULL) {
  25279         if ((pkt_attr_selectors->cng != 0) ||
  25280                 (pkt_attr_selectors->int_pri != 0)) {
  25281             (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map])++;
  25282             cmprsd_attr_maps->cng = 1;
  25283             cmprsd_attr_maps->int_pri = 1;
  25284         }
  25285         if ((pkt_attr_selectors->vlan_format != 0) ||
  25286                 (pkt_attr_selectors->outer_dot1p != 0) ||
  25287                 (pkt_attr_selectors->inner_dot1p != 0)) {
  25288             (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map])++;
  25289             cmprsd_attr_maps->vlan_format = 1;
  25290             cmprsd_attr_maps->outer_dot1p = 1;
  25291             cmprsd_attr_maps->inner_dot1p = 1;
  25292         }
  25293         if (pkt_attr_selectors->port != 0) {
  25294             (cmprsd_attr_maps->ref_counts[pkt_attr_port_map])++;
  25295             cmprsd_attr_maps->port = 1;
  25296         }
  25297         if ((pkt_attr_selectors->tos_dscp != 0) ||
  25298                 (pkt_attr_selectors->tos_ecn != 0)) {
  25299             (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map])++;
  25300             cmprsd_attr_maps->tos_dscp = 1;
  25301             cmprsd_attr_maps->tos_ecn = 1;
  25302         }
  25303         if ((pkt_attr_selectors->pkt_resolution != 0) ||
  25304                 (pkt_attr_selectors->svp_type != 0) ||
  25305                 (pkt_attr_selectors->drop != 0))   {
  25306             (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map])++;
  25307             cmprsd_attr_maps->pkt_resolution = 1;
  25308             cmprsd_attr_maps->svp_type = 1;
  25309             cmprsd_attr_maps->drop = 1;
  25310         }
  25311     }
  25312     return BCM_E_NONE;
  25313 }
  25314 
  25315 /*
  25316  * Function:
  25317  *      _bcm_esw_global_policer_offset_mode_update
  25318  * Purpose:
  25319  *      Update global_meter_offset_mode information based on values retrieve
  25320  *      from scache on warmboot
  25321  * Parameters:
  25322  *     unit                  - (IN) unit number
  25323  *     mode                  - (IN) meter offset mode
  25324  * Returns:
  25325  *     BCM_E_XXX
  25326  */
  25327 int _bcm_esw_global_policer_offset_mode_update(int unit, uint32 mode)
  25328 {
  25329     int rv;
  25330     uint32 offset;
  25331     uint32 width;
  25332     int udf_id;
  25333     uint32 num_selectors =0;
  25334     uint32 total_subdiv=0, sel, index=0, index1=0, sorted;
  25335     udf_pkt_attr_selectors_t *udf_pkt_attr = NULL;
  25336     bcm_policer_group_mode_attr_selector_t *attr_selectors = NULL;
  25337     bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb  = NULL;
  25338     uint8 udf_set_bits[SVC_METER_UDF1_MAX_BIT_POSITION] = {0};
  25339     bcm_policer_udf_sub_div_t dummy_data;
  25340     bcm_policer_udf_sub_div_t udf_subdiv[SVC_METER_UDF_MAX_SUB_DIVISIONS] = {{0,0,0}};
  25341     compressed_attr_selectors_t *cmprsd_attr_selectors = NULL;
  25342     bcm_policer_attr_selectors_t pkt_attr_selectors;
  25343     uint32 attr_count = 0;
  25344     uint32 total_policers = 0;
  25345     uint32 npolicers = 0;
  25346     uint32 port_attr_count = 0;
  25347     uint32 tos_dscp_attr_count = 0;
  25348     uint32 tos_ecn_attr_count = 0;
  25349     uint32 svp_type_attr_count = 0;
  25350 
  25351     num_selectors = global_meter_offset_mode[unit][mode].no_of_selectors;
  25352     attr_selectors_wb = global_meter_offset_mode[unit][mode].attr_selectors;
  25353     total_policers = global_meter_offset_mode[unit][mode].no_of_policers;
  25354     if ((global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \
  25355                         udf_mode) ||
  25356             (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \
  25357                         udf_cascade_mode) ||
  25358             (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \
  25359                         udf_cascade_with_coupling_mode)) {
  25360 
  25361         /* Re-populate udf_subdiv based on attr_selectors */
  25362         udf_pkt_attr = &(global_meter_offset_mode[unit][mode].meter_attr.
  25363                                 udf_pkt_attr_selectors_v);
  25364         for (sel = 0; sel < num_selectors; sel++) {
  25365             udf_id = attr_selectors_wb[sel].udf_id;
  25366             offset = attr_selectors_wb[sel].offset;
  25367             width = attr_selectors_wb[sel].width;
  25368 
  25369             if (udf_set_bits[offset] == 0) {
  25370                 index = total_subdiv;
  25371                 udf_subdiv[index].udf_id = udf_id;
  25372                 udf_subdiv[index].offset = offset;
  25373                 udf_subdiv[index].width = width;
  25374                 total_subdiv++;
  25375                 udf_set_bits[offset] = 1;
  25376             }
  25377         }
  25378 
  25379         /* Sort */
  25380         sorted = 0;
  25381         for (index = 0; index < SVC_METER_UDF1_MAX_BIT_POSITION; index++) {
  25382             if (udf_set_bits[index] == 1) {
  25383                 for (index1 = sorted; index1 < total_subdiv; index1++) {
  25384                     if (udf_subdiv[index1].offset == index) {
  25385                         /* Swap to rearrange */
  25386                         sal_memcpy(&dummy_data, &udf_subdiv[index1],
  25387                                 sizeof (bcm_policer_udf_sub_div_t));
  25388                         sal_memcpy(&udf_subdiv[index1],
  25389                                 &udf_subdiv[sorted],
  25390                                 sizeof(bcm_policer_udf_sub_div_t));
  25391                         sal_memcpy(&udf_subdiv[sorted], &dummy_data,
  25392                                 sizeof (bcm_policer_udf_sub_div_t));
  25393                         sorted++;
  25394                         break;
  25395                     }
  25396                 }
  25397             }
  25398         }
  25399         /* Save */
  25400         memcpy (&(udf_pkt_attr->udf_subdiv[0]), &udf_subdiv[0], sizeof(udf_subdiv));
  25401         udf_pkt_attr->total_subdiv = total_subdiv;
  25402     } else if (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v ==
  25403             compressed_mode) {
  25404 
  25405         /* If attr_selectors is NULL, update reference count from pkt_attr_bits_v */
  25406         if (attr_selectors_wb == NULL) {
  25407             cmprsd_attr_selectors = &(global_meter_offset_mode[unit][mode].
  25408                     meter_attr.compressed_attr_selectors_v);
  25409             return _bcm_esw_svm_pkt_compressed_attr_maps_reference(unit,
  25410                         cmprsd_attr_selectors, NULL);
  25411         }
  25412 
  25413         npolicers = total_policers;
  25414         if (global_meter_offset_mode[unit][mode].type ==
  25415                 bcmPolicerGroupModeTypeCascadeWithCoupling) {
  25416             npolicers = total_policers/2;
  25417         }
  25418         sal_memset(&pkt_attr_selectors, 0, sizeof(bcm_policer_attr_selectors_t));
  25419         pkt_attr_selectors.combine_attr_data =
  25420             sal_alloc(sizeof(bcm_policer_combine_attr_t) * npolicers,
  25421                     "combine attributes");
  25422         if (pkt_attr_selectors.combine_attr_data == NULL) {
  25423             return BCM_E_MEMORY;
  25424         }
  25425         sal_memset(pkt_attr_selectors.combine_attr_data, 0,
  25426                 sizeof(bcm_policer_combine_attr_t) * npolicers);
  25427 
  25428         /*
  25429          * allocate temp memory for convert attr_selectors_wb to attr_selectors
  25430          * _bcm_esw_policer_group_mode_fillup_values
  25431          */
  25432         attr_selectors = sal_alloc(
  25433                 sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors,
  25434                 "bcm_policer_group_mode_attr_selector_t");
  25435         if (attr_selectors == NULL) {
  25436             return BCM_E_MEMORY;
  25437         }
  25438         sal_memset(attr_selectors, 0,
  25439             sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors);
  25440 
  25441         rv = _bcm_wb_attr_selectors_copy_to_attr_selectors(
  25442                     num_selectors, attr_selectors_wb, attr_selectors);
  25443         if (BCM_FAILURE(rv)) {
  25444             sal_free(attr_selectors);
  25445             return (rv);
  25446         }
  25447 
  25448         _bcm_esw_policer_group_mode_fillup_values (unit, 0,
  25449                 global_meter_offset_mode[unit][mode].type,
  25450                 npolicers, num_selectors, attr_selectors, &pkt_attr_selectors);
  25451         sal_free(attr_selectors);
  25452         /* Update reference counts . */
  25453         (void) _bcm_esw_svm_pkt_compressed_attr_maps_reference(unit,
  25454                 NULL, &pkt_attr_selectors);
  25455 
  25456         cmprsd_attr_selectors = &(global_meter_offset_mode[unit][mode].
  25457                 meter_attr.compressed_attr_selectors_v);
  25458         sal_memset (&cmprsd_attr_selectors->pkt_attr_bits_v, 0,
  25459                 sizeof(cmprsd_attr_selectors->pkt_attr_bits_v));
  25460         if (pkt_attr_selectors.cng != 0) {
  25461             attr_count = _shr_popcount(pkt_attr_selectors.combine_cng_flags);
  25462             cmprsd_attr_selectors->pkt_attr_bits_v.cng =
  25463                 _bcm_policer_num_of_bits_get(attr_count);
  25464         }
  25465         if (pkt_attr_selectors.int_pri != 0) {
  25466             attr_count = _shr_popcount(pkt_attr_selectors.combine_int_pri_flags);
  25467             cmprsd_attr_selectors->pkt_attr_bits_v.int_pri =
  25468                 _bcm_policer_num_of_bits_get(attr_count);
  25469         }
  25470         if (pkt_attr_selectors.vlan_format != 0) {
  25471             attr_count = _shr_popcount(pkt_attr_selectors.combine_vlan_format_flags);
  25472             cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format =
  25473                 _bcm_policer_num_of_bits_get(attr_count);
  25474         }
  25475         if (pkt_attr_selectors.outer_dot1p != 0) {
  25476             attr_count = _shr_popcount(pkt_attr_selectors.combine_outer_dot1p_flags);
  25477             cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p =
  25478                 _bcm_policer_num_of_bits_get(attr_count);
  25479         }
  25480         if (pkt_attr_selectors.inner_dot1p != 0) {
  25481             attr_count = _shr_popcount(pkt_attr_selectors.combine_inner_dot1p_flags);
  25482             cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p =
  25483                 _bcm_policer_num_of_bits_get(attr_count);
  25484         }
  25485         if (pkt_attr_selectors.pkt_resolution != 0) {
  25486             attr_count = _shr_popcount(pkt_attr_selectors.combine_pkt_res_flags);
  25487             cmprsd_attr_selectors->pkt_attr_bits_v.pkt_resolution =
  25488                 _bcm_policer_num_of_bits_get(attr_count);
  25489         }
  25490         if (pkt_attr_selectors.drop != 0) {
  25491             attr_count = _shr_popcount(pkt_attr_selectors.combine_drop_flags);
  25492             cmprsd_attr_selectors->pkt_attr_bits_v.drop =
  25493                 _bcm_policer_num_of_bits_get(attr_count);
  25494         }
  25495         if (pkt_attr_selectors.int_pri != 0) {
  25496             attr_count = _shr_popcount(pkt_attr_selectors.combine_ip_pkt_flags);
  25497             cmprsd_attr_selectors->pkt_attr_bits_v.int_pri =
  25498                 _bcm_policer_num_of_bits_get(attr_count);
  25499         }
  25500         for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) {
  25501             port_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array
  25502                     [_bcmPolicerAttrPort][index]);
  25503             tos_dscp_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array
  25504                     [_bcmPolicerAttrTosDscp][index]);
  25505             tos_ecn_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array
  25506                     [_bcmPolicerAttrTosEcn][index]);
  25507             svp_type_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array
  25508                     [_bcmPolicerAttrSvpType][index]);
  25509         }
  25510         cmprsd_attr_selectors->pkt_attr_bits_v.ing_port =
  25511             _bcm_policer_num_of_bits_get(port_attr_count);
  25512         cmprsd_attr_selectors->pkt_attr_bits_v.tos =
  25513             _bcm_policer_num_of_bits_get(tos_dscp_attr_count);
  25514         cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn =
  25515             _bcm_policer_num_of_bits_get(tos_ecn_attr_count);
  25516         cmprsd_attr_selectors->pkt_attr_bits_v.svp_type =
  25517             _bcm_policer_num_of_bits_get(svp_type_attr_count);
  25518 
  25519         sal_free(pkt_attr_selectors.combine_attr_data);
  25520     }
  25521     return BCM_E_NONE;
  25522 }
  25523 
  25524 /*
  25525  * Function:
  25526  *      _bcm_esw_global_meter_offset_mode_reinit
  25527  * Purpose:
  25528  *      Recover the service meter offset mode configuration information
  25529  *      from HW on warm boot
  25530  * Parameters:
  25531  *     unit                  - (IN) unit number
  25532  * Returns:
  25533  *     BCM_E_XXX
  25534  */
  25535 int _bcm_esw_global_meter_offset_mode_reinit(int unit)
  25536 {
  25537     int rv = BCM_E_NONE;
  25538     int mode = 0;
  25539     bcm_policer_group_mode_t          group_mode = 0;
  25540     int                               npolicers = 0;
  25541     uint64 selector_key_value;
  25542     uint32 selector_count = 0, index = 0;
  25543     uint32 selector_for_bit_x_en_field_value[8] = {0};
  25544     uint32 selector_for_bit_x_en_field_name[8] = {
  25545                 SELECTOR_0_ENf,
  25546                 SELECTOR_1_ENf,
  25547                 SELECTOR_2_ENf,
  25548                 SELECTOR_3_ENf,
  25549                 SELECTOR_4_ENf,
  25550                 SELECTOR_5_ENf,
  25551                 SELECTOR_6_ENf,
  25552                 SELECTOR_7_ENf,
  25553     };
  25554     uint32  selector_for_bit_x_field_value[8] = {0};
  25555     uint32  selector_for_bit_x_field_name[8] = {
  25556                 SELECTOR_FOR_BIT_0f,
  25557                 SELECTOR_FOR_BIT_1f,
  25558                 SELECTOR_FOR_BIT_2f,
  25559                 SELECTOR_FOR_BIT_3f,
  25560                 SELECTOR_FOR_BIT_4f,
  25561                 SELECTOR_FOR_BIT_5f,
  25562                 SELECTOR_FOR_BIT_6f,
  25563                 SELECTOR_FOR_BIT_7f,
  25564     };
  25565     bcm_policer_svc_meter_mode_type_t mode_type = 0;
  25566 
  25567     COMPILER_64_ZERO(selector_key_value);
  25568     for (mode = 1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) {
  25569         BCM_IF_ERROR_RETURN(soc_reg64_get(unit,
  25570                                           _pkt_attr_sel_key_reg[mode],
  25571                                           REG_PORT_ANY,
  25572                                           0,
  25573                                           &selector_key_value)
  25574                             );
  25575         if (!COMPILER_64_IS_ZERO(selector_key_value))
  25576         {
  25577             for (selector_count = 0, index = 0; index < 8; index++)
  25578             {
  25579                 selector_for_bit_x_en_field_value[index] = soc_reg64_field32_get(
  25580                         unit,
  25581                         _pkt_attr_sel_key_reg[mode],
  25582                         selector_key_value,
  25583                         selector_for_bit_x_en_field_name[index]);
  25584                 selector_count += selector_for_bit_x_en_field_value[index];
  25585                 selector_for_bit_x_field_value[index] = 0;
  25586                 if (selector_for_bit_x_en_field_value[index] != 0)
  25587                 {
  25588                           selector_for_bit_x_field_value[index] =
  25589                                   soc_reg64_field32_get(
  25590                                      unit,
  25591                                      _pkt_attr_sel_key_reg[mode],
  25592                                      selector_key_value,
  25593                                      selector_for_bit_x_field_name[index]);
  25594                 }
  25595             }
  25596 
  25597             if (soc_reg64_field32_get(unit,
  25598                                      _pkt_attr_sel_key_reg[mode],
  25599                                       selector_key_value, USE_UDF_KEYf))
  25600             {
  25601                 mode_type = udf_mode;
  25602                 rv =  _bcm_esw_global_meter_udf_offset_mode_reinit(unit, mode,
  25603                              selector_count, selector_for_bit_x_en_field_value,
  25604                                               selector_for_bit_x_field_value);
  25605                 if (BCM_FAILURE(rv)) {
  25606                    LOG_DEBUG(BSL_LS_BCM_POLICER,
  25607                              (BSL_META_U(unit,
  25608                                          "Unable to re-init UDF offset mode\n")));
  25609                    return (rv);
  25610                 }
  25611             } else if (soc_reg64_field32_get(unit,
  25612                                    _pkt_attr_sel_key_reg[mode],
  25613                                    selector_key_value,
  25614                                    USE_COMPRESSED_PKT_KEYf))
  25615             {
  25616                 rv =  _bcm_esw_global_meter_compressed_offset_mode_reinit(unit,
  25617                                           mode, selector_count,
  25618                                           selector_for_bit_x_en_field_value,
  25619                                           selector_for_bit_x_field_value);
  25620                 if (BCM_FAILURE(rv)) {
  25621                    LOG_DEBUG(BSL_LS_BCM_POLICER,
  25622                              (BSL_META_U(unit,
  25623                                          "Unable to re-init compressed offset "
  25624                                          "mode\n")));
  25625                    return (rv);
  25626                 }
  25627             } else {
  25628                 rv = _bcm_esw_global_meter_uncompressed_offset_mode_reinit(
  25629                          unit, mode, selector_count,
  25630                          selector_for_bit_x_en_field_value,
  25631                          selector_for_bit_x_field_value);
  25632                 if (BCM_FAILURE(rv)) {
  25633                    LOG_VERBOSE(BSL_LS_BCM_POLICER,
  25634                                (BSL_META_U(unit,
  25635                                            "Unable to re-init uncompressed offset "
  25636                                            "mode\n")));
  25637                    return (rv);
  25638                 }
  25639             }
  25640             /* get the number of policers allocated for this mode */
  25641             /* Warmboot version BCM_WB_VERSION_1_1 onwards, npolicers and
  25642                group_mode are stored in scache. This function call is still
  25643                left here for backward compatibility */
  25644             rv = _bcm_esw_policer_get_offset_table_policer_count(unit,
  25645                                               mode, &group_mode, &npolicers);
  25646             if (BCM_FAILURE(rv)) {
  25647                LOG_DEBUG(BSL_LS_BCM_POLICER,
  25648                          (BSL_META_U(unit,
  25649                                      "Unable to re-init number of policers "
  25650                                      "to be allcated in this mode\n")));
  25651                return (rv);
  25652             }
  25653 
  25654             /* If npolicers is ZERO, group mode is also not stored  */
  25655             if (npolicers == 0)  {
  25656                 continue;
  25657             }
  25658             global_meter_offset_mode[unit][mode].no_of_policers = npolicers;
  25659             global_meter_offset_mode[unit][mode].group_mode = group_mode;
  25660             if ((group_mode == bcmPolicerGroupModeCascade) ||
  25661                 (group_mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  25662                 (group_mode == bcmPolicerGroupModeCascadeDroppedPktExclude) ||
  25663                 (group_mode == bcmPolicerGroupModeIntPriCascade) ||
  25664                 (group_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  25665                 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v =
  25666                                                                cascade_mode;
  25667             }
  25668             if (mode_type == udf_cascade_mode) {
  25669                 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v =
  25670                                                                udf_cascade_mode;
  25671             }
  25672             if (mode_type == udf_cascade_with_coupling_mode) {
  25673                 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v =
  25674                                                  udf_cascade_with_coupling_mode;
  25675             }
  25676         }
  25677     }
  25678     return rv;
  25679 }
  25680 
  25681 /*
  25682  * Function:
  25683  *      _bcm_esw_global_meter_action_reinit
  25684  * Purpose:
  25685  *      Recover the policer action table entries on warm boot
  25686  * Parameters:
  25687  *     unit                  - (IN) unit number
  25688  * Returns:
  25689  *     BCM_E_XXX
  25690  */
  25691 int _bcm_esw_global_meter_action_reinit(int unit)
  25692 {
  25693     int rv = BCM_E_NONE;
  25694     int total_size = SOC_INFO(unit).global_meter_action_size;
  25695 
  25696     GLOBAL_METER_LOCK(unit);
  25697         rv = _bcm_esw_svm_source_traverse (unit, SVM_POLICY_TABLEm, -1, total_size - 1,
  25698                 _bcm_esw_svm_action_reinit_from_table, NULL);
  25699     GLOBAL_METER_UNLOCK(unit);
  25700     return rv;
  25701 }
  25702 
  25703 /*
  25704  * Function:
  25705  *      _bcm_esw_svm_pkt_compressed_attr_maps_sync
  25706  * Purpose:
  25707  *      Sync compressed attr maps to scache.
  25708  * Parameters:
  25709  *     unit                  - (IN) unit number
  25710  *     scache_position       - (IN/OUT) Scache position
  25711  * Returns:
  25712  *     BCM_E_XXX
  25713  */
  25714 int
  25715 _bcm_esw_svm_pkt_compressed_attr_maps_sync(int unit, uint8 **scache_position)
  25716 {
  25717     int i = 0;
  25718     uint8 *scache_ptr = NULL;
  25719     uint32 array_size = 0;
  25720     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_map = NULL;
  25721 
  25722     scache_ptr = *scache_position;
  25723 
  25724     cmprsd_attr_map = svm_pkt_compressed_attr_maps_g[unit];
  25725 
  25726     if (cmprsd_attr_map->cng != 0) {
  25727         sal_memcpy(scache_ptr,
  25728                 &cmprsd_attr_map->combine_cng_flags,
  25729                 sizeof(uint32));
  25730     } else {
  25731         sal_memset(scache_ptr, 0, sizeof(uint32));
  25732     }
  25733     scache_ptr += sizeof(uint32);
  25734 
  25735     if (cmprsd_attr_map->int_pri != 0) {
  25736         sal_memcpy(scache_ptr,
  25737                 &cmprsd_attr_map->combine_int_pri_flags,
  25738                 sizeof(uint32));
  25739     } else {
  25740         sal_memset(scache_ptr, 0, sizeof(uint32));
  25741     }
  25742     scache_ptr += sizeof(uint32);
  25743 
  25744     if (cmprsd_attr_map->vlan_format != 0) {
  25745         sal_memcpy(scache_ptr,
  25746                 &cmprsd_attr_map->combine_vlan_format_flags,
  25747                 sizeof(uint32));
  25748     } else {
  25749         sal_memset(scache_ptr, 0, sizeof(uint32));
  25750     }
  25751     scache_ptr += sizeof(uint32);
  25752 
  25753     if (cmprsd_attr_map->outer_dot1p != 0) {
  25754         sal_memcpy(scache_ptr,
  25755                 &cmprsd_attr_map->combine_outer_dot1p_flags,
  25756                 sizeof(uint32));
  25757     } else {
  25758         sal_memset(scache_ptr, 0, sizeof(uint32));
  25759     }
  25760     scache_ptr += sizeof(uint32);
  25761 
  25762     if (cmprsd_attr_map->inner_dot1p != 0) {
  25763         sal_memcpy(scache_ptr,
  25764                 &cmprsd_attr_map->combine_inner_dot1p_flags,
  25765                 sizeof(uint32));
  25766     } else {
  25767         sal_memset(scache_ptr, 0, sizeof(uint32));
  25768     }
  25769     scache_ptr += sizeof(uint32);
  25770 
  25771     if (cmprsd_attr_map->pkt_resolution != 0) {
  25772         sal_memcpy(scache_ptr,
  25773                 &cmprsd_attr_map->combine_pkt_res_flags,
  25774                 sizeof(uint32));
  25775     } else {
  25776         sal_memset(scache_ptr, 0, sizeof(uint32));
  25777     }
  25778     scache_ptr += sizeof(uint32);
  25779 
  25780     if (cmprsd_attr_map->drop != 0) {
  25781         sal_memcpy(scache_ptr,
  25782                 &cmprsd_attr_map->combine_drop_flags,
  25783                 sizeof(uint32));
  25784     } else {
  25785         sal_memset(scache_ptr, 0, sizeof(uint32));
  25786     }
  25787     scache_ptr += sizeof(uint32);
  25788 
  25789     if (cmprsd_attr_map->ip_pkt != 0) {
  25790         sal_memcpy(scache_ptr,
  25791                 &cmprsd_attr_map->combine_ip_pkt_flags,
  25792                 sizeof(uint32));
  25793     } else {
  25794         sal_memset(scache_ptr, 0, sizeof(uint32));
  25795     }
  25796     scache_ptr += sizeof(uint32);
  25797 
  25798     /* Syncing Attributes which are array. */
  25799     if (cmprsd_attr_map->port != 0) {
  25800         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25801         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25802         scache_ptr += sizeof(uint32);
  25803         for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  25804             sal_memcpy(scache_ptr,
  25805                 &cmprsd_attr_map->combine_value_array
  25806                 [_bcmPolicerAttrPort][i], sizeof(uint32));
  25807             scache_ptr += sizeof(uint32);
  25808         }
  25809     } else {
  25810         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25811         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25812         scache_ptr += sizeof(uint32);
  25813         sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25814         scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25815     }
  25816 
  25817     if (cmprsd_attr_map->tos_dscp != 0) {
  25818         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25819         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25820         scache_ptr += sizeof(uint32);
  25821         for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  25822             sal_memcpy(scache_ptr,
  25823                 &cmprsd_attr_map->combine_value_array
  25824                 [_bcmPolicerAttrTosDscp][i], sizeof(uint32));
  25825             scache_ptr += sizeof(uint32);
  25826         }
  25827     } else {
  25828         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25829         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25830         scache_ptr += sizeof(uint32);
  25831         sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25832         scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25833     }
  25834 
  25835     if (cmprsd_attr_map->tos_ecn != 0) {
  25836         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25837         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25838         scache_ptr += sizeof(uint32);
  25839         for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  25840             sal_memcpy(scache_ptr,
  25841                 &cmprsd_attr_map->combine_value_array
  25842                 [_bcmPolicerAttrTosEcn][i],
  25843                 sizeof(uint32));
  25844             scache_ptr += sizeof(uint32);
  25845         }
  25846     } else {
  25847         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25848         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25849         scache_ptr += sizeof(uint32);
  25850         sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25851         scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25852     }
  25853 
  25854     if (cmprsd_attr_map->svp_type != 0) {
  25855         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25856         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25857         scache_ptr += sizeof(uint32);
  25858         for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) {
  25859             sal_memcpy(scache_ptr,
  25860                 &cmprsd_attr_map->combine_value_array
  25861                 [_bcmPolicerAttrSvpType][i],
  25862                 sizeof(uint32));
  25863             scache_ptr += sizeof(uint32);
  25864         }
  25865     } else {
  25866         array_size = _BCM_POLICER_BIT_ARRAY_SIZE;
  25867         sal_memcpy(scache_ptr, &array_size, sizeof(uint32));
  25868         scache_ptr += sizeof(uint32);
  25869         sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25870         scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE);
  25871     }
  25872 
  25873     *scache_position = scache_ptr;
  25874 
  25875     return BCM_E_NONE;
  25876 }
  25877 
  25878 /*
  25879  * Function:
  25880  *      _bcm_esw_global_meter_policer_sync
  25881  * Purpose:
  25882  *      Write poliers which are created but not yet used in any
  25883  *      table to scache so that we can recover the configuration
  25884  *      on warm boot
  25885  * Parameters:
  25886  *     unit                  - (IN) unit number
  25887  * Returns:
  25888  *     BCM_E_XXX
  25889  */
  25890 int
  25891 _bcm_esw_global_meter_policer_sync(int unit)
  25892 {
  25893     int    rv = BCM_E_NONE;
  25894     soc_scache_handle_t scache_handle;
  25895     _global_meter_policer_control_t *global_meter_pl = NULL;
  25896     uint32 hash_index;      /* Entry hash  */
  25897     int policer_id = 0;
  25898     uint8  *policer_state = NULL;
  25899     uint32 npolicers, group, udf_id;
  25900     uint8 type;
  25901     int mode;
  25902     int size = 0, count = 0;
  25903     bcm_policer_svc_meter_attr_t *meter_attr = NULL;
  25904     bcm_policer_group_mode_attr_selectors_info_t *attr_selectors_info = NULL;
  25905 
  25906 #if defined(BCM_GLOBAL_METER_V2_SUPPORT)
  25907     if (soc_feature(unit, soc_feature_global_meter_v2)) {
  25908         return bcmi_esw_global_meter_policer_sync(unit);
  25909     }
  25910 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */
  25911 
  25912     if (!soc_feature(unit, soc_feature_global_meter)) {
  25913         return BCM_E_UNAVAIL;
  25914     }
  25915 
  25916     CHECK_GLOBAL_METER_INIT(unit);
  25917     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
  25918 
  25919     BCM_IF_ERROR_RETURN(_bcm_esw_svc_meter_wb_size_calc(unit, &size));
  25920     SOC_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle,
  25921                           FALSE, size, &policer_state,
  25922                           BCM_WB_DEFAULT_VERSION, NULL));
  25923 
  25924     if (NULL == policer_state) {
  25925         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  25926                     (BSL_META_U(unit,
  25927                                 "SCACHE Memory not available \n")));
  25928         return BCM_E_MEMORY;
  25929     }
  25930 
  25931     attr_selectors_info =
  25932         sal_alloc(sizeof(bcm_policer_group_mode_attr_selectors_info_t),
  25933         "attr selector info");
  25934     if (NULL == attr_selectors_info) {
  25935         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  25936                     (BSL_META_U(unit,
  25937                                 "Memory not available \n")));
  25938         return BCM_E_MEMORY;
  25939     }
  25940     sal_memset(attr_selectors_info, 0,
  25941             sizeof(bcm_policer_group_mode_attr_selectors_info_t));
  25942 
  25943     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1)   {
  25944         /* Iterate through global_meter_offset_mode to store
  25945            npolicers,group_mode,udf_id */
  25946         for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++)   {
  25947             if (global_meter_offset_mode[unit][mode].used == 1) {
  25948                 npolicers = global_meter_offset_mode[unit][mode].no_of_policers;
  25949                 sal_memcpy(policer_state, &npolicers, sizeof(uint32));
  25950                 policer_state += sizeof(uint32);
  25951 
  25952                 /* Using same 32-bit for saving group mode and type.
  25953                  * group mode (0-23), type (24-31) */
  25954                 group = (uint32)global_meter_offset_mode[unit][mode].group_mode;
  25955                 type = (global_meter_offset_mode[unit][mode].type == -1) ?
  25956                         0 : (global_meter_offset_mode[unit][mode].type + 1);
  25957                 group |= (type << BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_SHIFT);
  25958                 sal_memcpy(policer_state, &group, sizeof(uint32));
  25959                 policer_state += sizeof(uint32);
  25960 
  25961                 meter_attr = &global_meter_offset_mode[unit][mode].meter_attr;
  25962                 udf_id = meter_attr->udf_pkt_attr_selectors_v.udf_id;
  25963                 sal_memcpy(policer_state, &udf_id, sizeof(uint32));
  25964                 policer_state += sizeof(uint32);
  25965 
  25966                 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
  25967                     if (global_meter_offset_mode[unit][mode].type == -1) {
  25968                         sal_memset(policer_state, 0,
  25969                             sizeof(bcm_policer_group_mode_attr_selectors_info_t));
  25970                         policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t);
  25971                         continue;
  25972                     }
  25973 
  25974                     /*Save attr_selectors info */
  25975                     if (global_meter_offset_mode[unit][mode].attr_selectors != NULL) {
  25976                         attr_selectors_info->flags = 0;
  25977                         attr_selectors_info->num_selectors =
  25978                             global_meter_offset_mode[unit][mode].no_of_selectors;
  25979                         sal_memcpy(&(attr_selectors_info->attr_selectors)[0],
  25980                                 &global_meter_offset_mode[unit][mode].attr_selectors[0],
  25981                                 sizeof(bcm_policer_group_mode_attr_selector_wb_t) * \
  25982                                 attr_selectors_info->num_selectors);
  25983                         sal_memcpy(policer_state, attr_selectors_info,
  25984                                 sizeof(bcm_policer_group_mode_attr_selectors_info_t));
  25985                     }
  25986                     policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t);
  25987                 }
  25988             }
  25989         }
  25990     }
  25991 
  25992     if (NULL != attr_selectors_info) {
  25993         sal_free(attr_selectors_info);
  25994     }
  25995 
  25996     /* go through policer control bookkeep structure and get policer
  25997        entries with ref_count=0 */
  25998     for (hash_index = 0; hash_index < _GLOBAL_METER_HASH_SIZE; hash_index++) {
  25999         global_meter_pl  =  global_meter_policer_bookkeep[unit][hash_index];
  26000         while ((NULL != global_meter_pl) &&
  26001                       (count < BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES)) {
  26002             /* Match entry id. */
  26003             if (global_meter_pl->ref_count == 0) {
  26004                 policer_id  = global_meter_pl->pid;
  26005                 sal_memcpy(policer_state, &policer_id, sizeof(bcm_policer_t));
  26006                 policer_state += sizeof(bcm_policer_t);
  26007                 count++;
  26008             }
  26009             global_meter_pl = global_meter_pl->next;
  26010         }
  26011         if (count == BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES) {
  26012             return rv;
  26013         }
  26014     }
  26015     policer_state +=
  26016         (sizeof(bcm_policer_t) * (BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES - count));
  26017 
  26018     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) {
  26019         if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  26020             BCM_IF_ERROR_RETURN(_bcm_esw_svm_pkt_compressed_attr_maps_sync(unit,
  26021                     &policer_state));
  26022         }
  26023     }
  26024     return rv;
  26025 }
  26026 
  26027 /*
  26028  * Function:
  26029  *      _bcm_esw_svm_pkt_compressed_attr_maps_recover
  26030  * Purpose:
  26031  *      Recover compressed attr maps from scache.
  26032  * Parameters:
  26033  *     unit                  - (IN) unit number
  26034  *     recovered_ver         - (IN) recovered wb version
  26035  *     scache_position       - (IN/OUT) Scache position
  26036  * Returns:
  26037  *     BCM_E_XXX
  26038  */
  26039 int _bcm_esw_svm_pkt_compressed_attr_maps_recover(int unit,
  26040     uint16 recovered_ver,
  26041     uint8 **scache_position)
  26042 {
  26043     int i = 0;
  26044     uint8 *scache_ptr = NULL;
  26045     uint32 array_size = 0;
  26046     _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL;
  26047 
  26048     scache_ptr = *scache_position;
  26049 
  26050     cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit];
  26051 
  26052     /* combine_cng_flags. */
  26053     sal_memcpy(&cmprsd_attr_maps->combine_cng_flags,
  26054             scache_ptr, sizeof(uint32));
  26055     scache_ptr += sizeof(uint32);
  26056 
  26057     /* combine_int_pri_flags */
  26058     sal_memcpy(&cmprsd_attr_maps->combine_int_pri_flags,
  26059             scache_ptr, sizeof(uint32));
  26060     scache_ptr += sizeof(uint32);
  26061 
  26062     /* combine_vlan_format_flags */
  26063     sal_memcpy(&cmprsd_attr_maps->combine_vlan_format_flags,
  26064             scache_ptr, sizeof(uint32));
  26065     scache_ptr += sizeof(uint32);
  26066 
  26067     /* combine_outer_dot1p_flags */
  26068     sal_memcpy(&cmprsd_attr_maps->combine_outer_dot1p_flags,
  26069             scache_ptr, sizeof(uint32));
  26070     scache_ptr += sizeof(uint32);
  26071 
  26072     /* combine_inner_dot1p_flags */
  26073     sal_memcpy(&cmprsd_attr_maps->combine_inner_dot1p_flags,
  26074             scache_ptr, sizeof(uint32));
  26075     scache_ptr += sizeof(uint32);
  26076 
  26077     /* combine_pkt_res_flags */
  26078     sal_memcpy(&cmprsd_attr_maps->combine_pkt_res_flags,
  26079             scache_ptr, sizeof(uint32));
  26080     scache_ptr += sizeof(uint32);
  26081 
  26082     /* combine_drop_flags */
  26083     sal_memcpy(&cmprsd_attr_maps->combine_drop_flags,
  26084             scache_ptr, sizeof(uint32));
  26085     scache_ptr += sizeof(uint32);
  26086 
  26087     /* combine_ip_pkt_flags */
  26088     sal_memcpy(&cmprsd_attr_maps->combine_ip_pkt_flags,
  26089             scache_ptr, sizeof(uint32));
  26090     scache_ptr += sizeof(uint32);
  26091 
  26092     /* Recovering Attributes which are array. */
  26093     sal_memcpy(&array_size, scache_ptr, sizeof(uint32));
  26094     scache_ptr += sizeof(uint32);
  26095     for(i = 0; i < array_size; i++) {
  26096         sal_memcpy(&cmprsd_attr_maps->combine_value_array
  26097                 [_bcmPolicerAttrPort][i], scache_ptr, sizeof(uint32));
  26098         scache_ptr += sizeof(uint32);
  26099     }
  26100     sal_memcpy(&array_size, scache_ptr, sizeof(uint32));
  26101     scache_ptr += sizeof(uint32);
  26102     for(i = 0; i < array_size; i++) {
  26103         sal_memcpy(&cmprsd_attr_maps->combine_value_array
  26104                 [_bcmPolicerAttrTosDscp][i], scache_ptr, sizeof(uint32));
  26105         scache_ptr += sizeof(uint32);
  26106     }
  26107     sal_memcpy(&array_size, scache_ptr, sizeof(uint32));
  26108     scache_ptr += sizeof(uint32);
  26109     for(i = 0; i < array_size; i++) {
  26110         sal_memcpy(&cmprsd_attr_maps->combine_value_array
  26111                 [_bcmPolicerAttrTosEcn][i], scache_ptr, sizeof(uint32));
  26112         scache_ptr += sizeof(uint32);
  26113     }
  26114     sal_memcpy(&array_size, scache_ptr, sizeof(uint32));
  26115     scache_ptr += sizeof(uint32);
  26116     for(i = 0; i < array_size; i++) {
  26117         sal_memcpy(&cmprsd_attr_maps->combine_value_array
  26118                 [_bcmPolicerAttrSvpType][i], scache_ptr, sizeof(uint32));
  26119         scache_ptr += sizeof(uint32);
  26120     }
  26121 
  26122     *scache_position = scache_ptr;
  26123 
  26124     return BCM_E_NONE;
  26125 }
  26126 
  26127 /*
  26128  * Function:
  26129  *      _bcm_esw_global_meter_policer_recover_from_scache
  26130  * Purpose:
  26131  *     Recover policers which are not configured in HW from
  26132  *     Scache as part of warm boot
  26133  * Parameters:
  26134  *     unit                  - (IN) unit number
  26135  * Returns:
  26136  *     BCM_E_XXX
  26137  */
  26138 int _bcm_esw_global_meter_policer_recover_from_scache(int unit)
  26139 {
  26140     int    rv = BCM_E_NONE;
  26141     int    stable_size;
  26142     uint16 recovered_ver;
  26143     int policer_id = 0;
  26144     uint8  *policer_state = NULL;
  26145     uint32 npolicers, udf_id;
  26146     uint32 group = 0;
  26147     uint8 type = 0;
  26148     int mode=0;
  26149     int size = 0, scache_index = 0;
  26150     uint32 num_selectors = 0;
  26151     soc_scache_handle_t scache_handle;
  26152     _global_meter_policer_control_t *policer_control = NULL;
  26153     bcm_policer_svc_meter_attr_t *meter_attr = NULL;
  26154     bcm_policer_group_mode_attr_selectors_info_t *attr_sel_info;
  26155     bcm_policer_group_mode_t group_mode;
  26156 
  26157     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0);
  26158     BCM_IF_ERROR_RETURN(_bcm_esw_svc_meter_wb_size_calc(unit, &size));
  26159 
  26160     if (SOC_WARM_BOOT(unit)) {
  26161         /* Warm Boot */
  26162         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  26163         if (stable_size > size) {
  26164             SOC_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle,
  26165                         FALSE, size, &policer_state,
  26166                         BCM_WB_DEFAULT_VERSION, &recovered_ver));
  26167 
  26168             if (NULL == policer_state) {
  26169                 LOG_DEBUG(BSL_LS_BCM_POLICER,
  26170                         (BSL_META_U(unit,
  26171                                     "SCACHE Memory not available \n")));
  26172                 return BCM_E_MEMORY;
  26173             }
  26174 
  26175             /* Read from scache and populate fields for global_meter_offset_mode first */
  26176             if (recovered_ver >= BCM_WB_VERSION_1_1)  {
  26177                 for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++)   {
  26178                     if (global_meter_offset_mode[unit][mode].used == 1) {
  26179                         sal_memcpy(&npolicers, policer_state, sizeof(uint32));
  26180                         global_meter_offset_mode[unit][mode].no_of_policers = npolicers;
  26181                         policer_state += (sizeof(uint32));
  26182 
  26183                         sal_memcpy(&group, policer_state, sizeof(uint32));
  26184                         group_mode = (group & (~(BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_MASK)));
  26185                         global_meter_offset_mode[unit][mode].group_mode = group_mode;
  26186                         type = (group & BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_MASK) >>
  26187                                     BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_SHIFT;
  26188                         if (type == 0) {
  26189                             global_meter_offset_mode[unit][mode].type = -1;
  26190                         } else {
  26191                             global_meter_offset_mode[unit][mode].type = type - 1;
  26192                         }
  26193                         policer_state+=(sizeof(uint32));
  26194 
  26195                         meter_attr = &global_meter_offset_mode[unit][mode].meter_attr;
  26196                         sal_memcpy(&udf_id, policer_state, sizeof(uint32));
  26197                         meter_attr->udf_pkt_attr_selectors_v.udf_id = udf_id;
  26198                         policer_state += (sizeof(uint32));
  26199 
  26200                         if (recovered_ver >= BCM_WB_VERSION_1_2) {
  26201                             if (global_meter_offset_mode[unit][mode].type != -1) {
  26202                                 attr_sel_info = (bcm_policer_group_mode_attr_selectors_info_t *) policer_state;
  26203                                 num_selectors = attr_sel_info->num_selectors;
  26204                                 global_meter_offset_mode[unit][mode].no_of_selectors = num_selectors;
  26205 
  26206                                 if (num_selectors != 0) {
  26207                                     global_meter_offset_mode[unit][mode].attr_selectors =
  26208                                         sal_alloc(sizeof(bcm_policer_group_mode_attr_selector_wb_t) * num_selectors,
  26209                                                 "attr selector info");
  26210                                     if (global_meter_offset_mode[unit][mode].attr_selectors == NULL) {
  26211                                         _bcm_esw_global_meter_cleanup(unit);
  26212                                         return BCM_E_MEMORY;
  26213                                     }
  26214                                     sal_memcpy(&(global_meter_offset_mode[unit][mode].attr_selectors[0]),
  26215                                             &(attr_sel_info->attr_selectors[0]),
  26216                                             sizeof(bcm_policer_group_mode_attr_selector_wb_t) * num_selectors);
  26217                                 }
  26218                                 if (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v !=
  26219                                         compressed_mode) {
  26220                                     _bcm_esw_global_policer_offset_mode_update(unit, mode);
  26221                                 }
  26222                             }
  26223                             policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t);
  26224                         }
  26225                         /* handling mode_type_v/type for udf based policers */
  26226                         if (meter_attr->mode_type_v == udf_mode) {
  26227                             global_meter_offset_mode[unit][mode].type = bcmPolicerGroupModeTypeNormal;
  26228                             if (group_mode == bcmPolicerGroupModeCascade) {
  26229                                 meter_attr->mode_type_v = udf_cascade_mode;
  26230                                 global_meter_offset_mode[unit][mode].type =
  26231                                         bcmPolicerGroupModeTypeCascade;
  26232                             } else if (group_mode == bcmPolicerGroupModeCascadeWithCoupling) {
  26233                                 meter_attr->mode_type_v = udf_cascade_with_coupling_mode;
  26234                                 global_meter_offset_mode[unit][mode].type =
  26235                                         bcmPolicerGroupModeTypeCascadeWithCoupling;
  26236                             }
  26237                         } else if (global_meter_offset_mode[unit][mode].type != -1) {
  26238                             /* Here, for group type Cascade/CascadeWithCoupling, there is
  26239                              * no need to modfy mode_type_v. Lets keep it compressed/uncompressed. */
  26240                             ;
  26241                         } else {
  26242                             if ((group_mode == bcmPolicerGroupModeCascade) ||
  26243                                     (group_mode == bcmPolicerGroupModeCascadeWithCoupling) ||
  26244                                     (group_mode == bcmPolicerGroupModeIntPriCascade) ||
  26245                                     (group_mode == bcmPolicerGroupModeCascadeDroppedPktExclude) ||
  26246                                     (group_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) {
  26247                                 meter_attr->mode_type_v = cascade_mode;
  26248                             }
  26249                         }
  26250                     }
  26251                 }
  26252             }
  26253 
  26254             /*  read from scache and create policer bookkeep data structure */
  26255             for (scache_index = 0; scache_index <
  26256                     BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES; scache_index++) {
  26257                 sal_memcpy(&policer_id,
  26258                         &policer_state[scache_index * sizeof(int)],
  26259                         sizeof(int));
  26260                 if ((policer_id & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) {
  26261                     policer_control = NULL;
  26262                     rv = _bcm_esw_policer_config_from_meter_table(unit,
  26263                             policer_id, policer_control);
  26264                 }
  26265             }
  26266             policer_state += (BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES * sizeof(int));
  26267 
  26268             if (recovered_ver >= BCM_WB_VERSION_1_3) {
  26269                 if (soc_feature(unit, soc_feature_global_meter_compression_share)) {
  26270                     /* Recover combined flags for compressd mode */
  26271                     (void) _bcm_esw_svm_pkt_compressed_attr_maps_recover(unit,
  26272                                     recovered_ver, &policer_state);
  26273                 }
  26274             }
  26275 
  26276             /* Loop through all modes and update for compressed mode. */
  26277             for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++)   {
  26278                 if ((global_meter_offset_mode[unit][mode].used == 1) &&
  26279                     (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v ==
  26280                             compressed_mode)) {
  26281                     _bcm_esw_global_policer_offset_mode_update(unit, mode);
  26282                 }
  26283             }
  26284         }
  26285     } else {
  26286         /* Cold Boot */
  26287         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
  26288                 size, &policer_state,
  26289                 BCM_WB_DEFAULT_VERSION, NULL);
  26290         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  26291             LOG_DEBUG(BSL_LS_BCM_POLICER,
  26292                     (BSL_META_U(unit,
  26293                                 "Scache Memory not available\n")));
  26294             return rv;
  26295         }
  26296     }
  26297     return BCM_E_NONE;
  26298 }
  26299 
  26300 /*
  26301  * Function:
  26302  *      _bcm_esw_global_meter_reinit
  26303  * Purpose:
  26304  *      Reinit all the global meter internal data structures on warm boot
  26305  * Parameters:
  26306  *     unit                  - (IN) unit number
  26307  * Returns:
  26308  *     BCM_E_XXX
  26309  */
  26310 int _bcm_esw_global_meter_reinit(int unit)
  26311 {
  26312     int rv = BCM_E_NONE;
  26313 
  26314     rv =  _bcm_esw_global_meter_offset_mode_reinit(unit);
  26315     if (BCM_FAILURE(rv)) {
  26316         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  26317                     (BSL_META_U(unit,
  26318                                 "Unable to reinit offset modes\n")));
  26319         return (rv);
  26320     }
  26321     /* go through scache and recover policer configuration */
  26322     rv = _bcm_esw_global_meter_policer_recover_from_scache(unit);
  26323     if (BCM_FAILURE(rv)) {
  26324         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  26325                     (BSL_META_U(unit,
  26326                                 "Unable to reinit policer configuration\n")));
  26327         return (rv);
  26328     }
  26329     /* go through all policer entries to increment action reference count
  26330        and set policer configuration parameter */
  26331     rv = _bcm_policer_config_reinit(unit);
  26332     if (BCM_FAILURE(rv)) {
  26333         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  26334                     (BSL_META_U(unit,
  26335                                 "Unable to reinit policer configuration\n")));
  26336         return (rv);
  26337     }
  26338     /* reinit action table bookkeep data structure */
  26339     rv =  _bcm_esw_global_meter_action_reinit(unit);
  26340     if (BCM_FAILURE(rv)) {
  26341         LOG_VERBOSE(BSL_LS_BCM_POLICER,
  26342                     (BSL_META_U(unit,
  26343                                 "Unable to reinit meter action configuration\n")));
  26344         return (rv);
  26345     }
  26346     return BCM_E_NONE;
  26347 }
  26348 
  26349 #endif /* BCM_WARM_BOOT_SUPPORT */
  26350 
  26351