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

oam.c (851668B)


      1  /* 
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * File:
      7  *  oam.c
      8  *
      9  * Purpose:
     10  *  OAM implementation for Triumph3 family of devices.
     11  */
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/core/libc.h>
     15 #include <soc/defs.h>
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/profile_mem.h>
     19 #include <soc/hash.h>
     20 #include <soc/l3x.h>
     21 #include <soc/katana2.h>
     22 #include <soc/ism_hash.h>
     23 
     24 #include <bcm/l3.h>
     25 #include <bcm/oam.h>
     26 #include <bcm/cosq.h>
     27 
     28 #include <bcm_int/esw/oam.h>
     29 #include <bcm_int/esw/port.h>
     30 #include <bcm_int/esw/l3.h>
     31 #include <bcm_int/esw/switch.h>
     32 #include <bcm_int/esw/katana2.h>
     33 #include <bcm_int/esw/virtual.h>
     34 #include <bcm_int/esw_dispatch.h>
     35 
     36 #if defined(BCM_KATANA2_SUPPORT)
     37 #include <bcm_int/esw/stack.h>
     38 #include <bcm_int/esw/subport.h>
     39 
     40 #if defined(INCLUDE_BHH)
     41 #include <bcm_int/esw/bhh.h>
     42 #include <bcm_int/esw/bhh_sdk_pack.h>
     43 #include <soc/uc.h>
     44 #include <soc/shared/oam_pm_shared.h>
     45 #include <soc/shared/oam_pm_pack.h>
     46 #endif /* INCLUDE_BHH */
     47 /*
     48  * Device OAM control structure.
     49  */
     50 _bcm_oam_control_t *_kt2_oam_control[SOC_MAX_NUM_DEVICES];
     51 
     52 /* * * * * * * * * * * * * * * * * * *
     53  *            OAM MACROS             *
     54  */
     55 /*
     56  * Macro:
     57  *     _BCM_OAM_IS_INIT (internal)
     58  * Purpose:
     59  *     Check that the unit is valid and confirm that the oam functions
     60  *     are initialized.
     61  * Parameters:
     62  *     unit - BCM device number
     63  * Notes:
     64  *     Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or
     65  *     return(BCM_E_INIT) if fails.
     66  */
     67 #define _BCM_OAM_IS_INIT(unit)                                               \
     68             do {                                                             \
     69                 if (!soc_feature(unit, soc_feature_oam)) {                   \
     70                     return (BCM_E_UNAVAIL);                                  \
     71                 }                                                            \
     72                 if (_kt2_oam_control[unit] == NULL) {                        \
     73                     LOG_ERROR(BSL_LS_BCM_OAM, \
     74                               (BSL_META_U(unit, \
     75                                           "OAM Error: Module not initialized\n"))); \
     76                     return (BCM_E_INIT);                                     \
     77                 }                                                            \
     78             } while (0)
     79 
     80 /*
     81  *Macro:
     82  *     _BCM_OAM_LOCK
     83  * Purpose:
     84  *     Lock take the OAM control mutex
     85  * Parameters:
     86  *     control - Pointer to OAM control structure.
     87  */
     88 #define _BCM_OAM_LOCK(control) \
     89             sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER)
     90 
     91 /*
     92  * Macro:
     93  *     _BCM_OAM_UNLOCK
     94  * Purpose:
     95  *     Lock take the OAM control mutex
     96  * Parameters:
     97  *     control - Pointer to OAM control structure.
     98  */
     99 #define _BCM_OAM_UNLOCK(control) \
    100             sal_mutex_give((control)->oc_lock);
    101 /*
    102  * Macro:
    103  *     _BCM_OAM_HASH_DATA_CLEAR
    104  * Purpose:
    105  *      Clear hash data memory occupied by one endpoint.
    106  * Parameters:
    107  *     _ptr_    - Pointer to endpoint hash data memory. 
    108  */
    109 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \
    110             sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t));
    111 
    112 /*
    113  * Macro:
    114  *     _BCM_OAM_HASH_DATA_HW_IDX_INIT
    115  * Purpose:
    116  *     Initialize hardware indices to invalid index for an endpoint hash data.
    117  * Parameters:
    118  *     _ptr_    - Pointer to endpoint hash data memory. 
    119  */
    120 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_)                             \
    121             do {                                                          \
    122                     (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX);      \
    123                     (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX);     \
    124                     (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX);    \
    125                     (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX);    \
    126                     (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \
    127                     (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX);   \
    128                     (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX);   \
    129             } while (0)
    130 /*
    131  * Macro:
    132  *     _BCM_OAM_ALLOC
    133  * Purpose:
    134  *      Generic memory allocation routine.
    135  * Parameters:
    136  *    _ptr_     - Pointer to allocated memory.
    137  *    _ptype_   - Pointer type.
    138  *    _size_    - Size of heap memory to be allocated.
    139  *    _descr_   - Information about this memory allocation.
    140  */
    141 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_)                     \
    142             do {                                                         \
    143                 if (NULL == (_ptr_)) {                                   \
    144                    (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \
    145                 }                                                        \
    146                 if((_ptr_) != NULL) {                                    \
    147                     sal_memset((_ptr_), 0, (_size_));                    \
    148                 }  else {                                                \
    149                     LOG_ERROR(BSL_LS_BCM_OAM, \
    150                               (BSL_META("OAM Error: Allocation failure %s\n"), \
    151                                (_descr_)));                              \
    152                 }                                                        \
    153             } while (0)
    154 
    155 /*
    156  * Macro:
    157  *     _BCM_OAM_GROUP_INDEX_VALIDATE
    158  * Purpose:
    159  *     Validate OAM Group ID value.
    160  * Parameters:
    161  *     _group_ - Group ID value.
    162  */
    163 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_)                               \
    164             do {                                                             \
    165                 if ((_group_) < 0 || (_group_) >= oc->group_count) {         \
    166                     LOG_ERROR(BSL_LS_BCM_OAM, \
    167                               (BSL_META("OAM Error: Invalid Group ID = %d.\n"), \
    168                                _group_));                              \
    169                     return (BCM_E_PARAM);                                    \
    170                 }                                                            \
    171             } while (0);
    172 
    173 /*
    174  * Macro:
    175  *     _BCM_OAM_EP_INDEX_VALIDATE
    176  * Purpose:
    177  *     Validate OAM Endpoint ID value.
    178  * Parameters:
    179  *     _ep_ - Endpoint ID value.
    180  */
    181 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_)                               \
    182             do {                                                       \
    183                 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) {            \
    184                     LOG_ERROR(BSL_LS_BCM_OAM, \
    185                               (BSL_META("OAM Error: Invalid Endpoint ID" \
    186                                " = %d.\n"), _ep_));              \
    187                     return (BCM_E_PARAM);                              \
    188                 }                                                      \
    189             } while (0);
    190 
    191 
    192 /*
    193  * Macro:
    194  *     _BCM_OAM_RMEP_INDEX_VALIDATE
    195  * Purpose:
    196  *     Validate OAM Endpoint ID value.
    197  * Parameters:
    198  *     _ep_ - Endpoint ID value.
    199  */
    200 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_)                              \
    201             do {                                                        \
    202                 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) {           \
    203                     LOG_ERROR(BSL_LS_BCM_OAM, \
    204                               (BSL_META("OAM Error: Invalid RMEP Index" \
    205                                " = %d.\n"), _ep_));               \
    206                     return (BCM_E_PARAM);                               \
    207                 }                                                       \
    208             } while (0);
    209 
    210 
    211 /*
    212  * Macro:
    213  *     _BCM_OAM_KEY_PACK
    214  * Purpose:
    215  *     Pack the hash table look up key fields.
    216  * Parameters:
    217  *     _dest_ - Hash key buffer.
    218  *     _src_  - Hash key field to be packed.
    219  *     _size_ - Hash key field size in bytes.
    220  */
    221 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_)            \
    222             do {                                          \
    223                 sal_memcpy((_dest_), (_src_), (_size_));  \
    224                 (_dest_) += (_size_);                     \
    225             } while (0)
    226 /*
    227  * Macro:
    228  *     _BCM_KT2_OAM_MOD_PORT_TO_GLP
    229  * Purpose:
    230  *     Construct hadware GLP value from module ID, port ID and Trunk ID value.
    231  * Parameters:
    232  *     _modid_ - Module ID.
    233  *     _port_  - Port ID.
    234  *     _trunk_ - Trunk (1 - TRUE/0 - FALSE).
    235  *     _tgid_  - Trunk ID.
    236  */
    237 #define _BCM_KT2_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_)     \
    238     do {                                                                    \
    239         if ((_tgid_) != -1) {                                               \
    240             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    241                 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1)           \
    242                 & (_tgid_)));                                               \
    243         } else {                                                            \
    244             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    245                 | ((SOC_MODID_MAX(_u_) & (_m_))                             \
    246                 << (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_)))   \
    247                 | (SOC_PORT_ADDR_MAX(_u_) & (_p_))));                       \
    248         }                                                                   \
    249         LOG_DEBUG(BSL_LS_BCM_OAM,                                           \
    250                   (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"),        \
    251                    _u_, _m_, _p_, _t_, _tgid_, _glp_));                     \
    252     } while (0)
    253 
    254 /*
    255  * Macro:
    256  *     _BCM_OAM_GLP_XXX
    257  * Purpose:
    258  *     Get components of generic logical port value.
    259  * Parameters:
    260  *     _glp_ - Generic logical port.
    261  */
    262 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_glp_) (0x1 & ((_glp_) >> 15))
    263 #define _BCM_OAM_GLP_TRUNK_ID_GET(_glp_)  (0xFF & (_glp_))
    264 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7))
    265 #define _BCM_OAM_GLP_PORT_GET(_glp_)      (0x7F & (_glp_))
    266 
    267 /*
    268  * Macro:
    269  *     _BCM_OAM_EP_LEVEL_XXX
    270  * Purpose:
    271  *     Maintenance domain level bit count and level max value.   
    272  * Parameters:
    273  *     _glp_ - Generic logical port.
    274  */
    275 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT))
    276 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1)
    277 #define BHH_EP_TYPE(ep) ( (ep->type == bcmOAMEndpointTypeBHHMPLS) ||        \
    278                           (ep->type == bcmOAMEndpointTypeBHHMPLSVccv) || \
    279                           (ep->type == bcmOAMEndpointTypeBhhSection)||\
    280                           (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    281                           (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    282                           (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    283                         )
    284 
    285 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\
    286                                      (ep->type == bcmOAMEndpointTypeBhhSection)||\
    287                                      (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    288                                      (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    289                                      (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    290                                     )
    291 
    292 
    293 #define ETH_TYPE(type) (type == bcmOAMEndpointTypeEthernet)
    294 
    295 /* Checks hash_data pointer's int_flags field */
    296 #define _BCM_OAM_EP_IS_VP_TYPE(h_data_p) (h_data_p->int_flags &\
    297                                      _BCM_OAM_ENDPOINT_IS_VP_BASED)
    298 #define _BCM_OAM_EP_IS_MIP(info) (info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
    299 
    300 /*
    301  * Macro:
    302  *     BCM_WB_XXX
    303  * Purpose:
    304  *    OAM module scache version information.
    305  * Parameters:
    306  *    (major number, minor number)
    307  */
    308 #ifdef BCM_WARM_BOOT_SUPPORT
    309 #define BCM_WB_VERSION_1_0      SOC_SCACHE_VERSION(1,0)
    310 #define BCM_WB_VERSION_1_1      SOC_SCACHE_VERSION(1,1)
    311 /* This new version incorporates new MA_INDEX allocation scheme.
    312  * Recovery of Endpoints allocated in new scheme will be
    313  * done for this version or higher only */
    314 #define BCM_WB_VERSION_1_2      SOC_SCACHE_VERSION(1,2)
    315 
    316 /* This new version saves the SW endpoint ids for OAM. 
    317  * Recovery of Endpoints allocated in new scheme will be
    318  * done for this version or higher only */
    319 
    320 #define BCM_WB_VERSION_1_3      SOC_SCACHE_VERSION(1,3)
    321 #define BCM_WB_VERSION_1_4      SOC_SCACHE_VERSION(1,4)
    322 #define BCM_WB_VERSION_1_5      SOC_SCACHE_VERSION(1,5)
    323 #define BCM_WB_DEFAULT_VERSION  BCM_WB_VERSION_1_5
    324 #endif
    325 
    326 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE \
    327         (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count))
    328 
    329 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)\
    330         (ma_base_index + ma_offset)
    331 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\
    332         (oc->ma_idx_count + ma_base_index + ma_offset)
    333 
    334 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, ma_offset, is_upmep)\
    335         ((is_upmep)?\
    336         _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\
    337         :_BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset))
    338 
    339 /* Macros for endpoint id locations for different endpoint types. */
    340 #define _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE \
    341         (sizeof(bcm_oam_endpoint_t) * (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + oc->egr_ma_idx_count))
    342 
    343 #define _BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(mep_index) \
    344                 (sizeof(bcm_oam_endpoint_t) * mep_index)
    345 #define _BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(mep_index) \
    346                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + mep_index))
    347 #define _BCM_KT2_OAM_RMEP_SCACHE_LOCATION(rmep_index) \
    348                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + rmep_index))
    349 #define _BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(mep_index) \
    350                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + oc->rmep_count + mep_index))
    351 
    352 /* Vlans will be programmed in ING/EGR MP_GROUP table depending on MEP_TYPE */
    353 #define _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC    0
    354 /* Inner & Outer Vlan will be always programmed in ING/EGR MP_GROUP table */
    355 #define _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT 1
    356 
    357 /* Defined for OAM opcode group 1 and 2 */
    358 #define _BCM_OAM_OTHER_OPCODE_GROUP_1    0x1
    359 #define _BCM_OAM_OTHER_OPCODE_GROUP_2    0x2
    360 /* Define the port used in OLP-XGS communication */
    361 #define _BCM_OAM_OLP_COMMUNICATION_PORT  0x7f
    362 
    363 /*
    364  * Device OAM control structure.
    365  */
    366 _bcm_oam_control_t *_kt2_oam_control[SOC_MAX_NUM_DEVICES];
    367 
    368 #if defined (INCLUDE_BHH)
    369 
    370 typedef struct _bcm_oam_pm_profile_int_info_s {
    371     int id_status;
    372     bcm_oam_pm_profile_info_t pm_profile;
    373 }_bcm_oam_pm_profile_int_info_t;
    374 typedef struct _bcm_oam_pm_profile_control_s {
    375     _bcm_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES];
    376 }_bcm_oam_pm_profile_control_t;
    377 
    378 
    379 _bcm_oam_pm_profile_control_t *kt2_pm_profile_control[SOC_MAX_NUM_DEVICES];
    380 
    381 #define _BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id)          (pmc->profile_info[id].id_status == 1)
    382 #define _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, id)             (&(pmc->profile_info[id].pm_profile))
    383 #define _BCM_KT2_SET_PM_CTRL_PROFILE_IN_USE(pmc, id)      (pmc->profile_info[id].id_status = 1)
    384 #define _BCM_KT2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id)  (pmc->profile_info[id].id_status = 0)
    385 
    386 #define _BCM_KT2_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_REPLACE)
    387 
    388 #define _BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_WITH_ID)
    389 
    390 #define _BCM_KT2_PM_PROFILE_ID_VALID(profile_id) \
    391     ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES))
    392 
    393 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \
    394                             (oc->pm_bhh_lmdm_data_collection_mode != \
    395                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    396 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \
    397                             (oc->pm_bhh_lmdm_data_collection_mode == \
    398                                 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    399 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \
    400                             (oc->pm_bhh_lmdm_data_collection_mode == \
    401                                 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    402 static int kt2_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE;
    403 #else
    404 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0
    405 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0
    406 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    407 #endif
    408 
    409 
    410 typedef struct _oam_tpid_s {
    411     uint32                       tpid;
    412     uint32                       ref_count;
    413 } _oam_tpid_t;
    414 
    415 #define BCM_MAX_TPID_ENTRIES 4
    416 #define BCM_MAX_INNER_TPID_ENTRIES 1
    417 
    418 
    419 #define BCM_OAM_TPID_TYPE_OUTER   0
    420 #define BCM_OAM_TPID_TYPE_INNER   1
    421 #define BCM_OAM_TPID_TYPE_SUBPORT 2
    422 #define BCM_OAM_TPID_VALUE_ZERO   0
    423 #define BCM_OAM_DEFAULT_TPID      0x8100
    424 #define BCM_OAM_TPID_9100         0x9100
    425 #define BCM_OAM_TPID_88A8         0x88A8
    426 #define DGLP_LAG_ID_INDICATOR_SHIFT_BITS   15
    427 #define DGLP_MODULE_ID_SHIFT_BITS          7
    428 #define _BCM_OAM_OPCODE_TYPE_CCM           0x1
    429 #define _BCM_OAM_OPCODE_TYPE_LBR           0x2
    430 #define _BCM_OAM_OPCODE_TYPE_LBM           0x3
    431 #define _BCM_OAM_OPCODE_TYPE_LTR           0x4
    432 #define _BCM_OAM_OPCODE_TYPE_LTM           0x5
    433 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST 0x6
    434 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST  0xFF
    435 #define _BCM_OAM_OPCODE_TYPE_CFM_MASK      0x3E
    436 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK  0xFFFFFFFF
    437 #define _BCM_OAM_DGLP1_PROFILE_PTR         0x1
    438 #define _BCM_OAM_DGLP2_PROFILE_PTR         0x2
    439 #define _BCM_OAM_LOW_MDL_DROP_PACKET       0x2
    440 #define _BCM_OAM_FWD_AS_DATA               0x0
    441 #define _BCM_OAM_DROP_REDIRECT_T0_DGLP1    0x2
    442 #define _BCM_OAM_DROP_REDIRECT_T0_DGLP2    0x3
    443 #define _BCM_OAM_SERVICE_PRI_MAX_OFFSET    0x7
    444 
    445 STATIC _oam_tpid_t
    446            (*_oam_outer_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES];
    447 
    448 STATIC _oam_tpid_t
    449            (*_oam_inner_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_INNER_TPID_ENTRIES];
    450 
    451 STATIC _oam_tpid_t
    452            (*_oam_subport_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES];
    453 
    454 STATIC sal_mutex_t _kt2_outer_tpid_lock[BCM_MAX_NUM_UNITS];
    455 STATIC sal_mutex_t _kt2_inner_tpid_lock[BCM_MAX_NUM_UNITS];
    456 STATIC sal_mutex_t _kt2_subport_tpid_lock[BCM_MAX_NUM_UNITS];
    457 
    458 /* OAM TPID registers and default values */
    459 STATIC int outer_tpid[4] = { OUTER_TPID_0r, OUTER_TPID_1r, 
    460                              OUTER_TPID_2r, OUTER_TPID_3r };
    461 
    462 STATIC int default_outer_tpid[4] = { BCM_OAM_DEFAULT_TPID, BCM_OAM_TPID_9100, 
    463                                   BCM_OAM_TPID_88A8, BCM_OAM_TPID_VALUE_ZERO};
    464 
    465 STATIC int subport_tpid[4] = { SUBPORT_TAG_TPID_0r, SUBPORT_TAG_TPID_1r, 
    466                                SUBPORT_TAG_TPID_2r, SUBPORT_TAG_TPID_3r };
    467 
    468 #define KT2_OAM_OUTER_TPID_TAB(unit) _oam_outer_tpid_tab[unit]
    469 #define KT2_OAM_INNER_TPID_TAB(unit) _oam_inner_tpid_tab[unit]
    470 #define KT2_OAM_SUBPORT_TPID_TAB(unit) _oam_subport_tpid_tab[unit]
    471 
    472 #define KT2_OAM_OUTER_TPID_ENTRY(unit, index) \
    473     ((*_oam_outer_tpid_tab[unit])[index].tpid)
    474 
    475 #define KT2_OAM_INNER_TPID_ENTRY(unit, index) \
    476     ((*_oam_inner_tpid_tab[unit])[index].tpid)
    477 
    478 #define KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) \
    479     ((*_oam_subport_tpid_tab[unit])[index].tpid)
    480 
    481 #define KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) \
    482     ((*_oam_outer_tpid_tab[unit])[index].ref_count)
    483 
    484 #define KT2_OAM_INNER_TPID_REF_COUNT(unit, index) \
    485     ((*_oam_inner_tpid_tab[unit])[index].ref_count)
    486 
    487 #define KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) \
    488     ((*_oam_subport_tpid_tab[unit])[index].ref_count)
    489 
    490 #define KT2_OAM_OUTER_TPID_TAB_INIT_CHECK(unit) \
    491     if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
    492 
    493 #define KT2_OAM_INNER_TPID_TAB_INIT_CHECK(unit) \
    494     if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
    495 
    496 #define KT2_OAM_SUBPORT_TPID_TAB_INIT_CHECK(unit) \
    497     if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
    498 
    499 #define BCM_KT2_OUTER_TPID_MUTEX(_u_) _kt2_outer_tpid_lock[_u_]
    500 #define BCM_KT2_INNER_TPID_MUTEX(_u_) _kt2_inner_tpid_lock[_u_]
    501 #define BCM_KT2_SUBPORT_TPID_MUTEX(_u_) _kt2_subport_tpid_lock[_u_]
    502 
    503 #define BCM_KT2_OUTER_TPID_LOCK(_u_)   \
    504          ((_kt2_outer_tpid_lock[_u_]) ? \
    505          sal_mutex_take(_kt2_outer_tpid_lock[_u_], sal_mutex_FOREVER) :  \
    506          (BCM_E_INTERNAL))
    507 
    508 #define BCM_KT2_INNER_TPID_LOCK(_u_)   \
    509          ((_kt2_inner_tpid_lock[_u_]) ? \
    510          sal_mutex_take(_kt2_inner_tpid_lock[_u_], sal_mutex_FOREVER) :  \
    511          (BCM_E_INTERNAL))
    512 
    513 #define BCM_KT2_SUBPORT_TPID_LOCK(_u_)   \
    514          ((_kt2_subport_tpid_lock[_u_]) ? \
    515          sal_mutex_take(_kt2_subport_tpid_lock[_u_], sal_mutex_FOREVER) :  \
    516          (BCM_E_INTERNAL))
    517 
    518 #define BCM_KT2_OUTER_TPID_UNLOCK(_u_)  \
    519          ((_kt2_outer_tpid_lock[_u_]) ? \
    520          sal_mutex_give(_kt2_outer_tpid_lock[_u_]) : \
    521          (BCM_E_INTERNAL))
    522 
    523 #define BCM_KT2_INNER_TPID_UNLOCK(_u_)  \
    524          ((_kt2_inner_tpid_lock[_u_]) ? \
    525          sal_mutex_give(_kt2_inner_tpid_lock[_u_]) : \
    526          (BCM_E_INTERNAL))
    527 
    528 #define BCM_KT2_SUBPORT_TPID_UNLOCK(_u_)  \
    529          ((_kt2_subport_tpid_lock[_u_]) ? \
    530          sal_mutex_give(_kt2_subport_tpid_lock[_u_]) : \
    531          (BCM_E_INTERNAL))
    532 
    533 
    534 /*
    535  * ==========================================================================
    536  *  Downmep/IFP      3'b000                8'd1(L2_HDR)      8'd0(NULL)
    537  *  Downmep/IFP      3'b001                8'd0(OAM_HDR)     8'd2(CCM/BHH-CCM)
    538  *  Downmep/IFP      3'b010                8'd0(OAM_HDR)     8'd3(BFD)
    539  *  Downmep/IFP      3'b011                8'd0(OAM_HDR)     8'd4(LM/DM)
    540  *  Upmep            3'b000                N/A               N/A
    541  *  Upmep            3'b001                8'd0(OAM_HDR)     8'd5(CCM)
    542  *  Upmep            3'b010                N/A               N/A
    543  *  Upmep            3'b011                8'd0(OAM_HDR)     8'd6(LM/DM)
    544  */
    545 #define _BCM_KT2_OLP_HDR_SUBTYPE_CCM                   0x2
    546 #define _BCM_KT2_OLP_HDR_SUBTYPE_BFD                   0x3
    547 #define _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM                 0x4
    548 #define _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM     0x5
    549 #define _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM   0x6
    550 
    551 #define _BCM_KT2_NO_OF_BITS_COMP_HDR 3
    552 #define _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(comp_hdr) \
    553              ((1 << _BCM_KT2_NO_OF_BITS_COMP_HDR) | comp_hdr)
    554 
    555 
    556 #define _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED                  0x1
    557 #define _BCM_KT2_BFD_OLP_HDR_TYPE_COMPRESSED                  0x2
    558 #define _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED                0x3
    559 
    560 #define _BCM_KT2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED           \
    561     _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                      \
    562                                _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED)
    563 
    564 #define _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED         \
    565     _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                      \
    566                              _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED)
    567 
    568 #define _BCM_KT2_OLP_OAM_HDR  0
    569 #define _BCM_KT2_OLP_L2_HDR   1
    570 
    571 /* No. of counter pool that can be programmed per endpoint */
    572 #define _KT2_OAM_COUNTER_SIZE 2
    573 
    574 /* * * * * * * * * * * * * * * * * * * * * * * * *
    575  *         OAM function prototypes               *
    576  */
    577 
    578 int _bcm_kt2_oam_convert_action_to_opcode_entry(
    579                                         int unit,
    580                                         bcm_oam_endpoint_action_t *action, 
    581                                         bcm_oam_endpoint_t ep_id,
    582                                         void *profile,
    583                                         uint8  *opcode_profile_changed); 
    584 STATIC int
    585 _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(int unit,
    586                        _bcm_oam_hash_data_t *h_data_p,
    587                               int *num_ma_idx_entries,
    588                        shr_idxres_list_handle_t *pool);
    589 STATIC int
    590 _bcm_kt2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc);
    591 STATIC int
    592 _bcm_kt2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc);
    593 
    594 STATIC int
    595 _bcm_kt2_oam_control_get(int unit, _bcm_oam_control_t **oc);
    596 
    597 STATIC INLINE bcm_oam_endpoint_t
    598 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t   *oc, int ma_idx);
    599 
    600 
    601 
    602 /* * * * * * * * * * * * * * * * * * * * * * * * *
    603  *         OAM global data initialization      *
    604  */
    605 #if defined(INCLUDE_BHH)
    606 
    607 #define BHH_COSQ_INVALID          0xFFFF
    608 
    609 /*
    610  * Macro:
    611  *     _BCM_OAM_BHH_IS_VALID (internal)
    612  * Purpose:
    613  *     Check that the BHH feature is available on this unit
    614  * Parameters:
    615  *     unit - BCM device number
    616  * Notes:
    617  *     Results in return(BCM_E_UNAVAIL),
    618  */
    619 #define _BCM_OAM_BHH_IS_VALID(unit)                                          \
    620             do {                                                             \
    621                 if (!soc_feature(unit, soc_feature_bhh)) {                   \
    622                     return (BCM_E_UNAVAIL);                                  \
    623                 }                                                            \
    624             } while (0)
    625 
    626 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \
    627         (ep - _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET)
    628 
    629 #define BCM_OAM_BHH_GET_SDK_EP(ep) \
    630         (ep + _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET)
    631 
    632 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \
    633             do {                                                       \
    634                 if (((_ep_) < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) ||         \
    635                     ((_ep_) >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET           \
    636                                          + oc->bhh_endpoint_count))) { \
    637                     LOG_ERROR(BSL_LS_BCM_OAM, \
    638                               (BSL_META_U(unit, \
    639                                           "OAM Error: Invalid Endpoint ID" \
    640                                           " = %d.\n"), _ep_));   \
    641                     _BCM_OAM_UNLOCK(oc);                               \
    642                     return (BCM_E_PARAM);                              \
    643                 }                                                      \
    644             } while (0);
    645 
    646 #define BCM_OAM_BHH_ABS(x)   (((x) < 0) ? (-(x)) : (x))
    647 
    648 
    649 STATIC int
    650 _bcm_kt2_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p);
    651 STATIC int
    652 _bcm_kt2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
    653                                     uint16 s_len, uint32 s_data,
    654                                     uint8 r_subclass, uint16 *r_len);
    655 STATIC int
    656 _bcm_kt2_oam_bhh_hw_init(int unit);
    657 STATIC void
    658 _bcm_kt2_oam_bhh_callback_thread(void *param);
    659 STATIC int
    660 _bcm_kt2_oam_bhh_event_mask_set(int unit);
    661 STATIC int
    662 bcm_kt2_oam_bhh_endpoint_create(int unit,
    663                                 bcm_oam_endpoint_info_t *endpoint_info,
    664                                 _bcm_oam_hash_key_t  *hash_key);
    665 STATIC int
    666 _bcm_kt2_oam_bhh_sec_mep_alloc_counter(int unit, shr_idxres_element_t *ctr_index);
    667 
    668 STATIC int
    669 _bcm_kt2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass,
    670                                     uint16 s_len, uint32 s_data,
    671                                     uint8 r_subclass, uint16 *r_len);
    672 
    673 STATIC void _bcm_kt2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc,
    674                                              mos_msg_data_t *event_msg);
    675 int _bcm_kt2_oam_pm_init(int unit);
    676 #endif  /* INCLUDE_BHH */
    677 
    678 STATIC int
    679 bcm_kt2_oam_hw_ccm_tx_ctr_update(int unit,
    680         bcm_oam_endpoint_info_t *ep_info);
    681 /*
    682  * Katana2 device OAM CCM intervals array initialization..
    683  */
    684 STATIC uint32 _kt2_ccm_intervals[] =
    685 {
    686     BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED,
    687     BCM_OAM_ENDPOINT_CCM_PERIOD_3MS,
    688     BCM_OAM_ENDPOINT_CCM_PERIOD_10MS,
    689     BCM_OAM_ENDPOINT_CCM_PERIOD_100MS,
    690     BCM_OAM_ENDPOINT_CCM_PERIOD_1S,
    691     BCM_OAM_ENDPOINT_CCM_PERIOD_10S,
    692     BCM_OAM_ENDPOINT_CCM_PERIOD_1M,
    693     BCM_OAM_ENDPOINT_CCM_PERIOD_10M,
    694     _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED
    695 };
    696 
    697 /*   
    698  * OAM hardware interrupts to software events mapping array initialization.
    699  * _kt2_oam_interrupts[] =
    700  *     {Interrupt status register, Remote MEP index field, MA index field,
    701  *          CCM_INTERRUPT_CONTROLr - Interrupt status Field,
    702  *          OAM event type}. 
    703  */
    704 STATIC _bcm_oam_interrupt_t _kt2_oam_interrupts[] =
    705 {
    706     /* 1. Port down interrupt. */
    707     {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    708         ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf,
    709         bcmOAMEventEndpointPortDown},
    710 
    711     /* 2. Port up interrupt. */
    712     {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    713         ANY_RMEP_TLV_PORT_UP_INT_ENABLEf,
    714         bcmOAMEventEndpointPortUp},
    715 
    716     /* 3. Interface down interrupt. */
    717     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    718         ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf,
    719         bcmOAMEventEndpointInterfaceDown},
    720 
    721     /* 4. Interface up interrupt. */
    722     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    723         ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf,
    724         bcmOAMEventEndpointInterfaceUp},
    725 
    726     /* 5. Interface TLV Testing to Up interrupt. */
    727     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    728         ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf,
    729         bcmOAMEventEndpointInterfaceTestingToUp},
    730 
    731     /* 6. Interface TLV Unknown to Up interrupt. */
    732     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    733         ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf,
    734         bcmOAMEventEndpointInterfaceUnknownToUp},
    735 
    736     /* 7. Interface TLV Dormant to Up interrupt. */
    737     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    738         ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf,
    739         bcmOAMEventEndpointInterfaceDormantToUp},
    740 
    741     /* 8. Interface TLV Not present to Up interrupt. */
    742     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    743         ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf,
    744         bcmOAMEventEndpointInterfaceNotPresentToUp},
    745 
    746     /* 9. Interface Link Layer Down to Up interrupt. */
    747     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    748         ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf,
    749         bcmOAMEventEndpointInterfaceLLDownToUp},
    750 
    751     /* 10. Interface up to testing transition interrupt. */
    752     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    753         ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf,
    754         bcmOAMEventEndpointInterfaceTesting},
    755 
    756     /* 11. Interface up to unknown transition interrupt. */
    757     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    758         ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf,
    759         bcmOAMEventEndpointInterfaceUnkonwn},
    760 
    761     /* 11. Interface up to dormant transition interrupt. */
    762     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    763         ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf,
    764         bcmOAMEventEndpointInterfaceDormant},
    765 
    766     /* 11. Interface up to not present transition interrupt. */
    767     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    768         ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf,
    769         bcmOAMEventEndpointInterfaceNotPresent},
    770 
    771     /* 11. Interface up to Link Layer Down transition interrupt. */
    772     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    773         ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf,
    774         bcmOAMEventEndpointInterfaceLLDown},
    775 
    776     /* 12. Low MDL or unexpected MAID interrupt. */
    777     {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    778         XCON_CCM_DEFECT_INT_ENABLEf,
    779         bcmOAMEventGroupCCMxcon},
    780 
    781     /*
    782      * 13. Remote MEP lookup failed or CCM interval mismatch during Remote MEP
    783      *    lookup interrupt.
    784      */
    785     {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    786         ERROR_CCM_DEFECT_INT_ENABLEf,
    787         bcmOAMEventGroupCCMError},
    788 
    789     /*
    790      * 14. Some Remote defect indicator interrupt - aggregated health of remote
    791      *    MEPs.
    792      */
    793     {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    794         SOME_RDI_DEFECT_INT_ENABLEf,
    795         bcmOAMEventGroupRemote},
    796 
    797     /* 15. Aggregate health of remote MEP state machines interrupt. */
    798     {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    799         SOME_RMEP_CCM_DEFECT_INT_ENABLEf,
    800         bcmOAMEventGroupCCMTimeout},
    801 
    802     /* Invalid Interrupt - Always Last */
    803     {INVALIDr, INVALIDf, 0, bcmOAMEventCount}
    804 };
    805 
    806 /*
    807  * 0AM Group faults array initialization.
    808  */
    809 STATIC _bcm_oam_fault_t _kt2_oam_group_faults[] =
    810 {
    811     {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf,
    812         BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08},
    813 
    814     {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf,
    815         BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04},
    816 
    817     {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf,
    818         BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02},
    819 
    820     {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf,
    821         BCM_OAM_GROUP_FAULT_REMOTE, 0x01},
    822 
    823     {0, 0, 0, 0}
    824 };
    825 
    826 /*
    827  * 0AM Endpoint faults array initialization.
    828  */
    829 STATIC _bcm_oam_fault_t _kt2_oam_endpoint_faults[] =
    830 {
    831     {CURRENT_RMEP_PORT_STATUS_DEFECTf,
    832         STICKY_RMEP_PORT_STATUS_DEFECTf,
    833         BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08},
    834 
    835     {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf,
    836         STICKY_RMEP_INTERFACE_STATUS_DEFECTf,
    837         BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04},
    838 
    839     {CURRENT_RMEP_CCM_DEFECTf,
    840         STICKY_RMEP_CCM_DEFECTf,
    841         BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20},
    842 
    843     {CURRENT_RMEP_LAST_RDIf,
    844         STICKY_RMEP_LAST_RDIf,
    845         BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10},
    846 
    847     {0, 0, 0, 0}
    848 };
    849 
    850 typedef struct _bcm_kt2_oam_intr_en_fields_s {
    851     soc_field_t field;
    852     uint32      value;
    853 } _bcm_kt2_oam_intr_en_fields_t;
    854  
    855 STATIC _bcm_kt2_oam_intr_en_fields_t _kt2_oam_intr_en_fields[bcmOAMEventCount] =
    856 {
    857     /*
    858      * Note:
    859      * The order of hardware field names in the below initialization
    860      * code must match the event enum order in bcm_oam_event_type_t.
    861      */
    862     { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1},
    863     { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1},
    864     { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1},
    865     { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    866     { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1},
    867     { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    868     { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    869     { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    870     { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    871     { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1},
    872     { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1},
    873     { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1},
    874     { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1},
    875     { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1},
    876     { XCON_CCM_DEFECT_INT_ENABLEf, 1},
    877     { ERROR_CCM_DEFECT_INT_ENABLEf, 1},
    878     { SOME_RDI_DEFECT_INT_ENABLEf, 1},
    879     { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1},
    880     { INVALIDf, 0},
    881     { INVALIDf, 0},
    882     { INVALIDf, 0},
    883     { INVALIDf, 0},
    884     { INVALIDf, 0},
    885     { INVALIDf, 0},
    886     { INVALIDf, 0},
    887     { INVALIDf, 0},
    888     { INVALIDf, 0},
    889     { INVALIDf, 0},
    890     { INVALIDf, 0}
    891 };
    892 
    893 /* LM counter related fields - Ingress */
    894 STATIC mep_ctr_info_t mep_ctr_info[] = {     
    895     { LMEP__CTR1_VALIDf, LMEP__CTR1_BASE_PTRf,            
    896       LMEP__CTR1_MEP_TYPEf, LMEP__CTR1_MEP_MDLf,                      
    897       LMEP__CTR1_SERVICE_PRI_MAP_PROFILE_PTRf 
    898     },
    899     { LMEP__CTR2_VALIDf, LMEP__CTR2_BASE_PTRf,
    900       LMEP__CTR2_MEP_TYPEf, LMEP__CTR2_MEP_MDLf,
    901       LMEP__CTR2_SERVICE_PRI_MAP_PROFILE_PTRf 
    902     }
    903 };
    904 
    905 /* LM counter related fields - Egress */
    906 STATIC mep_ctr_info_t egr_mep_ctr_info[] = {     
    907     { CTR1_VALIDf, CTR1_BASE_PTRf, 
    908       CTR1_MEP_TYPEf, CTR1_MEP_MDLf,                      
    909       CTR1_SERVICE_PRI_MAP_PROFILE_PTRf 
    910     },
    911     { CTR2_VALIDf, CTR2_BASE_PTRf, 
    912       CTR2_MEP_TYPEf, CTR2_MEP_MDLf,
    913       CTR2_SERVICE_PRI_MAP_PROFILE_PTRf
    914     } 
    915 };
    916 
    917 typedef struct _bcm_kt2_oam_olp_hdr_type_map_s {
    918     bcm_field_olp_header_type_t     field_olp_hdr_type;
    919     uint8                           mem_index;
    920     uint8                           subtype;
    921     uint8                           reuse;
    922 } _bcm_kt2_oam_olp_hdr_type_map_t;
    923 
    924 STATIC _bcm_kt2_oam_olp_hdr_type_map_t kt2_olp_hdr_type_mapping[] = {
    925 /* Down MEP CCM */
    926 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED,
    927                                  _BCM_KT2_OLP_HDR_SUBTYPE_CCM, 0},
    928 
    929 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED,
    930                                  _BCM_KT2_OLP_HDR_SUBTYPE_CCM, 1},
    931 
    932 /* BFD */
    933 {bcmFieldOlpHeaderTypeBfdOam,  _BCM_KT2_BFD_OLP_HDR_TYPE_COMPRESSED,
    934                                _BCM_KT2_OLP_HDR_SUBTYPE_BFD, 0},
    935 
    936 /* Down MEP LM/DM */
    937 {bcmFieldOlpHeaderTypeEthOamLmDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    938                                   _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 0},
    939 
    940 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    941                                 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1},
    942 
    943 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    944                                 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1},
    945 
    946 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    947                                 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1},
    948 
    949 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    950                                 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1},
    951 
    952 /*
    953  * UpMEP header types are not programmable by FP, but OAM pipeline lookup
    954  * can assign UpMEP subtypes.
    955  */
    956 
    957 /* UpMEP CCM*/
    958 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_KT2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED,
    959                                       _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM, 0},
    960 
    961 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    962                                      _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM, 0},
    963 
    964 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED,
    965                                      _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM, 1},
    966 };
    967 
    968 static uint8 kt2_olp_hdr_type_count = sizeof(kt2_olp_hdr_type_mapping) /
    969                                            sizeof(kt2_olp_hdr_type_mapping[0]);
    970 
    971 
    972 /* * * * * * * * * * * * * * * * * * * * * * * * *
    973  *            Static local functions             *
    974  */
    975 /*
    976  * Function:
    977  *      _bcm_kt2_outer_tpid_init
    978  * Purpose:
    979  *      Allocate and initialize memory to cache oam outer tpid entries.
    980  *      Initialize lock for cached tpid entries.
    981  * Parameters:
    982  *      unit       - (IN)SOC unit number.
    983  * Returns:
    984  *      BCM_E_XXX
    985  * Notes:
    986  */
    987 int
    988 _bcm_kt2_outer_tpid_init(int unit) {
    989     int               index;
    990     int               alloc_size;
    991     uint32            reg32;
    992     int               rv = BCM_E_NONE;
    993 
    994     /* Allocate memory to cache OUTER_TPID entries.  */
    995     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES;
    996     if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) {
    997         KT2_OAM_OUTER_TPID_TAB(unit) = sal_alloc(alloc_size,
    998                                          "Cached OAM Outer TPIDs");
    999         if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) {
   1000             return BCM_E_MEMORY;
   1001         }
   1002     }
   1003     sal_memset(KT2_OAM_OUTER_TPID_TAB(unit), 0, alloc_size);
   1004 
   1005     /* Cache outer TPID table */
   1006     for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) {
   1007         rv = soc_reg32_get(unit, outer_tpid[index], REG_PORT_ANY, 0, &reg32);
   1008         if (BCM_FAILURE(rv)) {
   1009             sal_free(KT2_OAM_OUTER_TPID_TAB(unit));
   1010             KT2_OAM_OUTER_TPID_TAB(unit) = NULL;
   1011         }
   1012         KT2_OAM_OUTER_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 
   1013                                           outer_tpid[index], reg32, TPIDf);
   1014     }
   1015 
   1016     if (NULL == BCM_KT2_OUTER_TPID_MUTEX(unit)) {
   1017         /* Create protection mutex. */
   1018         BCM_KT2_OUTER_TPID_MUTEX(unit) = sal_mutex_create("oamouter_tpid_lock");
   1019         if (NULL == BCM_KT2_OUTER_TPID_MUTEX(unit)) {
   1020             return (BCM_E_MEMORY);
   1021         }
   1022     }
   1023     return (BCM_E_NONE);
   1024 }
   1025 
   1026 /*
   1027  * Function:
   1028  *      _bcm_kt2_inner_tpid_init
   1029  * Purpose:
   1030  *      Allocate and initialize memory to cache oam inner tpid entries.
   1031  *      Initialize lock for cached tpid entries.
   1032  * Parameters:
   1033  *      unit       - (IN)SOC unit number.
   1034  * Returns:
   1035  *      BCM_E_XXX
   1036  * Notes:
   1037  */
   1038 int
   1039 _bcm_kt2_inner_tpid_init(int unit) {
   1040     int               alloc_size;
   1041     uint32            reg32;
   1042     int               rv = BCM_E_NONE;
   1043 
   1044     /* Allocate memory to cache INNER_TPID entries.  */
   1045     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_INNER_TPID_ENTRIES;
   1046     if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) {
   1047         KT2_OAM_INNER_TPID_TAB(unit) = sal_alloc(alloc_size,
   1048                                          "Cached OAM Inner TPIDs");
   1049         if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) {
   1050             return BCM_E_MEMORY;
   1051         }
   1052     }
   1053     sal_memset(KT2_OAM_INNER_TPID_TAB(unit), 0, alloc_size);
   1054 
   1055     /* Cache Inner TPID table */
   1056     rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &reg32);
   1057     if (BCM_FAILURE(rv)) {
   1058         sal_free(KT2_OAM_INNER_TPID_TAB(unit));
   1059         KT2_OAM_INNER_TPID_TAB(unit) = NULL;
   1060     }
   1061     /* Inner TPID has only 1 entry. So, index is always 0 */
   1062     KT2_OAM_INNER_TPID_ENTRY(unit, 0) = soc_reg_field_get(unit, INNER_TPIDr, 
   1063                                                           reg32, TPIDf);
   1064 
   1065     if (NULL == BCM_KT2_INNER_TPID_MUTEX(unit)) {
   1066         /* Create protection mutex. */
   1067         BCM_KT2_INNER_TPID_MUTEX(unit) = sal_mutex_create("oam inner_tpid_lock");
   1068         if (NULL == BCM_KT2_INNER_TPID_MUTEX(unit)) {
   1069             return (BCM_E_MEMORY);
   1070         }
   1071     }
   1072     return (BCM_E_NONE);
   1073 }
   1074 
   1075 /*
   1076  * Function:
   1077  *      _bcm_kt2_subport_tpid_init
   1078  * Purpose:
   1079  *      Allocate and initialize memory to cache oam subport tpid entries.
   1080  *      Initialize lock for cached tpid entries.
   1081  * Parameters:
   1082  *      unit       - (IN)SOC unit number.
   1083  * Returns:
   1084  *      BCM_E_XXX
   1085  * Notes:
   1086  */
   1087 int
   1088 _bcm_kt2_subport_tpid_init(int unit) {
   1089     int               index;
   1090     int               alloc_size;
   1091     uint32            reg32;
   1092     int               rv = BCM_E_NONE;
   1093 
   1094     /* Allocate memory to cache OUTER_TPID entries.  */
   1095     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES;
   1096     if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) {
   1097         KT2_OAM_SUBPORT_TPID_TAB(unit) = sal_alloc(alloc_size,
   1098                                          "Cached OAM Subport TPIDs");
   1099         if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) {
   1100             return BCM_E_MEMORY;
   1101         }
   1102     }
   1103     sal_memset(KT2_OAM_SUBPORT_TPID_TAB(unit), 0, alloc_size);
   1104 
   1105     /* Cache Subport TPID table */
   1106     for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) {
   1107         rv = soc_reg32_get(unit, subport_tpid[index], REG_PORT_ANY, 0, &reg32);
   1108         if (BCM_FAILURE(rv)) {
   1109             sal_free(KT2_OAM_SUBPORT_TPID_TAB(unit));
   1110             KT2_OAM_SUBPORT_TPID_TAB(unit) = NULL;
   1111         }
   1112         KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 
   1113                                           subport_tpid[index], reg32, TPIDf);
   1114     }
   1115 
   1116     if (NULL == BCM_KT2_SUBPORT_TPID_MUTEX(unit)) {
   1117         /* Create protection mutex. */
   1118         BCM_KT2_SUBPORT_TPID_MUTEX(unit) = sal_mutex_create("oam subport_tpid_lock");
   1119         if (NULL == BCM_KT2_SUBPORT_TPID_MUTEX(unit)) {
   1120             return (BCM_E_MEMORY);
   1121         }
   1122     }
   1123     return (BCM_E_NONE);
   1124 }
   1125 /*
   1126  * Function :
   1127  *    _bcm_kt2_oam_tpid_get
   1128  * 
   1129  * Purpose  :
   1130  *    Get tpid value for tpid entry index in the HW. 
   1131  *
   1132  * Parameters :
   1133  *     unit  - (IN) BCM device number.
   1134  *     tpid_type -(IN) - outer/inner/subport
   1135  *     index - (IN) Entry index.
   1136  *     value - (OUT) TPID value 
   1137  * Return :
   1138  *    BCM_E_XXX
   1139  */
   1140 int
   1141 _bcm_kt2_oam_tpid_get(int unit, int tpid_type, int index, int *value)
   1142 {
   1143     int  rv = BCM_E_NONE;
   1144     uint32 rval = 0;
   1145 
   1146     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1147         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1148             return (BCM_E_PARAM); 
   1149         }
   1150         rv = soc_reg32_get(unit, outer_tpid[index], REG_PORT_ANY, 0, &rval);
   1151         if (BCM_FAILURE(rv)) {
   1152             return (BCM_E_PARAM); 
   1153         }
   1154         *value = soc_reg_field_get(unit, outer_tpid[index], rval, TPIDf);
   1155     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1156         if (index >= BCM_MAX_INNER_TPID_ENTRIES)  {
   1157             return (BCM_E_PARAM); 
   1158         }
   1159         rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &rval);
   1160         if (BCM_FAILURE(rv)) {
   1161             return (BCM_E_PARAM); 
   1162         }
   1163         *value = soc_reg_field_get(unit, INNER_TPIDr, rval, TPIDf);
   1164     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1165         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1166             return (BCM_E_PARAM); 
   1167         }
   1168         rv = soc_reg32_get(unit, subport_tpid[index], REG_PORT_ANY, 0, &rval);
   1169         if (BCM_FAILURE(rv)) {
   1170             return (BCM_E_PARAM); 
   1171         }
   1172         *value = soc_reg_field_get(unit, subport_tpid[index], rval, TPIDf);
   1173     } else {
   1174         return (BCM_E_PARAM); 
   1175     } 
   1176     return (rv);
   1177 }
   1178 
   1179 /*
   1180  * Function :
   1181  *    _bcm_kt2_oam_tpid_set
   1182  * 
   1183  * Purpose  :
   1184  *    Set tpid value for tpid entry index in the HW. 
   1185  *
   1186  * Parameters :
   1187  *     unit  - (IN) BCM device number.
   1188  *     tpid_type -(IN) - outer/inner/subport
   1189  *     index - (IN) Entry index.
   1190  *     value - (IN) Value to be set as tpid 
   1191  * Return :
   1192  *    BCM_E_XXX
   1193  */
   1194 int
   1195 _bcm_kt2_oam_tpid_set(int unit, int tpid_type, int index, int value)
   1196 {
   1197     int  rv = BCM_E_NONE;
   1198     uint32 rval = 0;
   1199 
   1200     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1201         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1202             return (BCM_E_PARAM); 
   1203         }
   1204         soc_reg_field_set(unit, outer_tpid[index], &rval, TPIDf, value);
   1205         rv = soc_reg32_set(unit, outer_tpid[index], REG_PORT_ANY, 0, rval);
   1206         if (BCM_FAILURE(rv)) {
   1207             return (BCM_E_PARAM); 
   1208         }
   1209     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1210         if (index >= BCM_MAX_INNER_TPID_ENTRIES)  {
   1211             return (BCM_E_PARAM); 
   1212         }
   1213         soc_reg_field_set(unit, INNER_TPIDr, &rval, TPIDf, value);
   1214         rv = soc_reg32_set(unit, INNER_TPIDr, REG_PORT_ANY, 0, rval);
   1215         if (BCM_FAILURE(rv)) {
   1216             return (BCM_E_PARAM); 
   1217         }
   1218     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1219         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1220             return (BCM_E_PARAM); 
   1221         }
   1222         soc_reg_field_set(unit, subport_tpid[index], &rval, TPIDf, value);
   1223         rv = soc_reg32_set(unit, subport_tpid[index], REG_PORT_ANY, 0, rval);
   1224         if (BCM_FAILURE(rv)) {
   1225             return (BCM_E_PARAM); 
   1226         }
   1227     } else {
   1228         return (BCM_E_PARAM); 
   1229     } 
   1230     return (rv);
   1231 }
   1232 
   1233 /*
   1234  * Function :
   1235  *    _bcm_kt2_oam_tpid_entry_get
   1236  * 
   1237  * Purpose  :
   1238  *    Get tpid value for tpid entry index . 
   1239  *
   1240  * Parameters :
   1241  *     unit  - (IN) BCM device number.
   1242  *     tpid  - (OUT) TPID value.
   1243  *     index - (IN) Entry index.
   1244  *
   1245  * Return :
   1246  *    BCM_E_XXX
   1247  */
   1248 int
   1249 _bcm_kt2_oam_tpid_entry_get(int unit, uint16 *tpid, int index, int tpid_type) 
   1250 {
   1251     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1252         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   1253             (KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) {
   1254             return (BCM_E_PARAM);
   1255         }
   1256         *tpid = KT2_OAM_OUTER_TPID_ENTRY(unit, index);
   1257     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1258         if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) ||
   1259             (KT2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) {
   1260             return (BCM_E_PARAM);
   1261         }
   1262         *tpid = KT2_OAM_INNER_TPID_ENTRY(unit, index);
   1263     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1264         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   1265             (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) {
   1266             return (BCM_E_PARAM);
   1267         }
   1268         *tpid = KT2_OAM_SUBPORT_TPID_ENTRY(unit, index);
   1269     } else {
   1270         return (BCM_E_PARAM);
   1271     }
   1272     return (BCM_E_NONE);
   1273 }
   1274 
   1275 /*
   1276  * Function :
   1277  *    _bcm_kt2_oam_tpid_entry_delete
   1278  * 
   1279  * Purpose  :
   1280  *    Delete tpid entry by index.
   1281  *
   1282  * Parameters :
   1283  *     unit  - (IN) BCM device number.
   1284  *     index - (IN) Entry index.
   1285  *
   1286  * Return :
   1287  *    BCM_E_XXX
   1288  */
   1289 int
   1290 _bcm_kt2_tpid_entry_delete(int unit, int index, int tpid_type) 
   1291 {
   1292     int rv = BCM_E_NONE; 
   1293     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1294         BCM_KT2_OUTER_TPID_LOCK(unit);
   1295         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   1296             (KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) {
   1297             rv = BCM_E_PARAM;
   1298             BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1299             return rv;
   1300         }
   1301         KT2_OAM_OUTER_TPID_REF_COUNT(unit, index)--;
   1302         if (0 == KT2_OAM_OUTER_TPID_REF_COUNT(unit, index)) {
   1303             KT2_OAM_OUTER_TPID_ENTRY(unit, index) = default_outer_tpid[index];
   1304             rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 
   1305                                              default_outer_tpid[index]);
   1306         }
   1307         BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1308     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1309         BCM_KT2_INNER_TPID_LOCK(unit);
   1310         if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) ||
   1311             (KT2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) {
   1312             rv = BCM_E_PARAM;
   1313             BCM_KT2_INNER_TPID_UNLOCK(unit);
   1314             return rv;
   1315         }
   1316         KT2_OAM_INNER_TPID_REF_COUNT(unit, index)--;
   1317         if (0 == KT2_OAM_INNER_TPID_REF_COUNT(unit, index)) {
   1318             KT2_OAM_INNER_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID;
   1319             rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 
   1320                                              BCM_OAM_DEFAULT_TPID);
   1321         }
   1322         BCM_KT2_INNER_TPID_UNLOCK(unit);
   1323     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1324         BCM_KT2_SUBPORT_TPID_LOCK(unit);
   1325         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   1326             (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) {
   1327             rv = BCM_E_PARAM;
   1328             BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1329             return rv;
   1330         }
   1331         KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)--;
   1332         if (0 == KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)) {
   1333             KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID;
   1334             rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 
   1335                                              BCM_OAM_DEFAULT_TPID);
   1336         }
   1337         BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1338     } else {
   1339         return (BCM_E_PARAM);
   1340     }
   1341     return (rv);
   1342 }
   1343 
   1344 
   1345 /*
   1346  * Function :
   1347  *    _bcm_kt2_tpid_lkup
   1348  * 
   1349  * Purpose  :
   1350  *    Get tpid entry index for specific tpid value.
   1351  *
   1352  * Parameters :
   1353  *     unit  - (IN) BCM device number.
   1354  *     tpid  - (IN) TPID value.
   1355  *     tpid_type - (IN) Type of the tpid - inner/outer/subport
   1356  *     index - (OUT) Entry index.
   1357  *
   1358  * Return :
   1359  *    BCM_E_XXX
   1360  */
   1361 int
   1362 _bcm_kt2_tpid_lkup(int unit, uint16 tpid, int tpid_type,  int *index)
   1363 {
   1364     int i;
   1365     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 
   1366         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1367             if (KT2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) {
   1368                 *index = i;
   1369                 return BCM_E_NONE;
   1370             }
   1371         }
   1372     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 
   1373         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   1374             if (KT2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) {
   1375                 *index = i;
   1376                 return BCM_E_NONE;
   1377             }
   1378         }
   1379     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 
   1380         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1381             if (KT2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) {
   1382                 *index = i;
   1383                 return BCM_E_NONE;
   1384             }
   1385         }
   1386     }
   1387     return BCM_E_NOT_FOUND;
   1388 }
   1389 
   1390 /*
   1391  * Function:
   1392  *      _bcm_kt2_tpid_entry_add 
   1393  * Purpose:
   1394  *      Add a new TPID entry.
   1395  *      Allocate and initialize memory to cache tpid entries.
   1396  *      Initialize lock for cached tpid entries.
   1397  * Parameters:
   1398  *      unit       - (IN) SOC unit number.
   1399  *      tpid       - (IN) TPID to be added.
   1400  *      tpid_type  - (IN) Type of the tpid - inner/outer/subport
   1401  *      index      - (OUT) Index where the the new TPID is added.
   1402  * Returns:
   1403  *      BCM_E_XXX
   1404  * Notes:
   1405  *      If the same TPID already exists, simply increase the
   1406  * reference count of the cached entry. Otherwise, add the entry
   1407  * to the cached table and write the new entry to hardware.
   1408  * Only four distinct TPID values are currently supported for
   1409  * outer and subport TPID and only one value is supported for
   1410  * inner tpid.
   1411  */
   1412 
   1413 int
   1414 _bcm_kt2_tpid_entry_add(int unit, uint16 tpid, int tpid_type, int *index)
   1415 {
   1416     int rv = BCM_E_NONE;
   1417     int i, free_index;
   1418 
   1419     free_index = -1;
   1420     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 
   1421         BCM_KT2_OUTER_TPID_LOCK(unit);
   1422         /* Search for an existing entry.  */
   1423         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1424             if (KT2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) {
   1425                 KT2_OAM_OUTER_TPID_REF_COUNT(unit, i)++;
   1426                 *index = i;
   1427                 BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1428                 return rv;
   1429             }
   1430         }
   1431         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1432             if (KT2_OAM_OUTER_TPID_REF_COUNT(unit, i) == 0) {
   1433                 free_index = i;
   1434                 break;
   1435             }
   1436         } 
   1437         if (free_index < 0) {
   1438             rv = BCM_E_RESOURCE;
   1439             BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1440             return rv;
   1441         }
   1442         /* Insert the new configuration into tpid table as free
   1443            entry is available  */
   1444         rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   1445         if (BCM_FAILURE(rv)) {
   1446             BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1447             return rv;
   1448         }
   1449         KT2_OAM_OUTER_TPID_ENTRY(unit, free_index) = tpid;
   1450         KT2_OAM_OUTER_TPID_REF_COUNT(unit, free_index)++;
   1451         *index = free_index;
   1452         BCM_KT2_OUTER_TPID_UNLOCK(unit);
   1453     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 
   1454         BCM_KT2_INNER_TPID_LOCK(unit);
   1455         /* Search for an existing entry  */
   1456         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   1457             if (KT2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) {
   1458                 KT2_OAM_INNER_TPID_REF_COUNT(unit, i)++;
   1459                 *index = i;
   1460                 BCM_KT2_INNER_TPID_UNLOCK(unit);
   1461                 return rv;
   1462             }
   1463         }
   1464         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   1465             if (KT2_OAM_INNER_TPID_REF_COUNT(unit, i) == 0) {
   1466                 free_index = i;
   1467                 break;
   1468             }
   1469         } 
   1470         if (free_index < 0) {
   1471             rv = BCM_E_RESOURCE;
   1472             BCM_KT2_INNER_TPID_UNLOCK(unit);
   1473             return rv;
   1474         }
   1475         /* Insert the new configuration into tpid table as free
   1476            entry is available  */
   1477         rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   1478         if (BCM_FAILURE(rv)) {
   1479             BCM_KT2_INNER_TPID_UNLOCK(unit);
   1480             return rv;
   1481         }
   1482         KT2_OAM_INNER_TPID_ENTRY(unit, free_index) = tpid;
   1483         KT2_OAM_INNER_TPID_REF_COUNT(unit, free_index)++;
   1484         *index = free_index;
   1485         BCM_KT2_INNER_TPID_UNLOCK(unit);
   1486     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 
   1487         BCM_KT2_SUBPORT_TPID_LOCK(unit);
   1488         /* Search for an existing entry */
   1489         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1490             if (KT2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) {
   1491                 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, i)++;
   1492                 *index = i;
   1493                 BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1494                 return rv;
   1495             }
   1496         }
   1497         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   1498             if (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, i) == 0) {
   1499                 free_index = i;
   1500                 break;
   1501             }
   1502         } 
   1503         if (free_index < 0) {
   1504             rv = BCM_E_RESOURCE;
   1505             BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1506             return rv;
   1507         }
   1508         /* Insert the new configuration into tpid table as free
   1509            entry is available.  */
   1510         rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   1511         if (BCM_FAILURE(rv)) {
   1512             BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1513             return rv;
   1514         }
   1515         KT2_OAM_SUBPORT_TPID_ENTRY(unit, free_index) = tpid;
   1516         KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, free_index)++;
   1517         *index = free_index;
   1518         BCM_KT2_SUBPORT_TPID_UNLOCK(unit);
   1519     } else {
   1520         rv = BCM_E_PARAM;
   1521     }
   1522     return rv;    
   1523 }
   1524 
   1525 /*
   1526  * Function:
   1527  *     _bcm_kt2_oam_ccm_msecs_to_hw_encode
   1528  * Purpose:
   1529  *     Quanitze CCM interval from msecs to hardware encoding.
   1530  * Parameters:
   1531  *     period -  (IN) CCM interval in milli seconds.
   1532  * Retruns:
   1533  *     Hardware encoding for the specified CCM interval value.
   1534  */
   1535 STATIC int
   1536 _bcm_kt2_oam_ccm_msecs_to_hw_encode(int period)
   1537 {
   1538     int q_period = 0; /* Quantized CCM period value. */
   1539 
   1540     if (0 == period) {
   1541         return (q_period);
   1542     }
   1543 
   1544     /* Find closest supported period */
   1545     for (q_period = 1; _kt2_ccm_intervals[q_period]
   1546             != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) {
   1547         if (period < _kt2_ccm_intervals[q_period]) {
   1548             break;
   1549         }
   1550     }
   1551 
   1552     if (_kt2_ccm_intervals[q_period]
   1553         == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) {
   1554         /* Use the highest defined value */
   1555         --q_period;
   1556     } else {
   1557         if ((period - _kt2_ccm_intervals[q_period - 1])
   1558                 < (_kt2_ccm_intervals[q_period] - period)) {
   1559             /* Closer to the lower value */
   1560             --q_period;
   1561         }
   1562     }
   1563 
   1564     return q_period;
   1565 }
   1566 
   1567 #if defined(BCM_WARM_BOOT_SUPPORT)
   1568 /*
   1569  * Function:
   1570  *     _bcm_kt2_oam_ccm_hw_encode_to_msecs
   1571  * Purpose:
   1572  *     Get CCM interval in msecs for a given hardware encoded value.
   1573  * Parameters:
   1574  *     encode -  (IN) CCM interval hardware encoding.
   1575  * Retruns:
   1576  *     CCM interval in msecs.
   1577  */
   1578 STATIC int
   1579 _bcm_kt2_oam_ccm_hw_encode_to_msecs(int encode)
   1580 {
   1581     return (_kt2_ccm_intervals[encode]);
   1582 }
   1583 #endif
   1584 
   1585 /*
   1586  * Function:
   1587  *     _bcm_kt2_oam_opcode_profile_entry_set
   1588  * Purpose:
   1589  *     Program the OAM opcode control profile fields.
   1590  * Parameters:
   1591  *     unit  - (IN) BCM device number
   1592  *     mem   - (IN) Opcode profile memory - ingress/egress
   1593  *     flags - (IN) Bitmap of opcode control settings.
   1594  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
   1595  * Retruns:
   1596  *     BCM_E_XXX
   1597  */
   1598 STATIC int
   1599 _bcm_kt2_oam_opcode_profile_entry_set(int unit, _bcm_oam_hash_data_t *h_data_p,
   1600                                       soc_mem_t mem,
   1601                                       uint32 flags,
   1602                                       void *entry)
   1603 {
   1604     uint32 ep_opcode;        /* Endpoint opcode flag bits. */
   1605     uint32 opcode_count = 0; /* Number of bits set.        */
   1606     int    bp;               /* bit position.              */
   1607     int    rv = BCM_E_NONE;  /* Opreation return status.   */
   1608     
   1609     /* Validate opcode flag bits. */
   1610     if (flags & ~(_BCM_KT2_OAM_OPCODE_MASK)) {
   1611         return (BCM_E_PARAM);
   1612     }
   1613 
   1614     /* Get number of valid opcodes supported. */
   1615     opcode_count = _shr_popcount(_BCM_KT2_OAM_OPCODE_MASK);
   1616 
   1617     /*
   1618      * Iterate over opcode flag bits and set corresponding fields
   1619      * in entry buffer.
   1620      */
   1621     for (bp = 0; bp < opcode_count; bp++) {
   1622         ep_opcode = (flags & (1 << bp));
   1623 
   1624         switch (ep_opcode) {
   1625             case BCM_OAM_OPCODE_CCM_COPY_TO_CPU:
   1626                 soc_mem_field32_set(unit, mem, entry, CCM_COPYTO_CPUf, 1);
   1627                 break;
   1628 
   1629             case BCM_OAM_OPCODE_CCM_IN_HW:
   1630                 soc_mem_field32_set(unit, mem, entry, CCM_PROCESS_IN_HWf, 1);
   1631                 break;
   1632 
   1633             case BCM_OAM_OPCODE_CCM_DROP:
   1634                 soc_mem_field32_set(unit, mem, entry, CCM_DROPf, 1);
   1635                 break;
   1636 
   1637             case BCM_OAM_OPCODE_LBM_IN_HW:
   1638                 soc_mem_field32_set(unit, mem, entry, LBM_ACTIONf, 1);
   1639                 break;
   1640 
   1641             case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU:
   1642                 soc_mem_field32_set(unit, mem, entry, LBM_UC_COPYTO_CPUf, 1);
   1643                 break;
   1644 
   1645             case BCM_OAM_OPCODE_LBM_UC_DROP:
   1646                 soc_mem_field32_set(unit, mem, entry, LBM_UC_DROPf, 1);
   1647                 break;
   1648 
   1649             case BCM_OAM_OPCODE_LBM_MC_DROP:
   1650                 soc_mem_field32_set(unit, mem, entry, LBM_MC_DROPf, 1);
   1651                 break;
   1652 
   1653             case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU:
   1654                 soc_mem_field32_set(unit, mem, entry, LBM_MC_COPYTO_CPUf, 1);
   1655                 break;
   1656 
   1657             case BCM_OAM_OPCODE_LBR_COPY_TO_CPU:
   1658                 soc_mem_field32_set(unit, mem, entry, LBR_COPYTO_CPUf, 1);
   1659                 break;
   1660 
   1661             case BCM_OAM_OPCODE_LBR_DROP:
   1662                 soc_mem_field32_set(unit, mem, entry, LBR_DROPf, 1);
   1663                 break;
   1664 
   1665             case BCM_OAM_OPCODE_LTM_COPY_TO_CPU:
   1666                 soc_mem_field32_set(unit, mem, entry, LTM_COPYTO_CPUf, 1);
   1667                 break;
   1668 
   1669             case BCM_OAM_OPCODE_LTM_DROP:
   1670                 soc_mem_field32_set(unit, mem, entry, LTM_DROPf, 1);
   1671                 break;
   1672 
   1673             case BCM_OAM_OPCODE_LTR_COPY_TO_CPU:
   1674                 soc_mem_field32_set(unit, mem, entry, LTR_COPYTO_CPUf, 1);
   1675                 break;
   1676 
   1677             case BCM_OAM_OPCODE_LTR_DROP:
   1678                 soc_mem_field32_set(unit, mem, entry, LTR_DROPf, 1);
   1679                 break;
   1680 
   1681             case BCM_OAM_OPCODE_LMEP_PKT_FWD:
   1682                 soc_mem_field32_set(unit, mem, entry, FWD_LMEP_PKTf, 1);
   1683                 break;
   1684 
   1685             case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU:
   1686                 soc_mem_field32_set(unit, mem, entry, 
   1687                         OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_COPYTO_CPUf, 1);
   1688                 soc_mem_field32_set (unit, mem, entry, 
   1689                         OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_COPYTO_CPUf, 1);
   1690                 soc_mem_field32_set (unit, mem, entry, 
   1691                         OTHER_OPCODE_GROUP_1_LOW_MDL_COPYTO_CPUf, 1);
   1692                 soc_mem_field32_set (unit, mem, entry, 
   1693                         OTHER_OPCODE_GROUP_1_MC_COPYTO_CPUf, 1);
   1694                 soc_mem_field32_set(unit, mem, entry, 
   1695                         OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_COPYTO_CPUf, 1);
   1696                 soc_mem_field32_set (unit, mem, entry, 
   1697                         OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_COPYTO_CPUf, 1);
   1698                 soc_mem_field32_set (unit, mem, entry, 
   1699                         OTHER_OPCODE_GROUP_2_LOW_MDL_COPYTO_CPUf, 1);
   1700                 soc_mem_field32_set (unit, mem, entry, 
   1701                         OTHER_OPCODE_GROUP_2_MC_COPYTO_CPUf, 1);
   1702                 break;
   1703 
   1704             case BCM_OAM_OPCODE_OTHER_DROP:
   1705                 soc_mem_field32_set(unit, mem, entry, 
   1706                            OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf, 1);
   1707                 soc_mem_field32_set(unit, mem, entry, 
   1708                            OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf, 1);
   1709                 soc_mem_field32_set(unit, mem, entry, 
   1710                            OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf, 1);
   1711                 soc_mem_field32_set(unit, mem, entry, 
   1712                            OTHER_OPCODE_GROUP_1_MC_ACTIONf, 1);
   1713                 soc_mem_field32_set(unit, mem, entry, 
   1714                            OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf, 1);
   1715                 soc_mem_field32_set(unit, mem, entry, 
   1716                            OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf, 1);
   1717                 soc_mem_field32_set(unit, mem, entry, 
   1718                            OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf, 1);
   1719                 soc_mem_field32_set(unit, mem, entry, 
   1720                            OTHER_OPCODE_GROUP_2_MC_ACTIONf, 1);
   1721                 break;
   1722 
   1723             default:
   1724                 break;
   1725         }
   1726     }
   1727     if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   1728         soc_mem_field32_set(unit, mem, entry, LOW_MDL_CCM_FWD_ACTIONf, 0);
   1729         soc_mem_field32_set(unit, mem, entry, LOW_MDL_LB_LT_DROPf, 0);
   1730         soc_mem_field32_set(unit, mem, entry, LB_LT_UC_MY_STATION_MISS_DROPf, 0);
   1731     } else {
   1732         /* Set the opcode action values of the newly introduced CFM opcode actions
   1733            to values that match with the legacy behavior for these opcodes */
   1734         /* LOW MDL CCM / LB/LT drop and LB/LT my station miss drop */
   1735         soc_mem_field32_set(unit, mem, entry, LOW_MDL_CCM_FWD_ACTIONf, 2);
   1736         soc_mem_field32_set(unit, mem, entry, LOW_MDL_LB_LT_DROPf, 1);
   1737         soc_mem_field32_set(unit, mem, entry, LB_LT_UC_MY_STATION_MISS_DROPf, 1);
   1738     }
   1739     return rv;
   1740 }
   1741 
   1742 
   1743 /*
   1744  * Function:
   1745  *     _bcm_kt2_oam_opcode_profile_entry_init
   1746  * Purpose:
   1747  *     Setup default OAM opcode control profile settings for MEP.
   1748  * Parameters:
   1749  *     unit  - (IN) BCM device number
   1750  *     mem   - (IN) Opcode profile memory - ingress/egress
   1751  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
   1752  * Retruns:
   1753  *     BCM_E_XXX
   1754  */
   1755 int
   1756 _bcm_kt2_oam_opcode_profile_entry_init(int unit, soc_mem_t mem,
   1757                                        void *entry)
   1758 {
   1759     uint32 opcode; /* Opcode flag bits.        */
   1760     int    rv;     /* Operation return status. */
   1761 
   1762     _bcm_oam_hash_data_t h_data;
   1763     sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 
   1764 
   1765     h_data.type = bcmOAMEndpointTypeEthernet;
   1766 
   1767     opcode =  (BCM_OAM_OPCODE_CCM_COPY_TO_CPU |
   1768                     BCM_OAM_OPCODE_CCM_DROP |
   1769                     BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
   1770                     BCM_OAM_OPCODE_LBM_UC_DROP |
   1771                     BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
   1772                     BCM_OAM_OPCODE_LBM_MC_DROP |
   1773                     BCM_OAM_OPCODE_LBR_COPY_TO_CPU |
   1774                     BCM_OAM_OPCODE_LBR_DROP |
   1775                     BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
   1776                     BCM_OAM_OPCODE_LTM_DROP |
   1777                     BCM_OAM_OPCODE_LTR_COPY_TO_CPU |
   1778                     BCM_OAM_OPCODE_LTR_DROP |
   1779                     BCM_OAM_OPCODE_OTHER_COPY_TO_CPU |
   1780                     BCM_OAM_OPCODE_OTHER_DROP 
   1781                     );
   1782 
   1783     rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, &h_data, mem, opcode, entry);
   1784     return rv;
   1785 }
   1786 
   1787 /*
   1788  * Function:
   1789  *     _bcm_kt2_oam_mip_opcode_profile_entry_init
   1790  * Purpose:
   1791  *     Setup default OAM opcode control profile settings for MIP.
   1792  * Parameters:
   1793  *     unit  - (IN) BCM device number
   1794  *     mem   - (IN) Opcode profile memory - ingress/egress
   1795  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
   1796  * Retruns:
   1797  *     BCM_E_XXX
   1798  */
   1799 int
   1800 _bcm_kt2_oam_mip_opcode_profile_entry_init(int unit, soc_mem_t mem,
   1801                                        void *entry)
   1802 {
   1803     uint32 opcode; /* Opcode flag bits.        */
   1804     int    rv;     /* Operation return status. */
   1805 
   1806     _bcm_oam_hash_data_t h_data;
   1807     sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t));
   1808 
   1809     h_data.flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
   1810     h_data.type = bcmOAMEndpointTypeEthernet;
   1811     opcode =  (BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
   1812             BCM_OAM_OPCODE_LBM_UC_DROP |
   1813             BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
   1814             BCM_OAM_OPCODE_LBM_MC_DROP |
   1815             BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
   1816             BCM_OAM_OPCODE_LTM_DROP);
   1817     
   1818     rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, &h_data, mem, opcode, entry);
   1819     return rv;
   1820 }
   1821 
   1822 /*
   1823  * Function:
   1824  *     _bcm_kt2_oam_opcode_group_init
   1825  * Purpose:
   1826  *     Init ingress and egress OAM opcode groups. 
   1827  * Parameters:
   1828  *     unit  - (IN) BCM device number
   1829  * Retruns:
   1830  *     BCM_E_XXX
   1831  */
   1832 int
   1833 _bcm_kt2_oam_opcode_group_init(int unit)
   1834 {
   1835     int                       rv = BCM_E_NONE; 
   1836     ingress_oam_opcode_group_entry_t    *opcode_grp_buf;
   1837     ingress_oam_opcode_group_entry_t    *opcode_grp_entry;
   1838     int                       entry_mem_size;    /* Size of table entry. */ 
   1839     int                       index_max = 0;
   1840     int                       index = 0;
   1841     bcm_oam_endpoint_action_t action;
   1842     BCM_OAM_ACTION_CLEAR_ALL(action);
   1843     BCM_OAM_OPCODE_CLEAR_ALL(action);
   1844 
   1845    /* Set ingress and egress OAM opcode group */
   1846     entry_mem_size = sizeof(ingress_oam_opcode_group_entry_t);
   1847     /* Allocate buffer to store the DMAed table entries. */
   1848     index_max = soc_mem_index_max(unit, INGRESS_OAM_OPCODE_GROUPm);
   1849     opcode_grp_buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1),
   1850                               "Opcode group entry buffer");
   1851     if (NULL == opcode_grp_buf) {
   1852         return (BCM_E_MEMORY);
   1853     }
   1854     /* Initialize the entry buffer. */
   1855     sal_memset(opcode_grp_buf, 0, sizeof(entry_mem_size) * (index_max + 1));
   1856 
   1857     for (index = 0; index <= index_max; index++) {
   1858         opcode_grp_entry = soc_mem_table_idx_to_pointer
   1859                     (unit, INGRESS_OAM_OPCODE_GROUPm, 
   1860                      ingress_oam_opcode_group_entry_t *,
   1861                      opcode_grp_buf, index);
   1862         if (index <= _BCM_OAM_OPCODE_TYPE_LTM) {
   1863             /* For CFM packets group valid = 0 */
   1864             soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 
   1865                           (uint32 *)opcode_grp_entry, OPCODE_GROUP_VALIDf, 0);
   1866         } else {
   1867             /* For Non-CFM packets group valid = 1 and group is opcode group 1*/
   1868             soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 
   1869                           (uint32 *)opcode_grp_entry, OPCODE_GROUP_VALIDf, 1);
   1870             soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 
   1871                           (uint32 *)opcode_grp_entry, OPCODE_GROUPf, 0);
   1872         }
   1873     }
   1874     rv = soc_mem_write_range(unit, INGRESS_OAM_OPCODE_GROUPm,
   1875                             MEM_BLOCK_ALL, 0, index_max, opcode_grp_buf);
   1876     if (BCM_FAILURE(rv)) {
   1877         if (opcode_grp_buf) {
   1878             soc_cm_sfree(unit, opcode_grp_buf);
   1879         }
   1880         return rv;
   1881     }
   1882     rv = soc_mem_write_range(unit, EGR_OAM_OPCODE_GROUPm,
   1883                             MEM_BLOCK_ALL, 0, index_max, opcode_grp_buf); 
   1884     if (BCM_FAILURE(rv)) {
   1885         if (opcode_grp_buf) {
   1886             soc_cm_sfree(unit, opcode_grp_buf);
   1887         }
   1888         return rv;
   1889     }
   1890     if (opcode_grp_buf) {
   1891          soc_cm_sfree(unit, opcode_grp_buf);
   1892     }
   1893     return (rv);
   1894 }
   1895 
   1896 STATIC void
   1897 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(int unit, uint8 active_mdl, 
   1898                                              int ma_base_index,
   1899                                              uint8 *passive_mdl,
   1900                                              int is_upmep)
   1901 {
   1902     uint32               mdl_value[1] = { 0 };
   1903     int ma_offset = 0;
   1904     int mdl = 0;
   1905     bcm_oam_endpoint_t ep_id_at_mdl = _BCM_OAM_INVALID_INDEX;
   1906     _bcm_oam_control_t  *oc = NULL;
   1907     _bcm_oam_hash_data_t *h_data_p = NULL;
   1908 
   1909     /* coverity[check_return] */
   1910     _bcm_kt2_oam_control_get(unit, &oc);
   1911 
   1912     if (oc == NULL) {
   1913         /* Not expected */
   1914         return;
   1915     }
   1916  
   1917     /* Initialize passive_mdl to 0 */ 
   1918     *passive_mdl = 0; 
   1919     mdl_value[0] = active_mdl; 
   1920 
   1921     for (mdl = 0; mdl <= 7; mdl++) {
   1922         if (SHR_BITGET(mdl_value, mdl)) {
   1923             ep_id_at_mdl = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get(oc, 
   1924                             _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   1925                             (ma_base_index, ma_offset, is_upmep)); 
   1926             if (ep_id_at_mdl != _BCM_OAM_INVALID_INDEX) { 
   1927                 h_data_p = &(oc->oam_hash_data[ep_id_at_mdl]);
   1928                 /* Set the passive bitmap only if it is not a MIP */
   1929                 if (!_BCM_OAM_EP_IS_MIP(h_data_p)) {
   1930                     *passive_mdl = (1 << mdl) | ((1 << mdl) -1);
   1931                 }
   1932             } else {
   1933                 /* Log an error. Ideally should not happen. */
   1934                 LOG_ERROR(BSL_LS_BCM_OAM,
   1935                         (BSL_META_U(unit,
   1936                                     "OAM(unit %d) Error: EP ID mapping get failed (MA_IDX=%d) -"
   1937                                     "\n"), unit, ma_base_index+ma_offset));
   1938             }
   1939             ma_offset++;
   1940         }
   1941     }
   1942 }
   1943 
   1944 
   1945 
   1946 /*
   1947  * Function:
   1948  *     _bcm_kt2_oam_ep_hash_key_construct
   1949  * Purpose:
   1950  *     Construct hash table key for a given endpoint information.
   1951  * Parameters:
   1952  *     unit    - (IN) BCM device number
   1953  *     oc      - (IN) Pointer to OAM control structure.
   1954  *     ep_info - (IN) Pointer to endpoint information structure.
   1955  *     key     - (IN/OUT) Pointer to hash key buffer.
   1956  * Retruns:
   1957  *     None
   1958  */
   1959 STATIC void
   1960 _bcm_kt2_oam_ep_hash_key_construct(int unit,
   1961                                _bcm_oam_control_t *oc,
   1962                                bcm_oam_endpoint_info_t *ep_info,
   1963                                _bcm_oam_hash_key_t *key)
   1964 {
   1965     uint8  *loc = *key;
   1966     uint32 direction = 0;
   1967 
   1968     sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t));
   1969 
   1970     if (NULL != ep_info) {
   1971         if ((ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING)) {
   1972             direction = 1;
   1973         }
   1974 
   1975         _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group));
   1976 
   1977         _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name));
   1978 
   1979         _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport));
   1980 
   1981         _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level));
   1982 
   1983         _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan));
   1984 
   1985         _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 
   1986                                           sizeof(ep_info->inner_vlan));
   1987         _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction));
   1988     }
   1989 
   1990     /* End address should not exceed size of _bcm_oam_hash_key_t. */
   1991     assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t));
   1992 }
   1993 
   1994 /*
   1995  * Function:
   1996  *     _bcm_oam_egr_lmep_key_construct
   1997  * Purpose:
   1998  *     Construct egress MP group table lookup key for a given endpoint.
   1999  * Parameters:
   2000  *     unit     - (IN) BCM device number
   2001  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   2002  *     egr_mp_grp_key_p - (IN/OUT) Pointer to entry buffer.
   2003  * Retruns:
   2004  *     None
   2005  */
   2006 STATIC void
   2007 _bcm_oam_egr_lmep_key_construct(int unit,
   2008                             const _bcm_oam_hash_data_t *h_data_p,
   2009                             egr_mp_group_entry_t *egr_mp_grp_key_p)
   2010 {
   2011     _bcm_oam_control_t  *oc = NULL;
   2012 
   2013     /* coverity[check_return] */
   2014     _bcm_kt2_oam_control_get(unit, &oc);
   2015 
   2016     /* Set the valid bit. */
   2017     soc_EGR_MP_GROUPm_field32_set
   2018         (unit, egr_mp_grp_key_p, VALIDf, 1);
   2019     /* Set the search key type. */
   2020     soc_EGR_MP_GROUPm_field32_set
   2021         (unit, egr_mp_grp_key_p, KEY_TYPEf, h_data_p->oam_domain);
   2022 
   2023     if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_BHH) {
   2024 
   2025         /* Set port type status in the search key. */
   2026         if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) {
   2027 
   2028             /* DGLP field contains virtual port. */
   2029             soc_EGR_MP_GROUPm_field32_set
   2030                 (unit, egr_mp_grp_key_p, DGLPf, h_data_p->vp);
   2031 
   2032         } else {
   2033             if (oc->eth_oam_mp_group_vlan_key ==
   2034                               _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) {
   2035                 /* In earlier versions of the SDK, both inner & outer vlan was
   2036                  * always programmed in the MP_GROUP irrespective of the MEP
   2037                  * type, this has been changed to program only CVLAN for CVLAN
   2038                  * MEPs and SVLAN for SVLAN MEPs. To avoid breaking warm-upgrade
   2039                  * the old scheme is still supported.
   2040                  */
   2041                 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   2042                                               SVIDf, h_data_p->vlan);
   2043 
   2044                 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   2045                                               CVIDf, h_data_p->inner_vlan);
   2046             } else {
   2047                 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) {
   2048                     /* SVLAN/C+SVLAN */
   2049                     soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   2050                                                   SVIDf, h_data_p->vlan);
   2051                 }
   2052 
   2053                 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) {
   2054                     /* CLVAN/C+SVLAN */
   2055                     soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   2056                                                   CVIDf, h_data_p->inner_vlan);
   2057                 }
   2058             }
   2059             /* DGLP contains generic logical port. */
   2060             soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   2061                                           DGLPf, h_data_p->dglp);
   2062         }
   2063     } 
   2064 #if defined(INCLUDE_BHH)
   2065     else {
   2066 
   2067         /* BHH Domain, Key = Next Hop Index 
   2068            BHH API have been using L3_EGRESS type in 
   2069            bcm_oam_endpoint_info_t.intf field. 
   2070            However for supporting LM/DM on Katana2 this should be DVP_EGRESS type,
   2071            only CCM will work with L3_EGRESS type, retaining the old type for 
   2072            backward compatibility */
   2073         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) {
   2074             soc_EGR_MP_GROUPm_field32_set (unit, egr_mp_grp_key_p, NHIf, 
   2075                 h_data_p->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit));
   2076         } else {
   2077             if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) {
   2078                 soc_EGR_MP_GROUPm_field32_set (unit, egr_mp_grp_key_p, NHIf, 
   2079                     h_data_p->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   2080             }
   2081         }
   2082     }
   2083 #endif
   2084 
   2085 }
   2086 
   2087 /*
   2088  * Function:
   2089  *     _bcm_kt2_oam_lmep_key_construct
   2090  * Purpose:
   2091  *     Construct LMEP view lookup key for a given endpoint.
   2092  * Parameters:
   2093  *     unit     - (IN) BCM device number
   2094  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   2095  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
   2096  * Retruns:
   2097  *     None
   2098  */
   2099 STATIC void
   2100 _bcm_kt2_oam_lmep_key_construct(int unit,
   2101                             const _bcm_oam_hash_data_t *h_data_p,
   2102                             l3_entry_1_entry_t *l3_key_p)
   2103 {
   2104     _bcm_oam_control_t  *oc = NULL;
   2105 
   2106     /* coverity[check_return] */
   2107     _bcm_kt2_oam_control_get(unit, &oc);
   2108 
   2109     /* Set the search key type. */
   2110     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2111         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_LMEP);
   2112 
   2113     /* Set the search key sub type. */
   2114     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2115         (unit, l3_key_p, LMEP__OAM_LMEP_KEY_SUBTYPEf, 
   2116                                    h_data_p->oam_domain);
   2117     
   2118     if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_BHH) {
   2119 
   2120         /* Set port type status in the search key. */
   2121         if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) {
   2122             /* SGLP field contains virtual port. */
   2123             soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2124                 (unit, l3_key_p, LMEP__SGLPf, h_data_p->vp);
   2125 
   2126         } else {
   2127             if (oc->eth_oam_mp_group_vlan_key ==
   2128                               _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) {
   2129                 /* In earlier versions of the SDK, both inner & outer vlan was
   2130                  * always programmed in the MP_GROUP irrespective of the MEP
   2131                  * type, this has been changed to program only CVLAN for CVLAN
   2132                  * MEPs and SVLAN for SVLAN MEPs. To avoid breaking warm-upgrade
   2133                  * the old scheme is still supported.
   2134                  */
   2135                 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__SVIDf,
   2136                                                        h_data_p->vlan);
   2137 
   2138                 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__CVIDf,
   2139                                                        h_data_p->inner_vlan);
   2140             } else {
   2141                 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) {
   2142                     /* SVLAN/C+SVLAN */
   2143                     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p,
   2144                                                            LMEP__SVIDf,
   2145                                                            h_data_p->vlan);
   2146                 }
   2147 
   2148                 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) {
   2149                     /* CLVAN/C+SVLAN */
   2150                     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p,
   2151                                                            LMEP__CVIDf,
   2152                                                            h_data_p->inner_vlan);
   2153                 }
   2154             }
   2155             /* SGLP contains generic logical port. */
   2156             soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__SGLPf,
   2157                                                    h_data_p->sglp);
   2158 
   2159         }
   2160     } 
   2161 #if defined(INCLUDE_BHH)
   2162     else {
   2163  
   2164             /* If the label is not global, set port */
   2165             if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 
   2166                  BCM_GPORT_INVALID) != BCM_E_NONE) {
   2167                 /* SGLP contains generic logical port. */
   2168                 soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2169                     (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp);
   2170             } else {
   2171                 /* SGLP contains generic logical port. */
   2172                 soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2173                     (unit, l3_key_p, LMEP__SGLPf, 0xFFFF);
   2174                 
   2175             }
   2176 
   2177             /* Set incoming MPLS Label */
   2178             soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2179                 (unit, l3_key_p, LMEP__MPLS_LABELf, h_data_p->label);
   2180 
   2181     }
   2182 #endif
   2183 }
   2184 
   2185 /*
   2186  * Function:
   2187  *     _bcm_kt2_oam_rmep_key_construct
   2188  * Purpose:
   2189  *     Construct RMEP view lookup key for a given endpoint.
   2190  * Parameters:
   2191  *     unit     - (IN) BCM device number
   2192  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   2193  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
   2194  * Retruns:
   2195  *     None
   2196  */
   2197 STATIC void
   2198 _bcm_kt2_oam_rmep_key_construct(int unit,
   2199                             const _bcm_oam_hash_data_t *h_data_p,
   2200                             l3_entry_1_entry_t *l3_key_p)
   2201 {
   2202 
   2203     /* Set the search key type. */
   2204     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2205         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP);
   2206 
   2207     /* Set endpoint name. */
   2208     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2209         (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name);
   2210 
   2211     /* Set MA_PTR */
   2212     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   2213         (unit, l3_key_p, RMEP__MA_PTRf, h_data_p->group_index);
   2214 
   2215 }
   2216 
   2217 #if defined(KEY_PRINT)
   2218 /*
   2219  * Function:
   2220  *     _bcm_oam_hash_key_print
   2221  * Purpose:
   2222  *     Print the contents of a hash key buffer. 
   2223  * Parameters:
   2224  *     hash_key - (IN) Pointer to hash key buffer.
   2225  * Retruns:
   2226  *     None
   2227  */
   2228 STATIC void
   2229 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key)
   2230 {
   2231     int i;
   2232     LOG_CLI((BSL_META_U(unit,
   2233                         "HASH KEY:")));
   2234     for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) {
   2235         LOG_CLI((BSL_META_U(unit,
   2236                             ":%u"), *(hash_key[i])));
   2237     }
   2238     LOG_CLI((BSL_META_U(unit,
   2239                         "\n")));
   2240 }
   2241 #endif
   2242 
   2243 /*
   2244  * Function:
   2245  *     _bcm_kt2_oam_control_get
   2246  * Purpose:
   2247  *     Lookup a OAM control config from a bcm device id.
   2248  * Parameters:
   2249  *     unit -  (IN)BCM unit number.
   2250  *     oc   -  (OUT) OAM control structure.
   2251  * Retruns:
   2252  *     BCM_E_XXX
   2253  */
   2254 STATIC int
   2255 _bcm_kt2_oam_control_get(int unit, _bcm_oam_control_t **oc)
   2256 {
   2257     if (NULL == oc) {
   2258         return (BCM_E_PARAM);
   2259     }
   2260 
   2261     /* Ensure oam module is initialized. */
   2262     _BCM_OAM_IS_INIT(unit);
   2263 
   2264     *oc = _kt2_oam_control[unit];
   2265 
   2266     return (BCM_E_NONE);
   2267 }
   2268 
   2269 /*
   2270  * Function:
   2271  *     _bcm_kt2_oam_group_endpoint_count_init
   2272  * Purpose:
   2273  *     Retrieves and initializes endpoint count information for this device.
   2274  * Parameters:
   2275  *     unit -  (IN) BCM unit number.
   2276  *     oc   -  (IN) Pointer to device OAM control structure.
   2277  * Retruns:
   2278  *     BCM_E_XXX
   2279  */
   2280 STATIC int
   2281 _bcm_kt2_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc)
   2282 {
   2283     /* Input parameter check. */
   2284     if (NULL == oc) {
   2285         return (BCM_E_PARAM);
   2286     }
   2287 
   2288     /*
   2289      * Get endpoint hardware table index count values and
   2290      * initialize device OAM control structure members variables.
   2291      */
   2292     oc->rmep_count = soc_mem_index_count(unit, RMEPm);
   2293     oc->lmep_count = soc_mem_index_count(unit, LMEPm);
   2294     oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm);
   2295     oc->egr_ma_idx_count = soc_mem_index_count(unit, EGR_MA_INDEXm);
   2296 
   2297     /* Max number of endpoints supported by the device. */
   2298     oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + 
   2299                                                    oc->egr_ma_idx_count);
   2300 
   2301     LOG_VERBOSE(BSL_LS_BCM_OAM,
   2302                 (BSL_META_U(unit,
   2303                             "OAM Info: Total No. endpoint Count = %d.\n"),
   2304                  oc->ep_count));
   2305 
   2306     /* Max number of MA Groups supported by device. */
   2307     oc->group_count = soc_mem_index_count(unit, MA_STATEm);
   2308     LOG_VERBOSE(BSL_LS_BCM_OAM,
   2309                 (BSL_META_U(unit,
   2310                             "OAM Info: Total No. Group Count = %d.\n"),
   2311                  oc->group_count));
   2312 
   2313     oc->lm_counter_cnt = soc_mem_index_count(unit, OAM_LM_COUNTERS_0m);
   2314     return (BCM_E_NONE);
   2315 }
   2316 
   2317 /*
   2318  * Function:
   2319  *     _bcm_kt2_oam_ccm_rx_timeout_enable
   2320  * Purpose:
   2321  *     Enable CCM Timer operations for endpoint state table.
   2322  * Parameters:
   2323  *     unit -  (IN) BCM unit number.
   2324  *     state - (IN) Enable/Disable.
   2325  * Retruns:
   2326  *     BCM_E_XXX
   2327  * Note:
   2328  *     RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only.
   2329  */
   2330 STATIC int
   2331 _bcm_kt2_oam_ccm_rx_timeout_set(int unit, uint8 state)
   2332 {
   2333     int     rv;       /* Opreation return status.   */
   2334     uint32  rval = 0; /* Register value.            */
   2335 
   2336     /* Enable timer instructions to RMEP/MA_STATE Table. */
   2337     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   2338                       TIMER_ENABLEf, state ? 1 : 0);
   2339 
   2340     /* Set Clock granularity to 250us ticks - 1. */
   2341     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   2342                       CLK_GRANf, 1);
   2343 
   2344     rv = WRITE_OAM_TIMER_CONTROLr(unit, rval);
   2345     if (BCM_FAILURE(rv)) {
   2346         LOG_ERROR(BSL_LS_BCM_OAM,
   2347                   (BSL_META_U(unit,
   2348                               "OAM Error: Timer enable - Failed.\n")));
   2349         return (rv);
   2350     }
   2351 
   2352     return (rv);
   2353 }
   2354 
   2355 /*
   2356  * Function:
   2357  *     _bcm_kt2_oam_ccm_tx_config_enable
   2358  * Purpose:
   2359  *     Enable transmission of OAM PDUs on local endpoint.
   2360  * Parameters:
   2361  *     unit -  (IN) BCM unit number.
   2362  *     state - (IN) Enable/Disable
   2363  * Retruns:
   2364  *     BCM_E_XXX
   2365  */
   2366 STATIC int
   2367 _bcm_kt2_oam_ccm_tx_config_set(int unit, uint8 state)
   2368 {
   2369     int     rv;       /* Opreation return status.   */
   2370     uint32  rval = 0; /* Register value.            */
   2371 
   2372     /* Enable OAM LMEP Tx. */
   2373     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   2374                       TX_ENABLEf, state ? 1 : 0);
   2375 
   2376     /* Enable CMIC buffer. */
   2377     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   2378                       CMIC_BUF_ENABLEf, state ? 1 : 0);
   2379 
   2380     rv = WRITE_OAM_TX_CONTROLr(unit, rval);
   2381     if (BCM_FAILURE(rv)) {
   2382         LOG_ERROR(BSL_LS_BCM_OAM,
   2383                   (BSL_META_U(unit,
   2384                               "OAM Error: Tx config enable - Failed.\n")));
   2385     }
   2386     return (rv);
   2387 }
   2388 
   2389 /*
   2390  * Function:
   2391  *     _bcm_kt2_oam_misc_config
   2392  * Purpose:
   2393  *     Miscellaneous OAM configurations:
   2394  *         1. Enable IFP lookup on the CPU port. 
   2395  * Parameters:
   2396  *     unit -  (IN) BCM unit number.
   2397  * Retruns:
   2398  *     BCM_E_XXX
   2399  */
   2400 STATIC int
   2401 _bcm_kt2_oam_misc_config(int unit)
   2402 {
   2403     int     rv;       /* Opreation return status.   */
   2404 
   2405     /*
   2406      * Enable ingress FP for CPU port so LM/DM packets sent from CPU
   2407      * can be processed.
   2408      */
   2409     rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit),
   2410                                   bcmPortControlFilterIngress, 1);
   2411     if (BCM_FAILURE(rv)) {
   2412         LOG_ERROR(BSL_LS_BCM_OAM,
   2413                   (BSL_META_U(unit,
   2414                               "OAM Error: bcm_esw_port_control_set"
   2415                                " - Failed.\n")));
   2416         return (rv);
   2417     }
   2418     return (rv);
   2419 
   2420 }
   2421 
   2422 /*
   2423  * Function:
   2424  *     _bcm_kt2_oam_profile_tables_init
   2425  * Purpose:
   2426  *     Create ingress and egress service priority mapping profile table and 
   2427  *     setup a default profile. Create Ingress and egress OAM opcode control 
   2428  *     profile table, dglp profile 
   2429  * Parameters:
   2430  *     unit -  (IN) BCM unit number.
   2431  *     oc   -  (IN) Pointer to OAM control structure.
   2432  * Retruns:
   2433  *     BCM_E_XXX
   2434  */
   2435 STATIC int
   2436 _bcm_kt2_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc)
   2437 {
   2438     int         rv = BCM_E_NONE;/* Opreation return status.   */
   2439     soc_mem_t   mem;           /* Profiled table memory.      */
   2440     int         entry_words;   /* Profile table word size.    */
   2441     int         pri;           /* Priority                    */
   2442     void        *entries[1];   /* Profile entry. */
   2443     uint32      profile_index; /* Profile table index. */
   2444     ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX]; /* ing profile */
   2445                                                              /* entry */
   2446     egr_service_pri_map_entry_t egr_pri_ent[BCM_OAM_INTPRI_MAX]; /*egr profile*/
   2447                                                              /* entry */
   2448     bcm_module_t         modid;
   2449     uint32      dglp = 0;
   2450     egr_oam_dglp_profile_entry_t egr_dglp_profile_entry;
   2451     ing_oam_dglp_profile_entry_t ing_dglp_profile_entry;
   2452     oam_opcode_control_profile_entry_t opcode_entry; /* Opcode control 
   2453                                                              profile entry.  */
   2454     egr_oam_opcode_control_profile_entry_t egr_opcode_entry;   
   2455 
   2456     /* Ingress Service Priority Map profile table initialization. */
   2457     soc_profile_mem_t_init(&oc->ing_service_pri_map);
   2458 
   2459     entry_words = (sizeof(ing_service_pri_map_entry_t) / sizeof(uint32));
   2460 
   2461     mem = ING_SERVICE_PRI_MAPm;
   2462     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2463                                 &oc->ing_service_pri_map);
   2464     if (BCM_FAILURE(rv)) {
   2465         LOG_ERROR(BSL_LS_BCM_OAM,
   2466                   (BSL_META_U(unit,
   2467                               "OAM Error: service map profile - Failed.\n")));
   2468         return (rv);
   2469     }
   2470     if (!SOC_WARM_BOOT(unit)) {
   2471         /*
   2472          * Initialize ingress priority map profile table.
   2473          * All priorities priorities map to priority:'0'.
   2474          */
   2475         for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++)
   2476         {
   2477             /* Clear ingress service pri map profile entry. */
   2478             sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem),
   2479                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2480 
   2481             if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   2482             soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1);
   2483             }
   2484         }
   2485 
   2486         
   2487         entries[0] = &pri_ent;
   2488         rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map,
   2489                              (void *)entries, BCM_OAM_INTPRI_MAX,
   2490                              &profile_index);
   2491         if (BCM_FAILURE(rv)) {
   2492             LOG_ERROR(BSL_LS_BCM_OAM,
   2493                       (BSL_META_U(unit,
   2494                                   "OAM Error: service map init - Failed.\n")));
   2495             return (rv);
   2496         }
   2497     }
   2498 
   2499     /* Egress Service Priority Map profile table initialization. */
   2500     soc_profile_mem_t_init(&oc->egr_service_pri_map);
   2501 
   2502     entry_words = (sizeof(egr_service_pri_map_entry_t) / sizeof(uint32));
   2503 
   2504     mem = EGR_SERVICE_PRI_MAPm;
   2505     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2506                                 &oc->egr_service_pri_map);
   2507     if (BCM_FAILURE(rv)) {
   2508         LOG_ERROR(BSL_LS_BCM_OAM,
   2509                   (BSL_META_U(unit,
   2510                               "OAM Error: Egr service map profile - Failed.\n")));
   2511         return (rv);
   2512     }
   2513 
   2514     if (!SOC_WARM_BOOT(unit)) {
   2515 
   2516         /*
   2517          * Initialize Egress priority map profile table.
   2518          * All priorities priorities map to priority:'0'.
   2519          */
   2520         for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++)
   2521         {
   2522             /* Clear ingress service pri map profile entry. */
   2523             sal_memcpy(&egr_pri_ent[pri], soc_mem_entry_null(unit, mem),
   2524                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2525 
   2526             if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   2527                 soc_mem_field32_set(unit, mem, 
   2528                                     &egr_pri_ent[pri], OFFSET_VALIDf, 1);
   2529             }
   2530         }
   2531 
   2532         
   2533         entries[0] = &egr_pri_ent;
   2534         rv = soc_profile_mem_add(unit, &oc->egr_service_pri_map,
   2535                              (void *)entries, BCM_OAM_INTPRI_MAX,
   2536                              &profile_index);
   2537         if (BCM_FAILURE(rv)) {
   2538             LOG_ERROR(BSL_LS_BCM_OAM,
   2539                       (BSL_META_U(unit,
   2540                                   "OAM Error: Egress service map init - Failed.\n")));
   2541             return (rv);
   2542         }
   2543     }
   2544 
   2545     /* OAM Opcode Control profile table initialization. */
   2546     soc_profile_mem_t_init(&oc->oam_opcode_control_profile);
   2547 
   2548     entry_words = sizeof(oam_opcode_control_profile_entry_t)
   2549                          / sizeof(uint32);
   2550 
   2551     mem = OAM_OPCODE_CONTROL_PROFILEm;
   2552     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2553                                 &oc->oam_opcode_control_profile);
   2554     if (BCM_FAILURE(rv)) {
   2555         LOG_ERROR(BSL_LS_BCM_OAM,
   2556                   (BSL_META_U(unit,
   2557                               "OAM Error: opcode control profile - Failed.\n")));
   2558         return (rv);
   2559     }
   2560     if (!SOC_WARM_BOOT(unit)) {
   2561         /* Create default opcode control profile */
   2562         sal_memset(&opcode_entry, 0, sizeof(oam_opcode_control_profile_entry_t));
   2563         rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, mem, &opcode_entry);
   2564         if (BCM_FAILURE(rv)) {
   2565             LOG_ERROR(BSL_LS_BCM_OAM,
   2566                       (BSL_META_U(unit,
   2567                                   "OAM Error: Opcode profile init failed "
   2568                                    "  %s.\n"), bcm_errmsg(rv)));
   2569             return (rv);
   2570         }
   2571         /* Add entry to profile table.  */
   2572         entries[0] = &opcode_entry;
   2573         rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile,
   2574                              (void *)entries, 1, &profile_index);
   2575         if (BCM_FAILURE(rv)) {
   2576             LOG_ERROR(BSL_LS_BCM_OAM,
   2577                       (BSL_META_U(unit,
   2578                                   "OAM Opcode profile table is full - %s.\n"),
   2579                        bcm_errmsg(rv)));
   2580             return rv;
   2581         }
   2582     }
   2583 
   2584     /* Egress OAM Opcode Control profile table initialization. */
   2585     soc_profile_mem_t_init(&oc->egr_oam_opcode_control_profile);
   2586     entry_words = sizeof(egr_oam_opcode_control_profile_entry_t)
   2587                          / sizeof(uint32);
   2588     mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
   2589     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2590                                 &oc->egr_oam_opcode_control_profile);
   2591     if (BCM_FAILURE(rv)) {
   2592         LOG_ERROR(BSL_LS_BCM_OAM,
   2593                   (BSL_META_U(unit,
   2594                               "OAM Error: Egress opcode control profile- Failed.\n")));
   2595         return (rv);
   2596     }
   2597     if (!SOC_WARM_BOOT(unit)) {
   2598         /* Create default opcode control profile */
   2599         sal_memset(&egr_opcode_entry, 0, 
   2600                              sizeof(egr_oam_opcode_control_profile_entry_t));
   2601         rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, mem, &egr_opcode_entry);
   2602         if (BCM_FAILURE(rv)) {
   2603             LOG_ERROR(BSL_LS_BCM_OAM,
   2604                       (BSL_META_U(unit,
   2605                                   "OAM Error: Opcode profile init failed "
   2606                                    "  %s.\n"), bcm_errmsg(rv)));
   2607             return (rv);
   2608         }
   2609         /* Add entry to profile table.  */
   2610         entries[0] = &egr_opcode_entry;
   2611         rv = soc_profile_mem_add(unit, &oc->egr_oam_opcode_control_profile,
   2612                              (void *)entries, 1, &profile_index);
   2613         if (BCM_FAILURE(rv)) {
   2614             LOG_ERROR(BSL_LS_BCM_OAM,
   2615                       (BSL_META_U(unit,
   2616                                   "OAM Egr Opcode profile table is full - %s.\n"),
   2617                        bcm_errmsg(rv)));
   2618             return rv;
   2619         }
   2620     }
   2621 
   2622     /* Ingress OAM dglp profile table initialisation */
   2623     soc_profile_mem_t_init(&oc->ing_oam_dglp_profile);
   2624 
   2625     entry_words = sizeof(ing_oam_dglp_profile_entry_t) / sizeof(uint32);
   2626 
   2627     mem = ING_OAM_DGLP_PROFILEm;
   2628     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2629                                 &oc->ing_oam_dglp_profile);
   2630     if (BCM_FAILURE(rv)) {
   2631         LOG_ERROR(BSL_LS_BCM_OAM,
   2632                   (BSL_META_U(unit,
   2633                               "OAM Error: ING OAM DGLP profile create - Failed.\n")));
   2634         return (rv);
   2635     }
   2636     if (!SOC_WARM_BOOT(unit)) {
   2637         /* Add default profile */
   2638         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   2639         /* put local CPU as default dglp */
   2640         dglp = CMIC_PORT(unit);
   2641         dglp |= ((modid << DGLP_MODULE_ID_SHIFT_BITS)); 
   2642 
   2643         soc_mem_field32_set(unit, ING_OAM_DGLP_PROFILEm, 
   2644                         &ing_dglp_profile_entry, DGLPf, dglp);
   2645         entries[0] = &ing_dglp_profile_entry;
   2646 
   2647         rv = soc_profile_mem_add(unit, &oc->ing_oam_dglp_profile,
   2648                              (void *)entries, 1, &profile_index);
   2649         if (BCM_FAILURE(rv)) {
   2650             LOG_ERROR(BSL_LS_BCM_OAM,
   2651                       (BSL_META_U(unit,
   2652                                   "OAM DGLP profile table is full - %s.\n"),
   2653                        bcm_errmsg(rv)));
   2654             return rv;
   2655         }
   2656     }
   2657     
   2658 
   2659     /* Egress OAM dglp profile table initialisation */
   2660     soc_profile_mem_t_init(&oc->egr_oam_dglp_profile);
   2661 
   2662     entry_words = sizeof(egr_oam_dglp_profile_entry_t) / sizeof(uint32);
   2663 
   2664     mem = EGR_OAM_DGLP_PROFILEm;
   2665     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2666                                 &oc->egr_oam_dglp_profile);
   2667     if (BCM_FAILURE(rv)) {
   2668         LOG_ERROR(BSL_LS_BCM_OAM,
   2669                   (BSL_META_U(unit,
   2670                               "OAM Error: EGR OAM DGLP profile create - Failed.\n")));
   2671         return (rv);
   2672     }
   2673     if (!SOC_WARM_BOOT(unit)) {
   2674         profile_index = 0;
   2675         soc_mem_field32_set(unit, EGR_OAM_DGLP_PROFILEm, 
   2676                         &egr_dglp_profile_entry, DGLPf, dglp);
   2677         entries[0] = &egr_dglp_profile_entry;
   2678 
   2679         rv = soc_profile_mem_add(unit, &oc->egr_oam_dglp_profile,
   2680                              (void *)entries, 1, &profile_index);
   2681         if (BCM_FAILURE(rv)) {
   2682             LOG_ERROR(BSL_LS_BCM_OAM,
   2683                       (BSL_META_U(unit,
   2684                                   "OAM DGLP profile table is full - %s.\n"),
   2685                        bcm_errmsg(rv)));
   2686             return rv;
   2687         }
   2688     }
   2689     return (rv);
   2690 }
   2691 
   2692 /*
   2693  * Function:
   2694  *     _bcm_kt2_oam_control_free
   2695  * Purpose:
   2696  *     Free OAM control structure resources allocated by this unit.
   2697  * Parameters:
   2698  *     unit -  (IN) BCM unit number.
   2699  *     oc   -  (IN) Pointer to OAM control structure.
   2700  * Retruns:
   2701  *     BCM_E_XXX
   2702  */
   2703 STATIC int
   2704 _bcm_kt2_oam_control_free(int unit, _bcm_oam_control_t *oc)
   2705 {
   2706     int status = 0;
   2707     _kt2_oam_control[unit] = NULL;
   2708 
   2709     if (NULL == oc) {
   2710         /* Module already un-initialized. */
   2711         return (BCM_E_NONE);
   2712     }
   2713 
   2714     /* Free protection mutex. */
   2715     if (NULL != oc->oc_lock) {
   2716         sal_mutex_destroy(oc->oc_lock);
   2717     }
   2718 
   2719     /* Free hash data storage memory. */
   2720     if (NULL != oc->oam_hash_data) {
   2721         sal_free(oc->oam_hash_data);
   2722     }
   2723 
   2724     /* Destory endpoint hash table. */
   2725     if (NULL != oc->ma_mep_htbl) {
   2726         status = shr_htb_destroy(&oc->ma_mep_htbl, NULL);
   2727         if (BCM_FAILURE(status)) {
   2728             LOG_ERROR(BSL_LS_BCM_OAM,
   2729                       (BSL_META_U(unit,
   2730                                   "Freeing ma_mep_htbl failed\n")));
   2731         }
   2732     }
   2733 
   2734     /* Destory group indices list. */
   2735     if (NULL != oc->group_pool) {
   2736         shr_idxres_list_destroy(oc->group_pool);
   2737         oc->group_pool = NULL;
   2738     }
   2739 
   2740     /* Destroy endpoint indices list. */
   2741     if (NULL != oc->mep_pool) {
   2742         shr_idxres_list_destroy(oc->mep_pool);
   2743         oc->mep_pool = NULL;
   2744     }
   2745 
   2746     /* Destroy local endpoint indices list. */
   2747     if (NULL != oc->lmep_pool) {
   2748         shr_idxres_list_destroy(oc->lmep_pool);
   2749         oc->lmep_pool = NULL;
   2750     }
   2751 
   2752     /* Destroy remote endpoint indices list. */
   2753     if (NULL != oc->rmep_pool) {
   2754         shr_idxres_list_destroy(oc->rmep_pool);
   2755         oc->rmep_pool = NULL;
   2756     }
   2757 
   2758     /* Destroy ingress and egress group indices list. */
   2759     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_pool_destroy(oc));
   2760 
   2761     if (NULL != oc->egr_ma_idx_pool) {
   2762         shr_idxres_list_destroy(oc->egr_ma_idx_pool);
   2763         oc->egr_ma_idx_pool = NULL;
   2764     }
   2765 
   2766     /* Destroy LM counter indices list. */
   2767     if (NULL != oc->ing_lm_ctr_pool[0]) {
   2768         shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[0]);
   2769         oc->ing_lm_ctr_pool[0] = NULL;
   2770     }
   2771     if (NULL != oc->ing_lm_ctr_pool[1]) {
   2772         shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[1]);
   2773         oc->ing_lm_ctr_pool[1] = NULL;
   2774     }
   2775     if (soc_feature(unit, soc_feature_bhh)) {
   2776 #if defined(INCLUDE_BHH)
   2777         /* Destroy bhh indices list. */
   2778         if (NULL != oc->bhh_pool) {
   2779             shr_idxres_list_destroy(oc->bhh_pool);
   2780             oc->bhh_pool = NULL;
   2781         }
   2782         if (NULL != oc->dma_buffer){
   2783             soc_cm_sfree(oc->unit, oc->dma_buffer);
   2784             oc->dma_buffer = NULL;
   2785         }
   2786         if (NULL != oc->dmabuf_reply){
   2787             soc_cm_sfree(oc->unit, oc->dmabuf_reply);
   2788             oc->dmabuf_reply = NULL;
   2789         }
   2790 
   2791         if (NULL != oc->ing_lm_sec_mep_ctr_pool) {
   2792             shr_aidxres_list_destroy(oc->ing_lm_sec_mep_ctr_pool);
   2793             oc->ing_lm_sec_mep_ctr_pool = NULL;
   2794         }
   2795 #endif
   2796     }
   2797     if (soc_feature(unit, soc_feature_oam_pm)) {
   2798 #if defined (INCLUDE_BHH)
   2799         if (_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
   2800             soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer);
   2801         }
   2802 #endif
   2803     }
   2804     /* Free group memory. */
   2805     if (NULL != oc->group_info) {
   2806         sal_free(oc->group_info);
   2807     }
   2808 
   2809     /* Free RMEP H/w to logical index mapping memory. */
   2810     if (NULL != oc->remote_endpoints) {
   2811         sal_free(oc->remote_endpoints);
   2812     }
   2813 
   2814     /* Destroy ingress serivce priority mapping profile. */
   2815     if (NULL != oc->ing_service_pri_map.tables) {
   2816         soc_profile_mem_destroy(unit, &oc->ing_service_pri_map);
   2817     }
   2818     /* Destroy Egress serivce priority mapping profile. */
   2819     if (NULL != oc->egr_service_pri_map.tables) {
   2820         soc_profile_mem_destroy(unit, &oc->egr_service_pri_map);
   2821     }
   2822     /* Destroy Ingress OAM opcode control profile. */
   2823     if (NULL != oc->oam_opcode_control_profile.tables) {
   2824         soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile);
   2825     }
   2826     /* Destroy Egress OAM opcode control profile. */
   2827     if (NULL != oc->egr_oam_opcode_control_profile.tables) {
   2828         soc_profile_mem_destroy(unit, &oc->egr_oam_opcode_control_profile);
   2829     }
   2830     /* Destroy Ingress DGLP profile */
   2831     if (NULL != oc->ing_oam_dglp_profile.tables) {
   2832         soc_profile_mem_destroy(unit, &oc->ing_oam_dglp_profile);
   2833     }
   2834     /* Destroy Egress DGLP profile */
   2835     if (NULL != oc->egr_oam_dglp_profile.tables) {
   2836         soc_profile_mem_destroy(unit, &oc->egr_oam_dglp_profile);
   2837     }
   2838 
   2839 #if defined(INCLUDE_BHH) 
   2840     if (soc_feature(unit, soc_feature_oam_pm)) {
   2841         if (kt2_pm_profile_control[unit]) {
   2842             sal_free(kt2_pm_profile_control[unit]);
   2843             kt2_pm_profile_control[unit] = NULL;
   2844         }
   2845     }
   2846 #endif /* INCLUDE_BHH */
   2847 
   2848 
   2849     /* Free OAM control structure memory. */
   2850     sal_free(oc);
   2851     oc = NULL;
   2852 
   2853     return (BCM_E_NONE);
   2854 }
   2855 
   2856 /*
   2857  * Function:
   2858  *     _bcm_kt2_oam_handle_interrupt
   2859  * Purpose:
   2860  *     Process OAM interrupts generated by endpoints.
   2861  * Parameters:
   2862  *     unit  -  (IN) BCM unit number.
   2863  *     field -  (IN) fault field.
   2864  * Retruns:
   2865  *     BCM_E_XXX
   2866  */
   2867 STATIC int
   2868 _bcm_kt2_oam_handle_interrupt(int unit, soc_field_t field)
   2869 {
   2870     _bcm_oam_interrupt_t *intr;             /* OAM interrupt.                */
   2871     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
   2872     uint32               intr_rval;         /* Interrupt register value.     */
   2873     uint32               intr_cur_status;   /* Interrupt status.             */
   2874     uint32               flags;             /* Interrupt flags.              */
   2875     bcm_oam_group_t      grp_index;         /* MA group index.               */
   2876     bcm_oam_endpoint_t   remote_ep_index;   /* Remote Endpoint index.        */
   2877     int                  intr_multi;        /* Event occured multiple times. */
   2878     int                  intr_count;        /* No. of times event detected.  */
   2879     int                  rv;                /* Operation return status       */
   2880     _bcm_oam_event_handler_t *e_handler;    /* Pointer to Event handler.     */
   2881 
   2882 
   2883     /* Get OAM control structure. */
   2884     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   2885 
   2886     _BCM_OAM_LOCK(oc);
   2887 
   2888     /* Loop through the supported interrupts for this device. */
   2889     for (intr = _kt2_oam_interrupts; intr->status_register != INVALIDr;
   2890          intr++) {
   2891 
   2892         rv = soc_reg32_get(unit, intr->status_register,
   2893                            REG_PORT_ANY, 0, &intr_rval);
   2894         if (BCM_FAILURE(rv)) {
   2895             
   2896             continue;
   2897         }
   2898 
   2899         rv = soc_reg32_set(unit, intr->status_register,
   2900                            REG_PORT_ANY, 0, 0);
   2901         if (BCM_FAILURE(rv)) {
   2902             continue;
   2903         }
   2904 
   2905         /* Get status of interrupt from hardware. */
   2906         intr_cur_status = soc_reg_field_get(unit, intr->status_register,
   2907                                             intr_rval, VALIDf);
   2908         if (0 == intr_cur_status) {
   2909             /* This interrupt event is not valid, so continue. */
   2910             continue;
   2911         }
   2912 
   2913         /* Get this interrupt event counter value. */
   2914         intr_count = oc->event_handler_cnt[intr->event_type];
   2915 
   2916         /* Check if the interrupt is set. */
   2917         if ((1 == intr_cur_status) && (intr_count > 0)) {
   2918             flags = 0;
   2919 
   2920             /* Get MA group index for this interrupt. */
   2921             if (INVALIDf != intr->group_index_field ) {
   2922                 grp_index = soc_reg_field_get(unit, intr->status_register,
   2923                                               intr_rval,
   2924                                               intr->group_index_field);
   2925             } else {
   2926                 /* Group not valid for this interrupt. */
   2927                 grp_index = BCM_OAM_GROUP_INVALID;
   2928             }
   2929 
   2930             /* Get H/w index of RMEP for this interrupt. */
   2931             if (INVALIDf != intr->endpoint_index_field ) {
   2932                 remote_ep_index = soc_reg_field_get(unit, intr->status_register,
   2933                                               intr_rval,
   2934                                               intr->endpoint_index_field);
   2935 
   2936                 /* Get Logical index from H/w index for this RMEP. */
   2937                 remote_ep_index = oc->remote_endpoints[remote_ep_index];
   2938             } else {
   2939                 /* Endpoint not valid for this interrupt. */
   2940                 remote_ep_index = BCM_OAM_ENDPOINT_INVALID;
   2941             }
   2942 
   2943             /* Get interrupt MULTIf status. */
   2944             intr_multi = soc_reg_field_get(unit, intr->status_register,
   2945                                            intr_rval, MULTIf);
   2946             if (1 == intr_multi) {
   2947                 /*
   2948                  * Interrupt event asserted more than once.
   2949                  * Set flags status bit to indicate event multiple occurance.
   2950                  */
   2951                 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE;
   2952             }
   2953 
   2954             /* Check and call all the handlers registerd for this event. */
   2955             for (e_handler = oc->event_handler_list_p; e_handler != NULL;
   2956                  e_handler = e_handler->next_p) {
   2957 
   2958                 /* Check if an event handler is register for this event type. */
   2959                 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) {
   2960 
   2961                     /* Call the event handler with the call back parameters. */
   2962                     e_handler->cb(unit, flags, intr->event_type, grp_index,
   2963                                       remote_ep_index, e_handler->user_data);
   2964                 }
   2965             }
   2966         }
   2967     }
   2968 
   2969     _BCM_OAM_UNLOCK(oc);
   2970 
   2971     return (BCM_E_NONE);
   2972 }
   2973 
   2974 /*
   2975  * Function:
   2976  *     _bcm_kt2_oam_events_unregister
   2977  * Purpose:
   2978  *     Unregister all OAM events for this unit.
   2979  * Parameters:
   2980  *     unit -  (IN) BCM unit number.
   2981  *     oc   -  (IN) Pointer to OAM control structure.
   2982  * Retruns:
   2983  *     BCM_E_NONE
   2984  */
   2985 STATIC int
   2986 _bcm_kt2_oam_events_unregister(int unit, _bcm_oam_control_t *oc)
   2987 {
   2988     _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */
   2989     _bcm_oam_event_handler_t *e_delete;  /* Event handler to be freed.     */
   2990 
   2991     /* Control lock taken by the calling routine. */
   2992 
   2993     e_handler = oc->event_handler_list_p;
   2994 
   2995     while (e_handler != NULL) {
   2996         e_delete = e_handler;
   2997         e_handler = e_handler->next_p;
   2998         sal_free(e_delete);
   2999     }
   3000 
   3001     oc->event_handler_list_p = NULL;
   3002 
   3003     return (BCM_E_NONE);
   3004 }
   3005 
   3006 
   3007 /*
   3008  * Function:
   3009  *     _bcm_kt2_oam_clear_rmep
   3010  * Purpose:
   3011  *     Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 
   3012  *     the faults.
   3013  *      
   3014  * Parameters:
   3015  *     unit       - (IN) BCM device number
   3016  *     h_data_p   - (IN) Pointer to Endpoint info associated with RMEP entry 
   3017  *                       being cleared. 
   3018  *     valid      - (IN) 0 => Delete the H/w entry
   3019  *                       1 => Install fresh entry with faults cleared.
   3020  * Returns:
   3021  *     BCM_E_XXX
   3022  */
   3023 STATIC int
   3024 _bcm_kt2_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid)
   3025 {
   3026 
   3027     rmep_entry_t       rmep_entry;          /* RMEP table entry.              */
   3028     int                rv = BCM_E_INTERNAL; /* Operation return status entry  */
   3029     uint32             oam_cur_time;    /* Current time in H/w state machine  */
   3030 
   3031     LOG_VERBOSE(BSL_LS_BCM_OAM,
   3032                 (BSL_META_U(unit,
   3033                             "OAM: EP id %d, valid %d\n"), 
   3034                  h_data_p->remote_index, valid));
   3035     
   3036     if (h_data_p == NULL) {
   3037         LOG_ERROR(BSL_LS_BCM_OAM,
   3038                   (BSL_META_U(unit,
   3039                               "OAM ERR: Arg h_data_p NULL check failed\n")));
   3040         return BCM_E_INTERNAL;
   3041     }
   3042 
   3043     /* RMEP table programming. */
   3044     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   3045 
   3046     /* if valid==0 delete RMEP entry, else create a clean RMEP entry */
   3047     if (!(valid)) {
   3048         rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   3049                          &rmep_entry);
   3050         if (rv != BCM_E_NONE) {
   3051             LOG_ERROR(BSL_LS_BCM_OAM,
   3052                       (BSL_META_U(unit,
   3053                                   "OAM ERR: Deleting RMEP entry failied\n")));
   3054         }
   3055         return (rv);
   3056     }
   3057 
   3058     /* Set the MA group index. */
   3059     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 
   3060                           h_data_p->group_index);
   3061 
   3062     /*
   3063      * The following steps are necessary to enable CCM timeout events
   3064      * without having received any CCMs.
   3065      */
   3066     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1);
   3067 
   3068     BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   3069 
   3070     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time);
   3071 
   3072     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf,
   3073                          _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   3074     /* End of timeout setup */
   3075 
   3076 
   3077     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   3078 
   3079     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   3080                      &rmep_entry);
   3081     if (rv != BCM_E_NONE) {
   3082         LOG_ERROR(BSL_LS_BCM_OAM,
   3083                   (BSL_META_U(unit,
   3084                               "OAM ERR: Clearing RMEP entry failied\n")));
   3085         return (rv);
   3086     }
   3087 
   3088     return BCM_E_NONE;
   3089 }
   3090 
   3091 
   3092 /*
   3093  * Function:
   3094  *     _bcm_kt2_oam_clear_ma_state
   3095  * Purpose:
   3096  *     Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 
   3097  *     Clearing the faults.
   3098  * Parameters:
   3099  *     unit       - (IN) BCM device number
   3100  *     group_info - (IN) Group info associated with MA_STATE entry being 
   3101  *                       cleared.
   3102  *     index      - (IN) H/w index of MA_STATE entry to be modified. 
   3103  *     valid      - (IN) 0 => Delete the H/w entry
   3104  *                       1 => Install fresh entry with faults cleared.
   3105  * Returns:
   3106  *     BCM_E_XXX
   3107  */
   3108 STATIC int
   3109 _bcm_kt2_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 
   3110                             int index, int valid)
   3111 {
   3112 
   3113     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
   3114     
   3115     LOG_VERBOSE(BSL_LS_BCM_OAM,
   3116                 (BSL_META_U(unit,
   3117                             "OAM *group_info %p, index %d, valid %d\n"), 
   3118                  group_info, index, valid));
   3119                
   3120     if (group_info == NULL) {
   3121         LOG_ERROR(BSL_LS_BCM_OAM,
   3122                   (BSL_META_U(unit,
   3123                               "OAM ERR: Arg group_info NULL check failed\n")));
   3124         return BCM_E_INTERNAL;
   3125     }
   3126 
   3127     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   3128     
   3129     /* Mark the entry as valid. */
   3130     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid);
   3131 
   3132     /* Set the lowest alarm priority info. */
   3133     if (valid) {
   3134         soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
   3135                                   group_info->lowest_alarm_priority);
   3136     }
   3137 
   3138     /* Write group information to hardware table. */
   3139     SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index,
   3140                                         &ma_state_entry));
   3141     return BCM_E_NONE;
   3142 }
   3143 
   3144 
   3145 /*
   3146  * Function:
   3147  *     _bcm_kt2_oam_group_recreate
   3148  * Purpose:
   3149  *     Recreate MA_STATE and RMEP entries, due to current H/w limitation
   3150  *     Currently there is a race condition between H/w and Software
   3151  *     When RMEP is deleted and if it has any faults then, 
   3152  *     MA_STATE remote fault counters need to be decremented by software.
   3153  *     However it may so happen that after reading RMEP faults and just
   3154  *     before RMEP deletion, the fault gets cleared and H/w already decremented
   3155  *     the MA_STATE table, now when software decrements the MA_STATE it would
   3156  *     get MA_STATE table into an inconsistent state.
   3157  *     As a solution we always recreate the entire group on a RMEP deletion.
   3158  * Parameters:
   3159  *     unit     - (IN) BCM device number
   3160  *     group_id - (IN) Group Index, 
   3161  *                as per current implementation this is same as MA_STATE index.
   3162  * Returns:
   3163  *     BCM_E_XXX
   3164  * Expects:
   3165  *      OAM LOCK
   3166  */
   3167 STATIC int
   3168 _bcm_kt2_oam_group_recreate(int unit, int index)
   3169 {
   3170     _bcm_oam_control_t      *oc;                /* OAM control structure.     */
   3171     _bcm_oam_group_data_t   *group_info;        /* OAM group info             */
   3172     _bcm_oam_ep_list_t      *cur_ep_ptr = NULL; /* Pointer to group's EP list */
   3173                                                 /* entry.                     */
   3174     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   3175 
   3176     /* Get OAM control structure handle. */
   3177     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   3178 
   3179     /* Get the handle to group info */
   3180     group_info = &(oc->group_info[index]);
   3181     
   3182     /*if unused Group, just clear the MA_STATE index, including the valid bit*/
   3183     if (!(group_info->in_use)) {
   3184         LOG_WARN(BSL_LS_BCM_OAM,
   3185                  (BSL_META_U(unit,
   3186                              "OAM, WARN: Recieved group recreate request for " 
   3187                               "unused Group Id %d\n"), index));
   3188     
   3189         rv = _bcm_kt2_oam_clear_ma_state(unit, group_info, index, 0);
   3190         if (BCM_FAILURE(rv)) {
   3191             LOG_ERROR(BSL_LS_BCM_OAM,
   3192                       (BSL_META_U(unit,
   3193                                   "OAM Error: MA_STATE clear failed group id %d - "
   3194                                    "%s.\n"), index, bcm_errmsg(rv)));
   3195             return rv;
   3196         }
   3197 
   3198     }
   3199     
   3200     /* 1. Traverse and delete the RMEPs in the group */
   3201     if (group_info->ep_list != NULL) {
   3202         cur_ep_ptr = *(group_info->ep_list);
   3203     }
   3204     while (cur_ep_ptr) {
   3205         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   3206             rv = _bcm_kt2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0);
   3207             if (BCM_FAILURE(rv)) {
   3208                 LOG_ERROR(BSL_LS_BCM_OAM,
   3209                           (BSL_META_U(unit,
   3210                                       "OAM Error: RMEP delete failed Ep id %d - "
   3211                                        "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   3212                 return rv;
   3213             }
   3214         }
   3215         cur_ep_ptr = cur_ep_ptr->next;
   3216     }
   3217 
   3218     /* 2. Clear the MA_STATE table faults */
   3219     rv = _bcm_kt2_oam_clear_ma_state(unit, group_info, index, 1);
   3220     if (BCM_FAILURE(rv)) {
   3221         LOG_ERROR(BSL_LS_BCM_OAM,
   3222                   (BSL_META_U(unit,
   3223                               "OAM Error: MA_STATE clear failed group id %d - "
   3224                                "%s.\n"), index, bcm_errmsg(rv)));
   3225         return rv;
   3226     }
   3227 
   3228     /* 3. Recreate the RMEP table entries. Clearing the faults. */
   3229     if (group_info->ep_list != NULL) {
   3230         cur_ep_ptr = *(group_info->ep_list);
   3231     }
   3232     while (cur_ep_ptr) {
   3233         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   3234             rv = _bcm_kt2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1);
   3235             if (BCM_FAILURE(rv)) {
   3236                 LOG_ERROR(BSL_LS_BCM_OAM,
   3237                           (BSL_META_U(unit,
   3238                                       "OAM Error: RMEP clear failed EP id %d - "
   3239                                        "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   3240                 return rv;
   3241             }
   3242         }
   3243         cur_ep_ptr = cur_ep_ptr->next;
   3244     }
   3245     
   3246     return rv;
   3247 }
   3248 
   3249 
   3250 /*
   3251  * Function:
   3252  *     _bcm_kt2_oam_ser_handler
   3253  * Purpose:
   3254  *     Soft Error Correction routine for MA_STATE and RMEP tables.
   3255  * Parameters:
   3256  *     unit       - (IN) BCM device number
   3257  *     mem        - (IN) Memory MA_STATE or RMEP.
   3258  *     index      - (IN) Memory Index.
   3259  * Returns:
   3260  *     BCM_E_XXX
   3261  */
   3262 STATIC int
   3263 _bcm_kt2_oam_ser_handler(int unit, soc_mem_t mem, int index)
   3264 {
   3265     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   3266     _bcm_oam_control_t      *oc = NULL;         /* OAM control structure.     */
   3267     bcm_oam_endpoint_t      remote_ep_index;    /* Remote Endpoint index.     */
   3268     _bcm_oam_hash_data_t    *ep_data = NULL;    /* Remote Endpoint hash data  */
   3269 
   3270     LOG_VERBOSE(BSL_LS_BCM_OAM,
   3271                 (BSL_META_U(unit,
   3272                             "OAM SER on mem %s, index %d\n"), 
   3273                  SOC_MEM_NAME(unit, mem), index));
   3274               
   3275     /* Get OAM control structure handle. */
   3276     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   3277 
   3278     switch(mem){
   3279         case MA_STATEm:
   3280             _BCM_OAM_GROUP_INDEX_VALIDATE(index);
   3281             _BCM_OAM_LOCK(oc);
   3282             rv = _bcm_kt2_oam_group_recreate(unit, index);
   3283             _BCM_OAM_UNLOCK(oc);
   3284             break;
   3285             
   3286         case RMEPm:
   3287             _BCM_OAM_RMEP_INDEX_VALIDATE(index);
   3288             _BCM_OAM_LOCK(oc);
   3289             /* Get the logical index from H/w RMEP index */
   3290             remote_ep_index = oc->remote_endpoints[index];
   3291             if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) {
   3292                 /* If endpoint not in use, just clear the RMEP entry in memory */
   3293                 rmep_entry_t rmep_entry;
   3294                 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   3295 
   3296                 LOG_WARN(BSL_LS_BCM_OAM,
   3297                         (BSL_META_U(unit,
   3298                                     "OAM(unit %d), WARN: Recieved Parity Error on"
   3299                                     "index %d & invalid Remote Id\n"), unit, index));
   3300                 /* Just clear this entry including valid bit */
   3301                 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index,
   3302                                                      &rmep_entry);
   3303             } else {
   3304 
   3305                 /* Get handle to Hash data */
   3306                 ep_data = &(oc->oam_hash_data[remote_ep_index]);
   3307 
   3308                 if (!(ep_data->in_use)) {
   3309                     /* If endpoint not in use, just clear the RMEP entry in memory */
   3310                     LOG_WARN(BSL_LS_BCM_OAM,
   3311                             (BSL_META_U(unit,
   3312                                         "OAM, WARN: Recieved Parity Error on"
   3313                                         "unused Remote Id %d\n"), remote_ep_index));
   3314                     /* Just clear this entry including valid bit */
   3315                     rv = _bcm_kt2_oam_clear_rmep(unit, ep_data, 0);
   3316                 } else {
   3317                     /* Get the group Id from EP data, call group recreate routine */
   3318                     rv = _bcm_kt2_oam_group_recreate(unit, ep_data->group_index);
   3319                 }
   3320             }
   3321             _BCM_OAM_UNLOCK(oc);
   3322             break;
   3323 
   3324         default:
   3325             LOG_ERROR(BSL_LS_BCM_OAM,
   3326                       (BSL_META_U(unit,
   3327                                   "OAM, ERR: Invalid mem in OAM SER correction "
   3328                                    "routine %s\n"), SOC_MEM_NAME(unit, mem)));
   3329             return BCM_E_INTERNAL;
   3330     }
   3331 
   3332     LOG_VERBOSE(BSL_LS_BCM_OAM,
   3333                 (BSL_META_U(unit,
   3334                             "OAM SER completed on mem %s, index %d, rv %d\n"), 
   3335                  SOC_MEM_NAME(unit, mem), index, rv));
   3336     
   3337     return rv;
   3338     
   3339 }
   3340 
   3341 /*
   3342  * Function:
   3343  *     _bcm_kt2_oam_group_name_mangle
   3344  * Purpose:
   3345  *     Build tbe group name for hardware table write.
   3346  * Parameters:
   3347  *     name_p         -  (IN) OAM group name.
   3348  *     mangled_name_p -  (IN/OUT) Buffer to write the group name in hardware
   3349  *                       format.
   3350  * Retruns:
   3351  *     None
   3352  */
   3353 STATIC void
   3354 _bcm_kt2_oam_group_name_mangle(uint8 *name_p,
   3355                                uint8 *mangled_name_p)
   3356 {
   3357     uint8  *byte_p;    /* Pointer to group name buffer.       */
   3358     int    bytes_left; /* Number of bytes left in group name. */
   3359 
   3360     bytes_left = BCM_OAM_GROUP_NAME_LENGTH;
   3361     byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1);
   3362 
   3363     while (bytes_left > 0) {
   3364         *mangled_name_p = *byte_p;
   3365         ++mangled_name_p;
   3366         --byte_p;
   3367         --bytes_left;
   3368     }
   3369 }
   3370 
   3371 /*
   3372  * Function:
   3373  *      _bcm_kt2_oam_read_clear_faults
   3374  * Purpose:
   3375  *     Clear OAM group and endpoint faults on hardware table read operation.
   3376  * Parameters:
   3377  *     unit     - (IN) BCM device number
   3378  *     index    - (IN) Group/Endpoint hardware table index
   3379  *     mem      - (IN) Memory/table value
   3380  *     entry    - (IN) Pointer to group/endpoint entry
   3381  *     ma_mep   - (IN) Pointer to group/endpoint info structure
   3382  * Returns:
   3383  *     BCM_E_NONE      - No errors.
   3384  *     BCM_E_XXX       - Otherwise.
   3385  */
   3386 STATIC int
   3387 _bcm_kt2_oam_read_clear_faults(int unit, int index, soc_mem_t mem,
   3388                                uint32 *entry, void *ma_rmep)
   3389 {
   3390     bcm_oam_group_info_t    *group_info_p;  /* Pointer to group info         */
   3391                                             /* structure.                    */
   3392     bcm_oam_endpoint_info_t *ep_info_p;     /* Pointer to endpoint info      */
   3393                                             /* structure.                    */
   3394     _bcm_oam_fault_t        *faults_list;   /* Pointer to faults list.       */
   3395     uint32                  *faults;        /* Faults flag bits.             */
   3396     uint32                  *p_faults;      /* Persistent faults bits.       */
   3397     uint32                  clear_p_faults; /* Clear persistent faults bits. */
   3398     uint32                  rval = 0;       /* Hardware register value.      */
   3399     uint32                  clear_mask = 0; /* Mask to clear persistent faults*/
   3400 
   3401     LOG_DEBUG(BSL_LS_BCM_OAM,
   3402               (BSL_META_U(unit,
   3403                           "OAM Info: _bcm_kt2_oam_read_clear_faults index=%d "
   3404                            "Table=%d.\n"), index, mem));
   3405 
   3406     /* Switch on memory name. */
   3407     switch (mem) {
   3408         /* OAM group state table. */
   3409         case MA_STATEm:
   3410             /* Set the pointer to the start of the group faults array. */
   3411             faults_list = _kt2_oam_group_faults;
   3412 
   3413             /* Typecast to group information structure pointer. */
   3414             group_info_p = (bcm_oam_group_info_t *) ma_rmep;
   3415 
   3416             /* Get group faults information. */
   3417             faults = &group_info_p->faults;
   3418             p_faults = &group_info_p->persistent_faults;
   3419             clear_p_faults = group_info_p->clear_persistent_faults;
   3420             break;
   3421 
   3422         /* OAM remote endpoint table. */
   3423         case RMEPm:
   3424             faults_list = _kt2_oam_endpoint_faults;
   3425             ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep;
   3426             faults = &ep_info_p->faults;
   3427             p_faults = &ep_info_p->persistent_faults;
   3428             clear_p_faults = ep_info_p->clear_persistent_faults;
   3429             break;
   3430 
   3431         default:
   3432             return (BCM_E_NONE);
   3433     }
   3434 
   3435     /* Loop on list of valid faults. */
   3436     for (;faults_list->mask != 0; ++faults_list) {
   3437 
   3438         /* Get  faults status. */
   3439         if (0 != soc_mem_field32_get(unit, mem, entry,
   3440                                      faults_list->current_field)) {
   3441             *faults |= faults_list->mask;
   3442         }
   3443 
   3444         /* Get sticky faults status. */
   3445         if (0 != soc_mem_field32_get(unit, mem, entry,
   3446                                      faults_list->sticky_field)) {
   3447 
   3448             *p_faults |= faults_list->mask;
   3449 
   3450             /*
   3451              * If user has request to clear persistent faults,
   3452              * then set BITS_TO_CLEARf field in the register buffer.
   3453              */
   3454             if (clear_p_faults) {
   3455                 clear_mask |= faults_list->clear_sticky_mask;
   3456             }
   3457         }
   3458     }
   3459 
   3460     /* Check if faults need to be cleared. */
   3461     if (clear_mask && clear_p_faults) {
   3462 
   3463         LOG_VERBOSE(BSL_LS_BCM_OAM,
   3464                     (BSL_META_U(unit,
   3465                                 "OAM: clear_mask %d.\n"),
   3466                      clear_mask));
   3467 
   3468         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf,
   3469                           clear_mask);
   3470 
   3471         /* Enable clearing of faults. */
   3472         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1);
   3473 
   3474         
   3475         if (MA_STATEm == mem) {
   3476             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0);
   3477         } else {
   3478             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1);
   3479         }
   3480 
   3481         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index);
   3482 
   3483         /* Update read control register. */
   3484         BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval));
   3485     }
   3486 
   3487     return (BCM_E_NONE);
   3488 }
   3489 
   3490 /*
   3491  * Function:
   3492  *      _bcm_kt2_oam_get_group
   3493  * Purpose:
   3494  *     Get OAM group information.
   3495  * Parameters:
   3496  *     unit         - (IN) BCM device number
   3497  *     group_index  - (IN) Group hardware table index
   3498  *     group        - (IN) Pointer to group array list
   3499  *     group_info   - (IN/OUT) Pointer to group info structure
   3500  * Returns:
   3501  *     BCM_E_NONE      - No errors.
   3502  *     BCM_E_XXX       - Otherwise.
   3503  */
   3504 STATIC int
   3505 _bcm_kt2_oam_get_group(int unit, bcm_oam_group_t group_index,
   3506                        _bcm_oam_group_data_t *group_p,
   3507                        bcm_oam_group_info_t *group_info)
   3508 {
   3509     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   3510     ma_state_entry_t        ma_state_entry;       /* MA_STATE table entry.    */
   3511     int                     rv;                   /* Operation return status. */
   3512 
   3513     group_info->id = group_index;
   3514 
   3515     BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY,
   3516                                        group_index,
   3517                                        &ma_state_entry));
   3518 
   3519     group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get
   3520                                             (unit, &ma_state_entry,
   3521                                              LOWESTALARMPRIf);
   3522 
   3523     rv = _bcm_kt2_oam_read_clear_faults(unit, group_index,
   3524                                         MA_STATEm,
   3525                                         (uint32 *) &ma_state_entry,
   3526                                         group_info);
   3527     if (BCM_FAILURE(rv)) {
   3528         LOG_ERROR(BSL_LS_BCM_OAM,
   3529                   (BSL_META_U(unit,
   3530                               "OAM Error: Clean Faults Group ID=%d- Failed.\n"),
   3531                    group_index));
   3532         return (rv);
   3533     }
   3534     if (group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY) {
   3535         group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY;
   3536         return BCM_E_NONE;
   3537     }
   3538     sal_memcpy(group_info->name, group_p[group_index].name,
   3539                BCM_OAM_GROUP_NAME_LENGTH);
   3540 
   3541     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   3542                                              group_index,
   3543                                              &maid_reduction_entry));
   3544 
   3545     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   3546                                              SW_RDIf)) {
   3547         group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
   3548     }
   3549 
   3550     return (BCM_E_NONE);
   3551 }
   3552 
   3553 /*
   3554  * Function:
   3555  *     _bcm_kt2_oam_group_ep_list_add
   3556  * Purpose:
   3557  *     Add an endpoint to a group endpoint linked list.
   3558  * Parameters:
   3559  *     unit     - (IN) BCM device number
   3560  *     group_id - (IN) OAM group ID.
   3561  *     ep_id    - (IN) OAM endpoint ID.
   3562  * Retruns:
   3563  *     BCM_E_XXX
   3564  */
   3565 STATIC int
   3566 _bcm_kt2_oam_group_ep_list_add(int unit,
   3567                            bcm_oam_group_t group_id,
   3568                            bcm_oam_endpoint_t ep_id)
   3569 {
   3570     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   3571     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   3572     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   3573     _bcm_oam_ep_list_t    *ep_list_p = NULL; /* Pointer to endpoint list. */
   3574 
   3575     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   3576 
   3577     group_p = &oc->group_info[group_id];
   3578     /* coverity[dead_error_condition] */
   3579     if (NULL == group_p) {
   3580         LOG_ERROR(BSL_LS_BCM_OAM,
   3581                   (BSL_META_U(unit,
   3582                               "OAM Error: Group data access for GID=%d failed"
   3583         /* coverity[dead_error_begin] */
   3584                                " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL)));
   3585         return (BCM_E_INTERNAL);
   3586     }
   3587 
   3588     h_data_p = &oc->oam_hash_data[ep_id];
   3589     /* coverity[dead_error_condition] */
   3590     if (NULL == h_data_p) {
   3591         LOG_ERROR(BSL_LS_BCM_OAM,
   3592                   (BSL_META_U(unit,
   3593                               "OAM Error: Endpoint data access for EP=%d failed"
   3594         /* coverity[dead_error_begin] */
   3595                                " %s.\n"), ep_id, bcm_errmsg(BCM_E_INTERNAL)));
   3596         return (BCM_E_INTERNAL);
   3597     }
   3598 
   3599     _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t),
   3600                 "EP list");
   3601     if (NULL == ep_list_p) {
   3602         LOG_ERROR(BSL_LS_BCM_OAM,
   3603                   (BSL_META_U(unit,
   3604                               "OAM Error: Endpoint list alloc for EP=%d failed"
   3605                                " %s.\n"), ep_id, bcm_errmsg(BCM_E_MEMORY)));
   3606         return (BCM_E_MEMORY);
   3607     }
   3608 
   3609     ep_list_p->prev = NULL;
   3610     ep_list_p->ep_data_p = h_data_p;
   3611     if (NULL == (*group_p->ep_list)) {
   3612         /* Add endpoint as head node. */
   3613         ep_list_p->next = NULL;
   3614         *group_p->ep_list = ep_list_p;
   3615     } else {
   3616         /* Add the endpoint to the linked list. */
   3617         ep_list_p->next = *group_p->ep_list;
   3618         (*group_p->ep_list)->prev = ep_list_p;
   3619         *group_p->ep_list = ep_list_p;
   3620     }
   3621     LOG_DEBUG(BSL_LS_BCM_OAM,
   3622               (BSL_META_U(unit,
   3623                           "OAM Info: _bcm_kt2_oam_group_ep_list_add" 
   3624                            " (GID=%d) (EP=%d).\n"), group_id, ep_id));
   3625     return (BCM_E_NONE);
   3626 }
   3627 
   3628 /*
   3629  * Function:
   3630  *     _bcm_kt2_oam_group_ep_list_remove
   3631  * Purpose:
   3632  *     Remove an endpoint to a group endpoint linked list.
   3633  * Parameters:
   3634  *     unit     - (IN) BCM device number
   3635  *     group_id - (IN) OAM group ID.
   3636  *     ep_id    - (IN) OAM endpoint ID.
   3637  * Retruns:
   3638  *     BCM_E_XXX
   3639  */
   3640 STATIC int
   3641 _bcm_kt2_oam_group_ep_list_remove(int unit,
   3642                               bcm_oam_group_t group_id,
   3643                               bcm_oam_endpoint_t ep_id)
   3644 {
   3645     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   3646     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   3647     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   3648     _bcm_oam_ep_list_t    *cur;      /* Current endpoint node pointer.    */
   3649     _bcm_oam_ep_list_t    *del_node; /* Pointer to a node to be deleted.  */
   3650 
   3651     /* Control lock already taken by calling routine. */
   3652     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   3653 
   3654     group_p = &oc->group_info[group_id];
   3655     cur =  *group_p->ep_list;
   3656     if (NULL == cur) {
   3657         /* No endpoints to remove from this group. */
   3658         LOG_DEBUG(BSL_LS_BCM_OAM,
   3659                   (BSL_META_U(unit,
   3660                               "OAM Info: No endpoints to delete in group"
   3661                                " GID:%d.\n"), group_id));
   3662         return (BCM_E_NONE);
   3663     }
   3664 
   3665     /* Check if head node needs to be deleated. */
   3666     if (ep_id == cur->ep_data_p->ep_id) {
   3667         /* Delete head node. */
   3668         del_node = *group_p->ep_list;
   3669         if ((*group_p->ep_list)->next) {
   3670             *group_p->ep_list = (*group_p->ep_list)->next;
   3671             (*group_p->ep_list)->prev = NULL;
   3672         } else {
   3673             *group_p->ep_list = NULL;
   3674         }
   3675         sal_free(del_node);
   3676         LOG_DEBUG(BSL_LS_BCM_OAM,
   3677                   (BSL_META_U(unit,
   3678                               "OAM Info: Head node delete GID=%d - Success\n"),
   3679                    group_id));
   3680         return (BCM_E_NONE);
   3681     }
   3682 
   3683     /* Traverse the list and delete the matching node. */
   3684     while (NULL != cur->next->next) {
   3685         h_data_p = cur->next->ep_data_p;
   3686         if (NULL == h_data_p) {
   3687             LOG_ERROR(BSL_LS_BCM_OAM,
   3688                       (BSL_META_U(unit,
   3689                                   "OAM Error: Group=%d endpoints access failed -"
   3690                                    " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL)));
   3691             return (BCM_E_INTERNAL);
   3692         }
   3693 
   3694         if (ep_id == h_data_p->ep_id) {
   3695             del_node = cur->next;
   3696             cur->next = del_node->next;
   3697             del_node->next->prev = cur;
   3698             sal_free(del_node);
   3699             LOG_DEBUG(BSL_LS_BCM_OAM,
   3700                       (BSL_META_U(unit,
   3701                                   "OAM Info: Node delete GID=%d - Success\n"),
   3702                        group_id));
   3703             return (BCM_E_NONE);
   3704         }
   3705         cur = cur->next;
   3706     }
   3707 
   3708     /* Check if tail node needs to be deleted. */
   3709     h_data_p = cur->next->ep_data_p;
   3710     if (ep_id == h_data_p->ep_id) {
   3711         /* Delete tail node. */
   3712         del_node = cur->next;
   3713         cur->next = NULL;
   3714         sal_free(del_node);
   3715         LOG_DEBUG(BSL_LS_BCM_OAM,
   3716                   (BSL_META_U(unit,
   3717                               "OAM Info: Tail node delete GID=%d - Success\n"),
   3718                    group_id));
   3719         return (BCM_E_NONE);
   3720     }
   3721 
   3722     return (BCM_E_NOT_FOUND);
   3723 }
   3724 
   3725 /*
   3726  * Function:
   3727  *     _bcm_oam_kt2_remote_mep_hw_set
   3728  * Purpose:
   3729  *     Configure hardware tables for a remote endpoint.
   3730  * Parameters:
   3731  *     unit      - (IN) BCM device number
   3732  *     ep_info_p - (IN) Pointer to remote endpoint information.
   3733  * Retruns:
   3734  *     BCM_E_XXX
   3735  */
   3736 STATIC int
   3737 _bcm_oam_kt2_remote_mep_hw_set(int unit,
   3738                            const bcm_oam_endpoint_info_t *ep_info_p)
   3739 {
   3740     l3_entry_1_entry_t   l3_entry;          /* Remote view entry.            */
   3741     rmep_entry_t         rmep_entry;        /* Remote MEP entry.             */
   3742     uint32               oam_cur_time;      /* Current time.                 */
   3743     _bcm_oam_hash_data_t *h_data_p = NULL;  /* Hash data pointer.            */
   3744     int                  rv;                /* Operation return status.      */
   3745     _bcm_oam_control_t   *oc;               /* Pointer to control structure. */
   3746     const bcm_oam_endpoint_info_t *ep_p;    /* Pointer to endpoint info.     */
   3747 
   3748     if (NULL == ep_info_p) {
   3749         return (BCM_E_INTERNAL);
   3750     }
   3751 
   3752     /* Initialize local endpoint info pointer. */
   3753     ep_p = ep_info_p;
   3754 
   3755     /* Lock already taken by the calling routine. */
   3756     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   3757 
   3758     /* Get endpoint hash data pointer. */
   3759     h_data_p = &oc->oam_hash_data[ep_p->id];
   3760     if (0 == h_data_p->in_use) {
   3761         return (BCM_E_INTERNAL);
   3762     }
   3763 
   3764     /* RMEP table programming. */
   3765     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   3766 
   3767     /* Set the MA group index. */
   3768     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf,
   3769                           ep_p->group);
   3770 
   3771     /*
   3772      * The following steps are necessary to enable CCM timeout events
   3773      * without having received any CCMs.
   3774      */
   3775     soc_RMEPm_field32_set(unit, &rmep_entry,
   3776                           RMEP_TIMESTAMP_VALIDf, 1);
   3777 
   3778     BCM_IF_ERROR_RETURN
   3779         (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   3780 
   3781     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf,
   3782                           oam_cur_time);
   3783 
   3784     soc_RMEPm_field32_set(unit, &rmep_entry,
   3785                           RMEP_RECEIVED_CCMf,
   3786                          _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   3787     /* End of timeout setup */
   3788 
   3789     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   3790 
   3791     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   3792                      &rmep_entry);
   3793     if (BCM_FAILURE(rv)) {
   3794         LOG_ERROR(BSL_LS_BCM_OAM,
   3795                   (BSL_META_U(unit,
   3796                               "OAM Error: RMEP table write failed EP=%d %s.\n"),
   3797                    ep_info_p->id, bcm_errmsg(rv)));
   3798         return (rv);
   3799     }
   3800 
   3801     /* L3 unicast table programming. */
   3802     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   3803 
   3804     /* Set the CCM interval. */
   3805     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   3806         (unit, &l3_entry, RMEP__CCMf,
   3807         _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   3808 
   3809     /* Set the entry hardware index. */
   3810     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf,
   3811                                 h_data_p->remote_index);
   3812 
   3813     /*
   3814      * Construct endpoint RMEP view key for L3 Table entry
   3815      * insert operation.
   3816      */
   3817     _bcm_kt2_oam_rmep_key_construct(unit, h_data_p, &l3_entry);
   3818 
   3819     /* Mark the entry as valid. */
   3820     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1);
   3821 
   3822     /* Install entry in hardware. */
   3823     rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm,
   3824                         MEM_BLOCK_ALL, &l3_entry);
   3825     if (BCM_FAILURE(rv)) {
   3826         LOG_ERROR(BSL_LS_BCM_OAM,
   3827                   (BSL_META_U(unit,
   3828                               "OAM Error: L3 table insert failed EP=%d %s.\n"),
   3829                    ep_p->id, bcm_errmsg(rv)));
   3830         return (rv);
   3831     }
   3832     /* Add the H/w index to logical index mapping for RMEP */
   3833     oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 
   3834 
   3835     return (BCM_E_NONE);
   3836 }
   3837 /*
   3838  * Function:
   3839  *     _bcm_kt2_oam_find_egr_lmep
   3840  * Purpose:
   3841  *     Search EGR_MP_GROUP table and return the match entry hardware index and
   3842  *     match entry data.
   3843  * Parameters:
   3844  *     unit       - (IN) BCM device number
   3845  *     h_data_p   - (IN) Pointer to endpoint hash data.
   3846  *     entry_idx  - (OUT) Pointer to match entry hardware index.
   3847  *     mp_group_entry_p - (OUT) Pointer to match entry data.
   3848  * Retruns:
   3849  *     BCM_E_XXX
   3850  */
   3851 STATIC int
   3852 _bcm_kt2_oam_find_egr_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p,
   3853                        int *entry_idx,
   3854                        egr_mp_group_entry_t *mp_group_entry_p)
   3855 {
   3856     egr_mp_group_entry_t mp_group_entry; /* MP group table
   3857                                            entry to search.      */
   3858     int                rv;       /* Operation return status. */
   3859 
   3860     if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) {
   3861         return (BCM_E_INTERNAL);
   3862     }
   3863 
   3864     sal_memset(&mp_group_entry, 0, sizeof(egr_mp_group_entry_t));
   3865 
   3866     /* Construct endpoint egress MP group  Table entry search operation. */
   3867     _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &mp_group_entry);
   3868 
   3869     soc_mem_lock(unit, EGR_MP_GROUPm);
   3870     /* Perform the search in EGR_MP_GROUP table. */
   3871     rv = soc_mem_search(unit, EGR_MP_GROUPm, MEM_BLOCK_ANY, entry_idx,
   3872                                   &mp_group_entry, mp_group_entry_p, 0);
   3873     soc_mem_unlock(unit, EGR_MP_GROUPm);
   3874     if (BCM_FAILURE(rv)) {
   3875         LOG_VERBOSE(BSL_LS_BCM_OAM,
   3876                   (BSL_META_U(unit,
   3877                               "OAM Error:  Egr MP group entry lookup "
   3878                               "failed vlan=%d port =%x %s.\n"),
   3879                    h_data_p->vlan, h_data_p->dglp, bcm_errmsg(rv)));
   3880     }
   3881 
   3882     return (rv);
   3883 }
   3884 
   3885 /*
   3886  * Function:
   3887  *     _bcm_kt2_oam_find_lmep
   3888  * Purpose:
   3889  *     Search LMEP view table and return the match entry hardware index and
   3890  *     match entry data.
   3891  * Parameters:
   3892  *     unit       - (IN) BCM device number
   3893  *     h_data_p   - (IN) Pointer to endpoint hash data.
   3894  *     entry_idx  - (OUT) Pointer to match entry hardware index.
   3895  *     l3_entry_p - (OUT) Pointer to match entry data.
   3896  * Retruns:
   3897  *     BCM_E_XXX
   3898  */
   3899 STATIC int
   3900 _bcm_kt2_oam_find_lmep(int unit,  const _bcm_oam_hash_data_t *h_data_p,
   3901                        int *entry_idx,
   3902                        l3_entry_1_entry_t *l3_entry_p)
   3903 {
   3904     l3_entry_1_entry_t l3_entry; /* L3 entry to search.      */
   3905     int                rv;       /* Operation return status. */
   3906 
   3907     if (NULL == h_data_p || NULL == entry_idx || NULL == l3_entry_p) {
   3908         return (BCM_E_INTERNAL);
   3909     }
   3910 
   3911     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   3912 
   3913     /* Construct endpoint LMEP view key for L3 Table entry search operation. */
   3914     _bcm_kt2_oam_lmep_key_construct(unit, h_data_p, &l3_entry);
   3915 
   3916     /* Take L3 module protection mutex to block any updates. */
   3917     L3_LOCK(unit);
   3918 
   3919     /* Perform the search in L3_ENTRY table. */
   3920     rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, entry_idx,
   3921                         &l3_entry, l3_entry_p, 0);
   3922     if (BCM_FAILURE(rv)) {
   3923         LOG_VERBOSE(BSL_LS_BCM_OAM,
   3924                   (BSL_META_U(unit,
   3925                               "OAM Error: L3 entry lookup vlan=%d port=%x %s.\n"),
   3926                    h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv)));
   3927     }
   3928 
   3929     /* Release L3 module protection mutex. */
   3930     L3_UNLOCK(unit);
   3931 
   3932     return (rv);
   3933 }
   3934 
   3935 STATIC int
   3936 _bcm_kt2_oam_find_port_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p,
   3937                             int *stm_index, source_trunk_map_table_entry_t *stm_entry,
   3938                             uint8 *mdl)
   3939 {
   3940     port_tab_entry_t port_entry;
   3941     int rv = BCM_E_NONE;
   3942     int port_id, mod_id;
   3943 
   3944     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
   3945             h_data_p->src_pp_port, &port_entry);
   3946 
   3947     if (BCM_FAILURE(rv)) {
   3948         return rv;
   3949     }
   3950 
   3951     *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   3952 
   3953     if (*mdl == 0) {
   3954         /* No port mep enabled already on this port */
   3955         return BCM_E_NOT_FOUND;
   3956     }
   3957 
   3958     port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   3959     mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   3960 
   3961     /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/
   3962     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_id,
   3963                                                port_id, stm_index));
   3964     BCM_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   3965                                       *stm_index, stm_entry));
   3966     return BCM_E_NONE;
   3967 }
   3968 
   3969 STATIC
   3970 int _bcm_kt2_oam_lm_counters_mems_from_pool_get(int pool_id, soc_mem_t *mems)
   3971 {
   3972     switch(pool_id) {
   3973         case 0:
   3974             mems[0] = OAM_LM_COUNTERS_0m;
   3975             mems[1] = EGR_OAM_LM_COUNTERS_0m;
   3976             break;
   3977         case 1:
   3978             mems[0] = OAM_LM_COUNTERS_1m;
   3979             mems[1] = EGR_OAM_LM_COUNTERS_1m;
   3980             break;
   3981         default:
   3982             /* should not happen */
   3983             return BCM_E_INTERNAL;
   3984             break;
   3985     }
   3986     return BCM_E_NONE;
   3987 }
   3988 
   3989 
   3990 STATIC int
   3991 _bcm_kt2_oam_lm_counters_hw_values_init(int unit, int pool_id, int ctr_index)
   3992 {
   3993     oam_lm_counters_0_entry_t entry;
   3994     /* Ingress and egress. 2 memories */
   3995     soc_mem_t mems[2] = {INVALIDm, INVALIDm};
   3996     int index, entry_offset;
   3997 
   3998     BCM_IF_ERROR_RETURN(
   3999         _bcm_kt2_oam_lm_counters_mems_from_pool_get(pool_id, mems));
   4000 
   4001     for (index = 0; index < 2; index++) { 
   4002         sal_memset(&entry, 0, sizeof(entry));
   4003 
   4004         /* 8 entries allocated per endpoint */
   4005         for(entry_offset = 0; entry_offset < 8; entry_offset++) {
   4006             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mems[index], MEM_BLOCK_ALL,
   4007                         ctr_index + entry_offset, &entry));
   4008         }
   4009     }
   4010 
   4011     return BCM_E_NONE;
   4012 }
   4013 
   4014 STATIC int
   4015 _bcm_kt2_oam_lm_counters_hw_values_reset(int unit, int pool_id, int index)
   4016 {
   4017 
   4018     return _bcm_kt2_oam_lm_counters_hw_values_init(unit, pool_id, index);
   4019 }
   4020 
   4021 /*
   4022  * Function:
   4023  *     _bcm_kt2_oam_free_counter
   4024  * Purpose:
   4025  *     Free counter from counter pool.
   4026  * Parameters:
   4027  *     unit      - (IN) BCM device number
   4028  * Retruns:
   4029  *     BCM_E_XXX
   4030  */
   4031 STATIC int
   4032 _bcm_kt2_oam_free_counter(int unit, 
   4033                           _bcm_oam_hash_data_t *hash_data) 
   4034 {
   4035     int                  rv = BCM_E_NONE;/* Operation return status.         */
   4036     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   4037     int                  pool_id = 0;
   4038 
   4039     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4040 
   4041     if (hash_data->rx_ctr != _BCM_OAM_INVALID_INDEX) {
   4042         pool_id = (hash_data->rx_ctr >> 24);
   4043         rv =  shr_aidxres_list_free(oc->ing_lm_ctr_pool[pool_id], 
   4044                                        (hash_data->rx_ctr & 0xffffff));
   4045         
   4046         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lm_counters_hw_values_reset(unit, pool_id,
   4047                                              hash_data->rx_ctr & 0xffffff));
   4048         if (BCM_FAILURE(rv)) {
   4049             LOG_ERROR(BSL_LS_BCM_OAM,
   4050                       (BSL_META_U(unit,
   4051                                   "OAM Error: LM counter block "
   4052                                   "free failed (EP=%d) - %s.\n"),
   4053                        hash_data->ep_id, bcm_errmsg(rv)));
   4054             return (rv);
   4055         }
   4056         hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 
   4057     }
   4058     return (rv);
   4059 }
   4060 
   4061 /*
   4062  * Function:
   4063  *     _bcm_kt2_oam_alloc_counter
   4064  * Purpose:
   4065  *     Allocate counter from counter pool.
   4066  * Parameters:
   4067  *     unit      - (IN) BCM device number
   4068  * Retruns:
   4069  *     BCM_E_XXX
   4070  */
   4071 STATIC int
   4072 _bcm_kt2_oam_alloc_counter(int unit, int pool_id, 
   4073                            shr_idxres_element_t *ctr_index)
   4074 {
   4075     int                  rv;             /* Operation return status.         */
   4076     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   4077 
   4078     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4079 
   4080     /* Allocate 8 consecutive couters from the pool */
   4081     rv =  shr_aidxres_list_alloc_block(oc->ing_lm_ctr_pool[pool_id],
   4082                                  8, ctr_index);
   4083     if (BCM_FAILURE(rv)) {
   4084         LOG_ERROR(BSL_LS_BCM_OAM,
   4085                   (BSL_META_U(unit,
   4086                               "OAM Error: LM counter block alloic failed "
   4087                               "- %s.\n"), bcm_errmsg(rv)));
   4088         return (rv);
   4089     }
   4090     return (BCM_E_NONE);
   4091 }
   4092 
   4093 #if defined(INCLUDE_BHH)
   4094 /*
   4095  * Function:
   4096  *     _bcm_kt2_oam_bhh_sec_mep_alloc_counter
   4097  * Purpose:
   4098  *     Allocate counter from counter pool.
   4099  * Parameters:
   4100  *     unit      - (IN) BCM device number
   4101  * Retruns:
   4102  *     BCM_E_XXX
   4103  */
   4104 STATIC int
   4105 _bcm_kt2_oam_bhh_sec_mep_alloc_counter(int unit, shr_idxres_element_t *ctr_index)
   4106 {
   4107     int                  rv;             /* Operation return status.         */
   4108     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   4109 
   4110     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4111 
   4112     /* Allocate 8 consecutive couters from the pool */
   4113     rv =  shr_aidxres_list_alloc_block(oc->ing_lm_sec_mep_ctr_pool,
   4114                                  8, ctr_index);
   4115     if (BCM_FAILURE(rv)) {
   4116         LOG_ERROR(BSL_LS_BCM_OAM,
   4117                   (BSL_META_U(unit,
   4118                               "OAM Error: LM counter block alloc failed "
   4119                               "- %s.\n"), bcm_errmsg(rv)));
   4120         return (rv);
   4121     }
   4122 
   4123     return (BCM_E_NONE);
   4124 }
   4125 #endif
   4126 /*
   4127  * Function:
   4128  *     _bcm_kt2_oam_counter_set
   4129  * Purpose:
   4130  *     Set Rx counter for MEP 
   4131  * Parameters:
   4132  *     unit      - (IN) BCM device number
   4133  * Retruns:
   4134  *     BCM_E_XXX
   4135  */
   4136 STATIC int
   4137 _bcm_kt2_oam_counter_set(int unit, soc_mem_t  mem, 
   4138                          uint32 *entry,
   4139                          shr_idxres_element_t *ctr_index,
   4140                          int *pool_id) 
   4141 {
   4142 
   4143     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   4144     soc_field_t   ctr1_field;
   4145     soc_field_t   ctr2_field;
   4146     int           ctr1_valid = 0;
   4147     int           ctr2_valid = 0;
   4148     int           rv = BCM_E_NONE;/* Operation return status.         */
   4149 
   4150     /* Lock already taken by the calling routine. */
   4151     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4152 
   4153     if (mem == L3_ENTRY_IPV4_UNICASTm) { 
   4154         ctr1_field = LMEP__CTR1_VALIDf;
   4155         ctr2_field = LMEP__CTR2_VALIDf;
   4156     } else {
   4157         ctr1_field = CTR1_VALIDf;
   4158         ctr2_field = CTR2_VALIDf;
   4159     }
   4160 
   4161     ctr1_valid = soc_mem_field32_get(unit, mem, 
   4162                                           (uint32 *)entry, ctr1_field);
   4163     ctr2_valid = soc_mem_field32_get(unit, mem, 
   4164                                           (uint32 *)entry, ctr2_field);
   4165 
   4166     /* if both counters are already used, we can't enable LM on this endpoint */
   4167     if ((1 == ctr1_valid) && (1 == ctr2_valid)) {
   4168         rv =  BCM_E_RESOURCE;
   4169         LOG_ERROR(BSL_LS_BCM_OAM,
   4170                   (BSL_META_U(unit,
   4171                               "OAM Error: 2 counters are already "
   4172                                "allocated for EP on this service interface"
   4173                               "%s.\n"), bcm_errmsg(rv)));
   4174         return (rv);
   4175     } else if ((0 == ctr1_valid) && (1 == ctr2_valid)) {
   4176         *pool_id = 0;
   4177         rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index);
   4178         if (BCM_FAILURE(rv)) {
   4179             LOG_ERROR(BSL_LS_BCM_OAM,
   4180                       (BSL_META_U(unit,
   4181                                   "OAM Error: LM counter block alloc - %s.\n"),
   4182                        bcm_errmsg(rv)));
   4183             return (rv);
   4184         }
   4185         ctr1_valid = 1;
   4186     } else if ((0 == ctr2_valid) && (1 == ctr1_valid)) {
   4187         *pool_id = 1;
   4188         rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index);
   4189         if (BCM_FAILURE(rv)) {
   4190             LOG_ERROR(BSL_LS_BCM_OAM,
   4191                       (BSL_META_U(unit,
   4192                                   "OAM Error: LM counter block alloc - %s.\n"),
   4193                        bcm_errmsg(rv)));
   4194             return (rv);
   4195         }
   4196         ctr2_valid = 1;
   4197     } else {
   4198         *pool_id = 0;
   4199         rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index);
   4200         if (BCM_FAILURE(rv)) {
   4201             *pool_id = 1;
   4202             rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id,  ctr_index);
   4203             if (BCM_FAILURE(rv)) {
   4204                 LOG_ERROR(BSL_LS_BCM_OAM,
   4205                           (BSL_META_U(unit,
   4206                                       "OAM Error: LM counter block alloc - %s.\n"),
   4207                            bcm_errmsg(rv)));
   4208                 return (rv);
   4209             }
   4210         }
   4211         ctr1_valid = 1;
   4212     }
   4213     return (rv);
   4214 }
   4215 /*
   4216  * Function:
   4217  *     _bcm_kt2_oam_service_pri_profile_add
   4218  * Purpose:
   4219  *     Create ING_SERVICE_PRI_MAP or EGR_SERVICE_PRI_MAP profile entry  
   4220  * Parameters:
   4221  *     unit      - (IN) BCM device number
   4222  *     egr       - (IN) Ingress/egess profile
   4223  *     ep_info_p - (IN) Pointer to remote endpoint information.
   4224  *     profile_index - (IN) Index of the profile entry created
   4225  * Retruns:
   4226  *     BCM_E_XXX
   4227  */
   4228 int
   4229 _bcm_kt2_oam_service_pri_profile_add(int unit, int egr, 
   4230                                      bcm_oam_endpoint_info_t *endpoint_info,
   4231                                      uint32 *profile_index)
   4232 {
   4233     int rv = BCM_E_NONE;            
   4234     int i = 0;
   4235     void *entries[1];
   4236     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   4237     soc_mem_t  mem = ING_SERVICE_PRI_MAPm;
   4238     uint32 mem_entries[BCM_OAM_INTPRI_MAX];
   4239     soc_profile_mem_t    *profile; /* profile to be used ingress or egress    */
   4240    
   4241     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4242     if (egr) {
   4243         mem = EGR_SERVICE_PRI_MAPm;
   4244         profile = &oc->egr_service_pri_map;
   4245     } else { 
   4246         profile = &oc->ing_service_pri_map;
   4247     }
   4248     for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
   4249         if (endpoint_info->pri_map[i] > _BCM_OAM_SERVICE_PRI_MAX_OFFSET) {
   4250             return BCM_E_PARAM;
   4251         }
   4252         mem_entries[i] = endpoint_info->pri_map[i];
   4253         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   4254             soc_mem_field32_set(unit, mem, &mem_entries[i], OFFSET_VALIDf, 1);
   4255         }
   4256     }
   4257     soc_mem_lock(unit, mem);
   4258     entries[0] = &mem_entries;
   4259     rv = soc_profile_mem_add(unit, profile, (void *) &entries, 
   4260                                           BCM_OAM_INTPRI_MAX, profile_index);
   4261     if (BCM_FAILURE(rv)) {
   4262         soc_mem_unlock(unit, mem);
   4263         return rv;
   4264     }
   4265     *profile_index = ((*profile_index)/BCM_OAM_INTPRI_MAX);
   4266     soc_mem_unlock(unit, mem);
   4267     return rv;
   4268 }
   4269 
   4270 /*
   4271  * Function:
   4272  *     _bcm_kt2_oam_lmep_counters_set
   4273  * Purpose:
   4274  *     Get Tx counters for LMEP 
   4275  * Parameters:
   4276  *     unit      - (IN) BCM device number
   4277  *     ep_info_p - (IN) Pointer to remote endpoint information.
   4278  * Retruns:
   4279  *     BCM_E_XXX
   4280  */
   4281 STATIC int
   4282 _bcm_kt2_oam_lmep_counters_set(int unit,
   4283                                   bcm_oam_endpoint_info_t *ep_info_p)
   4284 {
   4285     _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */
   4286     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   4287     l3_entry_1_entry_t   l3_entry;       /* L3 entry buffer.                 */
   4288     int                  l3_index = -1;  /* L3 entry hardware index.         */
   4289     shr_idxres_element_t ctr_index = 0;
   4290     int                  pool_id = 0;
   4291     egr_mp_group_entry_t egr_mp_group;   /* Egress MP group tbl entry buffer */
   4292     int                  mp_grp_index = 0;
   4293     int                  rv = BCM_E_NONE;/* Operation return status.         */
   4294     uint32               profile_index = 0;
   4295     uint32               direction = 0; /* Up MEP or Down MEP */
   4296 
   4297     /* Lock already taken by the calling routine. */
   4298     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4299 
   4300     /* Get the stored endpoint information from hash table. */
   4301     hash_data = &oc->oam_hash_data[ep_info_p->id];
   4302     if (0 == hash_data->in_use) {
   4303         return (BCM_E_INTERNAL);
   4304     }
   4305 
   4306     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   4307         direction = 1;
   4308     }
   4309 
   4310     /*For downMEP Rx counters are in Ing Mp group table and for UpMEP
   4311       it is in egr mp group table */
   4312     if (BCM_SUCCESS
   4313         (_bcm_kt2_oam_find_lmep(unit, hash_data, &l3_index, &l3_entry))) {
   4314         if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) {
   4315             /* Allocate counters and configure the same in L3 entry */
   4316             rv = _bcm_kt2_oam_counter_set(unit,
   4317                                           L3_ENTRY_IPV4_UNICASTm,
   4318                                           (uint32 *)&l3_entry,
   4319                                           &ctr_index, &pool_id);
   4320             if (BCM_FAILURE(rv)) {
   4321                 LOG_ERROR(BSL_LS_BCM_OAM,
   4322                           (BSL_META_U(unit,
   4323                                       "OAM Error: L3_ENTRY table update failed "
   4324                                       "for EP=%d due to counter allocation failure "
   4325                                       "%s.\n"), ep_info_p->id, bcm_errmsg(rv)));
   4326                 return (rv);
   4327             }
   4328             /* MS 8 bits of counter Id is pool id. LS 24 bits are index */
   4329             hash_data->tx_ctr = pool_id << 24 | (ctr_index);
   4330             hash_data->rx_ctr = hash_data->tx_ctr;
   4331         } else {
   4332             pool_id = hash_data->tx_ctr >> 24;
   4333         }
   4334         ep_info_p->lm_counter_base_id = hash_data->tx_ctr;
   4335         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   4336                                   mep_ctr_info[pool_id].ctr_valid, 1);
   4337         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   4338                      mep_ctr_info[pool_id].ctr_base_ptr,
   4339                      (hash_data->tx_ctr & 0xFFFFFF));
   4340         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   4341                               mep_ctr_info[pool_id].ctr_mep_type, direction);
   4342         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   4343                        mep_ctr_info[pool_id].ctr_mep_mdl, ep_info_p->level);
   4344         /* Create SERVICE_PRI_MAP profile */
   4345         rv = _bcm_kt2_oam_service_pri_profile_add(unit, 0, ep_info_p,
   4346                                                   &profile_index);
   4347         if (BCM_FAILURE(rv)) {
   4348             LOG_ERROR(BSL_LS_BCM_OAM, \
   4349                       (BSL_META_U(unit, \
   4350                                   "OAM Error: L3_ENTRY table update failed "
   4351                                   "for EP=%d due to service pri map profile allocation "
   4352                                   "failure %s.\n"),
   4353                        ep_info_p->id, bcm_errmsg(rv)));
   4354             return (rv);
   4355         }
   4356         hash_data->pri_map_index = profile_index;
   4357 
   4358         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   4359                      mep_ctr_info[pool_id].ctr_profile, profile_index);
   4360 
   4361         rv = soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL,
   4362                                                    l3_index, &l3_entry);
   4363         if (BCM_FAILURE(rv)) {
   4364             LOG_ERROR(BSL_LS_BCM_OAM,
   4365                       (BSL_META_U(unit,
   4366                                   "OAM Error: L3_ENTRY table write failed "
   4367                                   "for EP=%d %s.\n"),
   4368                        ep_info_p->id, bcm_errmsg(rv)));
   4369             return (rv);
   4370         }
   4371 
   4372     } else  {
   4373         LOG_ERROR(BSL_LS_BCM_OAM,
   4374                   (BSL_META_U(unit,
   4375                               "OAM Error: MP group tbl entry not found-%s.\n"),
   4376                    bcm_errmsg(rv)));
   4377         return rv;
   4378     }
   4379 
   4380     /*For downMEP Tx counters are in Egr Mp group table and for UpMEP it
   4381       is in ING MP group table */
   4382     if (BCM_SUCCESS(_bcm_kt2_oam_find_egr_lmep(unit, hash_data,
   4383                                     &mp_grp_index, &egr_mp_group))) {
   4384         if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) {
   4385             rv = _bcm_kt2_oam_counter_set(unit, EGR_MP_GROUPm,
   4386                            (uint32 *)&egr_mp_group, &ctr_index, &pool_id);
   4387             if (BCM_FAILURE(rv)) {
   4388                 LOG_ERROR(BSL_LS_BCM_OAM,
   4389                           (BSL_META_U(unit,
   4390                                       "OAM Error: EGR_MP_GROUP table update "
   4391                                       "failed for EP=%d due to counter allocation "
   4392                                       "failure  %s.\n"),
   4393                            ep_info_p->id, bcm_errmsg(rv)));
   4394                 return (rv);
   4395             }
   4396             /* MS 8 bits of counter Id is pool id. LS 24 bits are index */
   4397             hash_data->tx_ctr = pool_id << 24 | (ctr_index);
   4398             hash_data->rx_ctr = hash_data->tx_ctr;
   4399         } else {
   4400             pool_id = hash_data->tx_ctr >> 24;
   4401         }
   4402         ep_info_p->lm_counter_base_id = hash_data->tx_ctr;
   4403         if (SAL_BOOT_BCMSIM) {
   4404             /* Added as WAR for Cmodel issue */
   4405             /* Construct endpoint egress MP group Table entry key part */
   4406             _bcm_oam_egr_lmep_key_construct(unit, hash_data, &egr_mp_group);
   4407             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1);
   4408         }
   4409         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   4410                      egr_mep_ctr_info[pool_id].ctr_valid, 1);
   4411         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   4412                  egr_mep_ctr_info[pool_id].ctr_base_ptr,
   4413                  (hash_data->tx_ctr & 0xFFFFFF));
   4414         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   4415                     egr_mep_ctr_info[pool_id].ctr_mep_type, direction);
   4416         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   4417                  egr_mep_ctr_info[pool_id].ctr_mep_mdl, ep_info_p->level);
   4418 
   4419         /* Create SERVICE_PRI_MAP profile */
   4420         rv = _bcm_kt2_oam_service_pri_profile_add(unit, 1, ep_info_p,
   4421                                                   &profile_index);
   4422         if (BCM_FAILURE(rv)) {
   4423             LOG_ERROR(BSL_LS_BCM_OAM,
   4424                       (BSL_META_U(unit,
   4425                                   "OAM Error: EGR_MP_GROUP table update failed "
   4426                                   "for EP=%d due to service pri map profile allocation "
   4427                                   "failure %s.\n"),
   4428                        ep_info_p->id, bcm_errmsg(rv)));
   4429             return (rv);
   4430         }
   4431         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   4432                  egr_mep_ctr_info[pool_id].ctr_profile, profile_index);
   4433         hash_data->egr_pri_map_index = profile_index;
   4434 
   4435         rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL,
   4436                                                mp_grp_index, &egr_mp_group);
   4437         if (BCM_FAILURE(rv)) {
   4438             LOG_ERROR(BSL_LS_BCM_OAM,
   4439                       (BSL_META_U(unit,
   4440                                   "OAM Error: EGR_MP_GROUP table update failed "
   4441                                   "for EP=%d %s.\n"),
   4442                        ep_info_p->id, bcm_errmsg(rv)));
   4443             return (rv);
   4444         }
   4445     } else  {
   4446         LOG_ERROR(BSL_LS_BCM_OAM,
   4447                   (BSL_META_U(unit,
   4448                               "OAM Error: EGR MP group tbl entry not found-%s.\n"),
   4449                    bcm_errmsg(rv)));
   4450         return rv;
   4451     }
   4452 
   4453     return (rv);
   4454 }
   4455 
   4456 /*
   4457  * Function:
   4458  *      bcm_kt2_oam_hw_ccm_tx_ctr_update
   4459  * Purpose:
   4460  *      Update CCM CTR params
   4461  * Parameters:
   4462  *      unit - (IN) Unit number.
   4463  *      ep_info - (IN) Pointer to endpoint parameters
   4464  * Returns:
   4465  *      BCM_E_XXX
   4466  * Notes:
   4467  */
   4468 STATIC int
   4469 bcm_kt2_oam_hw_ccm_tx_ctr_update(int unit,
   4470         bcm_oam_endpoint_info_t *ep_info) 
   4471 {
   4472 
   4473     _bcm_oam_hash_data_t        *h_data_p;
   4474     _bcm_oam_control_t          *oc;
   4475     int                         rv=BCM_E_NONE;
   4476     lmep_1_entry_t              lmep_1_entry;    /* LMEP_1 table entry.*/
   4477     uint8                       num_counter;
   4478     uint32                      counter_id;
   4479     uint32                      pool;
   4480     lmep_entry_t                lmep_entry;    /* LMEP_1 table entry.*/
   4481 
   4482     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4483 
   4484     h_data_p =  &oc->oam_hash_data[ep_info->id];
   4485 
   4486     /* Get the LMEP_1 table entry. for the endpoint*/
   4487     rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry);
   4488     if (BCM_FAILURE(rv)) {
   4489         LOG_ERROR(BSL_LS_BCM_OAM,
   4490                 (BSL_META_U(unit,
   4491                             "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed "
   4492                             "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv)));
   4493         return rv;
   4494     }
   4495     
   4496     /* Get the LMEP_1 table entry. for the endpoint*/
   4497     rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_entry);
   4498     if (BCM_FAILURE(rv)) {
   4499         LOG_ERROR(BSL_LS_BCM_OAM,
   4500                 (BSL_META_U(unit,
   4501                             "OAM(unit %d) Error: LMEP table read (index=%d) failed "
   4502                             "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv)));
   4503         return rv;
   4504     }
   4505    
   4506     if (_KT2_OAM_COUNTER_SIZE < ep_info->ccm_tx_update_lm_counter_size) {
   4507         return BCM_E_PARAM;
   4508     }
   4509 
   4510     for(num_counter = 0; num_counter < ep_info->ccm_tx_update_lm_counter_size;
   4511             num_counter++) {
   4512 
   4513         /* Get the counter pool id */
   4514         counter_id = ep_info->ccm_tx_update_lm_counter_base_id[num_counter] + 
   4515             ep_info->ccm_tx_update_lm_counter_offset[num_counter];
   4516         pool = counter_id >> 24;
   4517 
   4518         switch(pool){
   4519             case 0:
   4520                 /* Set Counter 1 ID and action */
   4521                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_IDf, 
   4522                         (counter_id & 0xFFFF));
   4523                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_ACTIONf, 1);
   4524                 break;
   4525             case 1:
   4526                 /* Set Counter 2 ID and action */
   4527                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_IDf, 
   4528                         (counter_id & 0xFFFF));
   4529                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_ACTIONf, 1);
   4530                 break;
   4531             default:
   4532                 return BCM_E_PARAM;
   4533         }
   4534     }
   4535 
   4536     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   4537         /* TX counter is located in IP (0) */
   4538         soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_1_LOCATIONf, 0); 
   4539         soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_2_LOCATIONf, 0); 
   4540     } else {
   4541         /* TX counter is located in EP (1) */
   4542         soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_1_LOCATIONf, 1); 
   4543         soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_2_LOCATIONf, 1); 
   4544     } 
   4545     
   4546     rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   4547             &lmep_1_entry);
   4548     if (BCM_FAILURE(rv)) {
   4549         LOG_ERROR(BSL_LS_BCM_OAM,
   4550                 (BSL_META_U(unit,
   4551                             "OAM(unit %d) Error: LMEP_1 table write (EP=%d)"
   4552                             " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   4553         return rv;
   4554     }
   4555 
   4556     rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   4557             &lmep_entry);
   4558     if (BCM_FAILURE(rv)) {
   4559         LOG_ERROR(BSL_LS_BCM_OAM,
   4560                 (BSL_META_U(unit,
   4561                             "OAM(unit %d) Error: LMEP table write (EP=%d)"
   4562                             " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   4563         return rv;
   4564     }
   4565     return rv;
   4566 }
   4567 
   4568 STATIC int
   4569 _bcm_kt2_oam_lmep_down_modify_new_dest_port(int unit, _bcm_oam_hash_data_t *h_data_p)
   4570 {
   4571 
   4572     lmep_1_entry_t              lmep_1_entry;    /* LMEP_1 table entry.*/
   4573 
   4574     /* Get the LMEP_1 table entry. */
   4575     BCM_IF_ERROR_RETURN(READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry));
   4576 
   4577    
   4578     /* Set the queue number */ 
   4579     soc_LMEP_1m_field32_set(unit, &lmep_1_entry, QUEUE_NUMf,
   4580             SOC_INFO(unit).port_uc_cosq_base[h_data_p->dst_pp_port] +
   4581             h_data_p->int_pri);
   4582 
   4583     /* Set the PP port */
   4584     soc_LMEP_1m_field32_set(unit, &lmep_1_entry, PP_PORTf, h_data_p->dst_pp_port); 
   4585 
   4586     SOC_IF_ERROR_RETURN
   4587         (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   4588                      &lmep_1_entry));
   4589 
   4590 
   4591     return (BCM_E_NONE);
   4592 }
   4593 /*
   4594  * Function:
   4595  *     _bcm_oam_kt2_local_tx_mep_hw_set
   4596  * Purpose:
   4597  *     Configure hardware tables for a local CCM Tx enabled endpoint.
   4598  * Parameters:
   4599  *     unit      - (IN) BCM device number
   4600  *     ep_info_p - (IN) Pointer to remote endpoint information.
   4601  * Retruns:
   4602  *     BCM_E_XXX
   4603  */
   4604 STATIC int
   4605 _bcm_oam_kt2_local_tx_mep_hw_set(int unit,
   4606                                 bcm_oam_endpoint_info_t *ep_info_p)
   4607 {
   4608     int                  rv = BCM_E_NONE;/* Operation return status.   */
   4609     _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */
   4610     lmep_entry_t         entry;      /* LMEP table entry.              */
   4611     lmep_1_entry_t       entry_1;    /* LMEP_1 table entry.            */
   4612     int                  word;       /* Word index.                    */
   4613     uint32               reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4];
   4614                                      /* Group name in Hw format.       */
   4615     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   4616     const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info.   */
   4617     int                  subport = 0;
   4618     int                  oam_replacement_offset = 0;
   4619     int                  tpid_index = 0;
   4620     _bcm_kt2_subport_info_t subport_info;
   4621     int                  up_mep = 0;
   4622     int                  pp_port = 0;
   4623     int                  vlan_tag_control = 0;
   4624     uint32               tag_type = 0;
   4625     bcm_port_t           up_mep_tx_port = 0;
   4626     bcm_gport_t          gport = 0;
   4627 
   4628     if (NULL == ep_info_p) {
   4629         return (BCM_E_INTERNAL);
   4630     }
   4631 
   4632     /* Initialize local endpoint info pointer. */
   4633     ep_p = ep_info_p;
   4634 
   4635     /* Lock already taken by the calling routine. */
   4636     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   4637 
   4638     /* Get the stored endpoint information from hash table. */
   4639     hash_data = &oc->oam_hash_data[ep_p->id];
   4640     if (0 == hash_data->in_use) {
   4641         return(BCM_E_INTERNAL);
   4642     }
   4643 
   4644     sal_memset(&entry, 0, sizeof(lmep_entry_t));
   4645     sal_memset(&entry_1, 0, sizeof(lmep_1_entry_t));
   4646 
   4647     /* Set the Group base index. */
   4648     soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group);
   4649 
   4650     /* Set source MAC address to be used on transmitted packets. */
   4651     soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address);
   4652 
   4653     /* Set the Maintenance Domain Level. */
   4654     soc_LMEPm_field32_set(unit, &entry, MDLf, ep_p->level);
   4655 
   4656     /* Set endpoint name. */
   4657     soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name);
   4658 
   4659     /*
   4660      * Set VLAN ID to be used in the transmitted packet.
   4661      * For link level MEPs, this VLAN_ID == 0.
   4662      */
   4663     soc_LMEPm_field32_set(unit, &entry, SVLAN_TAGf, ep_p->vlan);
   4664 
   4665     /* Set packet priority value to be used in transmitted packet. */
   4666     soc_LMEPm_field32_set(unit, &entry, PRIORITYf, ep_p->pkt_pri);
   4667 
   4668     /* Set CVLAN Id */
   4669     soc_LMEPm_field32_set(unit, &entry, CVLAN_TAGf, ((ep_p->inner_pkt_pri << 13) | ep_p->inner_vlan));
   4670 
   4671     /* Set interval between CCM packet transmissions. */
   4672     soc_LMEPm_field32_set
   4673         (unit, &entry, CCM_INTERVALf,
   4674         _bcm_kt2_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period));
   4675 
   4676     /* Set Port status TLV in CCM Tx packets. */
   4677     if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) {
   4678         if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) {
   4679             return BCM_E_PARAM;
   4680         }
   4681         soc_LMEPm_field32_set(unit, &entry, PORT_TLVf,
   4682                               (ep_p->port_state == BCM_OAM_PORT_TLV_UP)
   4683                               ? 1 : 0);
   4684     }
   4685 
   4686 
   4687     /* Set the MEP type - up/down */
   4688     soc_LMEPm_field32_set(unit, &entry, MEP_TYPEf, 
   4689                          ((ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) ? 1 : 0));
   4690     /*
   4691      * Construct group name for hardware.
   4692      * i.e Word-reverse the MAID bytes for hardware.
   4693      */
   4694     for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4); ++word) {
   4695         reversed_maid[word]
   4696             = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name)
   4697                 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]);
   4698     }
   4699 
   4700     /* Set the group name. */
   4701     soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid);
   4702 
   4703     /* Set OAM replacement offset & default TPID */
   4704     if (_BCM_OAM_EP_IS_VP_TYPE(hash_data)) {
   4705         oam_replacement_offset = 1;
   4706         if(hash_data->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   4707             oam_replacement_offset = 5;
   4708             vlan_tag_control = 3;
   4709             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   4710         }else if (hash_data->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   4711             oam_replacement_offset = 3;
   4712             vlan_tag_control = 1;
   4713             tag_type =_BCM_OAM_DOMAIN_CVLAN;
   4714         } else if (hash_data->vlan > 0) {
   4715             oam_replacement_offset = 3;
   4716             vlan_tag_control = 2;
   4717             tag_type =_BCM_OAM_DOMAIN_SVLAN;
   4718         }
   4719     }
   4720 
   4721     switch (hash_data->oam_domain) {
   4722         case _BCM_OAM_DOMAIN_PORT:
   4723             oam_replacement_offset = 1;
   4724             vlan_tag_control = 0;
   4725             break;
   4726 
   4727         case _BCM_OAM_DOMAIN_CVLAN:
   4728             vlan_tag_control = 1;
   4729             oam_replacement_offset = 3;
   4730             tag_type =_BCM_OAM_DOMAIN_CVLAN;
   4731             break;
   4732 
   4733         case _BCM_OAM_DOMAIN_SVLAN: 
   4734             oam_replacement_offset = 3;
   4735             vlan_tag_control = 2;
   4736             tag_type =_BCM_OAM_DOMAIN_SVLAN;
   4737             break;
   4738 
   4739         case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
   4740             oam_replacement_offset = 5;
   4741             vlan_tag_control = 3;
   4742             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   4743             break;
   4744 
   4745         default:
   4746             break;
   4747     }
   4748 
   4749 
   4750     /* if S or S+C vlan - set outer tpid index */
   4751     if ((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 
   4752         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) { 
   4753         rv = _bcm_kt2_tpid_entry_add(unit, 
   4754                                  (ep_p->outer_tpid ? ep_p->outer_tpid :
   4755                                                  BCM_OAM_DEFAULT_TPID), 
   4756                                  BCM_OAM_TPID_TYPE_OUTER, &tpid_index);
   4757         if (BCM_FAILURE(rv)) {
   4758             LOG_ERROR(BSL_LS_BCM_OAM,
   4759                       (BSL_META_U(unit,
   4760                                   "OAM Error: L3 entry config failed in TPID set "
   4761                                   "for EP=%d %s.\n"),
   4762                        ep_p->id, bcm_errmsg(rv)));
   4763             return (rv);
   4764         }
   4765         hash_data->outer_tpid_profile_index = tpid_index;
   4766         soc_LMEPm_field32_set(unit, &entry, SVLAN_TPID_INDEXf, tpid_index); 
   4767     }
   4768     if ((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 
   4769         /* C or S+C */
   4770         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) { 
   4771         rv = _bcm_kt2_tpid_entry_add(unit, 
   4772                                  (ep_p->inner_tpid ? ep_p->inner_tpid :
   4773                                                  BCM_OAM_DEFAULT_TPID), 
   4774                                  BCM_OAM_TPID_TYPE_INNER, &tpid_index);
   4775         if (BCM_FAILURE(rv)) {
   4776             LOG_ERROR(BSL_LS_BCM_OAM,
   4777                       (BSL_META_U(unit,
   4778                                   "OAM Error: L3 entry config failed in TPID set "
   4779                                   "for EP=%d""  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   4780             return (rv);
   4781         }
   4782         hash_data->inner_tpid_profile_index = tpid_index;
   4783     }
   4784 
   4785     gport = hash_data->gport;
   4786     if (BCM_GPORT_IS_TRUNK(ep_p->gport)) {
   4787         gport =  hash_data->resolved_trunk_gport;
   4788     }
   4789 
   4790     if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) &&
   4791               (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) {
   4792         /* CoE port */
   4793         rv = _bcm_kt2_tpid_entry_add(unit, 
   4794                                  (ep_p->subport_tpid ? ep_p->subport_tpid :
   4795                                                  BCM_OAM_DEFAULT_TPID), 
   4796                                  BCM_OAM_TPID_TYPE_SUBPORT, &tpid_index);
   4797         if (BCM_FAILURE(rv)) {
   4798             LOG_ERROR(BSL_LS_BCM_OAM,
   4799                       (BSL_META_U(unit,
   4800                                   "OAM Error: L3 entry config failed in TPID set "
   4801                                   "for EP=%d  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   4802             return (rv);
   4803         }
   4804         soc_LMEPm_field32_set(unit, &entry, 
   4805                               SUBPORT_TAG_TPID_INDEXf, tpid_index); 
   4806         hash_data->subport_tpid_profile_index = tpid_index;
   4807     }
   4808 
   4809     /* Set LMEP_1 table entry */
   4810 
   4811     /* If COE or LINKPHY port replacement offset should be increased 
   4812        by 2 to accomodate - stream_id/subport tag */ 
   4813     if (BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   4814         if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) ||
   4815             (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, gport))) {
   4816             oam_replacement_offset += 2; 
   4817             subport = 1 << 2;
   4818         }
   4819     }
   4820 
   4821     soc_LMEP_1m_field32_set(unit, &entry_1, OAM_REPLACEMENT_OFFSETf, 
   4822                                                 oam_replacement_offset);
   4823   
   4824 
   4825     /* Set Tag status of the generated CCM packet 
   4826        we can set it based on incoming packet tag info 
   4827        if SUBPORT - vlan tag control = 1 << 2 | hash_data->oam_domain & 0x3 */
   4828     if (subport) {
   4829         soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 
   4830                                    (subport  | (vlan_tag_control & 0x3)));
   4831     } else {
   4832         soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 
   4833                                    (vlan_tag_control & 0x3));
   4834 
   4835     }
   4836     /* allocate TX counters */
   4837         /* allocate TX counters */
   4838     if(ep_info_p->type == bcmOAMEndpointTypeEthernet) {
   4839         if((ep_info_p->ccm_tx_update_lm_counter_size) && 
   4840                 (_BCM_OAM_INVALID_INDEX != hash_data->local_tx_index)) {
   4841             BCM_IF_ERROR_RETURN(bcm_kt2_oam_hw_ccm_tx_ctr_update(unit, ep_info_p)); 
   4842         }
   4843     }
   4844     
   4845     if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   4846         up_mep = 1;
   4847     } 
   4848     /* For DownMEP, set Queue number to which this packet must be enqueued */ 
   4849     if (!up_mep) {
   4850         soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf, 
   4851                      SOC_INFO(unit).port_uc_cosq_base[hash_data->dst_pp_port] + 
   4852                      ep_p->int_pri);
   4853      /* Set the destination portt on which packet needs to Tx. */
   4854         pp_port = hash_data->dst_pp_port;
   4855     } else {
   4856         soc_LMEP_1m_field32_set(unit, &entry_1, INT_PRIf,
   4857                 ep_p->int_pri);
   4858      /* Set the source on which packet is received */
   4859         pp_port = hash_data->src_pp_port;
   4860     } 
   4861 
   4862     if (ep_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) {
   4863 
   4864         up_mep_tx_port = _BCM_KT2_SUBPORT_PORT_ID_GET(ep_p->tx_gport);
   4865         hash_data->src_pp_port = up_mep_tx_port;
   4866         pp_port = hash_data->src_pp_port;
   4867     }
   4868 
   4869      /* Set the PP port */
   4870     soc_LMEP_1m_field32_set(unit, &entry_1, PP_PORTf, pp_port); 
   4871 
   4872     /* Set Outgoing Subport tag to be inserted into CCM packet */
   4873     if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) &&
   4874         (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) {
   4875         /* Get the subport tag */
   4876         rv = bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 
   4877                                                          &subport_info);
   4878         if (BCM_FAILURE(rv)) {
   4879             LOG_ERROR(BSL_LS_BCM_OAM,
   4880                       (BSL_META_U(unit,
   4881                                   "OAM Error: failed to get subport tag EP=%d"
   4882                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   4883             return (rv);
   4884         }
   4885         if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) {
   4886                 soc_LMEP_1m_field32_set(unit, &entry_1, SUBPORT_TAGf, 
   4887                                              subport_info.subtag);
   4888         }
   4889     }
   4890 
   4891     /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */
   4892     if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) {
   4893         if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP)
   4894             || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) {
   4895             return BCM_E_PARAM;
   4896         }
   4897         soc_LMEP_1m_field32_set(unit, &entry_1, INTERFACE_TLVf,
   4898                               ep_p->interface_state);
   4899     }
   4900     /*
   4901      * When this bit is '1', both port and interface TLV values are set in
   4902      *  CCM Tx packets - set in LMEP table.
   4903      */
   4904     if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX)
   4905         || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) {
   4906         soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1);
   4907     }
   4908 
   4909     /* Set CCM packet Destination MAC address value. */
   4910     soc_mem_mac_addr_set(unit, LMEP_1m, &entry_1, DAf,
   4911                          ep_p->dst_mac_address);
   4912 
   4913 
   4914     /* Write entry to hardware LMEP table. */
   4915     SOC_IF_ERROR_RETURN
   4916         (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   4917                      &entry));
   4918 
   4919     /* Write entry to hardware LMEP_1 table. */
   4920     SOC_IF_ERROR_RETURN
   4921         (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   4922                      &entry_1));
   4923 
   4924 
   4925     return (BCM_E_NONE);
   4926 }
   4927 
   4928 /*
   4929  * Function:
   4930  *     _bcm_kt2_oam_stm_table_update
   4931  * Purpose:
   4932  *     Update MA_BASE_PTR in source trunk MAP table 
   4933  * Parameters:
   4934  *     unit      - (IN) BCM device number
   4935  *     mod_id    - (IN) module id
   4936  *     port_id   - (IN) port id
   4937  *     h_data_p  - (IN) endpoint hash data
   4938  * Retruns:
   4939  *     BCM_E_XXX
   4940  */
   4941 STATIC int
   4942 _bcm_kt2_oam_stm_table_update(int unit, bcm_module_t mod_id,
   4943                               bcm_port_t port_id, 
   4944                               _bcm_oam_hash_data_t *h_data_p)
   4945 {
   4946     int    stm_index = 0;
   4947     int    rv;
   4948     source_trunk_map_table_entry_t stm_entry;
   4949 
   4950     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   4951 
   4952     /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/
   4953     rv = _bcm_esw_src_mod_port_table_index_get(unit, mod_id,
   4954                                                port_id, &stm_index);
   4955 
   4956     if(BCM_FAILURE(rv)) {
   4957         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   4958         return rv;
   4959     }
   4960 
   4961     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   4962                                       stm_index, &stm_entry);
   4963 
   4964     if(BCM_FAILURE(rv)) {
   4965         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   4966         return rv;
   4967     }
   4968 
   4969     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf,
   4970                                             h_data_p->ma_base_index);
   4971     rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index,
   4972                                                                 &stm_entry);
   4973     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   4974 
   4975     return rv;
   4976 }
   4977 
   4978 
   4979 /*
   4980  * Function:
   4981  *     _bcm_kt2_oam_port_mdl_update
   4982  * Purpose:
   4983  *     Update MDL bitmap in port table
   4984  * Parameters:
   4985  *     unit      - (IN) BCM device number
   4986  *     pp_port   - (IN) pp port id
   4987  *     reset     - (IN) Reset MDL bitmap or not
   4988  *     h_data_p  - (IN) endpoint hash data
   4989  *     mdl       - (OUT) Maintenance domain level
   4990  * Retruns:
   4991  *     BCM_E_XXX
   4992  */
   4993 STATIC int
   4994 _bcm_kt2_oam_port_mdl_update(int unit, uint32  pp_port, int reset, 
   4995                              _bcm_oam_hash_data_t *h_data_p, uint8 *mdl) 
   4996 {
   4997     port_tab_entry_t     port_entry;
   4998 
   4999     if (NULL == h_data_p) {
   5000         return (BCM_E_INTERNAL);
   5001     }
   5002     BCM_IF_ERROR_RETURN
   5003           (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, pp_port, &port_entry));
   5004 
   5005     /* read and update MDL bitmap */
   5006     *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   5007     if (reset) {
   5008         /* Clear the MDL bit for this endpoint. */
   5009         *mdl &= ~(1 << h_data_p->level);
   5010 
   5011     } else {
   5012         *mdl |= (1 << h_data_p->level);
   5013     }
   5014     soc_PORT_TABm_field32_set(unit, &port_entry, MDL_BITMAPf, *mdl);
   5015     BCM_IF_ERROR_RETURN
   5016          (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, pp_port, &port_entry));
   5017 
   5018     return BCM_E_NONE;
   5019 }            
   5020    
   5021 /*
   5022  * Function:
   5023  *     _bcm_kt2_oam_port_mdl_passive_update
   5024  * Purpose:
   5025  *     Update passive MDL bitmap in egress port table
   5026  * Parameters:
   5027  *     unit      - (IN) BCM device number
   5028  *     reset     - (IN) Reset MDL bitmap
   5029  *     h_data_p  - (IN) endpoint hash data
   5030  * Retruns:
   5031  *     BCM_E_XXX
   5032  */
   5033 STATIC int
   5034 _bcm_kt2_oam_port_mdl_passive_update(int unit, int reset,
   5035                                      _bcm_oam_hash_data_t *h_data_p, uint8 mdl) 
   5036 {
   5037     egr_port_entry_t     egr_port_entry;
   5038     uint8                passive_mdl = 0; /* Maintenance domain level-passive */
   5039     
   5040     if (NULL == h_data_p) {
   5041         return (BCM_E_INTERNAL);
   5042     }
   5043 
   5044     /* Passive demux should not be done for MIP */
   5045     if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   5046         return BCM_E_NONE;
   5047     }
   5048 
   5049     /* Set MDL passive bitmap in EGR_PORT table */
   5050     BCM_IF_ERROR_RETURN
   5051          (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, h_data_p->dst_pp_port,
   5052                           &egr_port_entry));
   5053 
   5054     if (reset) {
   5055         if (mdl > 0) {
   5056             /* Passive MDL bitmap */
   5057             _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, mdl,
   5058                                     h_data_p->ma_base_index, &passive_mdl, 0);
   5059         } else {
   5060             passive_mdl = 0;
   5061         }
   5062         soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 
   5063                                             MDL_BITMAP_PASSIVEf, passive_mdl);
   5064     } else {
   5065         /* read and update MDL bitmap */
   5066         mdl = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 
   5067                                                        MDL_BITMAP_PASSIVEf);
   5068         mdl |= (1 << h_data_p->level);
   5069 
   5070         /* Set all the bits till the highest configured MDL, so that there are 
   5071            no holes in the bitmap */
   5072         mdl |= ((1 << h_data_p->level) - 1);
   5073 
   5074         soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 
   5075                                                   MDL_BITMAP_PASSIVEf, mdl);
   5076     }
   5077     BCM_IF_ERROR_RETURN
   5078         (soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   5079                            h_data_p->dst_pp_port, &egr_port_entry));
   5080     return BCM_E_NONE;
   5081 }            
   5082 
   5083 /*
   5084  * Function:
   5085  *     _bcm_kt2_oam_trunk_port_mdl_config
   5086  * Purpose:
   5087  *     Update port mdl and stm table for OAM on trunk case     
   5088  * Parameters:
   5089  *     unit      - (IN) BCM device number
   5090  *     h_data_p - (IN) Pointer to hash data 
   5091  * Retruns:
   5092  *     BCM_E_XXX
   5093  */
   5094 STATIC int
   5095 _bcm_kt2_oam_trunk_port_mdl_config(int unit,
   5096                           _bcm_oam_hash_data_t *h_data_p)
   5097 {
   5098     int                  rv = BCM_E_NONE;/* Operation return status.         */
   5099     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5100     int                  member_count = 0;
   5101     bcm_port_t           *member_array = NULL; /* Trunk member port array.   */
   5102     int                  local_member_count = 0;
   5103     int                  i = 0;
   5104     bcm_port_t           port = 0;
   5105     bcm_module_t         module_id;            /* Module ID                  */
   5106     uint8                mdl = 0;
   5107 
   5108     /* Lock already taken by the calling routine. */
   5109     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5110 
   5111     if(h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   5112         return BCM_E_PARAM;
   5113     }
   5114 
   5115     /* Get all the local member ports belonging to this trunk */
   5116     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   5117                                NULL, 0, NULL, &member_count));
   5118     if (0 == member_count) {
   5119         /* No members have been added to the trunk group yet */
   5120         LOG_ERROR(BSL_LS_BCM_OAM,
   5121                   (BSL_META_U(unit,
   5122                               "OAM Error: No local members have been added to "
   5123                               "the trunk group yet - %s.\n"), bcm_errmsg(rv)));
   5124         return BCM_E_PARAM;
   5125     }
   5126 
   5127     _BCM_OAM_ALLOC(member_array, bcm_port_t,
   5128                        sizeof(bcm_port_t) * member_count, "Trunk info");
   5129     if (NULL == member_array) {
   5130         return (BCM_E_MEMORY);
   5131     }
   5132 
   5133     /* Get members of the trunk belonging to this module */
   5134     if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   5135                                                      h_data_p->trunk_id, 
   5136                                                      member_count, member_array,
   5137                                                      &local_member_count))) {
   5138         if (local_member_count > 0) {
   5139             for(i = 0; i < local_member_count; i++) {
   5140                 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   5141                                                   &module_id, &port);
   5142                 if (BCM_FAILURE(rv)) {
   5143                     sal_free(member_array);
   5144                     return (rv);
   5145                 }
   5146                 rv = _bcm_kt2_oam_stm_table_update(unit, module_id,
   5147                                                member_array[i], h_data_p);
   5148                 if (BCM_FAILURE(rv)) {
   5149                     sal_free(member_array);
   5150                     return (rv);
   5151                 }
   5152                 rv =_bcm_kt2_oam_port_mdl_update(unit, member_array[i], 0, 
   5153                                                         h_data_p, &mdl); 
   5154                 if (BCM_FAILURE(rv)) {
   5155                     sal_free(member_array);
   5156                     return (rv);
   5157                 }
   5158             } 
   5159         }
   5160         h_data_p->active_mdl_bitmap = mdl;
   5161     }
   5162     sal_free(member_array);
   5163     return BCM_E_NONE;
   5164 }
   5165 
   5166 /*
   5167  * Function:
   5168  *     _bcm_port_domain_oam_hw_set
   5169  * Purpose:
   5170  *    Configure port table and stm table entries for port based MEP. 
   5171  * Parameters:
   5172  *     unit      - (IN) BCM device number
   5173  *     ep_info_p - (IN) Pointer to remote endpoint information.
   5174  * Retruns:
   5175  *     BCM_E_XXX
   5176  */
   5177 STATIC int
   5178 _bcm_port_domain_oam_hw_set(int unit,
   5179                           const bcm_oam_endpoint_info_t *ep_info_p)
   5180 {
   5181     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   5182     int                  rv = BCM_E_NONE;/* Operation return status.         */
   5183     uint8                mdl = 0;        /* Maintenance domain level.        */
   5184     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5185     const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info.        */
   5186     bcm_module_t         mod_id = 0;
   5187     bcm_port_t           port_id = 0;
   5188 
   5189     if (NULL == ep_info_p) {
   5190         return (BCM_E_INTERNAL);
   5191     }
   5192 
   5193     /* Initialize local endpoint info pointer. */
   5194     ep_p = ep_info_p;
   5195 
   5196     /* Lock already taken by the calling routine. */
   5197     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5198 
   5199     /* Get endpoint hash data pointer. */
   5200     h_data_p = &oc->oam_hash_data[ep_p->id];
   5201 
   5202     /*  Set port table and source trunk map table */
   5203     if (0 == ep_info_p->vlan) {
   5204         if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   5205             rv = _bcm_kt2_oam_trunk_port_mdl_config(unit, h_data_p);
   5206         } else {
   5207             port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   5208             mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   5209             BCM_IF_ERROR_RETURN
   5210                 (_bcm_kt2_oam_stm_table_update(unit, mod_id,
   5211                                                port_id, h_data_p));
   5212             BCM_IF_ERROR_RETURN
   5213                 (_bcm_kt2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 0, 
   5214                                              h_data_p,  &mdl)); 
   5215             h_data_p->active_mdl_bitmap = mdl;
   5216         }
   5217         BCM_IF_ERROR_RETURN
   5218             (_bcm_kt2_oam_port_mdl_passive_update(unit, 0, h_data_p, mdl)); 
   5219     }
   5220     return (rv);
   5221 }
   5222 
   5223 
   5224 /*
   5225  * Function:
   5226  *     _bcm_kt2_oam_l3_entry_set
   5227  * Purpose:
   5228  *     Configure l3 entry tables entry for a local CCM Rx enabled endpoint.
   5229  * Parameters:
   5230  *     unit      - (IN) BCM device number
   5231  *     ep_info_p - (IN) Pointer to remote endpoint information.
   5232  * Retruns:
   5233  *     BCM_E_XXX
   5234  */
   5235 STATIC int
   5236 _bcm_kt2_oam_l3_entry_set(int unit,
   5237                           bcm_oam_endpoint_info_t *ep_info_p)
   5238 {
   5239     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   5240     l3_entry_1_entry_t   l3_entry;       /* L3 entry buffer.                 */
   5241     int                  l3_index = -1;  /* L3 entry hardware index.         */
   5242     int                  rv;             /* Operation return status.         */
   5243     uint8                mdl = 0;        /* Maintenance domain level.        */
   5244     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5245     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   5246     soc_field_t          mdl_field = 0;             
   5247     int                  up_mep = 0;     /* Endpoint is an upMep             */
   5248 
   5249     if (NULL == ep_info_p) {
   5250         return (BCM_E_INTERNAL);
   5251     }
   5252 
   5253     /* Initialize local endpoint info pointer. */
   5254     ep_p = ep_info_p;
   5255 
   5256     /* Lock already taken by the calling routine. */
   5257     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5258 
   5259     /* Get endpoint hash data pointer. */
   5260     h_data_p = &oc->oam_hash_data[ep_p->id];
   5261 
   5262     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   5263         up_mep = 1 ;
   5264         mdl_field = LMEP__MDL_BITMAP_PASSIVEf;
   5265     } else {
   5266         mdl_field = LMEP__MDL_BITMAP_ACTIVEf;
   5267     }
   5268     /* L3 entry */
   5269     L3_LOCK(unit);
   5270     if (BCM_SUCCESS
   5271             (_bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry))) {
   5272         if ((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) &&
   5273                 (_BCM_OAM_EP_IS_MIP(h_data_p))) {
   5274             /* Passive demultiplexing should not be done on a MIP */
   5275             L3_UNLOCK(unit);
   5276             return BCM_E_NONE;
   5277         }
   5278 
   5279         /* There's already an entry for this */
   5280         mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, mdl_field);
   5281 
   5282         /* If active bitmap is 0, so for first active endppoint in the mp_group 
   5283          * need to programme ma_base_ptr field  during down_mep creation */
   5284         if((mdl == 0) && (up_mep == 0)) {
   5285             soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__MA_BASE_PTRf,
   5286                     h_data_p->ma_base_index);
   5287         } 
   5288 
   5289         mdl |= (1 << ep_p->level);
   5290 
   5291         /* Set all the bits till the highest configured MDL, so that there are 
   5292            no holes in the passive bitmap */
   5293         if (up_mep) {
   5294             mdl |= ((1 << ep_p->level) - 1);
   5295         }
   5296         /* set MDL bitmap passive or active depending on up or down mep */
   5297         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, mdl_field, mdl);
   5298 
   5299         rv = soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, 
   5300                                                        l3_index, &l3_entry);
   5301         if (BCM_FAILURE(rv)) {
   5302             L3_UNLOCK(unit);
   5303             LOG_ERROR(BSL_LS_BCM_OAM,
   5304                       (BSL_META_U(unit,
   5305                                   "OAM Error: L3_ENTRY table update failed for "
   5306                                   "EP=%d" "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   5307             return (rv);
   5308         }
   5309     } else {
   5310 
   5311         /* This is the first entry at this */
   5312         sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   5313 
   5314         /* Passive demultiplexing should not be done on a MIP */
   5315         if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf)
   5316             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   5317             mdl |= (1 << ep_p->level);
   5318 
   5319             /* Set all the bits till the highest configured MDL, so that there are 
   5320                no holes in the passive bitmap */
   5321             if (up_mep) {
   5322                 mdl |= ((1 << ep_p->level) - 1);
   5323             }
   5324         }
   5325         /* set MDL bitmap passive or active depending on up or down mep */
   5326         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, mdl_field, mdl);
   5327 
   5328         if (mdl == 0) {
   5329             /* MDL = 0 for case of MIP. Dont make the entry valid by
   5330                programming other fields.  */
   5331             return BCM_E_NONE;
   5332         }
   5333 
   5334         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 
   5335                                                LMEP__MA_BASE_PTRf,
   5336                                                h_data_p->ma_base_index);
   5337 
   5338         /* Configure time stamp type 1588(PTP)/NTP */
   5339         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 
   5340                                        LMEP__TIMESTAMP_TYPEf,
   5341              ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0));
   5342 
   5343         h_data_p->ts_format = ep_p->timestamp_format;
   5344 
   5345         /* Construct LMEP view key for L3 Table insert operation. */
   5346         _bcm_kt2_oam_lmep_key_construct(unit, h_data_p, &l3_entry);
   5347 
   5348         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1);
   5349 
   5350         rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, 
   5351                                                  MEM_BLOCK_ALL, &l3_entry);
   5352         if (BCM_FAILURE(rv)) {
   5353             LOG_ERROR(BSL_LS_BCM_OAM,
   5354                       (BSL_META_U(unit,
   5355                                   "OAM Error: L3_ENTRY table insert failed for "
   5356                                   "EP=%d" "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   5357             L3_UNLOCK(unit);
   5358             return (rv);
   5359         }
   5360     }
   5361     if (up_mep == 0) {
   5362         h_data_p->active_mdl_bitmap = mdl;
   5363     }
   5364     L3_UNLOCK(unit);
   5365     return (BCM_E_NONE);
   5366 }
   5367         
   5368 /*
   5369  * Function:
   5370  *     _bcm_kt2_oam_egr_mp_group_entry_set
   5371  * Purpose:
   5372  *     Configure Egress MP group tables entry for local CCM Rx enabled endpoint.
   5373  * Parameters:
   5374  *     unit      - (IN) BCM device number
   5375  *     ep_info_p - (IN) Pointer to remote endpoint information.
   5376  *     ctr_index - (OUT) LM counter index
   5377  * Retruns:
   5378  *     BCM_E_XXX
   5379  */
   5380 STATIC int
   5381 _bcm_kt2_oam_egr_mp_group_entry_set(int unit,
   5382                           bcm_oam_endpoint_info_t *ep_info_p,
   5383                           shr_idxres_element_t *ctr_index)
   5384 {
   5385     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   5386     int                  rv;             /* Operation return status.         */
   5387     uint8                mdl = 0;        /* Maintenance domain level.        */
   5388     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5389     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   5390     soc_field_t          mdl_field = 0;             
   5391     egr_mp_group_entry_t egr_mp_group;   /* Egress MP group tbl entry buffer */
   5392     int                  up_mep = 0;     /* Endpoint is an upMep             */
   5393     int                  mp_grp_index = 0;
   5394 
   5395     if (NULL == ep_info_p) {
   5396         return (BCM_E_INTERNAL);
   5397     }
   5398 
   5399     /* Initialize local endpoint info pointer. */
   5400     ep_p = ep_info_p;
   5401 
   5402     /* Lock already taken by the calling routine. */
   5403     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5404 
   5405     /* Get endpoint hash data pointer. */
   5406     h_data_p = &oc->oam_hash_data[ep_p->id];
   5407 
   5408     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   5409         up_mep = 1;
   5410         mdl_field = MDL_BITMAP_ACTIVEf;
   5411     } else {
   5412         mdl_field = MDL_BITMAP_PASSIVEf;
   5413     }
   5414 
   5415     /* form the key to search EGR_MP_GRUP table */
   5416     if (BCM_SUCCESS
   5417         (_bcm_kt2_oam_find_egr_lmep(unit, h_data_p,
   5418                                         &mp_grp_index, &egr_mp_group))) {
   5419 
   5420         /* There's already an entry for this */
   5421         if (SAL_BOOT_BCMSIM) {
   5422         /* Added as WAR for Cmodel issue */
   5423         /* Construct endpoint egress MP group  Table entry search operation. */
   5424             _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group);
   5425             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1);
   5426         }
   5427         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, mdl_field);
   5428         /* If active bitmap is 0, so for first active endppoint in the mp_group 
   5429          * need to programme ma_base_ptr field  during up_mep creation */
   5430         if((mdl == 0) && up_mep) {
   5431             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf,
   5432                     h_data_p->ma_base_index);
   5433         } 
   5434 
   5435         /* Passive demultiplexing should not be done on a MIP */
   5436         if (!((mdl_field == MDL_BITMAP_PASSIVEf) 
   5437             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   5438             mdl |= (1 << ep_p->level);
   5439 
   5440             /* Set all the bits till the highest configured MDL, so that there are 
   5441                no holes in the passive bitmap */
   5442             if (mdl_field == MDL_BITMAP_PASSIVEf) {
   5443                 mdl |= ((1 << ep_p->level) - 1);
   5444             }
   5445         }
   5446         /* set MDL bitmap passive or active depending on up or down mep */
   5447         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl);
   5448 
   5449         soc_mem_lock(unit, EGR_MP_GROUPm);
   5450 
   5451         rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 
   5452                                              mp_grp_index, &egr_mp_group);
   5453         if (BCM_FAILURE(rv)) {
   5454             soc_mem_unlock(unit, EGR_MP_GROUPm);
   5455             return (rv);
   5456         }
   5457         soc_mem_unlock(unit, EGR_MP_GROUPm);
   5458     } else {
   5459 
   5460         /* This is the first entry at this */
   5461         sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
   5462 
   5463         /* Passive demultiplexing should not be done on a MIP */
   5464         if (!((mdl_field == MDL_BITMAP_PASSIVEf) 
   5465             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   5466             mdl = (1 << ep_p->level);
   5467             /* Set all the bits till the highest configured MDL, so that there are 
   5468                no holes in the passive bitmap */
   5469             if ( mdl_field == MDL_BITMAP_PASSIVEf && !(BHH_EP_TYPE(ep_info_p)) ) {
   5470                 mdl |= ((1 << ep_p->level) - 1);
   5471             }
   5472         }
   5473 
   5474         if (mdl == 0) {
   5475             /* MDL = 0 for case of MIP. Dont make the entry valid by
   5476                programming other fields.  */
   5477             return BCM_E_NONE;
   5478         }
   5479 
   5480         /* set MDL bitmap passive or active depending on up or down mep */
   5481         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl);
   5482 
   5483         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf,
   5484                                       h_data_p->ma_base_index);
   5485 
   5486         /* Configure time stamp type 1588(PTP)/NTP */
   5487         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 
   5488                                        TIMESTAMP_TYPEf,
   5489              ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0));
   5490 
   5491         h_data_p->ts_format = ep_p->timestamp_format;
   5492 
   5493         /* Construct LMEP view key for L3 Table insert operation. */
   5494         _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group);
   5495 
   5496         soc_mem_lock(unit, EGR_MP_GROUPm);
   5497 
   5498         rv = soc_mem_insert(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, &egr_mp_group);
   5499         if (BCM_FAILURE(rv)) {
   5500             soc_mem_unlock(unit, EGR_MP_GROUPm);
   5501             return (rv);
   5502         }
   5503         soc_mem_unlock(unit, EGR_MP_GROUPm);
   5504     }
   5505     if (up_mep == 1) {
   5506         h_data_p->active_mdl_bitmap = mdl;
   5507     }
   5508     return (BCM_E_NONE);
   5509 }
   5510 
   5511  STATIC int
   5512 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op (int unit,
   5513                              _bcm_oam_hash_data_t *h_data_p,
   5514                              soc_mem_t mem,
   5515                              int delete)
   5516 {
   5517     uint32             mdl_value[1] = { 0 };
   5518     int                bit_pos = 0;
   5519     int                current_offset = 0;
   5520     int                new_offset = 0;
   5521     int                entry_count = 0;
   5522     shr_idxres_list_handle_t pool;
   5523     bcm_oam_endpoint_t *temp_array = NULL;
   5524     _bcm_oam_control_t   *oc = NULL;
   5525     int ma_base_index = _BCM_OAM_INVALID_INDEX;
   5526     int is_upmep = 0;
   5527     l3_entry_1_entry_t l3_entry;       /* LMEP view table entry.            */
   5528     int                l3_index = -1;  /* L3 table hardware index.          */
   5529     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   5530     int                mp_grp_index = -1;
   5531     int                     stm_index = 0;
   5532     source_trunk_map_table_entry_t stm_entry;
   5533     uint8 port_mdl = 0;
   5534     int rv = BCM_E_NONE;
   5535 
   5536     if (NULL == h_data_p) {
   5537         return (BCM_E_INTERNAL);
   5538     }
   5539 
   5540     /* Lock already taken by the calling routine. */
   5541     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5542 
   5543     if (mem == MA_INDEXm) { 
   5544         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit,
   5545                     h_data_p, &entry_count, &pool));
   5546     } else {
   5547         entry_count = 8;
   5548     }
   5549 
   5550     if (entry_count <= 0) {
   5551         return BCM_E_INTERNAL;
   5552     }
   5553 
   5554 
   5555     ma_base_index = h_data_p->ma_base_index;
   5556     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   5557 
   5558     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   5559         rv = _bcm_kt2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &port_mdl);
   5560         if (BCM_SUCCESS(rv)) {
   5561             mdl_value[0] = port_mdl; 
   5562         } else {
   5563             /* If app is not initialized (say rc), then during detach (delete)
   5564              * we will not find the entry. simply return without error */
   5565             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   5566                 return BCM_E_NONE;
   5567             } else {
   5568                 return BCM_E_INTERNAL;
   5569             }
   5570         }
   5571     } else if (is_upmep) {
   5572         rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 
   5573                 &mp_grp_index, &egr_mp_group);
   5574         if (BCM_SUCCESS(rv)) {
   5575             mdl_value[0] = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   5576                     MDL_BITMAP_ACTIVEf);
   5577         } else {
   5578             /* If app is not initialized (say rc), then during detach (delete)
   5579              * we will not find the entry. simply return without error */
   5580             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   5581                 return BCM_E_NONE;
   5582             } else {
   5583                 return BCM_E_INTERNAL;
   5584             }
   5585         }
   5586     } else {
   5587         rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry);
   5588         if (BCM_SUCCESS(rv)) {
   5589             mdl_value[0] = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   5590                                                       LMEP__MDL_BITMAP_ACTIVEf);
   5591         } else {
   5592             /* If app is not initialized (say rc), then during detach (delete)
   5593              * we will not find the entry. simply return without error */
   5594             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   5595                 return BCM_E_NONE;
   5596             } else {
   5597                 return BCM_E_INTERNAL;
   5598             }
   5599         }
   5600     }
   5601 
   5602     _BCM_OAM_ALLOC(temp_array, bcm_oam_endpoint_t,
   5603                        sizeof(bcm_oam_endpoint_t) * entry_count, "endpoint id array");
   5604     if (NULL == temp_array) {
   5605         return (BCM_E_MEMORY);
   5606     }
   5607     /* Initialize the entry buffer. */
   5608     sal_memset(temp_array, _BCM_OAM_INVALID_INDEX, sizeof(bcm_oam_endpoint_t) * entry_count);
   5609 
   5610 
   5611     if (delete) {
   5612         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5613             if (SHR_BITGET(mdl_value, bit_pos)) {
   5614                if (bit_pos == h_data_p->level) {
   5615                    current_offset++;
   5616                } else {
   5617                    temp_array[new_offset] = 
   5618                     oc->_bcm_oam_ma_idx_to_ep_id_map
   5619                     [_BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   5620                         (ma_base_index, current_offset, is_upmep)];
   5621                    new_offset++;
   5622                    current_offset++;
   5623                }    
   5624             }
   5625         }
   5626     } else {
   5627         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5628             if (SHR_BITGET(mdl_value, bit_pos)) {
   5629                if (bit_pos == h_data_p->level) {
   5630                    temp_array[new_offset] = h_data_p->ep_id; 
   5631                    new_offset++;
   5632                } else {
   5633                    temp_array[new_offset] = 
   5634                     oc->_bcm_oam_ma_idx_to_ep_id_map[
   5635                     _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index,
   5636                             current_offset, is_upmep)];
   5637                    new_offset++;
   5638                    current_offset++;
   5639                }    
   5640             }
   5641         }
   5642     }
   5643 
   5644     sal_memcpy(&(oc->_bcm_oam_ma_idx_to_ep_id_map[
   5645                 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   5646                 (ma_base_index, 0, is_upmep)]), 
   5647                 temp_array, sizeof(bcm_oam_endpoint_t) * entry_count);
   5648 
   5649     sal_free(temp_array);
   5650     return (BCM_E_NONE);
   5651 }
   5652  
   5653 STATIC int
   5654 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add (int unit,
   5655                              _bcm_oam_hash_data_t *h_data_p)
   5656 {
   5657     int is_upmep = 0;
   5658     int is_remote = 0;
   5659     int is_rx_enabled = 0;
   5660     soc_mem_t mem = MA_INDEXm;
   5661     int rv = BCM_E_NONE;
   5662 
   5663     /* h_data_p being NULL could already be some other error
   5664      * scenario. Lets not return error for such a scenario.
   5665      */
   5666     if (h_data_p == NULL) {
   5667         return BCM_E_NONE;
   5668     }
   5669 
   5670     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   5671     if (is_upmep) {
   5672         mem = EGR_MA_INDEXm;
   5673     }
   5674     is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0;
   5675     is_rx_enabled =  (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX);
   5676     if (is_remote || !is_rx_enabled) {
   5677         /* Dont touch anything for remote endpoints or only tx enabled */
   5678         return BCM_E_NONE;
   5679     }
   5680     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 0); 
   5681 
   5682     return rv;
   5683 }
   5684 
   5685 STATIC int
   5686 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete (int unit,
   5687                              _bcm_oam_hash_data_t *h_data_p)
   5688 {
   5689     int is_upmep = 0;
   5690     int is_remote = 0;
   5691     int is_rx_enabled = 0;
   5692     soc_mem_t mem = MA_INDEXm;
   5693     int rv = BCM_E_NONE;
   5694 
   5695     /* h_data_p being NULL could already be some other error
   5696      * scenario. Lets not return error for such a scenario.
   5697      */
   5698     if (h_data_p == NULL) {
   5699         return BCM_E_NONE;
   5700     }
   5701 
   5702     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   5703     if (is_upmep) {
   5704         mem = EGR_MA_INDEXm;
   5705     }
   5706     is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0;
   5707     is_rx_enabled =  (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX);
   5708     if (is_remote || !is_rx_enabled) {
   5709         /* Dont touch anything for remote endpoints or only tx enabled */
   5710         return BCM_E_NONE;
   5711     }
   5712     rv =  _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 1); 
   5713 
   5714     return rv;
   5715 }
   5716 
   5717 STATIC INLINE bcm_oam_endpoint_t
   5718 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t   *oc, int ma_idx)
   5719 {
   5720     return oc->_bcm_oam_ma_idx_to_ep_id_map[ma_idx];
   5721 }
   5722 
   5723 STATIC int _bcm_kt2_oam_ma_idx_to_ep_id_mapping_init (int unit)
   5724 {
   5725     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5726 
   5727     /* Lock already taken by the calling routine. */
   5728     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5729 
   5730     _BCM_OAM_ALLOC(oc->_bcm_oam_ma_idx_to_ep_id_map, bcm_oam_endpoint_t,
   5731                        _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE , "MA_IDX_TO_EP_ID map");
   5732 
   5733     if (oc->_bcm_oam_ma_idx_to_ep_id_map == NULL) {
   5734         return BCM_E_MEMORY;
   5735     }
   5736 
   5737     /* Init it to all invalid */
   5738     sal_memset(oc->_bcm_oam_ma_idx_to_ep_id_map, _BCM_OAM_INVALID_INDEX,
   5739                 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE);
   5740     return BCM_E_NONE;
   5741 }
   5742 
   5743 STATIC int _bcm_kt2_oam_ma_idx_to_ep_id_mapping_destroy (int unit)
   5744 {
   5745     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   5746 
   5747     /* Lock already taken by the calling routine. */
   5748     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   5749 
   5750     if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) {
   5751         sal_free(oc->_bcm_oam_ma_idx_to_ep_id_map);
   5752         oc->_bcm_oam_ma_idx_to_ep_id_map = NULL;
   5753     }
   5754 
   5755     return BCM_E_NONE;
   5756 }
   5757 
   5758 
   5759 STATIC int
   5760 _bcm_kt2_oam_ma_index_entry_set(int unit,
   5761                              _bcm_oam_hash_data_t *h_data_p,
   5762                              soc_mem_t mem,
   5763                              void *ma_idx_ptr, int delete)
   5764 {
   5765     int                rv = BCM_E_NONE;
   5766     uint32             mdl_value[1] = { 0 };
   5767     int                bit_pos = 0;
   5768     int                current_offset = 0;
   5769     int                new_offset = 0;
   5770     int                entry_count = 0;
   5771     int                entry_mem_size = 0; 
   5772     ma_index_entry_t *entry_buf;
   5773     ma_index_entry_t *entry;
   5774     ma_index_entry_t *entry_current;
   5775     shr_idxres_list_handle_t pool = NULL;
   5776 
   5777     if (NULL == h_data_p) {
   5778         return (BCM_E_INTERNAL);
   5779     }
   5780 
   5781     if (mem == MA_INDEXm) { 
   5782         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit,
   5783                     h_data_p, &entry_count, &pool));
   5784         new_offset = entry_count;
   5785         entry_mem_size = sizeof(ma_index_entry_t);
   5786     } else {
   5787         entry_mem_size = sizeof(egr_ma_index_entry_t);
   5788         new_offset = entry_count = 8;
   5789     }
   5790     if(entry_count <= 0) {
   5791         return BCM_E_INTERNAL;
   5792     }
   5793     /* Allocate buffer to store the DMAed table entries. */
   5794     entry_buf = soc_cm_salloc(unit, entry_mem_size * entry_count * 2,
   5795                               "MA index table entry buffer");
   5796     if (NULL == entry_buf) {
   5797         return (BCM_E_MEMORY);
   5798     }
   5799     /* Initialize the entry buffer. */
   5800     sal_memset(entry_buf, 0, entry_mem_size * entry_count * 2);
   5801 
   5802     /* Read the table entries into the buffer. */
   5803     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 
   5804                             (h_data_p->ma_base_index + entry_count - 1), 
   5805                             entry_buf);
   5806     if (BCM_FAILURE(rv)) {
   5807         if (entry_buf) {
   5808             soc_cm_sfree(unit, entry_buf);
   5809         }
   5810         return rv;
   5811     }
   5812 
   5813     mdl_value[0] = h_data_p->active_mdl_bitmap;
   5814 
   5815     if (delete) {
   5816         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5817             if (SHR_BITGET(mdl_value, bit_pos)) {
   5818                if (bit_pos == h_data_p->level) {
   5819                    current_offset++;
   5820                } else {
   5821                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   5822                                                     ma_index_entry_t *,
   5823                                                     entry_buf, new_offset);
   5824                    entry_current = soc_mem_table_idx_to_pointer(unit, mem, 
   5825                                                     ma_index_entry_t *,
   5826                                                     entry_buf, current_offset);
   5827                    sal_memcpy(entry, entry_current, entry_mem_size);
   5828                    new_offset++;
   5829                    current_offset++;
   5830                }    
   5831             }
   5832         }
   5833     } else {
   5834         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5835             if (SHR_BITGET(mdl_value, bit_pos)) {
   5836                if (bit_pos == h_data_p->level) {
   5837                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   5838                                                     ma_index_entry_t *,
   5839                                                     entry_buf, new_offset);
   5840                    sal_memcpy(entry, ma_idx_ptr, entry_mem_size);
   5841                    /* Doing Mod entry_count since new_offset starts
   5842                       from entry_count */
   5843                    h_data_p->local_rx_index = h_data_p->ma_base_index +
   5844                                      (new_offset % entry_count);
   5845                    new_offset++;
   5846                } else {
   5847                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   5848                                                     ma_index_entry_t *,
   5849                                                     entry_buf, new_offset);
   5850                    entry_current = soc_mem_table_idx_to_pointer(unit, mem, 
   5851                                                     ma_index_entry_t *,
   5852                                                     entry_buf, current_offset);
   5853                    sal_memcpy(entry, entry_current, entry_mem_size);
   5854                    new_offset++;
   5855                    current_offset++;
   5856                }    
   5857             }
   5858         }
   5859     }
   5860     /* Move to the entry_count index since from there the newly programmed
   5861      * ma_index table memory is present */
   5862     entry = soc_mem_table_idx_to_pointer(unit, mem, ma_index_entry_t *,
   5863                                                     entry_buf, entry_count);
   5864     rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index,
   5865                              (h_data_p->ma_base_index + entry_count - 1), 
   5866                              entry);
   5867     if (BCM_FAILURE(rv)) {
   5868         if (entry_buf) {
   5869             soc_cm_sfree(unit, entry_buf);
   5870         }
   5871         return rv;
   5872     }
   5873     if (entry_buf) {
   5874         soc_cm_sfree(unit, entry_buf);
   5875     }
   5876     return (BCM_E_NONE);
   5877 } 
   5878 
   5879 STATIC int
   5880 _bcm_kt2_oam_port_table_ma_index_offset_get(int unit, 
   5881                                             _bcm_oam_hash_data_t *h_data_p, 
   5882                                             int *ma_offset) 
   5883 {
   5884     int                rv = BCM_E_NONE;
   5885     uint32             mdl_value[1] = { 0 };
   5886     int                bit_pos = 0;
   5887     bcm_port_t         port_id;              /* Port ID.            */
   5888     int                local_member_count = 0;
   5889     port_tab_entry_t   port_entry;
   5890     int                offset_found = 0;
   5891 
   5892     if (NULL == h_data_p) {
   5893         return (BCM_E_INTERNAL);
   5894     }
   5895     if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   5896         rv = _bcm_kt2_oam_trunk_port_mdl_config(unit, h_data_p);
   5897 
   5898         /* Get a member of the trunk belonging to this module */
   5899         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   5900                                            h_data_p->trunk_id, 1,
   5901                                            &port_id,
   5902                                            &local_member_count))) {
   5903         } else {
   5904             return (BCM_E_INTERNAL);
   5905         }
   5906         BCM_IF_ERROR_RETURN
   5907               (soc_mem_read(unit, PORT_TABm, 
   5908                             MEM_BLOCK_ANY, port_id, &port_entry));
   5909     } else {
   5910          BCM_IF_ERROR_RETURN
   5911               (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 
   5912                             h_data_p->src_pp_port, &port_entry));
   5913     }
   5914     mdl_value[0] = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   5915     for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5916         if (SHR_BITGET(mdl_value, bit_pos)) {
   5917             if (bit_pos == h_data_p->level) {
   5918                 offset_found = 1; 
   5919                 break;   
   5920             } else {
   5921                 *ma_offset += 1;
   5922             }
   5923         }
   5924     }
   5925     h_data_p->active_mdl_bitmap = mdl_value[0];
   5926     /* Added the line below to avoid compiler warning - unused variable */  
   5927     mdl_value[0] = *ma_offset;
   5928     if (offset_found == 0) {
   5929         return (BCM_E_INTERNAL);
   5930     }
   5931     return rv;
   5932 }
   5933 
   5934 
   5935 STATIC int
   5936 _bcm_kt2_oam_mp_grp_table_ma_index_offset_get(int unit, 
   5937                                             _bcm_oam_hash_data_t *h_data_p, 
   5938                                             int *ma_offset) 
   5939 {
   5940     int                rv = BCM_E_NONE;
   5941     uint32             mdl_value[1] = { 0 };
   5942     int                bit_pos = 0;
   5943     soc_mem_t          mem = 0;
   5944     l3_entry_1_entry_t l3_entry;      /* L3 entry buffer.                 */
   5945     int                entry_index = 0;
   5946     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   5947     void               *entry;
   5948     soc_field_t        mdl_field = 0;
   5949     int                offset_found = 0;
   5950 
   5951     if (NULL == h_data_p) {
   5952         return (BCM_E_INTERNAL);
   5953     }
   5954     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   5955         mem = EGR_MP_GROUPm;
   5956         mdl_field = MDL_BITMAP_ACTIVEf;
   5957         entry = &egr_mp_group;
   5958         if (BCM_FAILURE(_bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 
   5959                                                    &entry_index, 
   5960                                                    &egr_mp_group))) {
   5961             LOG_ERROR(BSL_LS_BCM_OAM,
   5962                       (BSL_META_U(unit,
   5963                                   "OAM Error: EGR MP group tbl entry not found-%s.\n"),
   5964                        bcm_errmsg(rv)));
   5965             return rv;
   5966         }
   5967     } else {
   5968         mem = L3_ENTRY_IPV4_UNICASTm;
   5969         mdl_field = LMEP__MDL_BITMAP_ACTIVEf;
   5970         entry = &l3_entry;
   5971         if (BCM_FAILURE
   5972             (_bcm_kt2_oam_find_lmep(unit, h_data_p, &entry_index, &l3_entry))) {
   5973 
   5974             LOG_ERROR(BSL_LS_BCM_OAM,
   5975                       (BSL_META_U(unit,
   5976                                   "OAM Error: MP group tbl entry not found - %s.\n"),
   5977                        bcm_errmsg(rv)));
   5978             return rv;
   5979         }
   5980     }
   5981     mdl_value[0] = soc_mem_field32_get(unit, mem, entry, mdl_field);
   5982     for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   5983         if (SHR_BITGET(mdl_value, bit_pos)) {
   5984             if (bit_pos == h_data_p->level) {
   5985                 offset_found = 1; 
   5986                 break;   
   5987             } else {
   5988                 *ma_offset += 1;
   5989             }
   5990         }
   5991     }
   5992     h_data_p->active_mdl_bitmap = mdl_value[0];
   5993     if (offset_found == 0) {
   5994         return (BCM_E_INTERNAL);
   5995     }
   5996     return rv;
   5997 }
   5998 
   5999 
   6000 STATIC int
   6001 _bcm_kt2_oam_ma_index_offset_get(int unit, _bcm_oam_hash_data_t *h_data_p, 
   6002                                  int *ma_offset) 
   6003 {
   6004     int                rv = BCM_E_NONE;
   6005     if (NULL == h_data_p) {
   6006         return (BCM_E_INTERNAL);
   6007     }
   6008 
   6009     /* setting this to 0 is necessary as in the below functions this variable
   6010      * passed as a pointer is just incremented based upon the level.
   6011      * setting it to zero avoids any junk value that might have come in 
   6012      * by the caller function. */
   6013     *ma_offset = 0;
   6014 
   6015     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   6016         rv = _bcm_kt2_oam_port_table_ma_index_offset_get(unit, h_data_p, 
   6017                                                          ma_offset);
   6018         /* BCM_E_NOT_FOUND is not an error when switch is re-initializing
   6019            as entry would have been already deleted by port module init */
   6020         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   6021             LOG_ERROR(BSL_LS_BCM_OAM,
   6022                       (BSL_META_U(unit,
   6023                                   "OAM Error: Port table read failed - %s.\n"),
   6024                        bcm_errmsg(rv)));
   6025             return rv;
   6026         }
   6027     } else {
   6028         rv = _bcm_kt2_oam_mp_grp_table_ma_index_offset_get(unit, h_data_p, 
   6029                                                          ma_offset);
   6030         if (BCM_FAILURE(rv)) {
   6031             LOG_ERROR(BSL_LS_BCM_OAM,
   6032                       (BSL_META_U(unit,
   6033                                   "OAM Error: MP group table read failed - %s.\n"),
   6034                        bcm_errmsg(rv)));
   6035             return rv;
   6036         } 
   6037     }
   6038     return (BCM_E_NONE);
   6039 }
   6040 /*
   6041  * Function:
   6042  *     _bcm_kt2_oam_local_rx_mep_hw_set
   6043  * Purpose:
   6044  *     Configure hardware tables for a local CCM Rx enabled endpoint.
   6045  * Parameters:
   6046  *     unit      - (IN) BCM device number
   6047  *     ep_info_p - (IN) Pointer to remote endpoint information.
   6048  * Retruns:
   6049  *     BCM_E_XXX
   6050  */
   6051 STATIC int
   6052 _bcm_kt2_oam_local_rx_mep_hw_set(int unit,
   6053                              bcm_oam_endpoint_info_t *ep_info_p)
   6054 {
   6055     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   6056     ma_index_entry_t     ma_idx_entry;   /* MA_INDEX table entry buffer.     */
   6057     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/
   6058     oam_opcode_control_profile_entry_t opcode_entry; /* Opcode control 
   6059                                                              profile entry.  */
   6060     egr_oam_opcode_control_profile_entry_t egr_opcode_entry; /* Egress  
   6061                                                  Opcode control profile entry*/
   6062     void                 *entries[1];    /* Pointer to opcode control entry. */
   6063     uint32               profile_index;  /* opcode control profile index.    */
   6064     int                  rv;             /* Operation return status.         */
   6065     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   6066     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   6067     soc_mem_t            opcode_profile_mem = 0;
   6068     soc_mem_t            ma_index_mem = 0;
   6069     shr_idxres_element_t egr_ctr_index = 0;
   6070     soc_profile_mem_t    *opcode_control_profile; /* profile to be used 
   6071                                                         ingress or egress    */
   6072     void                 *ma_idx_ptr;
   6073     void                 *opcode_profile_entry;
   6074 
   6075     if (NULL == ep_info_p) {
   6076         return (BCM_E_INTERNAL);
   6077     }
   6078 
   6079     /* Initialize local endpoint info pointer. */
   6080     ep_p = ep_info_p;
   6081 
   6082     /* Lock already taken by the calling routine. */
   6083     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6084 
   6085     /* Get endpoint hash data pointer. */
   6086     h_data_p = &oc->oam_hash_data[ep_p->id];
   6087     if ( 0 == h_data_p->in_use) {
   6088         return (BCM_E_INTERNAL);
   6089     }
   6090 
   6091     if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   6092         opcode_profile_mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
   6093         opcode_control_profile = &oc->egr_oam_opcode_control_profile;
   6094         ma_index_mem   = EGR_MA_INDEXm;
   6095         ma_idx_ptr = &egr_ma_idx_entry; 
   6096         opcode_profile_entry = &egr_opcode_entry;
   6097         /* Clear the entry data. */
   6098         sal_memset(&egr_opcode_entry, 0, 
   6099                    sizeof(egr_oam_opcode_control_profile_entry_t));
   6100         sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t));
   6101     } else {
   6102         opcode_profile_mem = OAM_OPCODE_CONTROL_PROFILEm;
   6103         opcode_control_profile = &oc->oam_opcode_control_profile;
   6104         ma_index_mem   = MA_INDEXm;
   6105         ma_idx_ptr = &ma_idx_entry;
   6106         opcode_profile_entry = &opcode_entry;
   6107         /* Clear the entry data. */
   6108         sal_memset(&opcode_entry, 0, 
   6109                    sizeof(oam_opcode_control_profile_entry_t));
   6110         sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t));
   6111     }
   6112 
   6113     /* Construct the opcode control profile table entry. */
   6114     if (ep_p->opcode_flags & _BCM_KT2_OAM_OPCODE_MASK) {
   6115         /* Use application specified opcode control settings. */
   6116         rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, h_data_p, 
   6117                                                    opcode_profile_mem,
   6118                                                    ep_p->opcode_flags,
   6119                                                    opcode_profile_entry);
   6120         if (BCM_FAILURE(rv)) {
   6121             LOG_ERROR(BSL_LS_BCM_OAM,
   6122                       (BSL_META_U(unit,
   6123                                   "OAM Error: Opcode profile set failed for EP=%d"
   6124                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6125             return (rv);
   6126         }
   6127     } else {
   6128         /* Use default opcode control profile settings. */
   6129         if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   6130             rv = _bcm_kt2_oam_mip_opcode_profile_entry_init(unit, opcode_profile_mem,
   6131                     opcode_profile_entry);
   6132         } else {
   6133             rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, opcode_profile_mem, 
   6134                     opcode_profile_entry);
   6135         }
   6136         if (BCM_FAILURE(rv)) {
   6137             LOG_ERROR(BSL_LS_BCM_OAM,
   6138                       (BSL_META_U(unit,
   6139                                   "OAM Error: Opcode profile init failed for EP=%d"
   6140                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6141             return (rv);
   6142         }
   6143     }
   6144 
   6145     soc_mem_lock(unit, opcode_profile_mem);
   6146     /* Add entry to profile table.  */
   6147     entries[0] = opcode_profile_entry;
   6148 
   6149     rv = soc_profile_mem_add(unit, opcode_control_profile,
   6150                              (void *)entries, 1, &profile_index);
   6151     if (BCM_FAILURE(rv)) {
   6152         LOG_ERROR(BSL_LS_BCM_OAM,
   6153                   (BSL_META_U(unit,
   6154                               "OAM Error: Opcode profile add failed for EP=%d"
   6155                                "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6156         /* Release opcode control profile table lock. */
   6157         soc_mem_unlock(unit, opcode_profile_mem);
   6158         return (rv);
   6159     }
   6160 
   6161     /* Store endpoint OAM opcode profile table index value. */
   6162     h_data_p->profile_index = profile_index;
   6163 
   6164     /* Release opcode control profile table lock. */
   6165     soc_mem_unlock(unit, opcode_profile_mem);
   6166 
   6167     /*
   6168      * MA_INDEX table programming.
   6169      */
   6170 
   6171 
   6172     /* Set group index value. */
   6173     /* In case of BHH this needs to be the session Index */
   6174 #if defined(INCLUDE_BHH)
   6175     if ( BHH_EP_TYPE(ep_p) ) {
   6176         soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf,
   6177                             BCM_OAM_BHH_GET_UKERNEL_EP(ep_p->id));
   6178     } else 
   6179 #endif
   6180     {
   6181         soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf,
   6182                             ep_p->group);
   6183     }
   6184     
   6185 
   6186 
   6187     /* Set OAM opcode control profile table index. */
   6188     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
   6189                               OAM_OPCODE_CONTROL_PROFILE_PTRf,
   6190                               h_data_p->profile_index);
   6191 
   6192     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
   6193                                   INT_PRIf,
   6194                                   ep_p->int_pri);
   6195 
   6196 
   6197     /* If the OAM domain is port, set source trunk map table */
   6198     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   6199         rv = _bcm_port_domain_oam_hw_set(unit, ep_info_p);
   6200         if (BCM_FAILURE(rv)) {
   6201             LOG_ERROR(BSL_LS_BCM_OAM,
   6202                       (BSL_META_U(unit,
   6203                                   "OAM Error: port OAM config failed for EP=%d"
   6204                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6205             return (rv);
   6206         }
   6207     } else {
   6208         rv = _bcm_kt2_oam_l3_entry_set(unit, ep_info_p);
   6209         if (BCM_FAILURE(rv)) {
   6210             LOG_ERROR(BSL_LS_BCM_OAM,
   6211                       (BSL_META_U(unit,
   6212                                   "OAM Error: L3 entry config failed for EP=%d"
   6213                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6214             return (rv);
   6215         }
   6216         rv = _bcm_kt2_oam_egr_mp_group_entry_set(unit, ep_info_p, 
   6217                                                        &egr_ctr_index);
   6218         if (BCM_FAILURE(rv)) {
   6219             LOG_ERROR(BSL_LS_BCM_OAM,
   6220                       (BSL_META_U(unit,
   6221                                   "OAM Error: Egress MP group entry config "
   6222                                   "failed for EP=%d %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6223             return (rv);
   6224         }
   6225 
   6226         if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   6227             rv = _bcm_kt2_oam_lmep_counters_set(unit, ep_info_p);
   6228             if (BCM_FAILURE(rv)) {
   6229                 LOG_ERROR(BSL_LS_BCM_OAM,
   6230                           (BSL_META_U(unit,
   6231                                       "OAM Error: Counter config failed for EP=%d"
   6232                                        "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6233                 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
   6234                     rv =  shr_aidxres_list_free(oc->ing_lm_ctr_pool[
   6235                                                   (h_data_p->rx_ctr >> 24)],
   6236                                                   (h_data_p->rx_ctr & 0xffffff));
   6237                     if (BCM_FAILURE(rv)) {
   6238                         LOG_ERROR(BSL_LS_BCM_OAM,
   6239                                   (BSL_META_U(unit,
   6240                                               "OAM Error: Ing LM counter block "
   6241                                               "free failed (EP=%d) - %s.\n"),
   6242                                    ep_info_p->id, bcm_errmsg(rv)));
   6243                         return (rv);
   6244                     }
   6245                 }
   6246                 return (rv);
   6247             }
   6248         }
   6249     }
   6250     rv = _bcm_kt2_oam_ma_index_entry_set(unit, h_data_p, 
   6251                                          ma_index_mem, ma_idx_ptr, 0);
   6252     if (BCM_FAILURE(rv)) {
   6253         LOG_ERROR(BSL_LS_BCM_OAM,
   6254                   (BSL_META_U(unit,
   6255                               "OAM Error: MA_INDEX table write failed for EP=%d"
   6256                                "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6257         return (rv);
   6258     }
   6259     return rv;
   6260 }
   6261 
   6262 /*
   6263  * Function:
   6264  *     _bcm_kt2_oam_upmep_rx_endpoint_reserve
   6265  * Purpose:
   6266  *     Reserve an hardware index in the group state table to maintain the state
   6267  *     for a CCM Rx enabled endpoint.
   6268  * Parameters:
   6269  *     unit      - (IN) BCM device number
   6270  *     ep_info_p - (IN) Pointer to remote endpoint information.
   6271  * Retruns:
   6272  *     BCM_E_XXX
   6273  */
   6274 STATIC int
   6275 _bcm_kt2_oam_upmep_rx_endpoint_reserve(int unit,  
   6276                              const bcm_oam_endpoint_info_t *ep_info_p)
   6277 {
   6278     _bcm_oam_hash_data_t   *h_data_p;     /* Endpoint hash data pointer.      */
   6279     int                    rv;            /* Operation return status.         */
   6280     egr_mp_group_entry_t   egr_mp_grp_entry; /* egress mp group entry buffer. */
   6281     int                    mp_group_index = -1;/*MP group entry hardware index*/
   6282     int                    count = 0;     /* Successful Hw indices allocated. */
   6283     uint8                  mdl = 0;       /* Maintenance domain level.        */
   6284     int                    rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   6285                                           /* Endpoint Rx hardware index.      */
   6286     uint16                 ma_base_idx;   /* Base pointer to endpoint state   */
   6287                                           /* table [MA_INDEX = (BASE + MDL)]. */
   6288     _bcm_oam_control_t     *oc;           /* Pointer to control structure.    */
   6289     const bcm_oam_endpoint_info_t *ep_p;  /* Pointer to endpoint information. */
   6290 
   6291     if (NULL == ep_info_p) {
   6292         return (BCM_E_INTERNAL);
   6293     }
   6294 
   6295     /* Lock already taken by the calling routine. */
   6296     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6297 
   6298     /* Initialize local endpoint information pointer. */
   6299     ep_p = ep_info_p;
   6300 
   6301     /* Get endpoint hash data pointer. */
   6302     h_data_p = &oc->oam_hash_data[ep_p->id];
   6303     if (0 == h_data_p->in_use) {
   6304         return(BCM_E_INTERNAL);
   6305     }
   6306 
   6307     /* Initialize egress MP group table entry buffer. */
   6308     sal_memset(&egr_mp_grp_entry, 0, sizeof(egr_mp_group_entry_t));
   6309 
   6310     /* Find out if a matching entry already installed in hardware table. */
   6311     rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, &mp_group_index, 
   6312                                                         &egr_mp_grp_entry);
   6313     if (BCM_FAILURE(rv)) {
   6314         /*
   6315          * If NO match found, allocate a new hardware index from EGR_MA_INDEX
   6316          * pool.
   6317          */
   6318 
   6319         /*
   6320          * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   6321          * group endpoints. While allocating the base index, next 7 hardware
   6322          * indices are also reserved.
   6323          */
   6324         rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8,
   6325                                        (shr_idxres_element_t *) rx_index,
   6326                                        (shr_idxres_element_t *) &count);
   6327         if (BCM_FAILURE(rv)) {
   6328             LOG_ERROR(BSL_LS_BCM_OAM,
   6329                       (BSL_META_U(unit,
   6330                                   "OAM Error: EGR MA_INDEX index alloc failed EP:%d"
   6331                                    " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6332             return (rv);
   6333         } else {
   6334             LOG_DEBUG(BSL_LS_BCM_OAM,
   6335                       (BSL_META_U(unit,
   6336                                   "OAM Info: Egr MA_INDEX alloc for EP:%d success"
   6337                                    " rx_idx_base:%d alloc-count:%d.\n"), ep_p->id,
   6338                        rx_index[0], count));
   6339             h_data_p->ma_base_index = rx_index[0];
   6340         }
   6341 
   6342     } else if (BCM_SUCCESS(rv)) {
   6343 
   6344         /* Matching entry found, get installed entry MDL value. */
   6345         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, 
   6346                                                        MDL_BITMAP_ACTIVEf);
   6347 
   6348         if (mdl == 0) {
   6349             /* This is the first one in the active bitmap.
   6350                Allocate the hw indexes. */
   6351             /*
   6352              * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   6353              * group endpoints. While allocating the base index, next 7 hardware
   6354              * indices are also reserved.
   6355              */
   6356             rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8,
   6357                     (shr_idxres_element_t *) rx_index,
   6358                     (shr_idxres_element_t *) &count);
   6359             if (BCM_FAILURE(rv)) {
   6360                 LOG_ERROR(BSL_LS_BCM_OAM,
   6361                         (BSL_META_U(unit,
   6362                                     "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d"
   6363                                     " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   6364                 return (rv);
   6365             } else {
   6366                 LOG_DEBUG(BSL_LS_BCM_OAM,
   6367                         (BSL_META_U(unit,
   6368                                     "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success"
   6369                                     " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   6370                          rx_index[0], count));
   6371                 h_data_p->ma_base_index = rx_index[0];
   6372             }
   6373         } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */
   6374             ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry,
   6375                                                       MA_BASE_PTRf);
   6376             h_data_p->ma_base_index = ma_base_idx;
   6377         } else {
   6378             /* Rx index already taken return error. */
   6379             LOG_ERROR(BSL_LS_BCM_OAM,
   6380                       (BSL_META_U(unit,
   6381                                   "OAM Error: No free Rx index found for EP:%d"
   6382                                    " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6383             return (BCM_E_RESOURCE);
   6384         }
   6385     }
   6386     return (rv);
   6387 }
   6388 
   6389 /*
   6390  * Function:
   6391  *     _bcm_kt2_oam_downmep_rx_endpoint_reserve
   6392  * Purpose:
   6393  *     Reserve an hardware index in the group state table to maintain the state
   6394  *     for a CCM Rx enabled endpoint.
   6395  * Parameters:
   6396  *     unit      - (IN) BCM device number
   6397  *     ep_info_p - (IN) Pointer to remote endpoint information.
   6398  * Retruns:
   6399  *     BCM_E_XXX
   6400  */
   6401 STATIC int
   6402 _bcm_kt2_oam_downmep_rx_endpoint_reserve(int unit, 
   6403                                 const bcm_oam_endpoint_info_t *ep_info_p)
   6404 {
   6405     _bcm_oam_hash_data_t   *h_data_p;     /* Endpoint hash data pointer.      */
   6406     int                    rv;            /* Operation return status.         */
   6407     l3_entry_1_entry_t     l3_entry;      /* L3 entry buffer.                 */
   6408     int                    l3_index = -1; /* L3 entry hardware index.         */
   6409     int                    count = 0;     /* Successful Hw indices allocated. */
   6410     uint8                  mdl = 0;       /* Maintenance domain level.        */
   6411     int                    rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   6412                                           /* Endpoint Rx hardware index.      */
   6413     uint16                 ma_base_idx;   /* Base pointer to endpoint state   */
   6414                                           /* table [MA_INDEX = (BASE + MDL)]. */
   6415     _bcm_oam_control_t     *oc;           /* Pointer to control structure.    */
   6416     const bcm_oam_endpoint_info_t *ep_p;  /* Pointer to endpoint information. */
   6417     int                     stm_index = 0;
   6418     source_trunk_map_table_entry_t stm_entry;
   6419     int                    ma_idx_entry_count = 0;
   6420     shr_idxres_list_handle_t pool = NULL;
   6421 
   6422 
   6423     if (NULL == ep_info_p) {
   6424         return (BCM_E_INTERNAL);
   6425     }
   6426 
   6427     /* Lock already taken by the calling routine. */
   6428     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6429 
   6430     /* Initialize local endpoint information pointer. */
   6431     ep_p = ep_info_p;
   6432 
   6433     /* Get endpoint hash data pointer. */
   6434     h_data_p = &oc->oam_hash_data[ep_p->id];
   6435     if ( 0 == h_data_p->in_use) {
   6436         return (BCM_E_INTERNAL);
   6437     }
   6438     
   6439     /* Initialize L3 entry buffer. */
   6440     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   6441     sal_memset(&stm_entry, 0, sizeof(source_trunk_map_table_entry_t));
   6442 
   6443     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   6444         rv = _bcm_kt2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &mdl);
   6445     } else {
   6446         /* Find out if a matching entry already installed in hardware table. */
   6447         rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry);
   6448     }
   6449     if (BCM_FAILURE(rv)) {
   6450         /*
   6451          * If NO match found, allocate a new hardware index from MA_INDEX
   6452          * pool.
   6453          */
   6454 
   6455         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   6456                     &ma_idx_entry_count, &pool));
   6457         /*
   6458          * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   6459          * group endpoints. While allocating the base index, next 7 hardware
   6460          * indices are also reserved.
   6461          */
   6462         rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count,
   6463                            (shr_idxres_element_t *) rx_index,
   6464                            (shr_idxres_element_t *) &count);
   6465 
   6466         if (BCM_FAILURE(rv)) {
   6467             LOG_ERROR(BSL_LS_BCM_OAM,
   6468                       (BSL_META_U(unit,
   6469                                   "OAM Error: MA_INDEX index alloc failed EP:%d"
   6470                                    " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6471             return (rv);
   6472         } else {
   6473             LOG_DEBUG(BSL_LS_BCM_OAM,
   6474                       (BSL_META_U(unit,
   6475                                   "OAM Info: MA_INDEX alloc for EP:%d success."
   6476                                    " rx_idx_base:%d alloc-count:%d.\n"), ep_p->id,
   6477                        rx_index[0], count));
   6478         }
   6479 
   6480         h_data_p->ma_base_index = rx_index[0];
   6481     } else if (BCM_SUCCESS(rv)) {
   6482         if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   6483             /* MDL already found.*/
   6484             /* Findout if MDLs are same. */
   6485             if (0 == (mdl & (1 << ep_p->level))) {
   6486                 ma_base_idx =
   6487                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry,
   6488                             MA_BASE_PTRf);
   6489                 h_data_p->ma_base_index = ma_base_idx;
   6490             } else {
   6491                 /* Rx index already taken return error. */
   6492                 LOG_ERROR(BSL_LS_BCM_OAM,
   6493                         (BSL_META_U(unit,
   6494                                     "OAM Error: No free Rx index found for EP:%d"
   6495                                     " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6496                 return (BCM_E_RESOURCE);
   6497             }
   6498         } else {
   6499             /* Matching entry found, get installed entry MDL value. */
   6500             mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   6501                     LMEP__MDL_BITMAP_ACTIVEf);
   6502 
   6503             if (mdl == 0) {
   6504                 /* This is the first one in the active bitmap.
   6505                    Allocate the hw indexes. */
   6506                 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   6507                             &ma_idx_entry_count, &pool));
   6508                 /*
   6509                  * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   6510                  * group endpoints. While allocating the base index, next 7 hardware
   6511                  * indices are also reserved.
   6512                  */
   6513                 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count,
   6514                         (shr_idxres_element_t *) rx_index,
   6515                         (shr_idxres_element_t *) &count);
   6516 
   6517                 if (BCM_FAILURE(rv)) {
   6518                     LOG_ERROR(BSL_LS_BCM_OAM,
   6519                             (BSL_META_U(unit,
   6520                                         "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d"
   6521                                         " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   6522                     return (rv);
   6523                 } else {
   6524                     LOG_DEBUG(BSL_LS_BCM_OAM,
   6525                             (BSL_META_U(unit,
   6526                                         "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success."
   6527                                         " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   6528                              rx_index[0], count));
   6529                 }
   6530 
   6531                 h_data_p->ma_base_index = rx_index[0];
   6532             } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */
   6533                 ma_base_idx = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   6534                         LMEP__MA_BASE_PTRf);
   6535                 h_data_p->ma_base_index = ma_base_idx;
   6536             } else {
   6537                 /* Rx index already taken return error. */
   6538                 LOG_ERROR(BSL_LS_BCM_OAM,
   6539                         (BSL_META_U(unit,
   6540                                     "OAM Error: No free Rx index found for EP:%d"
   6541                                     " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   6542                 return (BCM_E_RESOURCE);
   6543             }
   6544         }
   6545     }
   6546 
   6547     return (rv);
   6548 }
   6549 
   6550 /*
   6551  * Function:
   6552  *     _bcm_kt2_oam_remote_endpoint_delete
   6553  * Purpose:
   6554  *     Delete a remote endpoint.
   6555  * Parameters:
   6556  *     unit      - (IN) BCM device number
   6557  *     h_data_p  - (IN) Pointer to endpoint hash data
   6558  * Retruns:
   6559  *     BCM_E_XXX
   6560  */
   6561 STATIC int
   6562 _bcm_kt2_oam_remote_endpoint_delete(int unit,
   6563                                     _bcm_oam_hash_data_t *h_data_p)
   6564 {
   6565     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure.  */
   6566     l3_entry_1_entry_t l3_entry;       /* RMEP view table entry.             */
   6567     ma_state_entry_t   ma_state_entry; /* Group state machine table entry.   */
   6568     rmep_entry_t       rmep_entry;     /* Remote endpoint table entry.       */
   6569     int                rv;             /* Operation return status.           */
   6570     uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM  */
   6571                                          /* defects.                         */
   6572     uint32 some_rdi_defect_counter = 0;  /* No. of RMEPs in MA with RDI      */
   6573                                          /* defects.                         */
   6574     uint32 cur_some_rdi_defect = 0;      /* Any RMEP in MA with RDI defect.  */
   6575     uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect.  */
   6576     uint32 cur_rmep_ccm_defect = 0;      /* RMEP lookup failed or CCM        */
   6577                                          /* interval mismatch.               */
   6578     uint32 cur_rmep_last_rdi = 0;        /* Last CCM RDI Rx from this RMEP.  */
   6579     uint32 first, last, validLow, validHigh, freeCount, allocCount;
   6580 
   6581     /* Lock already taken by the calling routine. */
   6582     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6583 
   6584     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   6585 
   6586     /* Get remote endpoint entry value from hardware. */
   6587     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
   6588     if (BCM_FAILURE(rv)) {
   6589         LOG_ERROR(BSL_LS_BCM_OAM,
   6590                   (BSL_META_U(unit,
   6591                               "OAM Error: RMEP table read failed for EP=%d"
   6592                                "%s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   6593         return (rv);
   6594     }
   6595 
   6596     cur_rmep_ccm_defect
   6597         = soc_RMEPm_field32_get(unit, &rmep_entry,
   6598                                 CURRENT_RMEP_CCM_DEFECTf);
   6599 
   6600     cur_rmep_last_rdi
   6601         = soc_RMEPm_field32_get(unit, &rmep_entry,
   6602                                 CURRENT_RMEP_LAST_RDIf);
   6603 
   6604     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry));
   6605     rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index,
   6606                         &ma_state_entry);
   6607     if (BCM_FAILURE(rv)) {
   6608         LOG_ERROR(BSL_LS_BCM_OAM,
   6609                   (BSL_META_U(unit,
   6610                               "OAM Error: Group state (GID=%d) table read"
   6611                                " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   6612         return (rv);
   6613     }
   6614 
   6615     if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) {
   6616         some_rmep_ccm_defect_counter
   6617             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   6618                                         SOME_RMEP_CCM_DEFECT_COUNTERf);
   6619         cur_some_rmep_ccm_defect
   6620             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   6621                                         CURRENT_SOME_RMEP_CCM_DEFECTf);
   6622 
   6623         if ((0 != cur_rmep_ccm_defect)
   6624             && (some_rmep_ccm_defect_counter > 0)) {
   6625             --some_rmep_ccm_defect_counter;
   6626             soc_MA_STATEm_field32_set
   6627                 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf,
   6628                  some_rmep_ccm_defect_counter);
   6629 
   6630             if (0 == some_rmep_ccm_defect_counter) {
   6631                 cur_some_rmep_ccm_defect = 0;
   6632                 soc_MA_STATEm_field32_set
   6633                     (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf,
   6634                      cur_some_rmep_ccm_defect);
   6635             }
   6636         }
   6637 
   6638         some_rdi_defect_counter
   6639             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   6640                                         SOME_RDI_DEFECT_COUNTERf);
   6641         cur_some_rdi_defect
   6642             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   6643                                         CURRENT_SOME_RDI_DEFECTf);
   6644 
   6645         if ((0 != cur_rmep_last_rdi)
   6646             && (some_rdi_defect_counter > 0)) {
   6647             --some_rdi_defect_counter;
   6648             soc_MA_STATEm_field32_set
   6649                 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf,
   6650                  some_rdi_defect_counter);
   6651 
   6652             if (0 == some_rdi_defect_counter) {
   6653                 cur_some_rdi_defect = 0;
   6654                 soc_MA_STATEm_field32_set
   6655                     (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf,
   6656                      cur_some_rdi_defect);
   6657             }
   6658         }
   6659 
   6660         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   6661                              &ma_state_entry);
   6662         if (BCM_FAILURE(rv)) {
   6663             LOG_ERROR(BSL_LS_BCM_OAM,
   6664                       (BSL_META_U(unit,
   6665                                   "OAM Error: Group state (GID=%d) table write"
   6666                                    " failed - %s.\n"), h_data_p->group_index,
   6667                        bcm_errmsg(rv)));
   6668             return (rv);
   6669         }
   6670     }
   6671 
   6672     /* Clear RMEP table entry for this endpoint index. */
   6673     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   6674     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   6675                      &rmep_entry);
   6676     if (BCM_FAILURE(rv)) {
   6677         LOG_ERROR(BSL_LS_BCM_OAM,
   6678                   (BSL_META_U(unit,
   6679                               "OAM Error: RMEP table write index=%x (EP=%d)"
   6680                                " - %s.\n"), h_data_p->remote_index,
   6681                    h_data_p->ep_id, bcm_errmsg(rv)));
   6682         return (rv);
   6683     }
   6684 
   6685     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   6686 
   6687     /* Construct endpoint RMEP view key for L3 Table entry delete operation. */
   6688     _bcm_kt2_oam_rmep_key_construct(unit, h_data_p, &l3_entry);
   6689 
   6690     rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry);
   6691     if (BCM_FAILURE(rv) && (oc->init)) {
   6692         LOG_ERROR(BSL_LS_BCM_OAM,
   6693                   (BSL_META_U(unit,
   6694                               "OAM Error: RMEP view update (EP=%d)"
   6695                                " - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   6696         return (rv);
   6697     }
   6698 
   6699     /* Return ID back to free RMEP ID pool. */
   6700     BCM_IF_ERROR_RETURN
   6701         (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index));
   6702 
   6703     rv = shr_idxres_list_state(oc->rmep_pool,
   6704                                    &first, &last,
   6705                                    &validLow, &validHigh,
   6706                                    &freeCount, &allocCount);
   6707     if (BCM_FAILURE(rv)) {
   6708         LOG_ERROR(BSL_LS_BCM_OAM,
   6709                   (BSL_META_U(unit,
   6710                               "OAM Error: RMEP pool state get failed "
   6711                                " - %s.\n"), bcm_errmsg(rv)));
   6712         return (rv);
   6713     }
   6714 
   6715     if(allocCount == 0)
   6716     {
   6717         soc_MA_STATEm_field32_set
   6718             (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf,
   6719              0);
   6720         soc_MA_STATEm_field32_set
   6721             (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf,
   6722              0);
   6723         soc_MA_STATEm_field32_set
   6724             (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf,
   6725              0);
   6726         soc_MA_STATEm_field32_set
   6727             (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf,
   6728              0);
   6729         soc_MA_STATEm_field32_set
   6730             (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf,
   6731              0);
   6732         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   6733                 &ma_state_entry);
   6734         if (BCM_FAILURE(rv)) {
   6735             LOG_ERROR(BSL_LS_BCM_OAM,
   6736                     (BSL_META_U(unit,
   6737                                 "OAM Error: Group state (GID=%d) table write"
   6738                                 " failed - %s.\n"), h_data_p->group_index,
   6739                      bcm_errmsg(rv)));
   6740             return (rv);
   6741         }
   6742     }
   6743 
   6744     /* Clear the H/w index to logical index Mapping for RMEP */
   6745     oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 
   6746 
   6747 
   6748     return (BCM_E_NONE);
   6749 }
   6750 
   6751 /*
   6752  * Function:
   6753  *     _bcm_kt2_oam_clear_counter
   6754  * Purpose:
   6755  *    Remove the counter associated with the endpoint being deleted 
   6756  * Parameters:
   6757  *     unit      - (IN) BCM device number
   6758  *     mem       - (IN) L3_ENTRY_IPV4_UNICAST/EGR_MP_GROUP
   6759  *     index     - (IN) Index of the table entry to be modified
   6760  *     h_data_p  - (IN) Pointer to endpoint hash data
   6761  *     entry     - (IN) pointer to table entry
   6762  * Retruns:
   6763  *     BCM_E_XXX
   6764  */
   6765 STATIC int
   6766 _bcm_kt2_oam_clear_counter(int unit, soc_mem_t mem,
   6767                            int index,
   6768                            _bcm_oam_hash_data_t *h_data_p, 
   6769                            void *entry)
   6770 {
   6771     int  rv = BCM_E_NONE;
   6772     mep_ctr_info_t  *ctr_info;
   6773     int           ctr_type = 0;
   6774     int           ctr1_valid = 0;
   6775     int           ctr2_valid = 0;
   6776     int           ctr_mdl = 0;
   6777     int           up_mep = 0;
   6778 
   6779     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   6780         up_mep = 1;
   6781     }
   6782     if (mem == L3_ENTRY_IPV4_UNICASTm) {
   6783         ctr_info = mep_ctr_info;
   6784     } else {
   6785         ctr_info = egr_mep_ctr_info;
   6786     }
   6787     ctr1_valid = soc_mem_field32_get(unit, mem, 
   6788                                     (uint32 *)entry, ctr_info[0].ctr_valid);
   6789     if (ctr1_valid) {
   6790         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   6791                                                  ctr_info[0].ctr_mep_type); 
   6792         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   6793                                                  ctr_info[0].ctr_mep_mdl); 
   6794         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
   6795             ctr1_valid = 0;
   6796             rv = soc_mem_field32_modify(unit, mem, index,
   6797                                                      ctr_info[0].ctr_valid, 0);
   6798         }
   6799     }   
   6800     ctr2_valid = soc_mem_field32_get(unit, mem, 
   6801                                     (uint32 *)entry, ctr_info[1].ctr_valid);
   6802     if (ctr2_valid) {
   6803         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   6804                                                  ctr_info[1].ctr_mep_type); 
   6805         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   6806                                                  ctr_info[1].ctr_mep_mdl); 
   6807         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
   6808             rv = soc_mem_field32_modify(unit, mem, index,
   6809                                                      ctr_info[1].ctr_valid, 0);
   6810             ctr2_valid = 0;
   6811         }
   6812     }
   6813 
   6814     /* return rx & tx counters allocated if any */
   6815     rv =_bcm_kt2_oam_free_counter(unit, h_data_p);
   6816     if (BCM_FAILURE(rv)) {
   6817         LOG_ERROR(BSL_LS_BCM_OAM,
   6818                 (BSL_META_U(unit,
   6819                             "OAM Error: LM counter block "
   6820                             "free failed (EP=%d) - %s.\n"),
   6821                  h_data_p->ep_id, bcm_errmsg(rv)));
   6822         return (rv);
   6823     }
   6824     return rv;
   6825 }
   6826 
   6827 /*
   6828  * Function:
   6829  *     _bcm_kt2_oam_stm_table_clear
   6830  * Purpose:
   6831  *     Clear MA base ptr and return MA index to the pool
   6832  * Parameters:
   6833  *     unit      - (IN) BCM device number
   6834  *     mod_id    - (IN) Module Id
   6835  *     index     - (IN) stm member index
   6836  *     port_id   - (IN) port number
   6837  *     h_data_p - (IN) Pointer to hash data 
   6838  * Retruns:
   6839  *     BCM_E_XXX
   6840  */
   6841 STATIC int
   6842 _bcm_kt2_oam_stm_table_clear(int unit, bcm_module_t mod_id, int index,
   6843                               bcm_port_t port_id, 
   6844                               _bcm_oam_hash_data_t *h_data_p)
   6845 {
   6846     int                  rv = BCM_E_NONE;/* Operation return status.        */
   6847     int                  stm_index = 0;
   6848     source_trunk_map_table_entry_t stm_entry;
   6849     uint16               ma_base_idx;   /* Base pointer to endpoint state   */
   6850                                         /* table [MA_INDEX = (BASE + MDL)]. */
   6851     int                  idx = 0;    
   6852     _bcm_oam_control_t   *oc;           /* Pointer to control structure.    */
   6853     int                  count = 0;
   6854     int                  ma_idx_entry_count = 0;
   6855     shr_idxres_list_handle_t pool = NULL;
   6856 
   6857     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   6858 
   6859     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6860 
   6861     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6862 
   6863     rv = _bcm_esw_src_mod_port_table_index_get(unit,
   6864                                         mod_id, port_id, &stm_index);
   6865     if(BCM_FAILURE(rv)) {
   6866         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6867         return rv;
   6868     }
   6869 
   6870     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   6871                                                    stm_index, &stm_entry);
   6872 
   6873     if(BCM_FAILURE(rv)) {
   6874         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6875         return rv;
   6876     }
   6877 
   6878     ma_base_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 
   6879                                                  &stm_entry, MA_BASE_PTRf);
   6880     if (index == 0) {
   6881         /* Return Rx indices to free pool. */
   6882         for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   6883             rx_index[idx] = ma_base_idx + idx;
   6884         }
   6885 
   6886         rv = _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   6887                     &ma_idx_entry_count, &pool);
   6888         if(BCM_FAILURE(rv)) {
   6889             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6890             return rv;
   6891         }
   6892 
   6893         rv = shr_idxres_list_free_set(pool, ma_idx_entry_count,
   6894                                      (shr_idxres_element_t *) rx_index,
   6895                                      (shr_idxres_element_t *) &count);
   6896         if (BCM_FAILURE(rv) || (8 != count)) {
   6897             LOG_ERROR(BSL_LS_BCM_OAM,
   6898                       (BSL_META_U(unit,
   6899                                   "OAM Error: Rx index list free (EP=%d)"
   6900                                    " (count=%d).\n"), h_data_p->ep_id, count));
   6901             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6902             return (rv);
   6903         }
   6904     }
   6905 
   6906     /* Set MA_BASE_PTR to 0 */
   6907     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 0);
   6908 
   6909     rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index,
   6910                                                                 &stm_entry);
   6911     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   6912     return rv;
   6913 }
   6914 
   6915 /*
   6916  * Function:
   6917  *     _bcm_kt2_oam_trunk_port_mdl_update
   6918  * Purpose:
   6919  *     Modify port, egr port and stm table entry
   6920  * Parameters:
   6921  *     unit      - (IN) BCM device number
   6922  *     h_data_p - (IN) Pointer to hash data 
   6923  * Retruns:
   6924  *     BCM_E_XXX
   6925  */
   6926 STATIC int
   6927 _bcm_kt2_oam_trunk_port_mdl_update(int unit,
   6928                           _bcm_oam_hash_data_t *h_data_p)
   6929 {
   6930     int                  rv = BCM_E_NONE;      /* Operation return status.    */
   6931     _bcm_oam_control_t   *oc;                  /* Pointer to control structure*/
   6932     int                  member_count = 0;
   6933     bcm_port_t           *member_array = NULL; /* Trunk member port array.    */
   6934     int                  local_member_count = 0;
   6935     int                  i = 0;
   6936     bcm_port_t           pp_port = 0;
   6937     bcm_module_t         module_id;           /* Module ID                   */
   6938     uint8                mdl = 0;
   6939 
   6940     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   6941 
   6942     if(h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   6943         return BCM_E_PARAM;
   6944     }
   6945 
   6946     /* Get all the local member ports belonging to this trunk */
   6947     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   6948                                NULL, 0, NULL, &member_count));
   6949     if (0 == member_count) {
   6950         /* No members have been added to the trunk group yet */
   6951         LOG_ERROR(BSL_LS_BCM_OAM,
   6952                   (BSL_META_U(unit,
   6953                               "OAM Error: No local members have been added to "
   6954                               "the trunk group yet - %s.\n"), bcm_errmsg(rv)));
   6955         return BCM_E_PARAM;
   6956     }
   6957 
   6958     _BCM_OAM_ALLOC(member_array, bcm_port_t,
   6959                        sizeof(bcm_port_t) * member_count, "Trunk info");
   6960     if (NULL == member_array) {
   6961         return (BCM_E_MEMORY);
   6962     }
   6963 
   6964     /* Get members of the trunk belonging to this module */
   6965     if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   6966                                                      h_data_p->trunk_id, 
   6967                                                      member_count, member_array,
   6968                                                      &local_member_count))) {
   6969         if (local_member_count > 0) {
   6970             for(i = 0; i < local_member_count; i++) {
   6971                 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   6972                                                   &module_id, &pp_port);
   6973                 if (BCM_FAILURE(rv)) {
   6974                     sal_free(member_array);
   6975                     return (rv);
   6976                 }
   6977                 rv =_bcm_kt2_oam_port_mdl_update(unit, pp_port, 1, 
   6978                                                  h_data_p, &mdl); 
   6979                 if (BCM_FAILURE(rv)) {
   6980                     sal_free(member_array);
   6981                     return (rv);
   6982                 }
   6983             } 
   6984             if (mdl == 0) { 
   6985                 for(i = 0; i < local_member_count; i++) {
   6986                     rv = _bcm_kt2_oam_stm_table_clear(unit, module_id, i,
   6987                                                member_array[i], h_data_p);
   6988                     if (BCM_FAILURE(rv)) {
   6989                         sal_free(member_array);
   6990                         return (rv);
   6991                     }
   6992                 }
   6993             }
   6994             rv = _bcm_kt2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl); 
   6995             if (BCM_FAILURE(rv)) {
   6996                 sal_free(member_array);
   6997                 return (rv);
   6998             }
   6999 
   7000         }
   7001     }
   7002     sal_free(member_array);
   7003     return BCM_E_NONE;
   7004 }
   7005 /*
   7006  * Function:
   7007  *     _bcm_port_domain_mdl_bitmap_update
   7008  * Purpose:
   7009  *     Update Port table MDL bitmap and STM table MA_BASE_PTR. 
   7010  * Parameters:
   7011  *     unit      - (IN) BCM device number
   7012  *     h_data_p  - (IN) Pointer to endpoint hash data
   7013  * Retruns:
   7014  *     BCM_E_XXX
   7015  */
   7016 STATIC int
   7017 _bcm_port_domain_mdl_bitmap_update(int unit, _bcm_oam_hash_data_t *h_data_p)
   7018 {
   7019     int                  rv = BCM_E_NONE;/* Operation return status.         */
   7020     uint8                mdl;            /* Maintenance domain level.        */
   7021     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7022     bcm_module_t         mod_id = 0;
   7023     bcm_port_t           port_id = 0;
   7024 
   7025     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7026 
   7027    /* If the OAM domain is port */
   7028     if (_BCM_OAM_DOMAIN_PORT != h_data_p->oam_domain) {
   7029         return (BCM_E_INTERNAL);
   7030     }
   7031 
   7032     if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   7033         rv = _bcm_kt2_oam_trunk_port_mdl_update(unit, h_data_p);
   7034     } else {
   7035         port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   7036         mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   7037         BCM_IF_ERROR_RETURN
   7038                 (_bcm_kt2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 
   7039                                              1, h_data_p, &mdl)); 
   7040         BCM_IF_ERROR_RETURN
   7041                 (_bcm_kt2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl)); 
   7042         if (mdl == 0) {
   7043             BCM_IF_ERROR_RETURN
   7044                 (_bcm_kt2_oam_stm_table_clear(unit, mod_id, 0,
   7045                                                port_id, h_data_p));
   7046         }
   7047     }
   7048     return (rv);
   7049 }
   7050 
   7051 /*
   7052  * Function:
   7053  *     _bcm_kt2_oam_l3_entry_destroy
   7054  * Purpose:
   7055  *     Update Ingress MP group table(L3 Entry- LMEP view)entry.
   7056  * Parameters:
   7057  *     unit      - (IN) BCM device number
   7058  *     h_data_p  - (IN) Pointer to endpoint hash data
   7059  *     active_mdl -(IN) Active MDL bitmap value
   7060  * Retruns:
   7061  *     BCM_E_XXX
   7062  */
   7063 STATIC int
   7064 _bcm_kt2_oam_l3_entry_destroy(int unit, _bcm_oam_hash_data_t *h_data_p, 
   7065                               uint8 *active_mdl)
   7066 {
   7067     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   7068     l3_entry_1_entry_t l3_entry;       /* LMEP view table entry.            */
   7069     int                l3_index = -1;  /* L3 table hardware index.          */
   7070     int                rv;             /* Operation return status.          */
   7071     uint8              mdl;            /* Maintenance domain level.         */
   7072     uint8              other_mdl = 0;  /* Maintenance domain level.         */
   7073     uint32             ma_base_index;  /* Endpoint tbl base index. */
   7074     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   7075                                        /* Endpoint Rx hardware index.       */
   7076     uint32 count;                      /* No. of Rx indices freed           */
   7077                                        /* successfully.                     */
   7078     int                idx;            /* Iterator variable.                */
   7079     soc_field_t        mdl_field = 0;
   7080     soc_field_t        other_mdl_field = 0;
   7081     int                upmep = 0;
   7082     int                ma_idx_entry_count = 0;
   7083     shr_idxres_list_handle_t pool = NULL;
   7084 
   7085     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7086     /* Check whether up/down MEP */
   7087     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7088         mdl_field = LMEP__MDL_BITMAP_PASSIVEf;
   7089         other_mdl_field = LMEP__MDL_BITMAP_ACTIVEf;
   7090         upmep = 1;
   7091     } else {
   7092         mdl_field = LMEP__MDL_BITMAP_ACTIVEf;
   7093         other_mdl_field = LMEP__MDL_BITMAP_PASSIVEf;
   7094     }
   7095     rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry);
   7096     if (BCM_SUCCESS(rv)) {
   7097         /* Endpoint found, get MDL bitmap value. */
   7098         mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   7099                                                      mdl_field);
   7100 
   7101         /* Passive demultiplexing should not be done on a MIP.
   7102          * Hence do not touch PASSIVE bitmap when destroying
   7103          * also. 
   7104          */
   7105         if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) &&
   7106              (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7107             /* Clear the MDL bit for this endpoint. */
   7108             mdl &= ~(1 << h_data_p->level);
   7109 
   7110             if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7111                 /* Passive MDL bitmap */
   7112                 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 
   7113                                                 h_data_p->ma_base_index, &mdl, 1);
   7114             } else {
   7115                 *active_mdl = mdl;
   7116             }
   7117         }
   7118         /* Take L3 module protection mutex to block any updates. */
   7119         L3_LOCK(unit);
   7120         if (0 != mdl) {
   7121             /* Valid endpoints exist for other MDLs at this index. */
   7122             rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, l3_index,
   7123                                                      mdl_field, mdl);
   7124             if (BCM_FAILURE(rv)) {
   7125                 LOG_ERROR(BSL_LS_BCM_OAM,
   7126                           (BSL_META_U(unit,
   7127                                       "OAM Error:L3 entry LMEP view update(EP=%d) -"
   7128                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7129                 L3_UNLOCK(unit);
   7130                 return (rv);
   7131             }
   7132             /* Clear the counter, if any */
   7133             rv = _bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm, 
   7134                                             l3_index, h_data_p, 
   7135                                             (void *)&l3_entry); 
   7136             if (BCM_FAILURE(rv)) {
   7137                 /* coverity[copy_paste_error] */
   7138                 LOG_ERROR(BSL_LS_BCM_OAM,
   7139                           (BSL_META_U(unit,
   7140                                       "OAM Error: Clear counter failed (EP=%d) -"
   7141                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7142                 L3_UNLOCK(unit);
   7143                 return (rv);
   7144             }
   7145 
   7146         } else {
   7147             /* check if other MDL bitmap is also zero (passive bitmap incase 
   7148                of downmep and active bitmap in case of upmep), if so delete the
   7149                entry completely */
   7150             other_mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   7151                                                      other_mdl_field);
   7152             if (0 == other_mdl) {
   7153                 rv = soc_mem_delete_index(unit, L3_ENTRY_IPV4_UNICASTm, 
   7154                                           MEM_BLOCK_ALL, l3_index);
   7155                 rv =_bcm_kt2_oam_free_counter(unit, h_data_p);
   7156                 if (BCM_FAILURE(rv)) {
   7157                     LOG_ERROR(BSL_LS_BCM_OAM,
   7158                               (BSL_META_U(unit,
   7159                                           "OAM Error: LM counter block "
   7160                                           "free failed (EP=%d) - %s.\n"),
   7161                                h_data_p->ep_id, bcm_errmsg(rv)));
   7162                     L3_UNLOCK(unit);
   7163                     return (rv);
   7164                 }
   7165             } else {
   7166                 /* Valid endpoints exist for other MDLs at this index. */
   7167                 rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, 
   7168                                             l3_index, mdl_field, mdl);
   7169                 if (BCM_FAILURE(rv)) {
   7170                     LOG_ERROR(BSL_LS_BCM_OAM,
   7171                               (BSL_META_U(unit,
   7172                                           "OAM Error: LMEP view update (EP=%d) -"
   7173                                            " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7174                     L3_UNLOCK(unit);
   7175                     return (rv);
   7176                 }
   7177                 /* Clear the counter, if any */
   7178                 rv = _bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm, 
   7179                                                 l3_index, h_data_p, 
   7180                                                 (void *)&l3_entry); 
   7181                 if (BCM_FAILURE(rv)) {
   7182                     LOG_ERROR(BSL_LS_BCM_OAM,
   7183                               (BSL_META_U(unit,
   7184                                           "OAM Error: Clear counter failed (EP=%d) -"
   7185                                            " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7186                     L3_UNLOCK(unit);
   7187                     return (rv);
   7188                 }
   7189                    
   7190             }
   7191         }
   7192         L3_UNLOCK(unit);
   7193 
   7194         /* This is the last Rx endpoint in this OAM group. */
   7195         if ((0 == mdl) && (upmep == 0)) {
   7196             ma_base_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
   7197                                                             &l3_entry,
   7198                                                             LMEP__MA_BASE_PTRf);
   7199             /* Return Rx indices to free pool. */
   7200             for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   7201                 rx_index[idx] = ma_base_index + idx;
   7202             }
   7203             BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   7204                         &ma_idx_entry_count, &pool));
   7205             rv = shr_idxres_list_free_set(pool, ma_idx_entry_count,
   7206                                           (shr_idxres_element_t *) rx_index,
   7207                                           (shr_idxres_element_t *) &count);
   7208             if (BCM_FAILURE(rv) || (8 != count)) {
   7209                 LOG_ERROR(BSL_LS_BCM_OAM,
   7210                           (BSL_META_U(unit,
   7211                                       "OAM Error: Rx index list free (EP=%d)"
   7212                                        " (count=%d).\n"), h_data_p->ep_id, count));
   7213                 return (rv);
   7214             }
   7215         }
   7216         /* Delete ING_SERVICE pri map profile entry for this endpoint. */
   7217         if (h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) { 
   7218             rv = soc_profile_mem_delete(unit, &oc->ing_service_pri_map,
   7219                                 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX));
   7220             if (BCM_FAILURE(rv)) {
   7221                 LOG_ERROR(BSL_LS_BCM_OAM,
   7222                           (BSL_META_U(unit,
   7223                                       "OAM Error: Profile table update error (idx=%d)"
   7224                                        "- %s.\n"), h_data_p->pri_map_index, bcm_errmsg(rv)));
   7225                 return (rv);
   7226             }
   7227             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
   7228         }
   7229     } else if (BCM_FAILURE(rv) && (oc->init)) {
   7230         /* We do not program passive bitmap for MIP. So dont throw error
   7231          * if you don't find an entry, since we might not have created
   7232          * such an entry at all. */
   7233         if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) &&
   7234                     (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7235             LOG_ERROR(BSL_LS_BCM_OAM,
   7236                     (BSL_META_U(unit,
   7237                                 "OAM(unit %d) Error:  L3 entry table lookup (EP=%d) -"
   7238                                 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   7239             return (rv);
   7240         }
   7241     }
   7242     return (BCM_E_NONE);
   7243 }
   7244 
   7245 /*
   7246  * Function:
   7247  *     _bcm_kt2_oam_egr_mp_group_entry_destroy
   7248  * Purpose:
   7249  *     Update Egress MP group table entry.
   7250  * Parameters:
   7251  *     unit      - (IN) BCM device number
   7252  *     h_data_p  - (IN) Pointer to endpoint hash data
   7253  * Retruns:
   7254  *     BCM_E_XXX
   7255  */
   7256 STATIC int
   7257 _bcm_kt2_oam_egr_mp_group_entry_destroy(int unit, 
   7258                                     _bcm_oam_hash_data_t *h_data_p,
   7259                                     uint8 *active_mdl)
   7260 {
   7261     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   7262     uint8              mdl;            /* Maintenance domain level.         */
   7263     uint8              other_mdl = 0;  /* Maintenance domain level.         */
   7264     int                rv;             /* Operation return status.          */
   7265     uint32             ma_base_index;  /* Endpoint tbl base index. */
   7266     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   7267                                        /* Endpoint Rx hardware index.       */
   7268     uint32 count;                      /* No. of Rx indices freed           */
   7269                                        /* successfully.                     */
   7270     int                idx;            /* Iterator variable.                */
   7271     soc_field_t        mdl_field = 0;
   7272     soc_field_t        other_mdl_field = 0;
   7273     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   7274     int                mp_grp_index = 0;
   7275     int                upmep = 0;
   7276 #if defined(INCLUDE_BHH)
   7277     _bcm_oam_hash_data_t *hash_data;
   7278     bcm_oam_endpoint_t    ep_id;
   7279     int                   key1 = 0, key2 = 0;
   7280 #endif /* INCLUDE_BHH */
   7281 
   7282     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7283 
   7284     /* Check whether up/down MEP */
   7285     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7286         mdl_field = MDL_BITMAP_ACTIVEf;
   7287         other_mdl_field = MDL_BITMAP_PASSIVEf;
   7288         upmep = 1;
   7289     } else {
   7290         mdl_field = MDL_BITMAP_PASSIVEf;
   7291         other_mdl_field = MDL_BITMAP_ACTIVEf;
   7292     }
   7293     rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 
   7294                                           &mp_grp_index, &egr_mp_group);
   7295     if (BCM_SUCCESS(rv)) {
   7296 
   7297 #if defined(INCLUDE_BHH)
   7298         if (BHH_EP_TYPE(h_data_p)) {
   7299 
   7300             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) {
   7301                 key1 = h_data_p->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
   7302             } else {
   7303                 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) {
   7304                     key1 = h_data_p->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7305                 }
   7306             }
   7307 
   7308             for (ep_id = _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET;
   7309                  ep_id < (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET + oc->bhh_endpoint_count);
   7310                  ep_id++) {
   7311 
   7312                 hash_data = &(oc->oam_hash_data[ep_id]);
   7313                 if ((!hash_data->in_use) || (hash_data->ep_id == h_data_p->ep_id)) {
   7314                     continue;
   7315                 }
   7316 
   7317                 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, hash_data->egress_if)) {
   7318                     key2 = hash_data->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
   7319                 } else {
   7320                     if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, hash_data->egress_if)) {
   7321                         key2 = h_data_p->egress_if -
   7322                                    BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7323                     }
   7324                 }
   7325 
   7326                 if (key1 == key2) {
   7327                     /* There are other EPs using the same NHI */
   7328                     return BCM_E_NONE;
   7329                 }
   7330             }
   7331         }
   7332 
   7333 #endif /* INCLUDE_BHH */
   7334 
   7335         /* Endpoint found, get MDL bitmap value. */
   7336         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   7337                                                      mdl_field);
   7338 
   7339         /* Passive demultiplexing should not be done on a MIP.
   7340          * Hence do not touch PASSIVE bitmap when destroying
   7341          * also. 
   7342          */
   7343         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   7344              (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7345             /* Clear the MDL bit for this endpoint. */
   7346             mdl &= ~(1 << h_data_p->level);
   7347 
   7348             if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7349                 *active_mdl = mdl;
   7350             } else{
   7351                 /* Passive MDL bitmap */
   7352                 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl,
   7353                                                  h_data_p->ma_base_index, &mdl, 0);
   7354             }
   7355         }
   7356 
   7357         /* Take L3 module protection mutex to block any updates. */
   7358         soc_mem_lock(unit, EGR_MP_GROUPm);
   7359         if (0 != mdl) {
   7360             /* Valid endpoints exist for other MDLs at this index. */
   7361             rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index,
   7362                                                      mdl_field, mdl);
   7363             if (BCM_FAILURE(rv)) {
   7364                 LOG_ERROR(BSL_LS_BCM_OAM,
   7365                           (BSL_META_U(unit,
   7366                                       "OAM Error: EGR MP group table update (EP=%d) -"
   7367                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7368                 soc_mem_unlock(unit, EGR_MP_GROUPm);
   7369                 return (rv);
   7370             }
   7371             /* Clear the counter, if any */
   7372             rv = _bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index,
   7373                                             h_data_p, (void *)&egr_mp_group); 
   7374             if (BCM_FAILURE(rv)) {
   7375                 LOG_ERROR(BSL_LS_BCM_OAM,
   7376                           (BSL_META_U(unit,
   7377                                       "OAM Error:EGR MP group table update(EP=%d) -"
   7378                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7379                 soc_mem_unlock(unit, EGR_MP_GROUPm);
   7380                 return (rv);
   7381             }
   7382         } else {
   7383             /* check if other MDL bitmap is also zero (passive bitmap in case 
   7384                of downmep and active bitmap in case of upmep), if so delete the
   7385                entry completely */
   7386             other_mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   7387                                                      other_mdl_field);
   7388             if (0 == other_mdl) {
   7389                 rv = soc_mem_delete_index(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL,
   7390                                           mp_grp_index);
   7391                 rv =_bcm_kt2_oam_free_counter(unit, h_data_p);
   7392                 if (BCM_FAILURE(rv)) {
   7393                     LOG_ERROR(BSL_LS_BCM_OAM,
   7394                               (BSL_META_U(unit,
   7395                                           "OAM Error: LM counter block "
   7396                                           "free failed (EP=%d) - %s.\n"),
   7397                                h_data_p->ep_id, bcm_errmsg(rv)));
   7398                     soc_mem_unlock(unit, EGR_MP_GROUPm);
   7399                     return (rv);
   7400                 }
   7401             } else {
   7402                 rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index,
   7403                                                      mdl_field, mdl);
   7404                 if (BCM_FAILURE(rv)) {
   7405                     LOG_ERROR(BSL_LS_BCM_OAM,
   7406                               (BSL_META_U(unit,
   7407                                           "OAM Error: EGR MP group table update "
   7408                                           "(EP=%d) -" " %s.\n"), 
   7409                                h_data_p->ep_id, bcm_errmsg(rv)));
   7410                     soc_mem_unlock(unit, EGR_MP_GROUPm);
   7411                     return (rv);
   7412                 }
   7413                 /* Clear the counter, if any */
   7414                 rv = _bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index,
   7415                                                h_data_p, (void *)&egr_mp_group); 
   7416                 if (BCM_FAILURE(rv)) {
   7417                     LOG_ERROR(BSL_LS_BCM_OAM,
   7418                               (BSL_META_U(unit,
   7419                                           "OAM Error:EGR MP group tbl update(EP=%d)-"
   7420                                            " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7421                     soc_mem_unlock(unit, EGR_MP_GROUPm);
   7422                     return (rv);
   7423                 }
   7424             }
   7425         }
   7426         soc_mem_unlock(unit, EGR_MP_GROUPm);
   7427 
   7428         /* This is the last Rx endpoint in this OAM group. */
   7429         if ((0 == mdl) && (upmep)) {
   7430             ma_base_index = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   7431                                                         MA_BASE_PTRf);
   7432             /* Return Rx indices to free pool. */
   7433             for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   7434                 rx_index[idx] = ma_base_index + idx;
   7435             }
   7436 
   7437             rv = shr_idxres_list_free_set(oc->egr_ma_idx_pool, 8,
   7438                                           (shr_idxres_element_t *) rx_index,
   7439                                           (shr_idxres_element_t *) &count);
   7440             if (BCM_FAILURE(rv) || (8 != count)) {
   7441                 LOG_ERROR(BSL_LS_BCM_OAM,
   7442                           (BSL_META_U(unit,
   7443                                       "OAM Error: Egr Rx index list free (EP=%d)"
   7444                                        " (count=%d).\n"), h_data_p->ep_id, count));
   7445                 return (rv);
   7446             }
   7447         }
   7448         /* Delete EGR_SERVICE pri map profile entry for this endpoint. */
   7449         if (h_data_p->egr_pri_map_index != _BCM_OAM_INVALID_INDEX) {
   7450             rv = soc_profile_mem_delete(unit, &oc->egr_service_pri_map,
   7451                           (h_data_p->egr_pri_map_index * BCM_OAM_INTPRI_MAX));
   7452             if (BCM_FAILURE(rv)) {
   7453                 LOG_ERROR(BSL_LS_BCM_OAM,
   7454                           (BSL_META_U(unit,
   7455                                       "OAMError:Profile table update error (idx=%d)"
   7456                                        "- %s.\n"), h_data_p->egr_pri_map_index, bcm_errmsg(rv)));
   7457                 return (rv);
   7458             }
   7459             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
   7460         }
   7461     } else if (BCM_FAILURE(rv) && (oc->init)) {
   7462         /* We do not program passive bitmap for MIP. So dont throw error
   7463          * if you don't find an entry, since we might not have created
   7464          * such an entry at all. */
   7465         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   7466                     (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7467             LOG_ERROR(BSL_LS_BCM_OAM,
   7468                     (BSL_META_U(unit,
   7469                                 "OAM(unit %d) Error: LMEP table write (EP=%d) -"
   7470                                 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   7471             return (rv);
   7472         }
   7473     }
   7474     return (BCM_E_NONE);
   7475 }
   7476 
   7477 /*
   7478  * Function:
   7479  *     _bcm_kt2_oam_local_endpoint_delete
   7480  * Purpose:
   7481  *     Delete a local endpoint.
   7482  * Parameters:
   7483  *     unit      - (IN) BCM device number
   7484  *     h_data_p  - (IN) Pointer to endpoint hash data
   7485  * Retruns:
   7486  *     BCM_E_XXX
   7487  */
   7488 STATIC int
   7489 _bcm_kt2_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
   7490 {
   7491     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   7492     lmep_entry_t       lmep_entry;     /* Local endpoint table entry.       */
   7493     int                rv;             /* Operation return status.          */
   7494     lmep_1_entry_t     lmep_1_entry;   /* LMEP_1 table entry.               */
   7495     soc_profile_mem_t  *opcode_control_profile; /* profile used -
   7496                                                         ingress or egress   */
   7497     soc_profile_mem_t  *dglp_profile;  /* dglp profile used -
   7498                                                         ingress or egress   */
   7499     ma_index_entry_t   ma_idx_entry;   /* MA_INDEX table entry buffer.      */
   7500     ma_index_entry_t   egr_ma_idx_entry;/* MA_INDEX table entry buffer.     */
   7501     void               *ma_idx_ptr;
   7502     soc_mem_t          ma_index_mem = 0;
   7503     uint8              active_mdl = 0;
   7504     int                ma_offset = 0;
   7505 
   7506     /* Lock already taken by the calling routine. */
   7507     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7508 
   7509     if (1 == h_data_p->local_tx_enabled) {
   7510 
   7511         /* Clear endpoint Tx config in hardware. */
   7512         sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   7513         sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t));
   7514         rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   7515                          &lmep_entry);
   7516 
   7517         if (BCM_FAILURE(rv)) {
   7518             LOG_ERROR(BSL_LS_BCM_OAM,
   7519                       (BSL_META_U(unit,
   7520                                   "OAM Error: LMEP table write (EP=%d)"
   7521                                    " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7522             return (rv);
   7523         }
   7524         rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   7525                          &lmep_1_entry);
   7526         if (BCM_FAILURE(rv)) {
   7527             LOG_ERROR(BSL_LS_BCM_OAM,
   7528                       (BSL_META_U(unit,
   7529                                   "OAM Error: LMEP_1 table write (EP=%d)"
   7530                                    " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7531             return (rv);
   7532         }
   7533 
   7534         /* Return ID back to free LMEP ID pool. */
   7535         BCM_IF_ERROR_RETURN
   7536             (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index));
   7537     }
   7538 
   7539     if (1 == h_data_p->local_rx_enabled) {
   7540         /* Check whether up/down MEP */
   7541         if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7542             opcode_control_profile = &oc->egr_oam_opcode_control_profile;
   7543             dglp_profile = &oc->egr_oam_dglp_profile;
   7544             ma_index_mem = EGR_MA_INDEXm;
   7545             sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t));
   7546             ma_idx_ptr = &egr_ma_idx_entry;
   7547         } else {
   7548             opcode_control_profile = &oc->oam_opcode_control_profile;
   7549             dglp_profile = &oc->ing_oam_dglp_profile;
   7550             ma_index_mem = MA_INDEXm;
   7551             sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t));
   7552             ma_idx_ptr = &ma_idx_entry;
   7553         }
   7554 
   7555         /* Delete OAM opcode profile entry for this endpoint. */
   7556         rv = soc_profile_mem_delete(unit, opcode_control_profile,
   7557                                     h_data_p->profile_index);
   7558         if (BCM_FAILURE(rv)) {
   7559             LOG_ERROR(BSL_LS_BCM_OAM,
   7560                       (BSL_META_U(unit,
   7561                                   "OAM Error: Profile table update error (idx=%d)"
   7562                                    "- %s.\n"), h_data_p->profile_index, bcm_errmsg(rv)));
   7563             return (rv);
   7564         }
   7565         /* Delete DGLP  profile entry for this endpoint. */
   7566         if (h_data_p->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 
   7567             rv = soc_profile_mem_delete(unit, dglp_profile,
   7568                                         h_data_p->dglp1_profile_index);
   7569             if (BCM_FAILURE(rv)) {
   7570                 LOG_ERROR(BSL_LS_BCM_OAM,
   7571                           (BSL_META_U(unit,
   7572                                       "OAM Error: Profile table update "
   7573                                       "error (idx=%d)" "- %s.\n"), 
   7574                            h_data_p->dglp1_profile_index, bcm_errmsg(rv)));
   7575                 return (rv);
   7576             }
   7577         }
   7578         if (h_data_p->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 
   7579             rv = soc_profile_mem_delete(unit, dglp_profile,
   7580                                         h_data_p->dglp2_profile_index);
   7581             if (BCM_FAILURE(rv)) {
   7582                 LOG_ERROR(BSL_LS_BCM_OAM,
   7583                           (BSL_META_U(unit,
   7584                                       "OAM Error: Profile table update "
   7585                                       "error (idx=%d)" "- %s.\n"), 
   7586                            h_data_p->dglp2_profile_index, bcm_errmsg(rv)));
   7587                 return (rv);
   7588             }
   7589         }
   7590         /* Get MA_INDEX offset  */
   7591         rv = _bcm_kt2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset);
   7592         if (BCM_FAILURE(rv)) {
   7593             LOG_ERROR(BSL_LS_BCM_OAM,
   7594                       (BSL_META_U(unit,
   7595                                   "OAM Error: MA INDEX table offset get failed EP=%d"
   7596                                    "  %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7597             return (rv);
   7598         }
   7599 
   7600         h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
   7601 
   7602         /* Delete MA INDEX entry */
   7603         rv = _bcm_kt2_oam_ma_index_entry_set(unit, h_data_p, 
   7604                                          ma_index_mem, ma_idx_ptr, 1);
   7605         if (BCM_FAILURE(rv)) {
   7606             LOG_ERROR(BSL_LS_BCM_OAM,
   7607                       (BSL_META_U(unit,
   7608                                   "OAM Error: MA INDEX table delete failed EP=%d"
   7609                                    "  %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7610             return (rv);
   7611         }
   7612         if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   7613             rv = _bcm_port_domain_mdl_bitmap_update(unit, h_data_p);
   7614             if (BCM_FAILURE(rv)) {
   7615                 LOG_ERROR(BSL_LS_BCM_OAM,
   7616                           (BSL_META_U(unit,
   7617                                       "OAM Error: port OAM MDL update failed EP=%d"
   7618                                        "  %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7619                 return (rv);
   7620             }
   7621         } else if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7622             rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 
   7623                                                          &active_mdl);
   7624             if (BCM_FAILURE(rv)) {
   7625                 LOG_ERROR(BSL_LS_BCM_OAM,
   7626                           (BSL_META_U(unit,
   7627                                       "OAM Error: Egr MP Group  update (EP=%d) -"
   7628                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7629                 return (rv);
   7630             }
   7631 
   7632 
   7633             /* Update Ingress MP group table(L3_ENTRY) */
   7634             rv = _bcm_kt2_oam_l3_entry_destroy(unit, h_data_p, &active_mdl);
   7635             if (BCM_FAILURE(rv)) {
   7636                 LOG_ERROR(BSL_LS_BCM_OAM,
   7637                           (BSL_META_U(unit,
   7638                                       "OAM Error: LMEP view update (EP=%d) -"
   7639                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7640                 return (rv);
   7641             }
   7642         } else {
   7643             /* Update Ingress MP group table(L3_ENTRY) */
   7644             rv = _bcm_kt2_oam_l3_entry_destroy(unit, h_data_p, &active_mdl);
   7645             if (BCM_FAILURE(rv)) {
   7646                 LOG_ERROR(BSL_LS_BCM_OAM,
   7647                           (BSL_META_U(unit,
   7648                                       "OAM Error: LMEP view update (EP=%d) -"
   7649                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7650                 return (rv);
   7651 
   7652             }
   7653             rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, h_data_p,
   7654                                                          &active_mdl);
   7655             if (BCM_FAILURE(rv)) {
   7656                 LOG_ERROR(BSL_LS_BCM_OAM,
   7657                           (BSL_META_U(unit,
   7658                                       "OAM Error: Egr MP Group  update (EP=%d) -"
   7659                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   7660                 return (rv);
   7661             }
   7662         } 
   7663     }
   7664     return (BCM_E_NONE);
   7665 }
   7666 
   7667 
   7668 /*
   7669  * Function:
   7670  *     _bcm_kt2_oam_port_table_key_update1
   7671  * Purpose:
   7672  *     Update OAM_KEY1 and OAM_KEY2 in port table 
   7673  * Parameters:
   7674  *     unit          - (IN) BCM device number
   7675  *     mem           - (IN) PORT_TAB/EGR_PORT
   7676  *     pp_port       - (IN) PP port
   7677  *     h_data_p      - (IN/OUT) Pointer to endpoint hash data 
   7678  * Returns:
   7679  *      BCM_E_XXX
   7680  */
   7681 int 
   7682  _bcm_kt2_oam_port_table_key_update1(int unit, soc_mem_t mem, int pp_port,
   7683                                     _bcm_oam_hash_data_t *h_data_p)
   7684 {
   7685     _bcm_oam_control_t   *oc;            /* Pointer to OAM control structure. */
   7686     int                  rv = BCM_E_NONE;  /* Operation return status.        */
   7687     port_tab_entry_t     port_entry;
   7688     egr_port_entry_t egr_port_entry;
   7689     uint32               key_type = 0;
   7690     uint32               oam_key1 = 0;
   7691     uint32               oam_key2 = 0;
   7692     void                 *port_entry_ptr;
   7693     uint16               *key1_ref_count = NULL;
   7694     uint16               *key2_ref_count = NULL;
   7695 
   7696     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7697 
   7698     /* Set the search key type. */
   7699     if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) {
   7700         key_type = _BCM_OAM_DOMAIN_VP;
   7701     } else if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   7702         key_type = _BCM_OAM_DOMAIN_CVLAN;
   7703     } else if(h_data_p->flags & 
   7704                      BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   7705         key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   7706     } else if((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) {
   7707         key_type = _BCM_OAM_DOMAIN_PORT;
   7708     } else {
   7709         key_type = _BCM_OAM_DOMAIN_SVLAN;
   7710     }
   7711 
   7712     if (mem == PORT_TABm) {
   7713         port_entry_ptr = &port_entry;
   7714         key1_ref_count = &oc->oam_key1_ref_count[0];
   7715         key2_ref_count = &oc->oam_key2_ref_count[0];
   7716     } else {
   7717         port_entry_ptr = &egr_port_entry;
   7718         key1_ref_count = &oc->egr_oam_key1_ref_count[0];
   7719         key2_ref_count = &oc->egr_oam_key2_ref_count[0];
   7720     }    
   7721 
   7722     /* 
   7723     We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 
   7724     EGR_PORT_TABLE based on the key_type of OAM */
   7725 
   7726     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port, port_entry_ptr);
   7727     if (BCM_FAILURE(rv)) {
   7728         LOG_ERROR(BSL_LS_BCM_OAM,
   7729                   (BSL_META_U(unit,
   7730                               "OAM Error: Port table read - %s.\n"),
   7731                    bcm_errmsg(rv)));
   7732         return (rv);
   7733     }
   7734     oam_key1 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY1f);
   7735     oam_key2 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY2f);
   7736 
   7737     if (key_type != _BCM_OAM_DOMAIN_PORT) {
   7738          if ((oam_key1 > 0) && (oam_key2 > 0)) {
   7739              if ((oam_key1 == key_type) || (oam_key2 == key_type)) {
   7740              } else {
   7741                  LOG_ERROR(BSL_LS_BCM_OAM,
   7742                            (BSL_META_U(unit,
   7743                                        "OAM Error: Invalid OAM domain to resolve "
   7744                                        "(EP=%d) - %s.\n"),
   7745                             h_data_p->ep_id, bcm_errmsg(rv)));
   7746                  return (BCM_E_PARAM);
   7747              }
   7748          }
   7749      }
   7750  
   7751     if (key_type != _BCM_OAM_DOMAIN_PORT) {
   7752         if ((oam_key1 == 0) && (oam_key2 == 0)) {
   7753             soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, key_type);
   7754             key1_ref_count[pp_port]++;  
   7755         } else if ((oam_key1 != key_type) && (oam_key2 == 0)) {
   7756             if (key_type > oam_key1) {
   7757                 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY2f, 
   7758                                                                  key_type);
   7759                 key2_ref_count[pp_port]++;  
   7760             } else {
   7761                 key2_ref_count[pp_port] = key1_ref_count[pp_port];  
   7762                 soc_mem_field32_set(unit, mem, port_entry_ptr, 
   7763                                                       OAM_KEY1f, key_type);
   7764                 key1_ref_count[pp_port] = 1;
   7765                 soc_mem_field32_set(unit, mem, port_entry_ptr,
   7766                                                       OAM_KEY2f, oam_key1);
   7767             }
   7768         } else if ((oam_key2 != key_type) && (oam_key1 == 0)) {
   7769             if (key_type < oam_key2) {
   7770                 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, 
   7771                                                                  key_type);
   7772                 key1_ref_count[pp_port]++;
   7773             } else {
   7774                 key1_ref_count[pp_port] = key2_ref_count[pp_port];  
   7775                 soc_mem_field32_set(unit, mem, port_entry_ptr, 
   7776                                                       OAM_KEY1f, oam_key2);
   7777                 soc_mem_field32_set(unit, mem, port_entry_ptr,
   7778                                                       OAM_KEY2f, key_type);
   7779                 key2_ref_count[pp_port] = 1;
   7780             }
   7781         } else if (oam_key1 == key_type) {
   7782             key1_ref_count[pp_port]++;
   7783         } else if (oam_key2 == key_type) {
   7784             key2_ref_count[pp_port]++ ;
   7785         }
   7786         if (SOC_WARM_BOOT(unit)) {
   7787             return rv;
   7788         }
   7789         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, pp_port, port_entry_ptr);
   7790         if (BCM_FAILURE(rv)) {
   7791             LOG_ERROR(BSL_LS_BCM_OAM,
   7792                       (BSL_META_U(unit,
   7793                                   "OAM Error: Port table update failed  "
   7794                                   "%s.\n"), bcm_errmsg(rv)));
   7795             return (rv);
   7796         }
   7797     }
   7798     return rv;
   7799 }
   7800 
   7801 /*
   7802  * Function:
   7803  *     _bcm_kt2_oam_port_table_key_update
   7804  * Purpose:
   7805  *     Update port table OAM key fields. 
   7806  * Parameters:
   7807  *     unit          - (IN) BCM device number
   7808  *     mem           - (IN) PORT_TAB/EGR_PORT
   7809  *     h_data_p      - (IN/OUT) Pointer to endpoint hash data
   7810  * Returns:
   7811  *      BCM_E_XXX
   7812  */
   7813 int 
   7814  _bcm_kt2_oam_port_table_key_update(int unit, soc_mem_t mem, 
   7815                                     _bcm_oam_hash_data_t *h_data_p)
   7816 {
   7817     int                  rv = BCM_E_NONE;      /* Operation return status. */
   7818     bcm_port_t           *member_array = NULL; /* Trunk member port array. */
   7819     bcm_module_t         module_id;            /* Module ID                */
   7820     bcm_port_t           pp_port = 0;
   7821     int                  member_count = 0;
   7822     int                  local_member_count = 0;
   7823     int                  i = 0; 
   7824 
   7825     if ((h_data_p->trunk_id != BCM_TRUNK_INVALID)) {
   7826         /* Get count of ports in this trunk. */
   7827         BCM_IF_ERROR_RETURN
   7828             (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   7829                                NULL, 0, NULL, &member_count));
   7830         if (0 == member_count) {
   7831             /* No members have been added to the trunk group yet */
   7832             LOG_ERROR(BSL_LS_BCM_OAM,
   7833                       (BSL_META_U(unit,
   7834                                   "OAM Error: No local members have been added to "
   7835                                   "the trunk group yet - %s.\n"), bcm_errmsg(rv)));
   7836             return BCM_E_PARAM;
   7837         }
   7838 
   7839         _BCM_OAM_ALLOC(member_array, bcm_port_t,
   7840                        sizeof(bcm_port_t) * member_count, "Trunk info");
   7841         if (NULL == member_array) {
   7842             return (BCM_E_MEMORY);
   7843         
   7844         }
   7845 
   7846         /* Get a member of the trunk belonging to this module */
   7847         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   7848                                         h_data_p->trunk_id, 
   7849                                         member_count, member_array,
   7850                                         &local_member_count))) {
   7851             if (local_member_count > 0) {
   7852                 for(i = 0; i < local_member_count; i++) {
   7853                     rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   7854                                                          &module_id, &pp_port);
   7855                     if (BCM_FAILURE(rv)) {
   7856                         sal_free(member_array);
   7857                         return (rv);
   7858                     }
   7859                     rv = _bcm_kt2_oam_port_table_key_update1(unit, mem, 
   7860                                                      pp_port, h_data_p);
   7861                     if (BCM_FAILURE(rv)) {
   7862                         sal_free(member_array);
   7863                         return (rv);
   7864                     }
   7865                 }
   7866 
   7867             }
   7868         }
   7869         sal_free(member_array);
   7870     } else {
   7871         if (mem == PORT_TABm) {
   7872             pp_port = h_data_p->src_pp_port;
   7873         } else {
   7874             pp_port = h_data_p->dst_pp_port;
   7875         }
   7876         rv = _bcm_kt2_oam_port_table_key_update1(unit, mem, pp_port, h_data_p);
   7877     }
   7878     return rv;
   7879 }
   7880 
   7881 /*
   7882  * Function:
   7883  *     _bcm_kt2_oam_decrement_key_ref_count1
   7884  * Purpose:
   7885  *     Decrement PORT tab key1/key2 usage ref count.
   7886  * Parameters:
   7887  *     unit        - (IN) BCM device number
   7888  *     src_pp_port - (IN) Source PP port
   7889  *     dst_pp_port - (IN) destination  PP port
   7890  *     h_data_p    - (IN) Endpoint hash data.
   7891  * Retruns:
   7892  *     BCM_E_XXX
   7893  */
   7894  int 
   7895 _bcm_kt2_oam_decrement_key_ref_count1(int unit, uint32 src_pp_port, 
   7896                                       uint32 dst_pp_port,
   7897                                       _bcm_oam_hash_data_t *h_data_p)
   7898 {
   7899     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
   7900     int                  rv = BCM_E_NONE;  /* Operation return status.    */
   7901     port_tab_entry_t     port_entry;
   7902     egr_port_entry_t egr_port_entry;
   7903     uint32               key_type = 0;
   7904     uint32               oam_key1 = 0;
   7905     uint32               oam_key2 = 0;
   7906     int                  update_entry = 0;
   7907 
   7908     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   7909 
   7910     /* Set the search key type. */
   7911     if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) {
   7912         key_type = _BCM_OAM_DOMAIN_VP;
   7913     } else if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   7914         key_type = _BCM_OAM_DOMAIN_CVLAN;
   7915     } else if(h_data_p->flags & 
   7916                      BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   7917         key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   7918     } else if((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) {
   7919         key_type = _BCM_OAM_DOMAIN_PORT;
   7920     } else {
   7921         key_type = _BCM_OAM_DOMAIN_SVLAN;
   7922     }
   7923 
   7924     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry);
   7925     if (BCM_FAILURE(rv)) {
   7926          LOG_ERROR(BSL_LS_BCM_OAM,
   7927                    (BSL_META_U(unit,
   7928                                "OAM Error: Port table entry read failed  - %s.\n"),
   7929                     bcm_errmsg(rv)));
   7930         return (rv);
   7931     }
   7932     rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 
   7933                       dst_pp_port, &egr_port_entry);
   7934     if (BCM_FAILURE(rv)) {
   7935          LOG_ERROR(BSL_LS_BCM_OAM,
   7936                    (BSL_META_U(unit,
   7937                                "OAM Error: Port table entry read failed  - %s.\n"),
   7938                     bcm_errmsg(rv)));
   7939         return (rv);
   7940     }
   7941 
   7942     oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 
   7943     oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 
   7944    
   7945     if (key_type != _BCM_OAM_DOMAIN_PORT) {
   7946         if (key_type == oam_key1) {
   7947             oc->oam_key1_ref_count[src_pp_port]--;
   7948             if (oc->oam_key1_ref_count[src_pp_port] == 0) {
   7949                 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0);
   7950                 update_entry = 1;
   7951             }
   7952         } else if (key_type == oam_key2) {
   7953             oc->oam_key2_ref_count[src_pp_port]--;
   7954             if (oc->oam_key2_ref_count[src_pp_port] == 0) {
   7955                 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0);
   7956                 update_entry = 1;
   7957             }
   7958         }
   7959         if (update_entry) {
   7960             rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 
   7961                                src_pp_port, &port_entry);
   7962             update_entry = 0;
   7963         }
   7964 
   7965         oam_key1 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY1f); 
   7966         oam_key2 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY2f); 
   7967 
   7968         if (key_type == oam_key1) {
   7969             oc->egr_oam_key1_ref_count[dst_pp_port]--;
   7970             if (oc->egr_oam_key1_ref_count[dst_pp_port] == 0) {
   7971                 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY1f, 0);
   7972                 update_entry = 1;
   7973             }
   7974         } else if (key_type == oam_key2) {
   7975             oc->egr_oam_key2_ref_count[dst_pp_port]--;
   7976             if (oc->egr_oam_key2_ref_count[dst_pp_port] == 0) {
   7977                 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY2f, 0);
   7978                 update_entry = 1;
   7979             }
   7980         }
   7981         if (update_entry) {
   7982             rv = soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   7983                                dst_pp_port, &egr_port_entry);
   7984             update_entry = 0;
   7985         }
   7986     }
   7987     return rv;
   7988 }
   7989 
   7990 /*
   7991  * Function:
   7992  *     _bcm_kt2_oam_decrement_key_ref_count
   7993  * Purpose:
   7994  *     Decrement PORT tab key1/key2 usage ref count.
   7995  * Parameters:
   7996  *     unit   - (IN) BCM device number
   7997  *     h_data_p - (IN) Endpoint hash data.
   7998  * Retruns:
   7999  *     BCM_E_XXX
   8000  */
   8001  int 
   8002 _bcm_kt2_oam_decrement_key_ref_count(int unit, 
   8003                                      _bcm_oam_hash_data_t *h_data_p)
   8004 {
   8005     int                  rv = BCM_E_NONE;      /* Operation return status.    */
   8006     bcm_port_t           *member_array = NULL; /* Trunk member port array.    */
   8007     bcm_module_t         module_id;            /* Module ID                   */
   8008     bcm_port_t           src_pp_port = 0;
   8009     int                  member_count = 0;
   8010     int                  local_member_count = 0;
   8011     int                  i = 0; 
   8012 
   8013     if (h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   8014         /* Get count of ports in this trunk. */
   8015         BCM_IF_ERROR_RETURN
   8016             (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   8017                                NULL, 0, NULL, &member_count));
   8018         if (0 == member_count) {
   8019             /* No members have been added to the trunk group yet */
   8020             LOG_ERROR(BSL_LS_BCM_OAM,
   8021                       (BSL_META_U(unit,
   8022                                   "OAM Error: No local members have been added to "
   8023                                   "the trunk group yet - %s.\n"), bcm_errmsg(rv)));
   8024             return BCM_E_PARAM;
   8025         }
   8026 
   8027         _BCM_OAM_ALLOC(member_array, bcm_port_t,
   8028                        sizeof(bcm_port_t) * member_count, "Trunk info");
   8029         if (NULL == member_array) {
   8030             return (BCM_E_MEMORY);
   8031         
   8032         }
   8033 
   8034         /* Get a member of the trunk belonging to this module */
   8035         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   8036                                         h_data_p->trunk_id, 
   8037                                         member_count, member_array,
   8038                                         &local_member_count))) {
   8039             if (local_member_count > 0) {
   8040                 for(i = 0; i < local_member_count; i++) {
   8041                     rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   8042                                                      &module_id, &src_pp_port);
   8043                     if (BCM_FAILURE(rv)) {
   8044                         sal_free(member_array);
   8045                         return (rv);
   8046                     }
   8047                     rv = _bcm_kt2_oam_decrement_key_ref_count1(unit, src_pp_port,
   8048                                                h_data_p->dst_pp_port, h_data_p);
   8049                     if (BCM_FAILURE(rv)) {
   8050                         sal_free(member_array);
   8051                         return (rv);
   8052                     }
   8053                 }
   8054 
   8055             }
   8056         }
   8057         sal_free(member_array);
   8058     } else {
   8059         rv = _bcm_kt2_oam_decrement_key_ref_count1(unit, h_data_p->src_pp_port, 
   8060                                               h_data_p->dst_pp_port, h_data_p);
   8061     }
   8062     return rv;
   8063 }
   8064 
   8065 
   8066      
   8067 /*
   8068  * Function: _bcm_kt2_oam_tpid_decrement_ref_count
   8069  *     
   8070  * Purpose:
   8071  *     Decrement TPID reference count.
   8072  * Parameters:
   8073  *     unit      - (IN) BCM device number
   8074  *     h_data_p  - (IN) Endpoint hash data.
   8075  * Retruns:
   8076  *     BCM_E_XXX
   8077  */
   8078 STATIC int 
   8079 _bcm_kt2_oam_tpid_decrement_ref_count(int unit, _bcm_oam_hash_data_t *h_data_p)
   8080 {
   8081     int    rv = BCM_E_NONE;
   8082     uint32 tag_type = 0;
   8083 
   8084     /* If local CCM tx generation was not enabled, then the tpid entries
   8085      * would not have been set. So do not try to delete them even though the
   8086      * h_data_p->outer/inner/subport_tpid has a non zero value */
   8087     if (!h_data_p->local_tx_enabled) {
   8088         return BCM_E_NONE;
   8089     }
   8090 
   8091     if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) {
   8092         if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   8093             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   8094         } else if (h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   8095             tag_type =_BCM_OAM_DOMAIN_CVLAN;
   8096         } else if (h_data_p->vlan > 0) {
   8097             tag_type =_BCM_OAM_DOMAIN_SVLAN;
   8098         }
   8099     } else {
   8100         tag_type =h_data_p->oam_domain;
   8101     }
   8102 
   8103     /* if S or S+C vlan - set outer tpid index */
   8104     if (((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 
   8105         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) &&
   8106         (h_data_p->outer_tpid > 0)) { 
   8107         if (BCM_SUCCESS(rv)) {
   8108             rv = _bcm_kt2_tpid_entry_delete(unit,
   8109                                            h_data_p->outer_tpid_profile_index,
   8110                                            BCM_OAM_TPID_TYPE_OUTER);
   8111             if (BCM_FAILURE(rv)) {
   8112                 LOG_ERROR(BSL_LS_BCM_OAM,
   8113                           (BSL_META_U(unit,
   8114                                       "OAM Error: L3 entry config failed in Outer TPID "
   8115                                       "decrement ref count""  %s.\n"), bcm_errmsg(rv)));
   8116                 return (rv);
   8117             }
   8118         }
   8119     }
   8120     if (((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 
   8121         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) &&
   8122         (h_data_p->inner_tpid > 0)) { 
   8123         /* C or S+C */
   8124         if (BCM_SUCCESS(rv)) {
   8125             rv = _bcm_kt2_tpid_entry_delete(unit,
   8126                                            h_data_p->inner_tpid_profile_index,
   8127                                            BCM_OAM_TPID_TYPE_INNER);
   8128             if (BCM_FAILURE(rv)) {
   8129                 LOG_ERROR(BSL_LS_BCM_OAM,
   8130                           (BSL_META_U(unit,
   8131                                       "OAM Error: L3 entry config failed in Inner TPID "
   8132                                       "decrement ref count""  %s.\n"), bcm_errmsg(rv)));
   8133                 return (rv);
   8134             }
   8135         }
   8136     }
   8137     if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) &&
   8138               (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport)) && 
   8139               (h_data_p->subport_tpid > 0)) {
   8140         /* CoE port */
   8141         if (BCM_SUCCESS(rv)) {
   8142             rv = _bcm_kt2_tpid_entry_delete(unit,
   8143                                             h_data_p->subport_tpid_profile_index,
   8144                                             BCM_OAM_TPID_TYPE_SUBPORT);
   8145             if (BCM_FAILURE(rv)) {
   8146                 LOG_ERROR(BSL_LS_BCM_OAM,
   8147                           (BSL_META_U(unit,
   8148                                       "OAM Error: L3 entry config failed in Subport TPID  "
   8149                                       "decrement ref count""  %s.\n"), bcm_errmsg(rv)));
   8150                 return (rv);
   8151             }
   8152         }
   8153     }
   8154     return rv;
   8155 }
   8156 
   8157 /*
   8158  * Function:
   8159  *     _bcm_kt2_oam_endpoint_destroy
   8160  * Purpose:
   8161  *     Delete an endpoint and free all its allocated resources.
   8162  * Parameters:
   8163  *     unit   - (IN) BCM device number
   8164  *     ep_id  - (IN) Endpoint ID value.
   8165  * Retruns:
   8166  *     BCM_E_XXX
   8167  */
   8168 STATIC int
   8169 _bcm_kt2_oam_endpoint_destroy(int unit,
   8170                               bcm_oam_endpoint_t ep_id)
   8171 {
   8172     _bcm_oam_control_t      *oc;        /* Pointer to OAM control structure. */
   8173     _bcm_oam_hash_data_t    *h_data_p;  /* Pointer to endpoint data.         */
   8174     _bcm_oam_hash_key_t     hash_key;   /* Hash key buffer for lookup.       */
   8175     bcm_oam_endpoint_info_t ep_info;    /* Endpoint information.             */
   8176     _bcm_oam_hash_data_t    h_data;     /* Pointer to endpoint data.         */
   8177     int                     rv;         /* Operation return status.          */
   8178 #if defined(INCLUDE_BHH)
   8179     uint16 reply_len;
   8180     bcm_oam_endpoint_t bhh_pool_ep_id;
   8181 #endif
   8182 
   8183     /* Lock already taken by the calling routine. */
   8184     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   8185 
   8186     /* Get the hash data pointer. */
   8187     h_data_p = &oc->oam_hash_data[ep_id];
   8188     if(0 == h_data_p->in_use){
   8189         return BCM_E_NOT_FOUND; 
   8190     } 
   8191 
   8192     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
   8193     if (BCM_FAILURE(rv)) {
   8194         LOG_ERROR(BSL_LS_BCM_OAM,
   8195                 (BSL_META_U(unit,
   8196                             "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
   8197                             " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   8198         return (rv);
   8199     }
   8200 
   8201     if(bcmOAMEndpointTypeEthernet == h_data_p->type)
   8202     {
   8203 
   8204     if (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) {
   8205         BCM_IF_ERROR_RETURN
   8206             (_bcm_kt2_oam_remote_endpoint_delete(unit, h_data_p));
   8207 
   8208     } else {
   8209         BCM_IF_ERROR_RETURN
   8210             (_bcm_kt2_oam_local_endpoint_delete(unit, h_data_p));
   8211         /* decrement TPID ref count */
   8212         BCM_IF_ERROR_RETURN
   8213             (_bcm_kt2_oam_tpid_decrement_ref_count(unit, h_data_p));
   8214     }
   8215 
   8216     /* Remove endpoint for group's endpoint list. */
   8217     rv = _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index,
   8218                                        h_data_p->ep_id);
   8219     if (BCM_FAILURE(rv)) {
   8220         LOG_ERROR(BSL_LS_BCM_OAM,
   8221                   (BSL_META_U(unit,
   8222                               "OAM Error: Remove from group list (EP=%d) -"
   8223                                " %s.\n"), ep_id, bcm_errmsg(rv)));
   8224         return (rv);
   8225     }
   8226 
   8227 
   8228     /* Return ID back to free MEP ID pool.*/
   8229     BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id));
   8230 
   8231     /* Decrement PORT tab key1/key2 usage ref count */
   8232     if (!(h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   8233         BCM_IF_ERROR_RETURN
   8234             (_bcm_kt2_oam_decrement_key_ref_count(unit, h_data_p));
   8235     }
   8236     /* Initialize endpoint info structure. */
   8237     bcm_oam_endpoint_info_t_init(&ep_info);
   8238 
   8239     /* Set up endpoint information for key construction. */
   8240     ep_info.group = h_data_p->group_index;
   8241     ep_info.name = h_data_p->name;
   8242     ep_info.gport = h_data_p->gport;
   8243     ep_info.level = h_data_p->level;
   8244     ep_info.vlan = h_data_p->vlan;
   8245     ep_info.inner_vlan = h_data_p->inner_vlan;
   8246     ep_info.flags = h_data_p->flags;
   8247 
   8248     /* Construct hash key for lookup + delete operation. */
   8249     _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
   8250 
   8251     /* Remove entry from hash table. */
   8252     BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key,
   8253                                      (shr_htb_data_t *)&h_data,
   8254                                      1));
   8255 
   8256     /* Clear the hash data memory previously occupied by this endpoint. */
   8257     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   8258     }
   8259     /*
   8260      * BHH specific
   8261      */
   8262     else if (soc_feature(unit, soc_feature_bhh)
   8263             && BHH_EP_TYPE(h_data_p)) {
   8264 #if defined(INCLUDE_BHH)
   8265 
   8266         if (h_data_p->is_remote) {
   8267             /*
   8268             * BHH uses same index for local and remote.  So, delete always goes through
   8269             * local endpoint destory
   8270             */
   8271             return (BCM_E_NONE);
   8272         } else {
   8273 
   8274             bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id);
   8275 
   8276             /* Delete BHH Session in HW. BCM_E_NOT_FOUND is not an error when
   8277                switch is re-initializing as entry would have been already 
   8278                deleted by respective module init. */ 
   8279             rv =  _bcm_kt2_oam_bhh_session_hw_delete(unit, h_data_p);
   8280             if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   8281                 LOG_ERROR(BSL_LS_BCM_OAM,
   8282                           (BSL_META_U(unit,
   8283                                       "OAM Error: bhh_session_hw_delete failled " 
   8284                                        "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
   8285                 return (rv);
   8286             }
   8287 
   8288             if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
   8289                 /* Send BHH Session Delete message to uC. Error response is not an  
   8290                    during switch re-init as uKernel is reloaded and its state is 
   8291                    cleared before oam init. As such endpoint wont exist during oam init*/
   8292 
   8293                 _bcm_kt2_oam_bhh_msg_send_receive(unit,
   8294                         MOS_MSG_SUBCLASS_BHH_SESS_DELETE,
   8295                         (int)bhh_pool_ep_id, 0,
   8296                         MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY,
   8297                         &reply_len);
   8298             }
   8299             if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
   8300                 rv = _bcm_kt2_oam_local_endpoint_delete(unit, h_data_p);
   8301                 if (BCM_FAILURE(rv)) {
   8302                     LOG_ERROR(BSL_LS_BCM_OAM,
   8303                               (BSL_META_U(unit,
   8304                                           "OAM Error:BHH local_endpoint_delete failled "
   8305                                            "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
   8306                     return (rv);
   8307                 }
   8308             }
   8309             h_data_p->in_use = 0;
   8310         
   8311 
   8312              /* Remove endpoint for group's endpoint list. */
   8313             rv = _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index,
   8314                                        h_data_p->ep_id);
   8315             if (BCM_FAILURE(rv)) {
   8316                 LOG_ERROR(BSL_LS_BCM_OAM,
   8317                           (BSL_META_U(unit,
   8318                                       "OAM Error: Remove from group list (EP=%d) -"
   8319                                        " %s.\n"), ep_id, bcm_errmsg(rv)));
   8320                 return (rv);
   8321             }
   8322 
   8323 
   8324             /* Return ID back to free MEP ID pool.*/
   8325             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id));
   8326 
   8327             /* Set up endpoint information for key construction. */
   8328             ep_info.group = h_data_p->group_index;
   8329             ep_info.name = h_data_p->name;
   8330             ep_info.gport = h_data_p->gport;
   8331             ep_info.level = h_data_p->level;
   8332             ep_info.vlan = h_data_p->vlan;
   8333             ep_info.inner_vlan = h_data_p->inner_vlan;
   8334             ep_info.flags = h_data_p->flags;
   8335 
   8336             /* Construct hash key for lookup + delete operation. */
   8337             _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
   8338 
   8339             /* Remove entry from hash table. */
   8340             BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key,
   8341                                              (shr_htb_data_t *)&h_data,
   8342                                              1));
   8343 
   8344             /* Clear the hash data memory previously occupied by this endpoint. */
   8345             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   8346 
   8347         }
   8348 #else
   8349         return (BCM_E_UNAVAIL);
   8350 #endif /* INCLUDE_BHH */
   8351     }
   8352     else {
   8353         return (BCM_E_PARAM);
   8354     }
   8355     return (BCM_E_NONE);
   8356 }
   8357 
   8358 /*
   8359  * Function:
   8360  *     _bcm_kt2_oam_group_endpoints_destroy
   8361  * Purpose:
   8362  *     Delete all endpoints associated with a group and free all
   8363  *     resources allocated by these endpoints. 
   8364  * Parameters:
   8365  *     unit      - (IN) BCM device number
   8366  *     g_info_p  - (IN) Pointer to group information
   8367  * Retruns:
   8368  *     BCM_E_XXX
   8369  */
   8370 STATIC int
   8371 _bcm_kt2_oam_group_endpoints_destroy(int unit,
   8372                                      _bcm_oam_group_data_t *g_info_p)
   8373 {
   8374     bcm_oam_endpoint_t    ep_id; /* Endpoint ID.                   */
   8375     _bcm_oam_ep_list_t    *cur;  /* Pointer to endpoint list node. */
   8376     int                   rv;    /* Operation return status.       */
   8377 
   8378     if (NULL == g_info_p) {
   8379         return (BCM_E_INTERNAL);
   8380     }
   8381 
   8382     /* Get the endpoint list head pointer. */
   8383     cur = *(g_info_p->ep_list);
   8384     if (NULL == cur) {
   8385         LOG_DEBUG(BSL_LS_BCM_OAM,
   8386                   (BSL_META_U(unit,
   8387                               "OAM Info: No endpoints in group.\n")));
   8388         return (BCM_E_NONE);
   8389     }
   8390 
   8391     while (NULL != cur) {
   8392         ep_id = cur->ep_data_p->ep_id;
   8393 
   8394         LOG_DEBUG(BSL_LS_BCM_OAM,
   8395                   (BSL_META_U(unit,
   8396                               "OAM Info: GID=%d EP:%d.\n"),
   8397                    cur->ep_data_p->group_index, ep_id));
   8398 
   8399         cur = cur->next;
   8400 
   8401         rv = _bcm_kt2_oam_endpoint_destroy(unit, ep_id);
   8402         if (BCM_FAILURE(rv)) {
   8403             LOG_ERROR(BSL_LS_BCM_OAM,
   8404                       (BSL_META_U(unit,
   8405                                   "OAM Error: Endpoint destroy (EP=%d) - "
   8406                                    "%s.\n"), ep_id, bcm_errmsg(rv)));
   8407             return (rv);
   8408         }
   8409     }
   8410 
   8411     return (BCM_E_NONE);
   8412 }
   8413 
   8414 /*
   8415  * Function:
   8416  *     _bcm_kt2_oam_trunk_resolve
   8417  * Purpose:
   8418  *     Resolve a trunk value to SGLP, DGLP value and Tx gport.
   8419  * Parameters:
   8420  *     unit        - (IN) BCM device number
   8421  *     trunk_id    - (IN) Pointer to trunk id
   8422  *     trunk_index - (IN) Index in the trunk array to Tx pkts
   8423  *     src_glp     - (IN/OUT) Pointer to source generic logical port value.
   8424  *     dst_glp     - (IN/OUT) Pointer to destination generic logical port value.
   8425  *     src_pp_port - (IN/OUT) Pointer to source pp port value.
   8426  *     dst_pp_port - (IN/OUT) Pointer to destination pp port value.
   8427  *     tx_gport    - (OUT) Gport on which PDUs need to be sent
   8428  * Retruns:
   8429  *     BCM_E_XXX
   8430  */
   8431 STATIC int
   8432 _bcm_kt2_oam_trunk_resolve(int unit, bcm_trunk_t trunk_id, int trunk_index,
   8433                            bcm_port_t *src_pp_port, bcm_port_t *dst_pp_port,
   8434                            uint32 *src_glp, uint32 *dst_glp, bcm_gport_t *tx_gport)
   8435 {
   8436     bcm_port_t          port_id = 0;
   8437     bcm_port_t          port = 0;
   8438     bcm_module_t        module_id = 0;
   8439     int                 local_id;
   8440     bcm_trunk_member_t *member_array = NULL;
   8441     int                 member_count = 0;
   8442     int                 local_member_count = 0;
   8443     bcm_trunk_info_t    trunk_info;
   8444     bcm_trunk_t         tid = BCM_TRUNK_INVALID;
   8445     int                 rv = BCM_E_NONE;
   8446 
   8447 
   8448     if (BCM_TRUNK_INVALID == trunk_id)  {
   8449         /* Has to be a valid Trunk. */
   8450         return (BCM_E_PARAM);
   8451     }
   8452 
   8453     /* Construct Hw SGLP value. */
   8454     _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1,
   8455                                  trunk_id, *src_glp);
   8456 
   8457     /* Get a member of the trunk belonging to this module */
   8458     if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, trunk_id, 1,
   8459                                                      &port_id,
   8460                                                      &local_member_count))) {
   8461 
   8462         BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit, port_id,
   8463                                                             &module_id, &port));
   8464         *src_pp_port = port_id;
   8465     }
   8466 
   8467     /* Get count of ports in this trunk. */
   8468     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, trunk_id, NULL, 0,
   8469                                           NULL, &member_count));
   8470     if (0 == member_count) {
   8471         /* No members have been added to the trunk group yet */
   8472         return BCM_E_PARAM;
   8473     }
   8474 
   8475     _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
   8476                    sizeof(bcm_trunk_member_t) * member_count, "Trunk info");
   8477     if (NULL == member_array) {
   8478         return (BCM_E_MEMORY);
   8479     }
   8480 
   8481     /* Get Trunk Info for the Trunk ID. */
   8482     rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info,
   8483                            member_count, member_array, &member_count);
   8484     if (BCM_FAILURE(rv)) {
   8485         sal_free(member_array);
   8486         return (rv);
   8487     }
   8488 
   8489     /* Check if the input trunk_index is valid. */
   8490     if (trunk_index >= member_count) {
   8491         sal_free(member_array);
   8492         return BCM_E_PARAM;
   8493     }
   8494 
   8495 
   8496     /* Get the Modid and Port value using Trunk Index value. */
   8497     rv = _bcm_esw_gport_resolve(unit, member_array[trunk_index].gport,
   8498                                 &module_id, &port_id, &tid, &local_id);
   8499     if (BCM_FAILURE(rv)) {
   8500         sal_free(member_array);
   8501         return (rv);
   8502     }
   8503     sal_free(member_array);
   8504 
   8505     /* Construct Hw DGLP value. */
   8506     _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, *dst_glp);
   8507 
   8508     /* Get HW PP port */
   8509     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, module_id,
   8510                                                         port_id, dst_pp_port));
   8511     *dst_glp = *src_glp;
   8512     *tx_gport = member_array[trunk_index].gport;
   8513 
   8514     return BCM_E_NONE;
   8515 
   8516 }
   8517 /*
   8518  * Function:
   8519  *     _bcm_kt2_oam_endpoint_gport_resolve
   8520  * Purpose:
   8521  *     Resolve an endpoint GPORT value to SGLP and DGLP value.
   8522  * Parameters:
   8523  *     unit       - (IN) BCM device number
   8524  *     ep_info_p  - (IN/OUT) Pointer to endpoint information.
   8525  *     src_glp    - (IN/OUT) Pointer to source generic logical port value.
   8526  *     dst_glp    - (IN/OUT) Pointer to destination generic logical port value.
   8527  *     src_pp_port- (IN/OUT) Pointer to source pp port value.
   8528  *     dst_pp_port- (IN/OUT) Pointer to destination pp port value.
   8529  *     svp        - (IN/OUT) Pointer to VP value
   8530  *     trunk_id   - (IN/OUT) Pointer to trunk id
   8531  *     tx_gport   - (OUT) Gport on which PDUs need to be sent
   8532  * Retruns:
   8533  *     BCM_E_XXX
   8534  */
   8535 STATIC int
   8536 _bcm_kt2_oam_endpoint_gport_resolve(int unit, bcm_oam_endpoint_info_t *ep_info_p,
   8537                                     uint32 *src_glp, uint32 *dst_glp,
   8538                                     bcm_port_t *src_pp_port,
   8539                                     bcm_port_t *dst_pp_port, uint32 *svp,
   8540                                     bcm_trunk_t *trunk_id, int *is_vp_valid,
   8541                                     bcm_gport_t *tx_gport)
   8542 {
   8543     bcm_module_t       module_id;            /* Module ID           */
   8544     bcm_port_t         port_id;              /* Port ID.            */
   8545     bcm_port_t         port;                 /* Port ID.            */
   8546     int                local_id;             /* Hardware ID.        */
   8547     int                tx_enabled = 0;       /* CCM Tx enabled.     */
   8548     int                local_member_count = 0;
   8549     int                rv = BCM_E_NONE;                   /* Return status.      */
   8550     uint8              glp_valid = 0;        /* Logical port valid. */
   8551     int                is_local = 0;
   8552     uint8              is_port_mep = 0;
   8553 
   8554     is_port_mep = ((ep_info_p->vlan == 0) && (ep_info_p->inner_vlan == 0));
   8555     /* Get Trunk ID or (Modid + Port) value from Gport */
   8556     BCM_IF_ERROR_RETURN
   8557         (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id,
   8558                                 &port_id, trunk_id, &local_id));
   8559  
   8560     /* Set CCM endpoint Tx status only for local endpoints. */
   8561     if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   8562         tx_enabled
   8563             = (ep_info_p->ccm_period
   8564                 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0;
   8565     }
   8566 
   8567     /*
   8568      * If Gport is Trunk type, _bcm_esw_gport_resolve()
   8569      * sets trunk_id. Using Trunk ID, get Dst Modid and Port value.
   8570      */
   8571     if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) {
   8572 
   8573         /*
   8574          * CCM Tx is enabled on a trunk member port.
   8575          * trunk_index value is required to derive the Modid and Port info.
   8576          */
   8577         if (1 == tx_enabled && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) {
   8578             /* Invalid Trunk member index passed. */
   8579             return (BCM_E_PORT);
   8580         }
   8581 
   8582         BCM_IF_ERROR_RETURN(
   8583               _bcm_kt2_oam_trunk_resolve(unit, *trunk_id, ep_info_p->trunk_index,
   8584                                          src_pp_port, dst_pp_port,
   8585                                          src_glp, dst_glp, tx_gport));
   8586         glp_valid = 1;
   8587     }
   8588 
   8589     /*
   8590      * Application can resolve the trunk and pass the desginated
   8591      * port as Gport value. Check if the Gport belongs to a trunk.
   8592      */
   8593     if ((BCM_TRUNK_INVALID == (*trunk_id))
   8594         && (BCM_GPORT_IS_MODPORT(ep_info_p->gport)
   8595         || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) {
   8596 
   8597         /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve()
   8598          * returns Modid and Port value. Use these values to make the DGLP
   8599          * value.
   8600          */
   8601         _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
   8602             *dst_glp);
   8603         /* get destination PP port */
   8604         BCM_IF_ERROR_RETURN
   8605             (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
   8606                                              dst_pp_port));
   8607 
   8608         /* Use the Modid, Port value and determine if the port
   8609          * belongs to a Trunk.
   8610          */
   8611         if (!is_port_mep) {
   8612             /* Dont find all other trunk members if it is a port mep */
   8613             rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
   8614         }
   8615         if (BCM_SUCCESS(rv) && !is_port_mep) {
   8616             /*
   8617              * Port is member of a valid trunk.
   8618              * Now create the SGLP value from Trunk ID.
   8619              */
   8620             /* Get a member of the trunk belonging to this module */
   8621             if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1,
   8622                                         &port_id,
   8623                                         &local_member_count))) {
   8624                 BCM_IF_ERROR_RETURN
   8625                     (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
   8626                                                       &module_id, &port));
   8627                 /* Get HW PP port */
   8628                 *src_pp_port = port_id;
   8629 
   8630                 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 
   8631                                              *trunk_id, *src_glp);
   8632                 *dst_glp = *src_glp;
   8633             } else {
   8634                 *src_pp_port = *dst_pp_port; 
   8635             }
   8636         } else {
   8637             /* Port not a member of trunk. DGLP and SGLP are the same. */
   8638             *src_glp = *dst_glp;
   8639             *src_pp_port = *dst_pp_port; 
   8640         }
   8641         glp_valid = 1;
   8642         *tx_gport = ep_info_p->gport;
   8643     }
   8644     if ((SOC_GPORT_IS_MIM_PORT(ep_info_p->gport)) ||
   8645         (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) ||
   8646         (SOC_GPORT_IS_VLAN_PORT(ep_info_p->gport))) {
   8647         *svp = local_id;
   8648 
   8649         if(BCM_TRUNK_INVALID == (*trunk_id)){
   8650             rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
   8651             if(BCM_SUCCESS(rv) && (is_local)) {
   8652                 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0,
   8653                                              -1, *dst_glp);
   8654                 /* get destination PP port */
   8655                 BCM_IF_ERROR_RETURN(
   8656                               _bcm_kt2_modport_to_pp_port_get(unit,
   8657                                                               module_id, port_id,
   8658                                                               dst_pp_port));
   8659                 *src_glp     = *dst_glp;
   8660                 *src_pp_port = *dst_pp_port;
   8661             }
   8662             *tx_gport = ep_info_p->gport;
   8663         } else {
   8664             /*
   8665              * CCM Tx is enabled on a trunk member port.
   8666              * trunk_index value is required to derive the Modid and Port info.
   8667              */
   8668             if ((1 == tx_enabled) &&
   8669                             (_BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index)) {
   8670                 /* Invalid Trunk member index passed. */
   8671                 return (BCM_E_PORT);
   8672             }
   8673             BCM_IF_ERROR_RETURN(
   8674                _bcm_kt2_oam_trunk_resolve(unit, *trunk_id, ep_info_p->trunk_index,
   8675                                           src_pp_port, dst_pp_port,
   8676                                           src_glp, dst_glp, tx_gport));
   8677         }
   8678         glp_valid    = 1;
   8679         *is_vp_valid = 1;
   8680     }
   8681 
   8682     /* LinkPhy/CoE case */
   8683     if ((BCM_GPORT_IS_SUBPORT_PORT(ep_info_p->gport))) {
   8684         if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, ep_info_p->gport)) ||
   8685             (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, ep_info_p->gport))) {
   8686             BCM_IF_ERROR_RETURN
   8687                 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
   8688                                                 dst_pp_port));
   8689             *src_pp_port = *dst_pp_port; 
   8690             _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
   8691                                              *dst_glp);
   8692                 /* Use the Modid, Port value and determine if the port
   8693                  * belongs to a Trunk.
   8694                  */
   8695             if (!is_port_mep) {
   8696                 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
   8697             }
   8698             if (BCM_SUCCESS(rv) && !is_port_mep) {
   8699                 /*
   8700                  * Port is member of a valid trunk.
   8701                  * Now create the SGLP value from Trunk ID.
   8702                  */
   8703                 /* Get a member of the trunk belonging to this module */
   8704                 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit,  
   8705                                         *trunk_id, 1,
   8706                                         &port_id,
   8707                                         &local_member_count))) {
   8708                     BCM_IF_ERROR_RETURN
   8709                         (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
   8710                                                       &module_id, &port));
   8711                    /* Get HW PP port */
   8712                     *src_pp_port = port_id;
   8713 
   8714                    _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 
   8715                                                 *trunk_id, *src_glp);
   8716                    *dst_glp = *src_glp;
   8717                 }
   8718             } else {
   8719                 *src_glp = *dst_glp;
   8720             }
   8721             glp_valid = 1;
   8722             BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id);
   8723         } 
   8724     }
   8725 
   8726     /*
   8727      * At this point, both src_glp and dst_glp should be valid.
   8728      * Gport types other than TRUNK, MODPORT or LOCAL are not valid.
   8729      */
   8730     if (0 == glp_valid) {
   8731         return (BCM_E_PORT);
   8732     }
   8733     return (BCM_E_NONE);
   8734 }
   8735 
   8736 /*
   8737  * Function:
   8738  *     _bcm_kt2_oam_mepid_validate
   8739  * Purpose:
   8740  *     Validate an endpoint MEP id.
   8741  * Parameters:
   8742  *     unit      - (IN) BCM device number
   8743  *     ep_info_p - (IN) Pointer to endpoint information.
   8744  * Retruns:
   8745  *     BCM_E_XXX
   8746  */
   8747 STATIC int
   8748 _bcm_kt2_oam_mepid_validate(int unit,  
   8749                             bcm_oam_endpoint_info_t *ep_info_p)
   8750 {
   8751     _bcm_oam_control_t *oc;
   8752     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
   8753     _bcm_oam_ep_list_t    *cur;     /* Current head node pointer.       */
   8754     _bcm_oam_hash_data_t  *h_data_p = NULL; /* Endpoint hash data pointer. */
   8755 
   8756     /* Get OAM control structure. */
   8757     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
   8758 
   8759     /* Get the group memory pointer. */
   8760     group_p = &oc->group_info[ep_info_p->group];
   8761 
   8762     if (1 != group_p->in_use) {
   8763         return BCM_E_NONE;
   8764     }    
   8765     cur =  *group_p->ep_list;
   8766 
   8767     /* Traverse the list and delete the matching node. */
   8768     while (NULL != cur) {
   8769         h_data_p = cur->ep_data_p;
   8770         if (NULL == h_data_p) {
   8771             LOG_ERROR(BSL_LS_BCM_OAM,
   8772                      (BSL_META_U(unit,
   8773                                  "OAM Error: Hash data is empty\n")));
   8774             return (BCM_E_INTERNAL);
   8775         }
   8776         if (ep_info_p->name  == h_data_p->name) { 
   8777             if (((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 
   8778                         (cur->ep_data_p->ep_id == ep_info_p->id)) || 
   8779                     ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) != 
   8780                      (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE))) {
   8781             } else {
   8782                 return BCM_E_PARAM;
   8783             }    
   8784         }
   8785         cur = cur->next;
   8786     }    
   8787     return (BCM_E_NONE);
   8788 }        
   8789 
   8790 /*
   8791  * Function:
   8792  *     _bcm_kt2_oam_endpoint_params_validate
   8793  * Purpose:
   8794  *     Validate an endpoint parameters.
   8795  * Parameters:
   8796  *     unit      - (IN) BCM device number
   8797  *     oc        - (IN) Pointer to OAM control structure.
   8798  *     hash_key  - (IN) Pointer to endpoint hash key value.
   8799  *     ep_info_p - (IN) Pointer to endpoint information.
   8800  * Retruns:
   8801  *     BCM_E_XXX
   8802  */
   8803 STATIC int
   8804 _bcm_kt2_oam_endpoint_params_validate(int unit,
   8805                                   _bcm_oam_control_t *oc,
   8806                                   _bcm_oam_hash_key_t *hash_key,
   8807                                   bcm_oam_endpoint_info_t *ep_info_p)
   8808 {
   8809     int                 rv;  /* Operation return status. */
   8810     _bcm_oam_hash_data_t h_stored_data;
   8811     int remote  = 0;
   8812 
   8813 
   8814     /* Get MEP remote endpoint status. */
   8815     remote = (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
   8816 
   8817     LOG_DEBUG(BSL_LS_BCM_OAM,
   8818               (BSL_META_U(unit,
   8819                           "OAM Info: "
   8820                           "_bcm_kt2_oam_endpoint_params_validate.\n")));
   8821 
   8822     /* Endpoint must be 802.1ag/Ethernet OAM type. */
   8823     if ((bcmOAMEndpointTypeEthernet != ep_info_p->type) 
   8824 #if defined(INCLUDE_BHH)
   8825         &&  /* BHH/Y.1731 OAM type */
   8826         (!BHH_EP_TYPE(ep_info_p))
   8827 #endif /* INCLUDE_BHH */
   8828         )
   8829     {
   8830         /* Other OAM types are not supported, return error. */
   8831         return BCM_E_UNAVAIL;
   8832     }
   8833 
   8834     /* Supported MDL level is 0 - 7. */
   8835     if ((!remote) &&
   8836         ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX))) {
   8837         LOG_ERROR(BSL_LS_BCM_OAM,
   8838                   (BSL_META_U(unit,
   8839                               "OAM Error: EP Level should be in the range(0-%d).\n"),
   8840                    _BCM_OAM_EP_LEVEL_MAX));
   8841         return (BCM_E_PARAM);
   8842      }
   8843 
   8844      /* Supported MEPID EP Name range is 1 - 8191, Skipping range check for MIP */
   8845      if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN)
   8846          || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) &&
   8847          !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) {
   8848         LOG_ERROR(BSL_LS_BCM_OAM,
   8849                   (BSL_META_U(unit,
   8850                               "OAM Error: MEP Name should be in the range(%d-%d).\n"),
   8851                    _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX));
   8852         return (BCM_E_PARAM);
   8853      }
   8854 
   8855     /*
   8856      * Check and return error if invalid flag bits are set for remote
   8857      * endpoint.
   8858      */
   8859     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)
   8860         && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) {
   8861 
   8862         return (BCM_E_PARAM);
   8863 
   8864     }
   8865 
   8866     /*
   8867      * Check and return error if MEPID is not unique within the group
   8868      */
   8869     if(_bcm_kt2_oam_mepid_validate(unit, ep_info_p)) {
   8870         LOG_ERROR(BSL_LS_BCM_OAM,
   8871                   (BSL_META_U(unit,
   8872                               "OAM Error: MEPID:%x passed is not unique in group %x\n"),
   8873                    ep_info_p->name, ep_info_p->group));
   8874 
   8875         return (BCM_E_EXISTS);
   8876     }
   8877 
   8878     /* For replace operation, endpoint ID is required. */
   8879     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)
   8880         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) {
   8881 
   8882         return (BCM_E_PARAM);
   8883 
   8884     }
   8885     /* Port based MEP is supported only for down MEP */
   8886     if ((0 == ep_info_p->vlan) && (0 == ep_info_p->inner_vlan) &&
   8887         (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) && (!remote)) {
   8888         return (BCM_E_PARAM);
   8889     }
   8890 
   8891     /* If it is a Port + CVlan based MEP and the
   8892      * CVlan (inner_vlan) is 0, return E_PARAM
   8893      */
   8894     if ((0 == ep_info_p->inner_vlan) &&
   8895         (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN)) {
   8896         return (BCM_E_PARAM);
   8897     }
   8898 
   8899     /* If it is a Port + S + CVlan based MEP and one of SVlan(vlan)
   8900      * or CVlan (inner_vlan) is 0, return E_PARAM
   8901      */
   8902     if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) &&
   8903         (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN)) {
   8904         return (BCM_E_PARAM);
   8905     }
   8906 
   8907     /* Validate endpoint index value. */
   8908     if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) {
   8909         _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id);
   8910     }
   8911 
   8912     /* MIP's are not created with non-zero ccm period */
   8913     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
   8914         (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) {
   8915          return (BCM_E_PARAM);
   8916     }
   8917 
   8918     /* Validate endpoint group id. */
   8919     _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group);
   8920 
   8921     rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group);
   8922     if (BCM_E_EXISTS != rv) {
   8923         LOG_ERROR(BSL_LS_BCM_OAM,
   8924                   (BSL_META_U(unit,
   8925                               "OAM Error: Group (GID:%d) does not exist.\n"),
   8926                    ep_info_p->group));
   8927         return (BCM_E_PARAM);
   8928     }
   8929   
   8930     if(soc_feature(unit, soc_feature_bhh)) {
   8931 #if defined(INCLUDE_BHH)
   8932         /*
   8933          * BHH can have multiple LSPs/endpoint on same port/MDL
   8934          * BHH does not have h/w support.  So, return here
   8935          */
   8936         if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) ||
   8937             (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) {
   8938             return (BCM_E_NONE);
   8939         }
   8940 #endif
   8941     }
   8942 
   8943 #if defined(KEY_PRINT)
   8944     _bcm_oam_hash_key_print(hash_key);
   8945 #endif
   8946 
   8947     /*
   8948      * Lookup using hash key value.
   8949      * Last param value '0' specifies keep the match entry.
   8950      * Value '1' would mean remove the entry from the table.
   8951      * Matched Params:
   8952      *      Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport.
   8953      */
   8954     rv = shr_htb_find(oc->ma_mep_htbl, *hash_key,
   8955                       (shr_htb_data_t *)&h_stored_data, 0);
   8956     if (BCM_SUCCESS(rv)
   8957         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   8958 
   8959         LOG_ERROR(BSL_LS_BCM_OAM,
   8960                   (BSL_META_U(unit,
   8961                               "OAM Error: Endpoint ID=%d %s.\n"),
   8962                    ep_info_p->id, bcm_errmsg(BCM_E_EXISTS)));
   8963 
   8964         /* Endpoint must not be in use expect for Replace operation. */
   8965         return (BCM_E_EXISTS);
   8966 
   8967     } else {
   8968 
   8969         LOG_DEBUG(BSL_LS_BCM_OAM,
   8970                   (BSL_META_U(unit,
   8971                               "OAM Info: Endpoint ID=%d Available. %s.\n"),
   8972                    ep_info_p->id, bcm_errmsg(rv)));
   8973 
   8974     }
   8975 
   8976     
   8977 
   8978     return (BCM_E_NONE);
   8979 }
   8980 
   8981 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type1_s {
   8982     uint32            start_index;
   8983     uint32            end_index;
   8984     soc_field_t       tag_source;
   8985     soc_field_t       data_processing;
   8986     soc_field_t       oam_processing;
   8987 } _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t;
   8988 
   8989 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_s {
   8990     uint32            start_index;
   8991     uint32            no_entries;
   8992     uint32            increment;
   8993     soc_field_t       tag_source_1;
   8994     soc_field_t       tag_source_2;
   8995     soc_field_t       data_processing;
   8996     soc_field_t       oam_processing;
   8997 } _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t;
   8998 
   8999 /*
   9000  * Function:
   9001  *     _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set
   9002  * Purpose:
   9003  *    Set the default values for ingress flexible oam domain control 
   9004  * Parameters:
   9005  *     unit - (IN) BCM device number
   9006  * Retruns:
   9007  *     BCM_E_XXX
   9008  * Index to the ing flexible domain control table is
   9009  *        index[5] = pars_inner_pri_tagged;
   9010  *        index[4] = pars_inner_tagged;
   9011  *        index[3] = pars_outer_tagged;
   9012  *        index[2] = vxlt_inner_tagged;
   9013  *        index[1] = vxlt_outer_tagged;
   9014  *        index[0] = svp_valid;
   9015  */
   9016 STATIC int
   9017 _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set(int unit)
   9018 {
   9019     int      rv = BCM_E_NONE;
   9020     ing_oam_flexible_domain_control_entry_t *ent_buf;
   9021     ing_oam_flexible_domain_control_entry_t *ent;
   9022     int      max_index = 0; 
   9023     int      index = 0; 
   9024     int      end_index = 0; 
   9025     int      loop_index = 0; 
   9026     int      entry_mem_size = 0;
   9027     int      entry_index = 0;
   9028     uint32   action_set = 1;
   9029 
   9030 
   9031     _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t c_vlan_ctrl_info[] = {
   9032       /* Set values for C VLAN MEP pre-VXLT actions */
   9033            /* Action for incoming untagged packets  */
   9034            { 4,   7, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 
   9035                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
   9036                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
   9037            /* Action for incoming single inner tagged but not 
   9038              priority tagged packets */
   9039            { 16, 23, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 
   9040                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
   9041                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
   9042            /* Action for incoming single inner priority tagged packets */
   9043            { 52, 55, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 
   9044                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
   9045                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
   9046        /* Set values for C VLAN MEP post-VXLT actions */
   9047            /* Action for incoming untagged packets */
   9048            { 4,   7, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 
   9049                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
   9050                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
   9051            /* Action for incoming single inner tagged but not 
   9052              priority tagged packets */
   9053            { 20, 23, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 
   9054                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
   9055                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
   9056            /* Action for incoming single inner priority tagged packets */
   9057            { 52, 55, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 
   9058                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
   9059                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
   9060            { 0 } /* table terminator */ 
   9061     };
   9062 
   9063     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t s_vlan_ctrl_info[] = {
   9064 
   9065         /* Set values for S VLAN MEP actions */
   9066            /* Action for incoming packet with single outer tagged after 
   9067               VXLT  */
   9068            { 2, 2, 8,  SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0,
   9069                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9070                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf},
   9071            /* Action for incoming packet with double tag after VXLT  */
   9072            { 6, 2, 8,  SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0,
   9073                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9074                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9075 
   9076        /* Set values for S+C VLAN MEP actions */
   9077            /* Action for incoming packet with double tag after VXLT  */
   9078            { 6, 2, 8,  SVLAN_CVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 
   9079                        SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 
   9080                        SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9081                        SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9082            { 6, 2, 8,  0, 0, 
   9083                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9084                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9085            { 6, 2, 8,  0, 0, 
   9086                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf, 
   9087                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf },
   9088            { 6, 2, 8,  0, 
   9089                        0, 
   9090                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf, 
   9091                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf },
   9092            { 0, 0 } /* table terminator */ 
   9093     };
   9094 
   9095     _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t *ctrl_info;
   9096     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *s_ctrl_info;
   9097 
   9098 
   9099     /* Read the table entries into the buffer. */
   9100     max_index = soc_mem_index_max(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm);
   9101 
   9102     entry_mem_size = sizeof(ing_oam_flexible_domain_control_entry_t);
   9103     /* Allocate buffer to store the DMAed table entries. */
   9104     ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1),
   9105                             "OAM flexible domain control table entry buffer");
   9106     if (NULL == ent_buf) {
   9107         return (BCM_E_MEMORY);
   9108     }
   9109     /* Initialize the entry buffer. */
   9110     sal_memset(ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1));
   9111 
   9112     /* Set action for C vlan */ 
   9113     for (index = 0; ;index++) { 
   9114         ctrl_info = &c_vlan_ctrl_info[index];
   9115         if(ctrl_info->start_index == 0) {
   9116             /* End of table */
   9117             break;
   9118         }
   9119         for (entry_index = ctrl_info->start_index; 
   9120              entry_index <= ctrl_info->end_index; entry_index++) {
   9121             ent = soc_mem_table_idx_to_pointer
   9122                     (unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9123                      ing_oam_flexible_domain_control_entry_t *,
   9124                      ent_buf, entry_index);
   9125 
   9126             soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9127                          (uint32 *)ent, ctrl_info->tag_source, &action_set);
   9128             soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9129                         (uint32 *)ent, ctrl_info->data_processing, &action_set);
   9130             soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9131                          (uint32 *)ent, ctrl_info->oam_processing, &action_set);
   9132         }
   9133     } 
   9134     /* Set action for S and S+C vlan */ 
   9135     for (index = 0; ;index++) { 
   9136         s_ctrl_info = &s_vlan_ctrl_info[index];
   9137         if(s_ctrl_info->start_index == 0) {
   9138             /* End of table */
   9139             break;
   9140         }
   9141         entry_index = s_ctrl_info->start_index;
   9142         loop_index = s_ctrl_info->start_index;
   9143         end_index = entry_index + s_ctrl_info->no_entries;
   9144         while (entry_index <= max_index) {  
   9145             for (; loop_index < end_index; loop_index++) {
   9146                 ent = soc_mem_table_idx_to_pointer(unit, 
   9147                                       ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9148                                       ing_oam_flexible_domain_control_entry_t *,
   9149                                       ent_buf, loop_index);
   9150                 if (s_ctrl_info->tag_source_1 != 0) {
   9151                     soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9152                          (uint32 *)ent, s_ctrl_info->tag_source_1, &action_set);
   9153                 }    
   9154                 if (s_ctrl_info->tag_source_2 != 0) {
   9155                     soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9156                          (uint32 *)ent, s_ctrl_info->tag_source_2, &action_set);
   9157                 }
   9158                 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9159                       (uint32 *)ent, s_ctrl_info->data_processing, &action_set);
   9160                 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9161                        (uint32 *)ent, s_ctrl_info->oam_processing, &action_set);
   9162             }
   9163             entry_index += s_ctrl_info->increment;
   9164             loop_index = entry_index;
   9165             end_index = (entry_index + s_ctrl_info->no_entries);
   9166         } 
   9167     }    
   9168 
   9169     rv = soc_mem_write_range(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9170                              MEM_BLOCK_ALL, 0, max_index, ent_buf); 
   9171     if (BCM_FAILURE(rv)) {
   9172         if (ent_buf) {
   9173             soc_cm_sfree(unit, ent_buf);
   9174         }
   9175         return rv;
   9176     }
   9177     if (ent_buf) {
   9178         soc_cm_sfree(unit, ent_buf);
   9179     }
   9180 
   9181     return rv;
   9182 }
   9183 /*
   9184  * Function:
   9185  *     _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set
   9186  * Purpose:
   9187  *    Set the default values for egress flexible oam domain control 
   9188  * Parameters:
   9189  *     unit - (IN) BCM device number
   9190  * Retruns:
   9191  *     BCM_E_XXX
   9192  */
   9193 
   9194 STATIC int
   9195 _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set(int unit)
   9196 {
   9197     int      rv = BCM_E_NONE;
   9198     egr_oam_flexible_domain_control_entry_t *egr_ent_buf;
   9199     egr_oam_flexible_domain_control_entry_t *ent;
   9200     int      max_index = 0; 
   9201     int      index = 0; 
   9202     int      end_index = 0; 
   9203     int      loop_index = 0; 
   9204     int      entry_mem_size = 0;
   9205     int      entry_index = 0;
   9206     uint32   action_set = 1;
   9207 
   9208     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t vlan_ctrl_info[] = {
   9209 
   9210           /*  CVLAN MEP before VXLT */
   9211            { 16, 2, 4, 0, 0, 
   9212                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
   9213                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
   9214           /* CVLAN MEP after VXLT */
   9215            { 4,  2, 8, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 
   9216                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
   9217                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
   9218           /* SVLAN MEP */
   9219            { 8,  8, 16, 0, 0, 
   9220                         SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9221                         SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9222           /* S+C VLAN MEP */
   9223            { 14, 2, 18, SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 0, 
   9224                         SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9225                         SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9226 
   9227            { 24, 8, 8, 0, 0, 
   9228                        SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9229                        SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9230            { 24, 8, 8, 0, 0, 
   9231                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
   9232                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
   9233            { 26, 2, 2, 0, 0, 
   9234                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9235                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9236            { 30, 2, 2, 0, 0, 
   9237                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
   9238                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
   9239            { 30, 2, 2, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 
   9240                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
   9241                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
   9242            { 0, 0 } /* table terminator */ 
   9243     };
   9244 
   9245     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *ctrl_info;
   9246 
   9247 
   9248     /* Read the table entries into the buffer. */
   9249     max_index = soc_mem_index_max(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm);
   9250 
   9251     entry_mem_size = sizeof(egr_oam_flexible_domain_control_entry_t);
   9252     /* Allocate buffer to store the DMAed table entries. */
   9253     egr_ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1),
   9254                             "OAM flexible domain control table entry buffer");
   9255     if (NULL == egr_ent_buf) {
   9256         return (BCM_E_MEMORY);
   9257     }
   9258     /* Initialize the entry buffer. */
   9259     sal_memset(egr_ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1));
   9260 
   9261     /* Set action for C, S and S+C vlan */ 
   9262     for (index = 0; ;index++) { 
   9263         ctrl_info = &vlan_ctrl_info[index];
   9264         if(ctrl_info->start_index == 0) {
   9265             /* End of table */
   9266             break;
   9267         }
   9268         entry_index = ctrl_info->start_index;
   9269         loop_index = ctrl_info->start_index;
   9270         end_index = entry_index + ctrl_info->no_entries;
   9271         while (entry_index <= max_index) {  
   9272             for (; loop_index < end_index; loop_index++) {
   9273                 ent = soc_mem_table_idx_to_pointer
   9274                     (unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9275                      egr_oam_flexible_domain_control_entry_t *,
   9276                      egr_ent_buf, loop_index);
   9277 
   9278                 if (ctrl_info->tag_source_1 != 0) {
   9279                     soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9280                            (uint32 *)ent, ctrl_info->tag_source_1, &action_set);
   9281                 }
   9282                 if (ctrl_info->tag_source_2 != 0) {
   9283                     soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9284                            (uint32 *)ent, ctrl_info->tag_source_2, &action_set);
   9285                 }
   9286                 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9287                         (uint32 *)ent, ctrl_info->data_processing, &action_set);
   9288                 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9289                          (uint32 *)ent, ctrl_info->oam_processing, &action_set);
   9290             }
   9291             entry_index += ctrl_info->increment;
   9292             loop_index = entry_index;
   9293             end_index = (entry_index + ctrl_info->no_entries);
   9294         } 
   9295     }    
   9296 
   9297     rv = soc_mem_write_range(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
   9298                              MEM_BLOCK_ALL, 0, max_index, egr_ent_buf); 
   9299     if (BCM_FAILURE(rv)) {
   9300         if (egr_ent_buf) {
   9301             soc_cm_sfree(unit, egr_ent_buf);
   9302         }
   9303         return rv;
   9304     }
   9305     if (egr_ent_buf) {
   9306         soc_cm_sfree(unit, egr_ent_buf);
   9307     }
   9308     return rv;
   9309 }
   9310 
   9311 
   9312 /*
   9313  * Function:
   9314  *     _bcm_kt2_oam_flexible_oam_domain_ctrl_set
   9315  * Purpose:
   9316  *    Set the default values for flexible oam domain control 
   9317  * Parameters:
   9318  *     unit - (IN) BCM device number
   9319  * Retruns:
   9320  *     BCM_E_XXX
   9321  */
   9322 STATIC int
   9323 _bcm_kt2_oam_flexible_oam_domain_ctrl_set(int unit)
   9324 {
   9325     int      rv = BCM_E_NONE;
   9326     /* Set ingress flexible domain control */
   9327     rv = _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set(unit); 
   9328     if (BCM_FAILURE(rv)) {
   9329         return (rv);
   9330     }
   9331 
   9332     /* Set egress flexible domain control */
   9333     rv = _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set(unit); 
   9334     if (BCM_FAILURE(rv)) {
   9335         return (rv);
   9336     }
   9337     return rv;
   9338 }
   9339 
   9340 
   9341 typedef struct _bcm_oam_ing_flexible_drop_ctrl_s {
   9342     soc_reg_t         drop_ctrl_reg;
   9343     uint32            vfp_drop_ctrl;
   9344     uint32            olp_drop_ctrl;
   9345     uint32            spst_drop_ctrl;
   9346     uint32            tag_drop_ctrl;
   9347     uint32            cvlan_bfr_vxlt_drop_ctrl;
   9348     uint32            cvlan_after_vxlt_drop_ctrl;
   9349     uint32            e2e_drop_ctrl;
   9350     uint32            vlan_drop_ctrl;
   9351     uint32            disc_drop_ctrl;
   9352 } _bcm_oam_ing_flexible_drop_ctrl_t;
   9353 
   9354 typedef struct _bcm_oam_egr_flexible_drop_ctrl_s {
   9355     soc_reg_t         drop_ctrl_reg;
   9356     uint32            egr_drop_ctrl;
   9357     uint32            evxlt_payload_drop_ctrl;
   9358     uint32            cvlan_after_vxlt_drop_ctrl;
   9359     uint32            cvlan_before_vxlt_drop_ctrl;
   9360 } _bcm_oam_egr_flexible_drop_ctrl_t;
   9361 
   9362 /*
   9363  * Function:
   9364  *     _bcm_kt2_oam_ing_flexible_drop_ctrl_set
   9365  * Purpose:
   9366  *    Set the default values for flexible ingress drop control 
   9367  * Parameters:
   9368  *     unit - (IN) BCM device number
   9369  * Retruns:
   9370  *     BCM_E_XXX
   9371  */
   9372 STATIC int
   9373 _bcm_kt2_oam_ing_flexible_drop_ctrl_set(int unit)
   9374 {
   9375     uint32 en_rval = 0;
   9376     int index = 0;
   9377     _bcm_oam_ing_flexible_drop_ctrl_t *flex_drop_info;
   9378     _bcm_oam_ing_flexible_drop_ctrl_t ing_flex_drop[] = {
   9379         { OAM_PORT_INTERFACE_DROP_CONTROLr, 0, 1, 0, 0, 0, 0, 1, 0, 0xe01c1 },
   9380         { OAM_C_INTERFACE_DROP_CONTROLr,    1, 1, 0, 0, 0, 1, 1, 0, 0xe01fd },
   9381         { OAM_S_INTERFACE_DROP_CONTROLr,    1, 1, 0, 1, 1, 1, 1, 5, 0xe01fd },
   9382         { OAM_S_C_INTERFACE_DROP_CONTROLr,  1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
   9383         { OAM_SVP_INTERFACE_DROP_CONTROLr,  1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
   9384         { 0 }, /* End of table */
   9385     };
   9386 
   9387     for (index = 0; ;index++) { 
   9388         flex_drop_info = &ing_flex_drop[index];
   9389         if(flex_drop_info->drop_ctrl_reg == 0) {
   9390             /* End of table */
   9391             break;
   9392         }
   9393 
   9394 	SOC_IF_ERROR_RETURN(soc_reg32_get(unit, flex_drop_info->drop_ctrl_reg, 
   9395                       REG_PORT_ANY, 0, &en_rval));
   9396         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9397                             &en_rval, VFP_DROP_CTRLf,
   9398                             flex_drop_info->vfp_drop_ctrl);
   9399         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9400                             &en_rval, OLP_ERROR_DROP_CTRLf,
   9401                             flex_drop_info->olp_drop_ctrl);
   9402         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9403                             &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf,
   9404                             flex_drop_info->spst_drop_ctrl);
   9405         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9406                             &en_rval, DISCARD_TAG_UNTAG_CTRLf,
   9407                             flex_drop_info->tag_drop_ctrl);
   9408         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9409                             &en_rval, 
   9410                             CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf,
   9411                             flex_drop_info->cvlan_bfr_vxlt_drop_ctrl);
   9412         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9413                             &en_rval, 
   9414                             CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf,
   9415                             flex_drop_info->cvlan_after_vxlt_drop_ctrl);
   9416         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9417                             &en_rval, ERRORED_E2E_PKT_DROP_CTRLf,
   9418                             flex_drop_info->e2e_drop_ctrl);
   9419         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9420                             &en_rval, VLAN_DROP_VECTOR_CTRLf,
   9421                             flex_drop_info->vlan_drop_ctrl);
   9422         soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9423                             &en_rval, DISC_DROP_VECTOR_CTRLf,
   9424                             flex_drop_info->disc_drop_ctrl);
   9425         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, flex_drop_info->drop_ctrl_reg,
   9426                             REG_PORT_ANY, 0, en_rval));
   9427     }
   9428     return (BCM_E_NONE);
   9429 }
   9430 
   9431 /*
   9432  * Function:
   9433  *     _bcm_kt2_oam_egr_flexible_drop_ctrl_set
   9434  * Purpose:
   9435  *    Set the default values for flexible egress drop control 
   9436  * Parameters:
   9437  *     unit - (IN) BCM device number
   9438  * Retruns:
   9439  *     BCM_E_XXX
   9440  */
   9441 STATIC int
   9442 _bcm_kt2_oam_egr_flexible_drop_ctrl_set(int unit)
   9443 {
   9444     uint64 en_rval, set_val;
   9445     int index = 0;
   9446 
   9447     _bcm_oam_egr_flexible_drop_ctrl_t *flex_drop_info;
   9448     _bcm_oam_egr_flexible_drop_ctrl_t egr_flex_drop[] = {
   9449         { EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r, 0x1e0787d, 1, 1, 1 },
   9450         { EGR_OAM_C_INTERFACE_DROP_CONTROL_64r,    0x1e0787c, 1, 1, 0 },
   9451         { EGR_OAM_S_INTERFACE_DROP_CONTROL_64r,    0x1e06848, 1, 0, 0 },
   9452         { EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r,  0x1e06048, 1, 0, 0 },
   9453         { EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r,  0x1e06048, 1, 0, 0 },
   9454         { 0 }, /* End of table */
   9455     };
   9456 
   9457     COMPILER_64_ZERO(en_rval); 
   9458 
   9459     for (index = 0; ;index++) { 
   9460         flex_drop_info = &egr_flex_drop[index];
   9461         if(flex_drop_info->drop_ctrl_reg == 0) {
   9462             /* End of table */
   9463             break;
   9464         }
   9465 
   9466 	SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 
   9467                                           REG_PORT_ANY, 0, &en_rval));
   9468         
   9469         COMPILER_64_SET(set_val, 0, flex_drop_info->egr_drop_ctrl);
   9470 
   9471         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9472                             &en_rval, EGR_DROP_VECTOR_CTRLf,
   9473                             set_val);
   9474 
   9475         COMPILER_64_SET(set_val, 0, flex_drop_info->evxlt_payload_drop_ctrl);
   9476         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9477                             &en_rval, 
   9478                             EVXLT_APPLIED_TO_PAYLOAD_VXLT_MISS_DROP_CTRLf,
   9479                             set_val);
   9480 
   9481         COMPILER_64_SET(set_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl);
   9482         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9483            &en_rval, 
   9484            EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf,
   9485            set_val);
   9486 
   9487         COMPILER_64_SET(set_val, 0, flex_drop_info->cvlan_before_vxlt_drop_ctrl);
   9488         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
   9489           &en_rval,
   9490           EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf,
   9491           set_val);
   9492 
   9493         SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg,
   9494                             REG_PORT_ANY, 0, en_rval));
   9495     }
   9496     return (BCM_E_NONE);
   9497 }
   9498 
   9499 /*
   9500  * Function:
   9501  *     _bcm_kt2_oam_flexible_drop_ctrl_set
   9502  * Purpose:
   9503  *    Set the default values for flexible ingress and egress drop control 
   9504  * Parameters:
   9505  *     unit - (IN) BCM device number
   9506  * Retruns:
   9507  *     BCM_E_XXX
   9508  */
   9509 STATIC int
   9510 _bcm_kt2_oam_flexible_drop_ctrl_set(int unit)
   9511 {
   9512     int rv = BCM_E_NONE;
   9513     /* Set ingress flexible drop control */
   9514     rv = _bcm_kt2_oam_ing_flexible_drop_ctrl_set(unit); 
   9515     if (BCM_FAILURE(rv)) {
   9516         return (rv);
   9517     }
   9518 
   9519     /* Set egress flexible drop control */
   9520     rv = _bcm_kt2_oam_egr_flexible_drop_ctrl_set(unit); 
   9521     if (BCM_FAILURE(rv)) {
   9522         return (rv);
   9523     }
   9524     return rv;
   9525 }
   9526 
   9527 /*
   9528  * Function:
   9529  *     _bcm_kt2_oam_s_intf_passive_proc_ctrl_set
   9530  * Purpose:
   9531  *    Set the default values for s-interface passive processing control 
   9532  * Parameters:
   9533  *     unit - (IN) BCM device number
   9534  * Retruns:
   9535  *     BCM_E_XXX
   9536  */
   9537 STATIC int
   9538 _bcm_kt2_oam_s_intf_passive_proc_ctrl_set(int unit)
   9539 {
   9540     uint32 en_rval = 0;
   9541     /* Set ingress s_intf passive processing control */
   9542     SOC_IF_ERROR_RETURN(
   9543         soc_reg32_get(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
   9544                       REG_PORT_ANY, 0, &en_rval));
   9545 
   9546     soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
   9547                         &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf,
   9548                         0x1);
   9549     /* Set ENIFILTER_DROP, INVALID_TPID_DROP and INVALID_VLAN_DROP  */
   9550     soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
   9551                         &en_rval, VLAN_DROP_VECTOR_CTRLf,
   9552                         0x7);
   9553     SOC_IF_ERROR_RETURN(
   9554         soc_reg32_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr,
   9555                         REG_PORT_ANY, 0, en_rval));
   9556 
   9557     en_rval = 0;
   9558     /* Set egress s_intf passive processing control */
   9559     SOC_IF_ERROR_RETURN(
   9560         soc_reg32_get(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
   9561                       REG_PORT_ANY, 0, &en_rval));
   9562 
   9563 
   9564     /* Set NOT_VLAN_MEMBER_DROP, STG_BLOCK_DROP, STG_DISABLE_DROP 
   9565        For details - refer to EGR_DROP_VECTOR */ 
   9566     soc_reg_field_set(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
   9567                         &en_rval, EGR_DROP_VECTOR_CTRLf,
   9568                         0x1030);
   9569 
   9570     SOC_IF_ERROR_RETURN(soc_reg32_set(unit,
   9571                         EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr,
   9572                         REG_PORT_ANY, 0, en_rval));
   9573     return (BCM_E_NONE);
   9574 }
   9575 
   9576 /*
   9577  * Function:
   9578  *     _bcm_kt2_oam_hg_olp_enable
   9579  * Purpose:
   9580  *    Enable OLP handling on HG ports 
   9581  * Parameters:
   9582  *     unit - (IN) BCM device number
   9583  * Retruns:
   9584  *     BCM_E_XXX
   9585  */
   9586 STATIC int
   9587 _bcm_kt2_oam_hg_olp_enable(int unit)
   9588 {
   9589     bcm_pbmp_t ports;
   9590     bcm_port_t port;
   9591     iarb_ing_physical_port_entry_t entry;
   9592 
   9593     BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit));
   9594     PBMP_ITER(ports, port) {
   9595         if (IS_HG_PORT(unit, port)) {
   9596             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 
   9597                                              MEM_BLOCK_ANY, port, &entry));
   9598             soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 
   9599                                                     OLP_ENABLEf, 1);
   9600             SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 
   9601                                               MEM_BLOCK_ALL, port, &entry));
   9602         } else {
   9603             soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 
   9604                                                     OLP_ENABLEf, 0);
   9605         }
   9606         SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 
   9607                                               MEM_BLOCK_ALL, port, &entry));
   9608     }
   9609     return (BCM_E_NONE);
   9610 }
   9611 
   9612 /*
   9613  * Function:
   9614  *     _bcm_kt2_oam_olp_header_type_mapping_set
   9615  * Purpose:
   9616  *    Set default olp header type mapping
   9617  * Parameters:
   9618  *     unit - (IN) BCM device number
   9619  * Retruns:
   9620  *     BCM_E_XXX
   9621  * MEP_TYPE      COMPRESSED_HDR_TYPE       HDR_TYPE          HDR_SUBTYPE
   9622  *
   9623  * ==========================================================================
   9624  *  Downmep/IFP      3'b000                8'd1(L2_HDR)      8'd0(NULL)
   9625  *  Downmep/IFP      3'b001                8'd0(OAM_HDR)     8'd2(CCM/BHH-CCM)
   9626  *  Downmep/IFP      3'b010                8'd0(OAM_HDR)     8'd3(BFD)
   9627  *  Downmep/IFP      3'b011                8'd0(OAM_HDR)     8'd4(LM/DM)
   9628  *  Upmep            3'b000                N/A               N/A
   9629  *  Upmep            3'b001                8'd0(OAM_HDR)     8'd5(CCM)
   9630  *  Upmep            3'b010                N/A               N/A
   9631  *  Upmep            3'b011                8'd0(OAM_HDR)     8'd6(LM/DM)
   9632  */
   9633 STATIC int
   9634 _bcm_kt2_oam_olp_header_type_mapping_set(int unit)
   9635 {
   9636     int                                 index = 0;
   9637     egr_olp_header_type_mapping_entry_t entry;
   9638 
   9639     for (index = 0; index < kt2_olp_hdr_type_count; index++) {
   9640 
   9641         if (kt2_olp_hdr_type_mapping[index].reuse) {
   9642             continue;
   9643         }
   9644 
   9645         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
   9646                                                      &entry,
   9647                                                      HDR_TYPEf,
   9648                                                      _BCM_KT2_OLP_OAM_HDR);
   9649 
   9650         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(
   9651                                             unit,
   9652                                             &entry,
   9653                                             HDR_SUBTYPEf,
   9654                                             kt2_olp_hdr_type_mapping[index].subtype);
   9655 
   9656         SOC_IF_ERROR_RETURN(
   9657               WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(
   9658                                        unit,
   9659                                        MEM_BLOCK_ALL,
   9660                                        kt2_olp_hdr_type_mapping[index].mem_index,
   9661                                        &entry));
   9662     }
   9663 
   9664     /* Program L2 HDR at the first entry */
   9665     memset(&entry, 0, sizeof(entry));
   9666     soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
   9667                                                  &entry,
   9668                                                  HDR_TYPEf,
   9669                                                  _BCM_KT2_OLP_L2_HDR);
   9670     SOC_IF_ERROR_RETURN(
   9671              WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(unit,
   9672                                                 MEM_BLOCK_ALL,
   9673                                                 0,
   9674                                                 &entry));
   9675     return BCM_E_NONE;
   9676 }
   9677 
   9678 /*
   9679  * Function: _bcm_kt2_oam_olp_fp_hw_index_get
   9680  *
   9681  * Purpose:
   9682  *     Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype
   9683  * Parameters:
   9684  *     unit - (IN) BCM device number
   9685  * Returns:
   9686  *     BCM_E_XXX
   9687  */
   9688 int
   9689 _bcm_kt2_oam_olp_fp_hw_index_get(int unit,
   9690                                   bcm_field_olp_header_type_t olp_hdr_type,
   9691                                   int *hwindex)
   9692 {
   9693     int index;
   9694 
   9695     switch (olp_hdr_type) {
   9696         /* KT2 does not allow IFP to program UpMEP header type for
   9697          * ADD_OLP_HEADER action, as the OLP_HDR_TYPE_COMPRESSED in
   9698          * FP_POLICY_TABLE is not wide enough to index Up MEP subtypes
   9699          * in EGR_OLP_HEADER_TYPE_MAPPING
   9700          */
   9701 
   9702         case bcmFieldOlpHeaderTypeEthOamUpMepCcm:
   9703         case bcmFieldOlpHeaderTypeEthOamUpMepLm:
   9704         case bcmFieldOlpHeaderTypeEthOamUpMepDm:
   9705             return BCM_E_PARAM;
   9706 
   9707         default:
   9708             break;
   9709     }
   9710 
   9711     for (index = 0; index < kt2_olp_hdr_type_count; index++) {
   9712         if (kt2_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) {
   9713             *hwindex = kt2_olp_hdr_type_mapping[index].mem_index;
   9714             return BCM_E_NONE;
   9715         }
   9716     }
   9717 
   9718     return BCM_E_NOT_FOUND;
   9719 }
   9720 
   9721 /*
   9722  * Function: _bcm_kt2_oam_olp_hw_index_olp_type_get
   9723  *
   9724  * Purpose:
   9725  *     Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED
   9726  * Parameters:
   9727  *     unit - (IN) BCM device number
   9728  * Returns:
   9729  *     BCM_E_XXX
   9730  */
   9731 int
   9732 _bcm_kt2_oam_olp_hw_index_olp_type_get(int unit,
   9733                                         int hwindex,
   9734                                         bcm_field_olp_header_type_t *olp_hdr_type)
   9735 {
   9736     int index;
   9737 
   9738     for (index = 0; index < kt2_olp_hdr_type_count; index++) {
   9739         if (kt2_olp_hdr_type_mapping[index].mem_index == hwindex) {
   9740 
   9741             *olp_hdr_type =
   9742                       kt2_olp_hdr_type_mapping[hwindex].field_olp_hdr_type;
   9743 
   9744             return BCM_E_NONE;
   9745         }
   9746     }
   9747     return BCM_E_PARAM;
   9748 }
   9749 
   9750 /*
   9751  * Function:
   9752  *     _bcm_kt2_oam_drop_ctrl_set
   9753  * Purpose:
   9754  *    Set OAM drop control to not to drop wrong version OAM packets 
   9755  * Parameters:
   9756  *     unit - (IN) BCM device number
   9757  * Retruns:
   9758  *     BCM_E_XXX
   9759  */
   9760 STATIC int
   9761 _bcm_kt2_oam_drop_ctrl_set(int unit) 
   9762 {
   9763     uint32   drop_ctrl = 0;
   9764     soc_reg_field_set(unit, OAM_DROP_CONTROLr, &drop_ctrl,
   9765                       IFP_OAM_UNKNOWN_OPCODE_VERSION_DROPf, 0);
   9766     
   9767     SOC_IF_ERROR_RETURN(WRITE_OAM_DROP_CONTROLr(unit, drop_ctrl));
   9768     return (BCM_E_NONE);
   9769 }
   9770 
   9771 /*
   9772  * Function:
   9773  *     _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default
   9774  * Purpose:
   9775  *     Set OAM LM cng and cpu data control
   9776  * Parameters:
   9777  *     unit - (IN) BCM device number
   9778  * Retruns:
   9779  *     BCM_E_XXX
   9780  */
   9781 STATIC int
   9782 _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default(int unit) 
   9783 {
   9784     uint32   rval = 0;
   9785     /* Set OAM LM CNG control such that
   9786        1. All colored packets are counted, 
   9787        2. Use LM_COLOR_MODE bit to qualify pre FP CNG for UPMEP TX 
   9788           counters in IP
   9789        3. Use LM_COLOR_MODE bit to qualify post FP CNG for DOWNMEP RX 
   9790           counters in IP     
   9791     */
   9792     soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9793                       LM_COLOR_MODEf, 1);
   9794     soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9795                       UPMEP_TX_CNG_SOURCEf, 1);
   9796     soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9797                       DOWNMEP_RX_CNG_SOURCEf, 0);
   9798     SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CNG_CONTROLr(unit, rval));
   9799 
   9800     rval = 0;
   9801     /* include all colored packets for LM accounting on egress side */
   9802     soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval,
   9803                                             LM_COLOR_MODEf, 1);
   9804     SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, rval));
   9805 
   9806     rval = 0;
   9807 
   9808     /* Set OAM_LM_CPU_DATA_CONTROL to not to count
   9809        CPU generated data packets for loss measurement */
   9810     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9811                                  OAM_LCPU_TX_CNT_DISABLEf, 1);
   9812     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9813                                  OAM_LCPU_RX_CNT_DISABLEf, 1);
   9814     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9815                                  OAM_SRCPORT0_TX_CNT_DISABLEf, 1);
   9816     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9817                                  OAM_SRCPORT0_RX_CNT_DISABLEf, 1);
   9818     SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval));
   9819 
   9820     return (BCM_E_NONE);
   9821 } 
   9822 /*
   9823  * Function:
   9824  *     _bcm_kt2_oam_lm_cng_cpu_ctrl_set
   9825  * Purpose:
   9826  *     Set OAM LM cng and cpu data control
   9827  * Parameters:
   9828  *     unit - (IN) BCM device number
   9829  * Retruns:
   9830  *     BCM_E_XXX
   9831  */
   9832 STATIC int
   9833 _bcm_kt2_oam_lm_cng_cpu_ctrl_set (int unit, bcm_oam_endpoint_info_t *ep) 
   9834 {
   9835     uint32   rval = 0;
   9836     uint32   egr_rval = 0;
   9837     int      up_mep = 0;
   9838     int      color_mode = 0;
   9839     int      cng_source = 0;
   9840     int      count_pkt = 1;
   9841     if (ep->lm_flags) {
   9842         /* read LM CNG register */
   9843         SOC_IF_ERROR_RETURN(READ_OAM_LM_CNG_CONTROLr(unit, &rval));
   9844         SOC_IF_ERROR_RETURN(READ_EGR_OAM_LM_CNG_CONTROLr(unit, &egr_rval));
   9845 
   9846         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_GREEN_AND_YELLOW) {
   9847             color_mode = 1;
   9848         }  
   9849         soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9850                           LM_COLOR_MODEf, color_mode);
   9851         soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &egr_rval,
   9852                           LM_COLOR_MODEf, color_mode);
   9853 
   9854         if (ep->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9855             up_mep = 1;
   9856         }
   9857         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_POST_TRAFFIC_CONDITIONING) {
   9858             cng_source = 1;
   9859         }
   9860         if (up_mep) {
   9861             soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9862                               UPMEP_TX_CNG_SOURCEf, cng_source);
   9863         } else {
   9864             soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval,
   9865                                   DOWNMEP_RX_CNG_SOURCEf, cng_source);
   9866         }
   9867          /* write back the registrs */  
   9868         SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CNG_CONTROLr(unit, rval));
   9869         SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, egr_rval));
   9870          /* Read LM CPU data control */
   9871         SOC_IF_ERROR_RETURN(READ_OAM_LM_CPU_DATA_CONTROLr(unit, &rval));
   9872         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_RX_PKT) {
   9873             count_pkt = 0; 
   9874         }
   9875         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9876                           OAM_LCPU_RX_CNT_DISABLEf, count_pkt);
   9877         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9878                           OAM_SRCPORT0_RX_CNT_DISABLEf, count_pkt);
   9879 
   9880         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_TX_PKT) {
   9881             count_pkt = 0; 
   9882         } else {
   9883             count_pkt = 1; 
   9884         }
   9885         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9886                           OAM_LCPU_TX_CNT_DISABLEf, count_pkt);
   9887         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
   9888                           OAM_SRCPORT0_TX_CNT_DISABLEf, count_pkt);
   9889         SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval));
   9890     }
   9891     return (BCM_E_NONE);
   9892 }
   9893 
   9894 /*
   9895  * Function:
   9896  *     _bcm_kt2_oam_olp_magic_port_set
   9897  * Purpose:
   9898  *     Set Magic port used in OLP-XGS communication 
   9899  * Parameters:
   9900  *     unit - (IN) BCM device number
   9901  * Retruns:
   9902  *     BCM_E_XXX
   9903  */
   9904 STATIC int
   9905 _bcm_kt2_oam_olp_magic_port_set(int unit)
   9906 {
   9907     uint64 rval, set_val;
   9908     int    modid;
   9909     COMPILER_64_ZERO(rval); 
   9910     /* configure modid and the magic port */
   9911     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   9912     SOC_IF_ERROR_RETURN(READ_IARB_OLP_CONFIG_1r(unit, &rval));
   9913 
   9914     COMPILER_64_SET(set_val, 0, modid);
   9915     soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_MODIDf, set_val);
   9916     COMPILER_64_SET(set_val, 0, _BCM_OAM_OLP_COMMUNICATION_PORT);
   9917     soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_PORT_NUMf, set_val);
   9918 
   9919     SOC_IF_ERROR_RETURN(WRITE_IARB_OLP_CONFIG_1r(unit, rval));
   9920     return (BCM_E_NONE);
   9921 }
   9922 
   9923 /*
   9924  * Function:
   9925  *     _bcm_kt2_oam_macsa_zero_check_disable
   9926  * Purpose:
   9927  *     Disable MACSA Zero check  
   9928  * Parameters:
   9929  *     unit - (IN) BCM device number
   9930  * Retruns:
   9931  *     BCM_E_XXX
   9932  */
   9933 STATIC int
   9934 _bcm_kt2_oam_macsa_zero_check_disable(int unit)
   9935 {
   9936     uint32   rval = 0;
   9937     soc_reg_field_set(unit, OAM_CONTROLr, &rval,
   9938                       MACSA_ZERO_CHECK_ENABLEf, 0);
   9939     SOC_IF_ERROR_RETURN(WRITE_OAM_CONTROLr(unit, rval));
   9940     soc_reg_field_set(unit, EGR_OAM_CONTROLr, &rval,
   9941                       MACSA_ZERO_CHECK_ENABLEf, 0);
   9942     SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_CONTROLr(unit, rval));
   9943     return (BCM_E_NONE);
   9944 }
   9945 
   9946 /*
   9947  * Function:
   9948  *     _bcm_kt2_oam_endpoint_cleanup
   9949  * Purpose:
   9950  *     Free all the counters and the indexes allocated on endpoint create
   9951  *     failure  
   9952  * Parameters:
   9953  *     unit - (IN) BCM device number
   9954  *     upmep- (IN) UpMep/DownMep
   9955  *     hash_key (IN)
   9956  *     hash_data (IN) Pointer to endpoint hash data
   9957  * Retruns:
   9958  *     BCM_E_XXX
   9959  */
   9960 void
   9961 _bcm_kt2_oam_endpoint_cleanup(int unit, int upmep, 
   9962                               _bcm_oam_hash_key_t  hash_key,
   9963                               _bcm_oam_hash_data_t *hash_data)
   9964 {
   9965     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   9966     int                  rv = BCM_E_NONE;
   9967     _bcm_oam_hash_data_t h_data_stored;     /* Stored hash data.            */
   9968     uint8              active_mdl = 0;
   9969 
   9970     rv = _bcm_kt2_oam_control_get(unit, &oc);
   9971     if (BCM_FAILURE(rv)) {
   9972         return;
   9973     }
   9974     if (upmep) {
   9975         /* Delete l3_entry, if already added */
   9976         rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, hash_data, 
   9977                                                          &active_mdl);
   9978         /* Update Ingress MP group table(L3_ENTRY) */
   9979         rv = _bcm_kt2_oam_l3_entry_destroy(unit, hash_data, &active_mdl);
   9980     } else {
   9981         /* Update Ingress MP group table(L3_ENTRY) */
   9982         rv = _bcm_kt2_oam_l3_entry_destroy(unit, hash_data, &active_mdl);
   9983         /* Delete l3_entry, if already added */
   9984         rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, hash_data, 
   9985                                                          &active_mdl);
   9986     }
   9987     /* return rx & tx counters allocated if any */
   9988     rv =_bcm_kt2_oam_free_counter(unit, hash_data);
   9989 
   9990     /* Clear opcode profile entry, if any */
   9991     if (hash_data->profile_index != _BCM_OAM_INVALID_INDEX) { 
   9992         if (upmep) {
   9993             rv = soc_profile_mem_delete(unit, 
   9994                                         &oc->egr_oam_opcode_control_profile, 
   9995                                         hash_data->profile_index);
   9996         } else {
   9997             rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile, 
   9998                                     hash_data->profile_index);
   9999         }
  10000     }
  10001     /* Clear dglp profile, if any */
  10002     if (hash_data->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) {
  10003         if (upmep) {
  10004             rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 
  10005                                     hash_data->dglp1_profile_index);
  10006         } else {
  10007             rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 
  10008                                     hash_data->dglp1_profile_index);
  10009         }
  10010     }
  10011  
  10012     if (hash_data->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) {
  10013         if (upmep) {
  10014             rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 
  10015                                     hash_data->dglp2_profile_index);
  10016         } else {
  10017             rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 
  10018                                     hash_data->dglp2_profile_index);
  10019         }
  10020     }
  10021     /* Clear Service pri map profile, if configured */
  10022     if (hash_data->pri_map_index != _BCM_OAM_INVALID_INDEX) {
  10023         rv = soc_profile_mem_delete(unit, &oc->ing_service_pri_map, 
  10024                                     hash_data->pri_map_index);
  10025 
  10026     }
  10027     if (hash_data->egr_pri_map_index != _BCM_OAM_INVALID_INDEX) {
  10028         rv = soc_profile_mem_delete(unit, &oc->egr_service_pri_map, 
  10029                                     hash_data->egr_pri_map_index);
  10030     }
  10031     /* Decrement TPID ref count, if already incremented */
  10032     if (hash_data->outer_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  10033         rv = _bcm_kt2_tpid_entry_delete(unit, 
  10034                                         hash_data->outer_tpid_profile_index,
  10035                                         BCM_OAM_TPID_TYPE_OUTER);
  10036     }
  10037     if (hash_data->subport_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  10038         rv = _bcm_kt2_tpid_entry_delete(unit, 
  10039                                         hash_data->subport_tpid_profile_index,
  10040                                         BCM_OAM_TPID_TYPE_SUBPORT);
  10041     }
  10042     if (hash_data->inner_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  10043         rv = _bcm_kt2_tpid_entry_delete(unit, 
  10044                                         hash_data->inner_tpid_profile_index,
  10045                                         BCM_OAM_TPID_TYPE_INNER);
  10046     }
  10047     
  10048     /* It might already have been deleted as well. 
  10049      * So just log it as debug, in case it fails */
  10050     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, hash_data);
  10051     if (BCM_FAILURE(rv)) {
  10052         LOG_DEBUG(BSL_LS_BCM_OAM,
  10053                   (BSL_META_U(unit,
  10054                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  10055                                " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv)));
  10056     }
  10057 #if defined(INCLUDE_BHH)
  10058     if((hash_data->type == bcmOAMEndpointTypeBHHMPLS) ||
  10059        (hash_data->type == bcmOAMEndpointTypeBHHMPLSVccv)) {
  10060         shr_idxres_list_free(oc->bhh_pool,
  10061                              BCM_OAM_BHH_GET_UKERNEL_EP(hash_data->ep_id));
  10062     } else
  10063 #endif
  10064     {
  10065         if (1 == hash_data->is_remote) {
  10066             /* If remote endpoint, return index to remp pool */
  10067             shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index);
  10068         } else {
  10069             /* If local endpoint, return index to lmep pool */
  10070             shr_idxres_list_free(oc->lmep_pool, hash_data->local_tx_index);
  10071         }
  10072 
  10073         /* return index to mep pool */
  10074         shr_idxres_list_free(oc->mep_pool, hash_data->ep_id);
  10075     }
  10076     /* Return entry to hash data entry to free pool. */
  10077     shr_htb_find(oc->ma_mep_htbl, hash_key, 
  10078                                  (shr_htb_data_t *)&h_data_stored, 1);
  10079 
  10080     /* Clear contents of hash data element. */
  10081     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  10082 }
  10083 
  10084 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
  10085 void
  10086 _bcm_kt2_oam_group_info_dump(int unit, bcm_oam_group_t group_index,
  10087                              _bcm_oam_group_data_t *group_p)
  10088 {
  10089     int                     rv;
  10090     bcm_oam_group_info_t    group_info;
  10091 
  10092     /* Initialize the group information structure. */
  10093     bcm_oam_group_info_t_init(&group_info);
  10094 
  10095     /* Retrieve group information and set in group_info structure. */
  10096     rv = _bcm_kt2_oam_get_group(unit, group_index, group_p, &group_info);
  10097     if (BCM_FAILURE(rv)) {
  10098         LOG_ERROR(BSL_LS_BCM_OAM,
  10099                   (BSL_META_U(unit,
  10100                               "OAM(unit %d) Error: _bcm_kt2_oam_group_info_dump"
  10101                               " (GID=%d) - %s.\n"),
  10102                               unit, group_index, bcm_errmsg(rv)));
  10103         return;
  10104     }
  10105     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  10106     LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index));
  10107     LOG_CLI((BSL_META_U(unit,"Group Name =  %s\r\n"), group_info.name));
  10108     LOG_CLI((BSL_META_U(unit,"Flags =  %d\r\n"), group_info.flags));
  10109     LOG_CLI((BSL_META_U(unit,"Faults =  %d\r\n"), group_info.faults));
  10110     LOG_CLI((BSL_META_U(unit,"Persistent_faults =  %d\r\n"),
  10111                               group_info.persistent_faults));
  10112     LOG_CLI((BSL_META_U(unit,"clear_persistent_faults =  %d\r\n"),
  10113                               group_info.clear_persistent_faults));
  10114     LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority =  %d\r\n"),
  10115                               group_info.lowest_alarm_priority));
  10116     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  10117 }
  10118 
  10119 void
  10120 _bcm_kt2_oam_hash_data_dump(int unit, _bcm_oam_hash_data_t *h_data_p)
  10121 {
  10122     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  10123     LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id));
  10124     LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type));
  10125     LOG_CLI((BSL_META_U(unit,"In use = %d\r\n"),h_data_p->in_use));
  10126     LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote));
  10127     LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name));
  10128     LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level));
  10129     LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan));
  10130     LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan));
  10131     LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport));
  10132     LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp));
  10133     LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp));
  10134     LOG_CLI((BSL_META_U(unit,"Tx ena = %d\r\n"),h_data_p->local_tx_enabled));
  10135     LOG_CLI((BSL_META_U(unit,"Rx ena = %d\r\n"),h_data_p->local_rx_enabled));
  10136     LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index));
  10137     LOG_CLI((BSL_META_U(unit,"Remote idx = %d\r\n"),h_data_p->remote_index));
  10138     LOG_CLI((BSL_META_U(unit,"LM ctr idx = %d\r\n"),h_data_p->lm_counter_index));
  10139     LOG_CLI((BSL_META_U(unit,"Pri map idx = %d\r\n"),h_data_p->pri_map_index));
  10140     LOG_CLI((BSL_META_U(unit,"Profile Idx = %d\r\n"),h_data_p->profile_index));
  10141     LOG_CLI((BSL_META_U(unit,"Local Tx index = %d\r\n"),h_data_p->local_tx_index));
  10142     LOG_CLI((BSL_META_U(unit,"Local Rx index = %d\r\n"),h_data_p->local_rx_index));
  10143     LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp));
  10144     LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags));
  10145     LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2));
  10146     LOG_CLI((BSL_META_U(unit,"Vfp_entry = 0x%x\r\n"),h_data_p->vfp_entry));
  10147     LOG_CLI((BSL_META_U(unit,"Fp_entry_tx = 0x%x\r\n"),h_data_p->fp_entry_tx));
  10148     LOG_CLI((BSL_META_U(unit,"Fp_entry_rx = 0x%x\r\n"),h_data_p->fp_entry_rx));
  10149     LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period));
  10150     LOG_CLI((BSL_META_U(unit,"Opcode flags = 0x%x\r\n"),h_data_p->opcode_flags));
  10151     LOG_CLI((BSL_META_U(unit,"TS format = %d\r\n"),h_data_p->ts_format));
  10152     LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label));
  10153     LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri));
  10154     LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if));
  10155     LOG_CLI((BSL_META_U(unit,"Int pri = %d\r\n"),h_data_p->int_pri));
  10156     LOG_CLI((BSL_META_U(unit,"Trunk index = %d\r\n"),h_data_p->trunk_index));
  10157     LOG_CLI((BSL_META_U(unit,"Domain = %d\r\n"),h_data_p->oam_domain));
  10158     LOG_CLI((BSL_META_U(unit,"Egr pri map idx = %d\r\n"),h_data_p->egr_pri_map_index));
  10159     LOG_CLI((BSL_META_U(unit,"Rx ctr = %d\r\n"),h_data_p->rx_ctr));
  10160     LOG_CLI((BSL_META_U(unit,"Tx ctr = %d\r\n"),h_data_p->tx_ctr));
  10161     LOG_CLI((BSL_META_U(unit,"src pp port = %d\r\n"),h_data_p->src_pp_port));
  10162     LOG_CLI((BSL_META_U(unit,"dst pp port = %d\r\n"),h_data_p->dst_pp_port));
  10163     LOG_CLI((BSL_META_U(unit,"DGLP1 = %d\r\n"),h_data_p->dglp1));
  10164     LOG_CLI((BSL_META_U(unit,"DGLP2 = %d\r\n"),h_data_p->dglp2));
  10165     LOG_CLI((BSL_META_U(unit,"DGLP1 Profile idx = %d\r\n"),h_data_p->dglp1_profile_index));
  10166     LOG_CLI((BSL_META_U(unit,"DGLP2 Profile idx = %d\r\n"),h_data_p->dglp2_profile_index));
  10167     LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid));
  10168     LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid));
  10169     LOG_CLI((BSL_META_U(unit,"SubPort TPID = %d\r\n"),h_data_p->subport_tpid));
  10170     LOG_CLI((BSL_META_U(unit,"Outer TPID profile idx = %d\r\n"),h_data_p->outer_tpid_profile_index));
  10171     LOG_CLI((BSL_META_U(unit,"Inner TPID profile idx = %d\r\n"),h_data_p->inner_tpid_profile_index));
  10172     LOG_CLI((BSL_META_U(unit,"SubPort TPID profile idx = %d\r\n"),h_data_p->subport_tpid_profile_index));
  10173     LOG_CLI((BSL_META_U(unit,"MA Base idx = %d\r\n"),h_data_p->ma_base_index));
  10174     LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id));
  10175     LOG_CLI((BSL_META_U(unit,"Active MDL BITMAP = 0x%x\r\n"),h_data_p->active_mdl_bitmap));
  10176     LOG_CLI((BSL_META_U(unit,"Internal flags = 0x%x\r\n"),h_data_p->int_flags));
  10177 #if defined(INCLUDE_BHH)
  10178     LOG_CLI((BSL_META_U(unit,"Cpu qid = %d\r\n"),h_data_p->cpu_qid));
  10179     LOG_CLI((BSL_META_U(unit,"BHH Endpoint Index = %d\r\n"),h_data_p->bhh_endpoint_index));
  10180     LOG_CLI((BSL_META_U(unit,"BHH DM ENTRY= %d\r\n"),h_data_p->bhh_dm_entry_rx));
  10181     LOG_CLI((BSL_META_U(unit,"BHH LM ENTRY= %d\r\n"),h_data_p->bhh_lm_entry_rx));
  10182     LOG_CLI((BSL_META_U(unit,"BHH ENTRY PKT RX= %d\r\n"),h_data_p->bhh_entry_pkt_rx));
  10183     LOG_CLI((BSL_META_U(unit,"BHH ENTRY PKT TX= %d\r\n"),h_data_p->bhh_entry_pkt_tx));
  10184     LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  10185              h_data_p->src_mac_address[0], h_data_p->src_mac_address[1],
  10186              h_data_p->src_mac_address[2], h_data_p->src_mac_address[3],
  10187              h_data_p->src_mac_address[4], h_data_p->src_mac_address[5]));
  10188     LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  10189              h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1],
  10190              h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3],
  10191              h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5]));
  10192     LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"),h_data_p->inner_vlan_pri));
  10193     LOG_CLI((BSL_META_U(unit,"egr label= %d\r\n"),h_data_p->egr_label));
  10194     LOG_CLI((BSL_META_U(unit,"egr label exp= %d\r\n"),h_data_p->egr_label_exp));
  10195     LOG_CLI((BSL_META_U(unit,"egr label ttl= %d\r\n"),h_data_p->egr_label_ttl));
  10196 #endif
  10197     LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type));
  10198     LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn));
  10199     LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"),h_data_p->pm_profile_attached));
  10200     LOG_CLI((BSL_META_U(unit,"CTR Field id = %d\r\n"),h_data_p->ctr_field_id));
  10201     LOG_CLI((BSL_META_U(unit,"EGR CTR Field id = %d\r\n"),h_data_p->egr_ctr_field_id));
  10202     LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk "
  10203                         "index 0x%x\r\n"),
  10204                         h_data_p->resolved_trunk_gport));
  10205     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  10206 }
  10207 
  10208 /*
  10209  * Function:
  10210  *     _bcm_oam_sw_dump
  10211  * Purpose:
  10212  *     Displays oam information maintained by software.
  10213  * Parameters:
  10214  *     unit - Device unit number
  10215  * Returns:
  10216  *     None
  10217  */
  10218 void
  10219 _bcm_kt2_oam_sw_dump(int unit)
  10220 {
  10221     int                    rv;
  10222     bcm_oam_group_t        grp_idx;
  10223     _bcm_oam_control_t     *oc = NULL;
  10224     _bcm_oam_group_data_t  *group_p = NULL;
  10225     _bcm_oam_ep_list_t     *ep_list_p = NULL;
  10226     _bcm_oam_hash_data_t   *ep_data_p = NULL;
  10227 
  10228     LOG_CLI((BSL_META_U(unit,"OAM\n")));
  10229     /* Get OAM control structure. */
  10230     rv = _bcm_kt2_oam_control_get(unit, &oc);
  10231     if(BCM_FAILURE(rv)) {
  10232         LOG_ERROR(BSL_LS_BCM_OAM,
  10233                 (BSL_META_U(unit,
  10234                 "OAM(unit %d) Error: Get oam control variable\n"),
  10235                  unit));
  10236 
  10237         return;
  10238     }
  10239 
  10240     _BCM_OAM_LOCK(oc);
  10241 
  10242     group_p = oc->group_info;
  10243     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) {
  10244         if (group_p[grp_idx].in_use == 1) {
  10245             ep_list_p = *(group_p[grp_idx].ep_list);
  10246             _bcm_kt2_oam_group_info_dump(unit, grp_idx, group_p);
  10247             while (ep_list_p != NULL) {
  10248                 ep_data_p = ep_list_p->ep_data_p;
  10249                 _bcm_kt2_oam_hash_data_dump(unit, ep_data_p);
  10250                 ep_list_p = ep_list_p->next;
  10251             }
  10252         }
  10253     }
  10254 
  10255     _BCM_OAM_UNLOCK(oc);
  10256 }
  10257 
  10258 void _bcm_kt2_oam_ma_idx_to_ep_id_mapping_print(int unit)
  10259 {
  10260     _bcm_oam_control_t   *oc = NULL;            /* Pointer to control structure.    */
  10261     int i = 0;
  10262     int rv = BCM_E_NONE;
  10263 
  10264     rv = _bcm_kt2_oam_control_get(unit, &oc);
  10265     if ((BCM_FAILURE(rv)) || (oc == NULL)) {
  10266         return;
  10267     }
  10268     _BCM_OAM_LOCK(oc);
  10269 
  10270     if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) {
  10271         for (i = 0; i < (oc->ma_idx_count + oc->egr_ma_idx_count);i++) {
  10272             if (oc->_bcm_oam_ma_idx_to_ep_id_map[i] != _BCM_OAM_INVALID_INDEX) {
  10273                 LOG_CLI((BSL_META_U(unit,"MA_IDX = %d EP_ID = %d\r\n"),
  10274                         i, oc->_bcm_oam_ma_idx_to_ep_id_map[i]));
  10275             } 
  10276         }
  10277     }
  10278     _BCM_OAM_UNLOCK(oc);
  10279 } 
  10280 #endif
  10281 
  10282 #if defined(BCM_WARM_BOOT_SUPPORT)
  10283 #ifdef _KATANA2_DEBUG
  10284 /*
  10285  * Function:
  10286  *     _bcm_kt2_oam_tx_counter_recover
  10287  * Purpose:
  10288  *     Recover Rx counter for MEP 
  10289  * Parameters:
  10290  *     unit      - (IN) BCM device number
  10291  * Retruns:
  10292  *     BCM_E_XXX
  10293  */
  10294 STATIC int
  10295 _bcm_kt2_oam_tx_counter_recover(int unit, soc_mem_t  mem, 
  10296                                 uint32 *entry,
  10297                                 _bcm_oam_hash_data_t   *h_data_p)
  10298 {
  10299     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
  10300     int           rv = BCM_E_NONE;/* Operation return status.         */
  10301     int           up_mep = 0;
  10302     mep_ctr_info_t  *ctr_info;
  10303     shr_aidxres_list_handle_t *ctr_pool;
  10304     int           *map;
  10305     int           ctr_type = 0;
  10306     int           ctr_valid = 0;
  10307     int           ctr_mdl = 0;
  10308 
  10309     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  10310     if (mem == L3_ENTRY_IPV4_UNICASTm) {
  10311         up_mep = 1;
  10312         ctr_info = mep_ctr_info;
  10313         map = &h_data_p->pri_map_index;
  10314     } else if (mem == EGR_MP_GROUPm) {
  10315         ctr_info = egr_mep_ctr_info;
  10316         map = &h_data_p->egr_pri_map_index;
  10317     } else {
  10318         return BCM_E_INTERNAL; 
  10319     }
  10320     ctr_pool = oc->ing_lm_ctr_pool;
  10321     ctr_valid = soc_mem_field32_get(unit, mem, 
  10322                                     (uint32 *)entry, ctr_info[0].ctr_valid);
  10323 
  10324     if (ctr_valid) {
  10325         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10326                                                  ctr_info[0].ctr_mep_type); 
  10327         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10328                                                  ctr_info[0].ctr_mep_mdl); 
  10329         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  10330             h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10331                                                  ctr_info[0].ctr_base_ptr);
  10332 
  10333             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  10334             *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10335                                                   ctr_info[0].ctr_profile);
  10336             /* Allocate 8 consecutive couters from the pool */
  10337             rv =  shr_aidxres_list_reserve_block(ctr_pool[0],
  10338                                                        h_data_p->tx_ctr, 8);
  10339             if (BCM_FAILURE(rv)) {
  10340                 LOG_ERROR(BSL_LS_BCM_OAM,
  10341                           (BSL_META_U(unit,
  10342                                       "OAM Error: LM counter block alloc failed "
  10343                                       "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
  10344                 return (rv);
  10345             }
  10346         }
  10347     }
  10348     ctr_valid = soc_mem_field32_get(unit, mem, 
  10349                                     (uint32 *)entry, ctr_info[1].ctr_valid);
  10350     if (ctr_valid) {
  10351         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10352                                                  ctr_info[1].ctr_mep_type); 
  10353         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10354                                                  ctr_info[1].ctr_mep_mdl); 
  10355         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  10356             h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10357                                                  ctr_info[1].ctr_base_ptr);
  10358 
  10359             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  10360             *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10361                                                   ctr_info[1].ctr_profile);
  10362             /* Allocate 8 consecutive couters from the pool */
  10363             rv =  shr_aidxres_list_reserve_block(ctr_pool[1],
  10364                                                         h_data_p->tx_ctr, 8);
  10365             if (BCM_FAILURE(rv)) {
  10366                 LOG_ERROR(BSL_LS_BCM_OAM,
  10367                           (BSL_META_U(unit,
  10368                                       "OAM Error: LM counter block alloc failed "
  10369                                       "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
  10370                 return (rv);
  10371             }
  10372         }
  10373     }
  10374     return (rv);
  10375 }
  10376 
  10377 #endif /* _KATANA2_DEBUG */
  10378 
  10379 /*
  10380  * Function:
  10381  *     _bcm_kt2_oam_rx_counter_recover
  10382  * Purpose:
  10383  *     Recover Rx counter for MEP 
  10384  * Parameters:
  10385  *     unit      - (IN) BCM device number
  10386  * Retruns:
  10387  *     BCM_E_XXX
  10388  */
  10389 STATIC int
  10390 _bcm_kt2_oam_rx_counter_recover(int unit, soc_mem_t  mem, 
  10391                                 uint32 *entry,
  10392                                 _bcm_oam_hash_data_t   *h_data_p)
  10393 {
  10394     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
  10395     int           rv = BCM_E_NONE;/* Operation return status.         */
  10396     int           up_mep = 0;
  10397     mep_ctr_info_t  *ctr_info;
  10398     shr_aidxres_list_handle_t *ctr_pool;
  10399     int           *map;
  10400     int           ctr_valid = 0;
  10401     int           ctr_mdl = 0;
  10402     int           ctr_type = 0;
  10403     soc_profile_mem_t    *pri_map_profile;  
  10404                                                         
  10405 
  10406     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  10407     if (mem == EGR_MP_GROUPm) {
  10408         up_mep = 1;
  10409         ctr_info = egr_mep_ctr_info;
  10410         map = &h_data_p->egr_pri_map_index;
  10411         pri_map_profile =  &oc->egr_service_pri_map;
  10412     } else {
  10413         ctr_info = mep_ctr_info;
  10414         map = &h_data_p->pri_map_index;
  10415         pri_map_profile =  &oc->ing_service_pri_map;
  10416     } 
  10417     ctr_pool = oc->ing_lm_ctr_pool;
  10418     ctr_valid = soc_mem_field32_get(unit, mem, 
  10419                                     (uint32 *)entry, ctr_info[0].ctr_valid);
  10420 
  10421     if (ctr_valid) {
  10422         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10423                                                  ctr_info[0].ctr_mep_type); 
  10424         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10425                                                  ctr_info[0].ctr_mep_mdl); 
  10426         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  10427             h_data_p->rx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10428                                                  ctr_info[0].ctr_base_ptr);
  10429 
  10430             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  10431             *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10432                                                   ctr_info[0].ctr_profile);
  10433             rv = soc_profile_mem_reference(unit, pri_map_profile,
  10434                                ((*map) * BCM_OAM_INTPRI_MAX), BCM_OAM_INTPRI_MAX);
  10435             if (BCM_FAILURE(rv)) {
  10436                 LOG_ERROR(BSL_LS_BCM_OAM,
  10437                           (BSL_META_U(unit,
  10438                                       "OAM Error: LM counter profile ref count "
  10439                                       "increment failed (EP=%d) - %s.\n"),
  10440                            h_data_p->ep_id, bcm_errmsg(rv)));
  10441                 return (rv);
  10442             }
  10443             /* Allocate 8 consecutive couters from the pool */
  10444             rv =  shr_aidxres_list_reserve_block(ctr_pool[0],
  10445                                                        h_data_p->rx_ctr, 8);
  10446             if (BCM_FAILURE(rv)) {
  10447                 LOG_ERROR(BSL_LS_BCM_OAM,
  10448                           (BSL_META_U(unit,
  10449                                       "OAM Error: LM counter block alloc failed "
  10450                                       "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
  10451                 return (rv);
  10452             }
  10453         }
  10454     }
  10455     ctr_valid = soc_mem_field32_get(unit, mem, 
  10456                                     (uint32 *)entry, ctr_info[1].ctr_valid);
  10457     if (ctr_valid) {
  10458         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10459                                                  ctr_info[1].ctr_mep_type); 
  10460         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  10461                                                  ctr_info[1].ctr_mep_mdl); 
  10462         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  10463             h_data_p->rx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10464                                                  ctr_info[1].ctr_base_ptr);
  10465 
  10466             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  10467             *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  10468                                                   ctr_info[1].ctr_profile);
  10469             rv = soc_profile_mem_reference(unit, pri_map_profile,
  10470                            ((*map) * BCM_OAM_INTPRI_MAX), BCM_OAM_INTPRI_MAX);
  10471             if (BCM_FAILURE(rv)) {
  10472                 LOG_ERROR(BSL_LS_BCM_OAM,
  10473                           (BSL_META_U(unit,
  10474                                       "OAM Error: LM counter profile ref count  "
  10475                                       "increment failed (EP=%d) - %s.\n"),
  10476                            h_data_p->ep_id, bcm_errmsg(rv)));
  10477                 return (rv);
  10478             }
  10479             /* Allocate 8 consecutive couters from the pool */
  10480             rv =  shr_aidxres_list_reserve_block(ctr_pool[1],
  10481                                                       h_data_p->rx_ctr, 8);
  10482             if (BCM_FAILURE(rv)) {
  10483                 LOG_ERROR(BSL_LS_BCM_OAM,
  10484                           (BSL_META_U(unit,
  10485                                       "OAM Error: LM counter block alloc failed "
  10486                                       "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
  10487                 return (rv);
  10488             }
  10489         }
  10490     }
  10491     return (rv);
  10492 }
  10493 /*
  10494  * Function:
  10495  *     _bcm_kt2_oam_endpoint_alloc
  10496  * Purpose:
  10497  *     Allocate an endpoint memory element.
  10498  * Parameters:
  10499  *     ep_pp - (IN/OUT) Pointer to endpoint address pointer.
  10500  * Returns:
  10501  *     BCM_E_XXX
  10502  */
  10503 STATIC int
  10504 _bcm_kt2_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp)
  10505 {
  10506     bcm_oam_endpoint_info_t *ep_p = NULL;
  10507 
  10508     _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t,
  10509                    sizeof(bcm_oam_endpoint_info_t), "Endpoint info");
  10510     if (NULL == ep_p) {
  10511         return (BCM_E_MEMORY);
  10512     }
  10513     
  10514     *ep_pp = ep_p;
  10515 
  10516     return (BCM_E_NONE);
  10517 
  10518 }
  10519 
  10520 /*
  10521  * Function:
  10522  *     _bcm_kt2_oam_sync
  10523  * Purpose:
  10524  *     Store OAM configuration to level two storage cache memory.
  10525  * Parameters:
  10526  *     unit - (IN) Device unit number
  10527  * Returns:
  10528  *     BCM_E_XXX
  10529  */
  10530 int
  10531 _bcm_kt2_oam_sync(int unit)
  10532 {
  10533     int                 rv;  /* Operation return status. */
  10534     _bcm_oam_control_t  *oc;
  10535     int                 alloc_size = 0;
  10536     int                 stable_size;
  10537     soc_scache_handle_t scache_handle;
  10538     uint8               *oam_scache;
  10539     int                 grp_idx;
  10540     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  10541     int                 group_count = 0;
  10542     _bcm_oam_ep_list_t  *ep_list_p = NULL;
  10543     _bcm_oam_hash_data_t ep_data;
  10544     int                 ma_offset;
  10545     int                 idx = 0;
  10546     _bcm_oam_hash_data_t    *h_data_p = NULL;       /* Endpoint hash data pointer.   */
  10547     
  10548 
  10549     /* Get OAM module storage size. */
  10550     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  10551 
  10552     /* If level 2 store is not configured return from here. */
  10553     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
  10554         return BCM_E_NONE;                                                      
  10555     }
  10556 
  10557     /* Get handle to control structure. */
  10558     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  10559 
  10560     _BCM_OAM_LOCK(oc);
  10561 
  10562     /* Initialize to group array pointer. */
  10563     group_p = oc->group_info;
  10564 
  10565     for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
  10566 
  10567         /* Check if the group is in use. */
  10568         if (BCM_E_EXISTS
  10569             == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
  10570             group_count++;
  10571         }
  10572     }
  10573     alloc_size += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
  10574     /* To store OAM group count. */
  10575     alloc_size += sizeof(int);
  10576 
  10577     /* To store FP GID. */
  10578     alloc_size += 3 * sizeof(bcm_field_group_t);
  10579 
  10580     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  10581 
  10582     /* To store EP ids */
  10583     alloc_size += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  10584 
  10585     /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */
  10586     alloc_size += sizeof(uint8);
  10587 
  10588     /* Check if memory has already been allocated */
  10589     rv = _bcm_esw_scache_ptr_get(unit,
  10590                                  scache_handle,
  10591                                  0,
  10592                                  alloc_size,
  10593                                  &oam_scache,
  10594                                  BCM_WB_DEFAULT_VERSION,
  10595                                  NULL
  10596                                  );
  10597     if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) {
  10598         rv = _bcm_esw_scache_ptr_get(unit,
  10599                                      scache_handle,
  10600                                      1,
  10601                                      alloc_size,
  10602                                      &oam_scache,
  10603                                      BCM_WB_DEFAULT_VERSION,
  10604                                      NULL
  10605                                      );
  10606         if (BCM_FAILURE(rv)
  10607             || (NULL == oam_scache)) {
  10608             goto cleanup;
  10609         }
  10610     } else if (BCM_FAILURE(rv)) {
  10611         goto cleanup;
  10612     }
  10613 
  10614     /* Store the FP groups */
  10615     sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t));
  10616     oam_scache += sizeof(bcm_field_group_t);
  10617 
  10618     sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t));
  10619     oam_scache += sizeof(bcm_field_group_t);
  10620 
  10621     sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t));
  10622     oam_scache += sizeof(bcm_field_group_t);
  10623 
  10624     sal_memcpy(oam_scache, &group_count, sizeof(int));
  10625     oam_scache += sizeof(int);
  10626 
  10627     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
  10628     {
  10629         /* Check if the group is in use. */
  10630         if (BCM_E_EXISTS
  10631                 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
  10632 
  10633             sal_memcpy(oam_scache, group_p[grp_idx].name,
  10634                        BCM_OAM_GROUP_NAME_LENGTH);
  10635 
  10636             oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
  10637         }
  10638     }
  10639 
  10640     /* Store logical endpoint indexes
  10641        Following is scache allocation for different types of EPs
  10642        -----------------------------------------------------------------------
  10643       | Rx DownMEP indexes | Rx UpMEP indexes | RMEP indexes | Tx MEP indexes |
  10644        -----------------------------------------------------------------------
  10645      */
  10646     sal_memset(oam_scache, 0, _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  10647 
  10648     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
  10649     {
  10650         if (group_p[grp_idx].in_use == 1) {
  10651             ep_list_p = *(group_p[grp_idx].ep_list);
  10652             while (ep_list_p != NULL) {
  10653                 sal_memcpy(&ep_data, ep_list_p->ep_data_p, sizeof(_bcm_oam_hash_data_t)); 
  10654                 if (ep_data.type == bcmOAMEndpointTypeEthernet) {
  10655 
  10656                     if (ep_data.is_remote) {
  10657                         sal_memcpy(oam_scache + 
  10658                                 (_BCM_KT2_OAM_RMEP_SCACHE_LOCATION(ep_data.remote_index)), 
  10659                                 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 
  10660                     } else {
  10661                         if (ep_data.local_tx_enabled) {
  10662                             sal_memcpy(oam_scache + 
  10663                                 (_BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(ep_data.local_tx_index)),
  10664                                     &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  10665                         }
  10666                         if (ep_data.local_rx_enabled) {
  10667                             if (ep_data.flags & BCM_OAM_ENDPOINT_UP_FACING) {
  10668                                 sal_memcpy(oam_scache + 
  10669                                         (_BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(ep_data.local_rx_index)),
  10670                                         &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  10671                             } else {
  10672                             _bcm_kt2_oam_ma_index_offset_get(unit, &ep_data, &ma_offset);
  10673                             ep_data.local_rx_index = ep_data.ma_base_index + ma_offset;
  10674                             sal_memcpy(oam_scache + 
  10675                                     (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ep_data.local_rx_index)),
  10676                                         &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  10677                             }
  10678 
  10679                         }
  10680                     }
  10681                 }
  10682                 ep_list_p = ep_list_p->next;
  10683             }
  10684         }
  10685     }
  10686     oam_scache +=  _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  10687 
  10688     sal_memcpy(oam_scache, &(oc->eth_oam_mp_group_vlan_key), sizeof(uint8));
  10689     oam_scache += sizeof(uint8);
  10690 
  10691     for (idx = 0; idx < oc->ep_count; idx++) {
  10692         h_data_p = &oc->oam_hash_data[idx];
  10693         if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) {
  10694             sal_memcpy(oam_scache, &(h_data_p->flags), sizeof(uint32));
  10695         }
  10696         oam_scache += sizeof(uint32);
  10697     }
  10698 
  10699 cleanup:
  10700     _BCM_OAM_UNLOCK(oc);
  10701     return (BCM_E_NONE);
  10702 }
  10703 
  10704 /*
  10705  * Function:
  10706  *     _bcm_kt2_oam_wb_group_recover
  10707  * Purpose:
  10708  *     Recover OAM group configuration.
  10709  * Parameters:
  10710  *     unit        - (IN) BCM device number
  10711  *     stable_size - (IN) OAM module Level2 storage size.
  10712  *     oam_scache  - (IN) Pointer to scache address pointer.
  10713  * Returns:
  10714  *     BCM_E_XXX
  10715  */
  10716 STATIC int
  10717 _bcm_kt2_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache)
  10718 {
  10719     int                    index;                    /* Hw table index.     */
  10720     _bcm_oam_group_data_t  *group_p;                 /* Group info pointer. */
  10721     maid_reduction_entry_t maid_entry;               /* Group entry info.   */
  10722     ma_state_entry_t       ma_state_ent;             /* Group state info.   */
  10723     int                    maid_reduction_valid = 0; /* Group valid.        */
  10724     int                    ma_state_valid = 0;       /* Group state valid.  */
  10725     _bcm_oam_control_t     *oc;                      /* Pointer to Control  */
  10726                                                      /* structure.          */
  10727     int                     rv;                      /* Operation return    */
  10728                                                      /* status.             */
  10729 
  10730     /* Control lock taken by calling routine. */
  10731     /* Get OAM control structure. */
  10732     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  10733 
  10734     for (index = 0; index < oc->group_count; index++) {
  10735 
  10736         rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index,
  10737                                   &maid_entry);
  10738         if (BCM_FAILURE(rv)) {
  10739             LOG_ERROR(BSL_LS_BCM_OAM,
  10740                       (BSL_META_U(unit,
  10741                                   "OAM Error: (GID=%d) MAID_REDUCTION table read"
  10742                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
  10743             goto cleanup;
  10744         }
  10745 
  10746         rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent);
  10747         if (BCM_FAILURE(rv)) {
  10748             LOG_ERROR(BSL_LS_BCM_OAM,
  10749                       (BSL_META_U(unit,
  10750                                   "OAM Error: (GID=%d) MA_STATE table read"
  10751                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
  10752             goto cleanup;
  10753         }
  10754 
  10755         maid_reduction_valid
  10756             = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf);
  10757 
  10758         ma_state_valid
  10759             = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf);
  10760 
  10761         if (maid_reduction_valid || ma_state_valid) {
  10762 
  10763             /* Entry must be valid in both the tables, else return error. */
  10764             if (!maid_reduction_valid || !ma_state_valid) {
  10765                 rv = BCM_E_INTERNAL;
  10766                 goto cleanup;
  10767             }
  10768 
  10769             /* Get the group memory pointer. */
  10770             group_p = &oc->group_info[index];
  10771             if (1 == group_p->in_use) {
  10772                 rv = BCM_E_INTERNAL;
  10773                 goto cleanup;
  10774             }
  10775 
  10776             if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
  10777 
  10778                 /* Set group name as zeros. */
  10779                 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH);
  10780 
  10781             } else {
  10782                     /* Get the group name from stored info. */
  10783                     sal_memcpy(group_p->name, *oam_scache, 
  10784                             BCM_OAM_GROUP_NAME_LENGTH);
  10785                     *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH);
  10786             }
  10787 
  10788             /* Reserve the group index. */
  10789             rv = shr_idxres_list_reserve(oc->group_pool, index, index);
  10790             if (BCM_FAILURE(rv)) {
  10791                 LOG_ERROR(BSL_LS_BCM_OAM,
  10792                           (BSL_META_U(unit,
  10793                                       "OAM Error: (GID=%d) Index reserve "
  10794                                        " failed  - %s.\n"), index, bcm_errmsg(rv)));
  10795                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  10796                 goto cleanup;
  10797             }
  10798 
  10799             /* Create the linked list to maintain group endpoint information. */
  10800             _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *,
  10801                            sizeof(_bcm_oam_ep_list_t *), "EP list head");
  10802             if (NULL == group_p->ep_list) {
  10803                 rv = BCM_E_MEMORY;
  10804                 goto cleanup;
  10805             }
  10806 
  10807             /* Initialize head node.*/
  10808             *group_p->ep_list =  NULL;
  10809         }
  10810     }
  10811 
  10812     return (BCM_E_NONE);
  10813 
  10814 cleanup:
  10815 
  10816     if (BCM_E_EXISTS
  10817         == shr_idxres_list_elem_state(oc->group_pool, index)) {
  10818         shr_idxres_list_free(oc->group_pool, index);
  10819     }
  10820 
  10821     return (rv);
  10822 
  10823 }
  10824 
  10825 /*
  10826  * Function:
  10827  *     _bcm_kt2_oam_rmep_recover
  10828  * Purpose:
  10829  *     Recover OAM remote endpoint configuration.
  10830  * Parameters:
  10831  *     unit        - (IN) BCM device number
  10832  *     index       - (IN) Remote MEP hardware index.
  10833  *     l3_entry    - (IN) RMEP view table entry pointer.
  10834  * Returns:
  10835  *     BCM_E_XXX
  10836  */
  10837 STATIC int
  10838 _bcm_kt2_oam_rmep_recover(int unit,
  10839                           int index,
  10840                           l3_entry_1_entry_t *l3_entry,
  10841                           uint8 **scache,
  10842                           uint16 recovered_ver)
  10843 {
  10844     rmep_entry_t            rmep_entry;      /* Remote table entry.           */
  10845     _bcm_oam_hash_data_t    *h_data_p;       /* Endpoint hash data pointer.   */
  10846     _bcm_oam_control_t      *oc;             /* Pointer to control structure. */
  10847     int                     rv;              /* Operation return status.      */
  10848     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  10849     _bcm_oam_hash_key_t     hash_key;        /* Hash key buffer for lookup.   */
  10850     int                     ep_id;           /* Endpoint ID.                  */
  10851     int                     rmep_index;      /* Index of RMEP table           */ 
  10852 
  10853     LOG_DEBUG(BSL_LS_BCM_OAM,
  10854               (BSL_META_U(unit,
  10855                           "OAM Info: _bcm_kt2_oam_rmep_recover.\n")));
  10856     /*
  10857      * Get OAM control structure.
  10858      *     Note: Lock taken by calling routine.
  10859      */
  10860     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  10861 
  10862     rmep_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf);
  10863 
  10864     if (recovered_ver >= BCM_WB_VERSION_1_3) {
  10865         /* Recover EP index from scache */ 
  10866         sal_memcpy(&ep_id, *scache + (_BCM_KT2_OAM_RMEP_SCACHE_LOCATION(rmep_index)),
  10867                 sizeof(bcm_oam_endpoint_t));
  10868         rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  10869         if (BCM_FAILURE(rv)) {
  10870             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  10871             LOG_ERROR(BSL_LS_BCM_OAM,
  10872                     (BSL_META_U(unit,
  10873                                 "OAM Error: (EP_ID=%d) Index reserve "
  10874                                 " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  10875             return (rv);
  10876         }
  10877 
  10878     } else {
  10879 
  10880         /* Allocate the next available endpoint index. */
  10881         rv = shr_idxres_list_alloc(oc->mep_pool,
  10882                 (shr_idxres_element_t *)&ep_id);
  10883         if (BCM_FAILURE(rv)) {
  10884             LOG_ERROR(BSL_LS_BCM_OAM,
  10885                     (BSL_META_U(unit,
  10886                                 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
  10887                      ep_id, bcm_errmsg(rv)));
  10888             return (rv);
  10889         }
  10890     } 
  10891     
  10892     h_data_p = &oc->oam_hash_data[ep_id];
  10893     if (1 == h_data_p->in_use) {
  10894         return(BCM_E_INTERNAL);
  10895     }
  10896 
  10897     /* 
  10898      * Clear the hash data element contents before
  10899      * storing values.
  10900      */
  10901     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  10902     h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  10903     h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  10904     h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  10905     h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  10906     h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  10907     h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  10908     h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  10909     h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  10910     h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  10911     h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  10912     h_data_p->trunk_id = BCM_TRUNK_INVALID;
  10913     h_data_p->gport = 0;
  10914     /* Get RMEP table index from LMEP view entry. */
  10915     h_data_p->remote_index
  10916         = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf);
  10917 
  10918     /* Get RMEP table entry contents. */
  10919     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
  10920     if (BCM_FAILURE(rv)) {
  10921         LOG_ERROR(BSL_LS_BCM_OAM,
  10922                   (BSL_META_U(unit,
  10923                               "OAM Error: RMEP (index=%d) read failed  - %s.\n"),
  10924                    h_data_p->remote_index, bcm_errmsg(rv)));
  10925         goto cleanup;
  10926     }
  10927 
  10928    /* Has to be a valid RMEP, return error otherwise. */
  10929     if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) {
  10930         rv = BCM_E_INTERNAL;
  10931         goto cleanup;
  10932     }
  10933     
  10934     h_data_p->ep_id = ep_id;
  10935 
  10936     h_data_p->is_remote = 1;
  10937 
  10938     h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE;
  10939 
  10940     h_data_p->group_index
  10941         = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf);
  10942 
  10943     h_data_p->period
  10944         = _bcm_kt2_oam_ccm_hw_encode_to_msecs
  10945             ((int) soc_RMEPm_field32_get(unit, &rmep_entry,
  10946                                          RMEP_RECEIVED_CCMf));
  10947 
  10948     h_data_p->name
  10949         = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__MEPIDf);
  10950 
  10951     h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX;
  10952     h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX;
  10953     h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  10954     h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  10955 
  10956     rv = shr_idxres_list_reserve(oc->rmep_pool,
  10957                                  h_data_p->remote_index,
  10958                                  h_data_p->remote_index);
  10959     if (BCM_FAILURE(rv)) {
  10960         LOG_ERROR(BSL_LS_BCM_OAM,
  10961                   (BSL_META_U(unit,
  10962                               "OAM Error: (RMEP=%d) Index reserve failed  - %s.\n"),
  10963                    h_data_p->remote_index, bcm_errmsg(rv)));
  10964         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  10965         goto cleanup;
  10966     }
  10967 
  10968     h_data_p->in_use = 1;
  10969 
  10970     rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  10971     if (BCM_FAILURE(rv)) {
  10972         goto cleanup;
  10973     }
  10974 
  10975     rv = _bcm_kt2_oam_endpoint_alloc(&ep_info);
  10976     if (BCM_FAILURE(rv)) {
  10977         _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
  10978         goto cleanup;
  10979     }
  10980 
  10981     bcm_oam_endpoint_info_t_init(ep_info);
  10982 
  10983     /* Set up endpoint information for key construction. */
  10984     ep_info->group = h_data_p->group_index;
  10985     ep_info->name = h_data_p->name;
  10986     ep_info->gport = h_data_p->gport;
  10987     ep_info->id= h_data_p->ep_id;
  10988     /* Calculate hash key for hash table insert operation. */
  10989     _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  10990 
  10991     if ((recovered_ver < BCM_WB_VERSION_1_5) 
  10992             || (!ETH_TYPE(h_data_p->type))) {
  10993         rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  10994         if (BCM_FAILURE(rv)) {
  10995             LOG_ERROR(BSL_LS_BCM_OAM,
  10996                     (BSL_META_U(unit,
  10997                                 "OAM Error: Hash table insert failed "
  10998                                 "EP=%d %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
  10999             _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
  11000             goto cleanup;
  11001         } else {
  11002             LOG_DEBUG(BSL_LS_BCM_OAM,
  11003                     (BSL_META_U(unit,
  11004                                 "OAM Info: Hash Tbl (EP=%d) inserted"
  11005                                 " - %s.\n"), ep_id, bcm_errmsg(rv)));
  11006         }
  11007     }
  11008 
  11009     /* Add the H/w index to logical index mapping for RMEP */
  11010     oc->remote_endpoints[h_data_p->remote_index] = ep_info->id;
  11011 
  11012     sal_free(ep_info);
  11013 
  11014     LOG_DEBUG(BSL_LS_BCM_OAM,
  11015               (BSL_META_U(unit,
  11016                           "OAM Info: _bcm_kt2_oam_rmep_recover - done.\n")));
  11017 
  11018     return (rv);
  11019 
  11020 cleanup:
  11021 
  11022     if (NULL != ep_info) {
  11023         sal_free(ep_info);
  11024     }
  11025 
  11026     /* Release the endpoint ID if in use. */
  11027     if (BCM_E_EXISTS
  11028         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  11029         shr_idxres_list_free(oc->mep_pool, ep_id);
  11030     }
  11031 
  11032     /* Release the remote index if in use. */
  11033     if ((1 == h_data_p->in_use)
  11034         && (BCM_E_EXISTS
  11035             == shr_idxres_list_elem_state(oc->rmep_pool,
  11036                                           h_data_p->remote_index))) {
  11037         shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index);
  11038 
  11039     }
  11040     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11041 
  11042     LOG_DEBUG(BSL_LS_BCM_OAM,
  11043               (BSL_META_U(unit,
  11044                           "OAM Info: _bcm_kt2_oam_rmep_recover - error_done.\n")));
  11045     return (rv);
  11046 }
  11047 
  11048 /*
  11049  * Function:
  11050  *     _bcm_kt2_oam_port_lmep_rx_config_recover
  11051  * Purpose:
  11052  *     Recover OAM local endpoint Rx configuration for port based DownMEPs.
  11053  * Parameters:
  11054  *     unit        - (IN) BCM device number
  11055  *     index       - (IN) Port entry hardware index.
  11056  *     port_entry  - (IN) port table entry pointer.
  11057  * Returns:
  11058  *     BCM_E_XXX
  11059  */
  11060 STATIC int
  11061 _bcm_kt2_oam_port_lmep_rx_config_recover(int unit,
  11062                          int index,
  11063                          port_tab_entry_t *port_entry,
  11064                          uint8 **scache,
  11065                          uint16 recovered_ver)
  11066 {
  11067 
  11068     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  11069     ma_index_entry_t        ma_idx_entry; /* MA_INDEX table entry.           */
  11070     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  11071     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  11072     uint8                   mdl;          /* Maintenance domain level.       */
  11073     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  11074     int                     rv, tmp_rv;   /* Operation return status.        */
  11075     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  11076     bcm_gport_t             gport;        /* Gport value.                    */
  11077     int                     ep_id;        /* Endpoint ID.                    */
  11078     bcm_module_t            my_modid;
  11079     int                     stm_index = 0;
  11080     source_trunk_map_table_entry_t stm_entry;
  11081     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  11082     int                     ma_offset = 0;
  11083     int                     ma_idx_entry_count = 0;
  11084     shr_idxres_list_handle_t pool = NULL;
  11085     int                     ma_idx;       /* MA_TABLE index                  */
  11086     int                     ma_base_idx = 0;
  11087     LOG_DEBUG(BSL_LS_BCM_OAM,
  11088               (BSL_META_U(unit,
  11089                           "OAM Info: _bcm_kt2_oam_port_lmep_rx_config_recover .\n")));
  11090     /*
  11091      * Get OAM control structure.
  11092      *     Note: Lock taken by calling routine.
  11093      */
  11094     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  11095 
  11096     /* recover port based DownMEPs */
  11097     mdl_bitmap = soc_PORT_TABm_field32_get(unit, port_entry, MDL_BITMAPf); 
  11098     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  11099 
  11100         if (mdl_bitmap & (1 << mdl)) {
  11101             if (recovered_ver >= BCM_WB_VERSION_1_3) {
  11102 
  11103                 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  11104                 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit,
  11105                             my_modid, index, &stm_index));
  11106                 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 
  11107                             MEM_BLOCK_ANY, stm_index, &stm_entry));
  11108                 ma_base_idx = 
  11109                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 
  11110                             MA_BASE_PTRf);
  11111 
  11112                 ma_idx = ma_base_idx + ma_offset;
  11113                 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)),
  11114                         sizeof(bcm_oam_endpoint_t));
  11115                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  11116                 if (BCM_FAILURE(rv)) {
  11117                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  11118                     LOG_ERROR(BSL_LS_BCM_OAM, 
  11119                             (BSL_META_U(unit,
  11120                                         "OAM Error: (EP_ID=%d) Index reserve "
  11121                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  11122                     return (rv);
  11123                 }
  11124             } else {
  11125                 /* Allocate the next available endpoint index. */
  11126                 rv = shr_idxres_list_alloc(oc->mep_pool,
  11127                         (shr_idxres_element_t *)&ep_id);
  11128                 if (BCM_FAILURE(rv)) {
  11129                     LOG_ERROR(BSL_LS_BCM_OAM,
  11130                             (BSL_META_U(unit,
  11131                                         "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
  11132                              ep_id, bcm_errmsg(rv)));
  11133                     goto cleanup;
  11134                 }
  11135             }
  11136             h_data_p = &oc->oam_hash_data[ep_id];
  11137             if (1 == h_data_p->in_use) {
  11138                 rv = BCM_E_INTERNAL;
  11139                 goto cleanup;
  11140             }
  11141             /* 
  11142              * Clear the hash data element contents before
  11143              * storing values.
  11144              */
  11145             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11146             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  11147             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  11148             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  11149             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  11150             h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  11151             h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  11152             h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  11153             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  11154             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11155             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11156             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11157 
  11158 
  11159             h_data_p->ep_id = ep_id;
  11160             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  11161             BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit,
  11162                                               my_modid, index, &stm_index));
  11163             SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 
  11164                                     MEM_BLOCK_ANY, stm_index, &stm_entry));
  11165             h_data_p->ma_base_index = 
  11166                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 
  11167                          MA_BASE_PTRf);
  11168             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  11169             ma_offset++;
  11170 
  11171             rv = READ_MA_INDEXm(unit, MEM_BLOCK_ANY, 
  11172                                  h_data_p->local_rx_index, &ma_idx_entry);
  11173             if (BCM_FAILURE(rv)) {
  11174                 LOG_ERROR(BSL_LS_BCM_OAM,
  11175                           (BSL_META_U(unit,
  11176                                       "OAM Error: MA_INDEX(index:%d) "
  11177                                       "read failed -" " %s.\n"),
  11178                            h_data_p->local_rx_index, bcm_errmsg(rv)));
  11179                 goto cleanup;
  11180             }
  11181 
  11182             h_data_p->in_use = 1;
  11183             h_data_p->is_remote = 0;
  11184             h_data_p->local_rx_enabled = 1;
  11185             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  11186             h_data_p->group_index
  11187                 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  11188 
  11189             h_data_p->profile_index
  11190                 = soc_MA_INDEXm_field32_get
  11191                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  11192 
  11193             rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
  11194                                        h_data_p->profile_index, 1);
  11195             if (BCM_FAILURE(rv)) {
  11196                 LOG_ERROR(BSL_LS_BCM_OAM,
  11197                           (BSL_META_U(unit,
  11198                                       "OAM Error: Profile entry recover failed "
  11199                                       "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
  11200                 goto cleanup;
  11201             }
  11202             h_data_p->name = 0xffff;
  11203             h_data_p->level = mdl;
  11204             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  11205             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  11206             h_data_p->oam_domain = 0;
  11207 
  11208             /* Generic logical port type, construct gport from GLP.  */
  11209             _bcm_gport_dest_t_init(&gport_dest);
  11210 
  11211             gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  11212             gport_dest.modid = my_modid;
  11213             gport_dest.port = index;
  11214             h_data_p->sglp = index;
  11215 
  11216             rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  11217             if (BCM_FAILURE(rv)) {
  11218                 LOG_ERROR(BSL_LS_BCM_OAM,
  11219                           (BSL_META_U(unit,
  11220                                       "OAM Error: Gport construct failed -"
  11221                                        " %s.\n"), bcm_errmsg(rv)));
  11222                  goto cleanup;
  11223             }
  11224             h_data_p->gport = gport;
  11225 
  11226             rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  11227             if (BCM_FAILURE(rv)) {
  11228                 goto cleanup;
  11229             }
  11230 
  11231             rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  11232             if (BCM_FAILURE(rv)) {
  11233                 LOG_ERROR(BSL_LS_BCM_OAM,
  11234                         (BSL_META_U(unit,
  11235                                     "OAM(unit %d) Error: Remove mapping from ma_idx_to_ep_id list (EP=%d) -"
  11236                                     " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  11237                 _bcm_kt2_oam_group_ep_list_remove(unit,
  11238                                               h_data_p->group_index,
  11239                                               ep_id);
  11240                 goto cleanup;
  11241             }
  11242 
  11243             rv = _bcm_kt2_oam_endpoint_alloc(&ep_info);
  11244             if (BCM_FAILURE(rv)) {
  11245                 _bcm_kt2_oam_group_ep_list_remove(unit,
  11246                                               h_data_p->group_index,
  11247                                               ep_id);
  11248                 goto cleanup;
  11249             }
  11250 
  11251             bcm_oam_endpoint_info_t_init(ep_info);
  11252 
  11253             /* Set up endpoint information for key construction. */
  11254             ep_info->group = h_data_p->group_index;
  11255             ep_info->name = h_data_p->name;
  11256             ep_info->gport = h_data_p->gport;
  11257             ep_info->level = h_data_p->level;
  11258             ep_info->vlan = 0;
  11259             ep_info->inner_vlan = 0;
  11260 
  11261             if ((recovered_ver < BCM_WB_VERSION_1_5) 
  11262                     || (!ETH_TYPE(h_data_p->type))) {
  11263                 /*
  11264                  * Calculate hash key for hash table insert
  11265                  * operation.
  11266                  */
  11267                 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  11268 
  11269 
  11270                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  11271                 if (BCM_FAILURE(rv)) {
  11272                     LOG_ERROR(BSL_LS_BCM_OAM,
  11273                             (BSL_META_U(unit,
  11274                                         "OAM Error: Hash table insert"
  11275                                         " (EP=%d) failed - %s.\n"),
  11276                              h_data_p->ep_id, bcm_errmsg(rv)));
  11277 
  11278                     _bcm_kt2_oam_group_ep_list_remove(unit,
  11279                             h_data_p->group_index,
  11280                             ep_id);
  11281                     goto cleanup;
  11282                 } else {
  11283                     LOG_DEBUG(BSL_LS_BCM_OAM,
  11284                             (BSL_META_U(unit,
  11285                                         "OAM Info: Hash Tbl (EP=%d)"
  11286                                         " inserted  - %s.\n"), ep_id,
  11287                              bcm_errmsg(rv)));
  11288                 }
  11289             }
  11290             sal_free(ep_info);
  11291             ep_info = NULL;
  11292         }
  11293     } /* end of for loop */
  11294     if (mdl_bitmap) {
  11295         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
  11296                     &ma_idx_entry_count,&pool));
  11297         rv = shr_idxres_list_reserve(pool,
  11298                                      h_data_p->ma_base_index,
  11299                                      h_data_p->ma_base_index + ma_idx_entry_count -1);
  11300         if (BCM_FAILURE(rv)) {
  11301             LOG_ERROR(BSL_LS_BCM_OAM,
  11302                       (BSL_META_U(unit,
  11303                                   "OAM Error: (LMEP=%d) MA Index reserve "
  11304                                   "failed" "  - %s.\n"), h_data_p->ma_base_index,
  11305                        bcm_errmsg(rv)));
  11306             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  11307             goto cleanup;
  11308         }
  11309     }
  11310 
  11311     LOG_DEBUG(BSL_LS_BCM_OAM,
  11312               (BSL_META_U(unit,
  11313                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  11314                            " - done.\n")));
  11315     return (BCM_E_NONE);
  11316 
  11317 cleanup:
  11318     /* Lets not check return value of delete during cleanup */
  11319     tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  11320     if (BCM_FAILURE(tmp_rv)) {
  11321         LOG_DEBUG(BSL_LS_BCM_OAM,
  11322                   (BSL_META_U(unit,
  11323                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) "
  11324                               "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  11325     }
  11326 
  11327     if (NULL != ep_info) {
  11328         sal_free(ep_info);
  11329     }
  11330 
  11331     if (BCM_E_EXISTS
  11332         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  11333         shr_idxres_list_free(oc->mep_pool, ep_id);
  11334     }
  11335     if (NULL != h_data_p
  11336         && (BCM_E_EXISTS
  11337             == shr_idxres_list_elem_state(pool,
  11338                                           h_data_p->ma_base_index))) {
  11339         shr_idxres_list_free(pool, h_data_p->ma_base_index);
  11340     }
  11341     if (NULL != h_data_p) {
  11342         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11343     }
  11344 
  11345     LOG_DEBUG(BSL_LS_BCM_OAM,
  11346               (BSL_META_U(unit,
  11347                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  11348                            " - error_done.\n")));
  11349     return (rv);
  11350 
  11351 }
  11352 
  11353 /*
  11354  * Function:
  11355  *     _bcm_kt2_oam_lmep_upmep_rx_config_recover
  11356  * Purpose:
  11357  *     Recover OAM local endpoint Rx configuration for UpMEPS.
  11358  * Parameters:
  11359  *     unit        - (IN) BCM device number
  11360  *     index       - (IN) Remote MEP hardware index.
  11361  *     egr_mp_grp_entry - (IN) Egress MP group table entry pointer.
  11362  * Returns:
  11363  *     BCM_E_XXX
  11364  */
  11365 STATIC int
  11366 _bcm_kt2_oam_lmep_upmep_rx_config_recover(int unit,
  11367                          int index,
  11368                          egr_mp_group_entry_t *egr_mp_grp_entry,
  11369                          uint8 **scache,
  11370                          uint16 recovered_ver)
  11371 {
  11372     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  11373     ma_index_entry_t        ma_idx_entry; /* MA_INDEX table entry.           */
  11374     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  11375     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  11376     uint8                   mdl;          /* Maintenance domain level.       */
  11377     int                     rv, tmp_rv;   /* Operation return status.        */
  11378     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  11379     bcm_gport_t             gport;        /* Gport value.                    */
  11380     uint16                  glp;          /* Generic logical port value.     */
  11381     int                     ep_id;        /* Endpoint ID.                    */
  11382     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  11383     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.        */
  11384     int                     lmep_type = 0;
  11385     int                     timestamp_type = 0;
  11386     int                     ma_offset = 0;
  11387     int                     ma_base_idx = 0;
  11388     int                     ma_idx      = 0;
  11389     l3_entry_1_entry_t      l3_entry;
  11390     int                     l3_index = -1;
  11391     uint8                   mdl_mip = 0;
  11392 
  11393     LOG_DEBUG(BSL_LS_BCM_OAM,
  11394               (BSL_META_U(unit,
  11395                           "OAM Info: _bcm_kt2_oam_lmep_upmep_rx_config_recover .\n")));
  11396     /*
  11397      * Get OAM control structure.
  11398      *     Note: Lock taken by calling routine.
  11399      */
  11400     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  11401 
  11402     /* recover UpMEPs */
  11403     mdl_bitmap
  11404         = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, MDL_BITMAP_ACTIVEf);
  11405     
  11406     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  11407             
  11408         if (mdl_bitmap & (1 << mdl)) {
  11409             if (recovered_ver >= BCM_WB_VERSION_1_3) {
  11410 
  11411                 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  11412                         MA_BASE_PTRf);
  11413 
  11414                 ma_idx = ma_base_idx + ma_offset;
  11415 
  11416                 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(ma_idx)), 
  11417                         sizeof(bcm_oam_endpoint_t));
  11418                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  11419                 if (BCM_FAILURE(rv)) {
  11420                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  11421                     LOG_ERROR(BSL_LS_BCM_OAM, 
  11422                             (BSL_META_U(unit,
  11423                                         "OAM Error: (EP_ID=%d) Index reserve "
  11424                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  11425                     return (rv);
  11426                 }
  11427             } else {
  11428                 /* Allocate the next available endpoint index. */
  11429                 rv = shr_idxres_list_alloc(oc->mep_pool,
  11430                         (shr_idxres_element_t *)&ep_id);
  11431                 if (BCM_FAILURE(rv)) {
  11432                     LOG_ERROR(BSL_LS_BCM_OAM,
  11433                             (BSL_META_U(unit,
  11434                                         "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
  11435                              ep_id, bcm_errmsg(rv)));
  11436                     goto cleanup;
  11437                 }
  11438             }
  11439             h_data_p = &oc->oam_hash_data[ep_id];
  11440             if (1 == h_data_p->in_use) {
  11441                 rv = BCM_E_INTERNAL;
  11442                 goto cleanup;
  11443             }
  11444 
  11445             /* 
  11446              * Clear the hash data element contents before
  11447              * storing values.
  11448              */
  11449             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11450             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  11451             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  11452             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  11453             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  11454             h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  11455             h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  11456             h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  11457             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  11458             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11459             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11460             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11461             h_data_p->trunk_id = BCM_TRUNK_INVALID;
  11462 
  11463             h_data_p->ep_id = ep_id;
  11464             h_data_p->ma_base_index = 
  11465                 (soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 
  11466                              MA_BASE_PTRf));
  11467             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  11468             ma_offset++;
  11469 
  11470             rv = READ_EGR_MA_INDEXm(unit, MEM_BLOCK_ANY, 
  11471                                  h_data_p->local_rx_index, &ma_idx_entry);
  11472             if (BCM_FAILURE(rv)) {
  11473                 LOG_ERROR(BSL_LS_BCM_OAM,
  11474                           (BSL_META_U(unit,
  11475                                       "OAM Error: EGR_MA_INDEX(index:%d) "
  11476                                       "read failed -" " %s.\n"),
  11477                            h_data_p->local_rx_index, bcm_errmsg(rv)));
  11478                 goto cleanup;
  11479             }
  11480 
  11481             h_data_p->flags |= BCM_OAM_ENDPOINT_UP_FACING;
  11482             h_data_p->in_use = 1;
  11483             h_data_p->is_remote = 0;
  11484             h_data_p->local_rx_enabled = 1;
  11485             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  11486             h_data_p->group_index
  11487                 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  11488 
  11489             h_data_p->profile_index
  11490                 = soc_EGR_MA_INDEXm_field32_get
  11491                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  11492 
  11493             rv = soc_profile_mem_reference(unit, &oc->egr_oam_opcode_control_profile,
  11494                                        h_data_p->profile_index, 1);
  11495             if (BCM_FAILURE(rv)) {
  11496                 LOG_ERROR(BSL_LS_BCM_OAM,
  11497                           (BSL_META_U(unit,
  11498                                       "OAM Error: Profile entry recover failed "
  11499                                       "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
  11500                 goto cleanup;
  11501             }
  11502 
  11503             h_data_p->dglp1_profile_index =
  11504                      soc_MA_INDEXm_field32_get
  11505                                 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  11506             rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile,
  11507                                          h_data_p->dglp1_profile_index, 1);
  11508             if (BCM_FAILURE(rv)) {
  11509                 LOG_ERROR(BSL_LS_BCM_OAM,
  11510                           (BSL_META_U(unit,
  11511                                       "OAM Error: DGLP profile ref count  "
  11512                                       "increment failed (EP=%d) - %s.\n"),
  11513                            h_data_p->ep_id, bcm_errmsg(rv)));
  11514                 goto cleanup;
  11515             }
  11516             h_data_p->dglp2_profile_index =
  11517                 soc_MA_INDEXm_field32_get
  11518                     (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  11519             rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile,
  11520                                          h_data_p->dglp2_profile_index, 1);
  11521             if (BCM_FAILURE(rv)) {
  11522                 LOG_ERROR(BSL_LS_BCM_OAM,
  11523                           (BSL_META_U(unit,
  11524                                       "OAM Error: DGLP profile ref count  "
  11525                                       "increment failed (EP=%d) - %s.\n"),
  11526                            h_data_p->ep_id, bcm_errmsg(rv)));
  11527                 goto cleanup;
  11528             }
  11529 #if defined(INCLUDE_BHH)
  11530             h_data_p->cpu_qid
  11531                 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf);
  11532 #endif
  11533             h_data_p->name = 0xffff;
  11534             h_data_p->level = mdl;
  11535             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  11536             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  11537             /* recover counters */
  11538             rv = _bcm_kt2_oam_rx_counter_recover(unit, EGR_MP_GROUPm, 
  11539                                          (uint32 *)egr_mp_grp_entry, h_data_p);
  11540             if (BCM_FAILURE(rv)) {
  11541                 LOG_ERROR(BSL_LS_BCM_OAM,
  11542                           (BSL_META_U(unit,
  11543                                       "OAM Error: LM RX counter recover failed "
  11544                                       "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
  11545                 goto cleanup;
  11546             }
  11547             /* rx and tx counters are located at same index, but on diff mem */
  11548             if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  11549                 h_data_p->tx_ctr = h_data_p->rx_ctr;
  11550             }
  11551 
  11552             /* time stamp */
  11553             timestamp_type = soc_EGR_MP_GROUPm_field32_get(unit,
  11554                                             egr_mp_grp_entry, TIMESTAMP_TYPEf);  
  11555             if (timestamp_type) {
  11556                 h_data_p->ts_format = timestamp_type;
  11557             } 
  11558             h_data_p->oam_domain = soc_EGR_MP_GROUPm_field32_get(unit,
  11559                                                  egr_mp_grp_entry, KEY_TYPEf);
  11560 
  11561             switch (h_data_p->oam_domain) {
  11562                 case _BCM_OAM_DOMAIN_CVLAN:
  11563                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN;
  11564                     h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  11565                                                      egr_mp_grp_entry, CVIDf);
  11566                     break;
  11567 
  11568                 case _BCM_OAM_DOMAIN_SVLAN:
  11569                     h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  11570                                                      egr_mp_grp_entry, SVIDf);
  11571                     break;
  11572 
  11573                 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
  11574                     h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  11575                                                      egr_mp_grp_entry, SVIDf);
  11576                     h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  11577                                                        egr_mp_grp_entry, CVIDf);
  11578                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN;
  11579                     break;
  11580                 
  11581                 case _BCM_OAM_DOMAIN_VP:
  11582                     h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit, 
  11583                                                      egr_mp_grp_entry, DVPf);
  11584                     h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  11585                     break;
  11586                 default :
  11587                     break;
  11588   
  11589             }
  11590 
  11591             glp = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, DGLPf);
  11592 
  11593             lmep_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 
  11594                                                                  KEY_TYPEf);
  11595 
  11596             if (lmep_type == _BCM_OAM_DOMAIN_VP) { 
  11597 #if defined(INCLUDE_L3)
  11598                 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
  11599 
  11600                     BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  11601 
  11602                 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
  11603 
  11604                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  11605 
  11606                 } else {
  11607                     LOG_ERROR(BSL_LS_BCM_OAM,
  11608                               (BSL_META_U(unit,
  11609                                           "OAM Error: Invalid Virtual Port (SVP=%d)"
  11610                                            " - %s.\n"), h_data_p->vp,
  11611                                bcm_errmsg(BCM_E_INTERNAL)));
  11612                     return (BCM_E_INTERNAL);
  11613                 }
  11614 #endif
  11615             } else {
  11616                 /*
  11617                  * Generic logical port type, construct gport from GLP.
  11618                  */
  11619                 h_data_p->dglp = glp;
  11620 
  11621                 _bcm_gport_dest_t_init(&gport_dest);
  11622 
  11623                 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) {
  11624                     gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  11625                     gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  11626                     h_data_p->trunk_id =  _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  11627                 } else {
  11628                     gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  11629                     gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp);
  11630                     gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp);
  11631                 }
  11632 
  11633                 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  11634                 if (BCM_FAILURE(rv)) {
  11635                     LOG_ERROR(BSL_LS_BCM_OAM,
  11636                               (BSL_META_U(unit,
  11637                                           "OAM Error: Gport construct failed -"
  11638                                            " %s.\n"), bcm_errmsg(rv)));
  11639                     goto cleanup;
  11640                 }
  11641 
  11642                 h_data_p->gport = gport;
  11643             }
  11644             h_data_p->dglp = glp;
  11645             h_data_p->sglp = glp;
  11646 
  11647             sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
  11648             L3_LOCK(unit);
  11649             if (BCM_SUCCESS
  11650                     (_bcm_kt2_oam_find_lmep(unit, h_data_p,
  11651                                             &l3_index, &l3_entry))) {
  11652                 mdl_mip = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
  11653                         LMEP__MDL_BITMAP_PASSIVEf);
  11654             }
  11655             L3_UNLOCK(unit);
  11656 
  11657             if (!(mdl_mip & (1 << h_data_p->level))) {
  11658                 /* Set the MIP flag */
  11659                 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  11660             }
  11661 
  11662             rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  11663             if (BCM_FAILURE(rv)) {
  11664                 goto cleanup;
  11665             }
  11666 
  11667             rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  11668             if (BCM_FAILURE(rv)) {
  11669                 LOG_ERROR(BSL_LS_BCM_OAM,
  11670                         (BSL_META_U(unit,
  11671                                     "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  11672                                     " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  11673                 _bcm_kt2_oam_group_ep_list_remove(unit,
  11674                                               h_data_p->group_index,
  11675                                               ep_id);
  11676                 goto cleanup;
  11677             }
  11678 
  11679 
  11680             rv = _bcm_kt2_oam_endpoint_alloc(&ep_info);
  11681             if (BCM_FAILURE(rv)) {
  11682                 _bcm_kt2_oam_group_ep_list_remove(unit,
  11683                                               h_data_p->group_index,
  11684                                               ep_id);
  11685                 goto cleanup;
  11686             }
  11687 
  11688             bcm_oam_endpoint_info_t_init(ep_info);
  11689 
  11690             /* Set up endpoint information for key construction. */
  11691             ep_info->group = h_data_p->group_index;
  11692             ep_info->name = h_data_p->name;
  11693             ep_info->gport = h_data_p->gport;
  11694             ep_info->level = h_data_p->level;
  11695             ep_info->vlan = h_data_p->vlan;
  11696             ep_info->inner_vlan = h_data_p->inner_vlan;
  11697             ep_info->flags = h_data_p->flags;
  11698             if ((recovered_ver < BCM_WB_VERSION_1_5) 
  11699                     || (!ETH_TYPE(h_data_p->type))) {
  11700                 /*
  11701                  * Calculate hash key for hash table insert
  11702                  * operation.
  11703                  */
  11704                 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  11705 
  11706 
  11707                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  11708                 if (BCM_FAILURE(rv)) {
  11709                     LOG_ERROR(BSL_LS_BCM_OAM,
  11710                             (BSL_META_U(unit,
  11711                                         "OAM Error: Hash table insert"
  11712                                         " (EP=%d) failed - %s.\n"),
  11713                              h_data_p->ep_id, bcm_errmsg(rv)));
  11714 
  11715                     _bcm_kt2_oam_group_ep_list_remove(unit,
  11716                             h_data_p->group_index,
  11717                             ep_id);
  11718                     goto cleanup;
  11719                 } else {
  11720                     LOG_DEBUG(BSL_LS_BCM_OAM,
  11721                             (BSL_META_U(unit,
  11722                                         "OAM Info: Hash Tbl (EP=%d)"
  11723                                         " inserted  - %s.\n"), ep_id,
  11724                              bcm_errmsg(rv)));
  11725                 }
  11726             }
  11727             sal_free(ep_info);
  11728             ep_info = NULL;
  11729 
  11730         }
  11731     } /* end of for loop */
  11732     if (mdl_bitmap) {
  11733         rv = shr_idxres_list_reserve(oc->egr_ma_idx_pool,
  11734                                          h_data_p->ma_base_index,
  11735                                          h_data_p->ma_base_index + 7);
  11736         if (BCM_FAILURE(rv)) {
  11737             LOG_ERROR(BSL_LS_BCM_OAM,
  11738                       (BSL_META_U(unit,
  11739                                   "OAM Error: (LMEP=%d) EGR MA Index reserve "
  11740                                   "failed" "  - %s.\n"), h_data_p->remote_index,
  11741                        bcm_errmsg(rv)));
  11742             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  11743             goto cleanup;
  11744         }
  11745     }
  11746 
  11747     LOG_DEBUG(BSL_LS_BCM_OAM,
  11748               (BSL_META_U(unit,
  11749                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  11750                            " - done.\n")));
  11751     return (BCM_E_NONE);
  11752 
  11753 cleanup:
  11754     /* Lets not check return value of delete during cleanup */
  11755     tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  11756     if (BCM_FAILURE(tmp_rv)) {
  11757         LOG_DEBUG(BSL_LS_BCM_OAM,
  11758                   (BSL_META_U(unit,
  11759                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) "
  11760                               "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  11761     }
  11762 
  11763     if (NULL != ep_info) {
  11764         sal_free(ep_info);
  11765     }
  11766 
  11767     if (BCM_E_EXISTS
  11768         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  11769         shr_idxres_list_free(oc->mep_pool, ep_id);
  11770     }
  11771     /* return rx & tx counters allocated if any */
  11772     if (NULL != h_data_p) {
  11773         rv =_bcm_kt2_oam_free_counter(unit, h_data_p);
  11774         if (BCM_FAILURE(rv)) {
  11775             LOG_ERROR(BSL_LS_BCM_OAM,
  11776                       (BSL_META_U(unit,
  11777                                   "OAM Error: LM counter block "
  11778                                   "free failed (EP=%d) - %s.\n"),
  11779                        ep_id, bcm_errmsg(rv)));
  11780         }
  11781     }
  11782     if (NULL != h_data_p
  11783         && (BCM_E_EXISTS
  11784             == shr_idxres_list_elem_state(oc->egr_ma_idx_pool,
  11785                                           h_data_p->ma_base_index))) {
  11786 
  11787         shr_idxres_list_free(oc->egr_ma_idx_pool, h_data_p->ma_base_index);
  11788 
  11789     }
  11790     if (NULL != h_data_p) {
  11791         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11792     }
  11793     LOG_DEBUG(BSL_LS_BCM_OAM,
  11794               (BSL_META_U(unit,
  11795                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  11796                            " - error_done.\n")));
  11797     return (rv);
  11798 }
  11799 /*
  11800  * Function:
  11801  *     _bcm_kt2_oam_lmep_downmep_rx_config_recover
  11802  * Purpose:
  11803  *     Recover OAM local endpoint Rx configuration for DownMEPS.
  11804  * Parameters:
  11805  *     unit        - (IN) BCM device number
  11806  *     index       - (IN) Remote MEP hardware index.
  11807  *     l3_entry    - (IN) LMEP view table entry pointer.
  11808  * Returns:
  11809  *     BCM_E_XXX
  11810  */
  11811 STATIC int
  11812 _bcm_kt2_oam_lmep_downmep_rx_config_recover(int unit,
  11813                                     int index,
  11814                                     l3_entry_1_entry_t *l3_entry,
  11815                                     uint8 **scache,
  11816                                     uint16 recovered_ver)
  11817 {
  11818     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  11819     ma_index_entry_t        ma_idx_entry; /* IA_INDEX table entry.           */
  11820     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  11821     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  11822     uint8                   mdl;          /* Maintenance domain level.       */
  11823     int                     rv, tmp_rv;   /* Operation return status.        */
  11824     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  11825     bcm_gport_t             gport;        /* Gport value.                    */
  11826     uint16                  glp;          /* Generic logical port value.     */
  11827     int                     ep_id;        /* Endpoint ID.                    */
  11828     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  11829     bcm_oam_endpoint_info_t *ep_info = NULL;  /* Endpoint information.        */
  11830     int                     lmep_type = 0;
  11831     int                     timestamp_type = 0;
  11832     int                     ma_offset = 0;
  11833     int                     ma_idx_entry_count = 0;
  11834     shr_idxres_list_handle_t pool = NULL;
  11835     int                     ma_base_idx = 0;
  11836     int                     ma_idx      = 0;
  11837     egr_mp_group_entry_t    egr_mp_group;
  11838     int                     mp_grp_index = 0;
  11839     uint8                   mdl_mip = 0;
  11840 
  11841     LOG_DEBUG(BSL_LS_BCM_OAM,
  11842               (BSL_META_U(unit,
  11843                           "OAM Info: "
  11844                           "_bcm_kt2_oam_lmep_downmep_rx_config_recover .\n")));
  11845     /*
  11846      * Get OAM control structure.
  11847      *     Note: Lock taken by calling routine.
  11848      */
  11849     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  11850 
  11851     /* recover DownMEPs */
  11852     mdl_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
  11853                                               l3_entry, LMEP__MDL_BITMAP_ACTIVEf);
  11854     
  11855     ma_base_idx = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, LMEP__MA_BASE_PTRf);
  11856     
  11857     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  11858 
  11859         if (mdl_bitmap & (1 << mdl)) {
  11860 
  11861             if (recovered_ver >= BCM_WB_VERSION_1_3) {
  11862                 ma_idx = ma_base_idx + ma_offset;
  11863                 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)),
  11864                         sizeof(bcm_oam_endpoint_t));
  11865                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  11866                 if (BCM_FAILURE(rv)) {
  11867                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  11868                     LOG_ERROR(BSL_LS_BCM_OAM, 
  11869                             (BSL_META_U(unit,
  11870                                         "OAM Error: (EP_ID=%d) Index reserve "
  11871                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  11872                     return (rv);
  11873                 }
  11874             } else {
  11875                 /* Allocate the next available endpoint index. */
  11876                 rv = shr_idxres_list_alloc(oc->mep_pool,
  11877                         (shr_idxres_element_t *)&ep_id);
  11878                 if (BCM_FAILURE(rv)) {
  11879                     LOG_ERROR(BSL_LS_BCM_OAM,
  11880                             (BSL_META_U(unit,
  11881                                         "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
  11882                              ep_id, bcm_errmsg(rv)));
  11883                     goto cleanup;
  11884                 }
  11885             }
  11886             h_data_p = &oc->oam_hash_data[ep_id];
  11887             if (1 == h_data_p->in_use) {
  11888                 return(BCM_E_INTERNAL);
  11889             }
  11890 
  11891             /* 
  11892              * Clear the hash data element contents before
  11893              * storing values.
  11894              */
  11895             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  11896 
  11897             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  11898             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  11899             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  11900             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  11901             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  11902             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11903             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11904             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  11905             h_data_p->trunk_id =  BCM_TRUNK_INVALID;
  11906 
  11907 
  11908 
  11909             h_data_p->ep_id = ep_id;
  11910             h_data_p->ma_base_index = 
  11911                 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry,
  11912                         LMEP__MA_BASE_PTRf);
  11913             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  11914             ma_offset++;
  11915 
  11916             rv = READ_MA_INDEXm
  11917                     (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index,
  11918                      &ma_idx_entry);
  11919             if (BCM_FAILURE(rv)) {
  11920                 LOG_ERROR(BSL_LS_BCM_OAM,
  11921                           (BSL_META_U(unit,
  11922                                       "OAM Error: MA_INDEX (index:%d) read failed -"
  11923                                        " %s.\n"), h_data_p->local_rx_index,
  11924                            bcm_errmsg(rv)));
  11925                 goto cleanup;
  11926             }
  11927 
  11928             h_data_p->in_use = 1;
  11929 
  11930             h_data_p->is_remote = 0;
  11931 
  11932             h_data_p->local_rx_enabled = 1;
  11933 
  11934             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  11935 
  11936             h_data_p->group_index
  11937                 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  11938             h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf);
  11939 
  11940             h_data_p->profile_index
  11941                 = soc_MA_INDEXm_field32_get
  11942                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  11943             rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
  11944                                        h_data_p->profile_index, 1);
  11945             if (BCM_FAILURE(rv)) {
  11946                 LOG_ERROR(BSL_LS_BCM_OAM,
  11947                           (BSL_META_U(unit,
  11948                                       "OAM Error: Profile entry recover failed "
  11949                                       "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
  11950                 goto cleanup;
  11951             }
  11952 
  11953             h_data_p->dglp1_profile_index =
  11954                      soc_MA_INDEXm_field32_get
  11955                                 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  11956             rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile,
  11957                                          h_data_p->dglp1_profile_index, 1);
  11958             if (BCM_FAILURE(rv)) {
  11959                 LOG_ERROR(BSL_LS_BCM_OAM,
  11960                           (BSL_META_U(unit,
  11961                                       "OAM Error: DGLP profile ref count  "
  11962                                       "increment failed (EP=%d) - %s.\n"),
  11963                            h_data_p->ep_id, bcm_errmsg(rv)));
  11964                 goto cleanup;
  11965             }
  11966             h_data_p->dglp2_profile_index =
  11967                 soc_MA_INDEXm_field32_get
  11968                     (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  11969             rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile,
  11970                                          h_data_p->dglp2_profile_index, 1);
  11971             if (BCM_FAILURE(rv)) {
  11972                 LOG_ERROR(BSL_LS_BCM_OAM,
  11973                           (BSL_META_U(unit,
  11974                                       "OAM Error: DGLP profile ref count  "
  11975                                       "increment failed (EP=%d) - %s.\n"),
  11976                            h_data_p->ep_id, bcm_errmsg(rv)));
  11977                 goto cleanup;
  11978             }
  11979 
  11980             h_data_p->name = 0xffff;
  11981             
  11982             h_data_p->level = mdl;
  11983 
  11984             h_data_p->oam_domain = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
  11985                                                  l3_entry,
  11986                                                  LMEP__OAM_LMEP_KEY_SUBTYPEf);
  11987 
  11988             switch (h_data_p->oam_domain) {
  11989                 case _BCM_OAM_DOMAIN_CVLAN:
  11990                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN;
  11991                     h_data_p->inner_vlan = 
  11992                           soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
  11993                                                          l3_entry, LMEP__CVIDf);
  11994                     break;
  11995 
  11996                 case _BCM_OAM_DOMAIN_SVLAN:
  11997                     h_data_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
  11998                                                      l3_entry, LMEP__SVIDf);
  11999                     break;
  12000 
  12001                 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
  12002                     h_data_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
  12003                                                      l3_entry, LMEP__SVIDf);
  12004                     h_data_p->inner_vlan = 
  12005                              soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
  12006                                                          l3_entry, LMEP__CVIDf);
  12007                     h_data_p->flags |= 
  12008                                    BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN;
  12009                     break;
  12010                 
  12011                 case _BCM_OAM_DOMAIN_VP:
  12012                     h_data_p->vp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
  12013                                                      l3_entry, LMEP__SVPf);
  12014                     h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  12015                     break;
  12016                 default :
  12017                     break;
  12018   
  12019             }
  12020 
  12021             rv = _bcm_kt2_oam_rx_counter_recover(unit, 
  12022                        L3_ENTRY_IPV4_UNICASTm, (uint32 *)l3_entry, h_data_p);
  12023             if (BCM_FAILURE(rv)) {
  12024                 LOG_ERROR(BSL_LS_BCM_OAM,
  12025                           (BSL_META_U(unit,
  12026                                       "OAM Error: LM counter recover failed "
  12027                                       "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
  12028                 goto cleanup;
  12029             }
  12030             /* rx and tx counters are located at same index, but on diff mem */
  12031             if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  12032                 h_data_p->tx_ctr = h_data_p->rx_ctr;
  12033             }
  12034 
  12035             /* time stamp */
  12036             timestamp_type = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
  12037                                                l3_entry, LMEP__TIMESTAMP_TYPEf);
  12038             if (timestamp_type) {
  12039                 h_data_p->ts_format = timestamp_type;
  12040             } 
  12041             glp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, 
  12042                                                          LMEP__SGLPf);
  12043 
  12044             lmep_type = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, 
  12045                                                    LMEP__OAM_LMEP_KEY_SUBTYPEf);
  12046 
  12047             if (lmep_type == _BCM_OAM_DOMAIN_VP) { 
  12048 #if defined(INCLUDE_L3)
  12049                 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
  12050 
  12051                     BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  12052 
  12053                 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
  12054 
  12055                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  12056 
  12057                 } else {
  12058                     LOG_ERROR(BSL_LS_BCM_OAM,
  12059                               (BSL_META_U(unit,
  12060                                           "OAM Error: Invalid Virtual Port (SVP=%d)"
  12061                                            " - %s.\n"), h_data_p->vp,
  12062                                bcm_errmsg(BCM_E_INTERNAL)));
  12063                     return (BCM_E_INTERNAL);
  12064                 }
  12065 #endif
  12066             } else {
  12067                 /*
  12068                  * Generic logical port type, construct gport from GLP.
  12069                  */
  12070                 _bcm_gport_dest_t_init(&gport_dest);
  12071 
  12072                 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) {
  12073                     gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  12074                     gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  12075                     h_data_p->trunk_id =  _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  12076                 } else {
  12077                     gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  12078                     gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp);
  12079                     gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp);
  12080                 }
  12081 
  12082                 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  12083                 if (BCM_FAILURE(rv)) {
  12084                     LOG_ERROR(BSL_LS_BCM_OAM,
  12085                               (BSL_META_U(unit,
  12086                                           "OAM Error: Gport construct failed -"
  12087                                            " %s.\n"), bcm_errmsg(rv)));
  12088                     goto cleanup;
  12089                 }
  12090 
  12091                 h_data_p->gport = gport;
  12092             }
  12093             h_data_p->dglp = glp;
  12094             h_data_p->sglp = glp;
  12095 
  12096             sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
  12097             if (BCM_SUCCESS
  12098                     (_bcm_kt2_oam_find_egr_lmep(unit, h_data_p,
  12099                                                 &mp_grp_index,
  12100                                                 &egr_mp_group))) {
  12101                 mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  12102                         MDL_BITMAP_PASSIVEf);
  12103             }
  12104 
  12105             if (!(mdl_mip & (1 << h_data_p->level))) {
  12106                 /* Set the MIP flag */
  12107                 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  12108             }
  12109 
  12110             rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  12111             if (BCM_FAILURE(rv)) {
  12112                 goto cleanup;
  12113             }
  12114 
  12115             rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  12116             if (BCM_FAILURE(rv)) {
  12117                 LOG_ERROR(BSL_LS_BCM_OAM,
  12118                         (BSL_META_U(unit,
  12119                                     "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  12120                                     " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  12121                 _bcm_kt2_oam_group_ep_list_remove(unit,
  12122                                               h_data_p->group_index,
  12123                                               ep_id);
  12124                 goto cleanup;
  12125             } 
  12126 
  12127 
  12128             rv = _bcm_kt2_oam_endpoint_alloc(&ep_info);
  12129             if (BCM_FAILURE(rv)) {
  12130                 _bcm_kt2_oam_group_ep_list_remove(unit,
  12131                                               h_data_p->group_index,
  12132                                               ep_id);
  12133                 goto cleanup;
  12134             }
  12135 
  12136             bcm_oam_endpoint_info_t_init(ep_info);
  12137 
  12138             /* Set up endpoint information for key construction. */
  12139             ep_info->group = h_data_p->group_index;
  12140             ep_info->name = h_data_p->name;
  12141             ep_info->gport = h_data_p->gport;
  12142             ep_info->level = h_data_p->level;
  12143             ep_info->vlan = h_data_p->vlan;
  12144             ep_info->inner_vlan = h_data_p->inner_vlan;
  12145             if ((recovered_ver < BCM_WB_VERSION_1_5) 
  12146                     || (!ETH_TYPE(h_data_p->type))) {
  12147                 /*
  12148                  * Calculate hash key for hash table insert
  12149                  * operation.
  12150                  */
  12151                 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  12152 
  12153 
  12154                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  12155                 if (BCM_FAILURE(rv)) {
  12156                     LOG_ERROR(BSL_LS_BCM_OAM,
  12157                             (BSL_META_U(unit,
  12158                                         "OAM Error: Hash table insert"
  12159                                         " (EP=%d) failed - %s.\n"),
  12160                              h_data_p->ep_id, bcm_errmsg(rv)));
  12161 
  12162                     _bcm_kt2_oam_group_ep_list_remove(unit,
  12163                             h_data_p->group_index,
  12164                             ep_id);
  12165                     goto cleanup;
  12166                 } else {
  12167                     LOG_DEBUG(BSL_LS_BCM_OAM,
  12168                             (BSL_META_U(unit,
  12169                                         "OAM Info: Hash Tbl (EP=%d)"
  12170                                         " inserted  - %s.\n"), ep_id,
  12171                              bcm_errmsg(rv)));
  12172                 }
  12173             }
  12174             sal_free(ep_info);
  12175             ep_info = NULL;
  12176         }
  12177     } /* end of for loop */
  12178     
  12179     if (mdl_bitmap) {
  12180         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit,
  12181                     h_data_p, &ma_idx_entry_count, &pool));
  12182         rv = shr_idxres_list_reserve(pool,
  12183                                          h_data_p->ma_base_index,
  12184                                          h_data_p->ma_base_index + ma_idx_entry_count -1);
  12185         if (BCM_FAILURE(rv)) {
  12186             LOG_ERROR(BSL_LS_BCM_OAM,
  12187                       (BSL_META_U(unit,
  12188                                   "OAM Error: (RMEP=%d) Index reserve failed"
  12189                                    "  - %s.\n"), h_data_p->remote_index,
  12190                        bcm_errmsg(rv)));
  12191             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  12192             goto cleanup;
  12193         }
  12194     }
  12195 
  12196     LOG_DEBUG(BSL_LS_BCM_OAM,
  12197               (BSL_META_U(unit,
  12198                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  12199                            " - done.\n")));
  12200     return (BCM_E_NONE);
  12201 
  12202 cleanup:
  12203     tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  12204     if (BCM_FAILURE(tmp_rv)) {
  12205         LOG_DEBUG(BSL_LS_BCM_OAM,
  12206                   (BSL_META_U(unit,
  12207                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) "
  12208                               "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  12209     }
  12210 
  12211 
  12212     if (NULL != ep_info) {
  12213         sal_free(ep_info);
  12214     }
  12215 
  12216     if (BCM_E_EXISTS
  12217         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  12218         shr_idxres_list_free(oc->mep_pool, ep_id);
  12219     }
  12220     /* return rx & tx counters allocated if any */
  12221     if (NULL != h_data_p) {
  12222         rv =_bcm_kt2_oam_free_counter(unit, h_data_p);
  12223         if (BCM_FAILURE(rv)) {
  12224             LOG_ERROR(BSL_LS_BCM_OAM,
  12225                       (BSL_META_U(unit,
  12226                                   "OAM Error: LM counter block "
  12227                                   "free failed (EP=%d) - %s.\n"),
  12228                        ep_id, bcm_errmsg(rv)));
  12229         }
  12230     }
  12231     if (NULL != h_data_p && (BCM_E_EXISTS
  12232             == shr_idxres_list_elem_state(pool,
  12233                                           h_data_p->ma_base_index))) {
  12234 
  12235         shr_idxres_list_free(pool, h_data_p->ma_base_index);
  12236 
  12237     }
  12238     if (NULL != h_data_p) {
  12239         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  12240     }
  12241     LOG_DEBUG(BSL_LS_BCM_OAM,
  12242               (BSL_META_U(unit,
  12243                           "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover"
  12244                            " - error_done.\n")));
  12245     return (rv);
  12246 }
  12247 
  12248 /*
  12249  * Function:
  12250  *      _bcm_kt2_oam_lmep_tx_config_recover
  12251  * Purpose:
  12252  *     Recover OAM local endpoint Tx configuration.
  12253  * Parameters:
  12254  *     unit        - (IN) BCM device number
  12255  * Returns:
  12256  *     BCM_E_XXX
  12257  */
  12258 STATIC int
  12259 _bcm_kt2_oam_lmep_tx_config_recover(int unit,
  12260                                   uint8 **scache,
  12261                                   uint16 recovered_ver)
  12262 {
  12263     _bcm_gport_dest_t       gport_dest;   /* Gport specification.             */
  12264     bcm_gport_t             gport;        /* Gport value.                     */
  12265     int                     index;        /* Hardware index.                  */
  12266     lmep_entry_t            lmep_entry;   /* LMEP table entry buffer.         */
  12267     lmep_1_entry_t          lmep_1_entry; /* LMEP table entry buffer.         */
  12268     maid_reduction_entry_t  maid_red_ent; /* MAID_REDUCTION table entry buf.  */
  12269     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.      */
  12270     _bcm_oam_group_data_t   *g_info_p;    /* Group information pointer.       */
  12271     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
  12272     bcm_module_t            modid;        /* Module ID.                       */
  12273     bcm_port_t              port_id;      /* Port ID.                         */
  12274     bcm_trunk_t             trunk_id;     /* Trunk ID.                        */
  12275     uint32                  grp_idx;      /* Group index.                     */
  12276     uint16                  glp;          /* Generic logical port.            */
  12277     uint16                  vlan;         /* VLAN ID.                         */
  12278     uint16                  inner_vlan;   /* Inner VLAN ID.                   */
  12279     uint8                   level;        /* Maintenance domain level.        */
  12280     _bcm_oam_ep_list_t      *cur;         /* Current head node pointer.       */
  12281     int                     ep_id = -1;   /* Endpoint ID.                     */
  12282     uint8                   match_found = 0; /* Matching endpoint found.      */
  12283     int                     rv;           /* Operation return status.         */
  12284     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  12285     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer.  */
  12286     _bcm_oam_hash_data_t    sh_data; /* Endpoint hash data pointer. */
  12287     uint32                  ccm_period = 0;
  12288     egr_port_entry_t        egr_port_entry;
  12289     uint8                   mdl_mip = 0;
  12290     int                     trunk_index = -1;
  12291     int                     tpid_index = 0;
  12292 
  12293     LOG_DEBUG(BSL_LS_BCM_OAM,
  12294               (BSL_META_U(unit,
  12295                           "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover.\n")));
  12296 
  12297     /*
  12298      * Get OAM control structure.
  12299      *     Note: Lock taken by calling routine.
  12300      */
  12301     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  12302 
  12303     rv = _bcm_kt2_oam_endpoint_alloc(&ep_info);
  12304     if (BCM_FAILURE(rv)) {
  12305         return (rv);
  12306     }
  12307 
  12308     /*
  12309      * At this point, Remote MEP and Local MEP Rx config has been
  12310      *  recovered. Now, recover the Tx config for Local MEPs.
  12311      */
  12312     for (index = 0; index < oc->lmep_count; index++) {
  12313 
  12314         /* Get the LMEP table entry. */
  12315         rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry);
  12316         if (BCM_FAILURE(rv)) {
  12317             LOG_ERROR(BSL_LS_BCM_OAM,
  12318                       (BSL_META_U(unit,
  12319                                   "OAM Error: LMEP table read (index=%d) failed "
  12320                                    "- %s.\n"), index, bcm_errmsg(rv)));
  12321             goto cleanup;
  12322         }
  12323 
  12324         /* Get the LMEP_1 table entry. */
  12325         rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry);
  12326         if (BCM_FAILURE(rv)) {
  12327             LOG_ERROR(BSL_LS_BCM_OAM,
  12328                       (BSL_META_U(unit,
  12329                                   "OAM Error: LMEP_1 table read (index=%d) failed "
  12330                                    "- %s.\n"), index, bcm_errmsg(rv)));
  12331             goto cleanup;
  12332         }
  12333         ccm_period = _bcm_kt2_oam_ccm_hw_encode_to_msecs
  12334                       ((int) soc_LMEPm_field32_get(unit, &lmep_entry,
  12335                                                    CCM_INTERVALf));
  12336         if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) {
  12337             continue;
  12338         } 
  12339         grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf);
  12340 
  12341         rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent);
  12342         if (BCM_FAILURE(rv)) {
  12343             LOG_ERROR(BSL_LS_BCM_OAM,
  12344                       (BSL_META_U(unit,
  12345                                   "OAM Error: MAID_REDU read (GID=%d) failed "
  12346                                    "- %s.\n"), grp_idx, bcm_errmsg(rv)));
  12347             goto cleanup;
  12348         }
  12349 
  12350         if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) {
  12351 
  12352             /* Get pointer to group memory. */
  12353             g_info_p = &oc->group_info[grp_idx];
  12354 
  12355             vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf);
  12356             inner_vlan = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf);
  12357             /* Only extract the VLAN ID portion of the tag. */
  12358             inner_vlan = inner_vlan & 0xfff;
  12359             rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry);
  12360             if (BCM_FAILURE(rv)) {
  12361                 LOG_ERROR(BSL_LS_BCM_OAM,
  12362                           (BSL_META_U(unit,
  12363                                       "OAM Error: LMEP_1 table read (index=%d) "
  12364                                       "failed " "- %s.\n"), index, bcm_errmsg(rv)));
  12365                 goto cleanup;
  12366             }
  12367 
  12368             glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf);
  12369             rv = _bcm_kt2_pp_port_to_modport_get(unit, glp,
  12370                                                   &modid, &port_id);
  12371             if (BCM_FAILURE(rv)) {
  12372                 goto cleanup;
  12373             }
  12374 
  12375             level = soc_LMEPm_field32_get(unit, &lmep_entry, MDLf);
  12376 
  12377             trunk_id = BCM_TRUNK_INVALID;
  12378             if (vlan != 0 || inner_vlan != 0) {
  12379                 rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id);
  12380                 if (BCM_FAILURE(rv)
  12381                         && (BCM_E_NOT_FOUND != rv)) {
  12382                     goto cleanup;
  12383                 }
  12384             }
  12385 
  12386             _bcm_gport_dest_t_init(&gport_dest);
  12387 
  12388             if (BCM_TRUNK_INVALID != trunk_id) {
  12389                 gport_dest.tgid = trunk_id;
  12390                 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  12391  
  12392                 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 
  12393                         trunk_id, 
  12394                         port_id,
  12395                         &trunk_index);
  12396 
  12397                 if(BCM_FAILURE(rv)) {
  12398                     goto cleanup;
  12399                 }
  12400 
  12401             } else {
  12402                 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  12403                 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp);
  12404                 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp);
  12405             }
  12406 
  12407             rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  12408             if (BCM_FAILURE(rv)) {
  12409                 LOG_ERROR(BSL_LS_BCM_OAM,
  12410                           (BSL_META_U(unit,
  12411                                       "OAM Error: Gport construct failed"
  12412                                        " - %s.\n"), bcm_errmsg(rv)));
  12413                 goto cleanup;
  12414             }
  12415             /* Get the endpoint list head pointer. */
  12416             cur = *(g_info_p->ep_list);
  12417             if (NULL != cur) {
  12418                 while (NULL != cur) {
  12419                     h_data_p = cur->ep_data_p;
  12420                     if (NULL == h_data_p) {
  12421                         LOG_ERROR(BSL_LS_BCM_OAM,
  12422                                   (BSL_META_U(unit,
  12423                                               "OAM Error: Group (GID=%d) NULL"
  12424                                                " endpoint list.\n"), grp_idx));
  12425                         rv = BCM_E_INTERNAL;
  12426                         goto cleanup;
  12427                     }
  12428 
  12429                     if (vlan == h_data_p->vlan &&
  12430                         inner_vlan == h_data_p->inner_vlan 
  12431                         && gport == h_data_p->gport
  12432                         && level == h_data_p->level
  12433                         && 1 == h_data_p->local_rx_enabled) {
  12434                         match_found = 1;
  12435                         break;
  12436                     }
  12437                     cur = cur->next;
  12438                 }
  12439             }
  12440 
  12441             if (1 == match_found) {
  12442 
  12443                 bcm_oam_endpoint_info_t_init(ep_info);
  12444 
  12445                 /* Set up endpoint information for key construction. */
  12446                 ep_info->group = h_data_p->group_index;
  12447                 ep_info->name = h_data_p->name;
  12448                 ep_info->gport = h_data_p->gport;
  12449                 ep_info->level = h_data_p->level;
  12450                 ep_info->vlan = h_data_p->vlan;
  12451                 ep_info->inner_vlan = h_data_p->inner_vlan;
  12452                 ep_info->flags = h_data_p->flags;
  12453 
  12454                 if ((recovered_ver < BCM_WB_VERSION_1_5) 
  12455                         || (!ETH_TYPE(h_data_p->type))) {
  12456                     /*
  12457                      * Calculate hash key for hash table insert
  12458                      * operation.
  12459                      */
  12460                     _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, 
  12461                             &hash_key);
  12462 
  12463                     /*
  12464                      * Delete insert done by Local Rx endpoint recovery code.
  12465                      * Endpoint name has been recovered and will result
  12466                      * in a different hash index.
  12467                      */
  12468                     rv = shr_htb_find(oc->ma_mep_htbl, hash_key,
  12469                             (shr_htb_data_t *)&sh_data, 1);
  12470                     if (BCM_E_NOT_FOUND == rv) {
  12471                         goto cleanup;
  12472                     }
  12473                 }
  12474 
  12475             } else {
  12476                 
  12477                 if (recovered_ver >= BCM_WB_VERSION_1_3) {
  12478 
  12479                     sal_memcpy(&ep_id, 
  12480                             *(scache) + _BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(index), 
  12481                             sizeof(bcm_oam_endpoint_t));                
  12482 
  12483                     rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  12484                     if (BCM_FAILURE(rv)) {
  12485                         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  12486                         LOG_ERROR(BSL_LS_BCM_OAM,
  12487                                 (BSL_META_U(unit,
  12488                                             "OAM Error: (EP_ID=%d) Index reserve "
  12489                                             " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  12490                         goto cleanup;
  12491                     }
  12492                 } else {
  12493 
  12494                     /* Allocate the next available endpoint index. */
  12495                     rv = shr_idxres_list_alloc(oc->mep_pool,
  12496                             (shr_idxres_element_t *)&ep_id);
  12497                     if (BCM_FAILURE(rv)) {
  12498                         LOG_ERROR(BSL_LS_BCM_OAM,
  12499                                 (BSL_META_U(unit,
  12500                                             "OAM Error: Endpoint alloc (EP=%d)"
  12501                                             " - %s.\n"), ep_id, bcm_errmsg(rv)));
  12502                         goto cleanup;
  12503                     }
  12504                 }
  12505                 h_data_p = &oc->oam_hash_data[ep_id];
  12506                 if (1 == h_data_p->in_use) {
  12507                     rv = BCM_E_INTERNAL;
  12508                     goto cleanup;
  12509                 }
  12510 
  12511                 _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  12512 
  12513                 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  12514 
  12515                 rv = _bcm_kt2_oam_group_ep_list_add(unit, grp_idx, ep_id);
  12516                 if (BCM_FAILURE(rv)) {
  12517                     LOG_ERROR(BSL_LS_BCM_OAM,
  12518                               (BSL_META_U(unit,
  12519                                           "OAM Error: Adding (EP=%d)"
  12520                                            " to (GID=%d) failed - %s.\n"),
  12521                                ep_id, grp_idx, bcm_errmsg(rv)));
  12522                     goto cleanup;
  12523                 }
  12524 
  12525                 h_data_p->ep_id = ep_id;
  12526                 h_data_p->group_index = grp_idx;
  12527                 h_data_p->local_rx_enabled = 0;
  12528                 h_data_p->vlan = vlan;
  12529                 h_data_p->inner_vlan = inner_vlan;
  12530                 h_data_p->gport = gport;
  12531                 h_data_p->level = level;
  12532                 if ((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) {
  12533                     h_data_p->oam_domain = _BCM_OAM_DOMAIN_PORT; 
  12534                 } 
  12535                 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  12536                 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  12537                 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  12538                 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  12539                 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  12540                 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  12541                 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  12542                 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  12543                 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  12544                 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  12545                 h_data_p->trunk_id =  BCM_TRUNK_INVALID;
  12546             }
  12547 
  12548             h_data_p->src_pp_port = glp;
  12549             h_data_p->dst_pp_port = glp;
  12550             h_data_p->is_remote = 0;
  12551             h_data_p->in_use = 1;
  12552             h_data_p->local_tx_enabled = 1;
  12553             h_data_p->local_tx_index = index;
  12554             
  12555             if((-1) != trunk_index) {
  12556                 h_data_p->trunk_index = trunk_index;
  12557             }
  12558 
  12559             h_data_p->name
  12560                 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf);
  12561             h_data_p->period
  12562                 = _bcm_kt2_oam_ccm_hw_encode_to_msecs
  12563                       ((int) soc_LMEPm_field32_get(unit, &lmep_entry,
  12564                                                    CCM_INTERVALf));
  12565 
  12566             if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) {
  12567                 h_data_p->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW;
  12568             }
  12569             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_PORT) {
  12570                 rv = _bcm_kt2_oam_port_table_key_update(unit, PORT_TABm, h_data_p);
  12571                 if (BCM_FAILURE(rv)) {
  12572                     LOG_ERROR(BSL_LS_BCM_OAM,
  12573                               (BSL_META_U(unit,
  12574                                           "OAM Error: Unable to increment key ref count "
  12575                                            " - %s.\n"), bcm_errmsg(rv)));
  12576                     goto cleanup;
  12577                 } 
  12578                 rv = _bcm_kt2_oam_port_table_key_update(unit, EGR_PORTm, h_data_p);
  12579                 if (BCM_FAILURE(rv)) {
  12580                     LOG_ERROR(BSL_LS_BCM_OAM,
  12581                               (BSL_META_U(unit,
  12582                                           "OAM Error: Unable to increment key ref count "
  12583                                            " - %s.\n"), bcm_errmsg(rv)));
  12584                     goto cleanup;
  12585                 }
  12586             } else {
  12587                 rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY,
  12588                                   h_data_p->dst_pp_port, &egr_port_entry);
  12589                 if (BCM_FAILURE(rv)) {
  12590                     LOG_ERROR(BSL_LS_BCM_OAM,
  12591                             (BSL_META_U(unit,
  12592                              "OAM Error: EGR_PORT Table read failed"
  12593                              " - %s.\n"), bcm_errmsg(rv)));
  12594                     goto cleanup;
  12595                 }
  12596                 mdl_mip = soc_EGR_PORTm_field32_get(unit, &egr_port_entry,
  12597                         MDL_BITMAP_PASSIVEf);
  12598                 if (!(mdl_mip & (1 << h_data_p->level))) {
  12599                     /* Set the MIP flag */
  12600                     h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  12601                 }
  12602             }
  12603 
  12604             /* For ethernet CCM TX endpoints, fetch TPIDs from HW.
  12605              */
  12606             if (h_data_p->vlan != 0) {
  12607                 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 
  12608                         SVLAN_TPID_INDEXf);
  12609                 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_OUTER,
  12610                         tpid_index, &(h_data_p->outer_tpid));
  12611                 if (BCM_FAILURE(rv)) {
  12612                     LOG_ERROR(BSL_LS_BCM_OAM,
  12613                             (BSL_META_U(unit,
  12614                                         "OAM(unit %d) Error: Outer TPID fetch failed"
  12615                                         " EP=%d %s.\n"), unit, ep_id, 
  12616                              bcm_errmsg(rv)));
  12617                     goto cleanup;
  12618                 }
  12619                 h_data_p->outer_tpid_profile_index = tpid_index;
  12620                 KT2_OAM_OUTER_TPID_REF_COUNT(unit, tpid_index)++;
  12621             }
  12622 
  12623             if (h_data_p->inner_vlan != 0) {
  12624                 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_INNER,
  12625                         0, &(h_data_p->inner_tpid));
  12626                 if (BCM_FAILURE(rv)) {
  12627                     LOG_ERROR(BSL_LS_BCM_OAM,
  12628                             (BSL_META_U(unit,
  12629                                         "OAM(unit %d) Error: Inner TPID fetch failed"
  12630                                         " EP=%d %s.\n"), unit, ep_id, 
  12631                              bcm_errmsg(rv)));
  12632                     goto cleanup;
  12633                 }
  12634                 h_data_p->inner_tpid_profile_index = 0;
  12635                 KT2_OAM_INNER_TPID_REF_COUNT(unit, 0)++;
  12636             }
  12637 
  12638             if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) &&
  12639                     (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport))) {
  12640                 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 
  12641                         SUBPORT_TAG_TPID_INDEXf);
  12642                 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_SUBPORT,
  12643                         tpid_index, &(h_data_p->subport_tpid));
  12644                 if (BCM_FAILURE(rv)) {
  12645                     LOG_ERROR(BSL_LS_BCM_OAM,
  12646                             (BSL_META_U(unit,
  12647                                         "OAM(unit %d) Error: Subport TPID fetch failed"
  12648                                         " EP=%d %s.\n"), unit, ep_id, 
  12649                              bcm_errmsg(rv)));
  12650                     goto cleanup;
  12651                 }
  12652                 h_data_p->subport_tpid_profile_index = tpid_index;
  12653                 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, tpid_index)++;
  12654             }
  12655 
  12656             rv = shr_idxres_list_reserve(oc->lmep_pool,
  12657                                          h_data_p->local_tx_index,
  12658                                          h_data_p->local_tx_index);
  12659             if (BCM_FAILURE(rv)) {
  12660                 LOG_ERROR(BSL_LS_BCM_OAM,
  12661                           (BSL_META_U(unit,
  12662                                       "OAM Error: Tx index=%d reserve failed"
  12663                                        " - %s.\n"), index, bcm_errmsg(rv)));
  12664 
  12665                 _bcm_kt2_oam_group_ep_list_remove(unit,
  12666                                               h_data_p->group_index,
  12667                                               h_data_p->ep_id);
  12668 
  12669                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  12670                 goto cleanup;
  12671             }
  12672 
  12673             bcm_oam_endpoint_info_t_init(ep_info);
  12674 
  12675             /* Set up endpoint information for key construction. */
  12676             ep_info->group = h_data_p->group_index;
  12677             ep_info->name = h_data_p->name;
  12678             ep_info->gport = h_data_p->gport;
  12679             ep_info->level = h_data_p->level;
  12680             ep_info->vlan = h_data_p->vlan;
  12681             ep_info->inner_vlan = h_data_p->inner_vlan;
  12682             ep_info->flags = h_data_p->flags;
  12683 
  12684             if ((recovered_ver < BCM_WB_VERSION_1_5) 
  12685                     || (!ETH_TYPE(h_data_p->type))) {
  12686                 /*
  12687                  * Calculate hash key for hash table insert
  12688                  * operation.
  12689                  */
  12690                 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  12691 
  12692                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  12693                 if (BCM_FAILURE(rv)) {
  12694                     LOG_ERROR(BSL_LS_BCM_OAM,
  12695                             (BSL_META_U(unit,
  12696                                         "OAM Error: Hash table insert"
  12697                                         " (EP=%d) failed - %s.\n"),
  12698                              h_data_p->ep_id, bcm_errmsg(rv)));
  12699 
  12700                     _bcm_kt2_oam_group_ep_list_remove(unit,
  12701                             h_data_p->group_index,
  12702                             h_data_p->ep_id);
  12703 
  12704                     goto cleanup;
  12705                 } else {
  12706                     LOG_DEBUG(BSL_LS_BCM_OAM,
  12707                             (BSL_META_U(unit,
  12708                                         "OAM Info: Hash Tbl (EP=%d)"
  12709                                         " inserted  - %s.\n"), h_data_p->ep_id,
  12710                              bcm_errmsg(rv)));
  12711                 }
  12712             }
  12713 
  12714         }
  12715 
  12716         match_found = 0;
  12717         h_data_p = NULL;
  12718     }
  12719 
  12720     LOG_DEBUG(BSL_LS_BCM_OAM,
  12721               (BSL_META_U(unit,
  12722                           "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover"
  12723                            " - done.\n")));
  12724     sal_free(ep_info);
  12725     return (rv);
  12726 
  12727 cleanup:
  12728 
  12729     if (NULL != ep_info) {
  12730         sal_free(ep_info);
  12731     }
  12732 
  12733     if (0 == match_found && NULL != h_data_p) {
  12734         /* Return endpoint index to MEP pool. */
  12735         if (BCM_E_EXISTS
  12736             == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  12737             shr_idxres_list_free(oc->mep_pool, ep_id);
  12738         }
  12739         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  12740     }
  12741 
  12742     if (BCM_E_EXISTS
  12743         == shr_idxres_list_elem_state(oc->lmep_pool, index)) {
  12744         shr_idxres_list_free(oc->lmep_pool, index);
  12745     }
  12746 
  12747     LOG_DEBUG(BSL_LS_BCM_OAM,
  12748               (BSL_META_U(unit,
  12749                           "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover"
  12750                            " - error_done.\n")));
  12751     return (rv);
  12752 }
  12753 
  12754 /*
  12755  * Function:
  12756  *     _bcm_kt2_oam_wb_endpoints_recover
  12757  * Purpose:
  12758  *     Recover OAM local endpoint Rx configuration.
  12759  * Parameters:
  12760  *     unit        - Device unit number.
  12761  *     stable_size - OAM module Level2 memory size.
  12762  *     oam_scache  - Pointer to secondary storage buffer pointer.
  12763  * Returns:
  12764  *     BCM_E_XXX
  12765  */
  12766 STATIC int
  12767 _bcm_kt2_oam_wb_endpoints_recover(int unit,
  12768                                   int stable_size,
  12769                                   uint8 **oam_scache,
  12770                                   uint16 recovered_ver)
  12771 {
  12772     int                     index;        /* Hardware index.                  */
  12773     uint32                  entry_count;  /* Max entries in L3_ENTRY_1/
  12774                                                           EGR_MP_GROUP table. */
  12775     l3_entry_1_entry_t      l3_entry;     /* L3 table entry.                  */
  12776     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
  12777     int                     rv;           /* Operation return status.         */
  12778     egr_mp_group_entry_t    egr_mp_grp_entry;/* Egr MP group tbl entry buffer */
  12779     port_tab_entry_t        port_entry;   /* Port table entry buffer          */
  12780 
  12781     /*
  12782      * Get OAM control structure.
  12783      *     Note: Lock taken by calling routine.
  12784      */
  12785     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  12786 
  12787     /* Get number of L3 table entries. */
  12788     entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm);
  12789 
  12790     /* Now get valid OAM endpoint entries. */
  12791     for (index = 0; index < entry_count; index++) {
  12792 
  12793         rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, index, &l3_entry);
  12794         if (BCM_FAILURE(rv)) {
  12795             LOG_ERROR(BSL_LS_BCM_OAM,
  12796                       (BSL_META_U(unit,
  12797                                   "OAM Error: L3_ENTRY (index=%d) read"
  12798                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
  12799                 return (rv);
  12800         }
  12801 
  12802         if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf)) {
  12803 
  12804             switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 
  12805                                                           KEY_TYPEf)) {
  12806 
  12807                 case SOC_MEM_KEY_L3_ENTRY_RMEP:
  12808                     rv = _bcm_kt2_oam_rmep_recover(unit, index,
  12809                                                    &l3_entry, oam_scache, recovered_ver);
  12810                     if (BCM_FAILURE(rv)) {
  12811                         LOG_ERROR(BSL_LS_BCM_OAM,
  12812                                   (BSL_META_U(unit,
  12813                                               "OAM Error: Remote endpoint"
  12814                                                " (index=%d) reconstruct failed  - %s.\n"),
  12815                                    index, bcm_errmsg(rv)));
  12816                         return (rv);
  12817                     }
  12818                     break;
  12819 
  12820                 /* Recover all downMEP's */
  12821                 case SOC_MEM_KEY_L3_ENTRY_LMEP:
  12822                     rv = _bcm_kt2_oam_lmep_downmep_rx_config_recover(unit,
  12823                                                              index,
  12824                                                              &l3_entry,
  12825                                                              oam_scache,
  12826                                                              recovered_ver);
  12827                     if (BCM_FAILURE(rv)) {
  12828                         LOG_ERROR(BSL_LS_BCM_OAM,
  12829                                   (BSL_META_U(unit,
  12830                                               "OAM Error: Local endpoint DownMEP"
  12831                                                " (index=%d) reconstruct failed  - %s.\n"),
  12832                                    index, bcm_errmsg(rv)));
  12833                         return (rv);
  12834                     }
  12835                     break;
  12836 
  12837                 default:
  12838                     /* Not an OAM entry. */
  12839                     continue;
  12840             }
  12841         }
  12842     }
  12843     /* Recover all UpMEPs */
  12844     /* Get number of EGR_MP_GROUP table entries. */
  12845     entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm);
  12846 
  12847     /* Now get valid OAM endpoint entries. */
  12848     for (index = 0; index < entry_count; index++) {
  12849         rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry);
  12850         if (BCM_FAILURE(rv)) {
  12851             LOG_ERROR(BSL_LS_BCM_OAM,
  12852                       (BSL_META_U(unit,
  12853                                   "OAM Error: EGR_MP_GROUP ENTRY (index=%d) read"
  12854                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
  12855                 return (rv);
  12856         }
  12857         if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) {
  12858             rv = _bcm_kt2_oam_lmep_upmep_rx_config_recover(unit, index,
  12859                                                              &egr_mp_grp_entry, oam_scache, recovered_ver);
  12860             if (BCM_FAILURE(rv)) {
  12861                 LOG_ERROR(BSL_LS_BCM_OAM,
  12862                           (BSL_META_U(unit,
  12863                                       "OAM Error: Local endpoint UpMEP"
  12864                                        " (index=%d) reconstruct failed  - %s.\n"),
  12865                            index, bcm_errmsg(rv)));
  12866                 return (rv);
  12867             }
  12868         }
  12869     } 
  12870 
  12871     /* recover endpoints from Port table */
  12872     /* Get number of PORT_TABLE table entries. */
  12873     entry_count = soc_mem_index_count(unit, PORT_TABm);
  12874     /* Now get valid OAM endpoint entries. */
  12875     for (index = 0; index < entry_count; index++) {
  12876         rv = READ_PORT_TABm(unit, MEM_BLOCK_ANY, index, &port_entry);
  12877         if (BCM_FAILURE(rv)) {
  12878             LOG_ERROR(BSL_LS_BCM_OAM,
  12879                       (BSL_META_U(unit,
  12880                                   "OAM Error: Port table ENTRY (index=%d) read"
  12881                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
  12882                 return (rv);
  12883         }
  12884         if (soc_PORT_TABm_field32_get(unit, &port_entry, OAM_ENABLEf)) {
  12885             rv = _bcm_kt2_oam_port_lmep_rx_config_recover(unit, index,
  12886                                                              &port_entry,
  12887                                                              oam_scache, recovered_ver);
  12888             if (BCM_FAILURE(rv)) {
  12889                 LOG_ERROR(BSL_LS_BCM_OAM,
  12890                           (BSL_META_U(unit,
  12891                                       "OAM Error: Port based local endpoint "
  12892                                        " (index=%d) reconstruct failed  - %s.\n"),
  12893                            index, bcm_errmsg(rv)));
  12894                 return (rv);
  12895             }
  12896         }
  12897     } 
  12898     rv = _bcm_kt2_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver);
  12899     if (BCM_FAILURE(rv)) {
  12900         LOG_ERROR(BSL_LS_BCM_OAM,
  12901                   (BSL_META_U(unit,
  12902                               "OAM Error: Endpoint Tx config recovery"
  12903                                " failed  - %s.\n"), bcm_errmsg(rv)));
  12904         return (rv);
  12905     }
  12906 
  12907     return (BCM_E_NONE);
  12908 }
  12909 
  12910 /*
  12911  * Function:
  12912  *       bcm_kt2_oam_scache_alloc
  12913  * Purpose:
  12914  *     Allocate scache memory for OAM module 
  12915  * Parameters:
  12916  *     unit - (IN) BCM device number
  12917  * Returns:
  12918  *     BCM_E_UNIT    - Invalid BCM unit number.
  12919  *     BCM_E_UNAVAIL - OAM not support on this device.
  12920  *     BCM_E_MEMORY  - Allocation failure
  12921  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
  12922  *     BCM_E_NONE    - Success
  12923  */
  12924 STATIC int
  12925 bcm_kt2_oam_scache_alloc(int unit) {
  12926     _bcm_oam_control_t *oc;
  12927     soc_scache_handle_t scache_handle;
  12928     uint8 *oam_scache;
  12929     int alloc_sz = 0;
  12930 
  12931 
  12932     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  12933 
  12934     alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
  12935 
  12936     /* Number of oam groups */
  12937     alloc_sz += sizeof(int);
  12938 
  12939     /* VFP group, IFP VP group, IFP GLP group */
  12940     alloc_sz += 3 * sizeof(bcm_field_group_t);
  12941     
  12942     /* Allocate memory to store logical endpoint Ids */
  12943     alloc_sz += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  12944 
  12945     /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */
  12946     alloc_sz += sizeof(uint8);
  12947 
  12948     /* FLAGS are stored for all ethernet OAM endpoints */
  12949     alloc_sz += (sizeof(uint32) * oc->ep_count);
  12950 
  12951     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  12952     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
  12953                         alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL));
  12954     return BCM_E_NONE;
  12955 }
  12956 
  12957 /* Given h_data_p, this function fills the endpoint_info required for
  12958  * hash_key generation and inserts it at appropriate location.
  12959  *
  12960  * oc->lock is already assumed to be taken by caller */
  12961 int _bcm_kt2_oam_hash_tbl_insert_hash_data_entry(int unit, _bcm_oam_hash_data_t *h_data_p)
  12962 {
  12963     bcm_oam_endpoint_info_t ep_info;
  12964     _bcm_oam_control_t  *oc = NULL;                  /* Pointer to OAM control structure. */
  12965     _bcm_oam_hash_key_t     hash_key;                /* Hash key buffer for lookup.      */
  12966     int rv = BCM_E_NONE;
  12967 
  12968 
  12969     if (h_data_p == NULL) {
  12970         return BCM_E_INTERNAL;
  12971     }
  12972 
  12973     /* Get OAM control structure. */
  12974     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  12975 
  12976     /* Initialize endpoint info structure. */
  12977     bcm_oam_endpoint_info_t_init(&ep_info);
  12978 
  12979     /* Set up endpoint information for key construction. */
  12980     ep_info.group = h_data_p->group_index;
  12981     ep_info.name = h_data_p->name;
  12982     ep_info.gport = h_data_p->gport;
  12983     ep_info.level = h_data_p->level;
  12984     ep_info.vlan = h_data_p->vlan;
  12985     ep_info.inner_vlan = h_data_p->inner_vlan;
  12986     ep_info.flags = h_data_p->flags;
  12987 
  12988     /* Construct hash key for lookup */
  12989     _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
  12990 
  12991     /* Insert entry from hash table. */
  12992     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  12993     if (BCM_FAILURE(rv)) {
  12994         LOG_ERROR(BSL_LS_BCM_OAM,
  12995                   (BSL_META_U(unit,
  12996                               "OAM(unit %d) Error: Hash table insert failed "
  12997                                "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  12998     } else {
  12999         LOG_DEBUG(BSL_LS_BCM_OAM,
  13000                   (BSL_META_U(unit,
  13001                               "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted"
  13002                                " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13003     }
  13004 
  13005     return rv;
  13006 }
  13007 
  13008 
  13009 /*
  13010  * Function:
  13011  *     _bcm_kt2_oam_reinit
  13012  * Purpose:
  13013  *     Reconstruct OAM module software state.
  13014  * Parameters:
  13015  *     unit - (IN) BCM device number
  13016  * Retruns:
  13017  *     BCM_E_XXX
  13018  */
  13019 STATIC int
  13020 _bcm_kt2_oam_reinit(int unit)
  13021 {
  13022     uint32              group_count = 0; /* Stored OAM group count.           */
  13023     int                 stable_size = 0; /* Secondary storage size.           */
  13024     uint8               *oam_scache;     /* Pointer to scache memory.         */
  13025     soc_scache_handle_t scache_handle;   /* Scache memory handler.            */
  13026     _bcm_oam_control_t  *oc;             /* Pointer to OAM control structure. */
  13027     int                 rv;              /* Operation return status.          */
  13028     uint16              recovered_ver = 0;
  13029     int                 realloc_size = 0;
  13030     int                 idx = 0;
  13031     _bcm_oam_hash_data_t    *h_data_p = NULL;       /* Endpoint hash data pointer.   */
  13032 
  13033     LOG_DEBUG(BSL_LS_BCM_OAM,
  13034               (BSL_META_U(unit,
  13035                           "OAM Info: OAM warm boot recovery.....\n")));
  13036 
  13037     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  13038 
  13039     /* Get OAM control structure. */
  13040     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  13041 
  13042     _BCM_OAM_LOCK(oc);
  13043 
  13044     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
  13045 
  13046         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  13047 
  13048         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
  13049                                      &oam_scache, BCM_WB_DEFAULT_VERSION,
  13050                                      &recovered_ver);
  13051         if (BCM_E_NOT_FOUND == rv) {
  13052             /* Upgrading from SDK release that does not have warmboot state */
  13053             bcm_kt2_oam_scache_alloc(unit);
  13054             _BCM_OAM_UNLOCK(oc);
  13055             return BCM_E_NONE;
  13056         } else if (BCM_FAILURE(rv)) {
  13057             goto cleanup;
  13058         } else {
  13059             if (recovered_ver < BCM_WB_VERSION_1_2 && MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) {
  13060                 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Warn:"
  13061                                 " Warm upgrade from a older version which does not support "
  13062                                 "flexible endpoint hw index allocation. Reverting to older "
  13063                                 "scheme.\n")));
  13064                 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL;
  13065                 /* Destroy the previous allocation and re-allocate based on this scheme */
  13066                 rv = _bcm_kt2_oam_ma_idx_pool_destroy(oc);
  13067                 if (BCM_FAILURE(rv)) {
  13068                     goto cleanup;
  13069                 }
  13070                 rv = _bcm_kt2_oam_ma_idx_pool_create(oc);
  13071                 if (BCM_FAILURE(rv)) {
  13072                     goto cleanup;
  13073                 }
  13074             }
  13075 
  13076             /* Recover the FP groups */
  13077             sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t));
  13078             oam_scache += sizeof(bcm_field_group_t);
  13079 
  13080             sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t));
  13081             oam_scache += sizeof(bcm_field_group_t);
  13082 
  13083             sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t));
  13084             oam_scache += sizeof(bcm_field_group_t);
  13085 
  13086             /* Recover the OAM groups */
  13087             sal_memcpy(&group_count, oam_scache, sizeof(int));
  13088             oam_scache += sizeof(int);
  13089             
  13090         }
  13091     } else {
  13092         rv = BCM_E_NONE;
  13093         goto cleanup;
  13094     }
  13095 
  13096     rv = _bcm_kt2_oam_wb_group_recover(unit, stable_size, &oam_scache);
  13097     
  13098     if (BCM_FAILURE(rv)) {
  13099         LOG_ERROR(BSL_LS_BCM_OAM,
  13100                   (BSL_META_U(unit,
  13101                               "OAM Error: Group recovery failed  - %s.\n"),
  13102                    bcm_errmsg(rv)));
  13103         goto cleanup;
  13104     }
  13105 
  13106     rv = _bcm_kt2_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, recovered_ver);
  13107     if (BCM_FAILURE(rv)) {
  13108         LOG_ERROR(BSL_LS_BCM_OAM,
  13109                   (BSL_META_U(unit,
  13110                               "OAM Error: Endpoint recovery failed  - %s.\n"),
  13111                    bcm_errmsg(rv)));
  13112         goto cleanup;
  13113     }
  13114     
  13115     if(recovered_ver >= BCM_WB_VERSION_1_3) {
  13116         oam_scache += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  13117     }
  13118 
  13119     if (recovered_ver >= BCM_WB_VERSION_1_4) {
  13120         sal_memcpy(&oc->eth_oam_mp_group_vlan_key, oam_scache, sizeof(uint8));
  13121         oam_scache += sizeof(uint8);
  13122     } else {
  13123         oc->eth_oam_mp_group_vlan_key =
  13124                                _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT;
  13125     }
  13126     if (recovered_ver >= BCM_WB_VERSION_1_5) {
  13127         for (idx = 0; idx < oc->ep_count; idx++) {
  13128             h_data_p = &oc->oam_hash_data[idx];
  13129             if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) {
  13130                 sal_memcpy(&(h_data_p->flags), oam_scache, sizeof(uint32));
  13131                 rv = _bcm_kt2_oam_hash_tbl_insert_hash_data_entry(unit, h_data_p);
  13132                 if (BCM_FAILURE(rv)) {
  13133                     LOG_ERROR(BSL_LS_BCM_OAM,
  13134                             (BSL_META_U(unit,
  13135                                         "OAM(unit %d) Error: Endpoint %d hash tbl insert failed  - %s.\n"),
  13136                              unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13137                     goto cleanup;
  13138                 }
  13139             }
  13140             oam_scache += sizeof(uint32);
  13141         }
  13142     }
  13143 
  13144     /* In BCM_WB_VERSION_1_1 onwards we allocate memory for max OAM groups and
  13145        not just the groups created, as such while upgrading from 
  13146        BCM_WB_VERSION_1_0 to BCM_WB_VERSION_1_1 or greater we must add the 
  13147        differential.
  13148     */
  13149     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
  13150         if (recovered_ver < BCM_WB_VERSION_1_1) {
  13151             realloc_size += (BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count - group_count));
  13152         }
  13153 
  13154         /* BCM_WB_VERSION_1_3 onwards addition memory is used to store
  13155          * software endpoint ids */
  13156         if(recovered_ver < BCM_WB_VERSION_1_3) {
  13157             realloc_size += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  13158 
  13159         }
  13160 
  13161         if (recovered_ver < BCM_WB_VERSION_1_4) {
  13162             realloc_size += sizeof(uint8);
  13163         }
  13164 
  13165         if (recovered_ver < BCM_WB_VERSION_1_5) {
  13166             realloc_size += (sizeof(uint32) * oc->ep_count);
  13167         }
  13168 
  13169         /* Added the check to avoid any like-to-like recovery where realloc is not required */
  13170         if (realloc_size) {
  13171             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  13172             rv = soc_scache_realloc(unit, scache_handle, realloc_size);
  13173             if (SOC_FAILURE(rv)) {
  13174                 LOG_ERROR(BSL_LS_BCM_OAM,
  13175                         (BSL_META_U(unit,
  13176                                     "OAM(unit %d) Error: scache alloc failed"
  13177                                     "  - %s.\n"),
  13178                          unit, bcm_errmsg(rv)));
  13179                 goto cleanup;
  13180             }
  13181         }
  13182     }
  13183 
  13184  
  13185 cleanup:
  13186     _BCM_OAM_UNLOCK(oc);
  13187     return (rv);
  13188 }
  13189 
  13190 #if defined(INCLUDE_BHH)
  13191 /*
  13192  * Function:
  13193  *     _bcm_kt2_oam_bhh_cos_map_recover
  13194  * Purpose:
  13195  *     Reconstruct CoS Map config done for BHH
  13196  * Parameters:
  13197  *     unit - (IN) BCM device number
  13198  * Retruns:
  13199  *     BCM_E_XXX
  13200  */
  13201 STATIC int
  13202 _bcm_kt2_oam_bhh_cos_map_recover(int unit)
  13203 {
  13204     int                    rv = BCM_E_NONE;
  13205     _bcm_oam_control_t     *oc;
  13206     int                    index;
  13207     int                    cosq_map_size;
  13208     bcm_rx_reasons_t       reasons, reasons_mask;
  13209     bcm_rx_reasons_t       ach_error_reasons, invalid_error_reasons;
  13210     bcm_rx_reasons_t       bhh_lb_reasons;
  13211     uint8                  int_prio, int_prio_mask;
  13212     uint32                 packet_type, packet_type_mask;
  13213     bcm_cos_queue_t        cosq;
  13214 
  13215     /* Get OAM Control Structure. */
  13216     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  13217     _BCM_OAM_LOCK(oc);
  13218 
  13219     if (oc->ukernel_not_ready) {
  13220         _BCM_OAM_UNLOCK(oc);
  13221         return BCM_E_NONE;
  13222     }
  13223 
  13224     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  13225     if(BCM_FAILURE(rv)) {
  13226         LOG_ERROR(BSL_LS_BCM_OAM,
  13227                   (BSL_META_U(unit,
  13228                               "BHH Error:hw init. cosq maps size %s.\n"),
  13229                    bcm_errmsg(rv)));
  13230         _BCM_OAM_UNLOCK(oc);
  13231         return (rv);
  13232     }
  13233 
  13234     BCM_RX_REASON_CLEAR_ALL(ach_error_reasons);
  13235     BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonBHHOAM);
  13236     BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonOAMCCMSlowpath);
  13237 
  13238     BCM_RX_REASON_CLEAR_ALL(invalid_error_reasons);
  13239     BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonBHHOAM);
  13240     BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonOAMLMDM);
  13241 
  13242     BCM_RX_REASON_CLEAR_ALL(bhh_lb_reasons);
  13243     BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonBHHOAM);
  13244     BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonOAMSlowpath);
  13245 
  13246     oc->cpu_cosq_ach_error_index       = -1;
  13247     oc->cpu_cosq_invalid_error_index   = -1;
  13248     oc->bhh_lb_index                   = -1;
  13249     for (index = 0; index < cosq_map_size; index++) {
  13250         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  13251                                          &reasons, &reasons_mask,
  13252                                          &int_prio, &int_prio_mask,
  13253                                          &packet_type, &packet_type_mask,
  13254                                          &cosq);
  13255         if (rv == BCM_E_NONE) {
  13256 
  13257             if (BCM_RX_REASON_EQ(reasons, ach_error_reasons) &&
  13258                 BCM_RX_REASON_EQ(reasons_mask, ach_error_reasons)) {
  13259                 oc->cpu_cosq_ach_error_index = index;
  13260                 oc->cpu_cosq = cosq;
  13261             } else if (BCM_RX_REASON_EQ(reasons, invalid_error_reasons) &&
  13262                        BCM_RX_REASON_EQ(reasons_mask, invalid_error_reasons)) {
  13263                 oc->cpu_cosq_invalid_error_index = index;
  13264             } else if (BCM_RX_REASON_EQ(reasons, bhh_lb_reasons) &&
  13265                        BCM_RX_REASON_EQ(reasons_mask, bhh_lb_reasons)) {
  13266                 oc->bhh_lb_index = index;
  13267             }
  13268         }
  13269         if( -1 != oc->cpu_cosq_ach_error_index         &&
  13270             -1 != oc->cpu_cosq_invalid_error_index     &&
  13271             -1 != oc->bhh_lb_index) {
  13272             break;
  13273         }
  13274     }
  13275 
  13276     if (index >= cosq_map_size) {
  13277         LOG_VERBOSE(BSL_LS_BCM_OAM,
  13278                   (BSL_META_U(unit,
  13279                             "BHH Error: Could not recover cos map entry \n")));
  13280     }
  13281 
  13282     _BCM_OAM_UNLOCK(oc);
  13283     return rv;
  13284 }
  13285 #endif /* INCLUDE_BHH */
  13286 #endif /* BCM_WARM_BOOT_SUPPORT */
  13287 
  13288 STATIC int
  13289 _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(int unit,
  13290                        _bcm_oam_hash_data_t *h_data_p,
  13291                               int *num_ma_idx_entries,
  13292                        shr_idxres_list_handle_t *pool)
  13293 {
  13294     _bcm_oam_control_t *oc = NULL; 
  13295 
  13296     /* Get OAM control structure handle. */
  13297     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  13298 
  13299     if ((h_data_p == NULL) || (h_data_p->in_use == 0)) {
  13300         return BCM_E_PARAM;
  13301     }
  13302 
  13303     switch (oc->ma_idx_alloc_scheme) {
  13304         case _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL:
  13305             *num_ma_idx_entries = 8;
  13306             *pool = oc->ma_idx_pool;
  13307             return BCM_E_NONE;
  13308             break;
  13309         case _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL:
  13310             if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  13311                 *num_ma_idx_entries = 8;
  13312                 *pool = oc->ma_idx_pool;
  13313             } else if (BHH_EP_TYPE(h_data_p)) {
  13314                 *num_ma_idx_entries = 1;
  13315                 *pool = oc->mpls_oam_ma_idx_pool;
  13316             }
  13317             return BCM_E_NONE;
  13318             break;
  13319         default:
  13320             /* Should not hit */
  13321             break;
  13322     }
  13323     return BCM_E_INTERNAL; 
  13324 }
  13325 
  13326 STATIC int
  13327 _bcm_kt2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc)
  13328 {
  13329     int rv = BCM_E_NONE;
  13330 
  13331     if (MA_INDEX_ALLOC_SCHEME_COMBINED_POOL) {
  13332         rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, 
  13333                 oc->ma_idx_count - 1,
  13334                 0, oc->ma_idx_count -1, "ma_idx pool");
  13335         if (BCM_FAILURE(rv)) {
  13336             return (rv);
  13337 
  13338         }
  13339     } else if (MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) {
  13340         if (_BCM_ETH_OAM_NUM_SESSIONS != 0) {
  13341             rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, _BCM_ETH_OAM_NUM_SESSIONS-1,
  13342                     0, _BCM_ETH_OAM_NUM_SESSIONS-1, "ma_idx pool");
  13343             if (BCM_FAILURE(rv)) {
  13344                 return (rv);
  13345 
  13346             }
  13347         }
  13348 
  13349         if (_BCM_MPLS_OAM_NUM_SESSIONS != 0) {
  13350             rv = shr_idxres_list_create(&oc->mpls_oam_ma_idx_pool, 
  13351                     _BCM_ETH_OAM_NUM_SESSIONS, 
  13352                     _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1,
  13353                     _BCM_ETH_OAM_NUM_SESSIONS, 
  13354                     _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1,
  13355                     "mpls oam ma_idx pool");
  13356             if (BCM_FAILURE(rv)) {
  13357                 return (rv);
  13358 
  13359             }
  13360         }
  13361     } else {
  13362         return (BCM_E_INTERNAL);
  13363 
  13364     }
  13365     return rv;
  13366 }
  13367 
  13368 STATIC int
  13369 _bcm_kt2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc)
  13370 {
  13371     if (NULL != oc->ma_idx_pool) {
  13372         shr_idxres_list_destroy(oc->ma_idx_pool);
  13373         oc->ma_idx_pool = NULL;
  13374     }
  13375     if (NULL != oc->mpls_oam_ma_idx_pool) {
  13376         shr_idxres_list_destroy(oc->mpls_oam_ma_idx_pool);
  13377         oc->mpls_oam_ma_idx_pool = NULL;
  13378     }
  13379     return BCM_E_NONE;
  13380 }
  13381 
  13382 
  13383 /* * * * * * * * * * * * * * * * * * * *
  13384  *            OAM BCM APIs             *
  13385  */
  13386 /*
  13387  * Function: bcm_kt2_oam_init
  13388  *
  13389  * Purpose:
  13390  *     Initialize OAM module.
  13391  * Parameters:
  13392  *     unit - (IN) BCM device number
  13393  * Returns:
  13394  *     BCM_E_UNIT    - Invalid BCM unit number.
  13395  *     BCM_E_UNAVAIL - OAM not support on this device.
  13396  *     BCM_E_MEMORY  - Allocation failure
  13397  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
  13398  *     BCM_E_NONE    - Success
  13399  */
  13400 int
  13401 bcm_kt2_oam_init(int unit)
  13402 {
  13403     _bcm_oam_control_t *oc = NULL;  /* OAM control structure.     */
  13404     int             rv;             /* Operation return value.    */
  13405     uint32          size;           /* Size of memory allocation. */
  13406     bcm_port_t      port;           /* Port number.               */
  13407     int             index = 0;
  13408     bcm_oam_endpoint_t   ep_index;  /* Endpoint index.               */
  13409     bcm_pbmp_t      all_pbmp;
  13410 #if defined(INCLUDE_BHH)
  13411     int uc;
  13412     uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  13413     char *carrier_code_str;
  13414     uint32 node_id = 0;
  13415     bhh_sdk_msg_ctrl_init_t msg_init;
  13416     uint8 *buffer, *buffer_ptr;
  13417     uint16 buffer_len, reply_len;
  13418     int priority;
  13419     int ukernel_not_ready = 0;
  13420     uint8 bhh_consolidate_final_event = 0;
  13421 #endif
  13422     /* Ensure that the unit has OAM support. */
  13423     if (!soc_feature(unit, soc_feature_oam)) {
  13424         LOG_ERROR(BSL_LS_BCM_OAM,
  13425                   (BSL_META_U(unit,
  13426                               "OAM Error: OAM not supported \n")));
  13427         return (BCM_E_UNAVAIL);
  13428     }
  13429 
  13430     /* Detach first if the module has been previously initialized. */
  13431     if (NULL != _kt2_oam_control[unit]) {
  13432         _kt2_oam_control[unit]->init = FALSE;
  13433         rv = bcm_kt2_oam_detach(unit);
  13434         if (BCM_FAILURE(rv)) {
  13435             LOG_ERROR(BSL_LS_BCM_OAM,
  13436                       (BSL_META_U(unit,
  13437                                   "OAM Error: Module deinit - %s.\n"),
  13438                        bcm_errmsg(rv)));
  13439             return (rv);
  13440         }
  13441     }
  13442 
  13443     /* Allocate OAM control memeory for this unit. */
  13444     _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t),
  13445                "OAM control");
  13446     if (NULL == oc) {
  13447         return (BCM_E_MEMORY);
  13448     }
  13449 
  13450     if (soc_feature(unit, soc_feature_bhh)) {
  13451 #ifdef INCLUDE_BHH
  13452         /*
  13453          * Initialize uController side
  13454          */
  13455 
  13456         /*
  13457          * Start BHH application in BTE (Broadcom Task Engine) uController,
  13458          * if not already running (warm boot).
  13459          * Determine which uController is running BHH  by choosing the first
  13460          * uC that returns successfully.
  13461          */
  13462         for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
  13463             if (!soc_uc_in_reset(unit, uc)) {
  13464                 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH,
  13465                                            _BHH_UC_MSG_TIMEOUT_USECS,
  13466                                            BHH_SDK_VERSION,
  13467                                            BHH_UC_MIN_VERSION,
  13468                                            _bcm_oam_bhh_appl_callback, NULL);
  13469                 if (SOC_E_NONE == rv) {
  13470                     /* BHH started successfully */
  13471                     oc->uc_num = uc;
  13472                     break;
  13473                 }
  13474             }
  13475         }
  13476 
  13477         if (uc >= SOC_INFO(unit).num_ucs) {  /* Could not find or start BHH appl */
  13478             ukernel_not_ready = 1;
  13479             LOG_ERROR(BSL_LS_BCM_OAM,
  13480                       (BSL_META_U(unit,
  13481                                   "uKernel Not Ready, bhh not started\n")));
  13482         }
  13483 #endif
  13484     }
  13485 
  13486 
  13487     /* Get number of endpoints and groups supported by this unit. */
  13488     rv = _bcm_kt2_oam_group_endpoint_count_init(unit, oc);
  13489     if (BCM_FAILURE(rv)) {
  13490         _bcm_kt2_oam_control_free(unit, oc);
  13491         return (rv);
  13492     }
  13493 
  13494     if (soc_feature(unit, soc_feature_bhh)) {
  13495 #if defined(INCLUDE_BHH)
  13496     oc->unit = unit;
  13497 
  13498     oc->ukernel_not_ready = ukernel_not_ready;
  13499     /* Get SOC properties for BHH */
  13500     oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128);
  13501     oc->bhh_max_encap_length =
  13502                             soc_property_get(unit,
  13503                                              spn_BHH_ENCAP_MAX_LENGTH,
  13504                                              _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH);
  13505 
  13506 
  13507     if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) {
  13508         LOG_ERROR(BSL_LS_BCM_OAM,
  13509                   (BSL_META_U(unit,
  13510                               "Invalid max encap_length=%u\n"),
  13511                               oc->bhh_max_encap_length));
  13512         return BCM_E_CONFIG;
  13513     }
  13514 
  13515     carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE);
  13516     if (carrier_code_str != NULL) {
  13517         /*
  13518          * Note that the carrier code is specified in colon separated
  13519          * MAC address format.
  13520          */
  13521         if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) {
  13522             _bcm_kt2_oam_control_free(unit, oc);
  13523             return (BCM_E_INTERNAL);
  13524         }
  13525     }
  13526 
  13527     node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0);
  13528     bhh_consolidate_final_event = soc_property_get(unit, 
  13529                                            spn_BHH_CONSOLIDATED_FINAL_EVENT, 0);
  13530     oc->ep_count += oc->bhh_endpoint_count;
  13531 
  13532     if(oc->ep_count >= _BCM_OAM_KATANA2_ENDPOINT_MAX) {
  13533         LOG_ERROR(BSL_LS_BCM_OAM,
  13534                   (BSL_META_U(unit,
  13535                               "OAM Error: OAM EP count %d not supported \n"),
  13536                    oc->ep_count));
  13537         _bcm_kt2_oam_control_free(unit, oc);
  13538         return (BCM_E_PARAM);
  13539     }
  13540 #endif /* INCLUDE_BHH */
  13541     }
  13542 
  13543     _BCM_MPLS_OAM_NUM_SESSIONS = soc_property_get(unit, spn_MPLS_OAM_NUM_SESSIONS,
  13544             _BCM_MPLS_OAM_NUM_SESSIONS_INVALID);
  13545 
  13546     if(_BCM_MPLS_OAM_NUM_SESSIONS ==
  13547             _BCM_MPLS_OAM_NUM_SESSIONS_INVALID) {
  13548         /* Entry does not exist. Revert to old scheme */
  13549         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL;
  13550     } else if (_BCM_MPLS_OAM_NUM_SESSIONS > soc_mem_index_max(unit, MA_INDEXm)){
  13551         /* If it is greater than max index of MA_INDEX table,
  13552          * set it to max_index value and set it to newer index alloc scheme.
  13553          */
  13554         _BCM_MPLS_OAM_NUM_SESSIONS = soc_mem_index_max(unit, MA_INDEXm);
  13555         _BCM_ETH_OAM_NUM_SESSIONS  = 0;
  13556         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL;
  13557     } else {
  13558         _BCM_ETH_OAM_NUM_SESSIONS =
  13559             soc_mem_index_count(unit, MA_INDEXm) - _BCM_MPLS_OAM_NUM_SESSIONS;
  13560         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL;
  13561     }
  13562 
  13563     /* Mem_1: Allocate hash data memory */
  13564     /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */
  13565     size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_KATANA2_ENDPOINT_MAX;
  13566 
  13567     _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data");
  13568     if (NULL == oc->oam_hash_data) {
  13569         _bcm_kt2_oam_control_free(unit, oc);
  13570         return (BCM_E_MEMORY);
  13571     }
  13572 
  13573     /* Mem_2: Allocate group memory */
  13574     size = sizeof(_bcm_oam_group_data_t) * oc->group_count;
  13575 
  13576     _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info");
  13577 
  13578     if (NULL == oc->group_info) {
  13579         _bcm_kt2_oam_control_free(unit, oc);
  13580         return (BCM_E_MEMORY);
  13581     }
  13582 
  13583     /* Allocate RMEP H/w to logical index mapping memory */
  13584     size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count;
  13585 
  13586     _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping");
  13587     if (NULL == oc->remote_endpoints) {
  13588         _bcm_kt2_oam_control_free(unit, oc);
  13589         return (BCM_E_MEMORY);
  13590     }
  13591     /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 
  13592     for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) {
  13593         oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID;
  13594     }
  13595 
  13596     /* Mem_3: Create application endpoint list. */
  13597     rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->ep_count - 1,
  13598                                 0, oc->ep_count -1, "endpoint pool");
  13599     if (BCM_FAILURE(rv)) {
  13600         _bcm_kt2_oam_control_free(unit, oc);
  13601         return (rv);
  13602     }
  13603 
  13604     /* Mem_4: Create local MEP endpoint list. */
  13605     rv = shr_idxres_list_create(&oc->lmep_pool, 0, oc->lmep_count - 1,
  13606                                 0, oc->lmep_count -1, "lmep pool");
  13607     if (BCM_FAILURE(rv)) {
  13608         _bcm_kt2_oam_control_free(unit, oc);
  13609         return (rv);
  13610     }
  13611 
  13612     /* Mem_5: Create Remote MEP endpoint list. */
  13613     rv = shr_idxres_list_create(&oc->rmep_pool, 0, oc->rmep_count - 1,
  13614                                 0, oc->rmep_count -1, "rmep pool");
  13615     if (BCM_FAILURE(rv)) {
  13616         _bcm_kt2_oam_control_free(unit, oc);
  13617         return (rv);
  13618     }
  13619 
  13620     /* Mem_6: Create MEP Rx state tracker table index endpoint list - DnMEP */
  13621     rv =_bcm_kt2_oam_ma_idx_pool_create(oc);
  13622     if (BCM_FAILURE(rv)) {
  13623         _bcm_kt2_oam_control_free(unit, oc);
  13624         return (rv);
  13625 
  13626     }
  13627 
  13628     /* Mem_7: Create MEP Rx state tracker table index endpoint list -UpMEP */
  13629     rv = shr_idxres_list_create(&oc->egr_ma_idx_pool, 0, 
  13630                                 oc->egr_ma_idx_count - 1,
  13631                                 0, oc->egr_ma_idx_count -1, "egr_ma_idx pool");
  13632     if (BCM_FAILURE(rv)) {
  13633         _bcm_kt2_oam_control_free(unit, oc);
  13634         return (rv);
  13635 
  13636     }
  13637 
  13638     /* Initialize to domain specific key by default, WB recovery might
  13639      * overwrite it, depending on older SDK.
  13640      */
  13641     oc->eth_oam_mp_group_vlan_key = _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC;
  13642 
  13643     if(soc_feature(unit, soc_feature_bhh)) {
  13644 #if defined(INCLUDE_BHH)
  13645     /* Create BHH endpoint list. */
  13646     rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1,
  13647                                 0, oc->bhh_endpoint_count - 1, "bhh pool");
  13648     if (BCM_FAILURE(rv)) {
  13649         LOG_ERROR(BSL_LS_BCM_OAM,
  13650                   (BSL_META_U(unit,
  13651                               "OAM Error: Creating BHH pool failed \n")));
  13652         _bcm_kt2_oam_control_free(unit, oc);
  13653         return (rv);
  13654     }
  13655 
  13656     /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */
  13657     rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET,
  13658                 _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET + oc->bhh_endpoint_count - 1);
  13659 
  13660     if (BCM_FAILURE(rv)) {
  13661         LOG_ERROR(BSL_LS_BCM_OAM,
  13662                   (BSL_META_U(unit,
  13663                               "OAM Error: Reserving BHH endpoints from mep_pool "
  13664                               "failed \n")));
  13665         _bcm_kt2_oam_control_free(unit, oc);
  13666         return (rv);
  13667     }
  13668 
  13669 #endif /* INCLUDE_BHH */
  13670     }
  13671 
  13672     /* Mem_4: Create group list. */
  13673     rv = shr_idxres_list_create(&oc->group_pool, 0, oc->group_count - 1,
  13674                                 0, oc->group_count - 1, "group pool");
  13675     if (BCM_FAILURE(rv)) {
  13676         _bcm_kt2_oam_control_free(unit, oc);
  13677         return (rv);
  13678     }
  13679     if(soc_feature(unit, soc_feature_bhh)) {
  13680 #if defined(INCLUDE_BHH)
  13681         if(ukernel_not_ready == 0){
  13682             int bhh_num_lm_sec_meps = soc_property_get(unit, spn_BHH_NUM_LM_ENABLED_SECTION_MEPS, 0);
  13683             int bhh_num_lm_sec_counters = bhh_num_lm_sec_meps * 8;
  13684 
  13685             if( bhh_num_lm_sec_counters > oc->lm_counter_cnt) {
  13686                 LOG_ERROR(BSL_LS_BCM_OAM,
  13687                           (BSL_META_U(unit,
  13688                                     "OAM Error: Number of LM enabled section meps cannot be more than "
  13689                                     "available lm counter count \n")));
  13690                 _bcm_kt2_oam_control_free(unit, oc);
  13691                 return (BCM_E_PARAM);
  13692             }
  13693             if (bhh_num_lm_sec_counters) {
  13694                 oc->lm_counter_cnt = oc->lm_counter_cnt - bhh_num_lm_sec_counters;
  13695 
  13696                 rv = shr_aidxres_list_create(&oc->ing_lm_sec_mep_ctr_pool, 0,
  13697                                               bhh_num_lm_sec_counters - 1, 0,
  13698                                               bhh_num_lm_sec_counters - 1, 8, "ing_lm_sec_mep_ctr_pool");
  13699                 if (BCM_FAILURE(rv)) {
  13700                     _bcm_kt2_oam_control_free(unit, oc);
  13701                     return (rv);
  13702                 }
  13703             }
  13704         }
  13705 #endif
  13706     }
  13707 
  13708     /* Index management for Ingress LM counter pool 1 */
  13709     rv = shr_aidxres_list_create(&oc->ing_lm_ctr_pool[0], 0, 
  13710                          oc->lm_counter_cnt - 1, 0, 
  13711                          oc->lm_counter_cnt - 1, 8,  "ing_lm_idx pool1");
  13712     if (BCM_FAILURE(rv)) {
  13713         _bcm_kt2_oam_control_free(unit, oc);
  13714         return (rv);
  13715 
  13716     }
  13717     /* Index management for Ingress LM counter pool 2 */
  13718     rv = shr_aidxres_list_create(&oc->ing_lm_ctr_pool[1], 0, 
  13719                          oc->lm_counter_cnt - 1, 0,
  13720                          oc->lm_counter_cnt - 1, 8, "ing_lm_idx pool2");
  13721     if (BCM_FAILURE(rv)) {
  13722         _bcm_kt2_oam_control_free(unit, oc);
  13723         return (rv);
  13724     }
  13725 
  13726     
  13727     /* Mem_5: Create MA group and MEP hash table. */
  13728     rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_KATANA2_ENDPOINT_MAX,
  13729                         sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash");
  13730     if (BCM_FAILURE(rv)) {
  13731         _bcm_kt2_oam_control_free(unit, oc);
  13732         return (rv);
  13733     }
  13734 
  13735     /* Create protection mutex. */
  13736     oc->oc_lock = sal_mutex_create("oam_control.lock");
  13737     if (NULL == oc->oc_lock) {
  13738         _bcm_kt2_oam_control_free(unit, oc);
  13739         return (BCM_E_MEMORY);
  13740     }
  13741 
  13742     /* Register device OAM interrupt handler & SER handler call back routine.*/
  13743     soc_kt2_oam_handler_register(unit, _bcm_kt2_oam_handle_interrupt);
  13744     soc_kt2_oam_ser_handler_register(unit, _bcm_kt2_oam_ser_handler);
  13745 
  13746     /* Set up the unit OAM control structure. */
  13747     _kt2_oam_control[unit] = oc;
  13748 #if defined (INCLUDE_BHH)
  13749     if (soc_feature(unit, soc_feature_oam_pm)) {
  13750         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_pm_init(unit));
  13751     }
  13752 #endif
  13753     /* Set up OAM module related profile tables. */
  13754     rv = _bcm_kt2_oam_profile_tables_init(unit, oc);
  13755     if (BCM_FAILURE(rv)) {
  13756         _bcm_kt2_oam_control_free(unit, oc);
  13757         return (rv);
  13758     }
  13759 
  13760     /* Initialize all the TPID tables */
  13761     rv =  _bcm_kt2_outer_tpid_init(unit); 
  13762     if (BCM_FAILURE(rv)) {
  13763         _bcm_kt2_oam_control_free(unit, oc);
  13764         return (rv);
  13765     }
  13766     rv =  _bcm_kt2_inner_tpid_init(unit); 
  13767     if (BCM_FAILURE(rv)) {
  13768         _bcm_kt2_oam_control_free(unit, oc);
  13769         return (rv);
  13770     }
  13771     rv =  _bcm_kt2_subport_tpid_init(unit); 
  13772     if (BCM_FAILURE(rv)) {
  13773         _bcm_kt2_oam_control_free(unit, oc);
  13774         return (rv);
  13775     }
  13776     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_init(unit);
  13777     if (BCM_FAILURE(rv)) {
  13778         _bcm_kt2_oam_control_free(unit, oc);
  13779         return rv;
  13780     }
  13781 
  13782 
  13783 #if defined(BCM_WARM_BOOT_SUPPORT)
  13784     if(!SOC_WARM_BOOT(unit)) {
  13785         bcm_kt2_oam_scache_alloc(unit);
  13786     }
  13787     if (SOC_WARM_BOOT(unit)) {
  13788         rv = _bcm_kt2_oam_reinit(unit);
  13789         if (BCM_FAILURE(rv)) {
  13790             _bcm_kt2_oam_control_free(unit, oc);
  13791             return (rv);
  13792         }
  13793     } else 
  13794 #endif
  13795     {
  13796         BCM_PBMP_CLEAR(all_pbmp);
  13797         BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
  13798 
  13799         if (soc_feature(unit, soc_feature_flex_port)) {
  13800             BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp));
  13801         }
  13802         if (soc_feature(unit, soc_feature_linkphy_coe) ||
  13803             soc_feature(unit, soc_feature_subtag_coe)) {
  13804             _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
  13805         }
  13806 
  13807         /* Enable OAM processing on all ports of this unit. */
  13808         PBMP_ITER(all_pbmp, port) {
  13809             rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable,
  13810                                           TRUE);
  13811             if (BCM_FAILURE(rv)) {
  13812                 _bcm_kt2_oam_control_free(unit, oc);
  13813                 return (rv);
  13814             }
  13815         }
  13816 
  13817         /* Enable CCM Rx timeouts. */
  13818         rv = _bcm_kt2_oam_ccm_rx_timeout_set(unit, 1);
  13819         if (BCM_FAILURE(rv)) {
  13820             _bcm_kt2_oam_control_free(unit, oc);
  13821             return (rv);
  13822         }
  13823 
  13824         /* Enable CCM Tx control. */
  13825         rv = _bcm_kt2_oam_ccm_tx_config_set(unit, 1);
  13826         if (BCM_FAILURE(rv)) {
  13827             _bcm_kt2_oam_control_free(unit, oc);
  13828             return (rv);
  13829         }
  13830 
  13831 
  13832         /* 
  13833          * Misc config: Enable IFP lookup on the CPU port. 
  13834          */
  13835         rv = _bcm_kt2_oam_misc_config(unit);
  13836         if (BCM_FAILURE(rv)) {
  13837             _bcm_kt2_oam_control_free(unit, oc);
  13838             return (rv);
  13839         }
  13840         /* Set all the non CFM opcodes in opcode group -1 */
  13841         oc->opcode_grp_bmp[0] = ~(_BCM_OAM_OPCODE_TYPE_CFM_MASK);
  13842         oc->opcode_grp_1_bmp[0] = 0; 
  13843         oc->opcode_grp_2_bmp[0] = 0; 
  13844         for (index = 1; index < 8; index ++) {
  13845             oc->opcode_grp_bmp[index] = _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK; 
  13846             oc->opcode_grp_1_bmp[index] = 0; 
  13847             oc->opcode_grp_2_bmp[index] = 0; 
  13848         }
  13849         /* Init OAM opcode group */ 
  13850         rv =_bcm_kt2_oam_opcode_group_init(unit);
  13851         if (BCM_FAILURE(rv)) {
  13852             _bcm_kt2_oam_control_free(unit, oc);
  13853             return (rv);
  13854         }
  13855         /* Set default values for flexible oam domain control  */
  13856         rv = _bcm_kt2_oam_flexible_oam_domain_ctrl_set(unit); 
  13857         if (BCM_FAILURE(rv)) {
  13858             _bcm_kt2_oam_control_free(unit, oc);
  13859             return (rv);
  13860         }
  13861         /* Set default values for flexible ingress and egress drop control */
  13862         rv = _bcm_kt2_oam_flexible_drop_ctrl_set(unit);
  13863         if (BCM_FAILURE(rv)) {
  13864             _bcm_kt2_oam_control_free(unit, oc);
  13865             return (rv);
  13866         }
  13867         /* Set default values for s-interface passive processing control */
  13868         rv = _bcm_kt2_oam_s_intf_passive_proc_ctrl_set(unit);
  13869         if (BCM_FAILURE(rv)) {
  13870             _bcm_kt2_oam_control_free(unit, oc);
  13871             return (rv);
  13872         } 
  13873         /* Enable OLP handling on HG ports */
  13874         rv = _bcm_kt2_oam_hg_olp_enable(unit);
  13875         if (BCM_FAILURE(rv)) {
  13876             _bcm_kt2_oam_control_free(unit, oc);
  13877             return (rv);
  13878         }
  13879         /* Set default olp header type mapping */
  13880         rv = _bcm_kt2_oam_olp_header_type_mapping_set(unit); 
  13881         if (BCM_FAILURE(rv)) {
  13882             _bcm_kt2_oam_control_free(unit, oc);
  13883             return (rv);
  13884         }
  13885         /* Set OAM drop control to not to drop wrong version OAM packets */
  13886         rv = _bcm_kt2_oam_drop_ctrl_set(unit); 
  13887         if (BCM_FAILURE(rv)) {
  13888             _bcm_kt2_oam_control_free(unit, oc);
  13889             return (rv);
  13890         }
  13891         /* Set OAM LM cng and cpu data control*/
  13892         rv = _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default(unit); 
  13893         if (BCM_FAILURE(rv)) {
  13894             _bcm_kt2_oam_control_free(unit, oc);
  13895             return (rv);
  13896         }
  13897         /* Set Magic port used in OLP-XGS communication */
  13898         rv = _bcm_kt2_oam_olp_magic_port_set(unit); 
  13899         if (BCM_FAILURE(rv)) {
  13900             _bcm_kt2_oam_control_free(unit, oc);
  13901             return (rv);
  13902         }
  13903         /* Disable MACSA Zero check  */
  13904         rv = _bcm_kt2_oam_macsa_zero_check_disable(unit); 
  13905         if (BCM_FAILURE(rv)) {
  13906             _bcm_kt2_oam_control_free(unit, oc);
  13907             return (rv);
  13908         }
  13909     
  13910     }
  13911 
  13912       /*
  13913      * BHH init
  13914      */
  13915     if(soc_feature(unit, soc_feature_bhh)) {
  13916 #if defined(INCLUDE_BHH)
  13917         if(ukernel_not_ready == 0){
  13918             /*
  13919              * Initialize HOST side
  13920              */
  13921             oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, BHH_COSQ_INVALID);
  13922 
  13923             /*
  13924              * Allocate DMA buffers
  13925              *
  13926              * DMA buffer will be used to send and receive 'long' messages
  13927              * between SDK Host and uController (BTE).
  13928              */
  13929             oc->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t);
  13930 
  13931             /* Adding  feature specific for dma_buf_len as currently
  13932              * required buffer length for faults_get can be configurable
  13933              * by user during init. So, taking the max value of either of
  13934              * them for the purpose.Putting it under fature_check for
  13935              * giving flexibility to user.
  13936              */
  13937 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET
  13938             if(soc_feature(unit, soc_feature_faults_multi_ep_get)) {
  13939                 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len);
  13940             }
  13941 #endif
  13942             oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len,
  13943                     "BHH DMA buffer");
  13944             if (!oc->dma_buffer) {
  13945                 _bcm_kt2_oam_control_free(unit, oc);
  13946                 return (BCM_E_MEMORY);
  13947             }
  13948             sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len);
  13949 
  13950             oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len,
  13951                     "BHH uC reply");
  13952             if (!oc->dmabuf_reply) {
  13953                 _bcm_kt2_oam_control_free(unit, oc);
  13954                 return (BCM_E_MEMORY);
  13955             }
  13956             sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len);
  13957 
  13958             /* RX DMA channel (0..3) local to the uC */
  13959             oc->rx_channel = BCM_KT_BHH_RX_CHANNEL;
  13960 
  13961 #if defined(BCM_WARM_BOOT_SUPPORT)
  13962     if (!SOC_WARM_BOOT(unit)) {
  13963 #endif
  13964             /* Set control message data */
  13965             sal_memset(&msg_init, 0, sizeof(msg_init));
  13966             msg_init.num_sessions       = oc->bhh_endpoint_count;
  13967             msg_init.rx_channel         = oc->rx_channel;
  13968             msg_init.node_id            = node_id;
  13969             sal_memcpy(msg_init.carrier_code, carrier_code, SHR_BHH_CARRIER_CODE_LEN);
  13970             msg_init.max_encap_length = oc->bhh_max_encap_length;
  13971             if (bhh_consolidate_final_event) {
  13972                 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT;
  13973             }
  13974             
  13975             msg_init.data_collection_mode = oc->pm_bhh_lmdm_data_collection_mode;
  13976 
  13977             /* Pack control message data into DMA buffer */
  13978             buffer     = oc->dma_buffer;
  13979             buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init);
  13980             buffer_len = buffer_ptr - buffer;
  13981 
  13982             /* Send BHH Init message to uC */
  13983             rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  13984                     MOS_MSG_SUBCLASS_BHH_INIT,
  13985                     buffer_len, 0,
  13986                     MOS_MSG_SUBCLASS_BHH_INIT_REPLY,
  13987                     &reply_len);
  13988 
  13989             if (BCM_FAILURE(rv) || (reply_len != 0)) {
  13990                 _bcm_kt2_oam_control_free(unit, oc);
  13991                 return (BCM_E_INTERNAL);
  13992             }
  13993 #if defined(BCM_WARM_BOOT_SUPPORT)
  13994     }
  13995 #endif
  13996             /*
  13997              * Start event message callback thread
  13998              */
  13999             priority = soc_property_get(unit, spn_BHH_THREAD_PRI, BHH_THREAD_PRI_DFLT);
  14000 
  14001             if (oc->event_thread_id == NULL) {
  14002                 if ((oc->event_thread_id =
  14003                      sal_thread_create("bcmBHH", SAL_THREAD_STKSZ,
  14004                                        priority,
  14005                                        _bcm_kt2_oam_bhh_callback_thread,
  14006                                        (void*)oc)) == SAL_THREAD_ERROR) {
  14007                     oc->event_thread_id = NULL;
  14008                     BCM_IF_ERROR_RETURN(bcm_kt2_oam_detach(unit));
  14009                     return (BCM_E_MEMORY);
  14010                 }
  14011             }
  14012             /*
  14013              * End BHH init
  14014              */
  14015         }
  14016         /*
  14017          * Initialize HW
  14018          */
  14019 #ifdef BCM_WARM_BOOT_SUPPORT
  14020         if (SOC_WARM_BOOT(unit)) {
  14021             rv = _bcm_kt2_oam_bhh_cos_map_recover(unit);
  14022         } else
  14023 #endif
  14024         {
  14025             rv = _bcm_kt2_oam_bhh_hw_init(unit);
  14026         }
  14027 
  14028         if (BCM_FAILURE(rv)) {
  14029             BCM_IF_ERROR_RETURN(bcm_kt2_oam_detach(unit));
  14030             return rv;
  14031         }
  14032 
  14033 #endif /* INCLUDE_BHH */
  14034     }
  14035 
  14036     /* OAM initialization complete. */
  14037     _kt2_oam_control[unit]->init = TRUE;
  14038     return (BCM_E_NONE);
  14039 }
  14040 
  14041 /*
  14042  * Function:
  14043  *     bcm_kt2_oam_detach
  14044  * Purpose:
  14045  *     Shut down OAM subsystem
  14046  * Parameters:
  14047  *     unit - (IN) BCM device number
  14048  * Returns:
  14049  *     BCM_E_XXX
  14050  */
  14051 int
  14052 bcm_kt2_oam_detach(int unit)
  14053 {
  14054     _bcm_oam_control_t *oc;  /* Pointer to OAM control structure. */
  14055     bcm_port_t         port; /* Port number.                      */
  14056     int                rv;   /* Operation return status.          */
  14057     bcm_pbmp_t         all_pbmp;
  14058 #if defined(INCLUDE_BHH)
  14059     uint16 reply_len;
  14060     sal_usecs_t timeout = 0;
  14061 #endif
  14062 
  14063     /* Get the device OAM module handle. */
  14064     oc = _kt2_oam_control[unit];
  14065     if (NULL == oc) {
  14066         /* Module already uninitialized. */
  14067         return (BCM_E_NONE);
  14068     }
  14069 
  14070     /* Unregister all OAM interrupt event handlers and SER handler. */
  14071     soc_kt2_oam_handler_register(unit, NULL);
  14072     soc_kt2_oam_ser_handler_register(unit, NULL);
  14073 
  14074     if (NULL != oc->oc_lock) {
  14075         _BCM_OAM_LOCK(oc);
  14076     }
  14077 
  14078     rv = _bcm_kt2_oam_events_unregister(unit, oc);
  14079     if (BCM_FAILURE(rv)) {
  14080         if (NULL != oc->oc_lock) {
  14081             _BCM_OAM_UNLOCK(oc);
  14082         }
  14083         return (rv);
  14084     }
  14085 
  14086     /* Disable CCM Rx Timeouts. */
  14087     rv = _bcm_kt2_oam_ccm_rx_timeout_set(unit, 0);
  14088     if (BCM_FAILURE(rv)) {
  14089         if (NULL != oc->oc_lock) {
  14090             _BCM_OAM_UNLOCK(oc);
  14091         }
  14092         return (rv);
  14093     }
  14094 
  14095     /* Disable CCM Tx control for the device. */
  14096     rv = _bcm_kt2_oam_ccm_tx_config_set(unit, 0);
  14097     if (BCM_FAILURE(rv)) {
  14098         if (NULL != oc->oc_lock) {
  14099             _BCM_OAM_UNLOCK(oc);
  14100         }
  14101         return (rv);
  14102     }
  14103 
  14104     BCM_PBMP_CLEAR(all_pbmp);
  14105     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
  14106     
  14107     if (soc_feature(unit, soc_feature_flex_port)) {
  14108         rv = _bcm_kt2_flexio_pbmp_update(unit, &all_pbmp);
  14109         if (BCM_FAILURE(rv)) {
  14110             _BCM_OAM_UNLOCK(oc);
  14111             return rv;
  14112         }
  14113     }
  14114     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  14115         soc_feature(unit, soc_feature_subtag_coe)) {
  14116         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
  14117     }
  14118 
  14119     /* Disable OAM PDU Rx processing on all ports. */
  14120     PBMP_ITER(all_pbmp, port) {
  14121         rv = bcm_esw_port_control_set(unit, port,
  14122                                       bcmPortControlOAMEnable, 0);
  14123         if (BCM_FAILURE(rv)) {
  14124             if (NULL != oc->oc_lock) {
  14125                 _BCM_OAM_UNLOCK(oc);
  14126             }
  14127             return (rv);
  14128         }
  14129     }
  14130     
  14131 
  14132      /*
  14133      * BHH specific
  14134      */
  14135     if (soc_feature(unit, soc_feature_bhh)) {
  14136 #if defined(INCLUDE_BHH)
  14137         if (oc->ukernel_not_ready == 0) {
  14138             /*
  14139              * Event Handler thread exit signal
  14140              */
  14141             timeout = sal_time_usecs() + 5000000;
  14142             while (NULL !=  oc->event_thread_id) {
  14143                 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num,
  14144                                                MOS_MSG_CLASS_BHH_EVENT);
  14145 
  14146                 if (sal_time_usecs() < timeout) {
  14147                     /*give some time to already running bhh callback thread
  14148                      * to schedule and exit */
  14149                     sal_usleep(10000);
  14150                 } else {
  14151                     /*timeout*/
  14152                     LOG_ERROR(BSL_LS_BCM_OAM,
  14153                               (BSL_META_U(unit,
  14154                                           "BHH event thread did not exit.\n")));
  14155                     _BCM_OAM_UNLOCK(oc);
  14156                     return BCM_E_INTERNAL;
  14157                 }
  14158             }
  14159 
  14160             /*
  14161              * Send BHH Uninit message to uC
  14162              * Ignore error since that may indicate uKernel was reloaded.
  14163              */
  14164 #if defined(BCM_WARM_BOOT_SUPPORT)
  14165     if (!SOC_WARM_BOOT(unit)) {
  14166 #endif
  14167             rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  14168                                               MOS_MSG_SUBCLASS_BHH_UNINIT,
  14169                                               0, 0,
  14170                                               MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY,
  14171                                               &reply_len);
  14172             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  14173                 if (NULL != oc->oc_lock) {
  14174                     _BCM_OAM_UNLOCK(oc);
  14175                 }
  14176                 return BCM_E_INTERNAL;
  14177             }
  14178 #if defined(BCM_WARM_BOOT_SUPPORT)
  14179     }
  14180 #endif
  14181 
  14182             /*
  14183              * Delete CPU COS queue mapping entries for BHH packets
  14184              */
  14185             if (!SOC_WARM_BOOT(unit)) {
  14186                 if (oc->cpu_cosq_ach_error_index >= 0) {
  14187                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  14188                                                   oc->cpu_cosq_ach_error_index);
  14189                     if (BCM_FAILURE(rv)) {
  14190                         if (NULL != oc->oc_lock) {
  14191                             _BCM_OAM_UNLOCK(oc);
  14192                         }
  14193                         return (rv);
  14194                     }
  14195                     oc->cpu_cosq_ach_error_index = -1;
  14196                 }
  14197                 if (oc->cpu_cosq_invalid_error_index >= 0) {
  14198                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  14199                                               oc->cpu_cosq_invalid_error_index);
  14200                     if (BCM_FAILURE(rv)) {
  14201                         if (NULL != oc->oc_lock) {
  14202                             _BCM_OAM_UNLOCK(oc);
  14203                         }
  14204                         return (rv);
  14205                     }
  14206                     oc->cpu_cosq_invalid_error_index = -1;
  14207                 }
  14208                 if (oc->bhh_lb_index >= 0) {
  14209                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  14210                                                         oc->bhh_lb_index);
  14211                     if (BCM_FAILURE(rv)) {
  14212                         if (NULL != oc->oc_lock) {
  14213                             _BCM_OAM_UNLOCK(oc);
  14214                         }
  14215                         return (rv);
  14216                     }
  14217                     oc->bhh_lb_index = -1;
  14218                 }
  14219             }
  14220         }
  14221 #endif /* INCLUDE_BHH */
  14222     }
  14223 
  14224     /* Destroy all groups and assoicated endpoints and free the resources. */
  14225     rv = bcm_kt2_oam_group_destroy_all(unit);
  14226     if (BCM_FAILURE(rv)) {
  14227         if (NULL != oc->oc_lock) {
  14228             _BCM_OAM_UNLOCK(oc);
  14229         }
  14230         return (rv);
  14231     }
  14232     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_destroy(unit);
  14233     if (BCM_FAILURE(rv)) {
  14234         if (NULL != oc->oc_lock) {
  14235             _BCM_OAM_UNLOCK(oc);
  14236         }
  14237         return (rv);
  14238     }
  14239 
  14240     /* Release the protection mutex. */
  14241     _BCM_OAM_UNLOCK(oc);
  14242 
  14243     /* Free OAM module allocated resources. */
  14244     _bcm_kt2_oam_control_free(unit, oc);
  14245 
  14246     return (BCM_E_NONE);
  14247 }
  14248 
  14249 /*
  14250  * Function:
  14251  *     bcm_kt2_oam_group_create
  14252  * Purpose:
  14253  *     Create or replace an OAM group object
  14254  * Parameters:
  14255  *     unit       - (IN) BCM device number
  14256  *     group_info - (IN/OUT) Pointer to an OAM group information.
  14257  * Returns:
  14258  *     BCM_E_XXX
  14259  */
  14260 int
  14261 bcm_kt2_oam_group_create(int unit, bcm_oam_group_info_t *group_info)
  14262 {
  14263     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
  14264     uint8                  grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */
  14265                                                  /* name.                     */
  14266     maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table     */
  14267     _bcm_oam_group_data_t  *ma_group;            /* Pointer to group info.    */
  14268     _bcm_oam_control_t     *oc;                  /* OAM control structure.    */
  14269     int                    rv;                   /* Operation return status.  */
  14270                                                  /* entry.                    */
  14271     uint8                  sw_rdi;               /* Remote defect indicator.  */
  14272 
  14273 #if defined(BCM_KATANA2_SUPPORT)  && defined(INCLUDE_BHH)
  14274     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
  14275     uint8 *buffer, *buffer_ptr;
  14276     uint16 buffer_len, reply_len;
  14277     uint32 session_flags = 0;
  14278     _bcm_oam_hash_data_t *h_data_p;
  14279     _bcm_oam_ep_list_t      *cur;
  14280 #endif
  14281 
  14282     /* Validate input parameter. */
  14283     if (NULL == group_info) {
  14284         return (BCM_E_PARAM);
  14285     }
  14286 
  14287     /* Get OAM control structure handle. */
  14288     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14289 
  14290     /* Validate group id. */
  14291     if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  14292         _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id);
  14293     }
  14294 
  14295     _BCM_OAM_LOCK(oc);
  14296 
  14297     /*
  14298      * If MA group create is called with replace flag bit set.
  14299      *  - Check and return error if a group does not exist with the ID.
  14300      */
  14301     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
  14302         if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  14303 
  14304             /* Search the list with the MA Group ID value. */
  14305             rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id);
  14306             if (BCM_E_EXISTS != rv) {
  14307                 _BCM_OAM_UNLOCK(oc);
  14308                 LOG_ERROR(BSL_LS_BCM_OAM,
  14309                           (BSL_META_U(unit,
  14310                                       "OAM Error: Group does not exist.\n")));
  14311                 return (BCM_E_PARAM);
  14312             }
  14313         } else {
  14314             _BCM_OAM_UNLOCK(oc);
  14315             LOG_ERROR(BSL_LS_BCM_OAM,
  14316                       (BSL_META_U(unit,
  14317                                   "OAM Error: Replace command needs a "
  14318                                   "valid Group ID.\n")));
  14319             return (BCM_E_PARAM);
  14320         }
  14321     } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  14322         /*
  14323          * If MA group create is called with ID flag bit set.
  14324          *  - Check and return error if the ID is already in use.
  14325          */
  14326         rv = shr_idxres_list_reserve(oc->group_pool, group_info->id,
  14327                                      group_info->id);
  14328         if (BCM_FAILURE(rv)) {
  14329             _BCM_OAM_UNLOCK(oc);
  14330             return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
  14331         }
  14332     } else {
  14333         /* Reserve the next available group index. */
  14334          rv = shr_idxres_list_alloc(oc->group_pool,
  14335                                     (shr_idxres_element_t *) &group_info->id);
  14336         if (BCM_FAILURE(rv)) {
  14337             _BCM_OAM_UNLOCK(oc);
  14338             LOG_ERROR(BSL_LS_BCM_OAM,
  14339                       (BSL_META_U(unit,
  14340                                   "OAM Error: Group allocation (GID=%d)"
  14341                                    " %s\n"), group_info->id, bcm_errmsg(rv)));
  14342             return (rv);
  14343         }
  14344     }
  14345 
  14346     /* Get this group memory to store group information. */
  14347     ma_group = &oc->group_info[group_info->id];
  14348 
  14349     /* Store the group name. */
  14350     sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH);
  14351 
  14352     /* Store Lowest Alarm Priority */
  14353     ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority;
  14354 
  14355     if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) {
  14356         _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *,
  14357                sizeof(_bcm_oam_ep_list_t *), "EP list head");
  14358 
  14359         /* Initialize head to NULL.*/
  14360         *ma_group->ep_list =  NULL;
  14361     }
  14362 
  14363     /*
  14364      * Maintenance Association ID - Reduction table update.
  14365      */
  14366 
  14367     /* Prepare group name for hardware write. */
  14368     _bcm_kt2_oam_group_name_mangle(ma_group->name, grp_name_hw_buf);
  14369 
  14370     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
  14371 
  14372     /* Calculate CRC32 value for the group name string and set in entry. */
  14373     soc_MAID_REDUCTIONm_field32_set
  14374         (unit, &maid_reduction_entry, REDUCED_MAIDf,
  14375          soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH));
  14376 
  14377     /* Check if software RDI flag bit needs to be set in hardware. */
  14378     sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0);
  14379 
  14380     /* Set RDI status for out going CCM PDUs. */
  14381     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf,
  14382                                     sw_rdi);
  14383 
  14384     if (soc_feature(unit, soc_feature_bhh)) {
  14385 #if defined(BCM_KATANA2_SUPPORT)  && defined(INCLUDE_BHH)
  14386         /* Send message to uC to set the Soft RDI   */
  14387         if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 
  14388 
  14389             /* Get the endpoint list head pointer. */
  14390             cur = *(ma_group->ep_list);
  14391 
  14392             while (NULL != cur) {
  14393                 h_data_p = cur->ep_data_p;
  14394                 if (NULL == h_data_p) {
  14395                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  14396                         "OAM Error: Group=%d endpoints access failed -"
  14397                          " %s.\n"), group_info->id, 
  14398                          bcm_errmsg(BCM_E_INTERNAL)));
  14399                     _BCM_OAM_UNLOCK(oc);
  14400                     return (BCM_E_INTERNAL);
  14401                 }
  14402                 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_BHH) {
  14403                     /* Set the RDI flag in session bits */
  14404                     session_flags |= SHR_BHH_SESS_SET_F_RDI;
  14405 
  14406                     /* Get the session is from endpoint */
  14407                     msg_sess.sess_id =
  14408                           BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
  14409                 
  14410                     /* Pack control message data into DMA buffer */
  14411                     msg_sess.flags = session_flags;
  14412 
  14413                     buffer     = oc->dma_buffer;
  14414                     buffer_ptr = 
  14415                         bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  14416                     buffer_len = buffer_ptr - buffer;
  14417 
  14418                     /* Send BHH Session Update message to uC */
  14419                     rv =  _bcm_kt2_oam_bhh_msg_send_receive(unit,
  14420                                          MOS_MSG_SUBCLASS_BHH_SESS_SET,
  14421                                          buffer_len, 0,
  14422                                          MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
  14423                                          &reply_len);
  14424                     if (BCM_FAILURE(rv)) {
  14425                         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  14426                                    "OAM Error: ukernel msg failed for"
  14427                                    "%s.\n"), bcm_errmsg(rv)));
  14428                         _BCM_OAM_UNLOCK(oc);
  14429                         return (BCM_E_INTERNAL);
  14430                     }
  14431                 }
  14432                 cur = cur->next;
  14433             }    
  14434         }
  14435 #endif
  14436     }
  14437 
  14438     /* Enable hardware lookup for this entry. */
  14439     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1);
  14440 
  14441 
  14442     /* Write entry to hardware. */
  14443     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id,
  14444                                &maid_reduction_entry);
  14445     if (BCM_FAILURE(rv)) {
  14446         _BCM_OAM_UNLOCK(oc);
  14447         return rv;
  14448     }
  14449 
  14450     /*
  14451      * Maintenance Association State table update.
  14452      */
  14453     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
  14454 
  14455     /*
  14456      * If it is a group info replace operation, retain previous group
  14457      * defect status.
  14458      */
  14459     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
  14460         rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id,
  14461                             &ma_state_entry);
  14462         if (BCM_FAILURE(rv)) {
  14463             _BCM_OAM_UNLOCK(oc);
  14464             return rv;
  14465         }
  14466     }
  14467 
  14468     /* Set the lowest alarm priority info. */
  14469     soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
  14470                               group_info->lowest_alarm_priority);
  14471 
  14472     /* Mark the entry as valid. */
  14473     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1);
  14474 
  14475     /* Write group information to hardware table. */
  14476     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id,
  14477                                         &ma_state_entry);
  14478     if (BCM_FAILURE(rv)) {
  14479         _BCM_OAM_UNLOCK(oc);
  14480         return rv;
  14481     }
  14482 
  14483     /* Make the group as in used status. */
  14484     ma_group->in_use = 1;
  14485 
  14486     _BCM_OAM_UNLOCK(oc);
  14487 
  14488 #ifdef BCM_WARM_BOOT_SUPPORT
  14489     SOC_CONTROL_LOCK(unit);
  14490     SOC_CONTROL(unit)->scache_dirty = 1;
  14491     SOC_CONTROL_UNLOCK(unit);
  14492 #endif
  14493 
  14494     return BCM_E_NONE;
  14495 }
  14496 
  14497 #if defined(INCLUDE_BHH)
  14498 /*
  14499  * Function:
  14500  *      _bcm_kt2_oam_get_group_sw_rdi
  14501  * Purpose:
  14502  *     Get OAM group SW RDI information.
  14503  * Parameters:
  14504  *     unit         - (IN) BCM device number
  14505  *     group_index  - (IN) Group hardware table index
  14506  *     group_sw_rdi - (OUT) Pointer to group SW RDI
  14507  * Returns:
  14508  *     BCM_E_NONE      - No errors.
  14509  *     BCM_E_XXX       - Otherwise.
  14510  */
  14511 STATIC int
  14512 _bcm_kt2_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index,
  14513                        uint8 *group_sw_rdi)
  14514 {
  14515     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
  14516 
  14517     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
  14518                                              group_index,
  14519                                              &maid_reduction_entry));
  14520 
  14521     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
  14522                                              SW_RDIf)) {
  14523         *group_sw_rdi = 1;
  14524     }
  14525     return (BCM_E_NONE);
  14526 }
  14527 #endif
  14528 
  14529 /*
  14530  * Function:
  14531  *     bcm_kt2_oam_group_get
  14532  * Purpose:
  14533  *     Get an OAM group object
  14534  * Parameters:
  14535  *     unit       - (IN) BCM device number
  14536  *     group      - (IN) OAM Group ID.
  14537  *     group_info - (OUT) Pointer to group information buffer.
  14538  * Returns:
  14539  *      BCM_E_XXX
  14540  */
  14541 int
  14542 bcm_kt2_oam_group_get(int unit, bcm_oam_group_t group,
  14543                       bcm_oam_group_info_t *group_info)
  14544 {
  14545     _bcm_oam_control_t    *oc;      /* Pointer to OAM control structure. */
  14546     _bcm_oam_group_data_t *group_p; /* Pointer to group list.            */
  14547     int                   rv;       /* Operation return status.          */
  14548 
  14549 #if defined(INCLUDE_BHH)
  14550     bhh_sdk_msg_ctrl_sess_get_t msg;
  14551     uint8 *buffer, *buffer_ptr;
  14552     uint16 buffer_len, reply_len;
  14553     _bcm_oam_hash_data_t *h_data_p;
  14554     _bcm_oam_ep_list_t      *cur = NULL;
  14555     int sess_id = 0;
  14556 #endif
  14557 
  14558     /* Validate input parameter. */
  14559     if (NULL == group_info) {
  14560         return (BCM_E_PARAM);
  14561     }
  14562 
  14563     /* Get OAM device control structure. */
  14564     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14565 
  14566     /* Validate group index. */
  14567     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  14568 
  14569     _BCM_OAM_LOCK(oc);
  14570 
  14571     /* Check if the group is in use. */
  14572     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  14573     if (BCM_E_EXISTS != rv) {
  14574         _BCM_OAM_UNLOCK(oc);
  14575         LOG_ERROR(BSL_LS_BCM_OAM,
  14576                   (BSL_META_U(unit,
  14577                               "OAM Error: GID=%d - %s.\n"),
  14578                    group, bcm_errmsg(rv)));
  14579         return (rv);
  14580     }
  14581 
  14582     /* Get pointer to this group in the group list. */
  14583     group_p = oc->group_info;
  14584 
  14585     /* Get the group information. */
  14586     rv = _bcm_kt2_oam_get_group(unit, group, group_p, group_info);
  14587     if (BCM_FAILURE(rv)) {
  14588         _BCM_OAM_UNLOCK(oc);
  14589         LOG_ERROR(BSL_LS_BCM_OAM,
  14590                   (BSL_META_U(unit,
  14591                               "OAM Error: bcm_kt2_oam_group_get Group ID=%d "
  14592                                "- Failed.\n"), group));
  14593         return (rv);
  14594     }
  14595 
  14596     if (soc_feature(unit, soc_feature_bhh)) {
  14597 #if defined(INCLUDE_BHH)
  14598 
  14599         if (!oc->ukernel_not_ready) {
  14600             group_p = &oc->group_info[group_info->id];
  14601             /* Get the endpoint list head pointer. */
  14602             if (group_p->ep_list != NULL) {
  14603                 cur = *(group_p->ep_list);
  14604             }
  14605 
  14606             while (NULL != cur) {
  14607                 h_data_p = cur->ep_data_p;
  14608                 if (NULL == h_data_p) {
  14609                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  14610                                                           "OAM(unit %d) Error: Group=%d endpoints access failed -"
  14611                                                           " %s.\n"), unit, group_info->id,
  14612                                                bcm_errmsg(BCM_E_INTERNAL)));
  14613                     _BCM_OAM_UNLOCK(oc);
  14614                     return (BCM_E_INTERNAL);
  14615                 }
  14616                 if ((h_data_p->oam_domain == _BCM_OAM_DOMAIN_BHH) &&
  14617                     !(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  14618                     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
  14619                     rv = _bcm_kt2_oam_bhh_msg_send_receive(
  14620                                              unit,
  14621                                              MOS_MSG_SUBCLASS_BHH_SESS_GET,
  14622                                              sess_id, 0,
  14623                                              MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  14624                                              &reply_len);
  14625                     if (BCM_FAILURE(rv)) {
  14626                         LOG_ERROR(BSL_LS_BCM_OAM,
  14627                                   (BSL_META_U(unit,
  14628                                     "OAM(unit %d) Error: ukernel msg failed for"
  14629                                     "EP=%d %s.\n"), unit, h_data_p->ep_id,
  14630                                    bcm_errmsg(rv)));
  14631                         _BCM_OAM_UNLOCK(oc);
  14632                         return (rv);
  14633                     }
  14634 
  14635                     /* Pack control message data into DMA buffer */
  14636                     buffer = oc->dma_buffer;
  14637                     buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  14638                     buffer_len = buffer_ptr - buffer;
  14639 
  14640                     if (reply_len != buffer_len) {
  14641                         rv = BCM_E_INTERNAL;
  14642                         LOG_ERROR(BSL_LS_BCM_OAM,
  14643                                   (BSL_META_U(unit,
  14644                                      "OAM(unit %d) Error: ukernel msg failed for"
  14645                                      " EP=%d %s.\n"), unit, h_data_p->ep_id,
  14646                                    bcm_errmsg(rv)));
  14647                         _BCM_OAM_UNLOCK(oc);
  14648                         return (rv);
  14649                     } else {
  14650                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
  14651                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  14652                         }
  14653                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
  14654                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  14655                         }
  14656                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  14657                             group_info->faults |=
  14658                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  14659                         }
  14660                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  14661                             group_info->faults |=
  14662                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  14663                         }
  14664                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  14665                             group_info->faults |=
  14666                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  14667                         }
  14668                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  14669                             group_info->faults |=
  14670                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  14671                         }
  14672                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  14673                             group_info->faults |=
  14674                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  14675                         }
  14676                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
  14677                             group_info->faults |=
  14678                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
  14679                         }
  14680                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
  14681                             group_info->faults |=
  14682                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
  14683                         }
  14684                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
  14685                             group_info->faults |=
  14686                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
  14687                         }
  14688                     }
  14689                 }
  14690                 cur = cur->next;
  14691             }
  14692         }
  14693 #endif
  14694     }
  14695 
  14696     _BCM_OAM_UNLOCK(oc);
  14697     return (BCM_E_NONE);
  14698 }
  14699 
  14700 /*
  14701  * Function:
  14702  *     bcm_kt2_oam_group_destroy
  14703  * Purpose:
  14704  *     Destroy an OAM group object and its associated endpoints.
  14705  * Parameters:
  14706  *     unit  - (IN) BCM device number
  14707  *     group - (IN) The ID of the OAM group object to destroy
  14708  * Returns:
  14709  *     BCM_E_XXX
  14710  */
  14711 int
  14712 bcm_kt2_oam_group_destroy(int unit,
  14713                           bcm_oam_group_t group)
  14714 {
  14715     _bcm_oam_control_t     *oc;       /* Pointer to OAM control structure. */
  14716     _bcm_oam_group_data_t  *g_info_p; /* Pointer to group list.            */
  14717     int                    rv;        /* Operation return status.          */
  14718     maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry.  */
  14719     ma_state_entry_t       ma_state_entry; /* MA_STATE table entry.        */
  14720 
  14721     /* Get OAM device control structure. */
  14722     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14723 
  14724     /* Validate group index. */
  14725     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  14726 
  14727     _BCM_OAM_LOCK(oc);
  14728 
  14729     /* Check if the group is in use. */
  14730     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  14731     if (BCM_E_EXISTS != rv) {
  14732         _BCM_OAM_UNLOCK(oc);
  14733         LOG_ERROR(BSL_LS_BCM_OAM,
  14734                   (BSL_META_U(unit,
  14735                               "OAM Error: GID=%d - %s.\n"),
  14736                    group, bcm_errmsg(rv)));
  14737         return (rv);
  14738     }
  14739 
  14740     /* Get pointer to this group in the group list. */
  14741     g_info_p = &oc->group_info[group];
  14742 
  14743     rv = _bcm_kt2_oam_group_endpoints_destroy(unit, g_info_p);
  14744     if (BCM_FAILURE(rv)) {
  14745         _BCM_OAM_UNLOCK(oc);
  14746         LOG_ERROR(BSL_LS_BCM_OAM,
  14747                   (BSL_META_U(unit,
  14748                               "OAM Error: bcm_kt2_oam_endpoint_destroy_all"
  14749                                " (GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
  14750         return (rv);
  14751     }
  14752 
  14753     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
  14754     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group,
  14755                           &maid_reduction_entry);
  14756     if (BCM_FAILURE(rv)) {
  14757         _BCM_OAM_UNLOCK(oc);
  14758         LOG_DEBUG(BSL_LS_BCM_OAM,
  14759                   (BSL_META_U(unit,
  14760                               "OAM Error: MAID REDUCTION write "
  14761                                "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
  14762         return (rv);
  14763     }
  14764 
  14765     /*
  14766      * Maintenance Association State table update.
  14767      */
  14768     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
  14769 
  14770     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry);
  14771     if (BCM_FAILURE(rv)) {
  14772         _BCM_OAM_UNLOCK(oc);
  14773         LOG_ERROR(BSL_LS_BCM_OAM,
  14774                   (BSL_META_U(unit,
  14775                               "OAM Error: MA STATE write "
  14776                                "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
  14777         return (rv);
  14778     }
  14779 
  14780     /* Return Group ID back to free group. */
  14781     rv = shr_idxres_list_free(oc->group_pool, group);
  14782     if (BCM_FAILURE(rv)) {
  14783         _BCM_OAM_UNLOCK(oc);
  14784         return (rv);
  14785     }
  14786 
  14787 #ifdef BCM_WARM_BOOT_SUPPORT
  14788     SOC_CONTROL_LOCK(unit);
  14789     SOC_CONTROL(unit)->scache_dirty = 1;
  14790     SOC_CONTROL_UNLOCK(unit);
  14791 #endif
  14792     _BCM_OAM_UNLOCK(oc);
  14793     return (BCM_E_NONE);
  14794 }
  14795 
  14796 /*
  14797  * Function:
  14798  *     bcm_kt2_oam_group_destroy_all
  14799  * Purpose:
  14800  *     Destroy all OAM group objects and their associated endpoints.
  14801  * Parameters:
  14802  *     unit  - (IN) BCM device number
  14803  * Returns:
  14804  *     BCM_E_XXX
  14805  */
  14806 int
  14807 bcm_kt2_oam_group_destroy_all(int unit)
  14808 {
  14809     _bcm_oam_control_t *oc;   /* Pointer to OAM control structure.    */
  14810     int                group; /* Maintenance Association group index. */
  14811     int                rv;    /* Operation return status .            */
  14812 
  14813     /* Get device OAM control structure handle. */
  14814     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14815 
  14816     _BCM_OAM_LOCK(oc);
  14817     for (group = 0; group < oc->group_count; group++) {
  14818 
  14819         /* Check if the group is in use. */
  14820         rv = shr_idxres_list_elem_state(oc->group_pool, group);
  14821         if (BCM_E_EXISTS != rv) {
  14822             continue;
  14823         }
  14824 
  14825         rv = bcm_kt2_oam_group_destroy(unit, group);
  14826         if (BCM_FAILURE(rv)) {
  14827             _BCM_OAM_UNLOCK(oc);
  14828             LOG_ERROR(BSL_LS_BCM_OAM,
  14829                       (BSL_META_U(unit,
  14830                                   "OAM Error: Group destroy failed "
  14831                                    "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
  14832             return (rv);
  14833         }
  14834     }
  14835 
  14836 #ifdef BCM_WARM_BOOT_SUPPORT
  14837     SOC_CONTROL_LOCK(unit);                                      
  14838     SOC_CONTROL(unit)->scache_dirty = 1;
  14839     SOC_CONTROL_UNLOCK(unit);
  14840 #endif
  14841 
  14842     _BCM_OAM_UNLOCK(oc);
  14843     return (BCM_E_NONE);
  14844 }
  14845 
  14846 /*
  14847  * Function:
  14848  *     bcm_kt2_oam_group_traverse
  14849  * Purpose:
  14850  *     Traverse the entire set of OAM groups, calling a specified
  14851  *     callback for each one
  14852  * Parameters:
  14853  *     unit  - (IN) BCM device number
  14854  *     cb        - (IN) Pointer to call back function.
  14855  *     user_data - (IN) Pointer to user supplied data.
  14856  * Returns:
  14857  *     BCM_E_XXX
  14858  */
  14859 int
  14860 bcm_kt2_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
  14861                            void *user_data)
  14862 {
  14863     _bcm_oam_control_t    *oc;        /* OAM control structure pointer. */
  14864     bcm_oam_group_info_t  group_info; /* Group information to be set.   */
  14865     bcm_oam_group_t       grp_idx;    /* MA Group index.                */
  14866     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  14867     int                   rv;         /* Operation return status.       */
  14868 
  14869     if (NULL == cb) {
  14870         return (BCM_E_PARAM);
  14871     }
  14872 
  14873     /* Get device OAM control structure handle. */
  14874     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14875 
  14876     _BCM_OAM_LOCK(oc);
  14877 
  14878     /* Initialize to group array pointer. */
  14879     group_p = oc->group_info;
  14880 
  14881     for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
  14882 
  14883         /* Check if the group is in use. */
  14884         if (BCM_E_EXISTS
  14885             == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
  14886 
  14887             /* Initialize the group information structure. */
  14888             bcm_oam_group_info_t_init(&group_info);
  14889 
  14890             /* Retrieve group information and set in group_info structure. */
  14891             rv = _bcm_kt2_oam_get_group(unit, grp_idx, group_p, &group_info);
  14892             if (BCM_FAILURE(rv)) {
  14893                 _BCM_OAM_UNLOCK(oc);
  14894                 LOG_ERROR(BSL_LS_BCM_OAM,
  14895                           (BSL_META_U(unit,
  14896                                       "OAM Error: _bcm_kt2_oam_get_group "
  14897                                        "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv)));
  14898                 return (rv);
  14899             }
  14900 
  14901             /* Call the user call back routine with group information. */
  14902             rv = cb(unit, &group_info, user_data);
  14903             if (BCM_FAILURE(rv)) {
  14904                 _BCM_OAM_UNLOCK(oc);
  14905                 LOG_ERROR(BSL_LS_BCM_OAM,
  14906                           (BSL_META_U(unit,
  14907                                       "OAM Error: User call back routine "
  14908                                        "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv)));
  14909                 return (rv);
  14910             }
  14911         }
  14912     }
  14913 
  14914     _BCM_OAM_UNLOCK(oc);
  14915 
  14916     return BCM_E_NONE;
  14917 }
  14918 
  14919 
  14920 /*
  14921  * Function:
  14922  *     bcm_kt2_oam_endpoint_lm_update
  14923  * Purpose:
  14924  *     Update LM related params of an endpoint
  14925  * Parameters:
  14926  *     unit          - (IN) BCM device number
  14927  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  14928  * Returns:
  14929  *      BCM_E_XXX
  14930  */
  14931 STATIC int
  14932 bcm_kt2_oam_endpoint_lm_update(int unit, bcm_oam_endpoint_info_t *ep_info)
  14933 {
  14934     _bcm_oam_hash_data_t         *h_data_p;
  14935     _bcm_oam_control_t           *oc;
  14936     int                           loss_add, loss_del;
  14937     int                           loss_configured;
  14938     soc_profile_mem_t             pri_map_prof_mem;
  14939     uint32                        pri_ent[BCM_OAM_INTPRI_MAX]; /* ing profile */
  14940     /* ing profile copy from HW*/
  14941     uint32                        pri_ent_copy[BCM_OAM_INTPRI_MAX];
  14942     int                           i;
  14943     void                          *entries[1];
  14944     int                           lm_ctr_pool_id = -1;
  14945     int                           mem_index;
  14946     egr_mp_group_entry_t          egr_mp_group;
  14947     l3_entry_1_entry_t            l3_entry;       /* LMEP view table entry.*/
  14948     int                           l3_index = -1;  /* L3 table hardware index.*/
  14949     uint32                        profile_index = -1;
  14950     int                           rv = BCM_E_NONE;
  14951     soc_mem_t                     mem = ING_SERVICE_PRI_MAPm;;
  14952 
  14953     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  14954 
  14955     if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  14956         /* Only LMEPs can update Loss parameters */
  14957         return BCM_E_PARAM;
  14958     }
  14959 
  14960     if (ep_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) {
  14961         /* Only MEPs can update LM */
  14962         return BCM_E_PARAM;
  14963     }
  14964 
  14965     /* Validate endpoint index value. */
  14966     _BCM_OAM_EP_INDEX_VALIDATE(ep_info->id);
  14967 
  14968     h_data_p =  &oc->oam_hash_data[ep_info->id];
  14969     if (0 == h_data_p->in_use) {
  14970         return BCM_E_NOT_FOUND;
  14971     }
  14972 
  14973     /* Figure out if loss is being added or deleted */
  14974     loss_add = loss_del = 0;
  14975     loss_configured = 1; /* Indicates if BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is
  14976                           * present in new & old config
  14977                           */
  14978     if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  14979         if (!(ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
  14980             loss_del = 1;
  14981         }
  14982     } else {
  14983         if (ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  14984             loss_add = 1;
  14985         } else {
  14986             /* BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is not present in old/new
  14987              * config.
  14988              */
  14989             loss_configured = 0;
  14990         }
  14991     }
  14992 
  14993     /* If loss configuration is present in either old & new configuration, then
  14994      * find out if something is being modified in loss, updates will result in
  14995      * delete and add.
  14996      */
  14997     if (1 == loss_configured && 0 == loss_add && 0 == loss_del) {
  14998 
  14999         lm_ctr_pool_id = (h_data_p->rx_ctr >> 24) & 0xFF;
  15000 
  15001         if (lm_ctr_pool_id != ep_info->lm_ctr_pool_id) {
  15002             loss_del = loss_add = 1;
  15003         }
  15004         
  15005         if(h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) {
  15006 
  15007             pri_map_prof_mem = oc->ing_service_pri_map;
  15008 
  15009             for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
  15010                 if (ep_info->pri_map[i] > _BCM_OAM_SERVICE_PRI_MAX_OFFSET) {
  15011                     return BCM_E_PARAM;
  15012                 }
  15013                 pri_ent[i] = ep_info->pri_map[i];
  15014                 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
  15015                     soc_mem_field32_set(unit, mem, &pri_ent[i], OFFSET_VALIDf, 1);
  15016                 }
  15017             }
  15018 
  15019             soc_mem_lock(unit, mem);
  15020           
  15021             entries[0] = &pri_ent_copy;
  15022 
  15023             rv = soc_profile_mem_get(unit, &pri_map_prof_mem,
  15024                     (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX),
  15025                     BCM_OAM_INTPRI_MAX, (void *) entries);
  15026             
  15027             if (BCM_FAILURE(rv)) {
  15028                 soc_mem_unlock(unit, mem);
  15029                 return rv;
  15030             }
  15031             
  15032             if (sal_memcmp(pri_ent, pri_ent_copy, 
  15033                         sizeof(uint32)*BCM_OAM_INTPRI_MAX)){
  15034                 rv = soc_profile_mem_delete(unit, &pri_map_prof_mem,
  15035                         (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX));
  15036                 if (BCM_FAILURE(rv)) {
  15037                     LOG_ERROR(BSL_LS_BCM_OAM,
  15038                             (BSL_META_U(unit,
  15039                                         "OAM Error: Profile table update error (idx=%d)"
  15040                                         "- %s.\n"), h_data_p->pri_map_index, bcm_errmsg(rv)));
  15041                     soc_mem_unlock(unit, mem);
  15042                     return (rv);
  15043                 }
  15044 
  15045                 h_data_p->pri_map_index = profile_index;
  15046 
  15047                 loss_del = loss_add = 1;
  15048             }
  15049             soc_mem_unlock(unit, mem);
  15050         } else {
  15051             /* If for some reason i.e. warmboot,index became invalid 
  15052              * though loss is configured */
  15053             return BCM_E_INTERNAL;
  15054         }
  15055 
  15056     }
  15057 
  15058     if (1 == loss_del) {
  15059         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index,
  15060                                                    &l3_entry));
  15061         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm,
  15062                                                        l3_index, h_data_p,
  15063                                                        (void *)&l3_entry));
  15064 
  15065         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_find_egr_lmep(unit, h_data_p,
  15066                                                        &mem_index,
  15067                                                        &egr_mp_group));
  15068         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm,
  15069                                                        mem_index, h_data_p,
  15070                                                        (void *)&egr_mp_group));
  15071         h_data_p->flags &= ~BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  15072     }
  15073 
  15074     if (1 == loss_add) {
  15075         h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  15076         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lmep_counters_set(unit, ep_info));
  15077     }
  15078 
  15079     if(ep_info->type == bcmOAMEndpointTypeEthernet) {
  15080         if((ep_info->ccm_tx_update_lm_counter_size) && 
  15081         (_BCM_OAM_INVALID_INDEX != h_data_p->local_tx_index)) {
  15082             BCM_IF_ERROR_RETURN(bcm_kt2_oam_hw_ccm_tx_ctr_update(unit, ep_info)); 
  15083         }
  15084     }
  15085 
  15086     return BCM_E_NONE;
  15087 }
  15088 
  15089 
  15090 /*
  15091  * Function:
  15092  *     bcm_kt2_oam_endpoint_create
  15093  * Purpose:
  15094  *     Create or replace an OAM endpoint object
  15095  * Parameters:
  15096  *     unit          - (IN) BCM device number
  15097  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  15098  * Returns:
  15099  *      BCM_E_XXX
  15100  */
  15101 int
  15102 bcm_kt2_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info)
  15103 {
  15104     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
  15105     _bcm_oam_hash_key_t  hash_key;          /* Hash Key buffer.             */
  15106     int                  ep_req_index;      /* Requested endpoint index.    */
  15107     int                  rv;                /* Operation return status.     */
  15108     _bcm_oam_control_t   *oc;               /* Pointer to OAM control       */
  15109                                             /* structure.                   */
  15110     uint32               sglp = 0;          /* Source global logical port.  */
  15111     uint32               dglp = 0;          /* Dest global logical port.    */
  15112     uint32               svp = 0;           /* Source virtual port          */
  15113     bcm_port_t           src_pp_port = 0;   /* Source pp port.              */
  15114     bcm_port_t           dst_pp_port = 0;   /* Dest pp port.                */
  15115     int                  mep_ccm_tx = 0;    /* Endpoint CCM Tx status.      */
  15116     int                  mep_ccm_rx = 0;    /* Endpoint CCM Rx status.      */
  15117     int                  remote = 0;        /* Remote endpoint status.      */
  15118     int                  up_mep = 0;        /* Endpoint is an upMep         */
  15119     int                  key_type = 0;
  15120     port_tab_entry_t     port_entry;
  15121     int                  oam_key1 = 0;
  15122     int                  oam_key2 = 0;
  15123     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID; 
  15124     int                  is_vp_valid = 0;
  15125     bcm_gport_t          tx_gport = BCM_GPORT_INVALID;
  15126 
  15127     LOG_DEBUG(BSL_LS_BCM_OAM,
  15128               (BSL_META_U(unit,
  15129                           "OAM Info: bcm_kt2_oam_endpoint_create "
  15130                            "Endpoint ID=%d.\n"), endpoint_info->id));
  15131 
  15132     /* Validate input parameter. */
  15133     if (NULL == endpoint_info) {
  15134         return (BCM_E_PARAM);
  15135     }
  15136 
  15137     /* Get OAM Control Structure. */
  15138     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  15139 
  15140     _BCM_OAM_LOCK(oc);
  15141 
  15142 #if defined(KEY_PRINT)
  15143     _bcm_oam_hash_key_print(&hash_key);
  15144 #endif
  15145 
  15146     /* Calculate the hash key for given enpoint input parameters. */
  15147     _bcm_kt2_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key);
  15148 
  15149     /* Validate endpoint input parameters. */
  15150     rv = _bcm_kt2_oam_endpoint_params_validate(unit, oc, &hash_key,
  15151                                                endpoint_info);
  15152     if (BCM_FAILURE(rv)) {
  15153         LOG_ERROR(BSL_LS_BCM_OAM,
  15154                   (BSL_META_U(unit,
  15155                               "OAM Error: (EP=%d) - %s.\n"),
  15156                    endpoint_info->id, bcm_errmsg(rv)));
  15157         _BCM_OAM_UNLOCK(oc);
  15158         return (rv);
  15159     }
  15160 
  15161     if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) &&
  15162             (endpoint_info->flags2 & BCM_OAM_ENDPOINT2_UPDATE_COUNTER_ACTION)) {
  15163         /* Update LM parameters */
  15164         rv =  bcm_kt2_oam_endpoint_lm_update(unit, endpoint_info);
  15165         _BCM_OAM_UNLOCK(oc);
  15166         return rv;
  15167     }
  15168 
  15169     if(soc_feature(unit, soc_feature_bhh)) {
  15170 #if defined(INCLUDE_BHH)
  15171         if(BHH_EP_TYPE(endpoint_info))
  15172         {
  15173             if ((oc->ukernel_not_ready == 1) && 
  15174                     (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){
  15175                 LOG_ERROR(BSL_LS_BCM_OAM,
  15176                         (BSL_META_U(unit,
  15177                                     "OAM(unit %d) Error: BTE(ukernel) "
  15178                                     "not ready.\n"), unit));
  15179                 _BCM_OAM_UNLOCK(oc);
  15180                 return (BCM_E_INIT);
  15181             }
  15182             rv = bcm_kt2_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key);
  15183             if (BCM_FAILURE(rv)) {
  15184                 LOG_ERROR(BSL_LS_BCM_OAM,
  15185                           (BSL_META_U(unit,
  15186                                       "OAM Error: BHH Endpoint create (EP=%d) - %s.\n"),
  15187                            endpoint_info->id, bcm_errmsg(rv)));
  15188             }
  15189             _BCM_OAM_UNLOCK(oc);
  15190 
  15191             return (rv);
  15192         }
  15193 #endif /* INCLUDE_BHH */
  15194     }
  15195 
  15196     /* Get MEP remote endpoint status. */
  15197     remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  15198 
  15199     /* For remote endpoints gport is not required.
  15200        Only group and MEP ID info is required. */
  15201     if (!remote) {
  15202         /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */
  15203         rv = _bcm_kt2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, &dglp,
  15204                                                  &src_pp_port, &dst_pp_port,
  15205                                                  &svp, &trunk_id, &is_vp_valid,
  15206                                                  &tx_gport);
  15207 
  15208         if (BCM_FAILURE(rv)) {
  15209             LOG_ERROR(BSL_LS_BCM_OAM,
  15210                     (BSL_META_U(unit,
  15211                                 "OAM Error: Gport resolve (EP=%d) - %s.\n"),
  15212                      endpoint_info->id, bcm_errmsg(rv)));
  15213             _BCM_OAM_UNLOCK(oc);
  15214             return (rv);
  15215         }
  15216     }
  15217 
  15218     /* Get MEP CCM Tx status. */
  15219     mep_ccm_tx
  15220         = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)
  15221             ? 1 : 0);
  15222 
  15223     /* Get MEP CCM Rx status. */
  15224     mep_ccm_rx
  15225         = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0);
  15226 
  15227   
  15228     /* Check whether up/down MEP */
  15229     if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  15230         up_mep = 1;
  15231     }
  15232     /* Set the search key type. */
  15233     if (is_vp_valid) {
  15234         key_type = _BCM_OAM_DOMAIN_VP;
  15235     } else if(endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
  15236         key_type = _BCM_OAM_DOMAIN_CVLAN;
  15237     } else if(endpoint_info->flags & 
  15238                            BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
  15239         key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
  15240     } else if((endpoint_info->vlan == 0) && (endpoint_info->inner_vlan == 0)) {
  15241         key_type = _BCM_OAM_DOMAIN_PORT;
  15242     } else {
  15243         key_type = _BCM_OAM_DOMAIN_SVLAN;
  15244     }
  15245 
  15246     /* We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 
  15247        EGR_PORT_TABLE based on the key_type of OAM */
  15248     if (trunk_id != BCM_TRUNK_INVALID) {
  15249         rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 
  15250                                                  src_pp_port, &port_entry);
  15251         if (BCM_FAILURE(rv)) {
  15252             LOG_ERROR(BSL_LS_BCM_OAM,
  15253                       (BSL_META_U(unit,
  15254                                   "OAM Error: Endpoint create (EP=%d) - %s.\n"),
  15255                        endpoint_info->id, bcm_errmsg(rv)));
  15256             _BCM_OAM_UNLOCK(oc);
  15257             return (rv);
  15258         }
  15259 
  15260         oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 
  15261         oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 
  15262 
  15263         if (key_type != _BCM_OAM_DOMAIN_PORT) {
  15264              if ((oam_key1 > 0) && (oam_key2 > 0)) {
  15265                 if ((oam_key1 == key_type) || (oam_key2 == key_type)) {
  15266                 } else {
  15267                     LOG_ERROR(BSL_LS_BCM_OAM,
  15268                               (BSL_META_U(unit,
  15269                                           "OAM Error: Invalid OAM domain to "
  15270                                           "resolve (EP=%d) - %s.\n"),
  15271                                endpoint_info->id, bcm_errmsg(rv)));
  15272                     _BCM_OAM_UNLOCK(oc);
  15273                     return (BCM_E_PARAM);
  15274                 }
  15275             }
  15276         }
  15277     }
  15278 
  15279     /* For Downmep CCM tx purposes, int_pri variable is used like a cosq.
  15280      * Hence verify if it is in the valid range, Else return error.
  15281      * For UPMEP CCM tx purposes, int_pri is used as internal priority only.
  15282      * Hence verify if it is in valid range of internal priority
  15283      */
  15284     if (mep_ccm_tx &&  !up_mep && 
  15285         (!BCM_COSQ_QUEUE_VALID(unit, endpoint_info->int_pri))) {
  15286         _BCM_OAM_UNLOCK(oc);
  15287         return (BCM_E_PARAM);
  15288     } else if (mep_ccm_tx &&  up_mep && 
  15289       (!(endpoint_info->int_pri >= 0 && endpoint_info->int_pri < BCM_OAM_INTPRI_MAX))) {
  15290         _BCM_OAM_UNLOCK(oc);
  15291         return (BCM_E_PARAM);
  15292     }
  15293 
  15294     /* Replace an existing endpoint. */
  15295     if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
  15296         
  15297         rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint_info->id);
  15298         if (BCM_FAILURE(rv)) {
  15299             LOG_ERROR(BSL_LS_BCM_OAM,
  15300                       (BSL_META_U(unit,
  15301                                   "OAM Error: Endpoint destroy (EP=%d) - %s.\n"),
  15302                        endpoint_info->id, bcm_errmsg(rv)));
  15303             _BCM_OAM_UNLOCK(oc);
  15304             return (rv);
  15305         }
  15306     }
  15307 
  15308     /* Create a new endpoint with the requested ID. */
  15309     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  15310         ep_req_index = endpoint_info->id;
  15311         rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index,
  15312                                      ep_req_index);
  15313         if (BCM_FAILURE(rv)) {
  15314             LOG_ERROR(BSL_LS_BCM_OAM,
  15315                       (BSL_META_U(unit,
  15316                                   "OAM Error: Endpoint reserve (EP=%d) - %s.\n"),
  15317                        endpoint_info->id, bcm_errmsg(rv)));
  15318             _BCM_OAM_UNLOCK(oc);
  15319             return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv);
  15320         }
  15321     } else {
  15322         /* Allocate the next available endpoint index. */
  15323         rv = shr_idxres_list_alloc(oc->mep_pool,
  15324                                    (shr_idxres_element_t *)&ep_req_index);
  15325         if (BCM_FAILURE(rv)) {
  15326             LOG_ERROR(BSL_LS_BCM_OAM,
  15327                       (BSL_META_U(unit,
  15328                                   "OAM Error: Endpoint alloc failed - %s.\n"),
  15329                        bcm_errmsg(rv)));
  15330             _BCM_OAM_UNLOCK(oc);
  15331             return (rv);
  15332         }
  15333         /* Set the allocated endpoint id value. */
  15334         endpoint_info->id =  ep_req_index;
  15335     }
  15336 
  15337     /* Get the hash data pointer where the data is to be stored. */
  15338     hash_data = &oc->oam_hash_data[ep_req_index];
  15339 
  15340     /* Clear the hash data element contents before storing the values. */
  15341     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  15342     hash_data->type = endpoint_info->type;
  15343     hash_data->ep_id = endpoint_info->id;
  15344     hash_data->is_remote = remote;
  15345     hash_data->local_tx_enabled = mep_ccm_tx;
  15346     hash_data->local_rx_enabled = mep_ccm_rx;
  15347     hash_data->group_index = endpoint_info->group;
  15348     hash_data->name  = endpoint_info->name;
  15349     hash_data->level = endpoint_info->level;
  15350     hash_data->vlan = endpoint_info->vlan;
  15351     hash_data->inner_vlan = endpoint_info->inner_vlan;
  15352     hash_data->gport = endpoint_info->gport;
  15353     hash_data->sglp = sglp;
  15354     hash_data->dglp = dglp;
  15355     hash_data->src_pp_port = src_pp_port;
  15356     hash_data->dst_pp_port = dst_pp_port;
  15357     hash_data->flags = endpoint_info->flags;
  15358     hash_data->opcode_flags = ( endpoint_info->opcode_flags &
  15359             _BCM_KT2_OAM_OPCODE_MASK );
  15360     hash_data->period = endpoint_info->ccm_period;
  15361     hash_data->in_use = 1;
  15362     hash_data->oam_domain = key_type;
  15363     hash_data->outer_tpid = endpoint_info->outer_tpid;
  15364     hash_data->inner_tpid = endpoint_info->inner_tpid;
  15365     hash_data->subport_tpid = endpoint_info->subport_tpid;
  15366     hash_data->int_pri = endpoint_info->int_pri;
  15367     hash_data->trunk_index = endpoint_info->trunk_index;
  15368     if (is_vp_valid) {
  15369         hash_data->vp = svp;
  15370         if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  15371             /* For implementation of VP based lookup on egress side (UP MEP)
  15372              * We need to set EGR_DVP_ATTRIBUTE OAM_KEY3 = 1.
  15373              */
  15374             rv = bcm_esw_port_control_set(unit, endpoint_info->gport,
  15375                     bcmPortControlOamLookupWithDvp,
  15376                     1);
  15377             if (BCM_FAILURE(rv)) {
  15378                 _BCM_OAM_UNLOCK(oc);
  15379                 return (rv);
  15380             }
  15381         }
  15382         hash_data->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  15383     }
  15384     if(endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
  15385         hash_data->inner_vlan = endpoint_info->inner_vlan;
  15386     }
  15387     hash_data->trunk_id = trunk_id;
  15388     if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
  15389         hash_data->resolved_trunk_gport = tx_gport;
  15390     }
  15391     /* Initialize hardware index as invalid indices. */
  15392     hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
  15393     hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
  15394     hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
  15395     hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX;
  15396     hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX;
  15397     hash_data->profile_index = _BCM_OAM_INVALID_INDEX;
  15398     hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX;
  15399     hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX;
  15400     hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX;
  15401     hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  15402     hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15403     hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15404     hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15405     hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX;
  15406 
  15407     if (1 == remote) {
  15408         /* Allocate the next available index for RMEP table. */
  15409         rv = shr_idxres_list_alloc
  15410                 (oc->rmep_pool,
  15411                  (shr_idxres_element_t *)&hash_data->remote_index);
  15412         if (BCM_FAILURE(rv)) {
  15413             _BCM_OAM_UNLOCK(oc);
  15414             LOG_ERROR(BSL_LS_BCM_OAM,
  15415                       (BSL_META_U(unit,
  15416                                   "OAM Error: RMEP index alloc failed EP:%d %s.\n"),
  15417                        endpoint_info->id, bcm_errmsg(rv)));
  15418             return (rv);
  15419         }
  15420     } else {
  15421 
  15422         /* Allocate the next available index for LMEP table. */
  15423         if (1 == mep_ccm_tx) {
  15424             rv = shr_idxres_list_alloc
  15425                     (oc->lmep_pool,
  15426                      (shr_idxres_element_t *)&hash_data->local_tx_index);
  15427             if (BCM_FAILURE(rv)) {
  15428                 _BCM_OAM_UNLOCK(oc);
  15429                 LOG_ERROR(BSL_LS_BCM_OAM,
  15430                           (BSL_META_U(unit,
  15431                                       "OAM Error: LMEP Tx index alloc failed EP:%d "
  15432                                        "%s.\n"), endpoint_info->id, bcm_errmsg(rv)));
  15433                 return (rv);
  15434             }
  15435         }
  15436 
  15437         /* Allocate the next available index for MA_INDEX table. */
  15438         if (1 == mep_ccm_rx) {
  15439            /* check up or down MEP */
  15440             if (1 == up_mep) {
  15441                 rv =  _bcm_kt2_oam_upmep_rx_endpoint_reserve(unit, 
  15442                                                           endpoint_info);
  15443                 if (BCM_FAILURE(rv)) {
  15444                     if (1 == mep_ccm_tx) {
  15445                     /* Return Tx index to the LMEP pool. */
  15446                         shr_idxres_list_free(oc->lmep_pool,
  15447                                          hash_data->local_tx_index);
  15448                     }
  15449 
  15450                     /* Return endpoint index to MEP pool. */
  15451                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
  15452 
  15453                     _BCM_OAM_UNLOCK(oc);
  15454                     LOG_ERROR(BSL_LS_BCM_OAM,
  15455                               (BSL_META_U(unit,
  15456                                           "OAM Error: LMEP Rx index alloc failed "
  15457                                           "EP:%d " "%s.\n"),
  15458                                endpoint_info->id, bcm_errmsg(rv)));
  15459                     return (rv);
  15460                 }
  15461             } else { /* down Mep */
  15462                 rv =  _bcm_kt2_oam_downmep_rx_endpoint_reserve(unit, 
  15463                                                                endpoint_info);
  15464                 if (BCM_FAILURE(rv)) {
  15465                     if (1 == mep_ccm_tx) {
  15466                     /* Return Tx index to the LMEP pool. */
  15467                         shr_idxres_list_free(oc->lmep_pool,
  15468                                          hash_data->local_tx_index);
  15469                     }
  15470 
  15471                     /* Return endpoint index to MEP pool. */
  15472                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
  15473 
  15474                     _BCM_OAM_UNLOCK(oc);
  15475                     LOG_ERROR(BSL_LS_BCM_OAM,
  15476                               (BSL_META_U(unit,
  15477                                           "OAM Error: LMEP Rx index alloc "
  15478                                           "failed EP:%d " "%s.\n"), endpoint_info->id, 
  15479                                bcm_errmsg(rv)));
  15480                     return (rv);
  15481                 }
  15482             }
  15483         }
  15484     }
  15485     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
  15486     if (BCM_FAILURE(rv)) {
  15487         LOG_ERROR(BSL_LS_BCM_OAM,
  15488                 (BSL_META_U(unit,
  15489                             "OAM Error: Hash table insert failed EP=%d %s.\n"),
  15490                  endpoint_info->id, bcm_errmsg(rv)));
  15491         _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15492         _BCM_OAM_UNLOCK(oc);
  15493         return (rv);
  15494     }
  15495 
  15496     if (1 == remote) {
  15497         rv = _bcm_oam_kt2_remote_mep_hw_set(unit, endpoint_info);
  15498         if (BCM_FAILURE(rv)) {
  15499             LOG_DEBUG(BSL_LS_BCM_OAM,
  15500                       (BSL_META_U(unit,
  15501                                   "OAM Error: Remote MEP set failed EP=%d %s.\n"),
  15502                        endpoint_info->id, bcm_errmsg(rv)));
  15503             _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15504             _BCM_OAM_UNLOCK(oc);
  15505             return (rv);
  15506         }
  15507     } else {
  15508         if (mep_ccm_rx) {
  15509             rv = _bcm_kt2_oam_local_rx_mep_hw_set(unit, endpoint_info);
  15510             if (BCM_FAILURE(rv)) {
  15511                 LOG_ERROR(BSL_LS_BCM_OAM,
  15512                           (BSL_META_U(unit,
  15513                                       "OAM Error: Rx config failed for EP=%d %s.\n"),
  15514                            endpoint_info->id, bcm_errmsg(rv)));
  15515                 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep,
  15516                                               hash_key, hash_data);
  15517                 _BCM_OAM_UNLOCK(oc);
  15518                 return (rv);
  15519             }
  15520         }
  15521         if (mep_ccm_tx) {
  15522             rv = _bcm_oam_kt2_local_tx_mep_hw_set(unit, endpoint_info);
  15523             if (BCM_FAILURE(rv)) {
  15524                 LOG_ERROR(BSL_LS_BCM_OAM,
  15525                           (BSL_META_U(unit,
  15526                                       "OAM Error: Tx config failed for EP=%d %s.\n"),
  15527                            endpoint_info->id, bcm_errmsg(rv)));
  15528                 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep,
  15529                                               hash_key, hash_data);
  15530                 _BCM_OAM_UNLOCK(oc);
  15531                 return (rv);
  15532             }
  15533         }
  15534 
  15535         rv = _bcm_kt2_oam_port_table_key_update(unit, PORT_TABm, hash_data);
  15536         if (BCM_FAILURE(rv)) {
  15537             LOG_ERROR(BSL_LS_BCM_OAM,
  15538                       (BSL_META_U(unit,
  15539                                   "OAM Error: Endpoint create (EP=%d) - %s.\n"),
  15540                        endpoint_info->id, bcm_errmsg(rv)));
  15541             _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15542             _BCM_OAM_UNLOCK(oc);
  15543             return (rv);
  15544         }
  15545         rv = _bcm_kt2_oam_port_table_key_update(unit, EGR_PORTm, hash_data);
  15546         if (BCM_FAILURE(rv)) {
  15547             LOG_ERROR(BSL_LS_BCM_OAM,
  15548                       (BSL_META_U(unit,
  15549                                   "OAM Error: Endpoint create (EP=%d) - %s.\n"),
  15550                        endpoint_info->id, bcm_errmsg(rv)));
  15551             _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15552             _BCM_OAM_UNLOCK(oc);
  15553             return (rv);
  15554         }
  15555         /* Set OAM LM cng and cpu data control from LM flags*/
  15556         if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  15557             _bcm_kt2_oam_lm_cng_cpu_ctrl_set(unit, endpoint_info); 
  15558         }
  15559     }
  15560 
  15561     rv = _bcm_kt2_oam_group_ep_list_add(unit, endpoint_info->group,
  15562             endpoint_info->id);
  15563     if (BCM_FAILURE(rv)) {
  15564         LOG_ERROR(BSL_LS_BCM_OAM,
  15565                   (BSL_META_U(unit,
  15566                               "OAM Error: failed to add entry to ep list "
  15567                               "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv)));
  15568         _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15569         _BCM_OAM_UNLOCK(oc);
  15570         return (rv);
  15571     }
  15572 
  15573     rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data);
  15574     if (BCM_FAILURE(rv)) {
  15575         LOG_ERROR(BSL_LS_BCM_OAM,
  15576                 (BSL_META_U(unit,
  15577                             "OAM(unit %d) Error: failed to add mapping to ma_idx_to_ep_id list "
  15578                             "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv)));
  15579         _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  15580         _BCM_OAM_UNLOCK(oc);
  15581         return (rv);
  15582     }
  15583     _BCM_OAM_UNLOCK(oc);
  15584 
  15585 #ifdef BCM_WARM_BOOT_SUPPORT
  15586     SOC_CONTROL_LOCK(unit);
  15587     SOC_CONTROL(unit)->scache_dirty = 1;
  15588     SOC_CONTROL_UNLOCK(unit);
  15589 #endif
  15590 
  15591     return (BCM_E_NONE);
  15592 }
  15593 
  15594 /*
  15595  * Function:
  15596  *      bcm_kt2_oam_hw_ccm_tx_ctr_get
  15597  * Purpose:
  15598  *      Update CCM CTR params
  15599  * Parameters:
  15600  *      unit - (IN) Unit number.
  15601  *      lmep_1_entry - (IN) lemp_1 entry read from HW
  15602  *      ep_info - (OUT) Pointer to get endpoint parameters
  15603  * Returns:
  15604  *      BCM_E_XXX
  15605  * Notes:
  15606  */
  15607 void
  15608 bcm_kt2_oam_hw_ccm_tx_ctr_get(int                       unit, 
  15609                                 lmep_1_entry_t          *lmep_1_entry,
  15610                                 bcm_oam_endpoint_info_t *endpoint_info)
  15611 {
  15612     int num_counter = 0;
  15613     uint32 counter_base_id = 0;
  15614 
  15615     if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_ACTIONf)) {
  15616 
  15617         counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_IDf);
  15618         endpoint_info->ccm_tx_update_lm_counter_base_id[0] = (counter_base_id & 0xFFF8);
  15619         endpoint_info->ccm_tx_update_lm_counter_offset[0] = counter_base_id % 8;
  15620         num_counter++;
  15621     }
  15622 
  15623     if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_ACTIONf)) {
  15624 
  15625         counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_IDf);
  15626         endpoint_info->ccm_tx_update_lm_counter_base_id[1] = (counter_base_id & 0xFFF8) + (1 << 24);
  15627         endpoint_info->ccm_tx_update_lm_counter_offset[1] = counter_base_id % 8;
  15628         num_counter++;
  15629     }
  15630 
  15631     endpoint_info->ccm_tx_update_lm_counter_size = num_counter;
  15632 
  15633     return;
  15634 }
  15635 
  15636 
  15637  /*
  15638  * Function:
  15639  *      bcm_kt2_oam_endpoint_get
  15640  * Purpose:
  15641  *      Get an OAM endpoint object
  15642  * Parameters:
  15643  *     unit          - (IN) BCM device number
  15644  *     endpoint      - (IN) Endpoint ID
  15645  *     endpoint_info - (OUT) Pointer to OAM endpoint information buffer.
  15646  * Returns:
  15647  *     BCM_E_XXX
  15648  */
  15649 int
  15650 bcm_kt2_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint,
  15651                          bcm_oam_endpoint_info_t *endpoint_info)
  15652 {
  15653     _bcm_oam_hash_data_t *h_data_p;      /* Pointer to endpoint hash data.    */
  15654     int                  rv = BCM_E_NONE;/* Operation return status.          */
  15655     _bcm_oam_control_t   *oc;            /* Pointer to OAM control structure. */
  15656     rmep_entry_t         rmep_entry;     /* Remote MEP entry buffer.          */
  15657     lmep_entry_t         lmep_entry;     /* Local MEP entry buffer.           */
  15658     lmep_1_entry_t       lmep_1_entry;   /* Local MEP entry buffer.           */
  15659     void *entries[1];
  15660     uint32 mem_entries[BCM_OAM_INTPRI_MAX];
  15661     int  i = 0;
  15662     uint16 inner_vlan_pri = 0;
  15663 #if defined(INCLUDE_BHH)
  15664     bhh_sdk_msg_ctrl_sess_get_t msg;
  15665     uint8 *buffer, *buffer_ptr;
  15666     uint16 buffer_len, reply_len;
  15667     int sess_id = 0;
  15668     bcm_l3_egress_t l3_egress;
  15669     bcm_l3_intf_t l3_intf;
  15670 #endif
  15671     uint16 glp = 0;
  15672     bcm_gport_t          tx_gport = 0;       /* Gport value.                     */
  15673 
  15674     if (NULL == endpoint_info) {
  15675         return (BCM_E_PARAM);
  15676     }
  15677 
  15678     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  15679     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  15680     _BCM_OAM_LOCK(oc);
  15681 
  15682     h_data_p =  &oc->oam_hash_data[endpoint];
  15683     if (NULL == h_data_p) {
  15684         _BCM_OAM_UNLOCK(oc);
  15685         return (BCM_E_INTERNAL);
  15686     }
  15687 
  15688     if (0 == h_data_p->in_use) {
  15689         _BCM_OAM_UNLOCK(oc);
  15690         return (BCM_E_NOT_FOUND);
  15691     }
  15692     LOG_DEBUG(BSL_LS_BCM_OAM,
  15693               (BSL_META_U(unit,
  15694                           "OAM Info: Endpoint (EP=%d) remote=%d local_tx=%d"
  15695                            "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d oam_domain=%d\n"),
  15696                endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled,
  15697                h_data_p->local_tx_index, h_data_p->local_rx_enabled,
  15698                h_data_p->local_rx_index, h_data_p->oam_domain));
  15699     if (bcmOAMEndpointTypeEthernet == h_data_p->type) {
  15700         if (1 == h_data_p->is_remote) {
  15701 
  15702             sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
  15703 
  15704             /* Get hardware table entry information.  */
  15705             rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index,
  15706                             &rmep_entry);
  15707             if (BCM_FAILURE(rv)) {
  15708                     LOG_ERROR(BSL_LS_BCM_OAM,
  15709                               (BSL_META_U(unit,
  15710                                           "OAM Error: RMEP table read failed for"
  15711                                            " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
  15712                     _BCM_OAM_UNLOCK(oc);
  15713                     return (rv);
  15714             }
  15715 
  15716             rv = _bcm_kt2_oam_read_clear_faults(unit, h_data_p->remote_index,
  15717                                             RMEPm, (uint32 *) &rmep_entry,
  15718                                             (void *) endpoint_info);
  15719             if (BCM_FAILURE(rv)) {
  15720                 LOG_ERROR(BSL_LS_BCM_OAM,
  15721                           (BSL_META_U(unit,
  15722                                       "OAM Error: RMEP table read failed for"
  15723                                        " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
  15724                     _BCM_OAM_UNLOCK(oc);
  15725                     return (rv);
  15726             }
  15727             if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) {
  15728                 endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY;
  15729                 _BCM_OAM_UNLOCK(oc);
  15730                 return BCM_E_NONE;
  15731             }
  15732         } else {
  15733             if (1 == h_data_p->local_tx_enabled) {
  15734 
  15735                 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
  15736 
  15737                 /* Get hardware table entry information.  */
  15738                 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
  15739                                 &lmep_entry);
  15740                 if (BCM_FAILURE(rv)) {
  15741                     LOG_ERROR(BSL_LS_BCM_OAM,
  15742                               (BSL_META_U(unit,
  15743                                           "OAM Error: LMEP table read failed for EP=%d"
  15744                                            " %s.\n"), endpoint, bcm_errmsg(rv)));
  15745                     _BCM_OAM_UNLOCK(oc);
  15746                     return (rv);
  15747                 }
  15748 
  15749                 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf,
  15750                                    endpoint_info->src_mac_address);
  15751 
  15752                 endpoint_info->pkt_pri
  15753                     = soc_LMEPm_field32_get(unit, &lmep_entry, PRIORITYf);
  15754 
  15755                 endpoint_info->port_state
  15756                     = (soc_LMEPm_field32_get
  15757                         (unit, &lmep_entry, PORT_TLVf)
  15758                         ? BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED);
  15759                 inner_vlan_pri = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf);
  15760                 endpoint_info->inner_vlan = 0xFFF & inner_vlan_pri;
  15761                 endpoint_info->inner_pkt_pri = inner_vlan_pri >> 13;
  15762                 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t));
  15763 
  15764                 /* Get hardware table entry information.  */
  15765                 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
  15766                                 &lmep_1_entry);
  15767                 if (BCM_FAILURE(rv)) {
  15768                     LOG_ERROR(BSL_LS_BCM_OAM,
  15769                               (BSL_META_U(unit,
  15770                                           "OAM Error: LMEP_1 table read failed "
  15771                                           "for EP=%d"" %s.\n"), endpoint, bcm_errmsg(rv)));
  15772                     _BCM_OAM_UNLOCK(oc);
  15773                     return (rv);
  15774                 }
  15775                 soc_LMEP_1m_mac_addr_get(unit, &lmep_1_entry, DAf,
  15776                                      endpoint_info->dst_mac_address);
  15777 
  15778                 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  15779                     endpoint_info->int_pri = soc_LMEP_1m_field32_get(unit,
  15780                             &lmep_1_entry, INT_PRIf);
  15781                 } else {
  15782                     endpoint_info->int_pri = h_data_p->int_pri;
  15783                 }
  15784 
  15785                 endpoint_info->interface_state
  15786                    = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, INTERFACE_TLVf);
  15787 
  15788                 bcm_kt2_oam_hw_ccm_tx_ctr_get(unit, &lmep_1_entry, endpoint_info);
  15789                 glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf);
  15790                 _BCM_KT2_SUBPORT_PORT_ID_SET(tx_gport, glp);
  15791                 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) {
  15792                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(tx_gport, _BCM_KT2_SUBPORT_TYPE_GENERAL);
  15793                     endpoint_info->tx_gport = tx_gport;
  15794                     endpoint_info->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW;
  15795                 }
  15796             }
  15797         }
  15798     }
  15799     else if (soc_feature(unit, soc_feature_bhh) &&
  15800              BHH_EP_TYPE(h_data_p)) {
  15801 #if defined(INCLUDE_BHH)
  15802         if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  15803             sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint);
  15804             rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  15805                     MOS_MSG_SUBCLASS_BHH_SESS_GET,
  15806                     sess_id, 0,
  15807                     MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  15808                     &reply_len);
  15809             if (BCM_FAILURE(rv)) {
  15810                 LOG_ERROR(BSL_LS_BCM_OAM,
  15811                         (BSL_META_U(unit,
  15812                                     "OAM(unit %d) Error: ukernel msg failed for"
  15813                                     " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  15814                 _BCM_OAM_UNLOCK(oc);
  15815                 return (rv);
  15816             }
  15817 
  15818             /* Pack control message data into DMA buffer */
  15819             buffer = oc->dma_buffer;
  15820             buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  15821             buffer_len = buffer_ptr - buffer;
  15822 
  15823             if (reply_len != buffer_len) {
  15824                 rv = BCM_E_INTERNAL;
  15825                 LOG_ERROR(BSL_LS_BCM_OAM,
  15826                         (BSL_META_U(unit,
  15827                                     "OAM(unit %d) Error: ukernel msg failed for"
  15828                                     " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  15829                 _BCM_OAM_UNLOCK(oc);
  15830                 return (rv);
  15831             } else {
  15832                 endpoint_info->int_pri = msg.tx_cos;
  15833                 endpoint_info->pkt_pri = msg.tx_pri;
  15834                 endpoint_info->mpls_exp = msg.priority;
  15835 
  15836                 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
  15837                     endpoint_info->name       = msg.remote_mep_id;
  15838                     endpoint_info->ccm_period = msg.remote_period;
  15839                 } else {
  15840                     endpoint_info->name       = msg.mep_id;
  15841                     endpoint_info->ccm_period = msg.local_period;
  15842                 }
  15843 
  15844                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
  15845                     endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  15846                 }
  15847                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
  15848                     endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  15849                 }
  15850                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  15851                     endpoint_info->faults |=
  15852                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  15853                 }
  15854                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  15855                     endpoint_info->faults |=
  15856                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  15857                 }
  15858                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  15859                     endpoint_info->faults |=
  15860                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  15861                 }
  15862                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  15863                     endpoint_info->faults |=
  15864                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  15865                 }
  15866                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  15867                     endpoint_info->faults |=
  15868                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  15869                 }
  15870                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
  15871                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
  15872                 }
  15873                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
  15874                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
  15875                 }
  15876                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
  15877                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
  15878                 }
  15879             }
  15880         }else {
  15881             endpoint_info->ccm_period = h_data_p->period;
  15882             endpoint_info->int_pri = h_data_p->int_pri;
  15883             endpoint_info->pkt_pri = h_data_p->vlan_pri;
  15884         }
  15885 
  15886         endpoint_info->intf_id    = h_data_p->egress_if;
  15887         endpoint_info->cpu_qid    =  h_data_p->cpu_qid;
  15888         endpoint_info->mpls_label = h_data_p->label;
  15889         endpoint_info->gport      = h_data_p->gport;
  15890         endpoint_info->vpn        = h_data_p->vpn;
  15891         endpoint_info->vccv_type  = h_data_p->vccv_type;
  15892         endpoint_info->egress_label.label = h_data_p->egr_label;
  15893         endpoint_info->egress_label.exp = h_data_p->egr_label_exp;
  15894         endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl;
  15895         endpoint_info->inner_pkt_pri = h_data_p->inner_vlan_pri;
  15896         if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  15897             /*
  15898             * Get MAC address
  15899             */
  15900             bcm_l3_egress_t_init(&l3_egress);
  15901             bcm_l3_intf_t_init(&l3_intf);
  15902 
  15903             if (BCM_FAILURE
  15904                 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  15905                 _BCM_OAM_UNLOCK(oc);
  15906                 return (BCM_E_INTERNAL);
  15907             }
  15908 
  15909             l3_intf.l3a_intf_id = l3_egress.intf;
  15910             if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  15911                 _BCM_OAM_UNLOCK(oc);
  15912                 return (BCM_E_INTERNAL);
  15913             }
  15914 
  15915             sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr,
  15916                    _BHH_MAC_ADDR_LENGTH);
  15917         } else {
  15918             sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address,
  15919                 _BHH_MAC_ADDR_LENGTH);
  15920             sal_memcpy(endpoint_info->dst_mac_address, h_data_p->dst_mac_address,
  15921                 _BHH_MAC_ADDR_LENGTH);
  15922         }
  15923 #else
  15924         _BCM_OAM_UNLOCK(oc);
  15925         return (BCM_E_UNAVAIL);
  15926 #endif /* INCLUDE_BHH */
  15927     }
  15928     else {
  15929         _BCM_OAM_UNLOCK(oc);
  15930         return (BCM_E_PARAM);
  15931     }
  15932 
  15933     /* BHH MEP Id & period already filled from uC msg */
  15934     if (!BHH_EP_TYPE(h_data_p)) {
  15935         endpoint_info->name = h_data_p->name;
  15936         endpoint_info->ccm_period = h_data_p->period;
  15937     }
  15938 
  15939     endpoint_info->id = endpoint;
  15940     endpoint_info->group = h_data_p->group_index;
  15941     endpoint_info->vlan = h_data_p->vlan;
  15942     endpoint_info->inner_vlan = h_data_p->inner_vlan;
  15943     endpoint_info->level = h_data_p->level;
  15944     endpoint_info->gport = h_data_p->gport;
  15945     endpoint_info->trunk_index = h_data_p->trunk_index;
  15946     endpoint_info->flags |= h_data_p->flags;
  15947     endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID);
  15948     endpoint_info->opcode_flags = h_data_p->opcode_flags;
  15949     endpoint_info->type = h_data_p->type;
  15950     endpoint_info->lm_counter_base_id = h_data_p->rx_ctr;
  15951     endpoint_info->outer_tpid = h_data_p->outer_tpid;
  15952     endpoint_info->inner_tpid = h_data_p->inner_tpid;
  15953     endpoint_info->subport_tpid = h_data_p->subport_tpid;
  15954     endpoint_info->timestamp_format = h_data_p->ts_format;
  15955     entries[0] = &mem_entries;
  15956     if (h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) {
  15957         rv = soc_profile_mem_get(unit, &oc->ing_service_pri_map,
  15958                            (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX),
  15959                            BCM_OAM_INTPRI_MAX, (void *)entries);
  15960         for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) {
  15961             if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) {
  15962                 soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i],
  15963                                     OFFSET_VALIDf, 0);
  15964                 endpoint_info->pri_map[i] = mem_entries[i];
  15965             }
  15966         }
  15967         endpoint_info->pri_map_id = h_data_p->pri_map_index;
  15968     }
  15969     _BCM_OAM_UNLOCK(oc);
  15970     return (BCM_E_NONE);
  15971 }
  15972 
  15973 
  15974 /*
  15975  * Function:
  15976  *     bcm_kt2_oam_endpoint_destroy
  15977  * Purpose:
  15978  *     Destroy an OAM endpoint object
  15979  * Parameters:
  15980  *     unit     - (IN) BCM device number
  15981  *     endpoint - (IN) Endpoint ID to destroy.
  15982  * result =s:
  15983  *     BCM_E_XXX
  15984  */
  15985 int
  15986 bcm_kt2_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint)
  15987 {
  15988     _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */
  15989     int rv;                 /* Operation return status.          */
  15990 
  15991     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  15992     /* Validate endpoint index value. */
  15993     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  15994 
  15995     _BCM_OAM_LOCK(oc);
  15996 
  15997     rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint);
  15998     if (BCM_FAILURE(rv)) {
  15999         LOG_ERROR(BSL_LS_BCM_OAM,
  16000                   (BSL_META_U(unit,
  16001                               "OAM Error: Endpoint destroy EP=%d failed - "
  16002                                "%s.\n"), endpoint, bcm_errmsg(rv)));
  16003     }
  16004 
  16005     _BCM_OAM_UNLOCK(oc);
  16006     return (rv);
  16007 }
  16008 
  16009 /*
  16010  * Function:
  16011  *     bcm_kt2_oam_endpoint_destroy_all
  16012  * Purpose:
  16013  *     Destroy all OAM endpoint objects associated with a group.
  16014  * Parameters:
  16015  *     unit  - (IN) BCM device number
  16016  *     group - (IN) The OAM group whose endpoints should be destroyed
  16017  * Returns:
  16018  *     BCM_E_XXX
  16019  */
  16020 int
  16021 bcm_kt2_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group)
  16022 {
  16023     _bcm_oam_control_t    *oc; /* Pointer to OAM control structure. */
  16024     int                   rv;  /* Operation return status.          */
  16025     _bcm_oam_group_data_t *g_info_p;
  16026 
  16027     /* Get OAM device control structure. */
  16028     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16029 
  16030     /* Validate group index. */
  16031     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  16032 
  16033     _BCM_OAM_LOCK(oc);
  16034 
  16035     /* Check if the group is in use. */
  16036     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  16037     if (BCM_E_EXISTS != rv) {
  16038         _BCM_OAM_UNLOCK(oc);
  16039         LOG_ERROR(BSL_LS_BCM_OAM,
  16040                   (BSL_META_U(unit,
  16041                               "OAM Error: Group ID=%d does not exist.\n"),
  16042                    group));
  16043         return (rv);
  16044     }
  16045 
  16046     /* Get the group data pointer. */
  16047     g_info_p = &oc->group_info[group];
  16048     rv = _bcm_kt2_oam_group_endpoints_destroy(unit, g_info_p);
  16049     if (BCM_FAILURE(rv)) {
  16050         LOG_ERROR(BSL_LS_BCM_OAM,
  16051                   (BSL_META_U(unit,
  16052                               "OAM Error: Group (GID=%d) endpoints destroy"
  16053                                " failed - %s.\n"), group, bcm_errmsg(rv)));
  16054         _BCM_OAM_UNLOCK(oc);
  16055         return (rv);
  16056     }
  16057     _BCM_OAM_UNLOCK(oc);
  16058     return (rv);
  16059 }
  16060 
  16061 /*
  16062  * Function:
  16063  *     bcm_kt2_oam_endpoint_traverse
  16064  * Purpose:
  16065  *     Traverse the set of OAM endpoints associated with the
  16066  *     specified group, calling a specified callback for each one
  16067  * Parameters:
  16068  *     unit      - (IN) BCM device number
  16069  *     group     - (IN) The OAM group whose endpoints should be traversed
  16070  *     cb        - (IN) A pointer to the callback function to call for each OAM
  16071  *                      endpoint in the specified group
  16072  *     user_data - (IN) Pointer to user data to supply in the callback
  16073  * Returns:
  16074  *      BCM_E_XXX
  16075  */
  16076 int
  16077 bcm_kt2_oam_endpoint_traverse(int unit, bcm_oam_group_t group,
  16078                               bcm_oam_endpoint_traverse_cb cb,
  16079                               void *user_data)
  16080 {
  16081     _bcm_oam_control_t      *oc; /* Pointer to OAM control structure. */
  16082     int                     rv;  /* Operation return status.          */
  16083     bcm_oam_endpoint_info_t ep_info;
  16084     _bcm_oam_hash_data_t    *h_data_p;
  16085     _bcm_oam_ep_list_t      *cur;
  16086     _bcm_oam_group_data_t   *g_info_p;
  16087 
  16088     /* Validate input parameter. */
  16089     if (NULL == cb) {
  16090         return (BCM_E_PARAM);
  16091     }
  16092 
  16093     /* Get OAM device control structure. */
  16094     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16095 
  16096     /* Validate group index. */
  16097     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  16098 
  16099     _BCM_OAM_LOCK(oc);
  16100 
  16101     /* Check if the group is in use. */
  16102     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  16103     if (BCM_E_EXISTS != rv) {
  16104         _BCM_OAM_UNLOCK(oc);
  16105         LOG_ERROR(BSL_LS_BCM_OAM,
  16106                   (BSL_META_U(unit,
  16107                               "OAM Error: Group ID=%d does not exist.\n"),
  16108                    group));
  16109         return (rv);
  16110     }
  16111 
  16112     /* Get the group data pointer. */
  16113     g_info_p = &oc->group_info[group];
  16114 
  16115     /* Get the endpoint list head pointer. */
  16116     cur = *(g_info_p->ep_list);
  16117     if (NULL == cur) {
  16118         _BCM_OAM_UNLOCK(oc);
  16119         LOG_DEBUG(BSL_LS_BCM_OAM,
  16120                   (BSL_META_U(unit,
  16121                               "OAM Info: No endpoints in group GID=%d.\n"),
  16122                    group));
  16123         return (BCM_E_NONE);
  16124     }
  16125 
  16126     /* Traverse to the tail of the list. */
  16127     while (NULL != cur->next) {
  16128         LOG_DEBUG(BSL_LS_BCM_OAM,
  16129                   (BSL_META_U(unit,
  16130                               "OAM Info: GID=%d EP:%d.\n"),
  16131                    cur->ep_data_p->group_index, cur->ep_data_p->ep_id));
  16132         cur = cur->next;
  16133     }
  16134 
  16135     while (NULL != cur) {
  16136         h_data_p = cur->ep_data_p;
  16137         if (NULL == h_data_p) {
  16138             LOG_ERROR(BSL_LS_BCM_OAM,
  16139                       (BSL_META_U(unit,
  16140                                   "OAM Error: Group=%d endpoints access failed -"
  16141                                    " %s.\n"), group, bcm_errmsg(BCM_E_INTERNAL)));
  16142             _BCM_OAM_UNLOCK(oc);
  16143             return (BCM_E_INTERNAL);
  16144         }
  16145         bcm_oam_endpoint_info_t_init(&ep_info);
  16146 
  16147         rv = bcm_kt2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info);
  16148         if (BCM_FAILURE(rv)) {
  16149             _BCM_OAM_UNLOCK(oc);
  16150             LOG_ERROR(BSL_LS_BCM_OAM,
  16151                       (BSL_META_U(unit,
  16152                                   "OAM Error: EP=%d info get failed %s.\n"),
  16153                        h_data_p->ep_id, bcm_errmsg(rv)));
  16154             return (rv);
  16155         }
  16156 
  16157         rv = cb(unit, &ep_info, user_data);
  16158         if (BCM_FAILURE(rv)) {
  16159             _BCM_OAM_UNLOCK(oc);
  16160             LOG_ERROR(BSL_LS_BCM_OAM,
  16161                       (BSL_META_U(unit,
  16162                                   "OAM Error: EP=%d callback failed - %s.\n"),
  16163                        h_data_p->ep_id, bcm_errmsg(rv)));
  16164             return (rv);
  16165         }
  16166         cur = cur->prev;
  16167     }
  16168     _BCM_OAM_UNLOCK(oc);
  16169     return (rv);
  16170 }
  16171 
  16172 /*
  16173  * Function:
  16174  *     bcm_kt2_oam_event_register
  16175  * Purpose:
  16176  *     Register a callback for handling OAM events
  16177  * Parameters:
  16178  *     unit        - (IN) BCM device number
  16179  *     event_types - (IN) The set of OAM events for which the specified
  16180  *                        callback should be called.
  16181  *     cb          - (IN) A pointer to the callback function to call for
  16182  *                        the specified OAM events
  16183  *     user_data   - (IN) Pointer to user data to supply in the callback
  16184  * Returns:
  16185  *      BCM_E_XXX
  16186  */
  16187 int
  16188 bcm_kt2_oam_event_register(int unit, bcm_oam_event_types_t event_types,
  16189                            bcm_oam_event_cb cb, void *user_data)
  16190 {
  16191     _bcm_oam_control_t       *oc;
  16192     _bcm_oam_event_handler_t *event_h_p;
  16193     _bcm_oam_event_handler_t *prev_p = NULL;
  16194     bcm_oam_event_type_t     e_type;
  16195     uint32                   rval;
  16196     int                      hw_update = 0;
  16197     uint32                   event_bmp;
  16198     int                      rv;             /* Operation return status. */
  16199 
  16200     /* Validate event callback input parameter. */
  16201     if (NULL == cb) {
  16202         return (BCM_E_PARAM);
  16203     }
  16204 
  16205     /* Check if an event is set for register in the events bitmap. */
  16206     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  16207     if (0 == event_bmp) {
  16208         /* No events specified. */
  16209         LOG_ERROR(BSL_LS_BCM_OAM,
  16210                   (BSL_META_U(unit,
  16211                               "OAM Error: No events specified for register.\n")));
  16212         return (BCM_E_PARAM);
  16213     }
  16214 
  16215     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16216 
  16217     _BCM_OAM_LOCK(oc);
  16218 
  16219     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  16220          event_h_p = event_h_p->next_p) {
  16221         if (event_h_p->cb == cb) {
  16222             break;
  16223         }
  16224         prev_p = event_h_p;
  16225     }
  16226 
  16227     if (NULL == event_h_p) {
  16228 
  16229         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t,
  16230              sizeof(_bcm_oam_event_handler_t), "OAM event handler");
  16231 
  16232         if (NULL == event_h_p) {
  16233             LOG_ERROR(BSL_LS_BCM_OAM,
  16234                       (BSL_META_U(unit,
  16235                                   "OAM Error: Event handler alloc failed -"
  16236                                    " %s.\n"), bcm_errmsg(BCM_E_MEMORY)));
  16237             _BCM_OAM_UNLOCK(oc);
  16238             return (BCM_E_MEMORY);
  16239         }
  16240 
  16241         event_h_p->next_p = NULL;
  16242         event_h_p->cb = cb;
  16243 
  16244         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
  16245         if (prev_p != NULL) {
  16246             prev_p->next_p = event_h_p;
  16247         } else {
  16248             oc->event_handler_list_p = event_h_p;
  16249         }
  16250     }
  16251 
  16252     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  16253     if (BCM_FAILURE(rv)) {
  16254         _BCM_OAM_UNLOCK(oc);
  16255         LOG_ERROR(BSL_LS_BCM_OAM,
  16256                   (BSL_META_U(unit,
  16257                               "OAM Error: CCM interrupt control read failed -"
  16258                                " %s.\n"), bcm_errmsg(rv)));
  16259         return (rv);
  16260     }
  16261 
  16262     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  16263         if (SHR_BITGET(event_types.w, e_type)) {
  16264             if(soc_feature(unit, soc_feature_bhh)) {
  16265 #if defined(INCLUDE_BHH)
  16266                 /*
  16267                 * BHH events are generated by the uKernel
  16268                 */
  16269                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  16270                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  16271                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  16272                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  16273                     (e_type == bcmOAMEventBHHCCMState) ||
  16274                     (e_type == bcmOAMEventBHHCCMRdi) ||
  16275                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  16276                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  16277                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  16278                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  16279                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  16280                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  16281                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  16282                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  16283                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  16284                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  16285                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  16286                     (e_type == bcmOAMEventCsfLos) ||
  16287                     (e_type == bcmOAMEventCsfFdi) ||
  16288                     (e_type == bcmOAMEventCsfRdi) ||
  16289                     (e_type == bcmOAMEventBhhPmCounterRollover) ||
  16290                     (e_type == bcmOAMEventCsfDci)) {
  16291                     SHR_BITSET(event_h_p->event_types.w, e_type);
  16292                     oc->event_handler_cnt[e_type] += 1;
  16293                     continue;
  16294                 }
  16295 #endif
  16296             }
  16297             if (!soc_reg_field_valid
  16298                     (unit, CCM_INTERRUPT_CONTROLr,
  16299                      _kt2_oam_intr_en_fields[e_type].field)) {
  16300                 continue;
  16301             }
  16302 
  16303             if (!SHR_BITGET(event_h_p->event_types.w, e_type)) {
  16304                 /* Add this event to the registered events list. */
  16305                 SHR_BITSET(event_h_p->event_types.w, e_type);
  16306                 oc->event_handler_cnt[e_type] += 1;
  16307                 if (1 == oc->event_handler_cnt[e_type]) {
  16308                     hw_update = 1;
  16309                      soc_reg_field_set
  16310                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  16311                          _kt2_oam_intr_en_fields[e_type].field, 1);
  16312                 }
  16313             }
  16314         }
  16315     }
  16316 
  16317     event_h_p->user_data = user_data;
  16318 
  16319     if (1 == hw_update) {
  16320         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  16321         if (BCM_FAILURE(rv)) {
  16322             _BCM_OAM_UNLOCK(oc);
  16323             LOG_ERROR(BSL_LS_BCM_OAM,
  16324                       (BSL_META_U(unit,
  16325                                   "OAM Error: CCM interrupt control write failed -"
  16326                                    " %s.\n"), bcm_errmsg(rv)));
  16327             return (rv);
  16328         }
  16329     }
  16330     if (soc_feature(unit, soc_feature_bhh)) {
  16331 #if defined(INCLUDE_BHH)
  16332         /*
  16333          * Update BHH Events mask
  16334          */
  16335         rv = _bcm_kt2_oam_bhh_event_mask_set(unit);
  16336 #endif /* INCLUDE_BHH */
  16337     }
  16338 
  16339     _BCM_OAM_UNLOCK(oc);
  16340 
  16341     return (BCM_E_NONE);
  16342 }
  16343 
  16344 /*
  16345  * Function:
  16346  *     bcm_kt2_oam_event_unregister
  16347  * Purpose:
  16348  *     Remove a registered event from the event handler list.
  16349  * Parameters:
  16350  *     unit        - (IN) BCM device number
  16351  *     event_types - (IN) The set of OAM events for which the specified
  16352  *                        callback should not be called
  16353  *     cb          - (IN) A pointer to the callback function to unregister
  16354  *                        from the specified OAM events
  16355  * Returns:
  16356  *      BCM_E_XXX
  16357  */
  16358 int
  16359 bcm_kt2_oam_event_unregister(int unit, bcm_oam_event_types_t event_types,
  16360                              bcm_oam_event_cb cb)
  16361 {
  16362     _bcm_oam_control_t       *oc;
  16363     _bcm_oam_event_handler_t *event_h_p;
  16364     _bcm_oam_event_handler_t *prev_p = NULL;
  16365     bcm_oam_event_type_t     e_type;
  16366     uint32                   rval;
  16367     int                      hw_update = 0;
  16368     uint32                   event_bmp;
  16369     int                      rv;             /* Operation return status. */
  16370   
  16371     /* Validate event callback input parameter. */
  16372     if (NULL == cb) {
  16373         return (BCM_E_PARAM);
  16374     }
  16375 
  16376     /* Check if an event is set for unregister in the events bitmap. */
  16377     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  16378     if (0 == event_bmp) {
  16379         /* No events specified. */
  16380         LOG_ERROR(BSL_LS_BCM_OAM,
  16381                   (BSL_META_U(unit,
  16382                               "OAM Error: No events specified for register.\n")));
  16383         return (BCM_E_PARAM);
  16384     }
  16385 
  16386     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16387 
  16388     _BCM_OAM_LOCK(oc);
  16389 
  16390     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  16391          event_h_p = event_h_p->next_p) {
  16392         if (event_h_p->cb == cb) {
  16393             break;
  16394         }
  16395         prev_p = event_h_p;
  16396     }
  16397 
  16398     if (NULL == event_h_p) {
  16399         _BCM_OAM_UNLOCK(oc);
  16400         return (BCM_E_NOT_FOUND);
  16401     }
  16402  
  16403     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  16404     if (BCM_FAILURE(rv)) {
  16405         _BCM_OAM_UNLOCK(oc);
  16406         LOG_ERROR(BSL_LS_BCM_OAM,
  16407                   (BSL_META_U(unit,
  16408                               "OAM Error: CCM interrupt control read failed -"
  16409                                " %s.\n"), bcm_errmsg(rv)));
  16410         return (rv);
  16411     }
  16412 
  16413     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  16414 
  16415         if (SHR_BITGET(event_types.w, e_type)) {
  16416             if(soc_feature(unit, soc_feature_bhh)) {
  16417 #if defined(INCLUDE_BHH)
  16418                 /*
  16419                 * BHH events are generated by the uKernel
  16420                 */
  16421                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  16422                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  16423                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  16424                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  16425                     (e_type == bcmOAMEventBHHCCMState) ||
  16426                     (e_type == bcmOAMEventBHHCCMRdi) ||
  16427                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  16428                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  16429                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  16430                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  16431                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  16432                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  16433                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  16434                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  16435                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  16436                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  16437                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  16438                     (e_type == bcmOAMEventCsfLos) ||
  16439                     (e_type == bcmOAMEventCsfFdi) ||
  16440                     (e_type == bcmOAMEventCsfRdi) ||
  16441                     (e_type == bcmOAMEventCsfDci) ||
  16442                     (e_type == bcmOAMEventBhhPmCounterRollover)) {
  16443                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  16444                     oc->event_handler_cnt[e_type] -= 1;
  16445                     continue;
  16446                 }
  16447 #endif
  16448             }
  16449 
  16450             if (!soc_reg_field_valid
  16451                     (unit, CCM_INTERRUPT_CONTROLr,
  16452                      _kt2_oam_intr_en_fields[e_type].field)) {
  16453                 _BCM_OAM_UNLOCK(oc);
  16454                 return (BCM_E_UNAVAIL);
  16455             }
  16456 
  16457             if ((oc->event_handler_cnt[e_type] > 0)
  16458                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
  16459 
  16460                 /* Remove this event from the registered events list. */
  16461                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  16462 
  16463                 oc->event_handler_cnt[e_type] -= 1;
  16464 
  16465                 if (0 == oc->event_handler_cnt[e_type]) {
  16466                     hw_update = 1;
  16467                      soc_reg_field_set
  16468                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  16469                          _kt2_oam_intr_en_fields[e_type].field, 0);
  16470                 }
  16471             }
  16472         }
  16473     }
  16474 
  16475     if (1 == hw_update) {
  16476         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  16477         if (BCM_FAILURE(rv)) {
  16478             _BCM_OAM_UNLOCK(oc);
  16479             LOG_ERROR(BSL_LS_BCM_OAM,
  16480                       (BSL_META_U(unit,
  16481                                   "OAM Error: CCM interrupt control write failed -"
  16482                                    " %s.\n"), bcm_errmsg(rv)));
  16483             return (rv);
  16484         }
  16485     }
  16486 
  16487     SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp);
  16488 
  16489     if (0 == event_bmp) {
  16490 
  16491         if (NULL != prev_p) {
  16492 
  16493             prev_p->next_p = event_h_p->next_p;
  16494             
  16495         } else {
  16496 
  16497             oc->event_handler_list_p = event_h_p->next_p;
  16498 
  16499         }
  16500         sal_free(event_h_p);
  16501     }
  16502     if(soc_feature(unit, soc_feature_bhh)) {
  16503 #if defined(INCLUDE_BHH)
  16504         /*
  16505          * Update BHH Events mask
  16506          */
  16507         rv = _bcm_kt2_oam_bhh_event_mask_set(unit);
  16508 #endif /* INCLUDE_BHH */
  16509     }
  16510     _BCM_OAM_UNLOCK(oc);
  16511     return (BCM_E_NONE);
  16512 }
  16513 
  16514 
  16515 /*
  16516  * Function:
  16517  *     bcm_kt2_oam_endpoint_action_set
  16518  * Purpose:
  16519  *     Remove a registered event from the event handler list.
  16520  * Parameters:
  16521  *     unit        - (IN) BCM device number
  16522  *     endpoint    - (IN) Endpoint id
  16523  *     action      - (IN) Set of OAM endpoint actions, for a set of
  16524  *                        opcodes specified.
  16525  * Returns:
  16526  *      BCM_E_XXX
  16527  *  In order to put the opcodes into opcode group1 and group2, first call the
  16528  *  action set API with opcode action and set of opcodes that need to use 
  16529  *  this action. This will put all these opcodes under group1. To put
  16530  *  the opcode to group2, call the set API with an action(with all the opcodes 
  16531  *  that need this action) which is differing compared to group1. This will 
  16532  *  classify the opcode to group2 
  16533  */
  16534 int bcm_kt2_oam_endpoint_action_set(int unit, bcm_oam_endpoint_t endpoint, 
  16535                                     bcm_oam_endpoint_action_t *action) 
  16536 {
  16537     int            rv = BCM_E_NONE;  /* Operation return status.          */
  16538     _bcm_oam_hash_data_t *h_data_p;  /* Pointer to endpoint hash data.    */
  16539     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  16540     void                 *entries[1]; 
  16541     oam_opcode_control_profile_entry_t opcode_profile;
  16542     egr_oam_opcode_control_profile_entry_t egr_opcode_profile;
  16543     soc_profile_mem_t    *profile_mem_ptr;
  16544     soc_mem_t     ma_index_mem = MA_INDEXm;
  16545     ma_index_entry_t     ma_idx_entry;   /* MA_INDEX table entry buffer.     */
  16546     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/
  16547     void                 *ma_idx_ptr;
  16548     int                  ma_offset = 0;
  16549     uint32               old_profile_index = 0;
  16550     char                 free_old_profile = 0;
  16551     /*setting default value to 0 whcih will be converted to 1 
  16552      * if opcode control profile set is touched */
  16553     uint8                opcode_profile_changed = 0;
  16554 
  16555     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16556     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  16557 
  16558     sal_memset(&opcode_profile, 0, sizeof(oam_opcode_control_profile_entry_t));
  16559     sal_memset(&egr_opcode_profile, 0, 
  16560                              sizeof(egr_oam_opcode_control_profile_entry_t));
  16561 
  16562     _BCM_OAM_LOCK(oc);
  16563 
  16564     /* Check endpoint status. */
  16565     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint);
  16566     if ((BCM_E_EXISTS != rv)) {
  16567         /* Endpoint not in use. */
  16568         LOG_ERROR(BSL_LS_BCM_OAM,
  16569                   (BSL_META_U(unit,
  16570                               "OAM Error: Endpoint EP=%d %s.\n"),
  16571                    endpoint, bcm_errmsg(rv)));
  16572         _BCM_OAM_UNLOCK(oc);
  16573         return (rv);
  16574     }
  16575 
  16576     h_data_p =  &oc->oam_hash_data[endpoint];
  16577     if (NULL == h_data_p) {
  16578         _BCM_OAM_UNLOCK(oc);
  16579         return (BCM_E_INTERNAL);
  16580     }
  16581 
  16582     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  16583         entries[0] = &egr_opcode_profile;
  16584         profile_mem_ptr =  &oc->egr_oam_opcode_control_profile;
  16585         ma_index_mem = EGR_MA_INDEXm;
  16586         ma_idx_ptr = &egr_ma_idx_entry; 
  16587     } else {
  16588         entries[0] = &opcode_profile;
  16589         profile_mem_ptr =  &oc->oam_opcode_control_profile;
  16590         ma_idx_ptr = &ma_idx_entry; 
  16591     }
  16592 
  16593     /* Get MA_INDEX offset  */
  16594     rv = _bcm_kt2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset);
  16595 
  16596     h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  16597     
  16598     /* Using the profile index, get the profile */
  16599     if ((h_data_p->profile_index == _BCM_OAM_INVALID_INDEX) ||
  16600         (h_data_p->profile_index == 0)) {
  16601       /* No profile exists or default profile is used, create one */
  16602       /* convert action into opcode profile entry */
  16603         rv = _bcm_kt2_oam_convert_action_to_opcode_entry(unit, action, 
  16604                                                     endpoint, 
  16605                                                     entries[0],
  16606                                                     &opcode_profile_changed);
  16607         if (BCM_FAILURE(rv)) {
  16608             _BCM_OAM_UNLOCK(oc);
  16609             LOG_ERROR(BSL_LS_BCM_OAM,
  16610                       (BSL_META_U(unit,
  16611                                   "OAM Error: Failed to convert action to "
  16612                                   "profile -" " %s.\n"), bcm_errmsg(rv)));
  16613             return (rv);
  16614         }
  16615         if(opcode_profile_changed) {
  16616             rv = soc_profile_mem_add(unit, profile_mem_ptr,
  16617                     (void *)entries, 1, 
  16618                     (uint32 *) &h_data_p->profile_index);
  16619             if (BCM_FAILURE(rv)) {
  16620                 _BCM_OAM_UNLOCK(oc);
  16621                 LOG_ERROR(BSL_LS_BCM_OAM,
  16622                         (BSL_META_U(unit,
  16623                                     "OAM Error: Soc profile mem add failed -"
  16624                                     " %s.\n"), bcm_errmsg(rv)));
  16625                 return (rv);
  16626             }
  16627         }
  16628     } else {
  16629         free_old_profile = 1;
  16630         old_profile_index = h_data_p->profile_index;
  16631 
  16632         rv = soc_profile_mem_get(unit, profile_mem_ptr,
  16633                                  old_profile_index, 1, entries);
  16634         if (BCM_FAILURE(rv)) {
  16635             _BCM_OAM_UNLOCK(oc);
  16636             LOG_ERROR(BSL_LS_BCM_OAM,
  16637                       (BSL_META_U(unit,
  16638                                   "OAM Error: Soc profile mem get failed -"
  16639                                    " %s.\n"), bcm_errmsg(rv)));
  16640             return (rv);
  16641         }
  16642         /* convert action into opcode profile entry */
  16643         _bcm_kt2_oam_convert_action_to_opcode_entry(unit, action, 
  16644                                                     endpoint, 
  16645                                                     entries[0],
  16646                                                     &opcode_profile_changed);
  16647 
  16648         /* Add new profile */
  16649         rv = soc_profile_mem_add(unit, profile_mem_ptr,
  16650                                  (void *)entries, 1, 
  16651                                  (uint32 *) &h_data_p->profile_index);
  16652         if (BCM_FAILURE(rv)) {
  16653             _BCM_OAM_UNLOCK(oc);
  16654             LOG_ERROR(BSL_LS_BCM_OAM,
  16655                       (BSL_META_U(unit,
  16656                                   "OAM Error: Soc profile mem add failed -"
  16657                                    " %s.\n"), bcm_errmsg(rv)));
  16658             return (rv);
  16659         }
  16660     } 
  16661     /* Set OAM opcode control profile table index. */
  16662     rv = soc_mem_read(unit, ma_index_mem, MEM_BLOCK_ANY, 
  16663                       h_data_p->local_rx_index, ma_idx_ptr);
  16664     if (BCM_FAILURE(rv)) {
  16665         _BCM_OAM_UNLOCK(oc);
  16666         LOG_ERROR(BSL_LS_BCM_OAM,
  16667                   (BSL_META_U(unit,
  16668                               "OAM Error: MA index table entry  read failed  "
  16669                               "%s.\n"), bcm_errmsg(rv)));
  16670         return (rv);
  16671     }
  16672     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
  16673                               OAM_OPCODE_CONTROL_PROFILE_PTRf,
  16674                               h_data_p->profile_index);
  16675     rv = soc_mem_write(unit, ma_index_mem, MEM_BLOCK_ALL,
  16676                   h_data_p->local_rx_index, ma_idx_ptr);
  16677 
  16678     /* Delete old profile once ma_index is pointing to new one*/
  16679     if(free_old_profile) {
  16680         rv = soc_profile_mem_delete(unit, profile_mem_ptr,
  16681                                     old_profile_index);
  16682         if (BCM_FAILURE(rv)) {
  16683             _BCM_OAM_UNLOCK(oc);
  16684             LOG_ERROR(BSL_LS_BCM_OAM,
  16685                       (BSL_META_U(unit,
  16686                                   "OAM Error: Soc profile mem delete failed -"
  16687                                    " %s.\n"), bcm_errmsg(rv)));
  16688             return (rv);
  16689         }
  16690 
  16691     }
  16692 
  16693     _BCM_OAM_UNLOCK(oc);
  16694     return rv;
  16695 }
  16696 
  16697 /*
  16698  * Function:
  16699  *     _kt2_oam_opcode_control_field_set
  16700  * Purpose:
  16701  *   Set the fields of opcode profile entry 
  16702  * Parameters:
  16703  *     unit        - (IN) BCM device number
  16704  *     field_index - (IN) Opcode profile action to be set
  16705  *     mem         - (IN) Opcode profile memory - ing/egr
  16706  *     oam_opcode  - (IN) Oam opcode for which action needs to be set
  16707  *     value       - (IN) value of the opcode action
  16708  *     profile     - (OUT) Pointer to the opcode profile table index.
  16709  * Returns:
  16710  *      BCM_E_XXX
  16711  */
  16712 int
  16713 _kt2_oam_opcode_control_field_set(int unit, bcm_oam_action_type_t field_index, 
  16714                                   soc_mem_t mem, int oam_opcode, int value, 
  16715                                   void *profile) 
  16716 {
  16717     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  16718     ingress_oam_opcode_group_entry_t entry;
  16719     int grp_1_modified = 0;
  16720     int grp_2_modified = 0;
  16721     uint32 opcode_bmp_1 = 0;
  16722     uint32 opcode_bmp_2 = 0;
  16723     soc_field_t cfm_field[bcmOAMActionCount+1][_BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST] =  { 
  16724                    /* bcmOAMActionCountEnable */ 
  16725                  { 0, 0, 0, 0, 0, 0}, 
  16726                    /* bcmOAMActionMeterEnable */ 
  16727                  { 0, 0, 0, 0, 0, 0}, 
  16728                  /* bcmOAMActionDrop */
  16729                  { 0, CCM_DROPf, LBR_DROPf, LBM_UC_DROPf, 
  16730                       LTR_DROPf, LTM_DROPf },    
  16731                   /* bcmOAMActionCopyToCpu */
  16732                  { 0, CCM_COPYTO_CPUf, LBR_COPYTO_CPUf, LBM_UC_COPYTO_CPUf, 
  16733                       LTR_COPYTO_CPUf, LTM_COPYTO_CPUf},
  16734                   /* bcmOAMActionFwdAsData */
  16735                  { 0, 0, 0, 0, 0, 0 },
  16736                    /* bcmOAMActionFwd */
  16737                  { 0, FWD_LMEP_PKTf, LBR_FWDf, LBM_ACTIONf, LTR_FWDf, LTM_FWDf},
  16738                  /* bcmOAMActionUcDrop */
  16739                  { 0, 0, 0, LBM_UC_DROPf, 0, 0}, 
  16740                   /* bcmOAMActionUcCopyToCpu */
  16741                  { 0, 0, 0, LBM_UC_COPYTO_CPUf, 0, 0},
  16742                   /* bcmOAMActionUcFwdAsData */
  16743                  { 0, 0, 0, 0, 0, 0 },
  16744                   /* bcmOAMActionUcFwd */
  16745                  { 0, 0, 0, LBM_ACTIONf, 0, 0},
  16746                  /* bcmOAMActionMcDrop */
  16747                  { 0, 0, 0, LBM_MC_DROPf, 0, 0},
  16748                     /* bcmOAMActionMcCopyToCpu */
  16749                  { 0, 0, 0, LBM_MC_COPYTO_CPUf, 0, 0},
  16750                     /* bcmOAMActionMcFwdAsData */
  16751                  { 0, 0, 0, 0, 0, 0},
  16752                    /* bcmOAMActionMcFwd*/
  16753                  { 0, 0, 0, LBM_MC_FWDf, 0, 0},
  16754                    /* bcmOAMActionLowMdlDrop */
  16755                  { 0, LOW_MDL_CCM_FWD_ACTIONf, LOW_MDL_LB_LT_DROPf, 
  16756                       LOW_MDL_LB_LT_DROPf, LOW_MDL_LB_LT_DROPf, 
  16757                       LOW_MDL_LB_LT_DROPf },
  16758                   /*  bcmOAMActionLowMdlCopyToCpu */
  16759                  { 0, LOW_MDL_CCM_COPYTO_CPUf, LOW_MDL_LB_LT_COPYTO_CPUf, 
  16760                       LOW_MDL_LB_LT_COPYTO_CPUf, 
  16761                       LOW_MDL_LB_LT_COPYTO_CPUf, LOW_MDL_LB_LT_COPYTO_CPUf}, 
  16762                   /* bcmOAMActionLowMdlFwdAsData */
  16763                  { 0, LOW_MDL_CCM_FWD_ACTIONf, LOW_MDL_LB_LT_DROPf, 
  16764                       LOW_MDL_LB_LT_DROPf, 
  16765                       LOW_MDL_LB_LT_DROPf, LOW_MDL_LB_LT_DROPf}, 
  16766                    /* bcmOAMActionLowMdlFwd*/
  16767                  { 0, 0, LOW_MDL_LB_LT_FWDf, LOW_MDL_LB_LT_FWDf, 0, 0},
  16768                     /* bcmOAMActionMyStationMissCopyToCpu */
  16769                  { 0, 0, LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf, 
  16770                    LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf,
  16771                    LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf,
  16772                    LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf},
  16773                     /* bcmOAMActionMyStationMissDrop */
  16774                  { 0, 0, LB_LT_UC_MY_STATION_MISS_DROPf, 
  16775                    LB_LT_UC_MY_STATION_MISS_DROPf,
  16776                    LB_LT_UC_MY_STATION_MISS_DROPf, 
  16777                    LB_LT_UC_MY_STATION_MISS_DROPf},
  16778                     /* bcmOAMActionMyStationMissFwdAsData */
  16779                  { 0, 0, 0, 0, 0, 0},
  16780                     /* bcmOAMActionMyStationMissFwd */
  16781                  { 0, 0, LB_LT_UC_MY_STATION_MISS_FWDf, 
  16782                    LB_LT_UC_MY_STATION_MISS_FWDf,
  16783                    LB_LT_UC_MY_STATION_MISS_FWDf,
  16784                    LB_LT_UC_MY_STATION_MISS_FWDf},
  16785                    /* bcmOAMActionProcessInHw */
  16786                  { 0, CCM_PROCESS_IN_HWf, 0, 0, 0, 0}, 
  16787                    /* bcmOAMActionLowMdlCcmFwdAsRegularCcm */ 
  16788                  { 0, LOW_MDL_CCM_FWD_ACTIONf, 0, 0, 0, 0}, 
  16789                  { 0, 0, 0, 0, 0, 0} 
  16790     };
  16791 
  16792     soc_field_t non_cfm_field[bcmOAMActionCount+1][2]= {
  16793                    /* bcmOAMActionCountEnable */ 
  16794                  { 0, 0 },
  16795                    /* bcmOAMActionMeterEnable */ 
  16796                  { 0, 0 },
  16797                    /* bcmOAMActionDrop */
  16798                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf,
  16799                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf },
  16800                    /* bcmOAMActionCopyToCpu */
  16801                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_COPYTO_CPUf,
  16802                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_COPYTO_CPUf },
  16803                    /* bcmOAMActionFwdAsData */
  16804                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf,
  16805                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf },
  16806                    /* bcmOAMActionFwd */
  16807                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf,
  16808                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf },
  16809                    /* bcmOAMActionUcDrop */
  16810                  { 0, 0 },
  16811                    /* bcmOAMActionUcCopyToCpu */
  16812                  { 0, 0 },
  16813                    /* bcmOAMActionUcFwdAsData */
  16814                  { 0, 0 },
  16815                    /* bcmOAMActionUcFwd */
  16816                  { 0, 0 },
  16817                    /* bcmOAMActionMcDrop */
  16818                  { OTHER_OPCODE_GROUP_1_MC_ACTIONf,
  16819                    OTHER_OPCODE_GROUP_2_MC_ACTIONf },
  16820                    /* bcmOAMActionMcCopyToCpu */
  16821                  { OTHER_OPCODE_GROUP_1_MC_COPYTO_CPUf,
  16822                    OTHER_OPCODE_GROUP_2_MC_COPYTO_CPUf },
  16823                    /* bcmOAMActionMcFwdAsData */
  16824                  { OTHER_OPCODE_GROUP_1_MC_ACTIONf,
  16825                    OTHER_OPCODE_GROUP_2_MC_ACTIONf },
  16826                    /* bcmOAMActionMcFwd*/
  16827                  { OTHER_OPCODE_GROUP_1_MC_ACTIONf,
  16828                    OTHER_OPCODE_GROUP_2_MC_ACTIONf },
  16829                    /* bcmOAMActionLowMdlDrop */
  16830                  { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf,
  16831                    OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf},
  16832                    /* bcmOAMActionLowMdlCopyToCpu */
  16833                  { OTHER_OPCODE_GROUP_1_LOW_MDL_COPYTO_CPUf,
  16834                    OTHER_OPCODE_GROUP_2_LOW_MDL_COPYTO_CPUf },
  16835                    /* bcmOAMActionLowMdlFwdAsData */
  16836                  { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf,
  16837                    OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf },
  16838                    /* bcmOAMActionLowMdlFwd*/
  16839                  { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf,
  16840                    OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf},
  16841                    /* bcmOAMActionMyStationMissCopyToCpu */
  16842                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_COPYTO_CPUf,
  16843                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_COPYTO_CPUf },
  16844                    /* bcmOAMActionMyStationMissDrop */
  16845                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf,
  16846                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf },
  16847                    /* bcmOAMActionMyStationMissFwdAsData */
  16848                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf,
  16849                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf },
  16850                    /* bcmOAMActionMyStationMissFwd */
  16851                  { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf,
  16852                    OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf},
  16853                    /* bcmOAMActionProcessInHw */
  16854                  { 0, 0 },
  16855                    /* bcmOAMActionLowMdlCcmFwdAsRegularCcm */ 
  16856                  { 0, 0 },
  16857                  { 0, 0 }
  16858     };
  16859 
  16860     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16861 
  16862     SHR_BITTEST_RANGE(oc->opcode_grp_1_bmp, 0, 
  16863                           _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST, opcode_bmp_1);
  16864     SHR_BITTEST_RANGE(oc->opcode_grp_2_bmp, 0,
  16865                           _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST, opcode_bmp_2);
  16866     if (oam_opcode < _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST) {
  16867         if (cfm_field[field_index][oam_opcode] != 0) {
  16868             soc_mem_field32_set(unit, mem, profile, 
  16869                    cfm_field[field_index][oam_opcode], value);
  16870         }
  16871     } else {
  16872         if ((opcode_bmp_1 == 0) && (opcode_bmp_2 == 0)) {
  16873            if (SHR_BITGET(oc->opcode_grp_bmp, oam_opcode)) {
  16874                SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode);
  16875                SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16876                opcode_bmp_1 = 1;
  16877                grp_1_modified = 1;
  16878            }
  16879         }
  16880         /* Changing the action for same opcode */
  16881         if (SHR_BITGET(oc->opcode_grp_1_bmp, oam_opcode)) {
  16882            if (non_cfm_field[field_index][0] != 0) {
  16883                soc_mem_field32_set(unit, mem, profile, 
  16884                        non_cfm_field[field_index][0], value);
  16885            } 
  16886         } else if (SHR_BITGET(oc->opcode_grp_2_bmp, oam_opcode)) {
  16887            if (non_cfm_field[field_index][1] != 0) {
  16888                soc_mem_field32_set(unit, mem, profile, 
  16889                                 non_cfm_field[field_index][1], value);
  16890            }
  16891         } else if (SHR_BITGET(oc->opcode_grp_bmp, oam_opcode)) {
  16892             if (value == soc_mem_field32_get(unit, mem, profile, 
  16893                        non_cfm_field[field_index][0])) {
  16894                /* Add this opcode to group 1 */
  16895                 grp_1_modified = 1;
  16896                 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode);
  16897                 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16898                 if (non_cfm_field[field_index][0] != 0) {
  16899                     soc_mem_field32_set(unit, mem, profile, 
  16900                                 non_cfm_field[field_index][0], value);
  16901                 }
  16902             } else if (value == soc_mem_field32_get(unit, mem, profile, 
  16903                        non_cfm_field[field_index][1])) {
  16904                /* Add this opcode to group 2 */
  16905                 grp_2_modified = 1;
  16906                 SHR_BITSET(oc->opcode_grp_2_bmp, oam_opcode);
  16907                 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16908                 if (non_cfm_field[field_index][1] != 0) {
  16909                     soc_mem_field32_set(unit, mem, profile, 
  16910                                 non_cfm_field[field_index][1], value);
  16911                 }
  16912             } else if (opcode_bmp_1 == 0) { 
  16913                 grp_1_modified = 1;
  16914                 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode);
  16915                 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16916                 if (non_cfm_field[field_index][0] != 0) {
  16917                     soc_mem_field32_set(unit, mem, profile, 
  16918                                 non_cfm_field[field_index][0], value);
  16919                 }
  16920             } else if (opcode_bmp_2 == 0) { 
  16921                 grp_2_modified = 1;
  16922                 SHR_BITSET(oc->opcode_grp_2_bmp, oam_opcode);
  16923                 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16924                 if (non_cfm_field[field_index][1] != 0) {
  16925                     soc_mem_field32_set(unit, mem, profile, 
  16926                                 non_cfm_field[field_index][1], value);
  16927                 }
  16928             } else {
  16929                 /* Add the opcode to group 1 by default */ 
  16930                 grp_1_modified = 1;
  16931                 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode);
  16932                 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode);
  16933                 if (non_cfm_field[field_index][0] != 0) {
  16934                     soc_mem_field32_set(unit, mem, profile, 
  16935                                 non_cfm_field[field_index][0], value);
  16936                 }
  16937             }
  16938         } else {
  16939             return (BCM_E_PARAM);
  16940         }
  16941     }
  16942     if (mem == OAM_OPCODE_CONTROL_PROFILEm) {
  16943         mem = INGRESS_OAM_OPCODE_GROUPm;
  16944     } else {
  16945         mem = EGR_OAM_OPCODE_GROUPm;
  16946     }
  16947     if (grp_1_modified) {
  16948         soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUP_VALIDf, 1);
  16949         soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUPf, 0);
  16950         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 
  16951                                           MEM_BLOCK_ANY, oam_opcode, &entry));
  16952 
  16953     } else if(grp_2_modified) {
  16954         soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUP_VALIDf, 1);
  16955         soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUPf, 1);
  16956         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 
  16957                                           MEM_BLOCK_ANY, oam_opcode, &entry));
  16958     }
  16959     return (BCM_E_NONE);
  16960 }
  16961 
  16962 /*
  16963  * Function:
  16964  *     _bcm_kt2_oam_resolve_dglp
  16965  * Purpose:
  16966  *   Add an dglp profile entry 
  16967  * Parameters:
  16968  *     unit        - (IN) BCM device number
  16969  *     mem         - (IN) dglp profile memory - ing/egr
  16970  *     dglp        - (IN) DGLP value
  16971  *     profile     - (OUT) Pointer to the dglp profile table index.
  16972  *     olp_enable  - (OUT) Pointer to field indicating whether olp is enabled on
  16973  *                         the port. 
  16974  * Returns:
  16975  *      BCM_E_XXX
  16976  */
  16977 int
  16978 _bcm_kt2_oam_resolve_dglp(int unit, soc_mem_t mem, uint32 dglp, 
  16979                           uint32 *profile_index, int *olp_enable) 
  16980 { 
  16981     int rv = BCM_E_NONE;
  16982     egr_olp_dgpp_config_entry_t *buf;
  16983     egr_olp_dgpp_config_entry_t *entry;
  16984     egr_oam_dglp_profile_entry_t egr_dglp_profile_entry;
  16985     ing_oam_dglp_profile_entry_t ing_dglp_profile_entry;
  16986     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  16987     int         index_max = 0;
  16988     int         index = 0;
  16989     uint32      configured_dglp = 0;
  16990     void        *entries[1];
  16991     void        *profile_entry;
  16992     soc_mem_t   profile_mem;
  16993     soc_profile_mem_t profile_ptr;
  16994     int         entry_mem_size = 0;
  16995 
  16996     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  16997 
  16998     if (mem == EGR_OAM_OPCODE_CONTROL_PROFILEm) {
  16999         profile_entry = (void *)&egr_dglp_profile_entry;
  17000         profile_mem = EGR_OAM_DGLP_PROFILEm;
  17001         profile_ptr = oc->egr_oam_dglp_profile;
  17002     } else {
  17003         profile_entry = (void *)&ing_dglp_profile_entry;
  17004         profile_mem = ING_OAM_DGLP_PROFILEm;
  17005         profile_ptr = oc->ing_oam_dglp_profile;
  17006     }
  17007     /* Check whether this DGLP is already configured as  OLP port */ 
  17008     entry_mem_size = sizeof(egr_olp_dgpp_config_entry_t);
  17009     /* Allocate buffer to store the DMAed table entries. */
  17010     index_max = soc_mem_index_max(unit, EGR_OLP_DGPP_CONFIGm);
  17011     buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1),
  17012                               "OLP dglp config table entry buffer");
  17013     if (NULL == buf) {
  17014         return (BCM_E_MEMORY);
  17015     }
  17016     /* Initialize the entry buffer. */
  17017     sal_memset(buf, 0, sizeof(entry_mem_size) * (index_max + 1));
  17018 
  17019     /* Read the table entries into the buffer. */
  17020     rv = soc_mem_read_range(unit, EGR_OLP_DGPP_CONFIGm, MEM_BLOCK_ALL,
  17021                             0, index_max, buf);
  17022     if (BCM_FAILURE(rv)) {
  17023         if (buf) {
  17024             soc_cm_sfree(unit, buf);
  17025         }
  17026         return rv;
  17027     }
  17028 
  17029     /* Iterate over the table entries. */
  17030     for (index = 0; index <= index_max; index++) {
  17031         entry = soc_mem_table_idx_to_pointer
  17032                     (unit, EGR_OLP_DGPP_CONFIGm, egr_olp_dgpp_config_entry_t *,
  17033                      buf, index);
  17034 
  17035         soc_mem_field_get(unit, EGR_OLP_DGPP_CONFIGm, 
  17036                           (uint32 *)entry, DGLPf, &configured_dglp);
  17037         if (dglp == configured_dglp) {
  17038             *olp_enable = 1;
  17039             break;
  17040         }
  17041     }
  17042     if (buf) {
  17043         soc_cm_sfree(unit, buf);
  17044     }
  17045     /* Add entry to dglp profile table.  */
  17046     soc_mem_field32_set(unit, profile_mem, profile_entry, DGLPf, dglp);
  17047     entries[0] = profile_entry;
  17048 
  17049     rv = soc_profile_mem_add(unit, &profile_ptr,
  17050                              (void *)entries, 1, profile_index);
  17051     if (BCM_FAILURE(rv)) {
  17052         LOG_ERROR(BSL_LS_BCM_OAM,
  17053                   (BSL_META_U(unit,
  17054                               "OAM DGLP profile table is full - %s.\n"),
  17055                    bcm_errmsg(rv)));
  17056         return rv;
  17057     }
  17058     return (BCM_E_NONE);
  17059 } 
  17060 
  17061 /*
  17062  * Function:
  17063  *     _bcm_kt2_ma_index_entry_modify
  17064  * Purpose:
  17065  *    Set dglp profile pointer index in the MA index table entry 
  17066  * Parameters:
  17067  *     unit        - (IN) BCM device number
  17068  *     index       - (IN) MA index table index
  17069  *     mem         - (IN) MA index memory - ing/egr
  17070  *     profile_index- (IN)DGLP profile index
  17071  *     olp_enable  - (IN) indicates whether olp is enabled for this entry
  17072  *     dglp_prt    - (OUT) Pointer to dglp1/2 profile.  
  17073  * Returns:
  17074  *      BCM_E_XXX
  17075  */
  17076 int 
  17077 _bcm_kt2_ma_index_entry_modify(int unit, int index, soc_mem_t mem, 
  17078                                int profile_index, int olp_enable, int *dglp_ptr)
  17079 {
  17080     int  rv = BCM_E_NONE;
  17081     ma_index_entry_t     ma_idx_entry;     /* MA_INDEX table entry buffer.    */
  17082     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer.*/
  17083     void *entry;
  17084 
  17085     if (mem == EGR_MA_INDEXm) {
  17086         entry = (void *)&egr_ma_idx_entry;
  17087     } else {
  17088         entry = (void *)&ma_idx_entry;
  17089     }
  17090     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry);
  17091     if (BCM_FAILURE(rv)) {
  17092         LOG_ERROR(BSL_LS_BCM_OAM,
  17093                   (BSL_META_U(unit,
  17094                               "OAM Error: MA index table entry  read failed  "
  17095                               "%s.\n"), bcm_errmsg(rv)));
  17096         return (rv);
  17097     }
  17098     if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  17099                                  DGLP1_PROFILE_PTRf)){
  17100         
  17101          soc_mem_field32_set(unit, mem, entry, 
  17102                              DGLP1_PROFILE_PTRf, profile_index);
  17103          if (olp_enable) {
  17104              soc_mem_field32_set(unit, mem, entry, DGLP1_OLP_HDR_ADDf, 1);
  17105          }
  17106          *dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR;
  17107     } else if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  17108                                  DGLP2_PROFILE_PTRf)){
  17109         
  17110          soc_mem_field32_set(unit, mem, entry, 
  17111                              DGLP2_PROFILE_PTRf, profile_index);
  17112          if (olp_enable) {
  17113              soc_mem_field32_set(unit, mem, entry, DGLP2_OLP_HDR_ADDf, 1);
  17114          }
  17115          *dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR;
  17116     }
  17117     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, entry));
  17118     return (BCM_E_NONE);
  17119 }
  17120 
  17121 /*
  17122  * Function:
  17123  *     _kt2_oam_counter_control_set
  17124  * Purpose:
  17125  *    Enable/disable LM counter for a particular opcode 
  17126  * Parameters:
  17127  *     unit        - (IN) BCM device number
  17128  *     opcode_i    - (IN) OAM opcode for which counter needs 
  17129  *                        to be enabled/disabled 
  17130  *     value       - (IN) Counter enable/disable
  17131  * Returns:
  17132  *      BCM_E_XXX
  17133  */
  17134 int
  17135 _kt2_oam_counter_control_set(int unit, int opcode_i, int value)
  17136 {
  17137     int rv = BCM_E_NONE;
  17138     egr_lm_counter_control_entry_t  egr_ctr;
  17139     lm_counter_control_entry_t      ing_ctr;
  17140 
  17141     rv = soc_mem_read(unit, LM_COUNTER_CONTROLm, MEM_BLOCK_ANY,
  17142                       opcode_i, &ing_ctr);
  17143     if (BCM_FAILURE(rv)) {
  17144         LOG_ERROR(BSL_LS_BCM_OAM,
  17145                   (BSL_META_U(unit,
  17146                               "OAM Error: Counter control table entry  read "
  17147                               "failed  %s.\n"), bcm_errmsg(rv)));
  17148         return (rv);
  17149     }
  17150     soc_LM_COUNTER_CONTROLm_field32_set(unit, &ing_ctr, COUNT_ENABLEf, value);
  17151     rv = soc_mem_write(unit, LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 
  17152                        opcode_i, &ing_ctr);
  17153     if (BCM_FAILURE(rv)) {
  17154         LOG_ERROR(BSL_LS_BCM_OAM,
  17155                   (BSL_META_U(unit,
  17156                               "OAM Error: Counter control table entry  wtite "
  17157                               "failed  %s.\n"), bcm_errmsg(rv)));
  17158         return (rv);
  17159     }
  17160     rv = soc_mem_read(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY,
  17161                       opcode_i, &egr_ctr);
  17162     if (BCM_FAILURE(rv)) {
  17163         LOG_ERROR(BSL_LS_BCM_OAM,
  17164                   (BSL_META_U(unit,
  17165                               "OAM Error: Counter control table entry  read "
  17166                               "failed  %s.\n"), bcm_errmsg(rv)));
  17167         return (rv);
  17168     }
  17169     soc_EGR_LM_COUNTER_CONTROLm_field32_set(unit, &egr_ctr, 
  17170                                             COUNT_ENABLEf, value);
  17171     rv = soc_mem_write(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 
  17172                        opcode_i, &ing_ctr);
  17173     if (BCM_FAILURE(rv)) {
  17174         LOG_ERROR(BSL_LS_BCM_OAM,
  17175                   (BSL_META_U(unit,
  17176                               "OAM Error: Counter control table entry  wtite "
  17177                               "failed  %s.\n"), bcm_errmsg(rv)));
  17178         return (rv);
  17179     }
  17180     return rv;
  17181 }
  17182 
  17183 /*
  17184  * Function:
  17185  *     _bcm_kt2_oam_convert_action_to_opcode_entry
  17186  * Purpose:
  17187  *    Convert endpoint action to opcode profile entry action 
  17188  * Parameters:
  17189  *     unit        - (IN) BCM device number
  17190  *     action      - (IN) Pointer to endpoint action
  17191  *     ep_id       - (IN) Endpoint id
  17192  *     profile     - (IN) Opcode profile table entry
  17193  * Returns:
  17194  *      BCM_E_XXX
  17195  */
  17196 int 
  17197 _bcm_kt2_oam_convert_action_to_opcode_entry(int unit,
  17198                                             bcm_oam_endpoint_action_t *action, 
  17199                                             bcm_oam_endpoint_t ep_id,
  17200                                             void *profile,
  17201                                             uint8  *opcode_profile_changed) 
  17202 {
  17203     int rv = BCM_E_NONE;
  17204     int action_i = 0;
  17205     int opcode_i = 0;
  17206     int break_the_loop = 0;
  17207     int profile_index = _BCM_OAM_INVALID_INDEX;
  17208     int olp_enable = 0;
  17209     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  17210     _bcm_oam_hash_data_t *h_data_p;  /* Pointer to endpoint hash data.    */
  17211     soc_mem_t     mem = OAM_OPCODE_CONTROL_PROFILEm;
  17212     soc_mem_t     ma_index_mem = MA_INDEXm;
  17213     int           dglp_ptr = 0;
  17214     int           skip_ma_index_modify = 0;
  17215     int           value = 0;        
  17216     bcm_module_t  module_id;
  17217     bcm_port_t    port_id;
  17218     bcm_trunk_t   trunk_id = BCM_TRUNK_INVALID;
  17219     int           local_id;
  17220     uint32        dglp = 0;
  17221     int           reset = 0;
  17222 
  17223     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  17224 
  17225     h_data_p = &oc->oam_hash_data[ep_id];
  17226     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  17227         ma_index_mem = EGR_MA_INDEXm;
  17228         mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
  17229     }
  17230 
  17231     reset = (action->flags & BCM_OAM_ENDPOINT_ACTION_DISABLE) ? 1 : 0;
  17232 
  17233     for (action_i = 0; action_i < bcmOAMActionCount; action_i++) {
  17234         if (BCM_OAM_ACTION_GET(*action, action_i)) {
  17235             for (opcode_i = 0; opcode_i <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST; 
  17236                                                                 opcode_i++) {
  17237                 if (BCM_OAM_OPCODE_GET(*action, opcode_i)) {
  17238                     switch (action_i) {
  17239                         case bcmOAMActionCountEnable:  
  17240                             rv = _kt2_oam_counter_control_set(unit, opcode_i,
  17241                                                               !reset);
  17242                             if (BCM_FAILURE(rv)) {
  17243                                LOG_ERROR(BSL_LS_BCM_OAM,
  17244                                          (BSL_META_U(unit,
  17245                                                      "OAM Error:Counter control "
  17246                                                      "set - %s.\n"), bcm_errmsg(rv)));
  17247                                 return (rv);
  17248                             }
  17249                             break;
  17250 
  17251                         case bcmOAMActionDrop:
  17252                         case bcmOAMActionUcDrop:             
  17253                         case bcmOAMActionMcDrop:                
  17254                         case bcmOAMActionLowMdlDrop:        
  17255                         case bcmOAMActionMyStationMissDrop:
  17256                             if ((action_i == bcmOAMActionLowMdlDrop) &&
  17257                                 (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM)) {
  17258                                 value = reset ? 0 : _BCM_OAM_LOW_MDL_DROP_PACKET;
  17259                             } else {
  17260                                 value = !reset;
  17261                             }
  17262                             rv = _kt2_oam_opcode_control_field_set(unit, 
  17263                                              action_i, mem, opcode_i, 
  17264                                              value, profile);
  17265                             *opcode_profile_changed = 1;
  17266                             break;
  17267 
  17268                         case bcmOAMActionCopyToCpu:             
  17269                         case bcmOAMActionUcCopyToCpu:       
  17270                         case bcmOAMActionMcCopyToCpu:          
  17271                         case bcmOAMActionLowMdlCopyToCpu:  
  17272                         case bcmOAMActionMyStationMissCopyToCpu:
  17273                             rv = _kt2_oam_opcode_control_field_set(unit, 
  17274                                            action_i, mem, opcode_i,
  17275                                             !reset, profile);
  17276                             *opcode_profile_changed = 1;
  17277                             break;
  17278 
  17279                         case bcmOAMActionFwdAsData:             
  17280                             if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 
  17281                                 /* Need not check reset in this case
  17282                                  * since this is default case
  17283                                  */
  17284                                 soc_mem_field32_set(unit, mem, profile, 
  17285                                                     LOW_MDL_CCM_FWD_ACTIONf, 0);
  17286                                break_the_loop = 1;
  17287                             }
  17288                             *opcode_profile_changed = 1;
  17289                             break;
  17290 
  17291                         case bcmOAMActionFwd:      
  17292                         case bcmOAMActionUcFwd:       
  17293                         case bcmOAMActionMcFwd:   
  17294                         case bcmOAMActionLowMdlFwd:
  17295                         case bcmOAMActionMyStationMissFwd:
  17296                             /* forward packets to DGLP1 or DGLP2 */
  17297                             if (!skip_ma_index_modify) {
  17298                                 SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit,
  17299                                              action->destination, &module_id, 
  17300                                              &port_id, &trunk_id, &local_id));
  17301                                 if (BCM_GPORT_IS_TRUNK(action->destination) && 
  17302                                              (trunk_id != BCM_TRUNK_INVALID)) {
  17303                                     /* Set LAG ID indicator bit */
  17304                                     dglp |= (1 << DGLP_LAG_ID_INDICATOR_SHIFT_BITS); 
  17305                                 }
  17306                                 dglp |= ((module_id << DGLP_MODULE_ID_SHIFT_BITS) + port_id); 
  17307 
  17308                                 if (dglp == h_data_p->dglp1) {
  17309                                     skip_ma_index_modify = 1;
  17310                                     dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR;
  17311                                 } else if (dglp == h_data_p->dglp2) {
  17312                                     skip_ma_index_modify = 1;
  17313                                     dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR;
  17314                                 /* if both dglp1 and dglp2 are already set, 
  17315                                    return error */
  17316                                 } else if ((h_data_p->dglp1 > 0) && 
  17317                                            (h_data_p->dglp2 > 0)) {
  17318                                     LOG_ERROR(BSL_LS_BCM_OAM,
  17319                                               (BSL_META_U(unit,
  17320                                                           "OAM Error: Invalid action"
  17321                                                           "destination - %s.\n"), bcm_errmsg(rv)));
  17322                                     return BCM_E_PARAM;
  17323                                 }
  17324                                 if (!skip_ma_index_modify) {
  17325                                     rv = _bcm_kt2_oam_resolve_dglp(unit, mem, 
  17326                                                  dglp, (uint32 *)&profile_index,
  17327                                                  &olp_enable); 
  17328                                     if (BCM_FAILURE(rv)) {
  17329                                        LOG_ERROR(BSL_LS_BCM_OAM,
  17330                                                  (BSL_META_U(unit,
  17331                                                              "OAM Error: Gport  "
  17332                                                              "to dglp-%s\n"), bcm_errmsg(rv)));
  17333                                        return (rv);
  17334                                     }
  17335                                     if (profile_index != _BCM_OAM_INVALID_INDEX) {
  17336                                         /* modify MA_INDEX table entry */       
  17337                                         rv = _bcm_kt2_ma_index_entry_modify(unit,
  17338                                                    h_data_p->local_rx_index, 
  17339                                                    ma_index_mem, profile_index, 
  17340                                                    olp_enable, &dglp_ptr);
  17341                                         if (BCM_FAILURE(rv)) {
  17342                                             return rv;
  17343                                         }
  17344                                         if (dglp_ptr == 
  17345                                                    _BCM_OAM_DGLP1_PROFILE_PTR) {
  17346                                             h_data_p->dglp1 = dglp;
  17347                                             h_data_p->dglp1_profile_index = 
  17348                                                                   profile_index;
  17349                                         } else {
  17350                                             h_data_p->dglp2 = dglp;
  17351                                             h_data_p->dglp2_profile_index = 
  17352                                                                   profile_index;
  17353                                         }
  17354                                         skip_ma_index_modify = 1; 
  17355                                     }
  17356                                 }
  17357                             }
  17358                             if (dglp_ptr == 0) {
  17359                                 break;
  17360                             }
  17361                             /* Opcode control value is to bet set to 2 for 
  17362                                DGLP1 and 3 for DGLP2 */
  17363                             if (((opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) && 
  17364                                  (action_i != bcmOAMActionMcFwd))  || 
  17365                                (opcode_i >= _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST)) {
  17366                                 value = dglp_ptr + 1;
  17367                             } else {
  17368                                 value = dglp_ptr;
  17369                             }
  17370                             _kt2_oam_opcode_control_field_set(unit, action_i, 
  17371                                            mem, opcode_i, value, profile);
  17372                             *opcode_profile_changed = 1;
  17373                             break;
  17374 
  17375                         case bcmOAMActionUcFwdAsData:      
  17376                         case bcmOAMActionMcFwdAsData:         
  17377                         case bcmOAMActionLowMdlFwdAsData:  
  17378                         case bcmOAMActionMyStationMissFwdAsData:
  17379                             /* Need not check reset in this case
  17380                              * since this is default case
  17381                              */
  17382                             rv = _kt2_oam_opcode_control_field_set(unit, 
  17383                                       action_i, mem, opcode_i, 
  17384                                       _BCM_OAM_FWD_AS_DATA, profile);
  17385                             *opcode_profile_changed = 1;
  17386                             break;
  17387 
  17388                         case bcmOAMActionProcessInHw:           
  17389                             if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 
  17390                                 soc_mem_field32_set(unit, mem, profile, 
  17391                                                     CCM_PROCESS_IN_HWf, !reset);
  17392                             } else if (opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) {
  17393                                 soc_mem_field32_set(unit, mem, profile, 
  17394                                        LBM_ACTIONf, !reset);
  17395                             }
  17396                             break_the_loop = 1;
  17397                             /* TBD - When CCM processing is done in HW, MA_PTR
  17398                                value in MA_INDEX table should be less than 2k. 
  17399                                If not, we should return error */
  17400                             *opcode_profile_changed = 1;
  17401                             break;
  17402 
  17403                         case bcmOAMActionLowMdlCcmFwdAsRegularCcm:
  17404                             if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 
  17405                                 soc_mem_field32_set(unit, mem, profile, 
  17406                                                    LOW_MDL_CCM_FWD_ACTIONf, !reset);
  17407                                break_the_loop = 1;
  17408                             }
  17409                             *opcode_profile_changed = 1;
  17410                             break;
  17411 
  17412                         default:
  17413                             break;
  17414                     }
  17415                 }
  17416                 if (break_the_loop) { 
  17417                     dglp_ptr = 0;
  17418                     break_the_loop = 0;
  17419                     olp_enable = 0;
  17420                     profile_index = _BCM_OAM_INVALID_INDEX;
  17421                     break;   
  17422                 }
  17423             }
  17424         }
  17425     }
  17426     return rv;
  17427 }
  17428 
  17429 /*
  17430  * Function:
  17431  *     _bcm_kt2_oam_flex_drop_get
  17432  * Purpose:
  17433  *     Query the value of the device-wide OAM control.
  17434  * Parameters:
  17435  *     unit        - (IN) BCM device number
  17436  *     type        - (IN) OAM control type
  17437  *     arg         - (OUT) A pointer to value of the control 
  17438  * Returns:
  17439  *      BCM_E_XXX
  17440  */
  17441 int _bcm_kt2_oam_flex_drop_get(int unit, bcm_oam_control_type_t type,
  17442                                      uint64  *arg) 
  17443 {
  17444    uint32 rval_32;
  17445    soc_reg_t  reg = 0;
  17446    uint32     is_64bit_reg = 0; 
  17447    int        rv = BCM_E_NONE;
  17448 
  17449    switch(type) {
  17450        case bcmOamControlFlexibleDropPort:
  17451            reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 
  17452            break;
  17453 
  17454        case bcmOamControlFlexibleDropCVlan:
  17455            reg = OAM_C_INTERFACE_DROP_CONTROLr; 
  17456            break;
  17457 
  17458        case bcmOamControlFlexibleDropSVlan:
  17459            reg = OAM_S_INTERFACE_DROP_CONTROLr; 
  17460            break;
  17461 
  17462        case bcmOamControlFlexibleDropCPlusSVlan:
  17463            reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 
  17464            break;
  17465 
  17466        case bcmOamControlFlexibleDropVP:
  17467            reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 
  17468            break;
  17469 
  17470        case bcmOamControlFlexibleDropEgressPort:
  17471            reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 
  17472            is_64bit_reg = 1;
  17473            break;
  17474 
  17475        case bcmOamControlFlexibleDropEgressCVlan:
  17476            reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 
  17477            is_64bit_reg = 1;
  17478            break;
  17479 
  17480        case bcmOamControlFlexibleDropEgressSVlan:
  17481            reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 
  17482            is_64bit_reg = 1;
  17483            break;
  17484 
  17485        case bcmOamControlFlexibleDropEgressCPlusSVlan:
  17486            reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 
  17487            is_64bit_reg = 1;
  17488            break;
  17489 
  17490        case bcmOamControlFlexibleDropEgressVP:
  17491            reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 
  17492            is_64bit_reg = 1;
  17493            break;
  17494 
  17495        case bcmOamControlFlexibleDropPasssiveSap:
  17496            reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  17497            break;
  17498 
  17499        case bcmOamControlFlexibleDropEgressPasssiveSap:
  17500            reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  17501            break;
  17502 
  17503        default:
  17504            return (BCM_E_UNAVAIL); 
  17505            break;
  17506     }
  17507     if (is_64bit_reg == 0) {
  17508         rv = soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval_32);
  17509         if(BCM_SUCCESS(rv)) {
  17510            COMPILER_64_SET(*arg, 0, rval_32);
  17511         }
  17512     } else {
  17513         rv = soc_reg64_get(unit, reg, REG_PORT_ANY, 0, arg);
  17514     }
  17515     return rv;
  17516 }
  17517 
  17518 /*
  17519  * Function:
  17520  *     _bcm_kt2_oam_flex_drop_get
  17521  * Purpose:
  17522  *     Query the value of the device-wide OAM control.
  17523  * Parameters:
  17524  *     unit        - (IN) BCM device number
  17525  *     type        - (IN) OAM control type
  17526  *     arg         - (IN) value to be set for the control 
  17527  * Returns:
  17528  *      BCM_E_XXX
  17529  */
  17530 int _bcm_kt2_oam_flex_drop_set(int unit, bcm_oam_control_type_t type,
  17531                                uint64  arg) 
  17532 {
  17533    uint32 rval_32;
  17534    soc_reg_t  reg = 0;
  17535    uint32     is_64bit_reg = 0; 
  17536    int        rv = BCM_E_NONE;
  17537 
  17538    switch(type) {
  17539        case bcmOamControlFlexibleDropPort:
  17540            reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 
  17541            break;
  17542 
  17543        case bcmOamControlFlexibleDropCVlan:
  17544            reg = OAM_C_INTERFACE_DROP_CONTROLr; 
  17545            break;
  17546 
  17547        case bcmOamControlFlexibleDropSVlan:
  17548            reg = OAM_S_INTERFACE_DROP_CONTROLr; 
  17549            break;
  17550 
  17551        case bcmOamControlFlexibleDropCPlusSVlan:
  17552            reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 
  17553            break;
  17554 
  17555        case bcmOamControlFlexibleDropVP:
  17556            reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 
  17557            break;
  17558 
  17559        case bcmOamControlFlexibleDropEgressPort:
  17560            reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 
  17561            is_64bit_reg = 1;
  17562            break;
  17563 
  17564        case bcmOamControlFlexibleDropEgressCVlan:
  17565            reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 
  17566            is_64bit_reg = 1;
  17567            break;
  17568 
  17569        case bcmOamControlFlexibleDropEgressSVlan:
  17570            reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 
  17571            is_64bit_reg = 1;
  17572            break;
  17573 
  17574        case bcmOamControlFlexibleDropEgressCPlusSVlan:
  17575            reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 
  17576            is_64bit_reg = 1;
  17577            break;
  17578 
  17579        case bcmOamControlFlexibleDropEgressVP:
  17580            reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 
  17581            is_64bit_reg = 1;
  17582            break;
  17583 
  17584        case bcmOamControlFlexibleDropPasssiveSap:
  17585            reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  17586            break;
  17587 
  17588        case bcmOamControlFlexibleDropEgressPasssiveSap:
  17589            reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  17590            break;
  17591 
  17592        default:
  17593            return (BCM_E_UNAVAIL); 
  17594            break;
  17595     }
  17596     if (is_64bit_reg == 0) {
  17597         COMPILER_64_TO_32_LO(rval_32, arg); 
  17598         rv = soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval_32);
  17599     } else {
  17600         rv = soc_reg64_set(unit, reg, REG_PORT_ANY, 0, arg);
  17601     }
  17602     return rv;
  17603 }
  17604 /*
  17605  * Function:
  17606  *     bcm_kt2_oam_control_get
  17607  * Purpose:
  17608  *     Query the value of the device-wide OAM control.
  17609  * Parameters:
  17610  *     unit        - (IN) BCM device number
  17611  *     type        - (IN) OAM control type
  17612  *     arg         - (OUT) A pointer to value of the control 
  17613  * Returns:
  17614  *      BCM_E_XXX
  17615  */
  17616 int bcm_kt2_oam_control_get(int unit, bcm_oam_control_type_t type,
  17617                                      uint64  *arg) 
  17618 {
  17619     int        rv = BCM_E_NONE;
  17620 
  17621     switch(type) {
  17622         case bcmOamControlFlexibleDropPort:
  17623         case bcmOamControlFlexibleDropCVlan:
  17624         case bcmOamControlFlexibleDropSVlan:
  17625         case bcmOamControlFlexibleDropCPlusSVlan:
  17626         case bcmOamControlFlexibleDropVP:
  17627         case bcmOamControlFlexibleDropEgressPort:
  17628         case bcmOamControlFlexibleDropEgressCVlan:
  17629         case bcmOamControlFlexibleDropEgressSVlan:
  17630         case bcmOamControlFlexibleDropEgressCPlusSVlan:
  17631         case bcmOamControlFlexibleDropEgressVP:
  17632         case bcmOamControlFlexibleDropPasssiveSap:
  17633         case bcmOamControlFlexibleDropEgressPasssiveSap:
  17634             rv = _bcm_kt2_oam_flex_drop_get(unit, type, arg);
  17635             break; 
  17636         default:
  17637             rv = BCM_E_UNAVAIL; 
  17638             break;
  17639     }
  17640     return rv;
  17641 }
  17642 
  17643 /*
  17644  * Function:
  17645  *     bcm_kt2_oam_control_set
  17646  * Purpose:
  17647  *     Set the value of the device-wide OAM control.
  17648  * Parameters:
  17649  *     unit        - (IN) BCM device number
  17650  *     type        - (IN) OAM control type
  17651  *     arg         - (IN) value to be set for control 
  17652  * Returns:
  17653  *      BCM_E_XXX
  17654  */
  17655 int bcm_kt2_oam_control_set(int unit, bcm_oam_control_type_t type,
  17656                                      uint64  arg) 
  17657 {
  17658     int        rv = BCM_E_NONE;
  17659     switch(type) {
  17660         case bcmOamControlFlexibleDropPort:
  17661         case bcmOamControlFlexibleDropCVlan:
  17662         case bcmOamControlFlexibleDropSVlan:
  17663         case bcmOamControlFlexibleDropCPlusSVlan:
  17664         case bcmOamControlFlexibleDropVP:
  17665         case bcmOamControlFlexibleDropEgressPort:
  17666         case bcmOamControlFlexibleDropEgressCVlan:
  17667         case bcmOamControlFlexibleDropEgressSVlan:
  17668         case bcmOamControlFlexibleDropEgressCPlusSVlan:
  17669         case bcmOamControlFlexibleDropEgressVP:
  17670         case bcmOamControlFlexibleDropPasssiveSap:
  17671         case bcmOamControlFlexibleDropEgressPasssiveSap:
  17672             rv = _bcm_kt2_oam_flex_drop_set(unit, type, arg);
  17673             break; 
  17674         default:
  17675             rv = BCM_E_UNAVAIL; 
  17676             break;
  17677     }
  17678     return rv;
  17679 }
  17680 
  17681 /*
  17682  * Function:
  17683  *     bcm_kt2_oam_upmep_cosq_set
  17684  * Purpose:
  17685  *     Set the value of the device-wide UP MEP PDU type CPU queue.
  17686  * Parameters:
  17687  *     unit        - (IN) BCM device number
  17688  *     upmep_pdu_type        - (IN) UP MEP PDU type
  17689  *     cosq        - (IN) value to be set for CPU queue
  17690  * Returns:
  17691  *      BCM_E_XXX
  17692  */
  17693 int bcm_kt2_oam_upmep_cosq_set(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type,
  17694                                bcm_cos_queue_t cosq)
  17695 {
  17696     int        rv = BCM_E_NONE;
  17697     uint64 cpu_control_2_64;
  17698     uint64 write_val;
  17699 
  17700     SOC_IF_ERROR_RETURN(
  17701             READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64));
  17702     switch(upmep_pdu_type) {
  17703         case bcmOamUpmepPduTypeCcm:
  17704             COMPILER_64_SET(write_val, 0, cosq);
  17705             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  17706                     OAM_CCM_SLOWPATH_CPU_COSf, write_val);
  17707             break;
  17708         case bcmOamUpmepPduTypeLmDm:
  17709             COMPILER_64_SET(write_val, 0, cosq);
  17710             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  17711                     OAM_LMDM_CPU_COSf, write_val);
  17712             break;
  17713         case bcmOamUpmepPduTypeSlowpath:
  17714             COMPILER_64_SET(write_val, 0, cosq);
  17715             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  17716                     OAM_SLOWPATH_CPU_COSf, write_val);
  17717             break;
  17718         case bcmOamUpmepPduTypeCount :
  17719             rv = BCM_E_PARAM;
  17720             break;
  17721         default:
  17722             rv = BCM_E_UNAVAIL;
  17723             break;
  17724     }
  17725     if (rv == BCM_E_NONE) {
  17726         SOC_IF_ERROR_RETURN(
  17727                 WRITE_EGR_CPU_CONTROL_2_64r(unit, cpu_control_2_64));
  17728     }
  17729     return rv;
  17730 }
  17731 
  17732 /*
  17733  * Function:
  17734  *     bcm_kt2_oam_upmep_cosq_get
  17735  * Purpose:
  17736  *     Query the value of the device-wide UP MEP PDU type CPU queue.
  17737  * Parameters:
  17738  *     unit        - (IN) BCM device number
  17739  *     upmep_pdu_type        - (IN) UP MEP PDU type
  17740  *     cosq        - (OUT) pointer to CPU queue to be get
  17741  * Returns:
  17742  *      BCM_E_XXX
  17743  */
  17744 int bcm_kt2_oam_upmep_cosq_get(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type,
  17745                                bcm_cos_queue_t *cosq)
  17746 {
  17747    int        rv = BCM_E_NONE;
  17748     uint64 cpu_control_2_64;
  17749 
  17750     SOC_IF_ERROR_RETURN(
  17751             READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64));
  17752     switch(upmep_pdu_type) {
  17753         case bcmOamUpmepPduTypeCcm:
  17754             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  17755             cpu_control_2_64, OAM_CCM_SLOWPATH_CPU_COSf);
  17756             break;
  17757         case bcmOamUpmepPduTypeLmDm:
  17758             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  17759             cpu_control_2_64, OAM_LMDM_CPU_COSf);
  17760             break;
  17761         case bcmOamUpmepPduTypeSlowpath:
  17762             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  17763             cpu_control_2_64, OAM_SLOWPATH_CPU_COSf);
  17764             break;
  17765         case bcmOamUpmepPduTypeCount :
  17766             rv = BCM_E_PARAM;
  17767             break;
  17768         default:
  17769             rv = BCM_E_UNAVAIL;
  17770             break;
  17771     }
  17772     return rv;
  17773 }
  17774 
  17775 #if defined(INCLUDE_BHH)
  17776 /*
  17777  * Function:
  17778  *      bcm_kt2_oam_mpls_tp_channel_type_tx_get
  17779  * Purpose:
  17780  *      Get MPLS TP(BHH) ACH Channel type
  17781  * Parameters:
  17782  *      unit                (IN)  BCM device number
  17783  *      channel_type        (IN)  Channel type is ignored in XGS devices
  17784  *      Value               (OUT) User define MPLS TP(BHH) ACH channel type
  17785  *
  17786  * Returns:
  17787  *      BCM_E_NONE          No error
  17788  *      BCM_E_XXXX          Error
  17789  */
  17790 int
  17791 bcm_kt2_oam_mpls_tp_channel_type_tx_get(int unit,
  17792                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  17793                                         int *value)
  17794 {
  17795     *value = kt2_oam_mpls_tp_ach_channel_type;
  17796     return BCM_E_NONE;
  17797 }
  17798 
  17799 /*
  17800  * Function:
  17801  *      bcm_kt2_oam_mpls_tp_channel_type_tx_set
  17802  * Purpose:
  17803  *      Update MPLS TP(BHH) ACH Channel type with user defined value
  17804  * Parameters:
  17805  *      unit                (IN) BCM device number
  17806  *      channel_type        (IN) Channel type is ignored in XGS devices
  17807  *      Value               (IN) User define MPLS TP(BHH) ACH channel type
  17808  *
  17809  * Returns:
  17810  *      BCM_E_NONE          No error
  17811  *      BCM_E_XXXX          Error
  17812  */
  17813 int
  17814 bcm_kt2_oam_mpls_tp_channel_type_tx_set(int unit,
  17815                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  17816                                         int value)
  17817 {
  17818     uint8               *buffer, *buffer_ptr;
  17819     uint16              buffer_len, reply_len;
  17820     int                 rv = BCM_E_NONE;
  17821     uint32              *msg;
  17822     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  17823 
  17824     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  17825     _BCM_OAM_LOCK(oc);
  17826 
  17827     if (oc->ukernel_not_ready) {
  17828         _BCM_OAM_UNLOCK(oc);
  17829         return BCM_E_INIT;
  17830     }
  17831 
  17832     if ((value != SHR_BHH_ACH_CHANNEL_TYPE) &&
  17833         (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) {
  17834         _BCM_OAM_UNLOCK(oc);
  17835         return BCM_E_CONFIG;
  17836     }
  17837 
  17838     kt2_oam_mpls_tp_ach_channel_type = value;
  17839     msg = (uint32 *)&kt2_oam_mpls_tp_ach_channel_type;
  17840 
  17841     /* Set BHH ACH Type in BHH_RX_ACH_TYPE register */
  17842     rv = WRITE_BHH_RX_ACH_TYPEr(unit, kt2_oam_mpls_tp_ach_channel_type);
  17843 
  17844     /* Pack control message data into DMA buffer */
  17845     buffer     = oc->dma_buffer;
  17846     buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg);
  17847     buffer_len = buffer_ptr - buffer;
  17848 
  17849     rv = _bcm_kt2_oam_bhh_msg_send_receive(
  17850                                            unit,
  17851                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE,
  17852                                            buffer_len, 0,
  17853                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY,
  17854                                            &reply_len);
  17855 
  17856     if (BCM_FAILURE(rv)) {
  17857         _BCM_OAM_UNLOCK(oc);
  17858         return (rv);
  17859     }
  17860 
  17861     _BCM_OAM_UNLOCK(oc);
  17862     return BCM_E_NONE;
  17863 }
  17864 
  17865 /*
  17866  * Function:
  17867  *      _bcm_kt2_oam_bhh_encap_hw_set
  17868  * Purpose:
  17869  *      Sets BHH encapsulation type in HW device.
  17870  * Parameters:
  17871  *      unit            - (IN) Unit number.
  17872  *      module_id       - (IN) Module id.
  17873  *      port_id         - (IN) Port.
  17874  *      is_local        - (IN) Indicates if module id is local.
  17875  *      endpoint_config - (IN) Pointer to BHH endpoint structure.
  17876  * Returns:
  17877  *      BCM_E_XXX
  17878  * Notes:
  17879  */
  17880 STATIC int
  17881 _bcm_kt2_oam_bhh_encap_hw_set(int unit, _bcm_oam_hash_data_t *h_data_p,
  17882                          bcm_module_t module_id, bcm_port_t port_id,
  17883                          int is_local, bcm_oam_endpoint_info_t *endpoint_info)
  17884 {
  17885     int rv = BCM_E_NONE;
  17886 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  17887     bcm_l3_egress_t l3_egress;
  17888     int ingress_if;
  17889     int i;
  17890     int num_entries;
  17891     mpls_entry_entry_t mpls_entry;
  17892     mpls_entry_entry_t mpls_key;
  17893     int vccv_type = 0;
  17894     int mpls_index = 0;
  17895 #endif /* BCM_KATANA2_SUPPORT &&  BCM_MPLS_SUPPORT */
  17896 
  17897     switch(h_data_p->type) {
  17898     case bcmOAMEndpointTypeBHHMPLS:
  17899     case bcmOAMEndpointTypeBHHMPLSVccv:
  17900 
  17901 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  17902         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
  17903 
  17904         sal_memset(&mpls_key, 0, sizeof(mpls_key));
  17905         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS__MPLS_LABELf,
  17906                                     h_data_p->label);
  17907 
  17908         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index,
  17909                             &mpls_key, &mpls_entry, 0);
  17910         if (SOC_FAILURE(rv)) {
  17911             bcm_tr_mpls_unlock (unit);
  17912             return rv;
  17913         }
  17914 
  17915         if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  17916                                          VALIDf) != 0x1)) {
  17917             bcm_tr_mpls_unlock (unit);
  17918             return (BCM_E_PARAM);
  17919         }
  17920 
  17921         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  17922             /* Get the control channel type */
  17923             vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  17924                                                     MPLS__PW_CC_TYPEf);
  17925 
  17926             if (vccv_type == 0) { /* No VCCV type configured */
  17927                 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  17928                                             MPLS__PW_CC_TYPEf,
  17929                                             (h_data_p->vccv_type + 1));
  17930 
  17931             } else if (vccv_type != (h_data_p->vccv_type + 1)) {
  17932                 /* Endpoint add configuration conflicts with MPLS port add config */
  17933                 bcm_tr_mpls_unlock(unit);
  17934                 return BCM_E_PARAM;
  17935             }
  17936 
  17937         }
  17938 
  17939         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  17940                                     MPLS__SESSION_IDENTIFIER_TYPEf, 1);
  17941         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS__BHH_ENABLEf, 1);
  17942         rv = soc_mem_write(unit, MPLS_ENTRYm,
  17943                            MEM_BLOCK_ANY, mpls_index,
  17944                            &mpls_entry);
  17945         if (rv != SOC_E_NONE) {
  17946             bcm_tr_mpls_unlock(unit);
  17947             return rv;
  17948         }
  17949 
  17950         /*
  17951          * PW CC-3
  17952          *
  17953          * Set MPLS entry DECAP_USE_TTL=0 for corresponding
  17954          * Tunnel Terminator label.
  17955          */
  17956         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  17957             if (h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  17958                 rv = bcm_esw_l3_egress_get(unit, h_data_p->egress_if,
  17959                                            &l3_egress);
  17960                 if (rv != BCM_E_NONE) {
  17961                     bcm_tr_mpls_unlock(unit);
  17962                     return rv;
  17963                 }
  17964 
  17965                 /* Look for Tunnel Terminator label */
  17966                 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
  17967                 for (i = 0; i < num_entries; i++) {
  17968                     rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry);
  17969                     if (rv != SOC_E_NONE) {
  17970                         bcm_tr_mpls_unlock(unit);
  17971                         return rv;
  17972                     }
  17973 
  17974                     if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) {
  17975                         continue;
  17976                     }
  17977                     if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  17978                                               MPLS__MPLS_ACTION_IF_BOSf) == 0x1) {
  17979                         continue;    /* L2_SVP */
  17980                     }
  17981 
  17982                     ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  17983                                                              MPLS__L3_IIFf);
  17984                     if (ingress_if == l3_egress.intf) {
  17985                         /* Label found */
  17986                         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  17987                                                     MPLS__DECAP_USE_TTLf, 0);
  17988                         rv = soc_mem_write(unit, MPLS_ENTRYm,
  17989                                            MEM_BLOCK_ALL, i,
  17990                                            &mpls_entry);
  17991                         if (rv != SOC_E_NONE) {
  17992                             bcm_tr_mpls_unlock(unit);
  17993                             return rv;
  17994                         }
  17995                         break;
  17996                     }
  17997                 }
  17998             }
  17999         }
  18000         bcm_tr_mpls_unlock (unit);
  18001 #else
  18002         rv = BCM_E_UNAVAIL;
  18003 #endif /* BCM_KATANA2_SUPPORT &&  BCM_MPLS_SUPPORT */
  18004 
  18005         break;
  18006 
  18007     default:
  18008         rv = BCM_E_UNAVAIL;
  18009         break;
  18010     }
  18011 
  18012     return (rv);
  18013 }
  18014 
  18015 /*
  18016  * Function:
  18017  *      _bcm_kt2_oam_bhh_encap_data_dump
  18018  * Purpose:
  18019  *      Dumps buffer contents.
  18020  * Parameters:
  18021  *      buffer  - (IN) Buffer to dump data.
  18022  *      length  - (IN) Length of buffer.
  18023  * Returns:
  18024  *      None
  18025  */
  18026 void
  18027 _bcm_kt2_oam_bhh_encap_data_dump(uint8 *buffer, int length)
  18028 {
  18029     int i;
  18030 
  18031     LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length));
  18032 
  18033     for (i = 0; i < length; i++) {
  18034         if ((i % 16) == 0) {
  18035             LOG_CLI((BSL_META("\n")));
  18036         }
  18037         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  18038     }
  18039 
  18040     LOG_CLI((BSL_META("\n")));
  18041     return;
  18042 }
  18043 
  18044 STATIC int
  18045 _bcm_kt2_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach)
  18046 {
  18047     sal_memset(ach, 0, sizeof(*ach));
  18048 
  18049     ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE;
  18050     ach->version  = SHR_BHH_ACH_VERSION;
  18051     ach->reserved = 0;
  18052 
  18053     ach->channel_type = kt2_oam_mpls_tp_ach_channel_type;
  18054 
  18055     return (BCM_E_NONE);
  18056 }
  18057 
  18058 STATIC int
  18059 _bcm_kt2_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
  18060                            _mpls_label_t *mpls)
  18061 {
  18062     sal_memset(mpls, 0, sizeof(*mpls));
  18063 
  18064     mpls->label = label;
  18065     mpls->exp   = exp & 0x07;
  18066     mpls->s     = s;
  18067     if(ttl)
  18068         mpls->ttl   = ttl;
  18069     else
  18070         mpls->ttl   = _BHH_MPLS_DFLT_TTL;
  18071 
  18072     return (BCM_E_NONE);
  18073 }
  18074 
  18075 STATIC int
  18076 _bcm_kt2_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp)
  18077 {
  18078     return _bcm_kt2_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL,
  18079                                       oam_exp, 1, 1, mpls);
  18080 }
  18081 
  18082 STATIC int
  18083 _bcm_kt2_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  18084                                 uint32 packet_flags,
  18085                                 int max_count, 
  18086                                 _mpls_label_t *pw_label,
  18087                                 _mpls_label_t *mpls,
  18088                                 int *mpls_count, bcm_if_t *l3_intf_id)
  18089 {
  18090     int count = 0;
  18091     bcm_l3_egress_t l3_egress;
  18092     bcm_mpls_port_t mpls_port;
  18093     bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS];
  18094     bcm_mpls_egress_label_t tmp_label;
  18095     int label_count;
  18096     int i = 0;
  18097 
  18098      /* Get L3 objects */
  18099     bcm_l3_egress_t_init(&l3_egress);
  18100     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  18101         return (BCM_E_PARAM);
  18102     }
  18103 
  18104     /* Look for a tunnel associated with this interface */
  18105     if (BCM_SUCCESS
  18106         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
  18107                                            _BHH_MPLS_MAX_LABELS,
  18108                                            label_array, &label_count))) {
  18109         /* We need to swap the labels configured in tunnel initiator as
  18110          * it returns labels in reverse order than how it should be in pkt.
  18111          */
  18112         for (i = 0; i < (label_count / 2); i++) {
  18113             sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label));
  18114             sal_memcpy(&label_array[i], &label_array[label_count - 1 - i],
  18115                        sizeof(tmp_label));
  18116             sal_memcpy(&label_array[label_count - 1 - i], &tmp_label,
  18117                        sizeof(tmp_label));
  18118         }
  18119 
  18120         /* Add VRL Label */
  18121         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS) {
  18122             if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
  18123                 (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID)  &&
  18124                 (label_count < _BHH_MPLS_MAX_LABELS) ) {
  18125 
  18126                 label_array[label_count].label = l3_egress.mpls_label;
  18127                 label_array[label_count].exp = l3_egress.mpls_exp;
  18128                 label_array[label_count].ttl = l3_egress.mpls_ttl;
  18129                 label_count++;
  18130             }
  18131             /* Traverse through Label stack and match on control label, this
  18132              * label should be the one just above GAL in the label stack, any
  18133              * following labels should not be added.
  18134              */
  18135             for (i = 0;  i < label_count; i++) {
  18136                 if (label_array[i].label == h_data_p->egr_label) {
  18137                     label_count = i + 1;
  18138                     label_array[i].exp = h_data_p->egr_label_exp;
  18139                     if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  18140                         h_data_p->egr_label_ttl) {
  18141                         label_array[i].ttl = h_data_p->egr_label_ttl;
  18142                     }
  18143                     break;
  18144                 }
  18145             }
  18146         }
  18147     }
  18148 
  18149         /* MPLS Router Alert */
  18150     if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  18151         /* Ignore overrun error as RAL is only added for PW MEPs and so overrun
  18152          * condition will not exist.
  18153          */
  18154         /* coverity[overrun-local] */
  18155         label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL;
  18156         label_array[label_count].exp = 0;
  18157         label_array[label_count].ttl = 0;
  18158         label_count++;
  18159     }
  18160 
  18161     /* Use GPORT to resolve interface */
  18162     if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
  18163         /* Get mpls port and label info */
  18164         bcm_mpls_port_t_init(&mpls_port);
  18165         mpls_port.mpls_port_id = h_data_p->gport;
  18166         if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn,
  18167                                               &mpls_port))) {
  18168             return (BCM_E_PARAM);
  18169         }
  18170         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  18171             h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  18172             mpls_port.egress_label.ttl = 0x1;
  18173         }
  18174 
  18175         label_array[label_count].label = mpls_port.egress_label.label;
  18176         if (h_data_p->egr_label == mpls_port.egress_label.label) {
  18177             label_array[label_count].exp = h_data_p->egr_label_exp;
  18178             if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  18179                     h_data_p->egr_label_ttl) {
  18180                 label_array[label_count].ttl = h_data_p->egr_label_ttl;
  18181             }
  18182         } else {
  18183             label_array[label_count].exp   = mpls_port.egress_label.exp;
  18184             label_array[label_count].ttl   = mpls_port.egress_label.ttl;
  18185         }
  18186         label_count++;
  18187     }
  18188 
  18189 
  18190     for (i=0;  i < label_count; i++) {
  18191         _bcm_kt2_oam_bhh_mpls_label_get(label_array[i].label,
  18192                                         label_array[i].exp,
  18193                                         0,
  18194                                         label_array[i].ttl,
  18195                                         &mpls[count++]);
  18196     }
  18197 
  18198     /* Set Bottom of Stack if there is no GAL label */
  18199     if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) {
  18200         mpls[count-1].s = 1;
  18201     }
  18202 
  18203     *mpls_count = count;
  18204 
  18205     return (BCM_E_NONE);
  18206 
  18207 }
  18208 
  18209 STATIC int
  18210 _bcm_kt2_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  18211                                bcm_port_t port, uint16 etype,
  18212                                _l2_header_t *l2)
  18213 {
  18214     uint16 tpid;
  18215     bcm_l3_egress_t l3_egress;
  18216     bcm_l3_intf_t l3_intf;
  18217     bcm_vlan_control_vlan_t vc;
  18218     int tpid_select;
  18219     bcm_pbmp_t pbmp, ubmp;
  18220 
  18221     sal_memset(l2, 0, sizeof(*l2));
  18222 
  18223     if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  18224         /* Get L3 interfaces */
  18225         bcm_l3_egress_t_init(&l3_egress);
  18226         bcm_l3_intf_t_init(&l3_intf);
  18227 
  18228         if (BCM_FAILURE
  18229             (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  18230             return (BCM_E_PARAM);
  18231         }
  18232 
  18233         l3_intf.l3a_intf_id = l3_egress.intf;
  18234         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  18235             return (BCM_E_PARAM);
  18236         }
  18237 
  18238         /* Get TPID */
  18239         BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit,
  18240                                                           port,
  18241                                                           bcmVlanPortOuterTpidSelect,
  18242                                                           &tpid_select));
  18243         if (tpid_select == BCM_PORT_OUTER_TPID) {
  18244             BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
  18245         } else {
  18246             BCM_IF_ERROR_RETURN(
  18247                          bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
  18248             tpid = vc.outer_tpid;
  18249         }
  18250 
  18251         sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
  18252         sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
  18253         l2->vlan_tag.tpid     = tpid;
  18254         l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  18255         l2->vlan_tag.tci.cfi  = 0;
  18256         l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
  18257 
  18258         BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
  18259                                                   l2->vlan_tag.tci.vid,
  18260                                                   &pbmp,
  18261                                                   &ubmp));
  18262         if (BCM_PBMP_MEMBER(ubmp, port)) {
  18263             l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
  18264         }
  18265 
  18266         if (l3_intf.l3a_inner_vlan != 0) {
  18267             BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
  18268             l2->vlan_tag_inner.tpid     = tpid;
  18269             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  18270             l2->vlan_tag_inner.tci.cfi  = 0;
  18271             l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
  18272         }
  18273         l2->etype             = etype;
  18274     } else {
  18275         sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH);
  18276         sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH);
  18277         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) ||
  18278             (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
  18279             (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
  18280             if (h_data_p->vlan != 0) {
  18281                 l2->vlan_tag.tpid     = h_data_p->outer_tpid;
  18282                 l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  18283                 l2->vlan_tag.tci.cfi  = 0;
  18284                 l2->vlan_tag.tci.vid  = h_data_p->vlan;
  18285             }
  18286         }
  18287         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
  18288             (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
  18289             l2->vlan_tag_inner.tpid     = h_data_p->inner_tpid;
  18290             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  18291             l2->vlan_tag_inner.tci.cfi  = 0;
  18292             l2->vlan_tag_inner.tci.vid  = h_data_p->inner_vlan;
  18293         }
  18294          l2->etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
  18295     }
  18296     return BCM_E_NONE;
  18297 }
  18298 STATIC uint8 *
  18299 _bcm_kt2_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach)
  18300 {
  18301     uint32  tmp;
  18302 
  18303     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
  18304         (ach->reserved << 16) | ach->channel_type;
  18305 
  18306     _BHH_ENCAP_PACK_U32(buffer, tmp);
  18307 
  18308     return (buffer);
  18309 }
  18310 
  18311 STATIC uint8 *
  18312 _bcm_kt2_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls)
  18313 {
  18314     uint32  tmp;
  18315 
  18316     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
  18317         ((mpls->s & 0x1) << 8) | mpls->ttl;
  18318     _BHH_ENCAP_PACK_U32(buffer, tmp);
  18319 
  18320     return (buffer);
  18321 }
  18322 
  18323 STATIC uint8 *
  18324 _bcm_kt2_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2)
  18325 {
  18326     uint32  tmp;
  18327     int     i;
  18328 
  18329     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  18330         _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
  18331     }
  18332 
  18333     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  18334         _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
  18335     }
  18336 
  18337     /* Vlan Tag tpid = 0 indicates untagged */
  18338     if (0 != l2->vlan_tag.tpid) {
  18339         tmp =  (l2->vlan_tag.tpid            << 16) |
  18340               ((l2->vlan_tag.tci.prio & 0x7) << 13) |
  18341               ((l2->vlan_tag.tci.cfi  & 0x1) << 12) |
  18342                (l2->vlan_tag.tci.vid  & 0xfff);
  18343         _BHH_ENCAP_PACK_U32(buffer, tmp);
  18344     }
  18345 
  18346     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
  18347     if (0 != l2->vlan_tag_inner.tpid) {
  18348         tmp = (l2->vlan_tag_inner.tpid            << 16) |
  18349              ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) |
  18350              ((l2->vlan_tag_inner.tci.cfi  & 0x1) << 12) |
  18351               (l2->vlan_tag_inner.tci.vid  & 0xfff);
  18352         _BHH_ENCAP_PACK_U32(buffer, tmp);
  18353     }
  18354     _BHH_ENCAP_PACK_U16(buffer, l2->etype);
  18355 
  18356     return (buffer);
  18357 }
  18358 
  18359 /*
  18360  * Function:
  18361  *      _bcm_kt2_oam_bhh_encap_build_pack
  18362  * Purpose:
  18363  *      Builds and packs the BHH packet encapsulation for a given
  18364  *      BHH tunnel type.
  18365  * Parameters:
  18366  *      unit            - (IN) Unit number.
  18367  *      port            - (IN) Port.
  18368  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  18369  *      packet_flags    - (IN) Flags for building packet.
  18370  *      buffer          - (OUT) Buffer returning BHH encapsulation.
  18371  * Returns:
  18372  *      BCM_E_XXX
  18373  * Notes:
  18374  *      The returning BHH encapsulation includes only all the
  18375  *      encapsulation headers/labels and does not include
  18376  *      the BHH control packet.
  18377  */
  18378 STATIC int
  18379 _bcm_kt2_oam_bhh_encap_build_pack(int unit, bcm_port_t port,
  18380                              _bcm_oam_hash_data_t *h_data_p,
  18381                              uint32 packet_flags,
  18382                              uint8 *buffer,
  18383                              uint32 *encap_length)
  18384 {
  18385     uint8          *cur_ptr = buffer;
  18386     uint16         etype = 0;
  18387     bcm_if_t       l3_intf_id = -1;
  18388     _ach_header_t  ach;
  18389     _mpls_label_t  mpls_gal;
  18390     _mpls_label_t  mpls_labels[_BHH_MPLS_MAX_LABELS];
  18391     _mpls_label_t  pw_label;
  18392     int            mpls_count = 0;
  18393     _l2_header_t   l2;
  18394     int i;
  18395 
  18396 
  18397     /*
  18398      * Get necessary headers/labels information.
  18399      *
  18400      * Following order is important since some headers/labels
  18401      * may depend on previous header/label information.
  18402      */
  18403     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  18404         BCM_IF_ERROR_RETURN
  18405             (_bcm_kt2_oam_bhh_ach_header_get(packet_flags, &ach));
  18406     }
  18407 
  18408     if (packet_flags & _BHH_ENCAP_PKT_GAL) {
  18409         if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) {
  18410             BCM_IF_ERROR_RETURN
  18411                 (_bcm_kt2_oam_bhh_mpls_gal_label_get(&mpls_gal,
  18412                                                      h_data_p->egr_label_exp));
  18413         } else {
  18414             BCM_IF_ERROR_RETURN
  18415                 (_bcm_kt2_oam_bhh_mpls_gal_label_get(&mpls_gal, 0));
  18416         }
  18417     }
  18418 
  18419     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  18420         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
  18421         BCM_IF_ERROR_RETURN
  18422             (_bcm_kt2_oam_bhh_mpls_labels_get(unit, h_data_p,
  18423                                              packet_flags,    
  18424                                              _BHH_MPLS_MAX_LABELS,
  18425                                              &pw_label,
  18426                                              mpls_labels, 
  18427                                              &mpls_count,
  18428                                              &l3_intf_id));
  18429     }
  18430 
  18431     /* Always build L2 Header */
  18432     BCM_IF_ERROR_RETURN
  18433         (_bcm_kt2_oam_bhh_l2_header_get(unit, 
  18434                                        h_data_p,
  18435                                        port, 
  18436                                        etype, 
  18437                                        &l2));
  18438 
  18439     /*
  18440      * Pack header/labels into given buffer (network packet format).
  18441      *
  18442      * Following packing order must be followed to correctly
  18443      * build the packet encapsulation.
  18444      */
  18445     cur_ptr = buffer;
  18446 
  18447     /* L2 Header is always present */
  18448     cur_ptr = _bcm_kt2_oam_bhh_l2_header_pack(cur_ptr, &l2);
  18449 
  18450     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  18451         for (i = 0;i < mpls_count;i++) {
  18452             cur_ptr = _bcm_kt2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]);
  18453         }
  18454     }
  18455 
  18456     if (packet_flags & _BHH_ENCAP_PKT_GAL) {    
  18457         cur_ptr = _bcm_kt2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal);
  18458     }
  18459 
  18460     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  18461         cur_ptr = _bcm_kt2_oam_bhh_ach_header_pack(cur_ptr, &ach);
  18462     }
  18463 
  18464 
  18465     /* Set BHH encapsulation length */
  18466     *encap_length = cur_ptr - buffer;
  18467 
  18468     return (BCM_E_NONE);
  18469 }
  18470 /*
  18471  * Function:
  18472  *      _bcm_kt2_oam_bhh_encap_create
  18473  * Purpose:
  18474  *      Creates a BHH packet encapsulation.
  18475  * Parameters:
  18476  *      unit            - (IN) Unit number.
  18477  *      port_id         - (IN) Port.
  18478  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  18479  *      encap_data      - (OUT) Buffer returning BHH encapsulation.
  18480  * Returns:
  18481  *      BCM_E_XXX
  18482  * Notes:
  18483  *      The returning BHH encapsulation buffer includes all the
  18484  *      corresponding headers/labels EXCEPT for the BHH control packet.
  18485  */
  18486 STATIC int
  18487 _bcm_kt2_oam_bhh_encap_create(int unit, bcm_port_t port_id,
  18488                          _bcm_oam_hash_data_t *h_data_p,
  18489                          uint8 *encap_data,
  18490                          uint8  *encap_type,
  18491                          uint32 *encap_length)
  18492 {
  18493     uint32 packet_flags;
  18494     _bcm_oam_control_t *oc;
  18495 
  18496     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  18497 
  18498     packet_flags = 0;
  18499 
  18500     /*
  18501      * Get BHH encapsulation packet format flags
  18502      *
  18503      * Also, perform the following for each BHH tunnel type:
  18504      * - Check for valid parameter values
  18505      * - Set specific values required by the BHH tunnel definition 
  18506      *   (e.g. such as ttl=1,...)
  18507      */
  18508     switch (h_data_p->type) {
  18509     case bcmOAMEndpointTypeBHHMPLS:
  18510         packet_flags |=
  18511             (_BHH_ENCAP_PKT_MPLS |
  18512              _BHH_ENCAP_PKT_GAL |
  18513              _BHH_ENCAP_PKT_G_ACH);
  18514         break;
  18515 
  18516     case bcmOAMEndpointTypeBHHMPLSVccv:
  18517         switch(h_data_p->vccv_type) {
  18518 
  18519         case bcmOamBhhVccvChannelAch:
  18520             packet_flags |=
  18521                 (_BHH_ENCAP_PKT_MPLS |
  18522                  _BHH_ENCAP_PKT_PW |
  18523                  _BHH_ENCAP_PKT_G_ACH);
  18524         break;
  18525 
  18526         case bcmOamBhhVccvRouterAlert:
  18527             packet_flags |=
  18528                 (_BHH_ENCAP_PKT_MPLS |
  18529                  _BHH_ENCAP_PKT_PW |
  18530                  _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT |
  18531                  _BHH_ENCAP_PKT_G_ACH); 
  18532             break;
  18533 
  18534         case bcmOamBhhVccvTtl:
  18535             packet_flags |=
  18536                 (_BHH_ENCAP_PKT_MPLS |
  18537                  _BHH_ENCAP_PKT_PW |
  18538                  _BHH_ENCAP_PKT_G_ACH); 
  18539             break;
  18540 
  18541     case bcmOamBhhVccvGal13:
  18542             packet_flags |=
  18543                 (_BHH_ENCAP_PKT_MPLS |
  18544                  _BHH_ENCAP_PKT_PW |
  18545                  _BHH_ENCAP_PKT_GAL  |
  18546                  _BHH_ENCAP_PKT_G_ACH);
  18547             break;
  18548 
  18549     default:
  18550         return (BCM_E_PARAM);
  18551         break;
  18552     }
  18553         break;
  18554     case bcmOAMEndpointTypeBhhSection:
  18555     case bcmOAMEndpointTypeBhhSectionInnervlan:
  18556     case bcmOAMEndpointTypeBhhSectionOuterVlan:
  18557     case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
  18558             packet_flags |=
  18559                 (_BHH_ENCAP_PKT_GAL |
  18560                  _BHH_ENCAP_PKT_G_ACH);
  18561             break;
  18562     default:
  18563         return (BCM_E_PARAM);
  18564     }
  18565 
  18566     /* Build header/labels and pack in buffer */
  18567     BCM_IF_ERROR_RETURN
  18568         (_bcm_kt2_oam_bhh_encap_build_pack(unit, port_id,
  18569                                       h_data_p,
  18570                                       packet_flags,
  18571                                       encap_data,
  18572                                   encap_length));
  18573 
  18574     /* Set encap type (indicates uC side that checksum is required) */
  18575     *encap_type = SHR_BHH_ENCAP_TYPE_RAW;
  18576 
  18577 #ifdef _BHH_DEBUG_DUMP
  18578     _bcm_kt2_oam_bhh_encap_data_dump(encap_data, *encap_length);
  18579 #endif
  18580 
  18581     if (*encap_length > oc->bhh_max_encap_length) {
  18582         LOG_ERROR(BSL_LS_BCM_OAM,
  18583                 (BSL_META_U(unit,
  18584                 "OAM(unit %d) Error: Encap length greater than max,"
  18585                 "encap_length=%u max=%u\n"),
  18586                  unit, *encap_length, oc->bhh_max_encap_length));
  18587         return BCM_E_CONFIG;
  18588     }
  18589 
  18590     return (BCM_E_NONE);
  18591 }
  18592 
  18593 /*
  18594  * Function:
  18595  *      _bcm_kt2_oam_bhh_appl_callback
  18596  * Purpose:
  18597  *      Update FW BHH appl state
  18598  * Parameters:
  18599  *      unit  - (IN) Unit number.
  18600  *      uC    - (IN) core number.
  18601  *      stage - (IN) core reset stage.
  18602  *      user_data - (IN) data pointer.
  18603  * Returns:
  18604  *      BCM_E_XXX
  18605  * Notes:
  18606  */
  18607 
  18608 int _bcm_kt2_oam_bhh_appl_callback(int unit,
  18609                                     int uC,
  18610                                     soc_cmic_uc_shutdown_stage_t stage,
  18611                                     void *user_data) {
  18612     _bcm_oam_control_t *oc;
  18613 
  18614     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  18615     _BCM_OAM_LOCK(oc);
  18616     oc->ukernel_not_ready = 1;
  18617 
  18618     _BCM_OAM_UNLOCK(oc);
  18619 
  18620     return BCM_E_NONE;
  18621 }
  18622 
  18623 /*
  18624  * Function:
  18625  *      bcm_kt2_oam_bhh_endpoint_create
  18626  * Purpose:
  18627  *      Initialize the HW for BHH packet processing.
  18628  *      Configure:
  18629  *      - Copy to CPU BHH error packets
  18630  *      - CPU COS Queue for BHH packets
  18631  *      - RX DMA channel
  18632  * Parameters:
  18633  *      unit - (IN) Unit number.
  18634  * Returns:
  18635  *      BCM_E_XXX
  18636  * Notes:
  18637  */
  18638 int
  18639 bcm_kt2_oam_bhh_endpoint_create(int unit, 
  18640                                 bcm_oam_endpoint_info_t *endpoint_info,
  18641                                 _bcm_oam_hash_key_t  *hash_key)
  18642 {
  18643     _bcm_oam_control_t *oc;
  18644     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
  18645     _bcm_oam_group_data_t *group_p;         /* Pointer to group data.       */
  18646     int                  ep_req_index;      /* Requested endpoint index.    */
  18647     int                  rv = BCM_E_NONE;   /* Operation return status.     */
  18648     int                  is_remote = 0;     /* Remote endpoint status.      */
  18649     int                  is_replace;
  18650     int                  is_local = 0;         
  18651     uint32               sglp = 0;          /* Source global logical port.  */
  18652     uint32               dglp = 0;          /* Dest global logical port.    */
  18653     bcm_module_t         module_id;         /* Module ID                    */
  18654     bcm_port_t           port_id;
  18655     bcm_trunk_t          trunk_id;
  18656     int                  local_id;
  18657     uint32               svp = 0;           /* Source virtual port          */
  18658     bcm_port_t           src_pp_port = 0;   /* Source pp port.              */
  18659     bcm_port_t           dst_pp_port = 0;   /* Dest pp port.                */
  18660     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
  18661     bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create;
  18662     uint8 *buffer, *buffer_ptr;
  18663     uint16 buffer_len, reply_len;
  18664     int encap = 0;
  18665     uint32 session_flags;
  18666     int bhh_pool_ep_idx = 0;
  18667     egr_l3_next_hop_entry_t egr_nh_entry;
  18668     int egr_nh_index;
  18669     int is_vp_valid = 0;
  18670     uint8 group_sw_rdi = 0;
  18671     bcm_gport_t tx_gport;
  18672 
  18673     LOG_DEBUG(BSL_LS_BCM_OAM,
  18674               (BSL_META_U(unit,
  18675                           "BHH Info: bcm_kt2_oam_bhh_endpoint_create"
  18676                            "Endpoint ID=%d.\n"), endpoint_info->id));
  18677 
  18678     _BCM_OAM_BHH_IS_VALID(unit);
  18679 
  18680     /* Validate input parameter. */
  18681     if (NULL == endpoint_info) {
  18682         return (BCM_E_PARAM);
  18683     }
  18684 
  18685     /* Lock already taken by the calling routine. */
  18686     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  18687 
  18688     /* Perform BHH specific validation checks */
  18689     /* BHH EP can only be at the MAX Level */
  18690     if ( endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) {
  18691         LOG_ERROR(BSL_LS_BCM_OAM,
  18692                   (BSL_META_U(unit,
  18693                               "OAM Error: EP Level should be equal to %d\n"),
  18694                    _BCM_OAM_EP_LEVEL_MAX));
  18695         return (BCM_E_PARAM);
  18696     }
  18697 
  18698     /* Get MEP remote endpoint status. */
  18699     is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  18700 
  18701     is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0);
  18702 
  18703     /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */
  18704     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  18705         if((endpoint_info->id < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) ||
  18706            (endpoint_info->id >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET 
  18707                                   + oc->bhh_endpoint_count))) {
  18708             return (BCM_E_PARAM);
  18709         }
  18710     }
  18711 
  18712     /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */
  18713     if (is_remote) {
  18714         if((endpoint_info->local_id < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) ||
  18715            (endpoint_info->local_id >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET
  18716                                         + oc->bhh_endpoint_count))) {
  18717             return (BCM_E_PARAM);
  18718         }
  18719     }
  18720 
  18721     if (is_replace) {
  18722         hash_data = &oc->oam_hash_data[endpoint_info->id];
  18723         if (!hash_data->in_use) {
  18724             return (BCM_E_NOT_FOUND);
  18725         }
  18726         
  18727         /* Delete original and recreate new EP */
  18728         rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint_info->id);
  18729         if (BCM_FAILURE(rv)) {
  18730             LOG_ERROR(BSL_LS_BCM_OAM,
  18731                       (BSL_META_U(unit,
  18732                                   "OAM Error: Endpoint destroy (EP=%d) - %s.\n"),
  18733                        endpoint_info->id, bcm_errmsg(rv)));
  18734             return (rv);
  18735         }
  18736     }
  18737 
  18738     /*
  18739        BHH API have been using L3_EGRESS type in 
  18740        bcm_oam_endpoint_info_t.intf field. 
  18741        However for supporting LM/DM on Katana2 this should be DVP_EGRESS type for PW,
  18742        only CCM will work with L3_EGRESS type, retaining the old type for 
  18743        backward compatibility
  18744     */
  18745     if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){
  18746         if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) &&
  18747             (endpoint_info->flags & (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT |
  18748                                      BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) {
  18749                 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) {
  18750                     LOG_ERROR(BSL_LS_BCM_OAM,
  18751                               (BSL_META_U(unit,
  18752                                           "OAM Error: bcm_oam_endpoint_info_t.intf type"
  18753                                            " not valid. It should be DVP_EGRESS type for LM/DM support.\n")));
  18754                     return (BCM_E_PARAM);
  18755                 }
  18756         } else {
  18757             if ( !BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) &
  18758                 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) ) {
  18759                 LOG_ERROR(BSL_LS_BCM_OAM,
  18760                           (BSL_META_U(unit,
  18761                                       "OAM Error: bcm_oam_endpoint_info_t.intf type"
  18762                                        " not valid. It should be DVP_EGRESS or L3_EGRESS type.\n")));
  18763                 return (BCM_E_PARAM);
  18764             }
  18765         }
  18766     }
  18767     /* Now that we passed the validation checks
  18768      * Create a new endpoint with the requested ID. */
  18769     if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) {
  18770 
  18771         hash_data = &oc->oam_hash_data[endpoint_info->id];
  18772 
  18773         if (!is_replace && hash_data->in_use) {
  18774             return (BCM_E_EXISTS);
  18775         }
  18776 
  18777         ep_req_index = endpoint_info->id;
  18778         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  18779 
  18780         if(BCM_FAILURE(rv)) {
  18781             LOG_ERROR(BSL_LS_BCM_OAM,
  18782                       (BSL_META_U(unit,
  18783                                   "BHH Error: Endpoint check (EP=%d) - %s.\n"),
  18784                        endpoint_info->id, bcm_errmsg(rv)));
  18785             return (rv);
  18786         }
  18787 
  18788         if(!is_replace) {
  18789             rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx,
  18790                                      bhh_pool_ep_idx);
  18791             if (BCM_FAILURE(rv)) {
  18792                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  18793                 LOG_ERROR(BSL_LS_BCM_OAM,
  18794                           (BSL_META_U(unit,
  18795                                       "BHH Error: Endpoint reserve (EP=%d) - %s.\n"),
  18796                            endpoint_info->id, bcm_errmsg(rv)));
  18797                 return (rv);
  18798             }
  18799         }
  18800     } else {
  18801 
  18802         /* BHH uses local and remote same index */
  18803         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  18804             ep_req_index = endpoint_info->local_id;
  18805             bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  18806         }
  18807         else {
  18808             /* Allocate the next available endpoint index. */
  18809             rv = shr_idxres_list_alloc(oc->bhh_pool,
  18810                                    (shr_idxres_element_t *)&bhh_pool_ep_idx);
  18811             if (BCM_FAILURE(rv)) {
  18812                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
  18813                 LOG_ERROR(BSL_LS_BCM_OAM,
  18814                           (BSL_META_U(unit,
  18815                                       "BHH Error: Endpoint alloc failed - %s.\n"),
  18816                            bcm_errmsg(rv)));
  18817                 return (rv);
  18818             }
  18819             /* Set the allocated endpoint id value. */
  18820             ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx);
  18821         }
  18822         endpoint_info->id =  ep_req_index;
  18823     }
  18824 
  18825     /* Get the hash data pointer where the data is to be stored. */
  18826     hash_data = &oc->oam_hash_data[ep_req_index];
  18827     group_p = &oc->group_info[endpoint_info->group];
  18828 
  18829     /*
  18830      * The uKernel is not provisioned until both endpoints (local and remote)
  18831      * are provisioned in the host.
  18832      */
  18833     if (is_remote) {
  18834 
  18835         if (!hash_data->in_use) {
  18836             return (BCM_E_NOT_FOUND);
  18837         } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) {
  18838             return (BCM_E_EXISTS);
  18839         }
  18840 
  18841         if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)){
  18842             /*
  18843              * Now that both ends are provisioned the uKernel can be 
  18844              * configured.
  18845              */
  18846             msg_rmep_create.sess_id = bhh_pool_ep_idx;
  18847             msg_rmep_create.flags = 0;
  18848             msg_rmep_create.enable = 1;
  18849             msg_rmep_create.remote_mep_id = endpoint_info->name;
  18850 
  18851             msg_rmep_create.period = _kt2_ccm_intervals[
  18852                 _bcm_kt2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  18853 
  18854             /* Pack control message data into DMA buffer */
  18855             buffer     = oc->dma_buffer;
  18856             buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create);
  18857             buffer_len = buffer_ptr - buffer;
  18858 
  18859             /* Send BHH Session Update message to uC */
  18860             rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  18861                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE,
  18862                     buffer_len, 0,
  18863                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY,
  18864                     &reply_len);
  18865             if (BCM_FAILURE(rv) || (reply_len != 0)) {
  18866                 LOG_ERROR(BSL_LS_BCM_OAM,
  18867                         (BSL_META_U(unit,
  18868                                     "BHH(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"),
  18869                          unit, endpoint_info->id, bcm_errmsg(rv)));
  18870                 return (BCM_E_INTERNAL);
  18871             }
  18872         }
  18873 
  18874     } else {
  18875     
  18876         /* Resolve given endpoint gport value to SGLP and DGLP values. */
  18877         rv = _bcm_kt2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp,
  18878                                                  &dglp, &src_pp_port,
  18879                                                  &dst_pp_port, &svp, &trunk_id,
  18880                                                  &is_vp_valid, &tx_gport);
  18881         if (BCM_FAILURE(rv)) {
  18882             LOG_ERROR(BSL_LS_BCM_OAM,
  18883                       (BSL_META_U(unit,
  18884                                   "OAM Error: Gport resolve (EP=%d) - %s.\n"),
  18885                        endpoint_info->id, bcm_errmsg(rv)));
  18886             /* Return endpoint index to MEP pool. */
  18887             shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
  18888             return (rv);
  18889         }
  18890     
  18891         /* Clear the hash data element contents before storing the values. */
  18892         _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  18893         hash_data->oam_domain = _BCM_OAM_DOMAIN_BHH;
  18894         hash_data->type = endpoint_info->type;
  18895         hash_data->ep_id = endpoint_info->id;
  18896         hash_data->group_index = endpoint_info->group;
  18897         hash_data->level = endpoint_info->level;
  18898         hash_data->vlan = endpoint_info->vlan;
  18899         hash_data->inner_vlan = endpoint_info->inner_vlan;
  18900         hash_data->outer_tpid = endpoint_info->outer_tpid;
  18901         hash_data->inner_tpid = endpoint_info->inner_tpid;
  18902         hash_data->vlan_pri = endpoint_info->pkt_pri;
  18903         hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri;
  18904         hash_data->gport = endpoint_info->gport;
  18905         hash_data->trunk_index = endpoint_info->trunk_index;
  18906         hash_data->sglp = sglp;
  18907         hash_data->dglp = dglp;
  18908         hash_data->flags = endpoint_info->flags;
  18909         hash_data->flags2 = endpoint_info->flags2;
  18910         hash_data->period = endpoint_info->ccm_period;
  18911         hash_data->vccv_type = endpoint_info->vccv_type;
  18912         hash_data->vpn  = endpoint_info->vpn;
  18913         hash_data->name      = endpoint_info->name;
  18914         hash_data->egress_if = endpoint_info->intf_id;
  18915         hash_data->cpu_qid   = endpoint_info->cpu_qid;
  18916         hash_data->int_pri   = endpoint_info->int_pri;
  18917         hash_data->label     = endpoint_info->mpls_label;
  18918         hash_data->local_tx_enabled = 0;
  18919         hash_data->local_rx_enabled = 1;
  18920         hash_data->ts_format = endpoint_info->timestamp_format;
  18921         hash_data->egr_label = endpoint_info->egress_label.label;
  18922         hash_data->egr_label_exp = endpoint_info->egress_label.exp;
  18923         hash_data->egr_label_ttl = endpoint_info->egress_label.ttl;
  18924 
  18925         /* Initialize hardware index as invalid indices. */
  18926         hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
  18927         hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
  18928         hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
  18929         hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX;
  18930         hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX;
  18931         hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX;
  18932         hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX;
  18933         hash_data->profile_index = _BCM_OAM_INVALID_INDEX;
  18934         hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX;
  18935         hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  18936         hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  18937         hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  18938         hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  18939         hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX;
  18940         hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  18941         sal_memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address,
  18942                     _BHH_MAC_ADDR_LENGTH);
  18943         sal_memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address,
  18944                         _BHH_MAC_ADDR_LENGTH);
  18945         hash_data->in_use = 1;
  18946 
  18947         if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) {
  18948 
  18949             /* Now that we have reserved the EP index, We can reserve MA INDEX */
  18950             rv =  _bcm_kt2_oam_downmep_rx_endpoint_reserve(unit, endpoint_info);
  18951             if (BCM_FAILURE(rv)) {
  18952                 /* Return endpoint index to MEP pool. */
  18953                 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
  18954                 LOG_ERROR(BSL_LS_BCM_OAM,
  18955                         (BSL_META_U(unit,
  18956                                     "OAM Error: EP MA INDEX alloc"
  18957                                     "failed EP:%d %s.\n"), endpoint_info->id,
  18958                         bcm_errmsg(rv)));
  18959                 return (rv);
  18960             }
  18961 
  18962             rv = _bcm_kt2_oam_local_rx_mep_hw_set(unit, endpoint_info);
  18963             if (BCM_FAILURE(rv)) {
  18964                 LOG_ERROR(BSL_LS_BCM_OAM,
  18965                           (BSL_META_U(unit,
  18966                                       "OAM Error: Rx config failed for EP=%d %s.\n"),
  18967                         endpoint_info->id, bcm_errmsg(rv)));
  18968                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  18969                 return (rv);
  18970             }
  18971 
  18972             /* Enable BHH in the EGR_L3_NEXT_HOP table */
  18973             if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) {
  18974                 egr_nh_index = endpoint_info->intf_id -
  18975                                    BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  18976             }
  18977             else {
  18978                 egr_nh_index = endpoint_info->intf_id -
  18979                                    BCM_XGS3_EGRESS_IDX_MIN(unit);
  18980             }
  18981             rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  18982                     egr_nh_index, &egr_nh_entry);
  18983             if (BCM_FAILURE(rv)) {
  18984                 LOG_ERROR(BSL_LS_BCM_OAM,
  18985                           (BSL_META_U(unit,
  18986                                       "OAM Error: reading EGR_L3_NEXT_HOP,"
  18987                                       "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv)));
  18988                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  18989                 return (rv);
  18990             }
  18991             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh_entry, MPLS__BHH_ENABLEf, 1); 
  18992             rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 
  18993                     egr_nh_index, &egr_nh_entry);
  18994             if (BCM_FAILURE(rv)) {
  18995                 LOG_ERROR(BSL_LS_BCM_OAM,
  18996                           (BSL_META_U(unit,
  18997                                       "OAM Error: writing EGR_L3_NEXT_HOP,"
  18998                                       "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv)));
  18999                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19000                 return (rv);
  19001             }
  19002         } else {
  19003             if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  19004                 shr_idxres_element_t ctr_index;
  19005 
  19006                 rv = _bcm_kt2_oam_bhh_sec_mep_alloc_counter(unit, &ctr_index);
  19007                 if (BCM_FAILURE(rv)) {
  19008                     LOG_ERROR(BSL_LS_BCM_OAM,
  19009                               (BSL_META_U(unit,
  19010                                           "OAM Error: LM counter block alloc - %s.\n"),
  19011                                           bcm_errmsg(rv)));
  19012                     _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19013                     return (rv);
  19014                 }
  19015                 hash_data->rx_ctr = (0 << 24) | (ctr_index); /* Pool id 0 for ingress counters*/
  19016                 hash_data->tx_ctr = (1 << 24) | (ctr_index); /* Pool id 1 for egress counters */
  19017             }
  19018         }
  19019         /* Get the Trunk, Port and Modid info for this Gport */
  19020         rv = _bcm_esw_gport_resolve(unit, tx_gport, &module_id, &port_id,
  19021                                     &trunk_id, &local_id);
  19022         if (BCM_FAILURE(rv)) {
  19023             LOG_ERROR(BSL_LS_BCM_OAM,
  19024                       (BSL_META_U(unit,
  19025                                   "BHH Error: Gport resolve (EP=%d) - %s.\n"),
  19026                        endpoint_info->id, bcm_errmsg(rv)));
  19027             _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19028             return (rv);
  19029         }
  19030 
  19031         /* Get local port used for TX BHH packet */
  19032         rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
  19033         if(BCM_FAILURE(rv)) {
  19034             LOG_ERROR(BSL_LS_BCM_OAM,
  19035                       (BSL_META_U(unit,
  19036                                   "BHH Error: local port for "
  19037                                   "BHH TX failed(EP=%d) - %s.\n"),
  19038                        endpoint_info->id, bcm_errmsg(rv)));
  19039             _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19040             return (rv);
  19041         }
  19042 
  19043         if (!is_local) {    /* HG port */
  19044             rv = bcm_esw_stk_modport_get(unit, module_id, &port_id);
  19045             if(BCM_FAILURE(rv)) {
  19046                 LOG_ERROR(BSL_LS_BCM_OAM,
  19047                           (BSL_META_U(unit,
  19048                                       "BHH Error: HG port get failed "
  19049                                       "(EP=%d) - %s.\n"),
  19050                            endpoint_info->id, bcm_errmsg(rv)));
  19051                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19052                 return (rv);
  19053             }
  19054         }
  19055 
  19056         /* Create or Update */
  19057         session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE;
  19058 
  19059         /* Set Endpoint config entry */
  19060         hash_data->bhh_endpoint_index = ep_req_index;
  19061 
  19062         /* Set Encapsulation in HW */
  19063         if ((!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) &&
  19064             ((!is_replace) || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET))) {
  19065             rv = _bcm_kt2_oam_bhh_encap_hw_set(unit, hash_data, module_id,
  19066                           port_id, is_local, endpoint_info);
  19067             if(BCM_FAILURE(rv)) {
  19068                 LOG_ERROR(BSL_LS_BCM_OAM,
  19069                           (BSL_META_U(unit,
  19070                                       "BHH Error: HW encap set failed (EP=%d)"
  19071                                       " - %s.\n"),
  19072                            endpoint_info->id, bcm_errmsg(rv)));
  19073                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19074                 return (rv);
  19075             }
  19076         }
  19077 
  19078         encap = 1;
  19079 
  19080         if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  19081             /* Set control message data */
  19082             sal_memset(&msg_sess, 0, sizeof(msg_sess));
  19083 
  19084             /*
  19085              * Set the BHH encapsulation data
  19086              *
  19087              * The function _bcm_kt2_oam_bhh_encap_create() is called first
  19088              * since this sets some fields in 'hash_data' which are
  19089              * used in the message.
  19090              */
  19091             if (encap) {
  19092                 rv = _bcm_kt2_oam_bhh_encap_create(unit,
  19093                         port_id,
  19094                         hash_data,
  19095                         msg_sess.encap_data,
  19096                         &msg_sess.encap_type,
  19097                         &msg_sess.encap_length);
  19098 
  19099                 if(BCM_FAILURE(rv))
  19100                 {
  19101                     LOG_ERROR(BSL_LS_BCM_OAM,
  19102                             (BSL_META_U(unit,
  19103                                         "BHH Error: Endpoint destroy (EP=%d) - %s.\n"),
  19104                              endpoint_info->id, bcm_errmsg(rv)));
  19105                     _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19106                     return (rv);
  19107                 }
  19108             }
  19109 
  19110             /*
  19111              * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM,
  19112              * all others modes must be specified via a config flag.
  19113  */
  19114             if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK)
  19115                 session_flags |= SHR_BHH_SESS_SET_F_LB;
  19116             else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)
  19117                 session_flags |= SHR_BHH_SESS_SET_F_DM;
  19118             else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
  19119                 session_flags |= SHR_BHH_SESS_SET_F_LM;
  19120             else
  19121                 session_flags |= SHR_BHH_SESS_SET_F_CCM;
  19122 
  19123             if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
  19124                 session_flags |= SHR_BHH_SESS_SET_F_MIP;
  19125 
  19126             _bcm_kt2_oam_get_group_sw_rdi (unit, endpoint_info->group,
  19127                     &group_sw_rdi);
  19128             if (group_sw_rdi) {
  19129                 session_flags |= SHR_BHH_SESS_SET_F_RDI;
  19130             }
  19131             /*if (!local_tx_enabled)
  19132               session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/
  19133 
  19134             msg_sess.sess_id = bhh_pool_ep_idx;
  19135             msg_sess.flags   = session_flags;
  19136 
  19137             msg_sess.mel     = hash_data->level;
  19138             msg_sess.mep_id  = hash_data->name;
  19139             sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
  19140 
  19141             msg_sess.period = _kt2_ccm_intervals[
  19142                 _bcm_kt2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  19143 
  19144             msg_sess.if_num  = endpoint_info->intf_id;
  19145             msg_sess.tx_port = port_id;
  19146             msg_sess.tx_cos  = endpoint_info->int_pri;
  19147             msg_sess.tx_pri  = endpoint_info->pkt_pri;
  19148             msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri;
  19149             msg_sess.lm_counter_index
  19150                 = hash_data->tx_ctr;
  19151 
  19152             msg_sess.mpls_label = endpoint_info->mpls_label;
  19153 
  19154             switch (endpoint_info->type) {
  19155             case bcmOAMEndpointTypeBHHMPLS:
  19156                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP;
  19157                 msg_sess.priority   = endpoint_info->mpls_exp;
  19158                 break;
  19159 
  19160             case bcmOAMEndpointTypeBHHMPLSVccv:
  19161                 switch(endpoint_info->vccv_type) {
  19162 
  19163                 case bcmOamBhhVccvChannelAch:
  19164                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1;
  19165                     msg_sess.priority   = endpoint_info->mpls_exp;
  19166                     break;
  19167 
  19168                 case bcmOamBhhVccvRouterAlert:
  19169                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2;
  19170                     msg_sess.priority   = endpoint_info->mpls_exp;
  19171                     break;
  19172 
  19173                 case bcmOamBhhVccvTtl:
  19174                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3;
  19175                     msg_sess.priority   = endpoint_info->mpls_exp;
  19176                     break;
  19177 
  19178                 case bcmOamBhhVccvGal13:
  19179                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4;
  19180                     msg_sess.priority   = endpoint_info->mpls_exp;
  19181                     break;
  19182 
  19183                 default:
  19184                     return BCM_E_PARAM;
  19185                     break;
  19186                 }
  19187                 break;
  19188 
  19189             case bcmOAMEndpointTypeBhhSection:
  19190                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION;
  19191                 msg_sess.priority   = 0;
  19192                 break;
  19193             case bcmOAMEndpointTypeBhhSectionInnervlan:
  19194                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN;
  19195                 msg_sess.priority   = endpoint_info->inner_pkt_pri;
  19196                 break;
  19197             case bcmOAMEndpointTypeBhhSectionOuterVlan:
  19198                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN;
  19199                 msg_sess.priority   = endpoint_info->pkt_pri;
  19200                 break;
  19201             case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
  19202                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN;
  19203                 msg_sess.priority   = endpoint_info->pkt_pri;
  19204                 break;
  19205 
  19206             default:
  19207                 return BCM_E_PARAM;
  19208             }
  19209 
  19210             /* Pack control message data into DMA buffer */
  19211             buffer     = oc->dma_buffer;
  19212             buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  19213             buffer_len = buffer_ptr - buffer;
  19214 
  19215             /* Send BHH Session Update message to uC */
  19216             rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  19217                     MOS_MSG_SUBCLASS_BHH_SESS_SET,
  19218                     buffer_len, 0,
  19219                     MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
  19220                     &reply_len);
  19221             if (BCM_FAILURE(rv) || (reply_len != 0)) {
  19222                 LOG_ERROR(BSL_LS_BCM_OAM,
  19223                         (BSL_META_U(unit,
  19224                                     "BHH Error: Endpoint destroy (EP=%d) - %s.\n"),
  19225                          endpoint_info->id, bcm_errmsg(rv)));
  19226                 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19227                 return (rv);
  19228             }
  19229         }
  19230 
  19231         if (!is_replace) {
  19232             rv = _bcm_kt2_oam_group_ep_list_add(unit, endpoint_info->group,
  19233                     endpoint_info->id);
  19234         }
  19235         if (BCM_FAILURE(rv)) {
  19236             LOG_ERROR(BSL_LS_BCM_OAM,
  19237                       (BSL_META_U(unit,
  19238                                   "OAM Error: Tx config failed for EP=%d %s.\n"),
  19239                        endpoint_info->id, bcm_errmsg(rv)));
  19240             _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19241             return (rv);
  19242         }
  19243         rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data);
  19244         if (BCM_FAILURE(rv)) {
  19245             LOG_ERROR(BSL_LS_BCM_OAM,
  19246                     (BSL_META_U(unit,
  19247                                 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  19248                                 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv)));
  19249             _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19250             return (rv);
  19251         }
  19252 
  19253         /* hash collision */
  19254         rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
  19255         if (BCM_FAILURE(rv)) {
  19256             LOG_ERROR(BSL_LS_BCM_OAM,
  19257                     (BSL_META_U(unit,
  19258                                 "OAM Error: Hash table insert failed EP=%d %s.\n"),
  19259                      endpoint_info->id, bcm_errmsg(rv)));
  19260             _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  19261             return (rv);
  19262         }
  19263     }
  19264     hash_data->in_use = 1;
  19265 
  19266 #ifdef BCM_WARM_BOOT_SUPPORT
  19267     SOC_CONTROL_LOCK(unit);
  19268     SOC_CONTROL(unit)->scache_dirty = 1;
  19269     SOC_CONTROL_UNLOCK(unit);
  19270 #endif
  19271 
  19272     return (rv);
  19273 }
  19274 
  19275 /*
  19276  * Function:
  19277  *      _bcm_kt2_oam_bhh_hw_init
  19278  * Purpose:
  19279  *      Initialize the HW for BHH packet processing.
  19280  *      Configure:
  19281  *      - Copy to CPU BHH error packets
  19282  *      - CPU COS Queue for BHH packets
  19283  *      - RX DMA channel
  19284  * Parameters:
  19285  *      unit - (IN) Unit number.
  19286  * Returns:
  19287  *      BCM_E_XXX
  19288  * Notes:
  19289  */
  19290 STATIC int
  19291 _bcm_kt2_oam_bhh_hw_init(int unit)
  19292 {
  19293     int rv = BCM_E_NONE;
  19294     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  19295     uint32 val=0;
  19296     int index;
  19297     int ach_error_index;
  19298     int invalid_error_index;
  19299     int bhh_lb_index;
  19300     int cosq_map_size;
  19301     bcm_rx_reasons_t reasons, reasons_mask;
  19302     uint8 int_prio, int_prio_mask;
  19303     uint32 packet_type, packet_type_mask;
  19304     bcm_cos_queue_t cosq;
  19305     bcm_rx_chan_t chan_id;
  19306     int num_cosq = 0;
  19307     int min_cosq, max_cosq;
  19308     int i;
  19309 
  19310     /* Get OAM Control Structure. */
  19311     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  19312 
  19313     _BCM_OAM_LOCK(oc);
  19314 
  19315     /*
  19316      * Send BHH lookup failure packet to CPU
  19317      * Configure CPU_CONTROL_M register
  19318      * Field BHH_SESSION_NOT_FOUND_TO_CPU
  19319      */
  19320     rv = READ_CPU_CONTROL_Mr(unit, &val);
  19321     if(BCM_FAILURE(rv)) {
  19322         LOG_ERROR(BSL_LS_BCM_OAM,
  19323                   (BSL_META_U(unit,
  19324                               "BHH Error:hw init. Read CPU Control Reg %s.\n"),
  19325                    bcm_errmsg(rv)));
  19326         _BCM_OAM_UNLOCK(oc);
  19327         return (rv);
  19328     }
  19329 
  19330     /* Steer lookup failure packet to CPU */
  19331     soc_reg_field_set(unit, CPU_CONTROL_Mr, &val,
  19332                       BHH_SESSION_NOT_FOUND_TO_CPUf, 1);
  19333 
  19334     rv = WRITE_CPU_CONTROL_Mr(unit, val);
  19335     if(BCM_FAILURE(rv)) {
  19336         LOG_ERROR(BSL_LS_BCM_OAM,
  19337                   (BSL_META_U(unit,
  19338                               "BHH Error:hw init. Write CPU_CONTROL_M Reg %s.\n"),
  19339                    bcm_errmsg(rv)));
  19340         _BCM_OAM_UNLOCK(oc);
  19341         return (rv);
  19342     }
  19343 
  19344     /* Set BHH ACH Type in BHH_RX_ACH_TYPE register */
  19345     rv = WRITE_BHH_RX_ACH_TYPEr(unit, SHR_BHH_ACH_CHANNEL_TYPE); 
  19346 
  19347     if(oc->ukernel_not_ready == 0){
  19348         /* 
  19349          * Get COSQ for BHH
  19350          */
  19351         min_cosq = 0;
  19352         for (i = 0; i < SOC_CMCS_NUM(unit); i++) {
  19353             num_cosq = NUM_CPU_ARM_COSQ(unit, i);
  19354             if (i == oc->uc_num + 1) {
  19355                 break;
  19356             }
  19357             min_cosq += num_cosq;
  19358         }
  19359         max_cosq = min_cosq + num_cosq - 1;
  19360 
  19361         if(max_cosq < min_cosq) {
  19362             LOG_ERROR(BSL_LS_BCM_OAM,
  19363                     (BSL_META_U(unit,
  19364                                 "BHH Error: "
  19365                                 "No BHH COS Queue available from uC%d - %s\n"),
  19366                      oc->uc_num, bcm_errmsg(BCM_E_CONFIG)));
  19367             _BCM_OAM_UNLOCK(oc);
  19368             return (BCM_E_CONFIG);
  19369         }
  19370 
  19371         /* check user configured COSq */
  19372         if (oc->cpu_cosq != BHH_COSQ_INVALID) {
  19373             if ((oc->cpu_cosq < min_cosq) ||
  19374                     (oc->cpu_cosq > max_cosq)) {
  19375                 _BCM_OAM_UNLOCK(oc);
  19376                 return (BCM_E_CONFIG);
  19377             }
  19378             min_cosq = max_cosq = oc->cpu_cosq;
  19379         }
  19380 
  19381 
  19382         /*
  19383          * Assign RX DMA channel to CPU COS Queue
  19384          * (This is the RX channel to listen on for BHH packets).
  19385          *
  19386          * DMA channels (12) are assigned 4 per processor:
  19387          * (see /src/bcm/common/rx.c)
  19388          *   channels 0..3  --> PCI host
  19389          *   channels 4..7  --> uController 0
  19390          *   chnanels 8..11 --> uController 1
  19391          *
  19392          * The uControllers designate the 4 local DMA channels as follows:
  19393          *   local channel  0     --> TX
  19394          *   local channel  1..3  --> RX
  19395          *
  19396          * Each uController application needs to use a different
  19397          * RX DMA channel to listen on.
  19398          */
  19399         chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) +
  19400             oc->rx_channel;
  19401 
  19402         for (i = max_cosq; i >= min_cosq; i--) {
  19403             rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
  19404             if(BCM_SUCCESS(rv)) {
  19405                 oc->cpu_cosq = i;
  19406                 break;
  19407             }
  19408         }
  19409 
  19410         if (i < min_cosq) {
  19411             rv = BCM_E_RESOURCE;
  19412             LOG_ERROR(BSL_LS_BCM_OAM,
  19413                     (BSL_META_U(unit,
  19414                                 "BHH Error: hw init."
  19415                                 " queue channel set %s.\n"),
  19416                      bcm_errmsg(rv)));
  19417             _BCM_OAM_UNLOCK(oc);
  19418             return (rv);
  19419         }
  19420 
  19421         /*
  19422          * Direct BHH packets to designated CPU COS Queue...or more accurately
  19423          * BFD error packets.
  19424          *
  19425          * Reasons:
  19426          *   - bcmRxReasonBFD:               BFD error
  19427          *   - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH
  19428          * NOTE:
  19429          *     The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be
  19430          *     used to select different CPU COS queue. Currently,
  19431          *     all priorities are mapped into the same CPU COS Queue.
  19432          */
  19433 
  19434         /* Find available entries in CPU COS queue map table */
  19435         ach_error_index    = -1;   /* COSQ map index for error packets */
  19436         invalid_error_index    = -1;   /* COSQ map index for error packets */
  19437         bhh_lb_index    = -1;   /* COSQ map index for LB packets */
  19438         rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  19439         if(BCM_FAILURE(rv)) {
  19440             LOG_ERROR(BSL_LS_BCM_OAM,
  19441                     (BSL_META_U(unit,
  19442                                 "BHH Error:hw init. cosq maps size %s.\n"),
  19443                      bcm_errmsg(rv)));
  19444             _BCM_OAM_UNLOCK(oc);
  19445             return (rv);
  19446         }
  19447 
  19448         for (index = cosq_map_size-1; index >= 0; index--) { 
  19449             rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  19450                     &reasons, &reasons_mask,
  19451                     &int_prio, &int_prio_mask,
  19452                     &packet_type, &packet_type_mask,
  19453                     &cosq);
  19454             if (rv == BCM_E_NOT_FOUND) {
  19455                 /* Assign first available index  before default entries*/
  19456                 rv = BCM_E_NONE;
  19457                 if (ach_error_index == -1) {
  19458                     ach_error_index = index;
  19459                 } else if (invalid_error_index == -1) {
  19460                     invalid_error_index = index;
  19461                 } else if (bhh_lb_index == -1) {
  19462                     bhh_lb_index = index;
  19463                     break;
  19464                 }
  19465             }
  19466             if (BCM_FAILURE(rv)) {
  19467                 LOG_ERROR(BSL_LS_BCM_OAM,
  19468                         (BSL_META_U(unit,
  19469                                     "BHH Error:hw init. cosq maps get %s.\n"),
  19470                          bcm_errmsg(rv)));
  19471                 _BCM_OAM_UNLOCK(oc);
  19472                 return (rv);
  19473             }
  19474         }
  19475 
  19476         if (ach_error_index == -1 || invalid_error_index == -1) {
  19477             LOG_ERROR(BSL_LS_BCM_OAM,
  19478                     (BSL_META_U(unit,
  19479                                 "BHH Error:hw init. ACH error %s.\n"),
  19480                      bcm_errmsg(rv)));
  19481             _BCM_OAM_UNLOCK(oc);
  19482             return (BCM_E_FULL);
  19483         }
  19484 
  19485         /* Set CPU COS Queue mapping */
  19486         BCM_RX_REASON_CLEAR_ALL(reasons);
  19487         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);         /* BHH Packet     */
  19488         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMCCMSlowpath); /*OAM Slowpath CCM*/
  19489 
  19490         rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index,
  19491                 reasons, reasons,
  19492                 0, 0, /* Any Internal Prio */  
  19493                 0, 0, /* Any packet type   */
  19494                 oc->cpu_cosq);
  19495         if(BCM_FAILURE(rv)) {
  19496             LOG_ERROR(BSL_LS_BCM_OAM,
  19497                     (BSL_META_U(unit,
  19498                                 "BHH Error:hw init. cosq map set %s.\n"),
  19499                      bcm_errmsg(rv)));
  19500             _BCM_OAM_UNLOCK(oc);
  19501             return (rv);
  19502         }
  19503         oc->cpu_cosq_ach_error_index = ach_error_index;
  19504 
  19505 
  19506         BCM_RX_REASON_CLEAR_ALL(reasons);
  19507         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);      /* BHH Packet         */
  19508         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM Slowpath(LB/LBR)*/
  19509 
  19510         rv = bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index,
  19511                 reasons, reasons,
  19512                 0, 0, /* Any Internal Prio */  
  19513                 0, 0, /* Any packet type */
  19514                 oc->cpu_cosq);
  19515         if(BCM_FAILURE(rv)) {
  19516             LOG_ERROR(BSL_LS_BCM_OAM,
  19517                     (BSL_META_U(unit,
  19518                                 "BHH Error:hw init. cosq map set %s.\n"),
  19519                      bcm_errmsg(rv)));
  19520             _BCM_OAM_UNLOCK(oc);
  19521             return (rv);
  19522         }
  19523         oc->cpu_cosq_invalid_error_index = invalid_error_index;
  19524     
  19525         BCM_RX_REASON_CLEAR_ALL(reasons);
  19526         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);      /* BHH Packet     */
  19527         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMSlowpath); /*OAM Slowpath */
  19528 
  19529         rv = bcm_esw_rx_cosq_mapping_set(unit, bhh_lb_index,
  19530                                          reasons, reasons,
  19531                                          0, 0, /* Any Internal Prio */  
  19532                                          0, 0, /* Any packet type   */
  19533                                          oc->cpu_cosq);
  19534         if(BCM_FAILURE(rv)) {
  19535             LOG_ERROR(BSL_LS_BCM_OAM,
  19536                       (BSL_META_U(unit,
  19537                                   "BHH(unit %d) Error:hw init. cosq map set for"
  19538                                   " Loopback %s.\n"),
  19539                        unit, bcm_errmsg(rv)));
  19540             _BCM_OAM_UNLOCK(oc);
  19541             return (rv);
  19542         }
  19543         oc->bhh_lb_index = bhh_lb_index;
  19544     }
  19545 
  19546     _BCM_OAM_UNLOCK(oc);
  19547     return (rv);
  19548 }
  19549 
  19550 /*
  19551  * Function:
  19552  *      _bcm_kt2_oam_bhh_session_hw_delete
  19553  * Purpose:
  19554  *      Delete BHH Session in HW device.
  19555  * Parameters:
  19556  *      unit       - (IN) Unit number.
  19557  *      h_data_p- (IN) Pointer to BHH endpoint structure.
  19558  * Returns:
  19559  *      BCM_E_XXX
  19560  * Notes:
  19561  */
  19562 STATIC int
  19563 _bcm_kt2_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
  19564 {
  19565     int rv = BCM_E_NONE;
  19566 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  19567     mpls_entry_entry_t mpls_entry;
  19568     mpls_entry_entry_t mpls_key;
  19569     int mpls_index = 0;
  19570 #endif /* BCM_KATANA2_SUPPORT &&  BCM_MPLS_SUPPORT */
  19571 
  19572 
  19573     switch(h_data_p->type) {
  19574     case bcmOAMEndpointTypeBHHMPLS:
  19575     case bcmOAMEndpointTypeBHHMPLSVccv:
  19576 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  19577         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
  19578 
  19579         sal_memset(&mpls_key, 0, sizeof(mpls_key));
  19580         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key,
  19581                                     MPLS__MPLS_LABELf, h_data_p->label);
  19582 
  19583         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index,
  19584                                            &mpls_key, &mpls_entry, 0);
  19585         /* It can so happen that this function is called when the switch is
  19586            re-initailizing, then MPLS ENTRY will not be found, as MPLS init 
  19587            happens before OAM init and it would have cleared the MPLS Entry, as 
  19588            such its not an error scenario. Hence dont return failure from here.*/
  19589 
  19590         if (BCM_SUCCESS(rv)) {
  19591             if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0x1)) 
  19592             {
  19593                 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 
  19594                                                         MPLS__BFD_ENABLEf, 0);
  19595                 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 
  19596                         mpls_index, &mpls_entry);
  19597                 if (BCM_FAILURE(rv)) {
  19598                     LOG_ERROR(BSL_LS_BCM_OAM,
  19599                               (BSL_META_U(unit,
  19600                                           "OAM Error: MPLS_ENTRY write failed - "
  19601                                            "%s.\n"), bcm_errmsg(rv)));
  19602                     bcm_tr_mpls_unlock(unit);
  19603                     return (rv);
  19604                 }
  19605             }
  19606         }
  19607         bcm_tr_mpls_unlock (unit);
  19608 #endif /* BCM_KATANA2_SUPPORT &&  BCM_MPLS_SUPPORT */
  19609         break;
  19610 
  19611     default:
  19612         break;
  19613     }
  19614 
  19615     return (rv);
  19616 }
  19617 
  19618 /*
  19619  * Function:
  19620  *      _bcm_kt2_oam_bhh_msg_send_receive
  19621  * Purpose:
  19622  *      Sends given BHH control message to the uController.
  19623  *      Receives and verifies expected reply.
  19624  *      Performs DMA operation if required.
  19625  * Parameters:
  19626  *      unit        - (IN) Unit number.
  19627  *      s_subclass  - (IN) BHH message subclass.
  19628  *      s_len       - (IN) Value for 'len' field in message struct.
  19629  *                         Length of buffer to flush if DMA send is required.
  19630  *      s_data      - (IN) Value for 'data' field in message struct.
  19631  *                         Ignored if message requires a DMA send/receive
  19632  *                         operation.
  19633  *      r_subclass  - (IN) Expected reply message subclass.
  19634  *      r_len       - (OUT) Returns value in 'len' reply message field.
  19635  * Returns:
  19636  *      BCM_E_XXX
  19637  * Notes:
  19638  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  19639  *       can take any arbitrary data.
  19640  *
  19641  *     BHH Long Control message:
  19642  *     - BHH control messages that require send/receive of information
  19643  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  19644  *       use DMA operations to exchange information (long control message).
  19645  *
  19646  *     - BHH convention for long control messages for
  19647  *        'mos_msg_data_t' fields:
  19648  *          'len'    size of the DMA buffer to send to uController
  19649  *          'data'   physical DMA memory address to send or receive
  19650  *
  19651  *      DMA Operations:
  19652  *      - DMA read/write operation is performed when a long BHH control
  19653  *        message is involved.
  19654  *
  19655  *      - Messages that require DMA operation (long control message)
  19656  *        is indicated by MOS_MSG_DMA_MSG().
  19657  *
  19658  *      - Callers must 'pack' and 'unpack' corresponding information
  19659  *        into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer.
  19660  */
  19661 STATIC int
  19662 _bcm_kt2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
  19663                                     uint16 s_len, uint32 s_data,
  19664                                     uint8 r_subclass, uint16 *r_len)
  19665 {
  19666     int rv;
  19667     _bcm_oam_control_t *oc;
  19668     mos_msg_data_t send, reply;
  19669     uint8 *dma_buffer;
  19670     int dma_buffer_len;
  19671     uint32 uc_rv;
  19672 
  19673     /* Lock already taken by the calling routine. */
  19674     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  19675 
  19676     sal_memset(&send, 0, sizeof(send));
  19677     sal_memset(&reply, 0, sizeof(reply));
  19678     send.s.mclass = MOS_MSG_CLASS_BHH;
  19679     send.s.subclass = s_subclass;
  19680     send.s.len = bcm_htons(s_len);
  19681 
  19682     /*
  19683      * Set 'data' to DMA buffer address if a DMA operation is
  19684      * required for send or receive.
  19685      */
  19686     dma_buffer = oc->dma_buffer;
  19687     dma_buffer_len = oc->dma_buffer_len;
  19688     if (MOS_MSG_DMA_MSG(s_subclass) ||
  19689         MOS_MSG_DMA_MSG(r_subclass)) {
  19690         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  19691     } else {
  19692         send.s.data = bcm_htonl(s_data);
  19693     }
  19694 
  19695     /* Flush DMA memory */
  19696     if (MOS_MSG_DMA_MSG(s_subclass)) {
  19697         soc_cm_sflush(unit, dma_buffer, s_len);
  19698     }
  19699 
  19700     /* Invalidate DMA memory to read */
  19701     if (MOS_MSG_DMA_MSG(r_subclass)) {
  19702         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  19703     }
  19704 
  19705     rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num,
  19706                                       &send, &reply,
  19707                                       _BHH_UC_MSG_TIMEOUT_USECS);
  19708 
  19709     /* Check reply class, subclass */
  19710     if ((rv != SOC_E_NONE) ||
  19711         (reply.s.mclass != MOS_MSG_CLASS_BHH) ||
  19712         (reply.s.subclass != r_subclass)) {
  19713         return (BCM_E_INTERNAL);
  19714     }
  19715 
  19716     /* Convert BHH uController error code to BCM */
  19717     uc_rv = bcm_ntohl(reply.s.data);
  19718     switch(uc_rv) {
  19719     case SHR_BHH_UC_E_NONE:
  19720         rv = BCM_E_NONE;
  19721         break;
  19722     case SHR_BHH_UC_E_INTERNAL:
  19723         rv = BCM_E_INTERNAL;
  19724         break;
  19725     case SHR_BHH_UC_E_MEMORY:
  19726         rv = BCM_E_MEMORY;
  19727         break;
  19728     case SHR_BHH_UC_E_PARAM:
  19729         rv = BCM_E_PARAM;
  19730         break;
  19731     case SHR_BHH_UC_E_RESOURCE:
  19732         rv = BCM_E_RESOURCE;
  19733         break;
  19734     case SHR_BHH_UC_E_EXISTS:
  19735         rv = BCM_E_EXISTS;
  19736         break;
  19737     case SHR_BHH_UC_E_NOT_FOUND:
  19738         rv = BCM_E_NOT_FOUND;
  19739         break;
  19740     case SHR_BHH_UC_E_INIT:
  19741         rv = BCM_E_INIT;
  19742         break;
  19743     default:
  19744         rv = BCM_E_INTERNAL;
  19745         break;
  19746     }
  19747         
  19748     *r_len = bcm_ntohs(reply.s.len);
  19749 
  19750     return (rv);
  19751 }
  19752 
  19753 /*
  19754  * Function:
  19755  *      _bcm_kt2_oam_bhh_callback_thread
  19756  * Purpose:
  19757  *      Thread to listen for event messages from uController.
  19758  * Parameters:
  19759  *      param - Pointer to BFD info structure.
  19760  * Returns:
  19761  *      None
  19762  */
  19763 STATIC void
  19764 _bcm_kt2_oam_bhh_callback_thread(void *param)
  19765 {
  19766     int rv;
  19767     _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param;
  19768     bcm_oam_event_types_t events;
  19769     bcm_oam_event_type_t event_type;
  19770     bhh_msg_event_t event_msg;
  19771     int sess_id;
  19772     uint32 event_mask, flags = 0;
  19773     _bcm_oam_event_handler_t *event_handler_p;
  19774     _bcm_oam_hash_data_t *h_data_p;
  19775     int ep_id = 0;
  19776     char thread_name[SAL_THREAD_NAME_MAX_LEN];
  19777 
  19778     thread_name[0] = 0;
  19779     sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name));
  19780 
  19781     while (1) {
  19782         /* Wait on notifications from uController */
  19783         rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num,
  19784                                      MOS_MSG_CLASS_BHH_EVENT, &event_msg,
  19785                                      sal_sem_FOREVER);
  19786 
  19787         if (BCM_FAILURE(rv)) {
  19788             break;  /*  Thread exit */
  19789         }
  19790 
  19791         event_handler_p = oc->event_handler_list_p;
  19792         /* Get data from event message */
  19793         sess_id = (int)bcm_ntohs(event_msg.s.len);
  19794         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id);
  19795 
  19796         if (sess_id < 0 ||
  19797             sess_id >= oc->ep_count) {
  19798             LOG_CLI((BSL_META_U(oc->unit,
  19799                                 "Invalid sess_id:%d \n"), sess_id));
  19800             continue;
  19801         }
  19802         /* Check endpoint status. */
  19803         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  19804         if ((BCM_E_EXISTS != rv)) {
  19805             /* Endpoint not in use. */
  19806             LOG_ERROR(BSL_LS_BCM_OAM,
  19807                       (BSL_META_U(oc->unit,
  19808                                   "OAM Error: Endpoint EP=%d %s.\n"),
  19809                        ep_id, bcm_errmsg(rv)));
  19810         }
  19811         h_data_p = &oc->oam_hash_data[ep_id];
  19812         event_mask = bcm_ntohl(event_msg.s.data);
  19813 
  19814 
  19815         /* Set events */
  19816         sal_memset(&events, 0, sizeof(events));
  19817 
  19818         if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) {
  19819             LOG_DEBUG(BSL_LS_BCM_OAM,
  19820                       (BSL_META_U(oc->unit,
  19821                                   "****** OAM BHH LB Timeout ******\n")));
  19822 
  19823             if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0)
  19824             SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout);
  19825         }
  19826         if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) {
  19827             LOG_DEBUG(BSL_LS_BCM_OAM,
  19828                       (BSL_META_U(oc->unit,
  19829                                   "****** OAM BHH LB Discovery Update ******\n")));
  19830             if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0)
  19831             SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate);
  19832         }
  19833         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) {
  19834             LOG_DEBUG(BSL_LS_BCM_OAM,
  19835                       (BSL_META_U(oc->unit,
  19836                                   "****** OAM BHH CCM Timeout ******\n")));
  19837             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0)
  19838             SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout);
  19839         }
  19840         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) {
  19841             LOG_DEBUG(BSL_LS_BCM_OAM,
  19842                       (BSL_META_U(oc->unit,
  19843                                   "****** OAM BHH CCM Timeout Clear ******\n")));
  19844             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0)
  19845             SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear);
  19846         }
  19847         if (event_mask & BHH_BTE_EVENT_STATE) {
  19848             LOG_DEBUG(BSL_LS_BCM_OAM,
  19849                       (BSL_META_U(oc->unit,
  19850                                   "****** OAM BHH State ******\n")));
  19851             if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0)
  19852             SHR_BITSET(events.w, bcmOAMEventBHHCCMState);
  19853         }
  19854 
  19855         if (event_mask & BHH_BTE_EVENT_CCM_RDI) {
  19856             LOG_DEBUG(BSL_LS_BCM_OAM,
  19857                       (BSL_META_U(oc->unit,
  19858                                   "****** OAM BHH CCM RDI ******\n")));
  19859             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0)
  19860             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi);
  19861         }
  19862         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) {
  19863             LOG_DEBUG(BSL_LS_BCM_OAM,
  19864                       (BSL_META_U(oc->unit,
  19865                                   "****** OAM BHH CCM  Unknown MEG LEVEL ******\n")));
  19866             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0)
  19867             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel);
  19868         }
  19869         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) {
  19870             LOG_DEBUG(BSL_LS_BCM_OAM,
  19871                       (BSL_META_U(oc->unit,
  19872                                   "****** OAM BHH CCM  Unknown MEG ID ******\n")));
  19873             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0)
  19874             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId);
  19875         }
  19876         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) {
  19877             LOG_DEBUG(BSL_LS_BCM_OAM,
  19878                       (BSL_META_U(oc->unit,
  19879                                   "****** OAM BHH CCM  Unknown MEP ID ******\n")));
  19880             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0)
  19881             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId);
  19882         }
  19883         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) {
  19884             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0)
  19885             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod);
  19886         }
  19887         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) {
  19888             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0)
  19889             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority);
  19890         }
  19891         if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) {
  19892             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0)
  19893             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear);
  19894         }
  19895         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) {
  19896             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0)
  19897             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear);
  19898         }
  19899         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) {
  19900             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0)
  19901             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear);
  19902         }
  19903         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) {
  19904             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0)
  19905             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear);
  19906         }
  19907         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) {
  19908             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0)
  19909             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear);
  19910         }
  19911         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) {
  19912             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0)
  19913             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear);
  19914         }
  19915         if (event_mask & BHH_BTE_EVENT_CSF_LOS) {
  19916             if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) {
  19917                 SHR_BITSET(events.w, bcmOAMEventCsfLos);
  19918             }
  19919         }
  19920         if (event_mask & BHH_BTE_EVENT_CSF_FDI) {
  19921             if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) {
  19922                 SHR_BITSET(events.w, bcmOAMEventCsfFdi);
  19923             }
  19924         }
  19925         if (event_mask & BHH_BTE_EVENT_CSF_RDI) {
  19926             if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) {
  19927                 SHR_BITSET(events.w, bcmOAMEventCsfRdi);
  19928             }
  19929         }
  19930         if (event_mask & BHH_BTE_EVENT_CSF_DCI) {
  19931             if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) {
  19932                 SHR_BITSET(events.w, bcmOAMEventCsfDci);
  19933             }
  19934         }
  19935         if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
  19936             LOG_DEBUG(BSL_LS_BCM_OAM,
  19937                     (BSL_META_U(oc->unit,
  19938                                 "****** OAM PM BHH Counter Rollover ******\n")));
  19939 
  19940             if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) {
  19941                 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover);
  19942             }
  19943         }
  19944         /* Loop over registered callbacks,
  19945          * If any match the events field, then invoke
  19946          */
  19947         for (event_handler_p = oc->event_handler_list_p;
  19948              event_handler_p != NULL;
  19949              event_handler_p = event_handler_p->next_p) {
  19950             for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) {
  19951                 if (SHR_BITGET(events.w, event_type)) {
  19952                     if (SHR_BITGET(event_handler_p->event_types.w,
  19953                                    event_type)) {
  19954                         event_handler_p->cb(oc->unit,
  19955                                         flags,
  19956                                         event_type,
  19957                                         h_data_p->group_index, /* Group index */
  19958                                         ep_id, /* Endpoint index */
  19959                                         event_handler_p->user_data);
  19960                     }
  19961                 }
  19962             }
  19963         }
  19964     }
  19965 
  19966     oc->event_thread_id = NULL;
  19967     LOG_VERBOSE(BSL_LS_BCM_OAM,
  19968               (BSL_META_U(oc->unit,
  19969                           "Thread Exit:%s\n"), thread_name));
  19970     sal_thread_exit(0);
  19971 }
  19972 
  19973 /* BHH Event Handler */
  19974 typedef struct _event_handler_s {
  19975     struct _event_handler_s *next;
  19976     bcm_oam_event_types_t event_types;
  19977     bcm_oam_event_cb cb;
  19978     void *user_data;
  19979 } _event_handler_t;
  19980 
  19981 /*
  19982  * Function:
  19983  *      _bcm_kt2_oam_bhh_event_mask_set
  19984  * Purpose:
  19985  *      Set the BHH Events mask.
  19986  *      Events are set per BHH module.
  19987  * Parameters:
  19988  *      unit        - (IN) Unit number.
  19989  * Returns:
  19990  *      BCM_E_NONE Operation completed successfully
  19991  *      BCM_E_XXX  Operation failed
  19992  * Notes:
  19993  */
  19994 STATIC int
  19995 _bcm_kt2_oam_bhh_event_mask_set(int unit)
  19996 {
  19997     _bcm_oam_control_t *oc;
  19998     _bcm_oam_event_handler_t *event_handler_p;
  19999     uint32 event_mask = 0;
  20000     uint16 reply_len;
  20001     int rv = BCM_E_NONE;
  20002 
  20003     /* Lock already taken by the calling routine. */
  20004     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20005 
  20006     /* Get event mask from all callbacks */
  20007     for (event_handler_p = oc->event_handler_list_p;
  20008          event_handler_p != NULL;
  20009          event_handler_p = event_handler_p->next_p) {
  20010 
  20011         if (SHR_BITGET(event_handler_p->event_types.w,
  20012                        bcmOAMEventBHHLBTimeout)) {
  20013             event_mask |= BHH_BTE_EVENT_LB_TIMEOUT;
  20014         }
  20015         if (SHR_BITGET(event_handler_p->event_types.w,
  20016                        bcmOAMEventBHHLBDiscoveryUpdate)) {
  20017             event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE;
  20018         }
  20019         if (SHR_BITGET(event_handler_p->event_types.w,
  20020                        bcmOAMEventBHHCCMTimeout)) {
  20021             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT;
  20022         }
  20023         if (SHR_BITGET(event_handler_p->event_types.w,
  20024                        bcmOAMEventBHHCCMTimeoutClear)) {
  20025             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR;
  20026         }
  20027         if (SHR_BITGET(event_handler_p->event_types.w,
  20028                        bcmOAMEventBHHCCMState)) {
  20029             event_mask |= BHH_BTE_EVENT_STATE;
  20030         }
  20031         if (SHR_BITGET(event_handler_p->event_types.w,
  20032                        bcmOAMEventBHHCCMRdi)) {
  20033             event_mask |= BHH_BTE_EVENT_CCM_RDI;
  20034         }
  20035         if (SHR_BITGET(event_handler_p->event_types.w,
  20036                        bcmOAMEventBHHCCMUnknownMegLevel)) {
  20037             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL;
  20038         }
  20039         if (SHR_BITGET(event_handler_p->event_types.w,
  20040                        bcmOAMEventBHHCCMUnknownMegId)) {
  20041             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID;
  20042         }
  20043         if (SHR_BITGET(event_handler_p->event_types.w,
  20044                        bcmOAMEventBHHCCMUnknownMepId)) {
  20045             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID;
  20046         }
  20047         if (SHR_BITGET(event_handler_p->event_types.w,
  20048                        bcmOAMEventBHHCCMUnknownPeriod)) {
  20049             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD;
  20050         }
  20051         if (SHR_BITGET(event_handler_p->event_types.w,
  20052                        bcmOAMEventBHHCCMUnknownPriority)) {
  20053             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY;
  20054         }
  20055         if (SHR_BITGET(event_handler_p->event_types.w,
  20056                        bcmOAMEventBHHCCMRdiClear)) {
  20057             event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR;
  20058         }
  20059         if (SHR_BITGET(event_handler_p->event_types.w,
  20060                        bcmOAMEventBHHCCMUnknownMegLevelClear)) {
  20061             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR;
  20062         }
  20063         if (SHR_BITGET(event_handler_p->event_types.w,
  20064                        bcmOAMEventBHHCCMUnknownMegIdClear)) {
  20065             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR;
  20066         }
  20067         if (SHR_BITGET(event_handler_p->event_types.w,
  20068                        bcmOAMEventBHHCCMUnknownMepIdClear)) {
  20069             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR;
  20070         }
  20071         if (SHR_BITGET(event_handler_p->event_types.w,
  20072                        bcmOAMEventBHHCCMUnknownPeriodClear)) {
  20073             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR;
  20074         }
  20075         if (SHR_BITGET(event_handler_p->event_types.w,
  20076                        bcmOAMEventBHHCCMUnknownPriorityClear)) {
  20077             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR;
  20078         }
  20079         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) {
  20080             event_mask |= BHH_BTE_EVENT_CSF_LOS;
  20081         }
  20082         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) {
  20083             event_mask |= BHH_BTE_EVENT_CSF_FDI;
  20084         }
  20085         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) {
  20086             event_mask |= BHH_BTE_EVENT_CSF_RDI;
  20087         }
  20088         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) {
  20089             event_mask |= BHH_BTE_EVENT_CSF_DCI;
  20090         }
  20091         if (SHR_BITGET(event_handler_p->event_types.w,
  20092                     bcmOAMEventBhhPmCounterRollover)) {
  20093             event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER;
  20094         }
  20095     }
  20096 
  20097     /* Update BHH event mask in uKernel */
  20098     if (event_mask != oc->event_mask) {
  20099         /* Send BHH Event Mask message to uC */
  20100         rv = _bcm_kt2_oam_bhh_msg_send_receive
  20101                 (unit,
  20102                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET,
  20103                  0, event_mask,
  20104                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY,
  20105                  &reply_len);
  20106 
  20107         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  20108             rv = BCM_E_INTERNAL;
  20109         }
  20110     }
  20111 
  20112     oc->event_mask = event_mask;
  20113 
  20114     return (rv);
  20115 }
  20116 
  20117 /*
  20118  * Function:
  20119  *     bcm_kt2_oam_loopback_add
  20120  * Purpose:
  20121  *     
  20122  * Parameters:
  20123  *     unit - Device unit number
  20124  * Returns:
  20125  *     None
  20126  */
  20127 int
  20128 bcm_kt2_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p)
  20129 {
  20130     _bcm_oam_control_t *oc;
  20131     _bcm_oam_hash_data_t *h_data_p;
  20132     int rv = BCM_E_NONE;
  20133     bhh_sdk_msg_ctrl_loopback_add_t msg;
  20134     uint8 *buffer, *buffer_ptr;
  20135     uint16 buffer_len, reply_len;
  20136     uint32 flags = 0;
  20137     int sess_id = 0;
  20138 
  20139     /* Get OAM Control Structure. */
  20140     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20141     _BCM_OAM_LOCK(oc);
  20142 
  20143     if (oc->ukernel_not_ready) {
  20144         _BCM_OAM_UNLOCK(oc);
  20145         return BCM_E_INIT;
  20146     }
  20147 
  20148 
  20149     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  20150 
  20151     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  20152 
  20153     /* Check endpoint status. */
  20154     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20155     if ((BCM_E_EXISTS != rv)) {
  20156         /* Endpoint not in use. */
  20157         LOG_ERROR(BSL_LS_BCM_OAM,
  20158                   (BSL_META_U(unit,
  20159                               "OAM Error: Endpoint EP=%d %s.\n"),
  20160                    loopback_p->id, bcm_errmsg(rv)));
  20161         _BCM_OAM_UNLOCK(oc);
  20162         return (rv);
  20163     }
  20164 
  20165     h_data_p = &oc->oam_hash_data[loopback_p->id];
  20166     if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  20167         _BCM_OAM_UNLOCK(oc);
  20168         return BCM_E_PARAM;
  20169     }
  20170 
  20171 
  20172     /*
  20173      * Only BHH is supported
  20174      */
  20175     if (BHH_EP_TYPE(h_data_p)) {
  20176 
  20177         /*
  20178          * Convert host space flags to uKernel space flags
  20179          */
  20180 
  20181         if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) {
  20182             flags |= BCM_BHH_TX_ENABLE;
  20183         }
  20184 
  20185         if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) {
  20186             flags |= BCM_BHH_INC_REQUESTING_MEP_TLV;
  20187         }
  20188 
  20189         if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  20190             flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  20191         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  20192             flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  20193         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) {
  20194             flags |= BCM_BHH_LBM_ICC_MEP_TLV;
  20195         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) {
  20196             flags |= BCM_BHH_LBM_ICC_MIP_TLV;
  20197         } else {
  20198             flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */
  20199         }
  20200 
  20201         if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) {
  20202             flags |= BCM_BHH_LBR_ICC_MEP_TLV;
  20203         } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) {
  20204             flags |= BCM_BHH_LBR_ICC_MIP_TLV;
  20205         }
  20206 
  20207         sal_memset(&msg, 0, sizeof(msg));
  20208         msg.flags   = flags;
  20209         msg.sess_id = sess_id;
  20210         msg.int_pri = loopback_p->int_pri;
  20211         msg.pkt_pri = loopback_p->pkt_pri;
  20212 
  20213         /*
  20214          * Set period
  20215          */
  20216         msg.period  = _kt2_ccm_intervals[
  20217                              _bcm_kt2_oam_ccm_msecs_to_hw_encode(
  20218                                                          loopback_p->period)];
  20219 
  20220         /*
  20221          * Check TTL
  20222          */
  20223         if (loopback_p->ttl == 0 || loopback_p->ttl > 255) {
  20224             _BCM_OAM_UNLOCK(oc);
  20225             return BCM_E_PARAM;
  20226         }
  20227 
  20228         if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) ||
  20229             (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  20230              h_data_p->vccv_type == bcmOamBhhVccvTtl)) {
  20231 
  20232             msg.ttl = 1; /* Only TTL 1 is valid */
  20233         } else {
  20234             msg.ttl = loopback_p->ttl;
  20235         }
  20236 
  20237         /* Pack control message data into DMA buffer */
  20238         buffer     = oc->dma_buffer;
  20239         buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg);
  20240         buffer_len = buffer_ptr - buffer;
  20241 
  20242         /* Send BHH Session Update message to uC */
  20243         rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20244                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD,
  20245                                          buffer_len, 0,
  20246                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY,
  20247                                          &reply_len);
  20248 
  20249         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  20250             rv =  BCM_E_INTERNAL;
  20251         }
  20252     }
  20253     else {
  20254         rv =  BCM_E_UNAVAIL;
  20255     }
  20256 
  20257     _BCM_OAM_UNLOCK(oc);
  20258     return (rv);
  20259 }
  20260 
  20261 /*
  20262  * Function:
  20263  *     bcm_kt2_oam_loopback_get
  20264  * Purpose:
  20265  *     
  20266  * Parameters:
  20267  *     unit - Device unit number
  20268  * Returns:
  20269  *     None
  20270  */
  20271 int
  20272 bcm_kt2_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p)
  20273 {
  20274     _bcm_oam_control_t *oc;
  20275     int rv = BCM_E_NONE;
  20276     bhh_sdk_msg_ctrl_loopback_get_t msg;
  20277     _bcm_oam_hash_data_t *h_data_p;
  20278     uint8 *buffer, *buffer_ptr;
  20279     uint16 buffer_len, reply_len;
  20280     int sess_id = 0;
  20281 
  20282     /* Get OAM Control Structure. */
  20283     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20284     _BCM_OAM_LOCK(oc);
  20285 
  20286     if (oc->ukernel_not_ready) {
  20287         _BCM_OAM_UNLOCK(oc);
  20288         return BCM_E_INIT;
  20289     }
  20290 
  20291 
  20292     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  20293 
  20294     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  20295 
  20296     /* Check endpoint status. */
  20297     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20298     if ((BCM_E_EXISTS != rv)) {
  20299         /* Endpoint not in use. */
  20300         LOG_ERROR(BSL_LS_BCM_OAM,
  20301                   (BSL_META_U(unit,
  20302                               "OAM Error: Endpoint EP=%d %s.\n"),
  20303                    loopback_p->id, bcm_errmsg(rv)));
  20304         _BCM_OAM_UNLOCK(oc);
  20305         return (rv);
  20306     }
  20307 
  20308     h_data_p = &oc->oam_hash_data[loopback_p->id];
  20309 
  20310     /*
  20311      * Only BHH is supported
  20312      */
  20313     if(BHH_EP_TYPE(h_data_p)) {
  20314 
  20315         sal_memset(&msg, 0, sizeof(msg));
  20316         /* Send BHH Session Update message to uC */
  20317         rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20318                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET,
  20319                                         sess_id, 0,
  20320                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY,
  20321                                         &reply_len);
  20322         if(BCM_FAILURE(rv)) {
  20323             LOG_ERROR(BSL_LS_BCM_OAM,
  20324                       (BSL_META_U(unit,
  20325                                   "OAM Error: Endpoint EP=%d %s.\n"),
  20326                        loopback_p->id, bcm_errmsg(rv)));
  20327             _BCM_OAM_UNLOCK(oc);
  20328             return (rv);
  20329         }
  20330 
  20331         /* Pack control message data into DMA buffer */
  20332         buffer     = oc->dma_buffer;
  20333         buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg);
  20334         buffer_len = buffer_ptr - buffer;
  20335 
  20336 
  20337         if (reply_len != buffer_len) {
  20338             rv =  BCM_E_INTERNAL;
  20339         } else {
  20340             /*
  20341              * Convert kernel space flags to host space flags
  20342              */
  20343             if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) {
  20344                 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV;
  20345             }
  20346 
  20347             if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  20348                 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  20349             } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  20350                 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  20351             } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) {
  20352                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV;
  20353             } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) {
  20354                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV;
  20355             }
  20356 
  20357             if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) {
  20358                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV;
  20359             } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) {
  20360                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV;
  20361             }
  20362 
  20363             if (msg.flags & BCM_BHH_TX_ENABLE) {
  20364                 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE;
  20365             }
  20366 
  20367             loopback_p->period                  = msg.period;
  20368             loopback_p->ttl                     = msg.ttl;
  20369             loopback_p->discovered_me.flags     = msg.discovery_flags;
  20370             loopback_p->discovered_me.name      = msg.discovery_id;
  20371             loopback_p->discovered_me.ttl       = msg.discovery_ttl;
  20372             loopback_p->rx_count                = msg.rx_count;
  20373             loopback_p->tx_count                = msg.tx_count;
  20374             loopback_p->drop_count              = msg.drop_count;
  20375             loopback_p->unexpected_response     = msg.unexpected_response;
  20376             loopback_p->out_of_sequence         = msg.out_of_sequence;
  20377             loopback_p->local_mipid_missmatch   = msg.local_mipid_missmatch;
  20378             loopback_p->remote_mipid_missmatch  = msg.remote_mipid_missmatch;
  20379             loopback_p->invalid_target_mep_tlv  = msg.invalid_target_mep_tlv;
  20380             loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype;
  20381             loopback_p->invalid_tlv_offset      = msg.invalid_tlv_offset;
  20382             loopback_p->int_pri                 = msg.int_pri;
  20383             loopback_p->pkt_pri                 = msg.pkt_pri;
  20384 
  20385             rv = BCM_E_NONE;
  20386         }
  20387     }
  20388     else {
  20389         rv = BCM_E_UNAVAIL;
  20390     }
  20391 
  20392     _BCM_OAM_UNLOCK(oc);
  20393 
  20394     return (rv);
  20395 }
  20396 
  20397 /*
  20398  * Function:
  20399  *     bcm_kt2_oam_loopback_delete
  20400  * Purpose:
  20401  *     
  20402  * Parameters:
  20403  *     unit - Device unit number
  20404  * Returns:
  20405  *     None
  20406  */
  20407 int
  20408 bcm_kt2_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p)
  20409 {
  20410     _bcm_oam_control_t *oc;
  20411     int rv = BCM_E_NONE;
  20412     shr_bhh_msg_ctrl_loopback_delete_t msg;
  20413     uint8 *buffer, *buffer_ptr;
  20414     uint16 buffer_len, reply_len;
  20415     int sess_id = 0;
  20416     _bcm_oam_hash_data_t *h_data_p;
  20417 
  20418     /* Get OAM Control Structure. */
  20419     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20420     _BCM_OAM_LOCK(oc);
  20421 
  20422     if (oc->ukernel_not_ready) {
  20423         _BCM_OAM_UNLOCK(oc);
  20424         return BCM_E_INIT;
  20425     }
  20426 
  20427 
  20428     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  20429 
  20430     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  20431 
  20432     /* Check endpoint status. */
  20433     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20434     if ((BCM_E_EXISTS != rv)) {
  20435         /* Endpoint not in use. */
  20436         LOG_ERROR(BSL_LS_BCM_OAM,
  20437                   (BSL_META_U(unit,
  20438                               "OAM Error: Endpoint EP=%d %s.\n"),
  20439                    loopback_p->id, bcm_errmsg(rv)));
  20440         _BCM_OAM_UNLOCK(oc);
  20441         return (rv);
  20442     }
  20443 
  20444     h_data_p = &oc->oam_hash_data[loopback_p->id];
  20445 
  20446     /*
  20447      * Only BHH is supported
  20448      */
  20449     if(BHH_EP_TYPE(h_data_p)) {
  20450 
  20451         msg.sess_id = sess_id;
  20452 
  20453         /* Pack control message data into DMA buffer */
  20454         buffer     = oc->dma_buffer;
  20455         buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg);
  20456         buffer_len = buffer_ptr - buffer;
  20457 
  20458         /* Send BHH Session Update message to uC */
  20459         rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20460                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE,
  20461                       buffer_len, 0,
  20462                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY,
  20463                       &reply_len);
  20464 
  20465         if(BCM_SUCCESS(rv) && (reply_len != 0))
  20466             rv =  BCM_E_INTERNAL;
  20467     }
  20468     else {
  20469         _BCM_OAM_UNLOCK(oc);
  20470         return BCM_E_UNAVAIL;
  20471     }
  20472 
  20473     _BCM_OAM_UNLOCK(oc);
  20474 
  20475     return (rv);
  20476 }
  20477 
  20478 /*
  20479  * Function:
  20480  *     bcm_kt2_oam_loss_add
  20481  * Purpose:
  20482  *        Loss Measurement add     
  20483  * Parameters:
  20484  *     unit - Device unit number
  20485  * Returns:
  20486  *     None
  20487  */
  20488 int
  20489 bcm_kt2_oam_loss_add(int unit, bcm_oam_loss_t *loss_p)
  20490 {
  20491     _bcm_oam_control_t *oc;
  20492     _bcm_oam_hash_data_t *h_data_p;
  20493     int rv = BCM_E_NONE;
  20494     bhh_sdk_msg_ctrl_loss_add_t msg;
  20495     uint8 *buffer, *buffer_ptr;
  20496     uint16 buffer_len, reply_len;
  20497     uint32 flags = 0;
  20498     int sess_id = 0;
  20499 
  20500     /* Get OAM Control Structure. */
  20501     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20502     _BCM_OAM_LOCK(oc);
  20503 
  20504     if (oc->ukernel_not_ready) {
  20505         _BCM_OAM_UNLOCK(oc);
  20506         return BCM_E_INIT;
  20507     }
  20508 
  20509 
  20510     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  20511 
  20512     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  20513 
  20514     /* Check endpoint status. */
  20515     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20516     if ((BCM_E_EXISTS != rv)) {
  20517         /* Endpoint not in use. */
  20518         LOG_ERROR(BSL_LS_BCM_OAM,
  20519                   (BSL_META_U(unit,
  20520                               "OAM Error: Endpoint EP=%d %s.\n"),
  20521                    loss_p->id, bcm_errmsg(rv)));
  20522         _BCM_OAM_UNLOCK(oc);
  20523         return (rv);
  20524     }
  20525 
  20526     h_data_p = &oc->oam_hash_data[loss_p->id];
  20527     if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  20528         _BCM_OAM_UNLOCK(oc);
  20529         return BCM_E_PARAM;
  20530     }
  20531 
  20532     /*
  20533      * Only BHH is supported
  20534      */
  20535     if(BHH_EP_TYPE(h_data_p)) {
  20536 
  20537 	/*
  20538 	 * Convert host space flags to uKernel space flags
  20539 	 */
  20540 	if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED)
  20541 	    flags |= BCM_BHH_LM_SINGLE_ENDED;
  20542 
  20543 	if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)
  20544 	    flags |= BCM_BHH_LM_TX_ENABLE;
  20545 
  20546         sal_memset(&msg, 0, sizeof(msg));
  20547 	msg.flags   = flags;
  20548 	msg.sess_id = sess_id;
  20549 
  20550 	/*
  20551 	 * Set period
  20552 	 */
  20553 	msg.period  = _kt2_ccm_intervals[_bcm_kt2_oam_ccm_msecs_to_hw_encode(loss_p->period)];
  20554     msg.int_pri = loss_p->int_pri;
  20555     msg.pkt_pri = loss_p->pkt_pri;
  20556 
  20557     /* Pack control message data into DMA buffer */
  20558     buffer     = oc->dma_buffer;
  20559     buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg);
  20560     buffer_len = buffer_ptr - buffer;
  20561 
  20562     /* Send BHH Session Update message to uC */
  20563     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20564                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD,
  20565                       buffer_len, 0,
  20566                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY,
  20567                       &reply_len);
  20568 
  20569     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
  20570         rv =  BCM_E_INTERNAL;
  20571     }
  20572     else {
  20573         _BCM_OAM_UNLOCK(oc);
  20574         return BCM_E_UNAVAIL;
  20575     }
  20576 
  20577     _BCM_OAM_UNLOCK(oc);
  20578     return (rv);
  20579 }
  20580 
  20581 int
  20582 bcm_kt2_oam_bhh_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns)
  20583 {
  20584     int rv = BCM_E_NONE;
  20585 
  20586     if (bts != NULL) {
  20587         /* if both seconds and nanoseconds are negative or both positive,
  20588          * then the ucode's subtraction is ok.
  20589          * if seconds and nanoseconds have different signs, then "borrow"
  20590          * 1000000000 nanoseconds from seconds.
  20591          */
  20592         if ((sec < 0) && (ns > 0)) {
  20593             ns -= 1000000000;
  20594             sec += 1;
  20595         } else if ((sec > 0) && (ns < 0)) {
  20596             ns += 1000000000;
  20597             sec -= 1;
  20598         }
  20599 
  20600         if (ns < 0) {
  20601             /* if still negative, then something else is wrong.
  20602              * the nanoseconds field is the difference between two
  20603              * (non-negative) time-stamps.
  20604              */
  20605             rv = BCM_E_INTERNAL;
  20606         }
  20607 
  20608         /* if seconds is negative then set the bts is-negative flag,
  20609          * and use the absolute value of seconds & nanoseconds.
  20610          */
  20611         bts->isnegative  = (sec < 0 ? 1 : 0);
  20612         bts->seconds     = BCM_OAM_BHH_ABS(sec);
  20613         bts->nanoseconds = BCM_OAM_BHH_ABS(ns);
  20614     } else {
  20615         rv = BCM_E_INTERNAL;
  20616     }
  20617 
  20618     return rv;
  20619 }
  20620 
  20621 #ifdef _KATANA2_DEBUG
  20622 /* d (difference) = m (minuend) - s (subtrahend) */
  20623 int
  20624 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s)
  20625 {
  20626     int rv = BCM_E_NONE;
  20627     int32 d_ns = 0;
  20628     int32 d_s = 0;
  20629 
  20630     if ((d != NULL) && (m != NULL) && (s != NULL)) {
  20631         /* subtract the nanoseconds first, then borrow is necessary. */
  20632         d_ns = m->nanoseconds - s->nanoseconds;
  20633         if (d_ns < 0) {
  20634             m->seconds = m->seconds - 1;
  20635             d_ns = 1000000000 + d_ns;
  20636         }
  20637         if (d_ns < 0) {
  20638             /* if still negative, then error */
  20639             rv = BCM_E_INTERNAL;
  20640             d_ns = abs(d_ns);
  20641         }
  20642         d->nanoseconds = d_ns;
  20643 
  20644         /* subtract the seconds next, check for negative. */
  20645         d_s = m->seconds - s->seconds;
  20646         if (d_s < 0) {
  20647             d->isnegative = TRUE;
  20648             d_s = abs(d_s);
  20649         } else {
  20650             d->isnegative = FALSE;
  20651         }
  20652         d->seconds = d_s;
  20653 
  20654     } else {
  20655         rv = BCM_E_INTERNAL;
  20656     }
  20657 
  20658     return rv;
  20659 }
  20660 #endif
  20661 
  20662 /*
  20663  * Function:
  20664  *     bcm_kt2_oam_loss_get
  20665  * Purpose:
  20666  *     Loss Measurement get
  20667  * Parameters:
  20668  *     unit - Device unit number
  20669  * Returns:
  20670  *     None
  20671  */
  20672 int
  20673 bcm_kt2_oam_loss_get(int unit, bcm_oam_loss_t *loss_p)
  20674 {
  20675     _bcm_oam_control_t *oc;
  20676     int rv = BCM_E_NONE;
  20677     bhh_sdk_msg_ctrl_loss_get_t msg;
  20678     _bcm_oam_hash_data_t *h_data_p;
  20679     uint8 *buffer, *buffer_ptr;
  20680     uint16 buffer_len, reply_len;
  20681     int sess_id = 0;
  20682 
  20683     /* Get OAM Control Structure. */
  20684     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20685     _BCM_OAM_LOCK(oc);
  20686 
  20687     if (oc->ukernel_not_ready) {
  20688         _BCM_OAM_UNLOCK(oc);
  20689         return BCM_E_INIT;
  20690     }
  20691 
  20692     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  20693 
  20694     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  20695 
  20696     /* Check endpoint status. */
  20697     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20698     if ((BCM_E_EXISTS != rv)) {
  20699         /* Endpoint not in use. */
  20700         LOG_ERROR(BSL_LS_BCM_OAM,
  20701                   (BSL_META_U(unit,
  20702                               "OAM Error: Endpoint EP=%d %s.\n"),
  20703                    loss_p->id, bcm_errmsg(rv)));
  20704         _BCM_OAM_UNLOCK(oc);
  20705         return (rv);
  20706     }
  20707 
  20708     h_data_p = &oc->oam_hash_data[loss_p->id];
  20709 
  20710     /*
  20711      * Only BHH is supported
  20712      */
  20713     if(BHH_EP_TYPE(h_data_p)) {
  20714 
  20715     sal_memset(&msg, 0, sizeof(msg));
  20716     /* Send BHH Session Update message to uC */
  20717     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20718                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET,
  20719                       sess_id, 0,
  20720                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY,
  20721                       &reply_len);
  20722     if(BCM_FAILURE(rv)) {
  20723         LOG_ERROR(BSL_LS_BCM_OAM,
  20724                   (BSL_META_U(unit,
  20725                               "OAM Error: Endpoint EP=%d %s.\n"),
  20726                    loss_p->id, bcm_errmsg(rv)));
  20727         _BCM_OAM_UNLOCK(oc);
  20728         return (rv);
  20729     }
  20730 
  20731     /* Pack control message data into DMA buffer */
  20732     buffer     = oc->dma_buffer;
  20733     buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg);
  20734     buffer_len = buffer_ptr - buffer;
  20735 
  20736     if (reply_len != buffer_len) {
  20737         rv =  BCM_E_INTERNAL;
  20738     } else {
  20739         /*
  20740          * Convert kernel space flags to host space flags
  20741          */
  20742         if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) {
  20743             loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
  20744         }
  20745 
  20746         if (msg.flags & BCM_BHH_LM_TX_ENABLE) {
  20747             loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  20748         }
  20749 
  20750         if (msg.flags & BCM_BHH_LM_SLM) {
  20751             loss_p->flags |= BCM_OAM_LOSS_SLM;
  20752         }
  20753 
  20754         loss_p->period = msg.period;
  20755         loss_p->loss_threshold = msg.loss_threshold;             
  20756         loss_p->loss_nearend = msg.loss_nearend;               
  20757         loss_p->loss_farend = msg.loss_farend;    
  20758         loss_p->tx_nearend = msg.tx_nearend;            
  20759         loss_p->rx_nearend = msg.rx_nearend;              
  20760         loss_p->tx_farend = msg.tx_farend;               
  20761         loss_p->rx_farend = msg.rx_farend;               
  20762         loss_p->rx_oam_packets = msg.rx_oam_packets;          
  20763         loss_p->tx_oam_packets = msg.tx_oam_packets;          
  20764         loss_p->int_pri = msg.int_pri;
  20765         loss_p->pkt_pri = msg.pkt_pri;         
  20766 
  20767         rv = BCM_E_NONE;
  20768     }
  20769     }
  20770     else {
  20771         _BCM_OAM_UNLOCK(oc);
  20772         return BCM_E_UNAVAIL;
  20773     }
  20774 
  20775     _BCM_OAM_UNLOCK(oc);
  20776 
  20777     return (rv);
  20778 }
  20779 
  20780 /*
  20781  * Function:
  20782  *     bcm_kt2_oam_loss_delete
  20783  * Purpose:
  20784  *    Loss Measurement Delete 
  20785  * Parameters:
  20786  *     unit - Device unit number
  20787  * Returns:
  20788  *     None
  20789  */
  20790 int
  20791 bcm_kt2_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p)
  20792 {
  20793     _bcm_oam_control_t *oc;
  20794     int rv = BCM_E_NONE;
  20795     shr_bhh_msg_ctrl_loss_delete_t msg;
  20796     uint8 *buffer, *buffer_ptr;
  20797     uint16 buffer_len, reply_len;
  20798     int sess_id = 0;
  20799     _bcm_oam_hash_data_t *h_data_p;
  20800 
  20801     /* Get OAM Control Structure. */
  20802     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20803     _BCM_OAM_LOCK(oc);
  20804 
  20805     if (oc->ukernel_not_ready) {
  20806         _BCM_OAM_UNLOCK(oc);
  20807         return BCM_E_INIT;
  20808     }
  20809 
  20810     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  20811 
  20812     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  20813 
  20814     /* Check endpoint status. */
  20815     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20816     if ((BCM_E_EXISTS != rv)) {
  20817         /* Endpoint not in use. */
  20818         LOG_ERROR(BSL_LS_BCM_OAM,
  20819                   (BSL_META_U(unit,
  20820                               "OAM Error: Endpoint EP=%d %s.\n"),
  20821                    loss_p->id, bcm_errmsg(rv)));
  20822         _BCM_OAM_UNLOCK(oc);
  20823         return (rv);
  20824     }
  20825 
  20826     h_data_p = &oc->oam_hash_data[loss_p->id];
  20827 
  20828     /*
  20829      * Only BHH is supported
  20830      */
  20831     if(BHH_EP_TYPE(h_data_p)) {
  20832 
  20833         msg.sess_id = sess_id;
  20834 
  20835         /* Pack control message data into DMA buffer */
  20836         buffer     = oc->dma_buffer;
  20837         buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg);
  20838         buffer_len = buffer_ptr - buffer;
  20839 
  20840         /* Send BHH Session Update message to uC */
  20841         rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20842                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE,
  20843                       buffer_len, 0,
  20844                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY,
  20845                       &reply_len);
  20846 
  20847         if(BCM_SUCCESS(rv) && (reply_len != 0))
  20848             rv =  BCM_E_INTERNAL;
  20849     }
  20850     else {
  20851         _BCM_OAM_UNLOCK(oc);
  20852         return BCM_E_UNAVAIL;
  20853     }
  20854 
  20855     _BCM_OAM_UNLOCK(oc);
  20856 
  20857     return (rv);
  20858 }
  20859 
  20860 /*
  20861  * Function:
  20862  *     bcm_kt2_oam_delay_add
  20863  * Purpose:
  20864  *     Delay Measurement add     
  20865  * Parameters:
  20866  *     unit - Device unit number
  20867  * Returns:
  20868  *     None
  20869  */
  20870 int
  20871 bcm_kt2_oam_delay_add(int unit, bcm_oam_delay_t *delay_p)
  20872 {
  20873     _bcm_oam_control_t *oc;
  20874     _bcm_oam_hash_data_t *h_data_p;
  20875     int rv = BCM_E_NONE;
  20876     bhh_sdk_msg_ctrl_delay_add_t msg;
  20877     uint8 *buffer, *buffer_ptr;
  20878     uint16 buffer_len, reply_len;
  20879     uint32 flags = 0;
  20880     int sess_id = 0;
  20881 
  20882     /* Get OAM Control Structure. */
  20883     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20884     _BCM_OAM_LOCK(oc);
  20885 
  20886     if (oc->ukernel_not_ready) {
  20887         _BCM_OAM_UNLOCK(oc);
  20888         return BCM_E_INIT;
  20889     }
  20890 
  20891 
  20892     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  20893 
  20894     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  20895 
  20896     /* Check endpoint status. */
  20897     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  20898     if ((BCM_E_EXISTS != rv)) {
  20899         /* Endpoint not in use. */
  20900         LOG_ERROR(BSL_LS_BCM_OAM,
  20901                   (BSL_META_U(unit,
  20902                               "OAM Error: Endpoint EP=%d %s.\n"),
  20903                    delay_p->id, bcm_errmsg(rv)));
  20904         _BCM_OAM_UNLOCK(oc);
  20905         return (rv);
  20906     }
  20907 
  20908     h_data_p = &oc->oam_hash_data[delay_p->id];
  20909     if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  20910         _BCM_OAM_UNLOCK(oc);
  20911         return BCM_E_PARAM;
  20912     }
  20913 
  20914     /*
  20915      * Only BHH is supported
  20916      */
  20917     if(BHH_EP_TYPE(h_data_p)) {
  20918 
  20919     /*
  20920      * Convert host space flags to uKernel space flags
  20921      */
  20922     if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY)
  20923         flags |= BCM_BHH_DM_ONE_WAY;
  20924 
  20925     if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)
  20926         flags |= BCM_BHH_DM_TX_ENABLE;
  20927 
  20928     sal_memset(&msg, 0, sizeof(msg));
  20929     msg.flags   = flags;
  20930     msg.sess_id = sess_id;
  20931     msg.int_pri = delay_p->int_pri;
  20932     msg.pkt_pri = delay_p->pkt_pri;
  20933 
  20934     h_data_p->ts_format = delay_p->timestamp_format;
  20935 
  20936     if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1)
  20937         msg.dm_format = BCM_BHH_DM_TYPE_PTP;
  20938     else
  20939         msg.dm_format = BCM_BHH_DM_TYPE_NTP;
  20940 
  20941     /*
  20942      * Set period
  20943      */
  20944     msg.period  = _kt2_ccm_intervals[_bcm_kt2_oam_ccm_msecs_to_hw_encode(delay_p->period)];
  20945 
  20946     /* Pack control message data into DMA buffer */
  20947     buffer     = oc->dma_buffer;
  20948     buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg);
  20949     buffer_len = buffer_ptr - buffer;
  20950 
  20951     /* Send BHH Session Update message to uC */
  20952     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  20953                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD,
  20954                       buffer_len, 0,
  20955                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY,
  20956                       &reply_len);
  20957 
  20958     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
  20959         rv =  BCM_E_INTERNAL;
  20960     }
  20961    else {
  20962         _BCM_OAM_UNLOCK(oc);
  20963         return BCM_E_UNAVAIL;
  20964     }
  20965 
  20966     _BCM_OAM_UNLOCK(oc);
  20967     return (rv);
  20968 }
  20969 
  20970 /*
  20971  * Function:
  20972  *     bcm_kt2_oam_delay_get
  20973  * Purpose:
  20974  *     Delay Measurements get 
  20975  * Parameters:
  20976  *     unit - Device unit number
  20977  * Returns:
  20978  *     None
  20979  */
  20980 int
  20981 bcm_kt2_oam_delay_get(int unit, bcm_oam_delay_t *delay_p)
  20982 {
  20983     _bcm_oam_control_t *oc;
  20984     int rv = BCM_E_NONE;
  20985     bhh_sdk_msg_ctrl_delay_get_t msg;
  20986     _bcm_oam_hash_data_t *h_data_p;
  20987     uint8 *buffer, *buffer_ptr;
  20988     uint16 buffer_len, reply_len;
  20989     int sess_id = 0;
  20990 
  20991     /* Get OAM Control Structure. */
  20992     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  20993     _BCM_OAM_LOCK(oc);
  20994 
  20995     if (oc->ukernel_not_ready) {
  20996         _BCM_OAM_UNLOCK(oc);
  20997         return BCM_E_INIT;
  20998     }
  20999 
  21000     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  21001 
  21002     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  21003 
  21004     /* Check endpoint status. */
  21005     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  21006     if ((BCM_E_EXISTS != rv)) {
  21007         /* Endpoint not in use. */
  21008         LOG_ERROR(BSL_LS_BCM_OAM,
  21009                   (BSL_META_U(unit,
  21010                               "OAM Error: Endpoint EP=%d %s.\n"),
  21011                    delay_p->id, bcm_errmsg(rv)));
  21012         _BCM_OAM_UNLOCK(oc);
  21013         return (rv);
  21014     }
  21015 
  21016     h_data_p = &oc->oam_hash_data[delay_p->id];
  21017 
  21018 
  21019     /*
  21020      * Only BHH is supported
  21021      */
  21022     if(BHH_EP_TYPE(h_data_p)) {
  21023 
  21024     sal_memset(&msg, 0, sizeof(msg));
  21025     /* Send BHH Session Update message to uC */
  21026     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  21027                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET,
  21028                       sess_id, 0,
  21029                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY,
  21030                       &reply_len);
  21031     if(BCM_FAILURE(rv)) {
  21032         LOG_ERROR(BSL_LS_BCM_OAM,
  21033                   (BSL_META_U(unit,
  21034                               "OAM Error: Endpoint EP=%d %s.\n"),
  21035                    delay_p->id, bcm_errmsg(rv)));
  21036         _BCM_OAM_UNLOCK(oc);
  21037         return (rv);
  21038     }
  21039 
  21040     /* Pack control message data into DMA buffer */
  21041     buffer     = oc->dma_buffer;
  21042     buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg);
  21043     buffer_len = buffer_ptr - buffer;
  21044 
  21045 
  21046     if (reply_len != buffer_len) {
  21047         rv =  BCM_E_INTERNAL;
  21048     } else {
  21049         /*
  21050          * Convert kernel space flags to host space flags
  21051          */
  21052         if (msg.flags & BCM_BHH_DM_ONE_WAY)
  21053             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  21054 
  21055         if (msg.flags & BCM_BHH_DM_TX_ENABLE)
  21056             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  21057 
  21058         delay_p->period = msg.period;
  21059 
  21060         if(msg.dm_format == BCM_BHH_DM_TYPE_PTP)
  21061             delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1;
  21062         else
  21063             delay_p->timestamp_format = bcmOAMTimestampFormatNTP;
  21064 
  21065         rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->delay), 
  21066                                        msg.delay_seconds, msg.delay_nanoseconds);
  21067         if(BCM_SUCCESS(rv)) {
  21068             rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->txf), 
  21069                                        msg.txf_seconds, msg.txf_nanoseconds);
  21070         }
  21071         if(BCM_SUCCESS(rv)) {
  21072             rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxf), 
  21073                                        msg.rxf_seconds, msg.rxf_nanoseconds);
  21074         }
  21075         if(BCM_SUCCESS(rv)) {
  21076             rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->txb), 
  21077                                        msg.txb_seconds, msg.txb_nanoseconds);
  21078         }
  21079         if(BCM_SUCCESS(rv)) {
  21080             rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxb), 
  21081                                        msg.rxb_seconds, msg.rxb_nanoseconds);
  21082         }
  21083         delay_p->rx_oam_packets = msg.rx_oam_packets;
  21084         delay_p->tx_oam_packets = msg.tx_oam_packets;
  21085         delay_p->int_pri = msg.int_pri;
  21086         delay_p->pkt_pri = msg.pkt_pri;
  21087 
  21088         rv = BCM_E_NONE;
  21089     }
  21090     }
  21091     else {
  21092         _BCM_OAM_UNLOCK(oc);
  21093         return BCM_E_UNAVAIL;
  21094     }
  21095 
  21096     _BCM_OAM_UNLOCK(oc);
  21097 
  21098     return (rv);
  21099 }
  21100 
  21101 /*
  21102  * Function:
  21103  *     bcm_kt2_oam_delay_delete
  21104  * Purpose:
  21105  *     Delay Measurement Delete 
  21106  * Parameters:
  21107  *     unit - Device unit number
  21108  * Returns:
  21109  *     None
  21110  */
  21111 int
  21112 bcm_kt2_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p)
  21113 {
  21114     _bcm_oam_control_t *oc;
  21115     int rv = BCM_E_NONE;
  21116     shr_bhh_msg_ctrl_delay_delete_t msg;
  21117     uint8 *buffer, *buffer_ptr;
  21118     uint16 buffer_len, reply_len;
  21119     int sess_id = 0;
  21120     _bcm_oam_hash_data_t *h_data_p;
  21121 
  21122     /* Get OAM Control Structure. */
  21123     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21124     _BCM_OAM_LOCK(oc);
  21125 
  21126     if (oc->ukernel_not_ready) {
  21127         _BCM_OAM_UNLOCK(oc);
  21128         return BCM_E_INIT;
  21129     }
  21130 
  21131     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  21132 
  21133     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  21134 
  21135     /* Check endpoint status. */
  21136     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  21137     if ((BCM_E_EXISTS != rv)) {
  21138         /* Endpoint not in use. */
  21139         LOG_ERROR(BSL_LS_BCM_OAM,
  21140                   (BSL_META_U(unit,
  21141                               "OAM Error: Endpoint EP=%d %s.\n"),
  21142                    delay_p->id, bcm_errmsg(rv)));
  21143         _BCM_OAM_UNLOCK(oc);
  21144         return (rv);
  21145     }
  21146 
  21147     h_data_p = &oc->oam_hash_data[delay_p->id];
  21148 
  21149     /*
  21150      * Only BHH is supported
  21151      */
  21152     if(BHH_EP_TYPE(h_data_p)) {
  21153 
  21154         msg.sess_id = sess_id;
  21155 
  21156         /* Pack control message data into DMA buffer */
  21157         buffer     = oc->dma_buffer;
  21158         buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg);
  21159         buffer_len = buffer_ptr - buffer;
  21160 
  21161         /* Send BHH Session Update message to uC */
  21162         rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  21163                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE,
  21164                       buffer_len, 0,
  21165                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY,
  21166                       &reply_len);
  21167 
  21168         if(BCM_SUCCESS(rv) && (reply_len != 0))
  21169             rv =  BCM_E_INTERNAL;
  21170     }
  21171     else {
  21172         _BCM_OAM_UNLOCK(oc);
  21173         return BCM_E_UNAVAIL;
  21174     }
  21175 
  21176     _BCM_OAM_UNLOCK(oc);
  21177 
  21178     return (rv);
  21179 }
  21180 
  21181 int _bcm_kt2_oam_pm_init(int unit)
  21182 {
  21183     /* Profile data structure initialization */
  21184     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21185     int rv = BCM_E_NONE;
  21186     _bcm_oam_control_t *oc = NULL;
  21187 
  21188     rv = _bcm_kt2_oam_control_get(unit, &oc);
  21189 
  21190     if (BCM_FAILURE(rv)) {
  21191         LOG_ERROR(BSL_LS_BCM_OAM,
  21192                 (BSL_META_U(unit,
  21193                             "OAM(unit %d) Error: Oam control get failed "
  21194                             "- %s.\n"), unit, bcm_errmsg(rv)));
  21195         return BCM_E_INIT;
  21196     }
  21197    
  21198     _BCM_OAM_LOCK(oc);
  21199     
  21200     oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit,
  21201             spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
  21202 
  21203     /* Raw mode is not supported in KT2. Internally it will be taken as none. */
  21204     if ( _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  21205 
  21206         oc->pm_bhh_lmdm_data_collection_mode = _BCM_OAM_PM_COLLECTION_MODE_NONE;
  21207 
  21208         LOG_ERROR(BSL_LS_BCM_OAM,
  21209                 (BSL_META_U(unit,
  21210                             "OAM(unit %d) Error: Raw mode is not supported in KT2."
  21211                             "Selected mode is none \n"), unit));
  21212 
  21213     }
  21214 
  21215     /* Allocate profiles only if one of them has processed stats 
  21216      * collection enabled 
  21217      */
  21218     if ((_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  21219         _BCM_OAM_ALLOC(pmc, _bcm_oam_pm_profile_control_t, 
  21220                 sizeof (_bcm_oam_pm_profile_control_t),
  21221                 "OAM PM profile control");
  21222         if (!pmc) {
  21223             _BCM_OAM_UNLOCK(oc);
  21224             return BCM_E_MEMORY;
  21225         }
  21226 
  21227         kt2_pm_profile_control[unit] = pmc;
  21228     }
  21229     /*
  21230      * Allocate DMA buffers and raw data buffers.
  21231      *
  21232      * 1) DMA buffer will be used to send and receive 'long' messages
  21233      * between SDK Host and uController (BTE).
  21234  */
  21235     
  21236     /* DMA buffer */
  21237     if (_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
  21238         oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
  21239         oc->pm_bhh_dma_buffer = soc_cm_salloc(unit, oc->pm_bhh_dma_buffer_len,
  21240                                               "PM DMA buffer");
  21241         if (!oc->pm_bhh_dma_buffer) {
  21242             _BCM_OAM_UNLOCK(oc);
  21243             return (BCM_E_MEMORY);
  21244         }
  21245         sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len);
  21246     }
  21247 
  21248     _BCM_OAM_UNLOCK(oc);
  21249 
  21250     return BCM_E_NONE;
  21251 }
  21252 
  21253 /*
  21254  * Function:
  21255  *      _bcm_kt2_oam_pm_msg_send_receive
  21256  * Purpose:
  21257  *      Sends given PM control message to the uController.
  21258  *      Receives and verifies expected reply.
  21259  *      Performs DMA operation if required.
  21260  * Parameters:
  21261  *      unit        - (IN) Unit number.
  21262  *      s_class     - (IN) PM message class.
  21263  *      s_len       - (IN) Value for 'len' field in message struct.
  21264  *                         Length of buffer to flush if DMA send is required.
  21265  *      s_data      - (IN) Value for 'data' field in message struct.
  21266  *                         Ignored if message requires a DMA send/receive
  21267  *                         operation.
  21268  *      r_subclass  - (IN) Expected reply message subclass.
  21269  *      r_len       - (OUT) Returns value in 'len' reply message field.
  21270  * Returns:
  21271  *      BCM_E_XXX
  21272  * Notes:
  21273  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  21274  *       can take any arbitrary data.
  21275  *
  21276  *     PM Long Control message:
  21277  *     - PM control messages that require send/receive of information
  21278  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  21279  *       use DMA operations to exchange information (long control message).
  21280  *
  21281  *     - PM convention for long control messages for
  21282  *        'mos_msg_data_t' fields:
  21283  *          'len'    size of the DMA buffer to send to uController
  21284  *          'data'   physical DMA memory address to send or receive
  21285  *
  21286  *      DMA Operations:
  21287  *      - DMA read/write operation is performed when a long BHH control
  21288  *        message is involved.
  21289  *
  21290  *      - Messages that require DMA operation (long control message)
  21291  *        is indicated by MOS_MSG_DMA_MSG().
  21292  *
  21293  *      - Callers must 'pack' and 'unpack' corresponding information
  21294  *        into/from DMA buffer indicated by dma_buffer.
  21295  */
  21296 STATIC int
  21297 _bcm_kt2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass,
  21298                                     uint16 s_len, uint32 s_data,
  21299                                     uint8 r_subclass, uint16 *r_len)
  21300 {
  21301     int rv = BCM_E_NONE;
  21302     _bcm_oam_control_t *oc;
  21303     mos_msg_data_t send, reply;
  21304     uint8 *dma_buffer = NULL;
  21305     int dma_buffer_len = 0;
  21306     uint32 uc_rv;
  21307     int uc_num;
  21308 
  21309     /* Lock already taken by the calling routine. */
  21310     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21311 
  21312     sal_memset(&send, 0, sizeof(send));
  21313     sal_memset(&reply, 0, sizeof(reply));
  21314     send.s.mclass = s_class;
  21315     send.s.subclass = s_subclass;
  21316     send.s.len = bcm_htons(s_len);
  21317 
  21318     /*
  21319      * Set 'data' to DMA buffer address if a DMA operation is
  21320      * required for send or receive.
  21321      */
  21322 
  21323     dma_buffer = oc->pm_bhh_dma_buffer;
  21324     dma_buffer_len = oc->pm_bhh_dma_buffer_len;
  21325 
  21326     if (MOS_MSG_DMA_MSG(s_subclass) ||
  21327         MOS_MSG_DMA_MSG(r_subclass)) {
  21328         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  21329     } else {
  21330         send.s.data = bcm_htonl(s_data);
  21331     }
  21332 
  21333     /* Flush DMA memory */
  21334     if (MOS_MSG_DMA_MSG(s_subclass)) {
  21335         soc_cm_sflush(unit, dma_buffer, s_len);
  21336     }
  21337 
  21338     /* Invalidate DMA memory to read */
  21339     if (MOS_MSG_DMA_MSG(r_subclass)) {
  21340         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  21341     }
  21342 
  21343     switch (s_class) {
  21344         case MOS_MSG_CLASS_BHH:
  21345             uc_num = oc->uc_num;
  21346             break;
  21347         
  21348         default:
  21349             return BCM_E_PARAM;
  21350             break;
  21351     }
  21352 
  21353     /* coverity[unreachable] */
  21354     rv = soc_cmic_uc_msg_send_receive(unit, uc_num,
  21355                                       &send, &reply,
  21356                                       _PM_UC_MSG_TIMEOUT_USECS);
  21357 
  21358     /* Check reply class, subclass */
  21359     if ((rv != SOC_E_NONE) ||
  21360         (reply.s.mclass != s_class) || /* We can expect the same class that was sent */
  21361         (reply.s.subclass != r_subclass)) {
  21362         return (BCM_E_INTERNAL);
  21363     }
  21364 
  21365     /* Convert OAM PM uController error code to BCM */
  21366     uc_rv = bcm_ntohl(reply.s.data);
  21367     switch(uc_rv) {
  21368     case SHR_OAM_PM_UC_E_NONE:
  21369         rv = BCM_E_NONE;
  21370         break;
  21371     case SHR_OAM_PM_UC_E_INTERNAL:
  21372         rv = BCM_E_INTERNAL;
  21373         break;
  21374     case SHR_OAM_PM_UC_E_MEMORY:
  21375         rv = BCM_E_MEMORY;
  21376         break;
  21377     case SHR_OAM_PM_UC_E_PARAM:
  21378         rv = BCM_E_PARAM;
  21379         break;
  21380     case SHR_OAM_PM_UC_E_RESOURCE:
  21381         rv = BCM_E_RESOURCE;
  21382         break;
  21383     case SHR_OAM_PM_UC_E_EXISTS:
  21384         rv = BCM_E_EXISTS;
  21385         break;
  21386     case SHR_OAM_PM_UC_E_NOT_FOUND:
  21387         rv = BCM_E_NOT_FOUND;
  21388         break;
  21389     case SHR_OAM_PM_UC_E_UNAVAIL:
  21390         rv = BCM_E_UNAVAIL;
  21391         break;
  21392     case SHR_OAM_PM_UC_E_VERSION:
  21393         rv = BCM_E_CONFIG;
  21394         break;
  21395     case SHR_OAM_PM_UC_E_INIT:
  21396         rv = BCM_E_INIT;
  21397         break;
  21398     default:
  21399         rv = BCM_E_INTERNAL;
  21400         break;
  21401     }
  21402         
  21403     *r_len = bcm_ntohs(reply.s.len);
  21404 
  21405     return (rv);
  21406 }
  21407 
  21408 int _bcm_kt2_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1, 
  21409                                 bcm_oam_pm_profile_info_t *profile_info2)
  21410 {
  21411     if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges,
  21412                      BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) {
  21413         /* Match */
  21414         return 1;
  21415     }
  21416     return 0;
  21417 }
  21418 
  21419 int _bcm_kt2_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info)
  21420 {
  21421     int id = 0;
  21422     _bcm_oam_pm_profile_control_t *pmc = NULL; 
  21423 
  21424     pmc = kt2_pm_profile_control[unit];
  21425     
  21426     if (!pmc) {
  21427         return 0; 
  21428     }
  21429 
  21430     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  21431         if (_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id)) { /* If a profile is in use */
  21432             if (_bcm_kt2_pm_profile_compare(
  21433                                          _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, id), 
  21434                                             profile_info)) {
  21435                 return 1;
  21436             }
  21437         }
  21438     }
  21439     return 0;
  21440 }
  21441 
  21442 int 
  21443 _bcm_kt2_find_free_pm_profile_id(int unit, int *pm_profile_id)
  21444 {
  21445     int id = 0;
  21446     _bcm_oam_pm_profile_control_t *pmc = NULL; 
  21447 
  21448     pmc = kt2_pm_profile_control[unit];
  21449     
  21450     if (!pmc) {
  21451         return BCM_E_INIT; 
  21452     }
  21453 
  21454     /* return the lowest un used id */
  21455     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  21456         if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id))) { /* If a profile is not in use */
  21457             *pm_profile_id = id; /* Assign it and return */
  21458             return BCM_E_NONE;
  21459         }
  21460     }
  21461     return BCM_E_RESOURCE;
  21462 }
  21463 
  21464 int
  21465 _bcm_kt2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all) 
  21466 {
  21467     _bcm_oam_pm_profile_control_t *pmc; 
  21468 
  21469     pmc = kt2_pm_profile_control[unit];
  21470     
  21471     if (!pmc) {
  21472         return BCM_E_INIT; 
  21473     }
  21474 
  21475     /* Check it only if it is a delete for a particular profile */
  21476     if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) {
  21477         /* It is not in use. Return error */
  21478         return BCM_E_NOT_FOUND;
  21479     }
  21480     /* Zero out that profile */
  21481     sal_memset(_BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0, 
  21482                 sizeof(bcm_oam_pm_profile_info_t));
  21483     /* Mark it un used */
  21484     _BCM_KT2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id);
  21485 
  21486     return BCM_E_NONE;
  21487 }
  21488 
  21489 int
  21490 bcm_kt2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id)
  21491 {
  21492     _bcm_oam_control_t *oc = NULL;
  21493     int rv = BCM_E_NONE;
  21494 
  21495     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21496     _BCM_OAM_LOCK(oc); 
  21497 
  21498     if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) {
  21499         
  21500         _BCM_OAM_UNLOCK(oc);
  21501         return BCM_E_PARAM;
  21502     }
  21503     
  21504     rv = _bcm_kt2_oam_pm_profile_delete(unit, profile_id, 0);
  21505     
  21506     _BCM_OAM_UNLOCK(oc);
  21507     return rv;
  21508 }
  21509 
  21510 int
  21511 bcm_kt2_oam_pm_profile_delete_all(int unit)
  21512 {
  21513     int id;
  21514     _bcm_oam_control_t *oc = NULL;
  21515     int rv = BCM_E_NONE;
  21516 
  21517     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21518     _BCM_OAM_LOCK(oc);    
  21519 
  21520     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  21521         rv = _bcm_kt2_oam_pm_profile_delete(unit, id, 1);
  21522 
  21523         if(rv != BCM_E_NONE) {
  21524             _BCM_OAM_UNLOCK(oc);
  21525         }
  21526     }
  21527 
  21528     _BCM_OAM_UNLOCK(oc);
  21529     return BCM_E_NONE;
  21530 }
  21531 
  21532 int 
  21533 bcm_kt2_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info)
  21534 {
  21535     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21536     bcm_oam_pm_profile_info_t     *profile_ptr = NULL;
  21537     int pm_profile_id = 0;
  21538     _bcm_oam_control_t *oc = NULL;
  21539     int rv=BCM_E_NONE;
  21540 
  21541     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21542     _BCM_OAM_LOCK(oc);
  21543     
  21544     pmc = kt2_pm_profile_control[unit];
  21545     
  21546     if (!pmc) {
  21547         _BCM_OAM_UNLOCK(oc);
  21548         return BCM_E_INIT; 
  21549     }
  21550 
  21551     if (_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
  21552         if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_info->id))) {
  21553             _BCM_OAM_UNLOCK(oc);
  21554             return BCM_E_PARAM;
  21555         }
  21556     }
  21557 
  21558     if (_BCM_KT2_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) {
  21559         if (!(_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) {
  21560             /* replace needs the id to be present */
  21561             _BCM_OAM_UNLOCK(oc);
  21562             return BCM_E_PARAM;
  21563         }
  21564 
  21565         if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) {
  21566             /* Trying to replace a non-existent PM profile */
  21567             _BCM_OAM_UNLOCK(oc);
  21568             return BCM_E_NOT_FOUND;
  21569         }
  21570 
  21571         /* Delete the previous profile. */
  21572         rv = _bcm_kt2_oam_pm_profile_delete(unit,
  21573                                              profile_info->id, 0);
  21574 
  21575         if(rv != BCM_E_NONE) {
  21576             _BCM_OAM_UNLOCK(oc);
  21577             return rv;
  21578         }
  21579     }
  21580 
  21581     if (_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
  21582         if (_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) {
  21583             /* That profile id is in use. */
  21584             _BCM_OAM_UNLOCK(oc);
  21585             return BCM_E_EXISTS;
  21586         }
  21587         /* Else use that as the id */
  21588         pm_profile_id = profile_info->id;
  21589     } else { 
  21590         rv = _bcm_kt2_find_free_pm_profile_id(unit, 
  21591                                                     &pm_profile_id);
  21592         if(rv != BCM_E_NONE) {
  21593             _BCM_OAM_UNLOCK(oc);
  21594             return rv;
  21595         }    
  21596     }
  21597 
  21598     /* Check if such a profile already exists. */
  21599     if (_bcm_kt2_pm_profile_exists(unit, profile_info)) {
  21600         
  21601         _BCM_OAM_UNLOCK(oc);
  21602         return BCM_E_EXISTS;
  21603     }
  21604 
  21605     /* Copy it to local profile information */ 
  21606     profile_ptr = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id);
  21607     sal_memcpy(profile_ptr, profile_info, 
  21608                 sizeof(bcm_oam_pm_profile_info_t));
  21609     
  21610     /* Update the id in the profile */
  21611     profile_ptr->id = profile_info->id =  pm_profile_id;
  21612 
  21613     /* Current flags have only transient meaning, so clear them */
  21614     profile_ptr->flags = 0;
  21615 
  21616     /* Mark that profile used */
  21617     _BCM_KT2_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id);
  21618     
  21619     _BCM_OAM_UNLOCK(oc);
  21620     
  21621     return BCM_E_NONE;
  21622 }
  21623 
  21624 int
  21625 bcm_kt2_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info)
  21626 {
  21627     _bcm_oam_pm_profile_control_t *pmc;
  21628     int profile_id = profile_info->id; 
  21629 
  21630     pmc = kt2_pm_profile_control[unit];
  21631     
  21632     if (!pmc) {
  21633         return BCM_E_INIT; 
  21634     }
  21635 
  21636     if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) {
  21637         return BCM_E_PARAM;
  21638     }
  21639 
  21640     if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  21641         /* It is not in use. Return error */
  21642         return BCM_E_NOT_FOUND;
  21643     }
  21644 
  21645     /* Copy the profile to the profile structure passed */
  21646     sal_memcpy(profile_info, _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id),
  21647                sizeof(bcm_oam_pm_profile_info_t));
  21648 
  21649     return BCM_E_NONE;  
  21650 }
  21651 
  21652 int bcm_kt2_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id,
  21653                               bcm_oam_pm_profile_t profile_id)
  21654 {
  21655     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21656     bcm_oam_pm_profile_info_t *profile_info = NULL;
  21657     _bcm_oam_control_t *oc = NULL;
  21658     _bcm_oam_hash_data_t *h_data_p = NULL;
  21659     int rv = BCM_E_NONE;
  21660     shr_oam_pm_msg_ctrl_profile_attach_t msg_profile_attach;
  21661     uint8                    msg_class = 0;
  21662     uint16                   reply_len = 0;
  21663     uint8                    msg_subclass = 0;
  21664     uint8                    msg_reply_subclass = 0;
  21665     uint8 *buffer, *buffer_ptr;
  21666     uint16 buffer_len;
  21667 
  21668     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21669     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  21670     _BCM_OAM_LOCK(oc);
  21671 
  21672     h_data_p =  &oc->oam_hash_data[endpoint_id];
  21673 
  21674     if (!BHH_EP_TYPE(h_data_p)) {
  21675         LOG_ERROR(BSL_LS_BCM_OAM,
  21676                 (BSL_META_U(unit,
  21677                             "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"),
  21678                  unit, endpoint_id));
  21679         _BCM_OAM_UNLOCK(oc);
  21680         return (BCM_E_UNAVAIL);        
  21681     }    
  21682     
  21683     if (0 == h_data_p->in_use) {
  21684         LOG_ERROR(BSL_LS_BCM_OAM,
  21685                 (BSL_META_U(unit,
  21686                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  21687                  unit, endpoint_id));
  21688         _BCM_OAM_UNLOCK(oc);
  21689         return (BCM_E_NOT_FOUND);
  21690     }
  21691     pmc = kt2_pm_profile_control[unit];
  21692     
  21693     if (!pmc) {
  21694         _BCM_OAM_UNLOCK(oc);
  21695         return BCM_E_INIT; 
  21696     }
  21697 
  21698     if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) {
  21699         _BCM_OAM_UNLOCK(oc);
  21700         return BCM_E_PARAM;
  21701     }
  21702 
  21703     /* Check profile id exists or not */
  21704     if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  21705         /* It is not in use. Return error */
  21706         _BCM_OAM_UNLOCK(oc);
  21707         return BCM_E_NOT_FOUND;
  21708     }
  21709     /* Check if a profile id is already attached to this endpoint */
  21710     if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) {
  21711         _BCM_OAM_UNLOCK(oc);
  21712         return BCM_E_EXISTS;
  21713     }
  21714 
  21715     /* Check if delay measurement flag is present for the endpoint */
  21716     if (!(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) {
  21717         _BCM_OAM_UNLOCK(oc);
  21718         return BCM_E_PARAM;
  21719     }
  21720 
  21721     profile_info = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id);
  21722 
  21723     /* Send info to u-Kernel about the profile attached with the endpoint */
  21724     sal_memset(&msg_profile_attach, 0, sizeof(msg_profile_attach));
  21725 
  21726     msg_class = MOS_MSG_CLASS_BHH;
  21727     msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH;
  21728     msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY;
  21729     msg_profile_attach.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  21730    
  21731     msg_profile_attach.profile_id = profile_id;
  21732     msg_profile_attach.profile_flags = profile_info->flags;
  21733     sal_memcpy(&(msg_profile_attach.profile_edges), &(profile_info->bin_edges), 
  21734                (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES));
  21735 
  21736     /* Pack control message data into DMA buffer */
  21737     buffer = oc->pm_bhh_dma_buffer;
  21738     buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg_profile_attach);
  21739     buffer_len = buffer_ptr - buffer;
  21740 
  21741 
  21742     rv = _bcm_kt2_oam_pm_msg_send_receive 
  21743         (unit, msg_class, 
  21744          msg_subclass,
  21745          buffer_len, 0, 
  21746          msg_reply_subclass,
  21747          &reply_len);
  21748 
  21749     if(BCM_FAILURE(rv)) {
  21750         _BCM_OAM_UNLOCK(oc);
  21751         return BCM_E_INTERNAL;
  21752     }
  21753 
  21754     /* Attach it to the endpoint */
  21755     h_data_p->pm_profile_attached = profile_id;
  21756 
  21757     _BCM_OAM_UNLOCK(oc);
  21758     return BCM_E_NONE;
  21759 }
  21760 
  21761 int bcm_kt2_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 
  21762                                   bcm_oam_pm_profile_t profile_id)
  21763 {
  21764     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21765     _bcm_oam_control_t *oc = NULL;
  21766     _bcm_oam_hash_data_t *h_data_p = NULL;
  21767     int rv = BCM_E_NONE;
  21768     uint8                    msg_class = 0;
  21769     uint16                   reply_len = 0;
  21770     uint8                    msg_subclass = 0;
  21771     uint8                    msg_reply_subclass = 0;
  21772     uint16                   sess_id = 0;
  21773 
  21774     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21775     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  21776     _BCM_OAM_LOCK(oc);
  21777 
  21778     h_data_p =  &oc->oam_hash_data[endpoint_id];
  21779 
  21780     if (!BHH_EP_TYPE(h_data_p)) {
  21781         LOG_ERROR(BSL_LS_BCM_OAM,
  21782                 (BSL_META_U(unit,
  21783                             "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"),
  21784                  unit, endpoint_id));
  21785         _BCM_OAM_UNLOCK(oc);
  21786         return (BCM_E_UNAVAIL);        
  21787     }    
  21788 
  21789     if (0 == h_data_p->in_use) {
  21790         LOG_ERROR(BSL_LS_BCM_OAM,
  21791                 (BSL_META_U(unit,
  21792                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  21793                  unit, endpoint_id));
  21794         _BCM_OAM_UNLOCK(oc);
  21795         return (BCM_E_NOT_FOUND);
  21796     }
  21797     pmc = kt2_pm_profile_control[unit];
  21798     
  21799     if (!pmc) {
  21800         _BCM_OAM_UNLOCK(oc);
  21801         return BCM_E_INIT; 
  21802     }
  21803 
  21804     if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) {
  21805         _BCM_OAM_UNLOCK(oc);
  21806         return BCM_E_PARAM;
  21807     }
  21808 
  21809     /* Check profile id exists or not */
  21810     if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  21811         /* It is not in use. Return error */
  21812         _BCM_OAM_UNLOCK(oc);
  21813         return BCM_E_NOT_FOUND;
  21814     }
  21815 
  21816     /* Check if the passed profile id is the one that is attached */
  21817     if (profile_id != h_data_p->pm_profile_attached) {
  21818         _BCM_OAM_UNLOCK(oc);
  21819         return BCM_E_PARAM;
  21820     }
  21821 
  21822     msg_class = MOS_MSG_CLASS_BHH;
  21823     msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH;
  21824     msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY;
  21825     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  21826     
  21827     rv = _bcm_kt2_oam_pm_msg_send_receive 
  21828         (unit, msg_class, 
  21829          msg_subclass,
  21830          sess_id, profile_id, 
  21831          msg_reply_subclass,
  21832          &reply_len);
  21833 
  21834     if(BCM_FAILURE(rv)) {
  21835         _BCM_OAM_UNLOCK(oc);
  21836         return BCM_E_INTERNAL;
  21837     }
  21838     /* Detach the profile from endpoint */
  21839     h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  21840 
  21841     _BCM_OAM_UNLOCK(oc);
  21842     return BCM_E_NONE;
  21843 }
  21844 
  21845 
  21846 int bcm_kt2_oam_pm_profile_traverse(int unit, 
  21847                     bcm_oam_pm_profile_traverse_cb cb, void *user_data)
  21848 {
  21849     int                     rv = BCM_E_NONE;  /* Operation return status.          */
  21850     bcm_oam_pm_profile_info_t *profile_info = NULL;
  21851     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21852     int profile_id;
  21853 
  21854     /* Validate input parameter. */
  21855     if (NULL == cb) {
  21856         return (BCM_E_PARAM);
  21857     }
  21858     pmc = kt2_pm_profile_control[unit];
  21859     
  21860     if (!pmc) {
  21861         return BCM_E_INIT; 
  21862     }
  21863 
  21864     for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) {
  21865         /* Check profile id is in use or not */
  21866         if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  21867             /* Skip that profile id */
  21868             continue;
  21869         }
  21870         profile_info = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id);
  21871         rv = cb(unit, profile_info, user_data);
  21872         if (BCM_FAILURE(rv)) {
  21873             LOG_ERROR(BSL_LS_BCM_OAM,
  21874                       (BSL_META_U(unit,
  21875                                   "OAM(unit %d) Error: EP=%d callback failed - %s.\n"),
  21876                        unit, profile_id, bcm_errmsg(rv)));
  21877             return (rv);
  21878         }
  21879     }
  21880 
  21881     return (rv);
  21882 }
  21883 
  21884 void _bcm_kt2_oam_copy_stats_msg_to_stats_ptr(shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg,
  21885                                              bcm_oam_pm_stats_t *stats_ptr,
  21886                                              uint8 pm_stat_extra_elem_feature)
  21887 {
  21888     stats_ptr->far_loss_min = stats_msg->far_loss_min;
  21889     stats_ptr->far_tx_min = stats_msg->far_tx_min;   
  21890     stats_ptr->far_loss_max = stats_msg->far_loss_max; 
  21891     stats_ptr->far_tx_max = stats_msg->far_tx_max;
  21892     stats_ptr->far_loss = stats_msg->far_loss;
  21893     stats_ptr->near_loss_min = stats_msg->near_loss_min;
  21894     stats_ptr->near_tx_min = stats_msg->near_tx_min;  
  21895     stats_ptr->near_loss_max = stats_msg->near_loss_max;
  21896     stats_ptr->near_tx_max = stats_msg->near_tx_max;  
  21897     stats_ptr->near_loss = stats_msg->near_loss;    
  21898     stats_ptr->lm_tx_count = stats_msg->lm_tx_count;  
  21899     stats_ptr->DM_min = stats_msg->DM_min;       
  21900     stats_ptr->DM_max = stats_msg->DM_max;
  21901     if(stats_msg->dm_rx_count) {
  21902         stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count;
  21903     }
  21904     stats_ptr->dm_tx_count = stats_msg->dm_tx_count;  
  21905     stats_ptr->profile_id = stats_msg->profile_id;
  21906     sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters), sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1));
  21907     if(pm_stat_extra_elem_feature) {
  21908         stats_ptr->lm_rx_count = stats_msg->lm_rx_count;
  21909         stats_ptr->dm_rx_count = stats_msg->dm_rx_count;
  21910         stats_ptr->far_total_tx_pkt_count = stats_msg->far_total_tx_pkt_count;
  21911         stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count;
  21912     }
  21913 
  21914     if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) {
  21915         stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER;
  21916     }
  21917 }
  21918 
  21919 int bcm_kt2_oam_pm_stats_get(int unit,
  21920                             bcm_oam_endpoint_t endpoint_id, bcm_oam_pm_stats_t *stats_ptr)
  21921 {
  21922     _bcm_oam_pm_profile_control_t *pmc = NULL;
  21923     _bcm_oam_control_t *oc = NULL;
  21924     _bcm_oam_hash_data_t *h_data_p = NULL;
  21925     shr_oam_pm_msg_ctrl_pm_stats_get_t stats_msg;
  21926     int rv = BCM_E_NONE;
  21927     uint16 sess_id = 0;
  21928     uint8                    msg_class = 0;
  21929     uint16                   reply_len = 0;
  21930     uint8                    msg_subclass = 0;
  21931     uint8                    msg_reply_subclass = 0;
  21932     uint8                   *dma_buffer = NULL;
  21933     uint8                   pm_stat_extra_elem_feature = 0;
  21934 
  21935     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  21936     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  21937     _BCM_OAM_LOCK(oc);
  21938 
  21939     /* Check endpoint status. */
  21940     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id);
  21941     if ((BCM_E_EXISTS != rv)) {
  21942         /* Endpoint not in use. */
  21943         LOG_ERROR(BSL_LS_BCM_OAM,
  21944                   (BSL_META_U(unit,
  21945                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  21946                    unit, endpoint_id, bcm_errmsg(rv)));
  21947         _BCM_OAM_UNLOCK(oc);
  21948         return (rv);
  21949     }
  21950 
  21951     h_data_p =  &oc->oam_hash_data[endpoint_id];
  21952 
  21953     if (!BHH_EP_TYPE(h_data_p)) {
  21954         LOG_ERROR(BSL_LS_BCM_OAM,
  21955                 (BSL_META_U(unit,
  21956                             "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"),
  21957                  unit, endpoint_id));
  21958         _BCM_OAM_UNLOCK(oc);
  21959         return (BCM_E_UNAVAIL);        
  21960     }    
  21961 
  21962     if (0 == h_data_p->in_use) {
  21963         LOG_ERROR(BSL_LS_BCM_OAM,
  21964                 (BSL_META_U(unit,
  21965                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  21966                  unit, endpoint_id));
  21967         _BCM_OAM_UNLOCK(oc);
  21968         return (BCM_E_INTERNAL);
  21969     }
  21970 
  21971     pmc = kt2_pm_profile_control[unit];
  21972 
  21973     if (!pmc) {
  21974         _BCM_OAM_UNLOCK(oc);
  21975         return BCM_E_INIT; 
  21976     }
  21977 
  21978 
  21979     msg_class = MOS_MSG_CLASS_BHH;
  21980     msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET;
  21981     msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY;
  21982     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  21983     pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK(BHH_PM_STAT_EXTRA_ELEM);
  21984 
  21985     dma_buffer = oc->pm_bhh_dma_buffer;
  21986     rv = _bcm_kt2_oam_pm_msg_send_receive 
  21987         (unit, msg_class, 
  21988          msg_subclass,
  21989          /* Pass the buffer pointer in data and sess id in length fields.*/
  21990          sess_id, soc_cm_l2p(unit, dma_buffer),
  21991          msg_reply_subclass,
  21992          &reply_len);
  21993 
  21994     if(BCM_FAILURE(rv) || reply_len == 0) {
  21995         _BCM_OAM_UNLOCK(oc);
  21996         return BCM_E_INTERNAL;
  21997     }
  21998 
  21999     shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg, pm_stat_extra_elem_feature);
  22000 
  22001     _bcm_kt2_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr, pm_stat_extra_elem_feature);
  22002 
  22003     _BCM_OAM_UNLOCK(oc);
  22004     return BCM_E_NONE;
  22005 }
  22006 
  22007 
  22008 int
  22009 bcm_kt2_oam_pm_profile_attach_get(
  22010         int unit,
  22011         bcm_oam_endpoint_t endpoint_id,
  22012         bcm_oam_pm_profile_t *profile_id)
  22013 {
  22014     _bcm_oam_pm_profile_control_t *pmc = NULL;
  22015     _bcm_oam_control_t *oc = NULL;
  22016     _bcm_oam_hash_data_t *h_data_p = NULL;
  22017     int rv = BCM_E_NONE;
  22018 
  22019     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22020     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  22021     _BCM_OAM_LOCK(oc);
  22022 
  22023     /* Check endpoint status. */
  22024     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id);
  22025     if ((BCM_E_EXISTS != rv)) {
  22026         /* Endpoint not in use. */
  22027         LOG_ERROR(BSL_LS_BCM_OAM,
  22028                   (BSL_META_U(unit,
  22029                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  22030                    unit, endpoint_id, bcm_errmsg(rv)));
  22031         _BCM_OAM_UNLOCK(oc);
  22032         return (rv);
  22033     }
  22034 
  22035     h_data_p =  &oc->oam_hash_data[endpoint_id];
  22036 
  22037     if (0 == h_data_p->in_use) {
  22038         LOG_ERROR(BSL_LS_BCM_OAM,
  22039                 (BSL_META_U(unit,
  22040                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  22041                  unit, endpoint_id));
  22042         _BCM_OAM_UNLOCK(oc);
  22043         return (BCM_E_INTERNAL);
  22044     }
  22045     pmc = kt2_pm_profile_control[unit];
  22046     
  22047     if (!pmc) {
  22048         _BCM_OAM_UNLOCK(oc);
  22049         return BCM_E_INIT; 
  22050     }
  22051 
  22052     /* Get the attached profile */
  22053     *profile_id = h_data_p->pm_profile_attached;
  22054 
  22055     if (*profile_id == _BCM_OAM_INVALID_INDEX) {
  22056         _BCM_OAM_UNLOCK(oc);
  22057         return BCM_E_NOT_FOUND;
  22058     } 
  22059     /* Check profile id is in use or not */
  22060     if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) {
  22061         /* It is not in use. Return error */
  22062         /* Ideally this should not happen */
  22063         _BCM_OAM_UNLOCK(oc);
  22064         return BCM_E_INTERNAL;
  22065     }
  22066 
  22067     _BCM_OAM_UNLOCK(oc);
  22068     return BCM_E_NONE;
  22069 }
  22070 
  22071 /*
  22072  * Function:
  22073  *      bcm_kt2_oam_csf_add
  22074  * Purpose:
  22075  *      Start CSF PDU transmission
  22076  * Parameters:
  22077  *      unit    - (IN)    Unit number.
  22078  *      csf_ptr - (INOUT) CSF object
  22079  * Returns:
  22080  *      BCM_E_XXX
  22081  * Notes:
  22082  */
  22083 int bcm_kt2_oam_csf_add(int unit, bcm_oam_csf_t *csf_p)
  22084 {
  22085     _bcm_oam_control_t         *oc;
  22086     _bcm_oam_hash_data_t       *h_data_p;
  22087     bhh_sdk_msg_ctrl_csf_add_t  msg;
  22088     uint8                      *buffer, *buffer_ptr;
  22089     uint16                      buffer_len, reply_len;
  22090     int                         sess_id = 0;
  22091     int                         rv = BCM_E_NONE;
  22092 
  22093     /* Get OAM Control Structure. */
  22094     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22095     _BCM_OAM_LOCK(oc);
  22096 
  22097     if (oc->ukernel_not_ready) {
  22098         _BCM_OAM_UNLOCK(oc);
  22099         return BCM_E_INIT;
  22100     }
  22101 
  22102     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  22103     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  22104 
  22105     /* Check endpoint status. */
  22106     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  22107     if ((BCM_E_EXISTS != rv)) {
  22108         /* Endpoint not in use. */
  22109         LOG_ERROR(BSL_LS_BCM_OAM,
  22110                   (BSL_META_U(unit,
  22111                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  22112                    unit, csf_p->id, bcm_errmsg(rv)));
  22113         _BCM_OAM_UNLOCK(oc);
  22114         return (rv);
  22115     }
  22116 
  22117     if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) &&
  22118         (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) {
  22119         /* Only 1S and 1M are supported */
  22120         _BCM_OAM_UNLOCK(oc);
  22121         return BCM_E_PARAM;
  22122     }
  22123 
  22124     h_data_p = &oc->oam_hash_data[csf_p->id];
  22125     /*
  22126      * Only BHH is supported
  22127      */
  22128     if (!BHH_EP_TYPE(h_data_p)) {
  22129         _BCM_OAM_UNLOCK(oc);
  22130         return BCM_E_UNAVAIL;
  22131     }
  22132 
  22133     sal_memset(&msg, 0, sizeof(msg));
  22134     msg.sess_id = sess_id;
  22135     msg.int_pri = csf_p->int_pri;
  22136     msg.pkt_pri = csf_p->pkt_pri;
  22137 
  22138     switch(csf_p->type) {
  22139         case BCM_OAM_CSF_LOS:
  22140             msg.type = SHR_CSF_TYPE_LOS;
  22141             break;
  22142 
  22143         case BCM_OAM_CSF_FDI:
  22144             msg.type = SHR_CSF_TYPE_FDI;
  22145             break;
  22146 
  22147         case BCM_OAM_CSF_RDI:
  22148             msg.type = SHR_CSF_TYPE_RDI;
  22149             break;
  22150 
  22151         case BCM_OAM_CSF_DCI:
  22152             msg.type = SHR_CSF_TYPE_DCI;
  22153             break;
  22154 
  22155         default:
  22156             _BCM_OAM_UNLOCK(oc);
  22157             return BCM_E_PARAM;
  22158     }
  22159 
  22160     /*
  22161      * Set period
  22162      */
  22163     msg.period  = csf_p->period;
  22164 
  22165     /* Pack control message data into DMA buffer */
  22166     buffer     = oc->dma_buffer;
  22167     buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg);
  22168     buffer_len = buffer_ptr - buffer;
  22169 
  22170     /* Send BHH Session Update message to uC */
  22171     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  22172                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD,
  22173                                            buffer_len, 0,
  22174                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY,
  22175                                            &reply_len);
  22176 
  22177     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  22178         rv =  BCM_E_INTERNAL;
  22179     }
  22180 
  22181     _BCM_OAM_UNLOCK(oc);
  22182     return rv;
  22183 }
  22184 
  22185 /*
  22186  * Function:
  22187  *      bcm_kt2_oam_csf_get
  22188  * Purpose:
  22189  *      Get CSF info
  22190  * Parameters:
  22191  *      unit    - (IN)  Unit number.
  22192  *      csf_ptr - (OUT) CSF object
  22193  * Returns:
  22194  *      BCM_E_XXX
  22195  * Notes:
  22196  */
  22197 int bcm_kt2_oam_csf_get(int unit, bcm_oam_csf_t *csf_p)
  22198 {
  22199     _bcm_oam_control_t          *oc;
  22200     bhh_sdk_msg_ctrl_csf_get_t   msg;
  22201     _bcm_oam_hash_data_t        *h_data_p;
  22202     uint8                       *buffer, *buffer_ptr;
  22203     uint16                       buffer_len, reply_len;
  22204     int                          sess_id = 0;
  22205     int                          rv = BCM_E_NONE;
  22206 
  22207     /* Get OAM Control Structure. */
  22208     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22209     _BCM_OAM_LOCK(oc);
  22210 
  22211     if (oc->ukernel_not_ready) {
  22212         _BCM_OAM_UNLOCK(oc);
  22213         return BCM_E_INIT;
  22214     }
  22215 
  22216     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  22217     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  22218 
  22219     /* Check endpoint status. */
  22220     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  22221     if ((BCM_E_EXISTS != rv)) {
  22222         /* Endpoint not in use. */
  22223         LOG_ERROR(BSL_LS_BCM_OAM,
  22224                   (BSL_META_U(unit,
  22225                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  22226                    unit, csf_p->id, bcm_errmsg(rv)));
  22227         _BCM_OAM_UNLOCK(oc);
  22228         return (rv);
  22229     }
  22230 
  22231     h_data_p = &oc->oam_hash_data[csf_p->id];
  22232 
  22233     if (!BHH_EP_TYPE(h_data_p)) {
  22234         _BCM_OAM_UNLOCK(oc);
  22235         return BCM_E_UNAVAIL;
  22236     }
  22237 
  22238 
  22239     sal_memset(&msg, 0, sizeof(msg));
  22240 
  22241     /* Send BHH Session Update message to uC */
  22242     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  22243                                            MOS_MSG_SUBCLASS_BHH_CSF_GET,
  22244                                            sess_id, 0,
  22245                                            MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY,
  22246                                            &reply_len);
  22247     if(BCM_FAILURE(rv)) {
  22248         LOG_ERROR(BSL_LS_BCM_OAM,
  22249                   (BSL_META_U(unit,
  22250                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  22251                    unit, csf_p->id, bcm_errmsg(rv)));
  22252         _BCM_OAM_UNLOCK(oc);
  22253         return (rv);
  22254     }
  22255 
  22256     /* Pack control message data into DMA buffer */
  22257     buffer     = oc->dma_buffer;
  22258     buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg);
  22259     buffer_len = buffer_ptr - buffer;
  22260 
  22261 
  22262     if (reply_len != buffer_len) {
  22263         _BCM_OAM_UNLOCK(oc);
  22264         return BCM_E_INTERNAL;
  22265     }
  22266 
  22267     switch(msg.type) {
  22268         case SHR_CSF_TYPE_LOS:
  22269             csf_p->type = BCM_OAM_CSF_LOS;
  22270             break;
  22271 
  22272         case SHR_CSF_TYPE_FDI:
  22273             csf_p->type = BCM_OAM_CSF_FDI;
  22274             break;
  22275 
  22276         case SHR_CSF_TYPE_RDI:
  22277             csf_p->type = BCM_OAM_CSF_RDI;
  22278             break;
  22279 
  22280         case SHR_CSF_TYPE_DCI:
  22281             csf_p->type = BCM_OAM_CSF_DCI;
  22282             break;
  22283 
  22284         default:
  22285             _BCM_OAM_UNLOCK(oc);
  22286             return BCM_E_INTERNAL;
  22287     }
  22288 
  22289     csf_p->period  = msg.period;
  22290     csf_p->flags   = msg.flags;
  22291     csf_p->pkt_pri = msg.pkt_pri;
  22292     csf_p->int_pri = msg.int_pri;
  22293 
  22294 
  22295     _BCM_OAM_UNLOCK(oc);
  22296     return BCM_E_NONE;
  22297 
  22298 }
  22299 
  22300 /*
  22301  * Function:
  22302  *      bcm_kt2_oam_csf_delete
  22303  * Purpose:
  22304  *      Stop CSF PDU transmission
  22305  * Parameters:
  22306  *      unit    - (IN  Unit number.
  22307  *      csf_ptr - (IN) CSF object
  22308  * Returns:
  22309  *      BCM_E_XXX
  22310  * Notes:
  22311  */
  22312 int bcm_kt2_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p)
  22313 {
  22314     _bcm_oam_control_t   *oc;
  22315     _bcm_oam_hash_data_t *h_data_p;
  22316     uint16                reply_len;
  22317     int                   sess_id;
  22318     int                   rv = BCM_E_NONE;
  22319 
  22320     /* Get OAM Control Structure. */
  22321     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22322     _BCM_OAM_LOCK(oc);
  22323 
  22324     if (oc->ukernel_not_ready) {
  22325         _BCM_OAM_UNLOCK(oc);
  22326         return BCM_E_INIT;
  22327     }
  22328 
  22329     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  22330     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  22331 
  22332     /* Check endpoint status. */
  22333     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  22334     if ((BCM_E_EXISTS != rv)) {
  22335         /* Endpoint not in use. */
  22336         LOG_ERROR(BSL_LS_BCM_OAM,
  22337                   (BSL_META_U(unit,
  22338                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  22339                    unit, csf_p->id, bcm_errmsg(rv)));
  22340         _BCM_OAM_UNLOCK(oc);
  22341         return (rv);
  22342     }
  22343 
  22344     h_data_p = &oc->oam_hash_data[csf_p->id];
  22345 
  22346     if (!BHH_EP_TYPE(h_data_p)) {
  22347         _BCM_OAM_UNLOCK(oc);
  22348         return BCM_E_UNAVAIL;
  22349     }
  22350 
  22351     /* Send BHH Session Update message to uC */
  22352     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  22353                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE,
  22354                                            sess_id, 0,
  22355                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY,
  22356                                            &reply_len);
  22357     _BCM_OAM_UNLOCK(oc);
  22358     return (rv);
  22359 }
  22360 #endif /* defined(INCLUDE_BHH) */
  22361 
  22362 /*
  22363  * Function:
  22364  *      _bcm_kt2_bhh_endpoint_faults_multi_get
  22365  * Purpose:
  22366  *      Function to get faults for multiple BHH endpoints
  22367  *      in a single call.
  22368  * Parameters:
  22369  *      unit                (IN) BCM device number
  22370  *      flags               (IN) Flags is kept unused as of now.
  22371  *                                This is for any future enhancement
  22372  *      max_endpoints       (IN) Number of max endpoint for the protocol
  22373  *      faults              (OUT) Pointer to faults for all endpoints
  22374  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
  22375  *                                filled by get API.
  22376  *
  22377  * Returns:
  22378  *      BCM_E_NONE          No error
  22379  *      BCM_E_XXXX          Error
  22380  */
  22381 
  22382 #if defined (INCLUDE_BHH)
  22383 int _bcm_kt2_bhh_endpoint_faults_multi_get(
  22384         int unit,
  22385         uint32 flags,
  22386         uint32 max_endpoints,
  22387         bcm_oam_endpoint_fault_t *faults,
  22388         uint32 *endpoint_count)
  22389 {
  22390     int rv = BCM_E_NONE;
  22391     _bcm_oam_control_t *oc = NULL;
  22392     bcm_oam_endpoint_fault_t *faults_temp = faults;
  22393     uint8 *buffer;
  22394     uint16 reply_len;
  22395     uint32 sess_count;
  22396     uint32 ep_id;
  22397     uint32 ep_count = 0;
  22398     uint32 faults_bitmap;
  22399     _bcm_oam_hash_data_t *h_data_p;      /* Pointer to endpoint hash data.    */
  22400 
  22401     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22402 
  22403     _BCM_OAM_LOCK(oc);
  22404 
  22405     if(max_endpoints != oc->bhh_endpoint_count) {
  22406         rv = BCM_E_PARAM;
  22407         _BCM_OAM_UNLOCK(oc);
  22408         return (rv);
  22409     }
  22410 
  22411     sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints));
  22412 
  22413     rv = _bcm_kt2_oam_bhh_msg_send_receive(unit,
  22414             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET,
  22415             0, 0,
  22416             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY,
  22417             &reply_len);
  22418 
  22419     if (BCM_FAILURE(rv)) {
  22420         LOG_ERROR(BSL_LS_BCM_OAM,
  22421                 (BSL_META_U(unit,
  22422                             "OAM(unit %d) Error: BHH uKernel msg failed for"
  22423                             "faults multi get %s.\n"), unit,
  22424                  bcm_errmsg(rv)));
  22425         _BCM_OAM_UNLOCK(oc);
  22426         return (rv);
  22427     }
  22428 
  22429     if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) {
  22430         rv = BCM_E_INTERNAL;
  22431         _BCM_OAM_UNLOCK(oc);
  22432         return (rv);
  22433     }
  22434     /* Unpack control message data into DMA buffer */
  22435     buffer = oc->dma_buffer;
  22436     for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++)
  22437     {
  22438         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  22439 
  22440         /* Validate endpoint index value. */
  22441         BCM_OAM_BHH_VALIDATE_EP(ep_id);
  22442 
  22443         h_data_p =  &oc->oam_hash_data[ep_id];
  22444 
  22445         /* If endpoint not in use, ignore and continue for next session_id).
  22446          * If session is running in hostCPU, skip and Go to ep_id.*/
  22447         if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  22448            continue;
  22449         }
  22450 
  22451          _SHR_UNPACK_U32(buffer, faults_bitmap);
  22452 
  22453         faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  22454 
  22455         if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){
  22456             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  22457         }
  22458         if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){
  22459             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  22460         }
  22461         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  22462             faults_temp->faults |=
  22463                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  22464         }
  22465         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  22466             faults_temp->faults |=
  22467                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  22468         }
  22469          if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  22470             faults_temp->faults |=
  22471                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  22472         }
  22473         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  22474             faults_temp->faults |=
  22475                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  22476         }
  22477         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  22478             faults_temp->faults |=
  22479                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  22480         }
  22481 
  22482         ep_count++;
  22483         faults_temp++;
  22484 
  22485     }
  22486 
  22487     *endpoint_count = ep_count;
  22488     _BCM_OAM_UNLOCK(oc);
  22489     return (rv);
  22490 
  22491 }
  22492 #endif
  22493 
  22494 /* Function:
  22495  *      bcm_kt2_oam_endpoint_faults_multi_get
  22496  * Purpose:
  22497  *      Function to get faults for multiple endpoints per protocl
  22498  *      in a single call.
  22499  * Parameters:
  22500  *      unit                (IN) BCM device number
  22501  *      flags               (IN) Flags is kept unused as of now.
  22502  *                               This is for any future enhancement
  22503  *      endpoint_protocol   (IN) Protocol type of the endpoints to retrieve faults
  22504  *      max_endpoints       (IN) Number of max endpoint for the protocol
  22505  *      faults              (OUT) Pointer to faults for all endpoints
  22506  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
  22507  *                                by get API.
  22508  *
  22509  * Returns:
  22510  *      BCM_E_NONE          No error
  22511  *      BCM_E_XXXX          Error
  22512  */
  22513 int bcm_kt2_oam_endpoint_faults_multi_get(
  22514         int unit,
  22515         uint32 flags,
  22516         bcm_oam_protocol_type_t endpoint_protocol,
  22517         uint32 max_endpoints,
  22518         bcm_oam_endpoint_fault_t *faults,
  22519         uint32 *endpoint_count)
  22520 
  22521 {
  22522     int rv = BCM_E_NONE;
  22523 
  22524     if(!faults) {
  22525         rv = BCM_E_PARAM;
  22526         return (rv);
  22527     }
  22528 
  22529     switch(endpoint_protocol) {
  22530 
  22531 #if defined(INCLUDE_BHH)
  22532         case bcmOamProtocolBhh:
  22533             *endpoint_count = 0;
  22534             rv = _bcm_kt2_bhh_endpoint_faults_multi_get(
  22535                     unit,
  22536                     flags,
  22537                     max_endpoints,
  22538                     faults,
  22539                     endpoint_count);
  22540         break;
  22541 #endif
  22542         default:
  22543             rv = BCM_E_UNAVAIL;
  22544             break;
  22545     }
  22546 
  22547     return rv;
  22548 
  22549 }
  22550 
  22551 /* This function assumes passed endpoint is a PORT MEP configured over trunk. */
  22552 int _bcm_kt2_oam_ep_trunk_ports_add_del_internal(int unit, _bcm_oam_hash_data_t *h_data_p, 
  22553                                     int max_ports, bcm_gport_t *port_arr, uint8 add)
  22554 {
  22555     _bcm_oam_hash_data_t old_hash_data;
  22556     bcm_oam_endpoint_info_t ep_info;
  22557     uint32 sglp = 0, dglp = 0;
  22558     bcm_port_t src_pp_port = 0, dst_pp_port = 0, pp_port = 0;
  22559     uint32 svp = 0;
  22560     int vp_valid = 0;
  22561     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  22562     bcm_gport_t tx_gport;
  22563     int i, module_id = 0;
  22564     uint8 active_mdl = 0;
  22565     
  22566 
  22567     bcm_oam_endpoint_info_t_init(&ep_info);
  22568     /* **********************************************
  22569      *               SW configurations
  22570  */
  22571     /* Keep a copy of old hash data for comparisons.
  22572      */
  22573     sal_memcpy(&old_hash_data, h_data_p, sizeof(_bcm_oam_hash_data_t));
  22574 
  22575 
  22576     /* Call endpoint get to get the endpoint info */
  22577     BCM_IF_ERROR_RETURN(bcm_kt2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info));
  22578     /* First call endpoint gport resolve to correctly update new
  22579      * sglp, dglp, src_pp_port, dst_pp_port variables.
  22580      */
  22581     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_endpoint_gport_resolve(unit, &ep_info, &sglp, &dglp,
  22582                                                             &src_pp_port, &dst_pp_port, &svp,
  22583                                                             &trunk_id, &vp_valid, &tx_gport));
  22584                                                             
  22585     /* Update the h_data_p. */
  22586     h_data_p->sglp                 = sglp;
  22587     h_data_p->dglp                 = dglp;
  22588     h_data_p->src_pp_port          = src_pp_port;
  22589     h_data_p->dst_pp_port          = dst_pp_port;
  22590     h_data_p->resolved_trunk_gport = tx_gport;
  22591 
  22592     /* ************************************************
  22593      *               HW configurations
  22594  */
  22595 
  22596     for (i = 0; i < max_ports; i++) {
  22597         BCM_IF_ERROR_RETURN
  22598             (_bcm_kt2_pp_port_to_modport_get(unit, port_arr[i],
  22599                                              &module_id, &pp_port));
  22600         if (add) {
  22601             /* _bcm_kt2_oam_trunk_port_mdl_config needs to be called so that
  22602              * new trunk members are programmed with MDL_BITMAP correctly.
  22603              */
  22604             BCM_IF_ERROR_RETURN(_bcm_kt2_oam_stm_table_update(unit, module_id, pp_port, h_data_p));
  22605             BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_update(unit, pp_port, 0, h_data_p, &active_mdl));
  22606         } else {
  22607             /* Delete the old ports' MDL BITMAP using _bcm_kt2_oam_port_mdl_update. And
  22608              * clear STM table if this is the last endpoint on this port.
  22609              */
  22610             BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_update(unit, pp_port, 1, h_data_p, &active_mdl));
  22611             if (active_mdl == 0) {
  22612                 /* Setting index = -1 so that rx indexes are not freed up, since there are
  22613                  * other ports on the trunk on which this endpoint is placed.
  22614                  */
  22615                 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_stm_table_clear(unit, module_id, -1,
  22616                             pp_port, 
  22617                             h_data_p));
  22618             }
  22619         }
  22620     }
  22621     
  22622     if (h_data_p->dst_pp_port != old_hash_data.dst_pp_port) {
  22623         /* If dst_pp_port has changed, delete the old EGR_PORT MDL_PASSIVE BITMAP and
  22624          * program the new port's EGR_PORT MDL_PASSIVE_BITMAP.
  22625          */
  22626         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_passive_update(unit,1, &old_hash_data, 0));
  22627         BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_passive_update(unit, 0 /* not reset */,
  22628                                                                 h_data_p, active_mdl));
  22629         
  22630         if (ep_info.ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) {
  22631             /* If dst_pp_port has changed, modify the LMEP table to reflect new
  22632              * dst pp port and corresponding queue number.
  22633              */
  22634             BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lmep_down_modify_new_dest_port(unit, h_data_p));
  22635         }
  22636     }
  22637 
  22638     return BCM_E_NONE;
  22639 } 
  22640 
  22641 
  22642 int _bcm_kt2_oam_trunk_ports_add_del_internal(int unit, bcm_gport_t trunk_gport, 
  22643                                 int max_ports, bcm_gport_t *port_arr, uint8 add)
  22644 {
  22645     int rv = BCM_E_NONE;
  22646     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  22647     _bcm_oam_control_t  *oc = NULL;
  22648     _bcm_oam_hash_data_t *h_data_p = NULL;
  22649     int i;
  22650 
  22651 
  22652     /* Validate port array and max ports inputs */
  22653     if (port_arr == NULL || max_ports == 0) {
  22654         return BCM_E_PARAM;
  22655     }
  22656 
  22657     /* Check the gport is TRUNK */ 
  22658     if (!(BCM_GPORT_IS_TRUNK(trunk_gport))) {
  22659         return BCM_E_PARAM;
  22660     }
  22661 
  22662     /* Get Trunk ID value from Gport */
  22663     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  22664 
  22665     if (trunk_id == BCM_TRUNK_INVALID) {
  22666         return BCM_E_PARAM;
  22667     }
  22668 
  22669     /* Get OAM control structure */
  22670     BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc));
  22671     _BCM_OAM_LOCK(oc);
  22672 
  22673     for (i = 0; i < oc->ep_count; i++) {
  22674         h_data_p = &oc->oam_hash_data[i];
  22675         /* This API is supported only for PORT MEPs on Trunks */
  22676         if ((ETH_TYPE(h_data_p->type)) && 
  22677             (h_data_p->in_use) && 
  22678             (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) &&
  22679             (h_data_p->gport      == trunk_gport) &&
  22680             (h_data_p->trunk_id == trunk_id)) {
  22681             rv = _bcm_kt2_oam_ep_trunk_ports_add_del_internal(unit, h_data_p, max_ports, port_arr, add); 
  22682             if (BCM_FAILURE(rv)) {
  22683                 _BCM_OAM_UNLOCK(oc);
  22684                 return rv;
  22685             }
  22686         }
  22687     }
  22688     _BCM_OAM_UNLOCK(oc);
  22689     return rv;
  22690 }
  22691 
  22692 int bcm_kt2_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 
  22693                                 int max_ports, bcm_gport_t *port_arr)
  22694 {
  22695     return _bcm_kt2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 1);
  22696 }
  22697 int bcm_kt2_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 
  22698                                 int max_ports, bcm_gport_t *port_arr)
  22699 {
  22700     return _bcm_kt2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 0);
  22701 }
  22702 #endif /* BCM_KATANA2_SUPPORT */