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


      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 Saber2 family of devices.
     11  */
     12 
     13 #include <shared/bsl.h>
     14 #include <sal/core/libc.h>
     15 #include <soc/defs.h>
     16 #include <soc/drv.h>
     17 #include <soc/mem.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 #include <soc/scache.h>
     24 #include <soc/tnl_term.h>
     25 
     26 #include <bcm/l3.h>
     27 #include <bcm/oam.h>
     28 #include <bcm/cosq.h>
     29 
     30 #include <bcm_int/esw/oam.h>
     31 #include <bcm_int/esw/port.h>
     32 #include <bcm_int/esw/l3.h>
     33 #include <bcm_int/esw/switch.h>
     34 #include <bcm_int/esw/triumph.h>
     35 #include <bcm_int/esw/triumph3.h>
     36 #include <bcm_int/esw/katana2.h>
     37 #include <bcm_int/esw/saber2.h>
     38 #include <bcm_int/esw/virtual.h>
     39 #include <bcm_int/esw_dispatch.h>
     40 #include <bcm_int/esw/failover.h>
     41 #include <soc/shared/bhh_pkt.h>
     42 #include <soc/shared/mpls_lm_dm_pkt.h>
     43 #include <soc/shared/olp_pkt.h>
     44 #include <soc/shared/olp_pack.h>
     45 #include <soc/shared/oam_pm_shared.h>
     46 
     47 #if defined(BCM_METROLITE_SUPPORT)
     48 #include <soc/metrolite.h>
     49 #endif
     50 #if defined(BCM_SABER2_SUPPORT)
     51 #include <bcm_int/esw/stack.h>
     52 #include <bcm_int/esw/subport.h>
     53 
     54 #if defined(INCLUDE_BHH)
     55 #include <bcm_int/esw/bhh.h>
     56 #include <bcm_int/esw/bhh_sdk_pack.h>
     57 #endif /* INCLUDE_BHH */
     58 #include <soc/shared/oam_pm_pack.h>
     59 
     60 /*
     61  * Saber2 A0 has HW issue in inserting MP_GROUP entry due to TCAM atomicity.
     62  * The HW Issue is fixed in B0 revision.
     63  */ 
     64 static uint16 g_dev_id = 0;
     65 static uint8 g_rev_id = 0;
     66 
     67 #define BCM_SB2_TCAM_ATOMICITY_DISABLE(unit) {\
     68     if (g_rev_id == 0) {\
     69         soc_cm_get_id(unit, &g_dev_id, &g_rev_id); \
     70     }\
     71     if (g_rev_id == BCM56260_A0_REV_ID) { \
     72         BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r,\
     73 					REG_PORT_ANY, TCAM_ATOMIC_WRITE_ENABLEf, 0)); \
     74     }\
     75 }
     76 #define BCM_SB2_TCAM_ATOMICITY_ENABLE(unit) {\
     77     if (g_rev_id == 0) {\
     78         soc_cm_get_id(unit, &g_dev_id, &g_rev_id); \
     79     }\
     80     if (g_rev_id == BCM56260_A0_REV_ID) { \
     81         BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r,\
     82 					REG_PORT_ANY, TCAM_ATOMIC_WRITE_ENABLEf, 1)); \
     83     }\
     84 }
     85 
     86 /* Vlans will be programmed in ING/EGR MP_GROUP table depending on MEP_TYPE */
     87 #define _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC    0
     88 /* Inner & Outer Vlan will be always programmed in ING/EGR MP_GROUP table */
     89 #define _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT 1
     90 
     91 #if defined(INCLUDE_ETH_LM_DM)
     92 #include <bcm_int/esw/eth_lm_dm.h>
     93 #include <soc/shared/eth_lm_dm_pkt.h>
     94 #include <bcm_int/esw/eth_lm_dm_feature.h>
     95 #include <bcm_int/esw/eth_lm_dm_sdk_msg.h>
     96 #include <bcm_int/esw/eth_lm_dm_sdk_pack.h>
     97 STATIC void
     98 _bcm_sb2_oam_pm_ethlmdm_callback_thread(void *param);
     99 
    100 STATIC int
    101 _bcm_sb2_eth_lm_dm_loss_delete (int unit,
    102         _bcm_oam_control_t   *oc,
    103         _bcm_oam_hash_data_t *h_data_p);
    104 STATIC int
    105 _bcm_sb2_eth_lm_dm_delay_delete (int unit,
    106         _bcm_oam_control_t   *oc,
    107         _bcm_oam_hash_data_t *h_data_p);
    108 STATIC int
    109 _bcm_sb2_eth_lm_dm_event_mask_set(int unit);
    110 #endif /* INCLUDE_ETH_LM_DM */
    111 
    112 #if defined(INCLUDE_MPLS_LM_DM)
    113 #include <bcm_int/esw/mpls_lm_dm.h>
    114 #include <bcm_int/esw/mpls_lm_dm_feature.h>
    115 #include <bcm_int/esw/mpls_lm_dm_sdk_msg.h>
    116 #include <bcm_int/esw/mpls_lm_dm_sdk_pack.h>
    117 STATIC void
    118 _bcm_sb2_oam_pm_mplslmdm_callback_thread(void *param);
    119 STATIC int
    120 _bcm_sb2_mpls_lm_dm_loss_delete(int unit, _bcm_oam_hash_data_t *h_data_p);
    121 STATIC int
    122 _bcm_sb2_mpls_lm_dm_delay_delete(int unit, _bcm_oam_hash_data_t *h_data_p);
    123 STATIC int
    124 _bcm_sb2_mpls_lm_dm_event_mask_set(int unit);
    125 #endif
    126 
    127 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH)
    128 #include <soc/uc.h>
    129 #endif
    130 
    131 STATIC int
    132 _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(int unit,
    133                        _bcm_oam_hash_data_t *h_data_p,
    134                               int *num_ma_idx_entries,
    135                        shr_idxres_list_handle_t *pool);
    136 STATIC int
    137 _bcm_sb2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc);
    138 STATIC int
    139 _bcm_sb2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc);
    140 STATIC int
    141 _bcm_sb2_oam_control_get(int unit, _bcm_oam_control_t **oc);
    142 
    143 
    144 STATIC INLINE bcm_oam_endpoint_t
    145 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t   *oc, int ma_idx);
    146 
    147 /*
    148  * Device OAM control structure.
    149  */
    150 _bcm_oam_control_t *_sb2_oam_control[SOC_MAX_NUM_DEVICES];
    151 
    152 typedef struct _bcm_oam_pm_profile_int_info_s {
    153     int id_status;
    154     bcm_oam_pm_profile_info_t pm_profile;
    155 }_bcm_oam_pm_profile_int_info_t;
    156 typedef struct _bcm_oam_pm_profile_control_s {
    157     _bcm_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES];
    158 }_bcm_oam_pm_profile_control_t;
    159 
    160 
    161 _bcm_oam_pm_profile_control_t *pm_profile_control[SOC_MAX_NUM_DEVICES];
    162 
    163 #define _BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id)          (pmc->profile_info[id].id_status == 1)
    164 #define _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, id)             (&(pmc->profile_info[id].pm_profile))
    165 #define _BCM_SB2_SET_PM_CTRL_PROFILE_IN_USE(pmc, id)      (pmc->profile_info[id].id_status = 1)
    166 #define _BCM_SB2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id)  (pmc->profile_info[id].id_status = 0)
    167 
    168 #define _BCM_SB2_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_REPLACE)
    169 
    170 #define _BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_WITH_ID)
    171 
    172 #define _BCM_SB2_PM_PROFILE_ID_VALID(profile_id) \
    173     ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES))
    174 
    175 /* PM raw data events handling macros */
    176 #define _BCM_SB2_EVENT_TYPE_PM_EVENT(event_types) ((SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) ||\
    177                                                    (SHR_BITGET(event_types.w, bcmOAMEventEthLmDmRawData)) ||\
    178                                                    (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData)))
    179 
    180 #define _BCM_SB2_BHH_OAM_PM_EVENT_TYPE(event_type) (event_type == bcmOAMEventBHHRawData)
    181 
    182 #if defined (INCLUDE_BHH)
    183 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \
    184                             (oc->pm_bhh_lmdm_data_collection_mode != \
    185                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    186 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \
    187                             (oc->pm_bhh_lmdm_data_collection_mode == \
    188                                 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    189 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \
    190                             (oc->pm_bhh_lmdm_data_collection_mode == \
    191                                 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    192 static int sb2_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE;
    193 #else
    194 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0
    195 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0
    196 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    197 #endif
    198 #if defined (INCLUDE_ETH_LM_DM)
    199 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \
    200                             (oc->pm_eth_lmdm_data_collection_mode != \
    201                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    202 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\
    203                             (oc->pm_eth_lmdm_data_collection_mode == \
    204                                  _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    205 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)\
    206                             (oc->pm_eth_lmdm_data_collection_mode == \
    207                                  _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    208 #else
    209 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) 0
    210 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0
    211 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    212 #endif
    213 #if defined (INCLUDE_MPLS_LM_DM)
    214 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \
    215                             (oc->pm_mpls_lmdm_data_collection_mode != \
    216                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    217 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\
    218                             (oc->pm_mpls_lmdm_data_collection_mode ==\
    219                                 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    220 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \
    221                             (oc->pm_mpls_lmdm_data_collection_mode ==\
    222                                 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    223 #else
    224 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) 0
    225 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0
    226 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    227 #endif
    228 
    229 #define _BCM_SB2_OAM_PM_BHH_EVENT_IDX 0
    230 #define _BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX 1 
    231 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX 2
    232 
    233 #define PM_READ_DONE_INDEX(event_idx) \
    234                     (oc->pm_read_done_index[event_idx])
    235 #define PM_WRITE_DONE_INDEX(event_idx) \
    236                     (oc->pm_write_done_index[event_idx])
    237 #define INCREMENT_PM_WRITE_DONE_INDEX(event_idx) \
    238                     (((oc->pm_write_done_index[event_idx])+1)%BCM_OAM_MAX_PM_BUFFERS)
    239 #define NUM_FREE_BUFFERS(event_idx)\
    240                     (oc->pm_num_free_raw_data_buffers[event_idx])
    241 #define SET_NUM_FREE_BUFFERS(event_idx, value)\
    242                     (oc->pm_num_free_raw_data_buffers[event_idx] = value)
    243 #define DECR_NUM_FREE_BUFFERS(event_idx) \
    244     SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) - 1))
    245 #define INCR_NUM_FREE_BUFFERS(event_idx) \
    246     SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) + 1))
    247 
    248 
    249 
    250 #define VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(index) \
    251         (index < BCM_OAM_MAX_PM_BUFFERS)
    252                     
    253 
    254 /* * * * * * * * * * * * * * * * * * *
    255  *            OAM MACROS             *
    256  */
    257 /*
    258  * Macro:
    259  *     _BCM_OAM_IS_INIT (internal)
    260  * Purpose:
    261  *     Check that the unit is valid and confirm that the oam functions
    262  *     are initialized.
    263  * Parameters:
    264  *     unit - BCM device number
    265  * Notes:
    266  *     Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or
    267  *     return(BCM_E_INIT) if fails.
    268  */
    269 #define _BCM_OAM_IS_INIT(unit)                                               \
    270             do {                                                             \
    271                 if (!soc_feature(unit, soc_feature_oam)) {                   \
    272                     return (BCM_E_UNAVAIL);                                  \
    273                 }                                                            \
    274                 if (_sb2_oam_control[unit] == NULL) {                        \
    275                     LOG_ERROR(BSL_LS_BCM_OAM, \
    276                               (BSL_META_U(unit, \
    277                                           "OAM(unit %d) Error: Module not initialized\n"), \
    278                                unit));                                       \
    279                     return (BCM_E_INIT);                                     \
    280                 }                                                            \
    281             } while (0)
    282 
    283 /*
    284  *Macro:
    285  *     _BCM_OAM_LOCK
    286  * Purpose:
    287  *     Lock take the OAM control mutex
    288  * Parameters:
    289  *     control - Pointer to OAM control structure.
    290  */
    291 #define _BCM_OAM_LOCK(control) \
    292             sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER)
    293 
    294 /*
    295  * Macro:
    296  *     _BCM_OAM_UNLOCK
    297  * Purpose:
    298  *     Lock take the OAM control mutex
    299  * Parameters:
    300  *     control - Pointer to OAM control structure.
    301  */
    302 #define _BCM_OAM_UNLOCK(control) \
    303             sal_mutex_give((control)->oc_lock);
    304 /*
    305  * Macro:
    306  *     _BCM_OAM_HASH_DATA_CLEAR
    307  * Purpose:
    308  *      Clear hash data memory occupied by one endpoint.
    309  * Parameters:
    310  *     _ptr_    - Pointer to endpoint hash data memory. 
    311  */
    312 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \
    313             sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t));
    314 
    315 /*
    316  * Macro:
    317  *     _BCM_OAM_HASH_DATA_HW_IDX_INIT
    318  * Purpose:
    319  *     Initialize hardware indices to invalid index for an endpoint hash data.
    320  * Parameters:
    321  *     _ptr_    - Pointer to endpoint hash data memory. 
    322  */
    323 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_)                             \
    324             do {                                                          \
    325                     (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX);      \
    326                     (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX);     \
    327                     (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX);    \
    328                     (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX);    \
    329                     (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \
    330                     (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX);   \
    331                     (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX);   \
    332             } while (0)
    333 /*
    334  * Macro:
    335  *     _BCM_OAM_ALLOC
    336  * Purpose:
    337  *      Generic memory allocation routine.
    338  * Parameters:
    339  *    _ptr_     - Pointer to allocated memory.
    340  *    _ptype_   - Pointer type.
    341  *    _size_    - Size of heap memory to be allocated.
    342  *    _descr_   - Information about this memory allocation.
    343  */
    344 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_)                     \
    345             do {                                                         \
    346                 if (NULL == (_ptr_)) {                                   \
    347                    (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \
    348                 }                                                        \
    349                 if((_ptr_) != NULL) {                                    \
    350                     sal_memset((_ptr_), 0, (_size_));                    \
    351                 }  else {                                                \
    352                     LOG_ERROR(BSL_LS_BCM_OAM, \
    353                               (BSL_META("OAM Error: Allocation failure %s\n"), \
    354                                (_descr_)));                              \
    355                 }                                                        \
    356             } while (0)
    357 
    358 /*
    359  * Macro:
    360  *     _BCM_OAM_GROUP_INDEX_VALIDATE
    361  * Purpose:
    362  *     Validate OAM Group ID value.
    363  * Parameters:
    364  *     _group_ - Group ID value.
    365  */
    366 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_)                               \
    367             do {                                                             \
    368                 if ((_group_) < 0 || (_group_) >= oc->group_count) {         \
    369                     LOG_ERROR(BSL_LS_BCM_OAM, \
    370                               (BSL_META("OAM(unit %d) Error: Invalid Group ID = %d.\n"), \
    371                                unit, _group_));                              \
    372                     return (BCM_E_PARAM);                                    \
    373                 }                                                            \
    374             } while (0);
    375 
    376 /*
    377  * Macro:
    378  *     _BCM_OAM_EP_INDEX_VALIDATE
    379  * Purpose:
    380  *     Validate OAM Endpoint ID value.
    381  * Parameters:
    382  *     _ep_ - Endpoint ID value.
    383  */
    384 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_)                               \
    385             do {                                                       \
    386                 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) {            \
    387                     LOG_ERROR(BSL_LS_BCM_OAM, \
    388                               (BSL_META("OAM(unit %d) Error: Invalid Endpoint ID" \
    389                                " = %d.\n"), unit, _ep_));              \
    390                     return (BCM_E_PARAM);                              \
    391                 }                                                      \
    392             } while (0);
    393 
    394 
    395 /*
    396  * Macro:
    397  *     _BCM_OAM_RMEP_INDEX_VALIDATE
    398  * Purpose:
    399  *     Validate OAM Endpoint ID value.
    400  * Parameters:
    401  *     _ep_ - Endpoint ID value.
    402  */
    403 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_)                              \
    404             do {                                                        \
    405                 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) {           \
    406                     LOG_ERROR(BSL_LS_BCM_OAM, \
    407                               (BSL_META("OAM(unit %d) Error: Invalid RMEP Index" \
    408                                " = %d.\n"), unit, _ep_));               \
    409                     return (BCM_E_PARAM);                               \
    410                 }                                                       \
    411             } while (0);
    412 /*
    413  * Macro:
    414  *    DGLP_MODULE_ID_SHIFT_BITS 
    415  * Purpose:
    416  *     shift bits value used for SB2/ML for constructing DGLP.
    417  */
    418 #define DGLP_MODULE_ID_SHIFT_BITS          7
    419 
    420 /*
    421  * Macro:
    422  *     _BCM_OAM_KEY_PACK
    423  * Purpose:
    424  *     Pack the hash table look up key fields.
    425  * Parameters:
    426  *     _dest_ - Hash key buffer.
    427  *     _src_  - Hash key field to be packed.
    428  *     _size_ - Hash key field size in bytes.
    429  */
    430 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_)            \
    431             do {                                          \
    432                 sal_memcpy((_dest_), (_src_), (_size_));  \
    433                 (_dest_) += (_size_);                     \
    434             } while (0)
    435 /*
    436  * Macro:
    437  *     _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT
    438  * Purpose:
    439  *     Return the shift_bit value for Mod_id reuired for DGLP.
    440  * Parameters:
    441  *     _shift_bits_  - Shift bit value.
    442  */
    443 #if defined (BCM_METROLITE_SUPPORT)
    444 #define _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(_shift_bits_,_u_)                          \
    445     do {                                                                                \
    446             if (SOC_IS_METROLITE(unit)) {                                               \
    447                 _shift_bits_ = DGLP_MODULE_ID_SHIFT_BITS;                               \
    448             } else {                                                                    \
    449                 _shift_bits_ = (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_)));  \
    450             }                                                                           \
    451     } while(0)
    452 #else
    453 #define _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(_shift_bits_,_u_)                          \
    454     do {                                                                                \
    455             _shift_bits_ = (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_)));      \
    456     } while(0)
    457 #endif
    458 
    459 /*
    460  * Macro:
    461  *     _BCM_SB2_OAM_MOD_PORT_TO_GLP
    462  * Purpose:
    463  *     Construct hadware GLP value from module ID, port ID and Trunk ID value.
    464  * Parameters:
    465  *     _modid_ - Module ID.
    466  *     _port_  - Port ID.
    467  *     _trunk_ - Trunk (1 - TRUE/0 - FALSE).
    468  *     _tgid_  - Trunk ID.
    469  */
    470 #define _BCM_SB2_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_)     \
    471     do {                                                                    \
    472         uint32  shift_bits = -1;                                            \
    473         _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(shift_bits,_u_);               \
    474         if ((_tgid_) != -1) {                                               \
    475             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    476                 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1)           \
    477                 & (_tgid_)));                                               \
    478         } else {                                                            \
    479             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    480                 | ((SOC_MODID_MAX(_u_) & (_m_))                             \
    481                 << (shift_bits)                                             \
    482                 | (SOC_PORT_ADDR_MAX(_u_) & (_p_))));                       \
    483         }                                                                   \
    484         LOG_DEBUG(BSL_LS_BCM_OAM,                                           \
    485                   (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"),        \
    486                    _u_, _m_, _p_, _t_, _tgid_, _glp_));                     \
    487     } while (0)
    488 
    489 /*
    490  * Macro:
    491  *     _BCM_OAM_GLP_XXX
    492  * Purpose:
    493  *     Get components of generic logical port value.
    494  * Parameters:
    495  *     _glp_ - Generic logical port.
    496  */
    497 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_glp_) (0x1 & ((_glp_) >> 15))
    498 #define _BCM_OAM_GLP_TRUNK_ID_GET(_glp_)  (0xFF & (_glp_))
    499 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7))
    500 #define _BCM_OAM_GLP_PORT_GET(_glp_)      (0x7F & (_glp_))
    501 
    502 /*
    503  * Macro:
    504  *     _BCM_OAM_EP_LEVEL_XXX
    505  * Purpose:
    506  *     Maintenance domain level bit count and level max value.   
    507  * Parameters:
    508  *     _glp_ - Generic logical port.
    509  */
    510 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT))
    511 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1)
    512 
    513 #define BHH_TYPE(type) ( (type == bcmOAMEndpointTypeBHHMPLS) ||        \
    514                 (type == bcmOAMEndpointTypeBHHMPLSVccv)||\
    515                 (type == bcmOAMEndpointTypeBhhSection)||\
    516                 (type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    517                 (type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    518                 (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    519                          ) 
    520 
    521 #define BHH_EP_TYPE(ep) (BHH_TYPE(ep->type)) 
    522 
    523 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\
    524                 (ep->type == bcmOAMEndpointTypeBhhSection)||\
    525                 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    526                 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    527                 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    528                                      )
    529 
    530 #define BHH_EP_LSP_TYPE(ep) (ep->type == bcmOAMEndpointTypeBHHMPLS)
    531 
    532 
    533 #define MPLS_LM_DM_ENDPOINT_TYPE(ep) (\
    534         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionPort)||\
    535         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)||\
    536         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)||\
    537         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)||\
    538         (ep->type == bcmOAMEndpointTypeMplsLmDmPw)||\
    539         (ep->type == bcmOAMEndpointTypeMplsLmDmLsp)\
    540                                      )
    541 
    542 #define MPLS_LM_DM_SECTION_ENDPOINT_TYPE(ep) (\
    543         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionPort)||\
    544         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)||\
    545         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)||\
    546         (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan))
    547 
    548 #define MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep) (\
    549         (ep->type == bcmOAMEndpointTypeMplsLmDmLsp))
    550 
    551 #define MPLS_LM_DM_PW_ENDPOINT_TYPE(ep) (\
    552         (ep->type == bcmOAMEndpointTypeMplsLmDmPw))
    553 
    554 #define _BCM_OAM_EP_IS_MIP(info) (info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
    555 
    556 #define ETH_TYPE(type) (type == bcmOAMEndpointTypeEthernet)
    557 
    558 #define _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID  0x1
    559 #define _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_EP_ID   0x2
    560 
    561 /*
    562  * Macro:
    563  *     BCM_WB_XXX
    564  * Purpose:
    565  *    OAM module scache version information.
    566  * Parameters:
    567  *    (major number, minor number)
    568  */
    569 #ifdef BCM_WARM_BOOT_SUPPORT
    570 #define BCM_WB_VERSION_1_0      SOC_SCACHE_VERSION(1,0)
    571 #define BCM_WB_VERSION_1_1      SOC_SCACHE_VERSION(1,1)
    572 #define BCM_WB_VERSION_1_2      SOC_SCACHE_VERSION(1,2)
    573 /* This new version incorporates new MA_INDEX allocation scheme.
    574  * Recovery of Endpoints allocated in new scheme will be
    575  * done for this version or higher only */
    576 #define BCM_WB_VERSION_1_3      SOC_SCACHE_VERSION(1,3)
    577 /* This ver supports recovery of PM profile */
    578 #define BCM_WB_VERSION_1_4      SOC_SCACHE_VERSION(1,4)
    579 #define BCM_WB_VERSION_1_5      SOC_SCACHE_VERSION(1,5)
    580 #define BCM_WB_VERSION_1_6      SOC_SCACHE_VERSION(1,6)
    581 #define BCM_WB_VERSION_1_7      SOC_SCACHE_VERSION(1,7)
    582 #define BCM_WB_VERSION_1_8      SOC_SCACHE_VERSION(1,8)
    583 #define BCM_WB_VERSION_1_9      SOC_SCACHE_VERSION(1,9)
    584 #define BCM_WB_VERSION_1_10     SOC_SCACHE_VERSION(1,10)
    585 #define BCM_WB_DEFAULT_VERSION  BCM_WB_VERSION_1_10
    586 
    587 STATIC int bcm_sb2_oam_scache_alloc(int unit);
    588 #endif
    589 
    590 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE \
    591         (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count))
    592 
    593 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)\
    594         (ma_base_index + ma_offset)
    595 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\
    596         (oc->ma_idx_count + ma_base_index + ma_offset)
    597 
    598 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, ma_offset, is_upmep)\
    599         ((is_upmep)?\
    600         _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\
    601         :_BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset))
    602 
    603 /* Macros for endpoint id locations for different endpoint types. */
    604 #define _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE \
    605         (sizeof(bcm_oam_endpoint_t) * (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + oc->egr_ma_idx_count))
    606 
    607 #define _BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(mep_index) \
    608                 (sizeof(bcm_oam_endpoint_t) * mep_index)
    609 #define _BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(mep_index) \
    610                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + mep_index))
    611 #define _BCM_SB2_OAM_RMEP_SCACHE_LOCATION(rmep_index) \
    612                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + rmep_index))
    613 #define _BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(mep_index) \
    614                 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + oc->rmep_count + mep_index))
    615 
    616 /* Warmboot helper for PM Id association */
    617 int _bcm_sb2_oam_pmid_scache_size(int unit)
    618 {
    619     int count = 0;
    620 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
    621     _bcm_oam_control_t *oc = _sb2_oam_control[unit];
    622     count =
    623 #if defined(INCLUDE_ETH_LM_DM)
    624         oc->eth_lm_dm_sess_count +
    625 #endif
    626 #if defined(INCLUDE_MPLS_LM_DM)
    627         oc->mpls_lm_dm_sess_count +
    628 #endif
    629 #if defined(INCLUDE_BHH)
    630         oc->bhh_endpoint_count +
    631 #endif
    632         count;
    633 #endif
    634     return (sizeof(int8) * (count));
    635 }
    636 
    637 int _bcm_sb2_oam_eth_pmid_scache_loc(int unit, int sess)
    638 {
    639     return (sizeof(int8) * (sess));
    640 }
    641 
    642 int _bcm_sb2_oam_mpls_pmid_scache_loc(int unit, int sess)
    643 {
    644 #if defined(INCLUDE_ETH_LM_DM)
    645     _bcm_oam_control_t *oc = _sb2_oam_control[unit];
    646 #endif
    647     return (sizeof(int8) * (
    648 #if defined(INCLUDE_ETH_LM_DM)
    649                 oc->eth_lm_dm_sess_count +
    650 #endif
    651                 sess));
    652 }
    653 
    654 int _bcm_sb2_oam_bhh_pmid_scache_loc(int unit, int sess)
    655 {
    656 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
    657     _bcm_oam_control_t *oc = _sb2_oam_control[unit];
    658 #endif
    659     return (sizeof(int8) * (
    660 #if defined(INCLUDE_ETH_LM_DM)
    661                 oc->eth_lm_dm_sess_count +
    662 #endif
    663 #if defined(INCLUDE_MPLS_LM_DM)
    664                 oc->mpls_lm_dm_sess_count +
    665 #endif
    666                 sess));
    667 }
    668 
    669 #if defined(INCLUDE_ETH_LM_DM)
    670 int8 *eth_oam_id_map = NULL;
    671 #endif
    672 #if defined(INCLUDE_MPLS_LM_DM)
    673 int8 *mpls_oam_id_map = NULL;
    674 #endif
    675 
    676 /* Macro for PM profile information */
    677 #define _BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE \
    678         (sizeof(_bcm_oam_pm_profile_int_info_t) * (_BCM_OAM_MAX_PM_PROFILES))
    679 
    680 typedef struct _bcm_lmdm_oam_scache_info_s {
    681 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
    682     bcm_vlan_t      vlan;
    683     bcm_vlan_t      inner_vlan;
    684     uint16          inner_tpid;
    685     uint16          outer_tpid;
    686     uint8           vlan_pri;
    687     uint8           inner_vlan_pri;
    688     bcm_mac_t       dst_mac_address;
    689     bcm_mac_t       src_mac_address;
    690     uint32          lm_dm_int_flag;
    691     uint32          lm_dm_uc_session_id;
    692 #endif
    693 #if defined(INCLUDE_MPLS_LM_DM)
    694     bcm_oam_group_t group_index;
    695 #endif
    696     bcm_vpn_t       vpn;
    697     uint8           egr_ctr_field_id;
    698 }_bcm_lmdm_oam_scache_info_t;
    699 
    700 #define _BCM_SB2_OAM_DOWN_MEP_LMDM_SCACHE_INFO_SIZE \
    701     (sizeof(_bcm_lmdm_oam_scache_info_t) * oc->ma_idx_count)
    702 
    703 #if defined(INCLUDE_ETH_LM_DM)
    704 #define _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE \
    705     (sizeof(_bcm_lmdm_oam_scache_info_t) * oc->egr_ma_idx_count)
    706 #else
    707 #define _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE (0)
    708 #endif
    709 
    710 #define _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE \
    711     (_BCM_SB2_OAM_DOWN_MEP_LMDM_SCACHE_INFO_SIZE + \
    712      _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE)
    713 
    714 #define _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(mep_idx) \
    715     (sizeof(_bcm_lmdm_oam_scache_info_t) * (mep_idx))
    716 #define _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(mep_idx) \
    717     (sizeof(_bcm_lmdm_oam_scache_info_t) * (oc->ma_idx_count + (mep_idx)))
    718 
    719 #if defined(INCLUDE_MPLS_LM_DM)
    720 typedef struct _bcm_mpls_lmdm_egr_label_scache_info_s {
    721     bcm_mpls_label_t egr_label;
    722     uint8 exp;
    723     uint8 ttl;
    724 }_bcm_sb2_oam_egr_label_scache_info_t;
    725 #endif
    726 
    727 #if defined(INCLUDE_MPLS_LM_DM)
    728 #define _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE \
    729     (sizeof(_bcm_sb2_oam_egr_label_scache_info_t) * oc->ma_idx_count)
    730 #define _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(mep_idx) \
    731     (sizeof(_bcm_sb2_oam_egr_label_scache_info_t) * mep_idx)
    732 #else
    733 #define _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE (0)
    734 #endif
    735 
    736 
    737 /* Define the port used in OLP-XGS communication */
    738 #define _BCM_OAM_OLP_COMMUNICATION_PORT  0x7f
    739 
    740 
    741 /* OAM opcode control profile actions */
    742 #define _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING      0
    743 #define _BCM_SB2_OAM_OC_PROF_DROP                  1
    744 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1          2
    745 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2          3
    746 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE      4
    747 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE   5
    748 
    749 /* OAM_OPCODE_GROUP table key construction */
    750 /* COMPRESSED PROTOCOL : 
    751  * 0 - ETH-OAM
    752  * 1 - BHH-OAM
    753  * 2 - MPLS LM DM 
    754  * 3 - Reserved.
    755  */
    756 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_ETH       0
    757 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_BHH       1
    758 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_MPLS_LMDM 2
    759 
    760 /*KEY=(COMPRESSED_PROTOCOL(2bits),OPCODE(8 bits)) 
    761   OPCODE_GROUP 
    762   CPU_OPCODE */
    763 
    764 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_MASK   0xff /* 8 bits set */
    765 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_PROTO_MASK    0x3 /* 2 bits set */
    766 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_BITS   8
    767 
    768 #define _BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(proto, opcode) (\
    769                         ((proto & _BCM_SB2_OAM_OPCODE_GROUP_KEY_PROTO_MASK) \
    770                          << _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_BITS) |\
    771                         (opcode & _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_MASK))
    772 #define _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode) \
    773      (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_ETH, \
    774                                        opcode))
    775 
    776 #define _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode) \
    777      (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_BHH, \
    778                                        opcode))
    779 
    780 #define _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode) \
    781      (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_MPLS_LMDM, \
    782                                        opcode))
    783 
    784 
    785 /* Ethernet OAM opcode groups */
    786 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_CCM           3
    787 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBR           4
    788 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBM           5
    789 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTR           4
    790 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTM           6
    791 
    792 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1       7
    793 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2       8
    794 
    795 /* BHH OAM opcode groups */
    796 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_CCM           9
    797 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBR           10
    798 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBM           11
    799 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTR           12
    800 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTM           13
    801 
    802 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1       14
    803 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2       15
    804 
    805 /* MPLS LM DM opcode groups */
    806 #define _BCM_SB2_OPCODE_GROUP_MPLS_LM               0
    807 #define _BCM_SB2_OPCODE_GROUP_MPLS_ILM              1
    808 #define _BCM_SB2_OPCODE_GROUP_MPLS_DM               1
    809 #define _BCM_SB2_OPCODE_GROUP_MPLS_LM_PLUS_DM       2
    810 #define _BCM_SB2_OPCODE_GROUP_MPLS_ILM_PLUS_DM      2
    811 
    812 #define _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX   0
    813 #define _BCM_SB2_OAM_NUM_OPCODE_GROUPS             16
    814 
    815 #define _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE       _BCM_SB2_OAM_NUM_OPCODE_GROUPS
    816 
    817 /* ING LM COUNT PROFILE TABLE entries per profile(256 - Max no. of OAM opcode */
    818 #define _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE        bcmOamOpcodeMax
    819 
    820 /* CPU_OPCODE is filled one of these values */
    821 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW          0
    822 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM       1
    823 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH         2
    824 
    825 /* OLP_HDR_TYPE_COMPRESSED is filled with one of the below values.
    826  *
    827  * NOTE: BFD always has olp hdr type compressed to 0. HW automatically fills it. 
    828  * Should not be changed.
    829  */
    830 
    831 #define _BCM_SB2_NO_OF_BITS_COMP_HDR 5
    832 #define _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(comp_hdr) \
    833              ((1 << _BCM_SB2_NO_OF_BITS_COMP_HDR) | comp_hdr)
    834 
    835 #define _BCM_SB2_BFD_OLP_HDR_TYPE_COMPRESSED              0
    836 
    837 #define _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED      1
    838 #define _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED       2
    839 #define _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED       3
    840 #define _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED 4
    841 
    842 #define _BCM_SB2_BHH_CCM_OLP_HDR_TYPE_COMPRESSED          5
    843 #define _BCM_SB2_BHH_LM_OLP_HDR_TYPE_COMPRESSED           6
    844 #define _BCM_SB2_BHH_DM_OLP_HDR_TYPE_COMPRESSED           7
    845 #define _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED     8
    846 
    847 #define _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED    9
    848 #define _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED     10
    849 #define _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED 11
    850 #define _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED    12
    851 #define _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED 13
    852 #define _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED           14
    853 #define _BCM_SB2_OTH_ACH_OLP_HDR_COMPRESSED               15
    854 
    855 #define _BCM_SB2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED                \
    856     _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                           \
    857                               _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED)
    858 
    859 #define _BCM_SB2_ETH_OAM_UP_MEP_LM_OLP_HDR_TYPE_COMPRESSED                  \
    860     _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                            \
    861                               _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED)
    862 
    863 #define _BCM_SB2_ETH_OAM_UP_MEP_DM_OLP_HDR_TYPE_COMPRESSED                  \
    864     _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                            \
    865                               _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED)
    866 
    867 #define _BCM_SB2_ETH_OAM_UP_MEP_OTHER_OC_OLP_HDR_TYPE_COMPRESSED            \
    868     _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                            \
    869                         _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED)
    870 
    871 #define _BCM_SAT_UPMEP_OLP_HDR_COMPRESSED                                    \
    872     _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(                             \
    873                                  _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED)
    874 
    875 /* OAM_OPCODE_CONTROL_PROFILE profile sizes */
    876 #define _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE (sizeof(oam_opcode_control_profile_entry_t) *\
    877                                              _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE)
    878 #define _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE (sizeof(egr_oam_opcode_control_profile_entry_t) *\
    879                                              _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE)
    880 /* ING_OAM_LM_COUNTER_CONTROL_PROFILE profile sizes */
    881 #define _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE (sizeof(ing_lm_counter_control_entry_t) *\
    882                                              _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE)
    883 #define _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE (sizeof(egr_lm_counter_control_entry_t) *\
    884                                              _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE)
    885                                              
    886 /* 4 bits from opcode group form lower 4 bits of profile index */
    887 #define NO_OF_BITS_OC_GRP 4 
    888 /* 8 bits from lm count profile form lower 8 bits of profile index */
    889 #define NO_OF_BITS_LM_COUNT_PROFILE 8 
    890 /* Oam opcode control Profile pointer from profile index and vice versa */
    891 #define _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(index) (index >> NO_OF_BITS_OC_GRP)
    892 #define _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(ptr) (ptr << NO_OF_BITS_OC_GRP)
    893 
    894 /* Oam opcode control Profile pointer from profile index and vice versa */
    895 #define _BCM_ML_OAM_GET_LM_COUNTER_CONTROL_PROFILE_PTR_FROM_INDEX(index) (index >> NO_OF_BITS_LM_COUNT_PROFILE)
    896 #define _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(ptr) (ptr << NO_OF_BITS_LM_COUNT_PROFILE)
    897 
    898 /* OLP_HEADER_TYPE filled with one of the following values.
    899  * TX is never filled in mapping table since OLP_TX header doesnt use
    900  * the mapping table. 
    901  */
    902 #define _BCM_SB2_OLP_HDR_TYPE_TX 0
    903 #define _BCM_SB2_OLP_HDR_TYPE_RX 1
    904 
    905 /* No. of counter pool that can be programmed per endpoint */
    906 #define _SB2_OAM_COUNTER_SIZE    3
    907 
    908 /* OLP_HEADER_SUBTYPE filled with one of the following values */
    909 /* Down mep subtypes */
    910 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_CCM             0x01
    911 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_LM              0x02
    912 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_DM              0x03
    913 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC        0x04
    914 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_CCM                 0x05
    915 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_LM                  0x06
    916 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_DM                  0x07
    917 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_OTHER_OC            0x08
    918 #define _BCM_SB2_OLP_HDR_SUBTYPE_BFD                     0x09
    919 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM           0x0A
    920 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DM            0x0B
    921 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM        0x0C
    922 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM           0x0D
    923 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM        0x0E
    924 #define _BCM_SB2_OLP_HDR_SUBTYPE_SAT                     0x0F
    925 #define _BCM_SB2_OLP_HDR_SUBTYPE_OTH_ACH                 0x10
    926 
    927 /* Up mep subtypes */
    928 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM             0x11
    929 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM              0x12
    930 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_DM              0x13
    931 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_OTHER_OC        0x14
    932 #define _BCM_SB2_OLP_HDR_SUBTYPE_SAT_UP                        0x15
    933 
    934 
    935 
    936 /* Possible values for MPLS_OAM_DOWNMEP_ENABLE field in MPLS_ENTRY memory */
    937 #define _BCM_SB2_MPLS_OAM_DISABLE               0
    938 #define _BCM_SB2_MPLS_OAM_ENABLE_BHH            1
    939 #define _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM      2
    940 #define _BCM_SB2_MPLS_OAM_ENABLE_RESERVED       3
    941 
    942 /* Key formation and profile mapping ptr logic for 
    943    ING/EGR_SERVICE_PRI_MAP_0/1/2 table */
    944 #define NO_OF_BITS_FOR_PRI 4
    945 #define _BCM_SB2_SERVICE_PRI_MAP_PROFILE_INDEX_TO_MAP_PTR(profile_index) \
    946                                       (profile_index >> NO_OF_BITS_FOR_PRI)
    947 #define _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr) \
    948                                       (map_ptr << NO_OF_BITS_FOR_PRI)
    949 
    950 /* The default ING/EGR_SERVICE_PRI_MAP_0/1/2 would be 0 */
    951 #define _BCM_OAM_PRI_MAP_DEFAULT_INDEX  0
    952 
    953 /* The valid ctr pool ids are 0/1/2 */
    954 #define _BCM_SB2_OAM_VALID_CTR_POOL_ID(ctr_pool_id) \
    955                    (ctr_pool_id >= 0 && ctr_pool_id <= 2)
    956 
    957 typedef struct _oam_tpid_s {
    958     uint32                       tpid;
    959     uint32                       ref_count;
    960 } _oam_tpid_t;
    961 
    962 typedef struct _bcm_sb2_opcode_group_entry_s {
    963     int key;
    964     int opcode_group;
    965     int cpu_opcode;
    966     int olp_hdr_type_compressed;
    967 } _bcm_sb2_opcode_group_entry_t;
    968 
    969 typedef struct _bcm_sb2_mpls_oam_ach_type_config_entry_s {
    970     int valid;
    971     int ach_type;
    972     int opcode_valid;
    973     int opcode;
    974     int lm_count_enable;
    975     int protocol_type;
    976 } _bcm_sb2_mpls_oam_ach_type_config_entry_t;
    977 
    978 #define BCM_MAX_TPID_ENTRIES 4
    979 #define BCM_MAX_INNER_TPID_ENTRIES 1
    980 
    981 
    982 #define BCM_OAM_TPID_TYPE_OUTER   0
    983 #define BCM_OAM_TPID_TYPE_INNER   1
    984 #define BCM_OAM_TPID_TYPE_SUBPORT 2
    985 #define BCM_OAM_TPID_VALUE_ZERO   0
    986 #define BCM_OAM_DEFAULT_TPID      0x8100
    987 #define BCM_OAM_TPID_9100         0x9100
    988 #define BCM_OAM_TPID_88A8         0x88A8
    989 #define DGLP_LAG_ID_INDICATOR_SHIFT_BITS   15
    990 #define _BCM_OAM_OPCODE_TYPE_CCM           1
    991 #define _BCM_OAM_OPCODE_TYPE_LBR           2
    992 #define _BCM_OAM_OPCODE_TYPE_LBM           3
    993 #define _BCM_OAM_OPCODE_TYPE_LTR           4
    994 #define _BCM_OAM_OPCODE_TYPE_LTM           5
    995 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST 6
    996 #define _BCM_OAM_OPCODE_TYPE_AIS           33
    997 #define _BCM_OAM_OPCODE_TYPE_LCK           35
    998 #define _BCM_OAM_OPCODE_TYPE_TST           37
    999 #define _BCM_OAM_OPCODE_TYPE_LIN_APS       39
   1000 #define _BCM_OAM_OPCODE_TYPE_RING_APS      40
   1001 #define _BCM_OAM_OPCODE_TYPE_MCC           41
   1002 #define _BCM_OAM_OPCODE_TYPE_LMM           43
   1003 #define _BCM_OAM_OPCODE_TYPE_LMR           42
   1004 #define _BCM_OAM_OPCODE_TYPE_1DM           45
   1005 #define _BCM_OAM_OPCODE_TYPE_DMM           47
   1006 #define _BCM_OAM_OPCODE_TYPE_DMR           46
   1007 #define _BCM_OAM_OPCODE_TYPE_EXM           49
   1008 #define _BCM_OAM_OPCODE_TYPE_EXR           48
   1009 #define _BCM_OAM_OPCODE_TYPE_VSM           51
   1010 #define _BCM_OAM_OPCODE_TYPE_VSR           50
   1011 #define _BCM_OAM_OPCODE_TYPE_SLR           54
   1012 #define _BCM_OAM_OPCODE_TYPE_SLM           55
   1013 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST  0xFF
   1014 #define _BCM_OAM_OPCODE_TYPE_CFM_MASK      0x3E
   1015 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK  0xFFFFFFFF
   1016 #define _BCM_OAM_DGLP1_PROFILE_PTR         0x1
   1017 #define _BCM_OAM_DGLP2_PROFILE_PTR         0x2
   1018 #define _BCM_OAM_SERVICE_PRI_MAX_OFFSET    0x7
   1019 
   1020 STATIC _oam_tpid_t
   1021            (*_sb2_oam_outer_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES];
   1022 
   1023 STATIC _oam_tpid_t
   1024            (*_sb2_oam_inner_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_INNER_TPID_ENTRIES];
   1025 
   1026 STATIC _oam_tpid_t
   1027            (*_sb2_oam_subport_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES];
   1028 
   1029 STATIC sal_mutex_t _sb2_outer_tpid_lock[BCM_MAX_NUM_UNITS];
   1030 STATIC sal_mutex_t _sb2_inner_tpid_lock[BCM_MAX_NUM_UNITS];
   1031 STATIC sal_mutex_t _sb2_subport_tpid_lock[BCM_MAX_NUM_UNITS];
   1032 
   1033 /* OAM TPID registers and default values */
   1034 STATIC int sb2_outer_tpid[4] = { OUTER_TPID_0r, OUTER_TPID_1r, 
   1035                           OUTER_TPID_2r, OUTER_TPID_3r };
   1036 
   1037 STATIC int sb2_default_outer_tpid[4] = { BCM_OAM_DEFAULT_TPID, BCM_OAM_TPID_9100, 
   1038                           BCM_OAM_TPID_88A8, BCM_OAM_TPID_VALUE_ZERO};
   1039 
   1040 STATIC int sb2_subport_tpid[4] = { SUBPORT_TAG_TPID_0r, SUBPORT_TAG_TPID_1r, 
   1041                             SUBPORT_TAG_TPID_2r, SUBPORT_TAG_TPID_3r };
   1042 
   1043 #define SB2_OAM_OUTER_TPID_TAB(unit) _sb2_oam_outer_tpid_tab[unit]
   1044 #define SB2_OAM_INNER_TPID_TAB(unit) _sb2_oam_inner_tpid_tab[unit]
   1045 #define SB2_OAM_SUBPORT_TPID_TAB(unit) _sb2_oam_subport_tpid_tab[unit]
   1046 
   1047 #define SB2_OAM_OUTER_TPID_ENTRY(unit, index) \
   1048     ((*_sb2_oam_outer_tpid_tab[unit])[index].tpid)
   1049 
   1050 #define SB2_OAM_INNER_TPID_ENTRY(unit, index) \
   1051     ((*_sb2_oam_inner_tpid_tab[unit])[index].tpid)
   1052 
   1053 #define SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) \
   1054     ((*_sb2_oam_subport_tpid_tab[unit])[index].tpid)
   1055 
   1056 #define SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) \
   1057     ((*_sb2_oam_outer_tpid_tab[unit])[index].ref_count)
   1058 
   1059 #define SB2_OAM_INNER_TPID_REF_COUNT(unit, index) \
   1060     ((*_sb2_oam_inner_tpid_tab[unit])[index].ref_count)
   1061 
   1062 #define SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) \
   1063     ((*_sb2_oam_subport_tpid_tab[unit])[index].ref_count)
   1064 
   1065 #define SB2_OAM_OUTER_TPID_TAB_INIT_CHECK(unit) \
   1066     if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
   1067 
   1068 #define SB2_OAM_INNER_TPID_TAB_INIT_CHECK(unit) \
   1069     if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
   1070 
   1071 #define SB2_OAM_SUBPORT_TPID_TAB_INIT_CHECK(unit) \
   1072     if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { return BCM_E_INIT; }
   1073 
   1074 #define BCM_SB2_OUTER_TPID_MUTEX(_u_) _sb2_outer_tpid_lock[_u_]
   1075 #define BCM_SB2_INNER_TPID_MUTEX(_u_) _sb2_inner_tpid_lock[_u_]
   1076 #define BCM_SB2_SUBPORT_TPID_MUTEX(_u_) _sb2_subport_tpid_lock[_u_]
   1077 
   1078 #define BCM_SB2_OUTER_TPID_LOCK(_u_)   \
   1079          ((_sb2_outer_tpid_lock[_u_]) ? \
   1080          sal_mutex_take(_sb2_outer_tpid_lock[_u_], sal_mutex_FOREVER) :  \
   1081          (BCM_E_INTERNAL))
   1082 
   1083 #define BCM_SB2_INNER_TPID_LOCK(_u_)   \
   1084          ((_sb2_inner_tpid_lock[_u_]) ? \
   1085          sal_mutex_take(_sb2_inner_tpid_lock[_u_], sal_mutex_FOREVER) :  \
   1086          (BCM_E_INTERNAL))
   1087 
   1088 #define BCM_SB2_SUBPORT_TPID_LOCK(_u_)   \
   1089          ((_sb2_subport_tpid_lock[_u_]) ? \
   1090          sal_mutex_take(_sb2_subport_tpid_lock[_u_], sal_mutex_FOREVER) :  \
   1091          (BCM_E_INTERNAL))
   1092 
   1093 #define BCM_SB2_OUTER_TPID_UNLOCK(_u_)  \
   1094          ((_sb2_outer_tpid_lock[_u_]) ? \
   1095          sal_mutex_give(_sb2_outer_tpid_lock[_u_]) : \
   1096          (BCM_E_INTERNAL))
   1097 
   1098 #define BCM_SB2_INNER_TPID_UNLOCK(_u_)  \
   1099          ((_sb2_inner_tpid_lock[_u_]) ? \
   1100          sal_mutex_give(_sb2_inner_tpid_lock[_u_]) : \
   1101          (BCM_E_INTERNAL))
   1102 
   1103 #define BCM_SB2_SUBPORT_TPID_UNLOCK(_u_)  \
   1104          ((_sb2_subport_tpid_lock[_u_]) ? \
   1105          sal_mutex_give(_sb2_subport_tpid_lock[_u_]) : \
   1106          (BCM_E_INTERNAL))
   1107 
   1108 /* Checks hash_data pointer's int_flags field */
   1109 #define _BCM_OAM_ETH_OAM_VP_TYPE(type, int_flags)  \
   1110                 ((type == bcmOAMEndpointTypeEthernet)\
   1111              && (int_flags & _BCM_OAM_ENDPOINT_IS_VP_BASED))
   1112 #define _BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p) \
   1113         (_BCM_OAM_ETH_OAM_VP_TYPE(h_data_p->type, h_data_p->int_flags))
   1114 
   1115 
   1116 /* * * * * * * * * * * * * * * * * * * * * * * * *
   1117  *         OAM function prototypes               *
   1118  */
   1119 
   1120 int _bcm_sb2_oam_convert_action_to_opcode_entry(
   1121                                         int unit,
   1122                                         bcm_oam_endpoint_action_t *action, 
   1123                                         bcm_oam_endpoint_t ep_id,
   1124                                         void *profile,
   1125                                         uint8  *opcode_profile_changed);
   1126 int
   1127 _sb2_oam_opcode_control_field_set(int unit, _bcm_oam_hash_data_t *h_data_p,
   1128                                   bcm_oam_action_type_t action, 
   1129                                   soc_mem_t mem, int oam_opcode, uint32 value,
   1130                                   void *profile);
   1131 
   1132 int
   1133 _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(int unit, 
   1134         _bcm_oam_hash_data_t *hash_data, int enable);
   1135 int 
   1136 _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(int unit, 
   1137         _bcm_oam_hash_data_t *hash_data, int enable);
   1138 int
   1139 _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(int unit, 
   1140         _bcm_oam_hash_data_t *hash_data, int enable);
   1141 int
   1142 _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(int unit,
   1143         _bcm_oam_hash_data_t *hash_data, int enable);
   1144 int 
   1145 _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(int unit, 
   1146         _bcm_oam_hash_data_t *hash_data, int enable);
   1147 
   1148 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_BHH)
   1149 STATIC int
   1150 _bcm_sb2_oam_olp_encap_header_decap(int unit,
   1151                                  uint8     *encap_data,
   1152                                  uint8     *counter_size,
   1153                                  uint32    *counter_base_id,
   1154                                  uint32    *counter_offset,
   1155                                  uint8     *counter_action,
   1156                                  uint8     *ts_mode,
   1157                                  uint8     *lm_pdu_counter_offset,
   1158                                  bcm_cos_t *int_pri,
   1159                                  uint32    *counter_lm_counter_byte_offset);
   1160 #endif
   1161 
   1162 /* * * * * * * * * * * * * * * * * * * * * * * * *
   1163  *         OAM global data initialization      *
   1164  */
   1165 #if defined(INCLUDE_BHH)
   1166 
   1167 #define BHH_COSQ_INVALID          0xFFFF
   1168 
   1169 static uint8 bhh_lsp_egr_lookup_key = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_EP_ID;
   1170 /*
   1171  * Macro:
   1172  *     _BCM_OAM_BHH_IS_VALID (internal)
   1173  * Purpose:
   1174  *     Check that the BHH feature is available on this unit
   1175  * Parameters:
   1176  *     unit - BCM device number
   1177  * Notes:
   1178  *     Results in return(BCM_E_UNAVAIL),
   1179  */
   1180 #define _BCM_OAM_BHH_IS_VALID(unit)                                          \
   1181             do {                                                             \
   1182                 if (!soc_feature(unit, soc_feature_bhh)) {                   \
   1183                     return (BCM_E_UNAVAIL);                                  \
   1184                 }                                                            \
   1185             } while (0)
   1186 
   1187 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \
   1188         (ep - _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc))
   1189 
   1190 #define BCM_OAM_BHH_GET_LSP_KEY(hash_data) \
   1191     ((bhh_lsp_egr_lookup_key == _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID)   ? \
   1192               ((hash_data)->name)                                             : \
   1193               ((hash_data)->ep_id - _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) + 1))
   1194 
   1195 #define BCM_OAM_BHH_GET_SDK_EP(ep) \
   1196         (ep + _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc))
   1197 
   1198 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \
   1199             do {                                                       \
   1200                 if (((_ep_) < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) ||         \
   1201                     ((_ep_) >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)           \
   1202                                          + oc->bhh_endpoint_count))) { \
   1203                     LOG_ERROR(BSL_LS_BCM_OAM, \
   1204                               (BSL_META_U(unit, \
   1205                                           "OAM(unit %d) Error: Invalid Endpoint ID" \
   1206                                           " = %d.\n"), unit, _ep_));   \
   1207                     _BCM_OAM_UNLOCK(oc);                               \
   1208                     return (BCM_E_PARAM);                              \
   1209                 }                                                      \
   1210             } while (0);
   1211 
   1212 
   1213 STATIC int
   1214 _bcm_sb2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
   1215                                     uint16 s_len, uint32 s_data,
   1216                                     uint8 r_subclass, uint16 *r_len);
   1217                                     
   1218 STATIC int
   1219 _bcm_sb2_oam_bhh_hw_init(int unit);
   1220 STATIC void
   1221 _bcm_sb2_oam_bhh_callback_thread(void *param);
   1222 STATIC int
   1223 _bcm_sb2_oam_bhh_event_mask_set(int unit);
   1224 STATIC int
   1225 bcm_sb2_oam_bhh_endpoint_create(int unit,
   1226                                 bcm_oam_endpoint_info_t *endpoint_info,
   1227                                 _bcm_oam_hash_key_t  *hash_key);
   1228 STATIC int
   1229 bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(int unit,
   1230                                         bcm_oam_endpoint_info_t *ep_info);
   1231 STATIC uint8 *
   1232 _bcm_sb2_oam_bhh_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls);
   1233 
   1234 STATIC void
   1235 _bcm_sb2_oam_bhh_get_egress_label_from_encap(_bcm_oam_hash_data_t *h_data_p,
   1236                                              uint8 *encap_data,
   1237                                              uint16 encap_length,
   1238                                              _mpls_label_t *label);
   1239 
   1240 #endif /* INCLUDE_BHH */
   1241 
   1242 #define BCM_OAM_ABS(x)   (((x) < 0) ? (-(x)) : (x))
   1243 
   1244 #if defined(INCLUDE_ETH_LM_DM)
   1245 
   1246 #define SB2_ETH_LM_DM_UC_NUM            2
   1247 #define ML_ETH_LM_DM_UC_NUM             0
   1248 
   1249 #define BCM_SB2_ETH_LM_DM_RX_CHANNEL     11
   1250 #define BCM_ML_ETH_LM_DM_RX_CHANNEL      5
   1251 #define BCM_SB2_ETH_LM_DM_UC_RX_CHANNEL  1 /* Rx DMA channel uC view (0..3 ) */
   1252 #define BCM_SB2_ETH_LM_DM_CPU_COS        45
   1253 #define BCM_ML_ETH_LM_DM_CPU_COS         37
   1254 
   1255 STATIC int
   1256 _bcm_sb2_oam_eth_lm_dm_msg_send_receive(int unit, uint8 s_subclass,
   1257                                     uint16 s_len, uint32 s_data,
   1258                                     uint8 r_subclass, uint16 *r_len);
   1259 STATIC int
   1260 _bcm_sb2_oam_eth_lm_dm_hw_init(int unit);
   1261 
   1262 #endif /* INCLUDE_ETH_LM_DM */
   1263 
   1264 #if defined(INCLUDE_MPLS_LM_DM)
   1265 
   1266 #define MPLS_LM_DM_COSQ_INVALID          0xFFFF
   1267 #define MPLS_LM_DM_UC_NUM                2
   1268 #define MPLS_LM_DM_MAX_SESSIONS          256
   1269 
   1270 #define MPLS_LM_DM_RX_CHANNEL_SDK_VIEW       11
   1271 #define MPLS_LM_DM_RX_CHANNEL_UC_VIEW        1
   1272 #define MPLS_LM_DM_CPU_COS                   45
   1273 
   1274 #define _MPLS_LM_DM_MPLS_MAX_LABELS    4   /* Max MPLS labels in Saber2 */
   1275 
   1276 
   1277 STATIC int
   1278 _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(int unit, uint8 s_subclass,
   1279                                     uint16 s_len, uint32 s_data,
   1280                                     uint8 r_subclass, uint16 *r_len);
   1281 
   1282 STATIC int
   1283 _bcm_sb2_oam_mpls_lm_dm_hw_init(int unit);
   1284 
   1285 #if defined(BCM_METROLITE_SUPPORT)
   1286 STATIC int
   1287 _bcm_ml_oam_mpls_lm_dm_hw_init(int unit);
   1288 #endif /* BCM_METROLITE_SUPPORT */
   1289 
   1290 #endif /* INCLUDE_MPLS_LM_DM */
   1291 
   1292 
   1293 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
   1294 STATIC int
   1295 bcm_sb2_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns);
   1296 #endif
   1297 STATIC int
   1298 _bcm_sb2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass,
   1299                                     uint16 s_len, uint32 s_data,
   1300                                     uint8 r_subclass, uint16 *r_len);
   1301 
   1302 #if defined (INCLUDE_BHH) || defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM)
   1303 STATIC void _bcm_sb2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc,
   1304                                              mos_msg_data_t *event_msg);
   1305 #endif
   1306 
   1307 int _bcm_sb2_oam_pm_init(int unit);
   1308 
   1309 int
   1310 _bcm_sb2_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label,
   1311                                      uint32 sglp, int *mpls_index,
   1312                                      mpls_entry_entry_t *found_entry);
   1313 
   1314 STATIC int
   1315 bcm_sb2_oam_hw_ccm_tx_ctr_update(int unit,
   1316         bcm_oam_endpoint_info_t *ep_info);
   1317 
   1318 #define _BCM_SB2_OAM_MAX_CCM_INTERVALS 8
   1319 /*
   1320  * Saber2 device OAM CCM intervals array initialization..
   1321  */
   1322 STATIC uint32 _sb2_ccm_intervals[] =
   1323 {
   1324     BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED,
   1325     BCM_OAM_ENDPOINT_CCM_PERIOD_3MS,
   1326     BCM_OAM_ENDPOINT_CCM_PERIOD_10MS,
   1327     BCM_OAM_ENDPOINT_CCM_PERIOD_100MS,
   1328     BCM_OAM_ENDPOINT_CCM_PERIOD_1S,
   1329     BCM_OAM_ENDPOINT_CCM_PERIOD_10S,
   1330     BCM_OAM_ENDPOINT_CCM_PERIOD_1M,
   1331     BCM_OAM_ENDPOINT_CCM_PERIOD_10M,
   1332     _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED
   1333 };
   1334 
   1335 /*   
   1336  * OAM hardware interrupts to software events mapping array initialization.
   1337  * _sb2_oam_interrupts[] =
   1338  *     {Interrupt status register, Remote MEP index field, MA index field,
   1339  *          CCM_INTERRUPT_CONTROLr - Interrupt status Field,
   1340  *          OAM event type}. 
   1341  */
   1342 STATIC _bcm_oam_interrupt_t _sb2_oam_interrupts[] =
   1343 {
   1344     /* 1. Port down interrupt. */
   1345     {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1346         ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf,
   1347         bcmOAMEventEndpointPortDown},
   1348 
   1349     /* 2. Port up interrupt. */
   1350     {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1351         ANY_RMEP_TLV_PORT_UP_INT_ENABLEf,
   1352         bcmOAMEventEndpointPortUp},
   1353 
   1354     /* 3. Interface down interrupt. */
   1355     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1356         ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf,
   1357         bcmOAMEventEndpointInterfaceDown},
   1358 
   1359     /* 4. Interface up interrupt. */
   1360     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1361         ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf,
   1362         bcmOAMEventEndpointInterfaceUp},
   1363 
   1364     /* 5. Interface TLV Testing to Up interrupt. */
   1365     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1366         ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf,
   1367         bcmOAMEventEndpointInterfaceTestingToUp},
   1368 
   1369     /* 6. Interface TLV Unknown to Up interrupt. */
   1370     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1371         ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf,
   1372         bcmOAMEventEndpointInterfaceUnknownToUp},
   1373 
   1374     /* 7. Interface TLV Dormant to Up interrupt. */
   1375     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1376         ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf,
   1377         bcmOAMEventEndpointInterfaceDormantToUp},
   1378 
   1379     /* 8. Interface TLV Not present to Up interrupt. */
   1380     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1381         ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf,
   1382         bcmOAMEventEndpointInterfaceNotPresentToUp},
   1383 
   1384     /* 9. Interface Link Layer Down to Up interrupt. */
   1385     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1386         ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf,
   1387         bcmOAMEventEndpointInterfaceLLDownToUp},
   1388 
   1389     /* 10. Interface up to testing transition interrupt. */
   1390     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1391         ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf,
   1392         bcmOAMEventEndpointInterfaceTesting},
   1393 
   1394     /* 11. Interface up to unknown transition interrupt. */
   1395     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1396         ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf,
   1397         bcmOAMEventEndpointInterfaceUnkonwn},
   1398 
   1399     /* 11. Interface up to dormant transition interrupt. */
   1400     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1401         ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf,
   1402         bcmOAMEventEndpointInterfaceDormant},
   1403 
   1404     /* 11. Interface up to not present transition interrupt. */
   1405     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1406         ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf,
   1407         bcmOAMEventEndpointInterfaceNotPresent},
   1408 
   1409     /* 11. Interface up to Link Layer Down transition interrupt. */
   1410     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
   1411         ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf,
   1412         bcmOAMEventEndpointInterfaceLLDown},
   1413 
   1414     /* 12. Low MDL or unexpected MAID interrupt. */
   1415     {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
   1416         XCON_CCM_DEFECT_INT_ENABLEf,
   1417         bcmOAMEventGroupCCMxcon},
   1418 
   1419     /*
   1420      * 13. Remote MEP lookup failed or CCM interval mismatch during Remote MEP
   1421      *    lookup interrupt.
   1422      */
   1423     {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
   1424         ERROR_CCM_DEFECT_INT_ENABLEf,
   1425         bcmOAMEventGroupCCMError},
   1426 
   1427     /*
   1428      * 14. Some Remote defect indicator interrupt - aggregated health of remote
   1429      *    MEPs.
   1430      */
   1431     {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
   1432         SOME_RDI_DEFECT_INT_ENABLEf,
   1433         bcmOAMEventGroupRemote},
   1434 
   1435     /* 15. Aggregate health of remote MEP state machines interrupt. */
   1436     {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
   1437         SOME_RMEP_CCM_DEFECT_INT_ENABLEf,
   1438         bcmOAMEventGroupCCMTimeout},
   1439 
   1440     /* Invalid Interrupt - Always Last */
   1441     {INVALIDr, INVALIDf, 0, bcmOAMEventCount}
   1442 };
   1443 
   1444 /*
   1445  * 0AM Group faults array initialization.
   1446  */
   1447 STATIC _bcm_oam_fault_t _sb2_oam_group_faults[] =
   1448 {
   1449     {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf,
   1450         BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08},
   1451 
   1452     {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf,
   1453         BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04},
   1454 
   1455     {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf,
   1456         BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02},
   1457 
   1458     {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf,
   1459         BCM_OAM_GROUP_FAULT_REMOTE, 0x01},
   1460 
   1461     {0, 0, 0, 0}
   1462 };
   1463 
   1464 /*
   1465  * 0AM Endpoint faults array initialization.
   1466  */
   1467 STATIC _bcm_oam_fault_t _sb2_oam_endpoint_faults[] =
   1468 {
   1469     {CURRENT_RMEP_PORT_STATUS_DEFECTf,
   1470         STICKY_RMEP_PORT_STATUS_DEFECTf,
   1471         BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08},
   1472 
   1473     {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf,
   1474         STICKY_RMEP_INTERFACE_STATUS_DEFECTf,
   1475         BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04},
   1476 
   1477     {CURRENT_RMEP_CCM_DEFECTf,
   1478         STICKY_RMEP_CCM_DEFECTf,
   1479         BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20},
   1480 
   1481     {CURRENT_RMEP_LAST_RDIf,
   1482         STICKY_RMEP_LAST_RDIf,
   1483         BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10},
   1484 
   1485     {0, 0, 0, 0}
   1486 };
   1487 
   1488 typedef struct _bcm_sb2_oam_intr_en_fields_s {
   1489     soc_field_t field;
   1490     uint32      value;
   1491 } _bcm_sb2_oam_intr_en_fields_t;
   1492  
   1493 STATIC _bcm_sb2_oam_intr_en_fields_t _sb2_oam_intr_en_fields[bcmOAMEventCount] =
   1494 {
   1495     /*
   1496      * Note:
   1497      * The order of hardware field names in the below initialization
   1498      * code must match the event enum order in bcm_oam_event_type_t.
   1499      */
   1500     { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1},
   1501     { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1},
   1502     { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1},
   1503     { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1504     { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1505     { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1506     { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1507     { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1508     { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
   1509     { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1},
   1510     { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1},
   1511     { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1},
   1512     { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1},
   1513     { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1},
   1514     { XCON_CCM_DEFECT_INT_ENABLEf, 1},
   1515     { ERROR_CCM_DEFECT_INT_ENABLEf, 1},
   1516     { SOME_RDI_DEFECT_INT_ENABLEf, 1},
   1517     { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1},
   1518     { INVALIDf, 0},
   1519     { INVALIDf, 0},
   1520     { INVALIDf, 0},
   1521     { INVALIDf, 0},
   1522     { INVALIDf, 0},
   1523     { INVALIDf, 0},
   1524     { INVALIDf, 0},
   1525     { INVALIDf, 0},
   1526     { INVALIDf, 0},
   1527     { INVALIDf, 0},
   1528     { INVALIDf, 0}
   1529 };
   1530 
   1531 /* LM counter related fields */
   1532 STATIC sb2_mep_ctr_info_t sb2_mep_ctr_info[] = {
   1533     { CTR1_VALIDf, CTR1_BASE_PTRf,            
   1534       CTR1_MEP_TYPEf, CTR1_MEP_MDLf,                      
   1535       CTR1_SERVICE_PRI_MAP_PROFILE_PTRf,
   1536       CTR1_SERVICE_PRI_MAP_MODEf,
   1537       CTR1_LM_PAYLOAD_OFFSETf,
   1538       CTR1_LM_COS_OFFSETf, CTR1_POOL_IDf
   1539     },
   1540     { CTR2_VALIDf, CTR2_BASE_PTRf,
   1541       CTR2_MEP_TYPEf, CTR2_MEP_MDLf,
   1542       CTR2_SERVICE_PRI_MAP_PROFILE_PTRf, 
   1543       CTR2_SERVICE_PRI_MAP_MODEf,
   1544       CTR2_LM_PAYLOAD_OFFSETf,
   1545       CTR2_LM_COS_OFFSETf, CTR2_POOL_IDf
   1546     }
   1547 };
   1548 
   1549 /* OLP header type mapping */
   1550 typedef struct _bcm_sb2_olp_hdr_type_mapping_s {
   1551     bcm_field_olp_header_type_t     field_olp_hdr_type;
   1552     uint8                           mem_index;
   1553     uint8                           subtype;
   1554 } _bcm_sb2_olp_hdr_type_mapping_t;
   1555 
   1556 
   1557 STATIC _bcm_sb2_olp_hdr_type_mapping_t sb2_olp_hdr_type_mapping[] = {
   1558 
   1559 /* BFD */
   1560 {bcmFieldOlpHeaderTypeBfdOam,  _BCM_SB2_BFD_OLP_HDR_TYPE_COMPRESSED,
   1561                                _BCM_SB2_OLP_HDR_SUBTYPE_BFD},
   1562 /* ETH OAM Down MEP */
   1563 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED,
   1564                                  _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_CCM},
   1565 
   1566 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED,
   1567                                 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_LM},
   1568 
   1569 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED,
   1570                                 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_DM},
   1571 
   1572 {bcmFieldOlpHeaderTypeEthOamOthers, _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED,
   1573                                     _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC},
   1574 
   1575 /* BHH */
   1576 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_SB2_BHH_CCM_OLP_HDR_TYPE_COMPRESSED,
   1577                                  _BCM_SB2_OLP_HDR_SUBTYPE_BHH_CCM},
   1578 
   1579 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_SB2_BHH_LM_OLP_HDR_TYPE_COMPRESSED,
   1580                                 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_LM},
   1581 
   1582 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_SB2_BHH_DM_OLP_HDR_TYPE_COMPRESSED,
   1583                                 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_DM},
   1584 
   1585 {bcmFieldOlpHeaderTypeBhhOamOthers, _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED,
   1586                                     _BCM_SB2_OLP_HDR_SUBTYPE_BHH_OTHER_OC},
   1587 
   1588 /* MPLS LM/DM */
   1589 {bcmFieldOlpHeaderTypeRfc6374Dlm, _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED,
   1590                                   _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM},
   1591 
   1592 {bcmFieldOlpHeaderTypeRfc6374Dm, _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED,
   1593                                  _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DM},
   1594 
   1595 {bcmFieldOlpHeaderTypeRfc6374DlmPlusDm, _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED,
   1596                                         _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM},
   1597 
   1598 {bcmFieldOlpHeaderTypeRfc6374Ilm, _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED,
   1599                                   _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM},
   1600 
   1601 {bcmFieldOlpHeaderTypeRfc6374IlmPlusDm, _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED,
   1602                                         _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM},
   1603 
   1604 
   1605 /* Down SAT */
   1606 {bcmFieldOlpHeaderTypeSat, _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED,
   1607                            _BCM_SB2_OLP_HDR_SUBTYPE_SAT},
   1608 
   1609 /* Other ACH */
   1610 {bcmFieldOlpHeaderTypeOtherAch, _BCM_SB2_OTH_ACH_OLP_HDR_COMPRESSED,
   1611                                 _BCM_SB2_OLP_HDR_SUBTYPE_OTH_ACH},
   1612 
   1613 /*
   1614  * UpMEP header types are not programmable by FP, but OAM pipeline lookup
   1615  * can assign UpMEP subtypes.
   1616  */
   1617 
   1618 /* ETH-OAM Up MEP */
   1619 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_SB2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED,
   1620                                       _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM},
   1621 
   1622 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_SB2_ETH_OAM_UP_MEP_LM_OLP_HDR_TYPE_COMPRESSED,
   1623                                      _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM},
   1624 
   1625 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_SB2_ETH_OAM_UP_MEP_DM_OLP_HDR_TYPE_COMPRESSED,
   1626                                      _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_DM},
   1627 
   1628 {bcmFieldOlpHeaderTypeEthOamUpMepOthers, _BCM_SB2_ETH_OAM_UP_MEP_OTHER_OC_OLP_HDR_TYPE_COMPRESSED,
   1629                                          _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_OTHER_OC},
   1630 
   1631 /* Up SAT*/
   1632 {bcmFieldOlpHeaderTypeUpSat, _BCM_SAT_UPMEP_OLP_HDR_COMPRESSED,
   1633                              _BCM_SB2_OLP_HDR_SUBTYPE_SAT_UP}
   1634 };
   1635 
   1636 static uint8 sb2_olp_hdr_type_count = sizeof(sb2_olp_hdr_type_mapping) /
   1637                                            sizeof(sb2_olp_hdr_type_mapping[0]);
   1638 
   1639 
   1640 /* * * * * * * * * * * * * * * * * * * * * * * * *
   1641  *            Static local functions             *
   1642  */
   1643 
   1644 #if defined (INCLUDE_BHH)
   1645 /*
   1646  * Function:
   1647  *     _bcm_sb2_oam_period_validate
   1648  * Purpose:
   1649  *     Validates whether OAM period is in allowed range or not .
   1650  * Parameters:
   1651  *     period -  (IN) OAM PDU interval in milli seconds.
   1652  * Returns:
   1653  *      BCM_E_XXX
   1654  */
   1655 STATIC int
   1656 _bcm_sb2_oam_period_validate(int period)
   1657 {
   1658     int q_period = 0; /* OAM period value. */
   1659 
   1660     /* Find whether requested period is matching with supported period or not */
   1661     for (q_period = 0; q_period <
   1662             _BCM_SB2_OAM_MAX_CCM_INTERVALS; q_period++) {
   1663         if (period ==  _sb2_ccm_intervals[q_period]) {
   1664             return BCM_E_NONE; 
   1665         }
   1666     }
   1667 
   1668     return BCM_E_PARAM;
   1669 }
   1670 #endif
   1671 
   1672 void
   1673 _bcm_sb2_oam_key_type_from_endpoint_get(bcm_oam_endpoint_type_t type,
   1674                                         uint32 flags, bcm_vlan_t vlan, 
   1675                                         bcm_vlan_t inner_vlan, 
   1676                                         uint32 int_flags, int *key_type)
   1677 {
   1678     if((type == bcmOAMEndpointTypeMplsLmDmSectionPort) ||
   1679        (type == bcmOAMEndpointTypeBhhSection)) {
   1680         *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION;
   1681     } else if(
   1682            (type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) ||
   1683            (type == bcmOAMEndpointTypeBhhSectionInnervlan)) {
   1684         *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN;
   1685     } else if(
   1686            (type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) ||
   1687            (type == bcmOAMEndpointTypeBhhSectionOuterVlan)) {
   1688         *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN;
   1689     } else if(
   1690       (type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) ||
   1691       (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)) {
   1692         *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN;
   1693     } else if(
   1694       (type == bcmOAMEndpointTypeMplsLmDmPw) ||
   1695       (type == bcmOAMEndpointTypeBHHMPLSVccv)) {
   1696         *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW;
   1697     } else if(
   1698       (type == bcmOAMEndpointTypeMplsLmDmLsp) ||
   1699       (type == bcmOAMEndpointTypeBHHMPLS)) {
   1700         *key_type = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP;
   1701     } else if (_BCM_OAM_ETH_OAM_VP_TYPE(type, int_flags)) {
   1702         *key_type = _BCM_OAM_DOMAIN_VP;
   1703     } else if(flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   1704         *key_type = _BCM_OAM_DOMAIN_CVLAN;
   1705     } else if(flags & 
   1706                            BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   1707         *key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   1708     } else if((vlan == 0) && (inner_vlan == 0)) {
   1709         *key_type = _BCM_OAM_DOMAIN_PORT;
   1710     } else {
   1711         *key_type = _BCM_OAM_DOMAIN_SVLAN;
   1712     }
   1713 }
   1714 
   1715 /*
   1716  * Function:
   1717  *      _bcm_sb2_outer_tpid_init
   1718  * Purpose:
   1719  *      Allocate and initialize memory to cache oam outer tpid entries.
   1720  *      Initialize lock for cached tpid entries.
   1721  * Parameters:
   1722  *      unit       - (IN)SOC unit number.
   1723  * Returns:
   1724  *      BCM_E_XXX
   1725  * Notes:
   1726  */
   1727 int
   1728 _bcm_sb2_outer_tpid_init(int unit) {
   1729     int               index;
   1730     int               alloc_size;
   1731     uint32            reg32;
   1732     int               rv = BCM_E_NONE;
   1733 
   1734     /* Allocate memory to cache OUTER_TPID entries.  */
   1735     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES;
   1736     if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) {
   1737         SB2_OAM_OUTER_TPID_TAB(unit) = sal_alloc(alloc_size,
   1738                                          "Cached OAM Outer TPIDs");
   1739         if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) {
   1740             return BCM_E_MEMORY;
   1741         }
   1742     }
   1743     sal_memset(SB2_OAM_OUTER_TPID_TAB(unit), 0, alloc_size);
   1744 
   1745     /* Cache outer TPID table */
   1746     for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) {
   1747         rv = soc_reg32_get(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, &reg32);
   1748         if (BCM_FAILURE(rv)) {
   1749             sal_free(SB2_OAM_OUTER_TPID_TAB(unit));
   1750             SB2_OAM_OUTER_TPID_TAB(unit) = NULL;
   1751         }
   1752         SB2_OAM_OUTER_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 
   1753                                           sb2_outer_tpid[index], reg32, TPIDf);
   1754     }
   1755 
   1756     if (NULL == BCM_SB2_OUTER_TPID_MUTEX(unit)) {
   1757         /* Create protection mutex. */
   1758         BCM_SB2_OUTER_TPID_MUTEX(unit) = sal_mutex_create("oamouter_tpid_lock");
   1759         if (NULL == BCM_SB2_OUTER_TPID_MUTEX(unit)) {
   1760             return (BCM_E_MEMORY);
   1761         }
   1762     }
   1763     return (BCM_E_NONE);
   1764 }
   1765 
   1766 /*
   1767  * Function:
   1768  *      _bcm_sb2_inner_tpid_init
   1769  * Purpose:
   1770  *      Allocate and initialize memory to cache oam inner tpid entries.
   1771  *      Initialize lock for cached tpid entries.
   1772  * Parameters:
   1773  *      unit       - (IN)SOC unit number.
   1774  * Returns:
   1775  *      BCM_E_XXX
   1776  * Notes:
   1777  */
   1778 int
   1779 _bcm_sb2_inner_tpid_init(int unit) {
   1780     int               alloc_size;
   1781     uint32            reg32;
   1782     int               rv = BCM_E_NONE;
   1783 
   1784     /* Allocate memory to cache INNER_TPID entries.  */
   1785     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_INNER_TPID_ENTRIES;
   1786     if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) {
   1787         SB2_OAM_INNER_TPID_TAB(unit) = sal_alloc(alloc_size,
   1788                                          "Cached OAM Inner TPIDs");
   1789         if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) {
   1790             return BCM_E_MEMORY;
   1791         }
   1792     }
   1793     sal_memset(SB2_OAM_INNER_TPID_TAB(unit), 0, alloc_size);
   1794 
   1795     /* Cache Inner TPID table */
   1796     rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &reg32);
   1797     if (BCM_FAILURE(rv)) {
   1798         sal_free(SB2_OAM_INNER_TPID_TAB(unit));
   1799         SB2_OAM_INNER_TPID_TAB(unit) = NULL;
   1800     }
   1801     /* Inner TPID has only 1 entry. So, index is always 0 */
   1802     SB2_OAM_INNER_TPID_ENTRY(unit, 0) = soc_reg_field_get(unit, INNER_TPIDr, 
   1803                                                           reg32, TPIDf);
   1804 
   1805     if (NULL == BCM_SB2_INNER_TPID_MUTEX(unit)) {
   1806         /* Create protection mutex. */
   1807         BCM_SB2_INNER_TPID_MUTEX(unit) = sal_mutex_create("oam inner_tpid_lock");
   1808         if (NULL == BCM_SB2_INNER_TPID_MUTEX(unit)) {
   1809             return (BCM_E_MEMORY);
   1810         }
   1811     }
   1812     return (BCM_E_NONE);
   1813 }
   1814 
   1815 /*
   1816  * Function:
   1817  *      _bcm_sb2_subport_tpid_init
   1818  * Purpose:
   1819  *      Allocate and initialize memory to cache oam subport tpid entries.
   1820  *      Initialize lock for cached tpid entries.
   1821  * Parameters:
   1822  *      unit       - (IN)SOC unit number.
   1823  * Returns:
   1824  *      BCM_E_XXX
   1825  * Notes:
   1826  */
   1827 int
   1828 _bcm_sb2_subport_tpid_init(int unit) {
   1829     int               index;
   1830     int               alloc_size;
   1831     uint32            reg32;
   1832     int               rv = BCM_E_NONE;
   1833 
   1834     /* Allocate memory to cache OUTER_TPID entries.  */
   1835     alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES;
   1836     if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) {
   1837         SB2_OAM_SUBPORT_TPID_TAB(unit) = sal_alloc(alloc_size,
   1838                                          "Cached OAM Subport TPIDs");
   1839         if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) {
   1840             return BCM_E_MEMORY;
   1841         }
   1842     }
   1843     sal_memset(SB2_OAM_SUBPORT_TPID_TAB(unit), 0, alloc_size);
   1844 
   1845     /* Cache Subport TPID table */
   1846     for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) {
   1847         rv = soc_reg32_get(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, &reg32);
   1848         if (BCM_FAILURE(rv)) {
   1849             sal_free(SB2_OAM_SUBPORT_TPID_TAB(unit));
   1850             SB2_OAM_SUBPORT_TPID_TAB(unit) = NULL;
   1851         }
   1852         SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 
   1853                                           sb2_subport_tpid[index], reg32, TPIDf);
   1854     }
   1855 
   1856     if (NULL == BCM_SB2_SUBPORT_TPID_MUTEX(unit)) {
   1857         /* Create protection mutex. */
   1858         BCM_SB2_SUBPORT_TPID_MUTEX(unit) = sal_mutex_create("oam subport_tpid_lock");
   1859         if (NULL == BCM_SB2_SUBPORT_TPID_MUTEX(unit)) {
   1860             return (BCM_E_MEMORY);
   1861         }
   1862     }
   1863     return (BCM_E_NONE);
   1864 }
   1865 /*
   1866  * Function :
   1867  *    _bcm_sb2_oam_tpid_get
   1868  * 
   1869  * Purpose  :
   1870  *    Get tpid value for tpid entry index in the HW. 
   1871  *
   1872  * Parameters :
   1873  *     unit  - (IN) BCM device number.
   1874  *     tpid_type -(IN) - outer/inner/subport
   1875  *     index - (IN) Entry index.
   1876  *     value - (OUT) TPID value in HW
   1877  * Return :
   1878  *    BCM_E_XXX
   1879  */
   1880 int
   1881 _bcm_sb2_oam_tpid_get(int unit, int tpid_type, int index, int *value)
   1882 {
   1883     int  rv = BCM_E_NONE;
   1884     uint32 rval = 0;
   1885 
   1886     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1887         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1888             return (BCM_E_PARAM); 
   1889         }
   1890         rv = soc_reg32_get(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, &rval);
   1891         if (BCM_FAILURE(rv)) {
   1892             return (BCM_E_PARAM); 
   1893         }
   1894         *value = soc_reg_field_get(unit, sb2_outer_tpid[index], rval, TPIDf);
   1895     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1896         if (index >= BCM_MAX_INNER_TPID_ENTRIES)  {
   1897             return (BCM_E_PARAM); 
   1898         }
   1899         rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &rval);
   1900         if (BCM_FAILURE(rv)) {
   1901             return (BCM_E_PARAM); 
   1902         }
   1903         *value = soc_reg_field_get(unit, INNER_TPIDr, rval, TPIDf);
   1904     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1905         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1906             return (BCM_E_PARAM); 
   1907         }
   1908         rv = soc_reg32_get(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, &rval);
   1909         if (BCM_FAILURE(rv)) {
   1910             return (BCM_E_PARAM); 
   1911         }
   1912         *value = soc_reg_field_get(unit, sb2_subport_tpid[index], rval, TPIDf);
   1913     } else {
   1914         return (BCM_E_PARAM); 
   1915     } 
   1916     return (rv);
   1917 }
   1918 
   1919 /*
   1920  * Function :
   1921  *    _bcm_sb2_oam_tpid_set
   1922  * 
   1923  * Purpose  :
   1924  *    Set tpid value for tpid entry index in the HW. 
   1925  *
   1926  * Parameters :
   1927  *     unit  - (IN) BCM device number.
   1928  *     tpid_type -(IN) - outer/inner/subport
   1929  *     index - (IN) Entry index.
   1930  *     value - (IN) Value to be set as tpid 
   1931  * Return :
   1932  *    BCM_E_XXX
   1933  */
   1934 int
   1935 _bcm_sb2_oam_tpid_set(int unit, int tpid_type, int index, int value)
   1936 {
   1937     int  rv = BCM_E_NONE;
   1938     uint32 rval = 0;
   1939 
   1940     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1941         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1942             return (BCM_E_PARAM); 
   1943         }
   1944         soc_reg_field_set(unit, sb2_outer_tpid[index], &rval, TPIDf, value);
   1945         rv = soc_reg32_set(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, rval);
   1946         if (BCM_FAILURE(rv)) {
   1947             return (BCM_E_PARAM); 
   1948         }
   1949     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1950         if (index >= BCM_MAX_INNER_TPID_ENTRIES)  {
   1951             return (BCM_E_PARAM); 
   1952         }
   1953         soc_reg_field_set(unit, INNER_TPIDr, &rval, TPIDf, value);
   1954         rv = soc_reg32_set(unit, INNER_TPIDr, REG_PORT_ANY, 0, rval);
   1955         if (BCM_FAILURE(rv)) {
   1956             return (BCM_E_PARAM); 
   1957         }
   1958     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   1959         if (index >= BCM_MAX_TPID_ENTRIES)  {
   1960             return (BCM_E_PARAM); 
   1961         }
   1962         soc_reg_field_set(unit, sb2_subport_tpid[index], &rval, TPIDf, value);
   1963         rv = soc_reg32_set(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, rval);
   1964         if (BCM_FAILURE(rv)) {
   1965             return (BCM_E_PARAM); 
   1966         }
   1967     } else {
   1968         return (BCM_E_PARAM); 
   1969     } 
   1970     return (rv);
   1971 }
   1972 
   1973 /*
   1974  * Function :
   1975  *    _bcm_sb2_oam_tpid_entry_get
   1976  * 
   1977  * Purpose  :
   1978  *    Get tpid value for tpid entry index . 
   1979  *
   1980  * Parameters :
   1981  *     unit  - (IN) BCM device number.
   1982  *     tpid  - (OUT) TPID value.
   1983  *     index - (IN) Entry index.
   1984  *
   1985  * Return :
   1986  *    BCM_E_XXX
   1987  */
   1988 int
   1989 _bcm_sb2_oam_tpid_entry_get(int unit, uint16 *tpid, int index, int tpid_type) 
   1990 {
   1991     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   1992         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   1993             (SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) {
   1994             return (BCM_E_PARAM);
   1995         }
   1996         *tpid = SB2_OAM_OUTER_TPID_ENTRY(unit, index);
   1997     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   1998         if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) ||
   1999             (SB2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) {
   2000             return (BCM_E_PARAM);
   2001         }
   2002         *tpid = SB2_OAM_INNER_TPID_ENTRY(unit, index);
   2003     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   2004         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   2005             (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) {
   2006             return (BCM_E_PARAM);
   2007         }
   2008         *tpid = SB2_OAM_SUBPORT_TPID_ENTRY(unit, index);
   2009     } else {
   2010         return (BCM_E_PARAM);
   2011     }
   2012     return (BCM_E_NONE);
   2013 }
   2014 
   2015 /*
   2016  * Function :
   2017  *    _bcm_sb2_oam_tpid_entry_delete
   2018  * 
   2019  * Purpose  :
   2020  *    Delete tpid entry by index.
   2021  *
   2022  * Parameters :
   2023  *     unit  - (IN) BCM device number.
   2024  *     index - (IN) Entry index.
   2025  *
   2026  * Return :
   2027  *    BCM_E_XXX
   2028  */
   2029 int
   2030 _bcm_sb2_tpid_entry_delete(int unit, int index, int tpid_type) 
   2031 {
   2032     int rv = BCM_E_NONE; 
   2033     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) {
   2034         BCM_SB2_OUTER_TPID_LOCK(unit);
   2035         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   2036             (SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) {
   2037             rv = BCM_E_PARAM;
   2038             BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2039             return rv;
   2040         }
   2041         SB2_OAM_OUTER_TPID_REF_COUNT(unit, index)--;
   2042         if (0 == SB2_OAM_OUTER_TPID_REF_COUNT(unit, index)) {
   2043             SB2_OAM_OUTER_TPID_ENTRY(unit, index) = sb2_default_outer_tpid[index];
   2044             rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 
   2045                                              sb2_default_outer_tpid[index]);
   2046         }
   2047         BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2048     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) {
   2049         BCM_SB2_INNER_TPID_LOCK(unit);
   2050         if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) ||
   2051             (SB2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) {
   2052             rv = BCM_E_PARAM;
   2053             BCM_SB2_INNER_TPID_UNLOCK(unit);
   2054             return rv;
   2055         }
   2056         SB2_OAM_INNER_TPID_REF_COUNT(unit, index)--;
   2057         if (0 == SB2_OAM_INNER_TPID_REF_COUNT(unit, index)) {
   2058             SB2_OAM_INNER_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID;
   2059             rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 
   2060                                              BCM_OAM_DEFAULT_TPID);
   2061         }
   2062         BCM_SB2_INNER_TPID_UNLOCK(unit);
   2063     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) {
   2064         BCM_SB2_SUBPORT_TPID_LOCK(unit);
   2065         if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) ||
   2066             (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) {
   2067             rv = BCM_E_PARAM;
   2068             BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2069             return rv;
   2070         }
   2071         SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)--;
   2072         if (0 == SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)) {
   2073             SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID;
   2074             rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 
   2075                                              BCM_OAM_DEFAULT_TPID);
   2076         }
   2077         BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2078     } else {
   2079         return (BCM_E_PARAM);
   2080     }
   2081     return (rv);
   2082 }
   2083 
   2084 
   2085 /*
   2086  * Function :
   2087  *    _bcm_sb2_tpid_lkup
   2088  * 
   2089  * Purpose  :
   2090  *    Get tpid entry index for specific tpid value.
   2091  *
   2092  * Parameters :
   2093  *     unit  - (IN) BCM device number.
   2094  *     tpid  - (IN) TPID value.
   2095  *     tpid_type - (IN) Type of the tpid - inner/outer/subport
   2096  *     index - (OUT) Entry index.
   2097  *
   2098  * Return :
   2099  *    BCM_E_XXX
   2100  */
   2101 int
   2102 _bcm_sb2_tpid_lkup(int unit, uint16 tpid, int tpid_type,  int *index)
   2103 {
   2104     int i;
   2105     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 
   2106         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2107             if (SB2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) {
   2108                 *index = i;
   2109                 return BCM_E_NONE;
   2110             }
   2111         }
   2112     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 
   2113         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   2114             if (SB2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) {
   2115                 *index = i;
   2116                 return BCM_E_NONE;
   2117             }
   2118         }
   2119     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 
   2120         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2121             if (SB2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) {
   2122                 *index = i;
   2123                 return BCM_E_NONE;
   2124             }
   2125         }
   2126     }
   2127     return BCM_E_NOT_FOUND;
   2128 }
   2129 
   2130 /*
   2131  * Function:
   2132  *      _bcm_sb2_tpid_entry_add 
   2133  * Purpose:
   2134  *      Add a new TPID entry.
   2135  *      Allocate and initialize memory to cache tpid entries.
   2136  *      Initialize lock for cached tpid entries.
   2137  * Parameters:
   2138  *      unit       - (IN) SOC unit number.
   2139  *      tpid       - (IN) TPID to be added.
   2140  *      tpid_type  - (IN) Type of the tpid - inner/outer/subport
   2141  *      index      - (OUT) Index where the the new TPID is added.
   2142  * Returns:
   2143  *      BCM_E_XXX
   2144  * Notes:
   2145  *      If the same TPID already exists, simply increase the
   2146  * reference count of the cached entry. Otherwise, add the entry
   2147  * to the cached table and write the new entry to hardware.
   2148  * Only four distinct TPID values are currently supported for
   2149  * outer and subport TPID and only one value is supported for
   2150  * inner tpid.
   2151  */
   2152 
   2153 int
   2154 _bcm_sb2_tpid_entry_add(int unit, uint16 tpid, int tpid_type, int *index)
   2155 {
   2156     int rv = BCM_E_NONE;
   2157     int i, free_index;
   2158 
   2159     free_index = -1;
   2160     if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 
   2161         BCM_SB2_OUTER_TPID_LOCK(unit);
   2162         /* Search for an existing entry.  */
   2163         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2164             if (SB2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) {
   2165                 SB2_OAM_OUTER_TPID_REF_COUNT(unit, i)++;
   2166                 *index = i;
   2167                 BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2168                 return rv;
   2169             }
   2170         }
   2171         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2172             if (SB2_OAM_OUTER_TPID_REF_COUNT(unit, i) == 0) {
   2173                 free_index = i;
   2174                 break;
   2175             }
   2176         } 
   2177         if (free_index < 0) {
   2178             rv = BCM_E_RESOURCE;
   2179             BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2180             return rv;
   2181         }
   2182         /* Insert the new configuration into tpid table as free
   2183            entry is available  */
   2184         rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   2185         if (BCM_FAILURE(rv)) {
   2186             BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2187             return rv;
   2188         }
   2189         SB2_OAM_OUTER_TPID_ENTRY(unit, free_index) = tpid;
   2190         SB2_OAM_OUTER_TPID_REF_COUNT(unit, free_index)++;
   2191         *index = free_index;
   2192         BCM_SB2_OUTER_TPID_UNLOCK(unit);
   2193     } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 
   2194         BCM_SB2_INNER_TPID_LOCK(unit);
   2195         /* Search for an existing entry  */
   2196         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   2197             if (SB2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) {
   2198                 SB2_OAM_INNER_TPID_REF_COUNT(unit, i)++;
   2199                 *index = i;
   2200                 BCM_SB2_INNER_TPID_UNLOCK(unit);
   2201                 return rv;
   2202             }
   2203         }
   2204         for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) {
   2205             if (SB2_OAM_INNER_TPID_REF_COUNT(unit, i) == 0) {
   2206                 free_index = i;
   2207                 break;
   2208             }
   2209         } 
   2210         if (free_index < 0) {
   2211             rv = BCM_E_RESOURCE;
   2212             BCM_SB2_INNER_TPID_UNLOCK(unit);
   2213             return rv;
   2214         }
   2215         /* Insert the new configuration into tpid table as free
   2216            entry is available  */
   2217         rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   2218         if (BCM_FAILURE(rv)) {
   2219             BCM_SB2_INNER_TPID_UNLOCK(unit);
   2220             return rv;
   2221         }
   2222         SB2_OAM_INNER_TPID_ENTRY(unit, free_index) = tpid;
   2223         SB2_OAM_INNER_TPID_REF_COUNT(unit, free_index)++;
   2224         *index = free_index;
   2225         BCM_SB2_INNER_TPID_UNLOCK(unit);
   2226     } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 
   2227         BCM_SB2_SUBPORT_TPID_LOCK(unit);
   2228         /* Search for an existing entry */
   2229         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2230             if (SB2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) {
   2231                 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, i)++;
   2232                 *index = i;
   2233                 BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2234                 return rv;
   2235             }
   2236         }
   2237         for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) {
   2238             if (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, i) == 0) {
   2239                 free_index = i;
   2240                 break;
   2241             }
   2242         } 
   2243         if (free_index < 0) {
   2244             rv = BCM_E_RESOURCE;
   2245             BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2246             return rv;
   2247         }
   2248         /* Insert the new configuration into tpid table as free
   2249            entry is available.  */
   2250         rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid);
   2251         if (BCM_FAILURE(rv)) {
   2252             BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2253             return rv;
   2254         }
   2255         SB2_OAM_SUBPORT_TPID_ENTRY(unit, free_index) = tpid;
   2256         SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, free_index)++;
   2257         *index = free_index;
   2258         BCM_SB2_SUBPORT_TPID_UNLOCK(unit);
   2259     } else {
   2260         rv = BCM_E_PARAM;
   2261     }
   2262     return rv;    
   2263 }
   2264 
   2265 /*
   2266  * Function:
   2267  *     _bcm_sb2_oam_ccm_msecs_to_hw_encode
   2268  * Purpose:
   2269  *     Quanitze CCM interval from msecs to hardware encoding.
   2270  * Parameters:
   2271  *     period -  (IN) CCM interval in milli seconds.
   2272  * Retruns:
   2273  *     Hardware encoding for the specified CCM interval value.
   2274  */
   2275 STATIC int
   2276 _bcm_sb2_oam_ccm_msecs_to_hw_encode(int period)
   2277 {
   2278     int q_period = 0; /* Quantized CCM period value. */
   2279 
   2280     if (0 == period) {
   2281         return (q_period);
   2282     }
   2283 
   2284     /* Find closest supported period */
   2285     for (q_period = 1; _sb2_ccm_intervals[q_period]
   2286             != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) {
   2287         if (period < _sb2_ccm_intervals[q_period]) {
   2288             break;
   2289         }
   2290     }
   2291 
   2292     if (_sb2_ccm_intervals[q_period]
   2293         == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) {
   2294         /* Use the highest defined value */
   2295         --q_period;
   2296     } else {
   2297         if ((period - _sb2_ccm_intervals[q_period - 1])
   2298                 < (_sb2_ccm_intervals[q_period] - period)) {
   2299             /* Closer to the lower value */
   2300             --q_period;
   2301         }
   2302     }
   2303 
   2304     return q_period;
   2305 }
   2306 
   2307 #if defined(BCM_WARM_BOOT_SUPPORT)
   2308 /*
   2309  * Function:
   2310  *     _bcm_sb2_oam_ccm_hw_encode_to_msecs
   2311  * Purpose:
   2312  *     Get CCM interval in msecs for a given hardware encoded value.
   2313  * Parameters:
   2314  *     encode -  (IN) CCM interval hardware encoding.
   2315  * Retruns:
   2316  *     CCM interval in msecs.
   2317  */
   2318 STATIC int
   2319 _bcm_sb2_oam_ccm_hw_encode_to_msecs(int encode)
   2320 {
   2321     return (_sb2_ccm_intervals[encode]);
   2322 }
   2323 #endif
   2324 
   2325 int _bcm_sb2_opcode_flags_to_opcode_group_index(int unit, uint32 opcode_flags, 
   2326                                                 bcm_oam_endpoint_type_t type,
   2327                                                 int *index_list, int *num_index)
   2328 {
   2329     int i;
   2330     int rv;
   2331     oam_opcode_group_entry_t    opcode_grp_entry;
   2332     int opcode_key[2] = {0, 0};
   2333 
   2334     switch(opcode_flags) {
   2335         case BCM_OAM_OPCODE_CCM_COPY_TO_CPU:      
   2336         case BCM_OAM_OPCODE_CCM_DROP:   
   2337         case BCM_OAM_OPCODE_CCM_IN_HW:
   2338             if (BHH_TYPE(type)) {
   2339                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2340                                                     _BCM_OAM_OPCODE_TYPE_CCM);
   2341             } else {
   2342                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2343                                                     _BCM_OAM_OPCODE_TYPE_CCM);
   2344             }
   2345             *num_index = 1;
   2346             break;
   2347 
   2348         case BCM_OAM_OPCODE_LBM_IN_HW:   
   2349         case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU:
   2350         case BCM_OAM_OPCODE_LBM_UC_DROP:
   2351         case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU:
   2352         case BCM_OAM_OPCODE_LBM_MC_DROP:      
   2353             if (BHH_TYPE(type)) {
   2354                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2355                                                     _BCM_OAM_OPCODE_TYPE_LBM);
   2356             } else {
   2357                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2358                                                     _BCM_OAM_OPCODE_TYPE_LBM);
   2359             }
   2360             *num_index = 1;
   2361             break;
   2362 
   2363         case BCM_OAM_OPCODE_LBR_COPY_TO_CPU:   
   2364         case BCM_OAM_OPCODE_LBR_DROP:      
   2365             if (BHH_TYPE(type)) {
   2366                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2367                                                     _BCM_OAM_OPCODE_TYPE_LBR);
   2368             } else {
   2369                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2370                                                     _BCM_OAM_OPCODE_TYPE_LBR);
   2371             }
   2372             *num_index = 1;
   2373             break;
   2374 
   2375         case BCM_OAM_OPCODE_LTM_COPY_TO_CPU:   
   2376         case BCM_OAM_OPCODE_LTM_DROP:      
   2377             if (BHH_TYPE(type)) {
   2378                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2379                                                     _BCM_OAM_OPCODE_TYPE_LTM);
   2380             } else {
   2381                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2382                                                     _BCM_OAM_OPCODE_TYPE_LTM);
   2383             }
   2384             *num_index = 1;
   2385             break;
   2386 
   2387         case BCM_OAM_OPCODE_LTR_COPY_TO_CPU:
   2388         case BCM_OAM_OPCODE_LTR_DROP:
   2389             if (BHH_TYPE(type)) {
   2390                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2391                                                     _BCM_OAM_OPCODE_TYPE_LTR);
   2392             } else {
   2393                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2394                                                     _BCM_OAM_OPCODE_TYPE_LTR);
   2395             }
   2396             *num_index = 1;
   2397             break;
   2398 
   2399         case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU:
   2400         case BCM_OAM_OPCODE_OTHER_DROP:
   2401             if (BHH_TYPE(type)) {
   2402                 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2403                                                     _BCM_OAM_OPCODE_TYPE_LMM);
   2404                 opcode_key[1] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(
   2405                                                     _BCM_OAM_OPCODE_TYPE_DMM);
   2406             } else {
   2407                 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2408                                                     _BCM_OAM_OPCODE_TYPE_LMM);
   2409                 opcode_key[1] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(
   2410                                                     _BCM_OAM_OPCODE_TYPE_DMM);
   2411             }
   2412             *num_index = 2;
   2413             break;
   2414 
   2415         default:
   2416             return BCM_E_PARAM;
   2417             break;
   2418     }
   2419 
   2420     for(i=0; i< (*num_index); i++) {
   2421         rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY,
   2422                 opcode_key[i], &opcode_grp_entry);
   2423 
   2424         if (BCM_FAILURE(rv)) {
   2425             LOG_ERROR(BSL_LS_BCM_OAM,
   2426                 (BSL_META_U(unit,
   2427                     "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  read "
   2428                     "failed  %s.\n"), unit, bcm_errmsg(rv)));
   2429             return rv;
   2430         }
   2431 
   2432         index_list[i] =  soc_mem_field32_get(unit, OAM_OPCODE_GROUPm,
   2433                 &opcode_grp_entry, OPCODE_GROUPf);
   2434     }
   2435 
   2436     return BCM_E_NONE;
   2437 }
   2438 
   2439 int
   2440 _bcm_sb2_oam_mpls_lm_dm_opcode_to_opcode_group_index(int unit, uint32 opcode,
   2441                                                      int *opcode_group)
   2442 {
   2443     int rv = BCM_E_NONE;
   2444     int opcode_key; 
   2445     oam_opcode_group_entry_t    opcode_grp_entry; 
   2446 
   2447     switch(opcode) {
   2448         case bcmOamMplsLmDmOpcodeTypeLm:
   2449         case bcmOamMplsLmDmOpcodeTypeDm:
   2450         case bcmOamMplsLmDmOpcodeTypeIlm:
   2451         case bcmOamMplsLmDmOpcodeTypeLmPlusDm:
   2452         case bcmOamMplsLmDmOpcodeTypeIlmPlusDm:
   2453             opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode); 
   2454             break; 
   2455         default:
   2456             rv = BCM_E_PARAM;
   2457             return rv;
   2458             break;
   2459     }
   2460 
   2461     rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY,
   2462             opcode_key, &opcode_grp_entry);
   2463 
   2464     if (BCM_FAILURE(rv)) {
   2465         LOG_ERROR(BSL_LS_BCM_OAM,
   2466                 (BSL_META_U(unit,
   2467                             "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  read "
   2468                             "failed  %s.\n"), unit, bcm_errmsg(rv)));
   2469         return rv;
   2470     }
   2471 
   2472     *opcode_group =  soc_mem_field32_get(unit, OAM_OPCODE_GROUPm,
   2473             &opcode_grp_entry, OPCODE_GROUPf);
   2474 
   2475     return rv;
   2476 
   2477 }
   2478 
   2479 int _bcm_sb2_opcode_to_opcode_group_index (int unit, _bcm_oam_hash_data_t *h_data_p,
   2480                                            uint32 opcode)
   2481 {
   2482     int opcode_key = -1; 
   2483     oam_opcode_group_entry_t    opcode_grp_entry;
   2484     int rv;
   2485     int opcode_group = -1; 
   2486 
   2487     if(opcode > _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST) {
   2488         return opcode_group;
   2489     }
   2490 
   2491     if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 
   2492         BCM_IF_ERROR_RETURN( 
   2493                 _bcm_sb2_oam_mpls_lm_dm_opcode_to_opcode_group_index(unit, opcode,
   2494                     &opcode_group));
   2495         return opcode_group;
   2496     }
   2497     
   2498     switch(opcode) {
   2499         case _BCM_OAM_OPCODE_TYPE_CCM:
   2500         case _BCM_OAM_OPCODE_TYPE_LBR:
   2501         case _BCM_OAM_OPCODE_TYPE_LBM:
   2502         case _BCM_OAM_OPCODE_TYPE_LTR:
   2503         case _BCM_OAM_OPCODE_TYPE_LTM:
   2504         case _BCM_OAM_OPCODE_TYPE_LMR:
   2505         case _BCM_OAM_OPCODE_TYPE_LMM:
   2506         case _BCM_OAM_OPCODE_TYPE_SLM:
   2507         case _BCM_OAM_OPCODE_TYPE_SLR:
   2508         case _BCM_OAM_OPCODE_TYPE_AIS:
   2509         case _BCM_OAM_OPCODE_TYPE_LCK:
   2510         case _BCM_OAM_OPCODE_TYPE_TST:
   2511         case _BCM_OAM_OPCODE_TYPE_LIN_APS:
   2512         case _BCM_OAM_OPCODE_TYPE_RING_APS:
   2513         case _BCM_OAM_OPCODE_TYPE_1DM:
   2514         case _BCM_OAM_OPCODE_TYPE_DMM:
   2515         case _BCM_OAM_OPCODE_TYPE_DMR:
   2516         case _BCM_OAM_OPCODE_TYPE_MCC:
   2517         case _BCM_OAM_OPCODE_TYPE_EXM:
   2518         case _BCM_OAM_OPCODE_TYPE_EXR:
   2519         case _BCM_OAM_OPCODE_TYPE_VSM:
   2520         case _BCM_OAM_OPCODE_TYPE_VSR:
   2521             if (BHH_EP_TYPE(h_data_p)) {
   2522                 opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode);
   2523             } else {
   2524                 opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode);
   2525             }
   2526 
   2527             break;
   2528     }
   2529 
   2530     if(opcode_key != -1) {
   2531         rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY,
   2532                 opcode_key, &opcode_grp_entry);
   2533 
   2534         if (BCM_FAILURE(rv)) {
   2535             LOG_ERROR(BSL_LS_BCM_OAM,
   2536                     (BSL_META_U(unit,
   2537                                 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  read " 
   2538                                 "failed  %s.\n"), unit, bcm_errmsg(rv)));
   2539             return opcode_group;
   2540         }
   2541 
   2542         opcode_group =  soc_mem_field32_get(unit, OAM_OPCODE_GROUPm,
   2543                 &opcode_grp_entry, OPCODE_GROUPf);
   2544     }
   2545 
   2546     return opcode_group;
   2547 
   2548 }
   2549 
   2550 /*
   2551  * Function:
   2552  *     _bcm_sb2_oam_opcode_profile_entry_set
   2553  * Purpose:
   2554  *     Program the OAM opcode control profile fields.
   2555  * Parameters:
   2556  *     unit  - (IN) BCM device number
   2557  *     mem   - (IN) Opcode profile memory - ingress/egress
   2558  *     flags - (IN) Bitmap of opcode control settings.
   2559  *     entry - (IN/OUT) Pointer to opcode control profile table 
   2560  *                      array of entries buffer.
   2561  * Retruns:
   2562  *     BCM_E_XXX
   2563  */
   2564 STATIC int
   2565 _bcm_sb2_oam_opcode_profile_entry_set(int unit, _bcm_oam_hash_data_t *h_data_p, 
   2566                                       soc_mem_t mem,
   2567                                       uint32 flags,
   2568                                       void *entry)
   2569 {
   2570     uint32 ep_opcode;        /* Endpoint opcode flag bits. */
   2571     uint32 opcode_count = 0; /* Number of bits set.        */
   2572     int    bp;               /* bit position.              */
   2573     int    rv = BCM_E_NONE;  /* Opreation return status.   */
   2574     oam_opcode_control_profile_entry_t *temp_entry;
   2575     oam_opcode_control_profile_entry_t *actual_entry;
   2576     int index_list[2] = {0 , 0}; /* There can be atmost 2 indexes returned */
   2577     int index, num_index = 0;
   2578     
   2579     
   2580     /* Validate opcode flag bits. */
   2581     if (flags & ~(_BCM_SB2_OAM_OPCODE_MASK)) {
   2582         return (BCM_E_PARAM);
   2583     }
   2584 
   2585     /* Get number of valid opcodes supported. */
   2586     opcode_count = _shr_popcount(_BCM_SB2_OAM_OPCODE_MASK);
   2587 
   2588     /*
   2589      * Iterate over opcode flag bits and set corresponding fields
   2590      * in entry buffer.
   2591      */
   2592     for (bp = 0; bp < opcode_count; bp++) {
   2593         ep_opcode = (flags & (1 << bp));
   2594         if(ep_opcode != 0)
   2595         {
   2596             rv =  _bcm_sb2_opcode_flags_to_opcode_group_index(unit, ep_opcode, h_data_p->type,
   2597                                                   index_list, &num_index);
   2598             if(rv < 0)
   2599             {
   2600                 return BCM_E_PARAM;
   2601             }
   2602             for(index = 0; index < num_index; index++)
   2603             {
   2604                 temp_entry = (oam_opcode_control_profile_entry_t *)entry;
   2605                 /* coverity[overrun-local] */
   2606                 actual_entry = &(temp_entry[index_list[index]]);
   2607 
   2608                 /*NOTE: Setting of some fields is also done to
   2609                   maintain the legacy behavior */
   2610                 /* LOW MDL CCM / LB/LT drop and LB/LT my station miss drop */
   2611 
   2612                 switch (ep_opcode) {
   2613                     case BCM_OAM_OPCODE_CCM_COPY_TO_CPU:
   2614                         /* CCM packet could be UC as well as MC */
   2615                         soc_mem_field32_set(unit, mem, actual_entry, 
   2616                                 UC_MY_STATION_HIT_COPYTO_CPUf, 1);
   2617                         if (!BHH_TYPE(h_data_p->type)) {
   2618                             soc_mem_field32_set(unit, mem, actual_entry,
   2619                                     UC_MY_STATION_MISS_COPYTO_CPUf, 1);
   2620                             soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1);
   2621                         } else {
   2622                             soc_mem_field32_set(unit, mem, actual_entry, 
   2623                                                 LOW_MDL_COPYTO_CPUf, 1);
   2624                             if (SOC_IS_METROLITE(unit)) {
   2625                                 soc_mem_field32_set(unit, mem, actual_entry,
   2626                                         EQUAL_MDL_SAMPLE_LM_COUNTERf, 1);
   2627                             }
   2628                         }
   2629                         break;
   2630                     case BCM_OAM_OPCODE_CCM_DROP:
   2631                         /* CCM packet could be UC as well as MC */
   2632                         soc_mem_field32_set(unit, mem, actual_entry, 
   2633                                 UC_MY_STATION_HIT_ACTIONf, 
   2634                                 _BCM_SB2_OAM_OC_PROF_DROP);
   2635                         if (!BHH_TYPE(h_data_p->type)) {
   2636                             soc_mem_field32_set(unit, mem, actual_entry,
   2637                                     UC_MY_STATION_MISS_ACTIONf,
   2638                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2639                             soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 
   2640                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2641                         }
   2642                         break;
   2643                     case BCM_OAM_OPCODE_CCM_IN_HW:
   2644                         /* CCM packet could be UC as well as MC */
   2645                         soc_mem_field32_set(unit, mem, actual_entry, 
   2646                                 UC_MY_STATION_HIT_ACTIONf,
   2647                                 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE);
   2648                         if (!BHH_TYPE(h_data_p->type)) {
   2649                             soc_mem_field32_set(unit, mem, actual_entry,
   2650                                     UC_MY_STATION_MISS_ACTIONf,
   2651                                     _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE);
   2652                             soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 
   2653                                     _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE);
   2654                         }
   2655                         break;
   2656                     case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU:
   2657                     case BCM_OAM_OPCODE_LBR_COPY_TO_CPU:
   2658                     case BCM_OAM_OPCODE_LTR_COPY_TO_CPU:
   2659                         soc_mem_field32_set(unit, mem, actual_entry, 
   2660                                 UC_MY_STATION_HIT_COPYTO_CPUf, 1);
   2661                         if (!BHH_TYPE(h_data_p->type)) {
   2662                             soc_mem_field32_set(unit, mem, actual_entry, 
   2663                                     UC_MY_STATION_MISS_ACTIONf,
   2664                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2665                         }
   2666                         break;
   2667                     case BCM_OAM_OPCODE_LTM_COPY_TO_CPU:
   2668                         /* LTM comes with multicast class 2 DA */
   2669                         soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1);
   2670                         break;
   2671 
   2672                     case BCM_OAM_OPCODE_LBM_IN_HW:
   2673                         /* LBM could be UC as well as MC */
   2674                         soc_mem_field32_set(unit, mem, actual_entry, 
   2675                                 UC_MY_STATION_HIT_ACTIONf,
   2676                                 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE);
   2677                         if (!BHH_TYPE(h_data_p->type)) {
   2678                             soc_mem_field32_set(unit, mem, actual_entry, 
   2679                                     UC_MY_STATION_MISS_ACTIONf,
   2680                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2681                             soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 
   2682                                     _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE);
   2683                         }
   2684                         break;
   2685 
   2686                     case BCM_OAM_OPCODE_LBM_UC_DROP:
   2687                     case BCM_OAM_OPCODE_LBR_DROP:
   2688                     case BCM_OAM_OPCODE_LTR_DROP:
   2689                         /* Replies are always UC */
   2690                         soc_mem_field32_set(unit, mem, actual_entry, 
   2691                                 UC_MY_STATION_HIT_ACTIONf, 
   2692                                 _BCM_SB2_OAM_OC_PROF_DROP);
   2693                         if (!BHH_TYPE(h_data_p->type)) {
   2694                             soc_mem_field32_set(unit, mem, actual_entry, 
   2695                                     UC_MY_STATION_MISS_ACTIONf,
   2696                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2697                         }
   2698                         break;
   2699                     case BCM_OAM_OPCODE_LTM_DROP:
   2700                         soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 
   2701                                 _BCM_SB2_OAM_OC_PROF_DROP);
   2702                         break;
   2703 
   2704                     case BCM_OAM_OPCODE_LBM_MC_DROP:
   2705                         soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 
   2706                                 _BCM_SB2_OAM_OC_PROF_DROP);
   2707                         break;
   2708 
   2709                     case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU:
   2710                         soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1);
   2711                         break;
   2712 
   2713                     case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU:
   2714                         if (!BHH_TYPE(h_data_p->type)) {
   2715                             soc_mem_field32_set(unit, mem, actual_entry,
   2716                                     MC_COPYTO_CPUf, 1);
   2717                             soc_mem_field32_set(unit, mem, actual_entry,
   2718                                     UC_MY_STATION_MISS_COPYTO_CPUf, 1);
   2719                         }
   2720                         soc_mem_field32_set(unit, mem, actual_entry,
   2721                                 UC_MY_STATION_HIT_COPYTO_CPUf, 1);
   2722                         soc_mem_field32_set(unit, mem, actual_entry,
   2723                                 LOW_MDL_COPYTO_CPUf, 1);
   2724                         if (index == 0) {
   2725                             soc_mem_field32_set(unit, mem, actual_entry,
   2726                                     EQUAL_MDL_SAMPLE_LM_COUNTERf, 1);
   2727                         } else if (index == 1) {
   2728                             soc_mem_field32_set(unit, mem, actual_entry,
   2729                                     EQUAL_MDL_SAMPLE_TIMESTAMPf, 1);
   2730                         }
   2731                         break;
   2732 
   2733                     case BCM_OAM_OPCODE_OTHER_DROP:
   2734                         if (!BHH_TYPE(h_data_p->type)) {
   2735                             soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf,
   2736                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2737                             soc_mem_field32_set(unit, mem, actual_entry,
   2738                                     UC_MY_STATION_MISS_ACTIONf,
   2739                                     _BCM_SB2_OAM_OC_PROF_DROP);
   2740                         }
   2741                         soc_mem_field32_set(unit, mem, actual_entry,
   2742                                 UC_MY_STATION_HIT_ACTIONf,
   2743                                 _BCM_SB2_OAM_OC_PROF_DROP);
   2744                         break;
   2745 
   2746                     default:
   2747                         break;
   2748                 }
   2749                 if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   2750                     /* Do not drop low mdl*/
   2751                     soc_mem_field32_set(unit, mem, actual_entry, 
   2752                             LOW_MDL_ACTIONf, _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING);
   2753                 } else {
   2754                     /* Drop LOW MDL packets. */
   2755                     soc_mem_field32_set(unit, mem, actual_entry, 
   2756                             LOW_MDL_ACTIONf, _BCM_SB2_OAM_OC_PROF_DROP);
   2757                 }
   2758             }
   2759         }
   2760     }
   2761 
   2762     return rv;
   2763 }
   2764 
   2765 
   2766 int
   2767 _bcm_sb2_mpls_lmdm_opcode_profile_entry_init(int unit,
   2768                                             soc_mem_t mem,
   2769                                             void *entry)
   2770 {
   2771     int opcode, rv = BCM_E_NONE;
   2772     _bcm_oam_hash_data_t hash_data;
   2773 
   2774     sal_memset(&hash_data , 0, sizeof(hash_data));
   2775     /* All they care about is type field of hash_data inside
   2776        _sb2_oam_opcode_control_field_set to be of type MPLS LM/DM.
   2777         Filling one of MPLS LM/DM endpoint types
   2778         */
   2779     hash_data.type = bcmOAMEndpointTypeMplsLmDmLsp;
   2780     
   2781     /* Initialize action to copy to cpu for all MPLS LM/DM opcodes. */
   2782     for (opcode = bcmOamMplsLmDmOpcodeTypeLm; 
   2783          opcode <= bcmOamMplsLmDmOpcodeTypeIlmPlusDm;
   2784          opcode++) {
   2785         rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, bcmOAMActionCopyToCpu, 
   2786                 mem, opcode, 1,
   2787                 entry);
   2788         if (BCM_FAILURE(rv)) {
   2789             return rv;
   2790         }
   2791 
   2792         /* Pkt termination is required for sampling to work. Hence adding
   2793          * drop action
   2794          */
   2795         rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, bcmOAMActionDrop,
   2796                 mem, opcode, 1,
   2797                 entry);
   2798         if (BCM_FAILURE(rv)) {
   2799             return rv;
   2800         }
   2801 
   2802         /* Sample LM Counter action for LM opcodes.
   2803          * However, for ILM opcodes, we dont sample counters. */
   2804         if ((opcode == bcmOamMplsLmDmOpcodeTypeLm) ||
   2805             (opcode == bcmOamMplsLmDmOpcodeTypeLmPlusDm)) {
   2806             rv = _sb2_oam_opcode_control_field_set(unit, &hash_data,
   2807                     bcmOAMActionSampleLmCounter,
   2808                     mem, opcode, 1,
   2809                     entry);
   2810         }
   2811         if (BCM_FAILURE(rv)) {
   2812             return rv;
   2813         }
   2814         /* Sample timestamp for DM opcodes */
   2815         if ((opcode == bcmOamMplsLmDmOpcodeTypeDm) ||
   2816             (opcode == bcmOamMplsLmDmOpcodeTypeLmPlusDm) ||
   2817             (opcode == bcmOamMplsLmDmOpcodeTypeIlmPlusDm)) {
   2818             rv = _sb2_oam_opcode_control_field_set(unit, &hash_data,
   2819                     bcmOAMActionSampleTimeStamp,
   2820                     mem, opcode, 1,
   2821                     entry);
   2822         }
   2823         if (BCM_FAILURE(rv)) {
   2824             return rv;
   2825         }
   2826     }
   2827     return rv;
   2828 }
   2829 
   2830 /*
   2831  * Function:
   2832  *     _bcm_sb2_oam_opcode_profile_entry_init
   2833  * Purpose:
   2834  *     Setup default OAM opcode control profile settings for MEP.
   2835  * Parameters:
   2836  *     unit  - (IN) BCM device number
   2837  *     mem   - (IN) Opcode profile memory - ingress/egress
   2838  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
   2839  * Retruns:
   2840  *     BCM_E_XXX
   2841  */
   2842 int
   2843 _bcm_sb2_oam_opcode_profile_entry_init(int unit, 
   2844                                        soc_mem_t mem,
   2845                                        void *entry)
   2846 {
   2847     uint32 opcode; /* Opcode flag bits.        */
   2848     int    rv;     /* Operation return status. */
   2849 
   2850     _bcm_oam_hash_data_t h_data;
   2851     sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 
   2852 
   2853     opcode =  (BCM_OAM_OPCODE_CCM_COPY_TO_CPU |
   2854                     BCM_OAM_OPCODE_CCM_DROP |
   2855                     BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
   2856                     BCM_OAM_OPCODE_LBM_UC_DROP |
   2857                     BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
   2858                     BCM_OAM_OPCODE_LBM_MC_DROP |
   2859                     BCM_OAM_OPCODE_LBR_COPY_TO_CPU |
   2860                     BCM_OAM_OPCODE_LBR_DROP |
   2861                     BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
   2862                     BCM_OAM_OPCODE_LTM_DROP |
   2863                     BCM_OAM_OPCODE_LTR_COPY_TO_CPU |
   2864                     BCM_OAM_OPCODE_LTR_DROP |
   2865                     BCM_OAM_OPCODE_OTHER_COPY_TO_CPU |
   2866                     BCM_OAM_OPCODE_OTHER_DROP
   2867                     );
   2868     /* Initialize for Ethernet OAM */
   2869     h_data.type = bcmOAMEndpointTypeEthernet;
   2870     rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data,
   2871                                                  mem, opcode, entry);
   2872     if (BCM_FAILURE(rv)) {
   2873         return rv;
   2874     }
   2875     /* Initialize for BHH OAM. Using one of the types of BHH endpoints */
   2876     h_data.type = bcmOAMEndpointTypeBHHMPLS;
   2877     rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data,
   2878                                                  mem, opcode, entry);
   2879     if (BCM_FAILURE(rv)) {
   2880         return rv;
   2881     }
   2882     /* Initialize for MPLS LM/DM */
   2883     rv = _bcm_sb2_mpls_lmdm_opcode_profile_entry_init(unit, mem, entry);
   2884     if (BCM_FAILURE(rv)) {
   2885         return rv;
   2886     }
   2887     return rv;
   2888 }
   2889 
   2890 /*
   2891  * Function:
   2892  *     _bcm_sb2_oam_mip_opcode_profile_entry_init
   2893  * Purpose:
   2894  *     Setup default OAM opcode control profile settings for MIP.
   2895  * Parameters:
   2896  *     unit  - (IN) BCM device number
   2897  *     mem   - (IN) Opcode profile memory - ingress/egress
   2898  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
   2899  * Retruns:
   2900  *     BCM_E_XXX
   2901  */
   2902 int
   2903 _bcm_sb2_oam_mip_opcode_profile_entry_init(int unit, 
   2904                                        soc_mem_t mem,
   2905                                        void *entry)
   2906 {
   2907     uint32 opcode; /* Opcode flag bits.        */
   2908     int    rv;     /* Operation return status. */
   2909 
   2910     _bcm_oam_hash_data_t h_data;
   2911     sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t));
   2912    
   2913     h_data.flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
   2914   
   2915     opcode =  (BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
   2916             BCM_OAM_OPCODE_LBM_UC_DROP |
   2917             BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
   2918             BCM_OAM_OPCODE_LBM_MC_DROP |
   2919             BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
   2920             BCM_OAM_OPCODE_LTM_DROP);
   2921 
   2922     /* Initialize for Ethernet OAM */
   2923     h_data.type = bcmOAMEndpointTypeEthernet;
   2924     rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data,
   2925                                                  mem, opcode, entry);
   2926     if (BCM_FAILURE(rv)) {
   2927         return rv;
   2928     }
   2929     /* Initialize for BHH OAM. Using one of the types of BHH endpoints */
   2930     h_data.type = bcmOAMEndpointTypeBHHMPLS;
   2931     rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data,
   2932                                                  mem, opcode, entry);
   2933     if (BCM_FAILURE(rv)) {
   2934         return rv;
   2935     }
   2936     /* No Initialization for MPLS LM/DM on MIP */
   2937     return rv;
   2938 }
   2939 
   2940 /*
   2941  * Function:
   2942  *     _bcm_sb2_oam_lookup_interface_priorities_init 
   2943  * Purpose:
   2944  *     Init ingress and egress OAM_INTF_PROC_SELECT_CONTROL registers.
   2945  * Parameters:
   2946  *     unit  - (IN) BCM device number
   2947  * Returns:
   2948  *     BCM_E_XXX
   2949  */
   2950 int 
   2951 _bcm_sb2_oam_lookup_interface_priorities_init (int unit)
   2952 {
   2953     uint64 intf_select;
   2954     uint64 egr_intf_select;
   2955     uint64 write_val;
   2956 
   2957     /* Default intf selection values for Ingress */
   2958     uint32 intf0_select = _BCM_OAM_DOMAIN_CVLAN;
   2959     uint32 intf1_select = _BCM_OAM_DOMAIN_SVLAN;
   2960     uint32 intf2_select = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   2961     uint32 intf3_select = _BCM_OAM_DOMAIN_VP;
   2962     uint32 intf4_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION;
   2963     uint32 intf5_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN;
   2964     uint32 intf6_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN;
   2965     uint32 intf7_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN;
   2966     uint32 intf8_select = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP;
   2967     uint32 intf9_select = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW;
   2968 
   2969     /* Default intf selection values for Egress */
   2970     uint32 egr_intf0_select = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW;
   2971     uint32 egr_intf1_select = _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP;
   2972     uint32 egr_intf2_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN;
   2973     uint32 egr_intf3_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN;
   2974     uint32 egr_intf4_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN;
   2975     uint32 egr_intf5_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION;
   2976     uint32 egr_intf6_select = _BCM_OAM_DOMAIN_VP;
   2977     uint32 egr_intf7_select = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   2978     uint32 egr_intf8_select = _BCM_OAM_DOMAIN_SVLAN;
   2979     uint32 egr_intf9_select = _BCM_OAM_DOMAIN_CVLAN;
   2980 
   2981     COMPILER_64_ZERO(intf_select);
   2982     COMPILER_64_ZERO(egr_intf_select);
   2983     COMPILER_64_ZERO(write_val);
   2984 
   2985     /* Ingress OAM_INTF_PROC_SELECT_CONTROL register config */
   2986     SOC_IF_ERROR_RETURN(
   2987             READ_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, &intf_select));
   2988     COMPILER_64_SET(write_val, 0, intf0_select);
   2989     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   2990                       INTF0f, write_val);
   2991     COMPILER_64_SET(write_val, 0, intf1_select);
   2992     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   2993                       INTF1f, write_val);
   2994     COMPILER_64_SET(write_val, 0, intf2_select);
   2995     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   2996                       INTF2f, write_val);
   2997     COMPILER_64_SET(write_val, 0, intf3_select);
   2998     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   2999                       INTF3f, write_val);
   3000     COMPILER_64_SET(write_val, 0, intf4_select);
   3001     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3002                       INTF4f, write_val);
   3003     COMPILER_64_SET(write_val, 0, intf5_select);
   3004     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3005                       INTF5f, write_val);
   3006     COMPILER_64_SET(write_val, 0, intf6_select);
   3007     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3008                       INTF6f, write_val);
   3009     COMPILER_64_SET(write_val, 0, intf7_select);
   3010     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3011                       INTF7f, write_val);
   3012     COMPILER_64_SET(write_val, 0, intf8_select);
   3013     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3014                       INTF8f, write_val);
   3015     COMPILER_64_SET(write_val, 0, intf9_select);
   3016     soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select,
   3017                       INTF9f, write_val);
   3018     
   3019     SOC_IF_ERROR_RETURN(
   3020             WRITE_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, intf_select));
   3021 
   3022     /* Egress OAM_INTF_PROC_SELECT_CONTROL register config */
   3023 
   3024     SOC_IF_ERROR_RETURN(
   3025             READ_EGR_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, &egr_intf_select));
   3026 
   3027     COMPILER_64_SET(write_val, 0, egr_intf0_select);
   3028     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3029             &egr_intf_select, INTF0f, write_val);
   3030     COMPILER_64_SET(write_val, 0, egr_intf1_select);
   3031     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3032             &egr_intf_select, INTF1f, write_val);
   3033     COMPILER_64_SET(write_val, 0, egr_intf2_select);
   3034     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3035             &egr_intf_select, INTF2f, write_val);
   3036     COMPILER_64_SET(write_val, 0, egr_intf3_select);
   3037     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3038             &egr_intf_select, INTF3f, write_val);
   3039     COMPILER_64_SET(write_val, 0, egr_intf4_select);
   3040     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3041             &egr_intf_select, INTF4f, write_val);
   3042     COMPILER_64_SET(write_val, 0, egr_intf5_select);
   3043     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3044             &egr_intf_select, INTF5f, write_val);
   3045     COMPILER_64_SET(write_val, 0, egr_intf6_select);
   3046     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3047             &egr_intf_select, INTF6f, write_val);
   3048     COMPILER_64_SET(write_val, 0, egr_intf7_select);
   3049     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3050             &egr_intf_select, INTF7f, write_val);
   3051     COMPILER_64_SET(write_val, 0, egr_intf8_select);
   3052     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3053             &egr_intf_select, INTF8f, write_val);
   3054     COMPILER_64_SET(write_val, 0, egr_intf9_select);
   3055     soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r,
   3056             &egr_intf_select, INTF9f, write_val);
   3057 
   3058     SOC_IF_ERROR_RETURN(
   3059             WRITE_EGR_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, egr_intf_select));
   3060 
   3061     return (BCM_E_NONE);
   3062 }
   3063 
   3064 /*
   3065  * Function:
   3066  *   _bcm_sb2_oam_lookup_key_priorities_init 
   3067  * Purpose:
   3068  *     Init ingress and egress OAM_KEY_SELECT_CONTROL registers.
   3069  * Parameters:
   3070  *     unit  - (IN) BCM device number
   3071  * Returns:
   3072  *     BCM_E_XXX
   3073  */
   3074 int 
   3075 _bcm_sb2_oam_lookup_key_priorities_init (int unit)
   3076 {
   3077     uint64 key_select;
   3078     uint64 egr_key_select;
   3079     uint64 write_val;
   3080 
   3081     /* Default key selection values for Ingress */
   3082     uint32 key0_select = 2;/*VFP_KEY1*/
   3083     uint32 key1_select = 3;/*VFP_KEY2*/
   3084     uint32 key2_select = 0;/*ETH_KEY1*/
   3085     uint32 key3_select = 1;/*ETH_KEY2*/
   3086     uint32 key4_select = 4;/*MPLS_KEY1*/
   3087     uint32 key5_select = 5;/*MPLS_KEY2*/
   3088     uint32 key6_select = 6;/*MPLS_KEY3*/
   3089     uint32 key7_select = 7;/*SVP_KEY*/
   3090     uint32 key8_select = 8;/*SECTION_MEP_KEY*/
   3091 
   3092     /* Default key selection values for Egress */
   3093     uint32 egr_key0_select = 2;/*DVP_KEY*/
   3094     uint32 egr_key1_select = 3;/*MEPID*/
   3095     uint32 egr_key2_select = 0;/*ETH_KEY1*/   
   3096     uint32 egr_key3_select = 1;/*ETH_KEY2*/    
   3097     uint32 egr_key4_select = 4;/*SECTION_MEP_KEY*/
   3098 
   3099     COMPILER_64_ZERO(key_select);
   3100     COMPILER_64_ZERO(egr_key_select);
   3101     COMPILER_64_ZERO(write_val);
   3102 
   3103     /* Ingress OAM_KEY_SELECT_CONTROL register config */
   3104     COMPILER_64_SET(write_val, 0, key0_select);
   3105     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3106                       KEY0f, write_val);
   3107     COMPILER_64_SET(write_val, 0, key1_select);
   3108     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3109                       KEY1f, write_val);
   3110     COMPILER_64_SET(write_val, 0, key2_select);
   3111     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3112                       KEY2f, write_val);
   3113     COMPILER_64_SET(write_val, 0, key3_select);
   3114     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3115                       KEY3f, write_val);
   3116     COMPILER_64_SET(write_val, 0, key4_select);
   3117     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3118                       KEY4f, write_val);
   3119     COMPILER_64_SET(write_val, 0, key5_select);
   3120     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3121                       KEY5f, write_val);
   3122     COMPILER_64_SET(write_val, 0, key6_select);
   3123     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3124                       KEY6f, write_val);
   3125     COMPILER_64_SET(write_val, 0, key7_select);
   3126     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3127                       KEY7f, write_val);
   3128     COMPILER_64_SET(write_val, 0, key8_select);
   3129     soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select,
   3130                       KEY8f, write_val);
   3131     
   3132     SOC_IF_ERROR_RETURN(WRITE_OAM_KEY_SELECT_CONTROL_64r(unit, key_select));
   3133 
   3134     /* Egress OAM_KEY_SELECT_CONTROL register config */
   3135 
   3136     SOC_IF_ERROR_RETURN(READ_EGR_OAM_KEY_SELECT_CONTROL_64r(unit, &egr_key_select));
   3137 
   3138     COMPILER_64_SET(write_val, 0, egr_key0_select);
   3139     soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select,
   3140                       KEY0f, write_val);
   3141     COMPILER_64_SET(write_val, 0, egr_key1_select);
   3142     soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select,
   3143                       KEY1f, write_val);
   3144     COMPILER_64_SET(write_val, 0, egr_key2_select);
   3145     soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select,
   3146                       KEY2f, write_val);
   3147     COMPILER_64_SET(write_val, 0, egr_key3_select);
   3148     soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select,
   3149                       KEY3f, write_val);
   3150     COMPILER_64_SET(write_val, 0, egr_key4_select);
   3151     soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select,
   3152                       KEY4f, write_val);
   3153 
   3154     SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_KEY_SELECT_CONTROL_64r(unit, egr_key_select));
   3155 
   3156     return (BCM_E_NONE);
   3157 } 
   3158 
   3159 /* Entry indexes in mpls_oam_ach_type_config table for various
   3160  * mpls lm dm ach types.
   3161  * NOTE:
   3162  * If you change these values, please make appropriate change in
   3163  * _bcm_sb2_mpls_oam_ach_type_config_entry_t entry_info[] variable
   3164  * in _bcm_sb2_oam_mpls_oam_ach_type_config_init function.
   3165  */
   3166 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_LM_ENTRY           0x1
   3167 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILM_ENTRY          0x2
   3168 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_DM_ENTRY           0x3
   3169 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_LMPLUSDM_ENTRY     0x4
   3170 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILMPLUSDM_ENTRY    0x5
   3171 
   3172 int
   3173 _bcm_sb2_mpls_lmdm_ach_type_counter_enable(int unit, int opcode, int value)
   3174 {
   3175     int index = 0;
   3176     soc_mem_t mem = MPLS_OAM_ACH_TYPE_CONFIGm;
   3177 
   3178     switch (opcode) {
   3179         case bcmOamMplsLmDmOpcodeTypeLm:
   3180             index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_LM_ENTRY;
   3181             break;
   3182         case bcmOamMplsLmDmOpcodeTypeIlm:
   3183             index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILM_ENTRY;
   3184             break;
   3185         case bcmOamMplsLmDmOpcodeTypeDm:
   3186             index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_DM_ENTRY;
   3187             break;
   3188         case bcmOamMplsLmDmOpcodeTypeLmPlusDm:
   3189             index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_LMPLUSDM_ENTRY;
   3190             break;
   3191         case bcmOamMplsLmDmOpcodeTypeIlmPlusDm:
   3192             index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILMPLUSDM_ENTRY;
   3193             break;
   3194         default:
   3195             /* Other opcodes are not expected. */
   3196             return BCM_E_PARAM;
   3197             break;
   3198     }
   3199     return (soc_mem_field32_modify(unit, mem, index,
   3200             LM_COUNT_ENABLEf, value));
   3201 }
   3202 
   3203 /*
   3204  * Function:
   3205  *    _bcm_sb2_oam_mpls_oam_ach_type_config_init 
   3206  * Purpose:
   3207  *     Init ingress MPLS OAM ACH TYPE CONFIG table.
   3208  * Parameters:
   3209  *     unit  - (IN) BCM device number
   3210  * Returns:
   3211  *     BCM_E_XXX
   3212  */
   3213 int 
   3214 _bcm_sb2_oam_mpls_oam_ach_type_config_init(int unit)
   3215 {
   3216     int                       rv = BCM_E_NONE; 
   3217     mpls_oam_ach_type_config_entry_t *mpls_oam_ach_type_config_buf;
   3218     int entry_mem_size;
   3219     int index = 0;
   3220     int entries_max = 0;
   3221     soc_mem_t mem = MPLS_OAM_ACH_TYPE_CONFIGm;
   3222 
   3223     _bcm_sb2_mpls_oam_ach_type_config_entry_t entry_info[]= {
   3224         /* Valid, 
   3225            ach_type, 
   3226            opcode_valid,
   3227            opcode, 
   3228            lm_count_enable,
   3229            protocol_type
   3230          */
   3231         {1, SHR_BHH_ACH_CHANNEL_TYPE, 0, -1, 0, 0}, /* BHH OAM */
   3232         {1, SHR_MPLS_LM_DM_ACH_TYPE_DLM, 1, bcmOamMplsLmDmOpcodeTypeLm, 0, 1}, /* MPLS LM */
   3233         {1, SHR_MPLS_LM_DM_ACH_TYPE_ILM, 1, bcmOamMplsLmDmOpcodeTypeIlm, 0, 1}, /* MPLS ILM */ 
   3234         {1, SHR_MPLS_LM_DM_ACH_TYPE_DM, 1, bcmOamMplsLmDmOpcodeTypeDm, 0, 1}, /* MPLS DM */
   3235         {1, SHR_MPLS_LM_DM_ACH_TYPE_DLM_DM, 1, bcmOamMplsLmDmOpcodeTypeLmPlusDm, 0, 1}, /* MPLS LM + DM */
   3236         {1, SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM, 1, bcmOamMplsLmDmOpcodeTypeIlmPlusDm, 0, 1}, /* MPLS ILM + DM */
   3237         {1, 0x0022, 0, -1, 0, 2}, /* BFD CC */
   3238         {1, 0x0023, 0, -1, 0, 2}, /* BFD CV */
   3239         {1, 0x0007, 0, -1, 0, 3}, /* BFD Raw */
   3240         {1, 0x0021, 0, -1, 0, 5}, /* PW BFD IPv4 */
   3241         {1, 0x0057, 0, -1, 0, 5}, /* PW BFD IPv6 */
   3242     };
   3243 
   3244     entries_max = 
   3245     sizeof(entry_info)/sizeof(_bcm_sb2_mpls_oam_ach_type_config_entry_t);
   3246 
   3247     entry_mem_size = sizeof(mpls_oam_ach_type_config_entry_t);
   3248 
   3249     mpls_oam_ach_type_config_buf = soc_cm_salloc(unit, 
   3250                               entry_mem_size,
   3251                               "MPLS OAM ACH TYPE CONFIG entry buffer");
   3252     
   3253     for (index = 0; index < entries_max; index++)
   3254     {
   3255         sal_memset(mpls_oam_ach_type_config_buf, 0, entry_mem_size);
   3256         soc_mem_field32_set(unit, mem, 
   3257                 (uint32 *)mpls_oam_ach_type_config_buf, VALIDf,
   3258                 entry_info[index].valid); 
   3259         soc_mem_field32_set(unit, mem, 
   3260                 (uint32 *)mpls_oam_ach_type_config_buf, ACH_TYPEf,
   3261                 entry_info[index].ach_type); 
   3262         soc_mem_field32_set(unit, mem, 
   3263                 (uint32 *)mpls_oam_ach_type_config_buf, OPCODE_VALIDf,
   3264                 entry_info[index].opcode_valid); 
   3265         if(entry_info[index].opcode != -1)
   3266         {
   3267             soc_mem_field32_set(unit, mem, 
   3268                     (uint32 *)mpls_oam_ach_type_config_buf, OPCODEf,
   3269                     entry_info[index].opcode); 
   3270         }
   3271         soc_mem_field32_set(unit, mem, 
   3272                 (uint32 *)mpls_oam_ach_type_config_buf, LM_COUNT_ENABLEf,
   3273                 entry_info[index].lm_count_enable); 
   3274         soc_mem_field32_set(unit, mem, 
   3275                 (uint32 *)mpls_oam_ach_type_config_buf, PROTOCOL_TYPEf,
   3276                 entry_info[index].protocol_type); 
   3277 
   3278         rv = soc_mem_write(unit, mem,
   3279                 MEM_BLOCK_ALL, index, mpls_oam_ach_type_config_buf); 
   3280         if (BCM_FAILURE(rv)) {
   3281             if (mpls_oam_ach_type_config_buf) {
   3282                 soc_cm_sfree(unit, mpls_oam_ach_type_config_buf);
   3283             }
   3284             return rv;
   3285         }
   3286     }
   3287 
   3288     if (mpls_oam_ach_type_config_buf) {
   3289         soc_cm_sfree(unit, mpls_oam_ach_type_config_buf);
   3290     }
   3291     
   3292     return rv;
   3293 }
   3294 
   3295 /*
   3296  * Function:
   3297  *     _bcm_sb2_oam_opcode_group_init
   3298  * Purpose:
   3299  *     Init ingress and egress OAM opcode groups. 
   3300  * Parameters:
   3301  *     unit  - (IN) BCM device number
   3302  * Retruns:
   3303  *     BCM_E_XXX
   3304  */
   3305 int
   3306 _bcm_sb2_oam_opcode_group_init(int unit)
   3307 {
   3308     int                       rv = BCM_E_NONE; 
   3309     oam_opcode_group_entry_t    *opcode_grp_buf;
   3310     int                       entry_mem_size;    /* Size of table entry. */ 
   3311     int                       index = 0;
   3312     int                       entries_max = 0;
   3313     _bcm_sb2_opcode_group_entry_t entry_info[] = {
   3314 
   3315       /* ETH OAM */
   3316       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_CCM),
   3317          _BCM_SB2_OPCODE_GROUP_ETH_OAM_CCM ,
   3318          _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH,
   3319          _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM CCM */
   3320       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBR),
   3321          _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBR ,
   3322          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3323          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LBR */
   3324       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBM),
   3325          _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBM ,
   3326          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3327          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LBM */
   3328       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTR),
   3329          _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTR ,
   3330          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3331          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LTR */
   3332       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTM),
   3333          _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTM,
   3334          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3335          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LTM */
   3336 
   3337        /* NON CFM */
   3338       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMM),
   3339          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3340          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3341          _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LMM */
   3342       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMR),
   3343          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3344          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3345          _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LMR */
   3346       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_1DM),
   3347          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3348          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3349          _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM 1DM */
   3350       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMM),
   3351          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3352          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3353          _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM DMM */
   3354       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMR),
   3355          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3356          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3357          _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM DMR */
   3358       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLM),
   3359          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3360          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3361          _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM SLM */
   3362       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLR),
   3363          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3364          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM,
   3365          _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM SLR */
   3366       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_AIS),
   3367          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3368          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3369          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM AIS */
   3370       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LCK),
   3371          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3372          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3373          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LCK */
   3374       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_TST),
   3375          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3376          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3377          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM TST */
   3378       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LIN_APS),
   3379          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3380          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3381          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LIN_APS */
   3382       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_RING_APS),
   3383          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 ,
   3384          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3385          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM RING_APS */
   3386       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_MCC),
   3387          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3388          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3389          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM MCC */
   3390       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXM),
   3391          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3392          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3393          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM EXM */
   3394       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXR),
   3395          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3396          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3397          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM EXR */
   3398       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSM),
   3399          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3400          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3401          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM VSM */
   3402       {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSR),
   3403          _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 ,
   3404          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3405          _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM VSR */
   3406 
   3407       /* BHH OAM */
   3408       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_CCM),
   3409          _BCM_SB2_OPCODE_GROUP_BHH_OAM_CCM ,
   3410          _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH}, /* BHH OAM CCM */
   3411       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBR),
   3412          _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBR ,
   3413          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LBR */
   3414       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBM),
   3415          _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBM ,
   3416          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LBM */
   3417       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTR),
   3418          _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTR ,
   3419          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LTR */
   3420       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTM),
   3421          _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTM,
   3422          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LTM */
   3423 
   3424        /* NON CFM */
   3425       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMM),
   3426          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3427          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM LMM */
   3428       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMR),
   3429          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3430          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM LMR */
   3431       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_1DM),
   3432          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3433          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM 1DM */
   3434       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMM),
   3435          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3436          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM DMM */
   3437       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMR),
   3438          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3439          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM DMR */
   3440       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLM),
   3441          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3442          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM SLM */
   3443       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLR),
   3444          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3445          _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM SLR */
   3446       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_AIS),
   3447          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3448          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3449          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM AIS */
   3450       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LCK),
   3451          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3452          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3453          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM LCK */
   3454       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_TST),
   3455          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3456          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3457          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM TST */
   3458       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LIN_APS),
   3459          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3460          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3461          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM LIN_APS */
   3462       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_RING_APS),
   3463          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 ,
   3464          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3465          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM RING_APS */
   3466       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_MCC),
   3467          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3468          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3469          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM MCC */
   3470       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXM),
   3471          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3472          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3473          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM EXM */
   3474       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXR),
   3475          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3476          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3477          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM EXR */
   3478       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSM),
   3479          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3480          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3481          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM VSM */
   3482       {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSR),
   3483          _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 ,
   3484          _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW,
   3485          _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM VSR */
   3486 
   3487       /* MPLS LM DM */
   3488       {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeLm), 
   3489        _BCM_SB2_OPCODE_GROUP_MPLS_LM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 
   3490        _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (D)LM */
   3491       {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeIlm), 
   3492        _BCM_SB2_OPCODE_GROUP_MPLS_ILM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 
   3493        _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS ILM */
   3494       {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeDm), 
   3495        _BCM_SB2_OPCODE_GROUP_MPLS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 
   3496        _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS DM */
   3497       {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeLmPlusDm), 
   3498        _BCM_SB2_OPCODE_GROUP_MPLS_LM_PLUS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 
   3499        _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (D)LM + DM */
   3500       {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeIlmPlusDm), 
   3501        _BCM_SB2_OPCODE_GROUP_MPLS_ILM_PLUS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 
   3502        _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (I)LM + DM */
   3503 
   3504     };
   3505     entries_max = sizeof(entry_info) / sizeof(_bcm_sb2_opcode_group_entry_t);
   3506 
   3507    /* Set ingress and egress OAM opcode group */
   3508     entry_mem_size = sizeof(oam_opcode_group_entry_t);
   3509     opcode_grp_buf = soc_cm_salloc(unit, entry_mem_size ,
   3510                               "Opcode group entry buffer");
   3511     if (NULL == opcode_grp_buf) {
   3512         return (BCM_E_MEMORY);
   3513     }
   3514     /* Initialize the entry buffer. */
   3515     sal_memset(opcode_grp_buf, 0, entry_mem_size);
   3516 
   3517     for (index = 0; index < entries_max; index++) {
   3518         soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 
   3519                 (uint32 *)opcode_grp_buf, OPCODE_GROUPf,
   3520                 entry_info[index].opcode_group); 
   3521         soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 
   3522                 (uint32 *)opcode_grp_buf, CPU_OPCODEf,
   3523                 entry_info[index].cpu_opcode); 
   3524         soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 
   3525                 (uint32 *)opcode_grp_buf, OLP_HDR_TYPE_COMPRESSEDf,
   3526                 entry_info[index].olp_hdr_type_compressed); 
   3527         rv = soc_mem_write(unit, OAM_OPCODE_GROUPm,
   3528                 MEM_BLOCK_ALL, entry_info[index].key, opcode_grp_buf);
   3529         if (BCM_FAILURE(rv)) {
   3530             if (opcode_grp_buf) {
   3531                 soc_cm_sfree(unit, opcode_grp_buf);
   3532                 opcode_grp_buf = NULL;
   3533             }
   3534             return rv;
   3535         }
   3536         rv = soc_mem_write(unit, EGR_OAM_OPCODE_GROUPm,
   3537                 MEM_BLOCK_ALL, entry_info[index].key, opcode_grp_buf); 
   3538         if (BCM_FAILURE(rv)) {
   3539             if (opcode_grp_buf) {
   3540                 soc_cm_sfree(unit, opcode_grp_buf);
   3541                 opcode_grp_buf = NULL;
   3542             }
   3543             return rv;
   3544         }
   3545     }
   3546     if (opcode_grp_buf) {
   3547          soc_cm_sfree(unit, opcode_grp_buf);
   3548     }
   3549     return (rv);
   3550 }
   3551 
   3552 
   3553 STATIC void
   3554 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(int unit, uint8 active_mdl, 
   3555                                              int ma_base_index,
   3556                                              uint8 *passive_mdl,
   3557                                              int is_upmep)
   3558 {
   3559     uint32               mdl_value[1] = { 0 };
   3560     int ma_offset = 0;
   3561     int mdl = 0;
   3562     bcm_oam_endpoint_t ep_id_at_mdl = _BCM_OAM_INVALID_INDEX;
   3563     _bcm_oam_control_t  *oc = NULL;
   3564     _bcm_oam_hash_data_t *h_data_p = NULL;
   3565 
   3566     /* coverity[check_return] */
   3567     _bcm_sb2_oam_control_get(unit, &oc);
   3568 
   3569     if (oc == NULL) {
   3570         /* Not expected */
   3571         return;
   3572     }
   3573  
   3574     /* Initialize passive_mdl to 0 */ 
   3575     *passive_mdl = 0; 
   3576     mdl_value[0] = active_mdl; 
   3577 
   3578     for (mdl = 0; mdl <= 7; mdl++) {
   3579         if (SHR_BITGET(mdl_value, mdl)) {
   3580             ep_id_at_mdl = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get(oc, 
   3581                             _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   3582                             (ma_base_index, ma_offset, is_upmep)); 
   3583             if (ep_id_at_mdl != _BCM_OAM_INVALID_INDEX) { 
   3584                 h_data_p = &(oc->oam_hash_data[ep_id_at_mdl]);
   3585                 /* Set the passive bitmap only if it is not a MIP */
   3586                 if (!_BCM_OAM_EP_IS_MIP(h_data_p)) {
   3587                     *passive_mdl = (1 << mdl) | ((1 << mdl) -1);
   3588                 }
   3589             } else {
   3590                 /* Log an error. Ideally should not happen. */
   3591                 LOG_ERROR(BSL_LS_BCM_OAM,
   3592                         (BSL_META_U(unit,
   3593                                     "OAM(unit %d) Error: EP ID mapping get failed (MA_IDX=%d) -"
   3594                                     "\n"), unit, ma_base_index+ma_offset));
   3595             }
   3596             ma_offset++;
   3597         }
   3598     }
   3599 }
   3600 
   3601 
   3602 /*
   3603  * Function:
   3604  *     _bcm_sb2_oam_ep_hash_key_construct
   3605  * Purpose:
   3606  *     Construct hash table key for a given endpoint information.
   3607  * Parameters:
   3608  *     unit    - (IN) BCM device number
   3609  *     oc      - (IN) Pointer to OAM control structure.
   3610  *     ep_info - (IN) Pointer to endpoint information structure.
   3611  *     key     - (IN/OUT) Pointer to hash key buffer.
   3612  * Retruns:
   3613  *     None
   3614  */
   3615 STATIC void
   3616 _bcm_sb2_oam_ep_hash_key_construct(int unit,
   3617                                _bcm_oam_control_t *oc,
   3618                                bcm_oam_endpoint_info_t *ep_info,
   3619                                _bcm_oam_hash_key_t *key)
   3620 {
   3621     uint8  *loc = *key;
   3622     uint32 direction = 0;
   3623 
   3624     sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t));
   3625 
   3626     if (NULL != ep_info) {
   3627         if ((ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING)) {
   3628             direction = 1;
   3629         }
   3630 
   3631         _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group));
   3632 
   3633         _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name));
   3634 
   3635         _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport));
   3636 
   3637         _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level));
   3638 
   3639         _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan));
   3640 
   3641         _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 
   3642                                           sizeof(ep_info->inner_vlan));
   3643         _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction));
   3644         _BCM_OAM_KEY_PACK(loc, &ep_info->mpls_label, 
   3645                 sizeof(ep_info->mpls_label));
   3646         _BCM_OAM_KEY_PACK(loc, &ep_info->type, sizeof(ep_info->type));
   3647     }
   3648 
   3649     /* End address should not exceed size of _bcm_oam_hash_key_t. */
   3650     assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t));
   3651 }
   3652 
   3653 /* Return if a given PW endpoint's port is in protection or working state. 
   3654    Return values : 
   3655    0 - Working 
   3656    1 - Protection
   3657 */
   3658 int
   3659 _bcm_sb2_oam_mpls_lmdm_pw_protection_get(int unit, 
   3660                                          const _bcm_oam_hash_data_t *hash_data)
   3661 {
   3662 #if defined(INCLUDE_L3)
   3663     int nh_index = 0, failover_nh_index = 0;
   3664     ing_dvp_table_entry_t dvp;
   3665     ing_l3_next_hop_entry_t failover_l3_next_hop;
   3666     int rv = BCM_E_NONE;
   3667     bcm_failover_t failover_id;
   3668     bcm_multicast_t  failover_mc_group;
   3669     int failover_port_is_trunk = 0, failover_port_trunk = BCM_TRUNK_INVALID;
   3670     int failover_port = 0, failover_modid = 0, mod_id = 0, port_id = 0;
   3671     uint32 vp = hash_data->vp;
   3672 
   3673     sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   3674     sal_memset(&failover_l3_next_hop, 0, sizeof(ing_l3_next_hop_entry_t));
   3675 
   3676     /* Read the ING_DVP table to get the next hop index */
   3677     rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
   3678     if (BCM_FAILURE(rv)) {
   3679         return 0;
   3680     }
   3681 
   3682     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   3683             NEXT_HOP_INDEXf);
   3684 
   3685     /* Use that nh index to find if there exists a failover nh index */
   3686     rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index,
   3687             &failover_id, &failover_nh_index, &failover_mc_group);
   3688 
   3689     if (BCM_SUCCESS(rv)) {
   3690         if (failover_nh_index > 0) {
   3691             /* Failover enabled */
   3692             
   3693             /* Check if it is the same interface as ours. If it 
   3694                is the same interface, then our interface is in protection 
   3695                state else it is in working state. */
   3696             rv = READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, failover_nh_index,
   3697                                        &failover_l3_next_hop);
   3698             if (BCM_FAILURE(rv)) {
   3699                 return 0;
   3700             }
   3701             failover_port_is_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   3702                                                         &failover_l3_next_hop,
   3703                                                         Tf);
   3704             if (failover_port_is_trunk) {
   3705                 if (hash_data->trunk_id != BCM_TRUNK_INVALID) {   
   3706                     failover_port_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   3707                                                          &failover_l3_next_hop,
   3708                                                             TGIDf);
   3709                     if (failover_port_trunk == hash_data->trunk_id) {
   3710                         /* Matched. Return PROTECTION state */
   3711                         return 1; 
   3712                     }
   3713                     /* No match. Return WORKING (or not PROTECTION) state */
   3714                     return 0;
   3715                 } else {
   3716                     /* Endpoint port is not a trunk (or part of it), but 
   3717                        failover port is. So return WORKING (or NOT PROTECTION).
   3718                      */
   3719                     return 0;
   3720                 }
   3721             } else {
   3722                 failover_modid = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   3723                                                     &failover_l3_next_hop,
   3724                                                     MODULE_IDf);
   3725                 failover_port = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   3726                                                  &failover_l3_next_hop,
   3727                                                   PORT_NUMf);
   3728                 port_id = _BCM_OAM_GLP_PORT_GET(hash_data->sglp);
   3729                 mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(hash_data->sglp);
   3730                 if ((failover_modid == mod_id) &&
   3731                     (failover_port  == port_id)) {
   3732                     /* Matched. Return PROTECTION state */
   3733                     return 1; 
   3734                 }
   3735                 return 0;
   3736             }
   3737         }
   3738         return 0;
   3739     }
   3740 #endif /* INCLUDE_L3 */
   3741     return 0;
   3742 } 
   3743 
   3744 STATIC void
   3745 _bcm_sb2_oam_mpls_mp_group_key_construct (int unit, 
   3746                                          const _bcm_oam_hash_data_t *h_data_p,
   3747                                          int is_egress,
   3748                                          void *mp_group_key_p)
   3749 {
   3750     soc_field_t          fields[4] = {INVALIDf, INVALIDf, INVALIDf, INVALIDf};
   3751     uint32               values[4] = {0,0,0,0};
   3752     int                  num_fields = 0;
   3753     int                  field;
   3754 #if defined(INCLUDE_BHH)
   3755     _bcm_oam_control_t  *oc;
   3756 
   3757     /* coverity[check_return] */
   3758     _bcm_sb2_oam_control_get(unit, &oc);
   3759 #endif /* INCLUDE_BHH */
   3760 
   3761     if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) ||
   3762         (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) {
   3763         fields[0] = KEY_TYPEf;
   3764         if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionPort) ||
   3765             (h_data_p->type == bcmOAMEndpointTypeBhhSection))  {
   3766             values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION;
   3767 
   3768             fields[1] = GLPf;
   3769             values[1] = h_data_p->sglp;
   3770 
   3771             num_fields = 2;
   3772         } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) ||
   3773                    (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan)) {
   3774             values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN;
   3775 
   3776             fields[1] = GLPf;
   3777             values[1] = h_data_p->sglp;
   3778 
   3779             fields[2] = CVIDf;
   3780             values[2] = h_data_p->inner_vlan;
   3781 
   3782             num_fields = 3;
   3783         } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) ||
   3784                    (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan))  {
   3785             values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN;
   3786 
   3787             fields[1] = GLPf;
   3788             values[1] = h_data_p->sglp;
   3789 
   3790             fields[2] = SVIDf;
   3791             values[2] = h_data_p->vlan;
   3792 
   3793             num_fields = 3;
   3794         } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) ||
   3795                    (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)) {
   3796             values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN;
   3797 
   3798             fields[1] = GLPf;
   3799             values[1] = h_data_p->sglp;
   3800 
   3801             fields[2] = SVIDf;
   3802             values[2] = h_data_p->vlan;
   3803 
   3804             fields[3] = CVIDf;
   3805             values[3] = h_data_p->inner_vlan;
   3806 
   3807             num_fields = 4;
   3808         }
   3809     } else if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))||
   3810                (h_data_p->type == bcmOAMEndpointTypeBHHMPLS)) {
   3811         fields[0] = KEY_TYPEf;
   3812         if (is_egress) {
   3813             values[0] = _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP;
   3814 
   3815             fields[1] = MEPIDf;
   3816 
   3817             if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
   3818                 values[1] = h_data_p->name;
   3819             } else {
   3820 #if defined(INCLUDE_BHH)
   3821                 values[1] = BCM_OAM_BHH_GET_LSP_KEY(h_data_p);
   3822 #endif /* INCLUDE_BHH */
   3823             }
   3824 
   3825             num_fields = 2;
   3826         } else {
   3827             values[0] = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP;
   3828 #if defined(INCLUDE_L3)
   3829             if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label,
   3830                         BCM_GPORT_INVALID) != BCM_E_NONE) {
   3831                 /* SGLP contains generic logical port. */
   3832                 fields[1] = GLPf;
   3833                 values[1] = h_data_p->sglp;
   3834             } else {
   3835                 /* SGLP is invalid if label is port independent. */
   3836                 fields[1] = GLPf;
   3837                 values[1] = 0xffff;
   3838             }
   3839 #else
   3840                 fields[1] = GLPf;
   3841                 values[1] = h_data_p->sglp;
   3842 #endif
   3843 
   3844             fields[2] = MPLS_LABELf;
   3845             values[2] = h_data_p->label;
   3846 
   3847             num_fields = 3;
   3848         }
   3849     } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) {
   3850         fields[0] = KEY_TYPEf;
   3851         values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW;
   3852 
   3853         fields[1] = VPf;
   3854         if (is_egress) {
   3855             values[1] = BCM_GPORT_MPLS_PORT_ID_GET(h_data_p->gport);
   3856         } else {
   3857             values[1] = h_data_p->vp;
   3858         }
   3859 
   3860         fields[2] = PROTECTIONf;
   3861         if (is_egress) {
   3862             values[2] = 0; /* Protection should be always set to 0 in egress */
   3863         } else {
   3864             values[2] = _bcm_sb2_oam_mpls_lmdm_pw_protection_get(unit, h_data_p);
   3865         }
   3866         num_fields = 3;
   3867     } else if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   3868         fields[0] = KEY_TYPEf;
   3869 
   3870         if (is_egress) {
   3871             values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW;
   3872             fields[1] = VPf;
   3873             values[1] = BCM_GPORT_MPLS_PORT_ID_GET(h_data_p->gport);
   3874             fields[2] = PROTECTIONf;
   3875             values[2] = 0;
   3876         } else {
   3877             values[0] = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP;
   3878 #if defined(INCLUDE_L3)
   3879             if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label,
   3880                         BCM_GPORT_INVALID) != BCM_E_NONE) {
   3881                 /* SGLP contains generic logical port. */
   3882                 fields[1] = GLPf;
   3883                 values[1] = h_data_p->sglp;
   3884             } else {
   3885                 /* SGLP is invalid if label is port independent. */
   3886                 fields[1] = GLPf;
   3887                 values[1] = 0xffff;
   3888             }
   3889 #else
   3890                 fields[1] = GLPf;
   3891                 values[1] = h_data_p->sglp;
   3892 #endif
   3893 
   3894             fields[2] = MPLS_LABELf;
   3895             values[2] = h_data_p->label;
   3896         }
   3897         num_fields = 3;
   3898     } else {
   3899         /* Should not be hit */
   3900         return;
   3901     }
   3902 
   3903     for (field = 0; field < num_fields; field++) {
   3904         if (is_egress) {
   3905             soc_EGR_MP_GROUPm_field32_set(unit, mp_group_key_p, fields[field], values[field]);
   3906         } else {
   3907             soc_MP_GROUPm_field32_set(unit, mp_group_key_p, fields[field], values[field]);
   3908         }
   3909     }
   3910 }
   3911 
   3912 /*
   3913  * Function:
   3914  *     _bcm_sb2_oam_egr_lmep_key_construct
   3915  * Purpose:
   3916  *     Construct egress MP group table lookup key for a given endpoint.
   3917  * Parameters:
   3918  *     unit     - (IN) BCM device number
   3919  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   3920  *     egr_mp_grp_key_p - (IN/OUT) Pointer to entry buffer.
   3921  * Retruns:
   3922  *     None
   3923  */
   3924 STATIC void
   3925 _bcm_sb2_oam_egr_lmep_key_construct(int unit,
   3926                             const _bcm_oam_hash_data_t *h_data_p,
   3927                             egr_mp_group_entry_t *egr_mp_grp_key_p)
   3928 {
   3929     _bcm_oam_control_t  *oc = NULL;
   3930 
   3931     /* coverity[check_return] */
   3932     _bcm_sb2_oam_control_get(unit, &oc);
   3933 
   3934     /* Set the valid bit. */
   3935     soc_EGR_MP_GROUPm_field32_set
   3936         (unit, egr_mp_grp_key_p, VALIDf, 1);
   3937     /* Set the search key type. */
   3938     soc_EGR_MP_GROUPm_field32_set
   3939         (unit, egr_mp_grp_key_p, KEY_TYPEf, h_data_p->oam_domain);
   3940 
   3941 
   3942     if (BHH_EP_TYPE(h_data_p) || MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
   3943         _bcm_sb2_oam_mpls_mp_group_key_construct(unit, h_data_p, 1,
   3944                                                  egr_mp_grp_key_p);
   3945     } else if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) {
   3946         /* Set port type status in the search key.
   3947          * VP field contains virtual port.
   3948          */
   3949         soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, VPf, h_data_p->vp);
   3950     } else {
   3951         if (oc->eth_oam_mp_group_vlan_key ==
   3952                               _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) {
   3953             /* In earlier versions of the SDK, both inner & outer vlan was always
   3954              * programmed in the MP_GROUP irrespective of the MEP type, this has
   3955              * been changed to program only CVLAN for CVLAN MEPs and SVLAN for
   3956              * SVLAN MEPs. To avoid breaking warm-upgrade the old scheme is still
   3957              * supported.
   3958              */
   3959             soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   3960                                           SVIDf, h_data_p->vlan);
   3961 
   3962             soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   3963                                           CVIDf, h_data_p->inner_vlan);
   3964 
   3965         } else {
   3966             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) {
   3967                 /* SVLAN/C+SVLAN */
   3968                 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   3969                                               SVIDf, h_data_p->vlan);
   3970             }
   3971 
   3972             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) {
   3973                 /* CLVAN/C+SVLAN */
   3974                 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   3975                                               CVIDf, h_data_p->inner_vlan);
   3976             }
   3977         }
   3978         /* DGLP contains generic logical port. */
   3979         soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p,
   3980                                       GLPf, h_data_p->dglp);
   3981     }
   3982 }
   3983 
   3984 /*
   3985  * Function:
   3986  *     _bcm_sb2_oam_lmep_key_construct
   3987  * Purpose:
   3988  *     Construct LMEP view lookup key for a given endpoint.
   3989  * Parameters:
   3990  *     unit     - (IN) BCM device number
   3991  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   3992  *     mp_group_key_p - (IN/OUT) Pointer to entry buffer.
   3993  * Retruns:
   3994  *     None
   3995  */
   3996 STATIC void
   3997 _bcm_sb2_oam_lmep_key_construct(int unit,
   3998                             const _bcm_oam_hash_data_t *h_data_p,
   3999                             mp_group_entry_t *mp_group_key_p)
   4000 {
   4001     _bcm_oam_control_t  *oc = NULL;
   4002 
   4003     /* coverity[check_return] */
   4004     _bcm_sb2_oam_control_get(unit, &oc);
   4005 
   4006     /* Set the search key type. */
   4007     soc_MP_GROUPm_field32_set(unit, mp_group_key_p, KEY_TYPEf,
   4008                               h_data_p->oam_domain);
   4009 
   4010     if (BHH_EP_TYPE(h_data_p) || MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
   4011         _bcm_sb2_oam_mpls_mp_group_key_construct(unit, h_data_p,
   4012                                                  0, mp_group_key_p);
   4013 
   4014     } else if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) {
   4015         /* Set port type status in the search key.
   4016          * Vp field contains virtual port.
   4017          */
   4018         soc_MP_GROUPm_field32_set(unit, mp_group_key_p, VPf, h_data_p->vp);
   4019 
   4020     } else { /* Ethernet */
   4021 
   4022         if (oc->eth_oam_mp_group_vlan_key ==
   4023                               _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) {
   4024             /* In earlier versions of the SDK, both inner & outer vlan was always
   4025              * programmed in the MP_GROUP irrespective of the MEP type, this has
   4026              * been changed to program only CVLAN for CVLAN MEPs and SVLAN for
   4027              * SVLAN MEPs. To avoid breaking warm-upgrade the old scheme is still
   4028              * supported.
   4029              */
   4030             soc_MP_GROUPm_field32_set(unit, mp_group_key_p,
   4031                                       SVIDf, h_data_p->vlan);
   4032 
   4033             soc_MP_GROUPm_field32_set(unit, mp_group_key_p,
   4034                                       CVIDf, h_data_p->inner_vlan);
   4035 
   4036         } else {
   4037             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) {
   4038                 /* SVLAN/C+SVLAN */
   4039                 soc_MP_GROUPm_field32_set(unit, mp_group_key_p,
   4040                                           SVIDf, h_data_p->vlan);
   4041             }
   4042 
   4043             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) {
   4044                 /* CLVAN/C+SVLAN */
   4045                 soc_MP_GROUPm_field32_set(unit, mp_group_key_p,
   4046                                           CVIDf, h_data_p->inner_vlan);
   4047             }
   4048         }
   4049         /* SGLP contains generic logical port. */
   4050         soc_MP_GROUPm_field32_set(unit, mp_group_key_p,
   4051                                   GLPf, h_data_p->sglp);
   4052     }
   4053 }
   4054 
   4055 /*
   4056  * Function:
   4057  *     _bcm_sb2_oam_rmep_key_construct
   4058  * Purpose:
   4059  *     Construct RMEP view lookup key for a given endpoint.
   4060  * Parameters:
   4061  *     unit     - (IN) BCM device number
   4062  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   4063  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
   4064  * Retruns:
   4065  *     None
   4066  */
   4067 STATIC void
   4068 _bcm_sb2_oam_rmep_key_construct(int unit,
   4069                             const _bcm_oam_hash_data_t *h_data_p,
   4070                             l3_entry_1_entry_t *l3_key_p)
   4071 {
   4072 
   4073     /* Set the search key type. */
   4074     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   4075         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP);
   4076 
   4077     /* Set endpoint name. */
   4078     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   4079         (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name);
   4080 
   4081     /* Set MA_PTR */
   4082     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   4083         (unit, l3_key_p, RMEP__MA_PTRf, h_data_p->group_index);
   4084 
   4085 }
   4086 
   4087 #if defined(KEY_PRINT)
   4088 /*
   4089  * Function:
   4090  *     _bcm_oam_hash_key_print
   4091  * Purpose:
   4092  *     Print the contents of a hash key buffer. 
   4093  * Parameters:
   4094  *     hash_key - (IN) Pointer to hash key buffer.
   4095  * Retruns:
   4096  *     None
   4097  */
   4098 STATIC void
   4099 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key)
   4100 {
   4101     int i;
   4102     LOG_CLI((BSL_META_U(unit,
   4103                         "HASH KEY:")));
   4104     for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) {
   4105         LOG_CLI((BSL_META_U(unit,
   4106                             ":%u"), *(hash_key[i])));
   4107     }
   4108     LOG_CLI((BSL_META_U(unit,
   4109                         "\n")));
   4110 }
   4111 #endif
   4112 
   4113 /*
   4114  * Function:
   4115  *     _bcm_sb2_oam_control_get
   4116  * Purpose:
   4117  *     Lookup a OAM control config from a bcm device id.
   4118  * Parameters:
   4119  *     unit -  (IN)BCM unit number.
   4120  *     oc   -  (OUT) OAM control structure.
   4121  * Retruns:
   4122  *     BCM_E_XXX
   4123  */
   4124 STATIC int
   4125 _bcm_sb2_oam_control_get(int unit, _bcm_oam_control_t **oc)
   4126 {
   4127     if (NULL == oc) {
   4128         return (BCM_E_PARAM);
   4129     }
   4130 
   4131     /* Ensure oam module is initialized. */
   4132     _BCM_OAM_IS_INIT(unit);
   4133 
   4134     *oc = _sb2_oam_control[unit];
   4135 
   4136     return (BCM_E_NONE);
   4137 }
   4138 
   4139 /*
   4140  * Function:
   4141  *     _bcm_sb2_oam_group_endpoint_count_init
   4142  * Purpose:
   4143  *     Retrieves and initializes endpoint count information for this device.
   4144  * Parameters:
   4145  *     unit -  (IN) BCM unit number.
   4146  *     oc   -  (IN) Pointer to device OAM control structure.
   4147  * Retruns:
   4148  *     BCM_E_XXX
   4149  */
   4150 STATIC int
   4151 _bcm_sb2_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc)
   4152 {
   4153     /* Input parameter check. */
   4154     if (NULL == oc) {
   4155         return (BCM_E_PARAM);
   4156     }
   4157 
   4158     /*
   4159      * Get endpoint hardware table index count values and
   4160      * initialize device OAM control structure members variables.
   4161      */
   4162     oc->rmep_count = soc_mem_index_count(unit, RMEPm);
   4163     oc->lmep_count = soc_mem_index_count(unit, LMEPm);
   4164     oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm);
   4165     oc->egr_ma_idx_count = soc_mem_index_count(unit, EGR_MA_INDEXm);
   4166 
   4167     /* Max number of endpoints supported by the device. */
   4168     oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + 
   4169                                                    oc->egr_ma_idx_count);
   4170 
   4171     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4172                 (BSL_META_U(unit,
   4173                             "OAM(unit %d) Info: Total No. endpoint Count = %d.\n"),
   4174                  unit, oc->ep_count));
   4175 
   4176     /* Max number of MA Groups supported by device. */
   4177     oc->group_count = soc_mem_index_count(unit, MA_STATEm);
   4178     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4179                 (BSL_META_U(unit,
   4180                             "OAM(unit %d) Info: Total No. Group Count = %d.\n"),
   4181                  unit, oc->group_count));
   4182 
   4183     return (BCM_E_NONE);
   4184 }
   4185 
   4186 /*
   4187  * Function:
   4188  *     _bcm_sb2_oam_ccm_rx_timeout_enable
   4189  * Purpose:
   4190  *     Enable CCM Timer operations for endpoint state table.
   4191  * Parameters:
   4192  *     unit -  (IN) BCM unit number.
   4193  *     state - (IN) Enable/Disable.
   4194  * Retruns:
   4195  *     BCM_E_XXX
   4196  * Note:
   4197  *     RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only.
   4198  */
   4199 STATIC int
   4200 _bcm_sb2_oam_ccm_rx_timeout_set(int unit, uint8 state)
   4201 {
   4202     int     rv;       /* Opreation return status.   */
   4203     uint32  rval = 0; /* Register value.            */
   4204 
   4205     /* Enable timer instructions to RMEP/MA_STATE Table. */
   4206     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   4207                       TIMER_ENABLEf, state ? 1 : 0);
   4208 
   4209     /* Set Clock granularity to 250us ticks - 1. */
   4210     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   4211                       CLK_GRANf, 1);
   4212 
   4213     rv = WRITE_OAM_TIMER_CONTROLr(unit, rval);
   4214     if (BCM_FAILURE(rv)) {
   4215         LOG_ERROR(BSL_LS_BCM_OAM,
   4216                   (BSL_META_U(unit,
   4217                               "OAM(unit %d) Error: Timer enable - Failed.\n"),
   4218                    unit));
   4219         return (rv);
   4220     }
   4221 
   4222     return (rv);
   4223 }
   4224 
   4225 /*
   4226  * Function:
   4227  *     _bcm_sb2_oam_ccm_tx_config_enable
   4228  * Purpose:
   4229  *     Enable transmission of OAM PDUs on local endpoint.
   4230  * Parameters:
   4231  *     unit -  (IN) BCM unit number.
   4232  *     state - (IN) Enable/Disable
   4233  * Retruns:
   4234  *     BCM_E_XXX
   4235  */
   4236 STATIC int
   4237 _bcm_sb2_oam_ccm_tx_config_set(int unit, uint8 state)
   4238 {
   4239     int     rv;       /* Opreation return status.   */
   4240     uint32  rval = 0; /* Register value.            */
   4241 
   4242     /* Enable OAM LMEP Tx. */
   4243     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   4244                       TX_ENABLEf, state ? 1 : 0);
   4245 
   4246     /* Enable CMIC buffer. */
   4247     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   4248                       CMIC_BUF_ENABLEf, state ? 1 : 0);
   4249 
   4250     rv = WRITE_OAM_TX_CONTROLr(unit, rval);
   4251     if (BCM_FAILURE(rv)) {
   4252         LOG_ERROR(BSL_LS_BCM_OAM,
   4253                   (BSL_META_U(unit,
   4254                               "OAM(unit %d) Error: Tx config enable - Failed.\n"),
   4255                    unit));
   4256     }
   4257     return (rv);
   4258 }
   4259 
   4260 /*
   4261  * Function:
   4262  *     _bcm_sb2_oam_misc_config
   4263  * Purpose:
   4264  *     Miscellaneous OAM configurations:
   4265  *         1. Enable IFP lookup on the CPU port. 
   4266  * Parameters:
   4267  *     unit -  (IN) BCM unit number.
   4268  * Retruns:
   4269  *     BCM_E_XXX
   4270  */
   4271 STATIC int
   4272 _bcm_sb2_oam_misc_config(int unit)
   4273 {
   4274     int     rv;       /* Opreation return status.   */
   4275 
   4276     /*
   4277      * Enable ingress FP for CPU port so LM/DM packets sent from CPU
   4278      * can be processed.
   4279      */
   4280     rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit),
   4281                                   bcmPortControlFilterIngress, 1);
   4282     if (BCM_FAILURE(rv)) {
   4283         LOG_ERROR(BSL_LS_BCM_OAM,
   4284                   (BSL_META_U(unit,
   4285                               "OAM(unit %d) Error: bcm_esw_port_control_set"
   4286                                " - Failed.\n"), unit));
   4287         return (rv);
   4288     }
   4289     return (rv);
   4290 
   4291 }
   4292 
   4293 /*
   4294  * Function:
   4295  *     _bcm_sb2_oam_profile_tables_init
   4296  * Purpose:
   4297  *     Create ingress and egress service priority mapping profile table and 
   4298  *     setup a default profile. Create Ingress and egress OAM opcode control 
   4299  *     profile table, dglp profile 
   4300  * Parameters:
   4301  *     unit -  (IN) BCM unit number.
   4302  *     oc   -  (IN) Pointer to OAM control structure.
   4303  * Retruns:
   4304  *     BCM_E_XXX
   4305  */
   4306 STATIC int
   4307 _bcm_sb2_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc)
   4308 {
   4309     int         rv = BCM_E_NONE;/* Opreation return status.   */
   4310     soc_mem_t   mem;           /* Profiled table memory.      */
   4311     int         entry_words;   /* Profile table word size.    */
   4312     int         pri;           /* Priority                    */
   4313     void        *entries[1];   /* Profile entry. */
   4314     uint32      profile_index; /* Profile table index. */
   4315     bcm_module_t         modid;
   4316     uint32      dglp = 0;
   4317     egr_oam_dglp_profile_entry_t egr_dglp_profile_entry;
   4318     ing_oam_dglp_profile_entry_t ing_dglp_profile_entry;
   4319     oam_opcode_control_profile_entry_t *opcode_entry; /* Opcode control 
   4320                                                              profile entry.  */
   4321     egr_oam_opcode_control_profile_entry_t *egr_opcode_entry;
   4322     int map_id;
   4323     bcm_qos_map_t map;
   4324 
   4325     if (!SOC_WARM_BOOT(unit)) {
   4326         /*
   4327          * Initialize ingress/egress priority map profile table.
   4328          * All internal priorities map to counter offset:'0'.
   4329          */
   4330         BCM_IF_ERROR_RETURN(bcm_esw_qos_map_create(unit, 
   4331                     BCM_QOS_MAP_OAM_INTPRI,
   4332                     &map_id));
   4333         for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++)
   4334         {
   4335             sal_memset(&map, 0, sizeof(map));
   4336             map.int_pri = pri;
   4337             map.counter_offset = 0;
   4338             BCM_IF_ERROR_RETURN(bcm_esw_qos_map_add(unit,
   4339                                                     BCM_QOS_MAP_OAM_INTPRI,
   4340                                                     &map, map_id)); 
   4341         }
   4342         /* Assign it to default priority map profile id */
   4343         oc->default_pri_map_id = map_id;
   4344     }
   4345 
   4346     /* OAM Opcode Control profile table initialization. */
   4347     soc_profile_mem_t_init(&oc->oam_opcode_control_profile);
   4348 
   4349     entry_words = sizeof(oam_opcode_control_profile_entry_t)
   4350                          / sizeof(uint32);
   4351 
   4352     mem = OAM_OPCODE_CONTROL_PROFILEm;
   4353     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4354                                 &oc->oam_opcode_control_profile);
   4355     if (BCM_FAILURE(rv)) {
   4356         LOG_ERROR(BSL_LS_BCM_OAM,
   4357                   (BSL_META_U(unit,
   4358                               "OAM(unit %d) Error: opcode control profile - Failed.\n"),
   4359                    unit));
   4360         return (rv);
   4361     }
   4362     if (!SOC_WARM_BOOT(unit)) {
   4363         /* Create default opcode control profile */
   4364         opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, "opcode profile");
   4365         sal_memset(opcode_entry, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE);
   4366         rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, mem, opcode_entry);
   4367         if (BCM_FAILURE(rv)) {
   4368             LOG_ERROR(BSL_LS_BCM_OAM,
   4369                       (BSL_META_U(unit,
   4370                                   "OAM(unit %d) Error: Opcode profile init failed "
   4371                                    "  %s.\n"), unit, bcm_errmsg(rv)));
   4372             if(opcode_entry) {
   4373                 sal_free(opcode_entry);
   4374             }
   4375             return (rv);
   4376         }
   4377         /* Add entry to profile table.  */
   4378         entries[0] = opcode_entry;
   4379         rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile,
   4380                              (void *)entries, 
   4381                 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index);
   4382         if (BCM_FAILURE(rv)) {
   4383             LOG_ERROR(BSL_LS_BCM_OAM,
   4384                       (BSL_META_U(unit,
   4385                                   "OAM(unit %d) Opcode profile table is full - %s.\n"),
   4386                        unit, bcm_errmsg(rv)));
   4387             if(opcode_entry) {
   4388                 sal_free(opcode_entry);
   4389             }
   4390             return rv;
   4391         }
   4392         if(opcode_entry) {
   4393             sal_free(opcode_entry);
   4394         }
   4395     }
   4396 
   4397     /* Egress OAM Opcode Control profile table initialization. */
   4398     soc_profile_mem_t_init(&oc->egr_oam_opcode_control_profile);
   4399     entry_words = sizeof(egr_oam_opcode_control_profile_entry_t)
   4400                          / sizeof(uint32);
   4401     mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
   4402     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4403                                 &oc->egr_oam_opcode_control_profile);
   4404     if (BCM_FAILURE(rv)) {
   4405         LOG_ERROR(BSL_LS_BCM_OAM,
   4406                   (BSL_META_U(unit,
   4407                               "OAM(unit %d) Error: Egress opcode control profile- Failed.\n"),
   4408                    unit));
   4409         return (rv);
   4410     }
   4411     if (!SOC_WARM_BOOT(unit)) {
   4412         egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, "egr opcode profile");
   4413         /* Create default opcode control profile */
   4414         sal_memset(egr_opcode_entry, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE);
   4415         rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, mem, egr_opcode_entry);
   4416         if (BCM_FAILURE(rv)) {
   4417             LOG_ERROR(BSL_LS_BCM_OAM,
   4418                       (BSL_META_U(unit,
   4419                                   "OAM(unit %d) Error: Opcode profile init failed "
   4420                                    "  %s.\n"), unit, bcm_errmsg(rv)));
   4421             if(egr_opcode_entry) {
   4422                 sal_free(egr_opcode_entry);
   4423             }
   4424             return (rv);
   4425         }
   4426         /* Add entry to profile table.  */
   4427         entries[0] = egr_opcode_entry;
   4428         rv = soc_profile_mem_add(unit, &oc->egr_oam_opcode_control_profile,
   4429                              (void *)entries, 
   4430                       _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index);
   4431         if (BCM_FAILURE(rv)) {
   4432             LOG_ERROR(BSL_LS_BCM_OAM,
   4433                       (BSL_META_U(unit,
   4434                                   "OAM(unit %d) Egr Opcode profile table is full - %s.\n"),
   4435                        unit, bcm_errmsg(rv)));
   4436             if(egr_opcode_entry) {
   4437                 sal_free(egr_opcode_entry);
   4438             }
   4439             return rv;
   4440         }
   4441         if(egr_opcode_entry) {
   4442             sal_free(egr_opcode_entry);
   4443         }
   4444     }
   4445 
   4446     /* Ingress OAM dglp profile table initialisation */
   4447     soc_profile_mem_t_init(&oc->ing_oam_dglp_profile);
   4448 
   4449     entry_words = sizeof(ing_oam_dglp_profile_entry_t) / sizeof(uint32);
   4450 
   4451     mem = OAM_DGLP_PROFILEm;
   4452     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4453                                 &oc->ing_oam_dglp_profile);
   4454     if (BCM_FAILURE(rv)) {
   4455         LOG_ERROR(BSL_LS_BCM_OAM,
   4456                   (BSL_META_U(unit,
   4457                               "OAM(unit %d) Error: ING OAM DGLP profile create - Failed.\n"),
   4458                    unit));
   4459         return (rv);
   4460     }
   4461     if (!SOC_WARM_BOOT(unit)) {
   4462         /* Add default profile */
   4463         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   4464         /* put local CPU as default dglp */
   4465         dglp = CMIC_PORT(unit);
   4466         dglp |= ((modid << DGLP_MODULE_ID_SHIFT_BITS)); 
   4467 
   4468         soc_mem_field32_set(unit, OAM_DGLP_PROFILEm, 
   4469                         &ing_dglp_profile_entry, DGLPf, dglp);
   4470         entries[0] = &ing_dglp_profile_entry;
   4471 
   4472         rv = soc_profile_mem_add(unit, &oc->ing_oam_dglp_profile,
   4473                              (void *)entries, 1, &profile_index);
   4474         if (BCM_FAILURE(rv)) {
   4475             LOG_ERROR(BSL_LS_BCM_OAM,
   4476                       (BSL_META_U(unit,
   4477                                   "OAM(unit %d) DGLP profile table is full - %s.\n"),
   4478                        unit, bcm_errmsg(rv)));
   4479             return rv;
   4480         }
   4481     }
   4482     
   4483 
   4484     /* Egress OAM dglp profile table initialisation */
   4485     soc_profile_mem_t_init(&oc->egr_oam_dglp_profile);
   4486 
   4487     entry_words = sizeof(egr_oam_dglp_profile_entry_t) / sizeof(uint32);
   4488 
   4489     mem = EGR_OAM_DGLP_PROFILEm;
   4490     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4491                                 &oc->egr_oam_dglp_profile);
   4492     if (BCM_FAILURE(rv)) {
   4493         LOG_ERROR(BSL_LS_BCM_OAM,
   4494                   (BSL_META_U(unit,
   4495                               "OAM(unit %d) Error: EGR OAM DGLP profile create - Failed.\n"),
   4496                    unit));
   4497         return (rv);
   4498     }
   4499     if (!SOC_WARM_BOOT(unit)) {
   4500         profile_index = 0;
   4501         soc_mem_field32_set(unit, EGR_OAM_DGLP_PROFILEm, 
   4502                         &egr_dglp_profile_entry, DGLPf, dglp);
   4503         entries[0] = &egr_dglp_profile_entry;
   4504 
   4505         rv = soc_profile_mem_add(unit, &oc->egr_oam_dglp_profile,
   4506                              (void *)entries, 1, &profile_index);
   4507         if (BCM_FAILURE(rv)) {
   4508             LOG_ERROR(BSL_LS_BCM_OAM,
   4509                       (BSL_META_U(unit,
   4510                                   "OAM(unit %d) DGLP profile table is full - %s.\n"),
   4511                        unit, bcm_errmsg(rv)));
   4512             return rv;
   4513         }
   4514     }
   4515 
   4516 #if defined(BCM_METROLITE_SUPPORT)
   4517     if (SOC_IS_METROLITE(unit)) {
   4518         /* ING OAM LM count profile table initialization. 
   4519          * soc_profile_mem_add will be done in bcm_esw_oam_opcodes_count_profile_create API.
   4520          * This will return the lm_count_profile index.*/
   4521         soc_profile_mem_t_init(&oc->ing_lm_counter_control_profile);
   4522 
   4523         entry_words = sizeof(ing_lm_counter_control_entry_t)
   4524             / sizeof(uint32);
   4525 
   4526         mem = ING_LM_COUNTER_CONTROLm;
   4527         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4528                 &oc->ing_lm_counter_control_profile);
   4529         if (BCM_FAILURE(rv)) {
   4530             LOG_ERROR(BSL_LS_BCM_OAM,
   4531                     (BSL_META_U(unit,
   4532                                 "OAM(unit %d) Error: ING LM counter control  profile - Failed.\n"),
   4533                      unit));
   4534             return (rv);
   4535         }
   4536 
   4537         /* EGR OAM LM count profile table initialization. 
   4538          * soc_profile_mem_add will be done in bcm_esw_oam_opcodes_count_profile_create API.
   4539          * This will return the lm_count_profile index.*/
   4540         soc_profile_mem_t_init(&oc->egr_lm_counter_control_profile);
   4541 
   4542         entry_words = sizeof(egr_lm_counter_control_entry_t)
   4543             / sizeof(uint32);
   4544 
   4545         mem = EGR_LM_COUNTER_CONTROLm;
   4546         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4547                 &oc->egr_lm_counter_control_profile);
   4548         if (BCM_FAILURE(rv)) {
   4549             LOG_ERROR(BSL_LS_BCM_OAM,
   4550                     (BSL_META_U(unit,
   4551                                 "OAM(unit %d) Error: EGR LM counter control  profile - Failed.\n"),
   4552                      unit));
   4553             return (rv);
   4554         }
   4555     }   
   4556 #endif
   4557     return (rv);
   4558 }
   4559 
   4560 /*
   4561  * Function:
   4562  *     _bcm_sb2_oam_control_free
   4563  * Purpose:
   4564  *     Free OAM control structure resources allocated by this unit.
   4565  * Parameters:
   4566  *     unit -  (IN) BCM unit number.
   4567  *     oc   -  (IN) Pointer to OAM control structure.
   4568  * Retruns:
   4569  *     BCM_E_XXX
   4570  */
   4571 STATIC int
   4572 _bcm_sb2_oam_control_free(int unit, _bcm_oam_control_t *oc)
   4573 {
   4574     int status = 0;
   4575     _sb2_oam_control[unit] = NULL;
   4576 
   4577     if (NULL == oc) {
   4578         /* Module already un-initialized. */
   4579         return (BCM_E_NONE);
   4580     }
   4581 
   4582     /* Free protection mutex. */
   4583     if (NULL != oc->oc_lock) {
   4584         sal_mutex_destroy(oc->oc_lock);
   4585     }
   4586 
   4587     /* Free hash data storage memory. */
   4588     if (NULL != oc->oam_hash_data) {
   4589         sal_free(oc->oam_hash_data);
   4590     }
   4591 
   4592     /* Destory endpoint hash table. */
   4593     if (NULL != oc->ma_mep_htbl) {
   4594         status = shr_htb_destroy(&oc->ma_mep_htbl, NULL);
   4595         if (BCM_FAILURE(status)) {
   4596             LOG_ERROR(BSL_LS_BCM_OAM,
   4597                       (BSL_META_U(unit,
   4598                                   "Freeing ma_mep_htbl failed\n")));
   4599         }
   4600     }
   4601 
   4602     /* Destory group indices list. */
   4603     if (NULL != oc->group_pool) {
   4604         shr_idxres_list_destroy(oc->group_pool);
   4605         oc->group_pool = NULL;
   4606     }
   4607 
   4608     /* Destroy endpoint indices list. */
   4609     if (NULL != oc->mep_pool) {
   4610         shr_idxres_list_destroy(oc->mep_pool);
   4611         oc->mep_pool = NULL;
   4612     }
   4613 
   4614     /* Destroy local endpoint indices list. */
   4615     if (NULL != oc->lmep_pool) {
   4616         shr_idxres_list_destroy(oc->lmep_pool);
   4617         oc->lmep_pool = NULL;
   4618     }
   4619 
   4620     /* Destroy remote endpoint indices list. */
   4621     if (NULL != oc->rmep_pool) {
   4622         shr_idxres_list_destroy(oc->rmep_pool);
   4623         oc->rmep_pool = NULL;
   4624     }
   4625 
   4626     /* Destroy ingress and egress group indices list. */
   4627 
   4628     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_pool_destroy(oc));
   4629 
   4630     if (NULL != oc->egr_ma_idx_pool) {
   4631         shr_idxres_list_destroy(oc->egr_ma_idx_pool);
   4632         oc->egr_ma_idx_pool = NULL;
   4633     }
   4634 
   4635     /* Destroy LM counter indices list. */
   4636     if (NULL != oc->ing_lm_ctr_pool[0]) {
   4637         shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[0]);
   4638         oc->ing_lm_ctr_pool[0] = NULL;
   4639     }
   4640     if (NULL != oc->ing_lm_ctr_pool[1]) {
   4641         shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[1]);
   4642         oc->ing_lm_ctr_pool[1] = NULL;
   4643     }
   4644     if (NULL != oc->ing_lm_ctr_pool[2]) {
   4645         shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[2]);
   4646         oc->ing_lm_ctr_pool[2] = NULL;
   4647     }
   4648     if (soc_feature(unit, soc_feature_bhh)) {
   4649 #if defined(INCLUDE_BHH)
   4650         /* Destroy bhh indices list. */
   4651         if (NULL != oc->bhh_pool) {
   4652             shr_idxres_list_destroy(oc->bhh_pool);
   4653             oc->bhh_pool = NULL;
   4654         }
   4655         if (NULL != oc->dma_buffer){
   4656             soc_cm_sfree(oc->unit, oc->dma_buffer);
   4657             oc->dma_buffer = NULL;
   4658         }
   4659         if (NULL != oc->dmabuf_reply){
   4660             soc_cm_sfree(oc->unit, oc->dmabuf_reply);
   4661             oc->dmabuf_reply = NULL;
   4662         }
   4663         if (NULL != oc->bhh_ma_index_in_use){
   4664             soc_cm_sfree(oc->unit, oc->bhh_ma_index_in_use);
   4665             oc->bhh_ma_index_in_use = NULL;
   4666         }
   4667         if (NULL != oc->bhh_ep_grp_id){
   4668             soc_cm_sfree(oc->unit, oc->bhh_ep_grp_id);
   4669             oc->bhh_ep_grp_id = NULL;
   4670         }
   4671         if (NULL != oc->bhh_ep_vpn){
   4672             soc_cm_sfree(oc->unit, oc->bhh_ep_vpn);
   4673             oc->bhh_ep_vpn = NULL;
   4674         }
   4675 #endif
   4676     }
   4677 
   4678     if (soc_feature(unit, soc_feature_eth_lm_dm)) {
   4679 #if defined(INCLUDE_ETH_LM_DM)
   4680         /* Destroy ETH_LM_DM Session pool */
   4681         if (NULL != oc->eth_lm_dm_pool) {
   4682             shr_idxres_list_destroy(oc->eth_lm_dm_pool);
   4683             oc->eth_lm_dm_pool = NULL;
   4684         }
   4685         soc_cm_sfree(oc->unit, oc->eth_lm_dm_dma_buffer);
   4686         soc_cm_sfree(oc->unit, oc->eth_lm_dm_dmabuf_reply);
   4687 #endif
   4688     }
   4689 
   4690 #if defined(INCLUDE_MPLS_LM_DM)
   4691         /* Destroy MPLS_LM_DM Session pool */
   4692         if (NULL != oc->mpls_lm_dm_pool) {
   4693             shr_idxres_list_destroy(oc->mpls_lm_dm_pool);
   4694             oc->mpls_lm_dm_pool = NULL;
   4695         }
   4696         soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dma_buffer);
   4697         soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dmabuf_reply);
   4698 #endif
   4699 
   4700     if (soc_feature(unit, soc_feature_oam_pm)) {
   4701 #if defined (INCLUDE_BHH)
   4702         if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
   4703             soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer);
   4704         }
   4705 #endif
   4706 #if defined (INCLUDE_ETH_LM_DM)
   4707         if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
   4708             soc_cm_sfree(oc->unit, oc->pm_eth_lm_dm_dma_buffer);
   4709         }
   4710         if (NULL != oc->eth_lm_dm_sess_id_ep_id) {
   4711             sal_free(oc->eth_lm_dm_sess_id_ep_id);
   4712             oc->eth_lm_dm_sess_id_ep_id = NULL;
   4713         }
   4714 #endif
   4715 #if defined (INCLUDE_MPLS_LM_DM)
   4716         if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
   4717             soc_cm_sfree(oc->unit, oc->pm_mpls_lm_dm_dma_buffer);
   4718         }
   4719         if (NULL != oc->mpls_lm_dm_sess_id_ep_id) {
   4720             sal_free(oc->mpls_lm_dm_sess_id_ep_id);
   4721             oc->mpls_lm_dm_sess_id_ep_id = NULL;
   4722         }
   4723 #endif
   4724     }
   4725 
   4726     /* Free group memory. */
   4727     if (NULL != oc->group_info) {
   4728         sal_free(oc->group_info);
   4729     }
   4730 
   4731     /* Free RMEP H/w to logical index mapping memory. */
   4732     if (NULL != oc->remote_endpoints) {
   4733         sal_free(oc->remote_endpoints);
   4734     }
   4735 
   4736     /* Destroy Ingress OAM opcode control profile. */
   4737     if (NULL != oc->oam_opcode_control_profile.tables) {
   4738         soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile);
   4739     }
   4740     /* Destroy Egress OAM opcode control profile. */
   4741     if (NULL != oc->egr_oam_opcode_control_profile.tables) {
   4742         soc_profile_mem_destroy(unit, &oc->egr_oam_opcode_control_profile);
   4743     }
   4744     /* Destroy Ingress DGLP profile */
   4745     if (NULL != oc->ing_oam_dglp_profile.tables) {
   4746         soc_profile_mem_destroy(unit, &oc->ing_oam_dglp_profile);
   4747     }
   4748     /* Destroy Egress DGLP profile */
   4749     if (NULL != oc->egr_oam_dglp_profile.tables) {
   4750         soc_profile_mem_destroy(unit, &oc->egr_oam_dglp_profile);
   4751     }
   4752 #if defined (BCM_METROLITE_SUPPORT)
   4753     if(SOC_IS_METROLITE(unit)) {
   4754         /* Destroy Ingress OAM LM counter control profile. */
   4755         if (NULL != oc->ing_lm_counter_control_profile.tables) {
   4756             soc_profile_mem_destroy(unit, &oc->ing_lm_counter_control_profile);
   4757         }
   4758         /* Destroy Egress OAM LM counter control profile. */
   4759         if (NULL != oc->egr_lm_counter_control_profile.tables) {
   4760             soc_profile_mem_destroy(unit, &oc->egr_lm_counter_control_profile);
   4761         }
   4762     }
   4763 #endif
   4764 
   4765 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
   4766     if (soc_feature(unit, soc_feature_oam_pm)) {
   4767         if (pm_profile_control[unit]) {
   4768             sal_free(pm_profile_control[unit]);
   4769             pm_profile_control[unit] = NULL;
   4770         }
   4771     }
   4772 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM || INCLUDE_ETH_LM_DM*/
   4773     
   4774     /* Free OAM control structure memory. */
   4775     sal_free(oc);
   4776     oc = NULL;
   4777 
   4778     return (BCM_E_NONE);
   4779 }
   4780 
   4781 /*
   4782  * Function:
   4783  *     _bcm_sb2_oam_handle_interrupt
   4784  * Purpose:
   4785  *     Process OAM interrupts generated by endpoints.
   4786  * Parameters:
   4787  *     unit  -  (IN) BCM unit number.
   4788  *     field -  (IN) fault field.
   4789  * Retruns:
   4790  *     BCM_E_XXX
   4791  */
   4792 STATIC int
   4793 _bcm_sb2_oam_handle_interrupt(int unit, soc_field_t field)
   4794 {
   4795     _bcm_oam_interrupt_t *intr;             /* OAM interrupt.                */
   4796     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
   4797     uint32               intr_rval;         /* Interrupt register value.     */
   4798     uint32               intr_cur_status;   /* Interrupt status.             */
   4799     uint32               flags;             /* Interrupt flags.              */
   4800     bcm_oam_group_t      grp_index;         /* MA group index.               */
   4801     bcm_oam_endpoint_t   remote_ep_index;   /* Remote Endpoint index.        */
   4802     int                  intr_multi;        /* Event occured multiple times. */
   4803     int                  intr_count;        /* No. of times event detected.  */
   4804     int                  rv;                /* Operation return status       */
   4805     _bcm_oam_event_handler_t *e_handler;    /* Pointer to Event handler.     */
   4806 
   4807 
   4808     /* Get OAM control structure. */
   4809     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   4810 
   4811     _BCM_OAM_LOCK(oc);
   4812 
   4813     /* Loop through the supported interrupts for this device. */
   4814     for (intr = _sb2_oam_interrupts; intr->status_register != INVALIDr;
   4815          intr++) {
   4816 
   4817         rv = soc_reg32_get(unit, intr->status_register,
   4818                            REG_PORT_ANY, 0, &intr_rval);
   4819         if (BCM_FAILURE(rv)) {
   4820             
   4821             continue;
   4822         }
   4823 
   4824         rv = soc_reg32_set(unit, intr->status_register,
   4825                            REG_PORT_ANY, 0, 0);
   4826         if (BCM_FAILURE(rv)) {
   4827             continue;
   4828         }
   4829 
   4830         /* Get status of interrupt from hardware. */
   4831         intr_cur_status = soc_reg_field_get(unit, intr->status_register,
   4832                                             intr_rval, VALIDf);
   4833         if (0 == intr_cur_status) {
   4834             /* This interrupt event is not valid, so continue. */
   4835             continue;
   4836         }
   4837 
   4838         /* Get this interrupt event counter value. */
   4839         intr_count = oc->event_handler_cnt[intr->event_type];
   4840 
   4841         /* Check if the interrupt is set. */
   4842         if ((1 == intr_cur_status) && (intr_count > 0)) {
   4843             flags = 0;
   4844 
   4845             /* Get MA group index for this interrupt. */
   4846             if (INVALIDf != intr->group_index_field ) {
   4847                 grp_index = soc_reg_field_get(unit, intr->status_register,
   4848                                               intr_rval,
   4849                                               intr->group_index_field);
   4850             } else {
   4851                 /* Group not valid for this interrupt. */
   4852                 grp_index = BCM_OAM_GROUP_INVALID;
   4853             }
   4854 
   4855             /* Get H/w index of RMEP for this interrupt. */
   4856             if (INVALIDf != intr->endpoint_index_field ) {
   4857                 remote_ep_index = soc_reg_field_get(unit, intr->status_register,
   4858                                               intr_rval,
   4859                                               intr->endpoint_index_field);
   4860 
   4861                 /* Get Logical index from H/w index for this RMEP. */
   4862                 remote_ep_index = oc->remote_endpoints[remote_ep_index];
   4863             } else {
   4864                 /* Endpoint not valid for this interrupt. */
   4865                 remote_ep_index = BCM_OAM_ENDPOINT_INVALID;
   4866             }
   4867 
   4868             /* Get interrupt MULTIf status. */
   4869             intr_multi = soc_reg_field_get(unit, intr->status_register,
   4870                                            intr_rval, MULTIf);
   4871             if (1 == intr_multi) {
   4872                 /*
   4873                  * Interrupt event asserted more than once.
   4874                  * Set flags status bit to indicate event multiple occurance.
   4875                  */
   4876                 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE;
   4877             }
   4878 
   4879             /* Check and call all the handlers registerd for this event. */
   4880             for (e_handler = oc->event_handler_list_p; e_handler != NULL;
   4881                  e_handler = e_handler->next_p) {
   4882 
   4883                 /* Check if an event handler is register for this event type. */
   4884                 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) {
   4885 
   4886                     /* Call the event handler with the call back parameters. */
   4887                     e_handler->cb(unit, flags, intr->event_type, grp_index,
   4888                                       remote_ep_index, e_handler->user_data);
   4889                 }
   4890             }
   4891         }
   4892     }
   4893 
   4894     _BCM_OAM_UNLOCK(oc);
   4895 
   4896     return (BCM_E_NONE);
   4897 }
   4898 
   4899 /*
   4900  * Function:
   4901  *     _bcm_sb2_oam_events_unregister
   4902  * Purpose:
   4903  *     Unregister all OAM events for this unit.
   4904  * Parameters:
   4905  *     unit -  (IN) BCM unit number.
   4906  *     oc   -  (IN) Pointer to OAM control structure.
   4907  * Retruns:
   4908  *     BCM_E_NONE
   4909  */
   4910 STATIC int
   4911 _bcm_sb2_oam_events_unregister(int unit, _bcm_oam_control_t *oc)
   4912 {
   4913     _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */
   4914     _bcm_oam_event_handler_t *e_delete;  /* Event handler to be freed.     */
   4915 
   4916     /* Control lock taken by the calling routine. */
   4917 
   4918     e_handler = oc->event_handler_list_p;
   4919 
   4920     while (e_handler != NULL) {
   4921         e_delete = e_handler;
   4922         e_handler = e_handler->next_p;
   4923         sal_free(e_delete);
   4924     }
   4925 
   4926     oc->event_handler_list_p = NULL;
   4927 
   4928     return (BCM_E_NONE);
   4929 }
   4930 
   4931 
   4932 /*
   4933  * Function:
   4934  *     _bcm_sb2_oam_clear_rmep
   4935  * Purpose:
   4936  *     Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 
   4937  *     the faults.
   4938  *      
   4939  * Parameters:
   4940  *     unit       - (IN) BCM device number
   4941  *     h_data_p   - (IN) Pointer to Endpoint info associated with RMEP entry 
   4942  *                       being cleared. 
   4943  *     valid      - (IN) 0 => Delete the H/w entry
   4944  *                       1 => Install fresh entry with faults cleared.
   4945  * Returns:
   4946  *     BCM_E_XXX
   4947  */
   4948 STATIC int
   4949 _bcm_sb2_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid)
   4950 {
   4951 
   4952     rmep_entry_t       rmep_entry;          /* RMEP table entry.              */
   4953     int                rv = BCM_E_INTERNAL; /* Operation return status entry  */
   4954     uint32             oam_cur_time;    /* Current time in H/w state machine  */
   4955 
   4956     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4957                 (BSL_META_U(unit,
   4958                             "OAM(unit %d): %s, EP id %d, valid %d\n"), 
   4959                  unit, FUNCTION_NAME(), h_data_p->remote_index, valid));
   4960     
   4961     if (h_data_p == NULL) {
   4962         LOG_ERROR(BSL_LS_BCM_OAM,
   4963                   (BSL_META_U(unit,
   4964                               "OAM(unit %d), ERR: %s Arg h_data_p NULL check failed\n"),
   4965                    unit, FUNCTION_NAME()));
   4966         return BCM_E_INTERNAL;
   4967     }
   4968 
   4969     /* RMEP table programming. */
   4970     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   4971 
   4972     /* if valid==0 delete RMEP entry, else create a clean RMEP entry */
   4973     if (!(valid)) {
   4974         rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   4975                          &rmep_entry);
   4976         if (rv != BCM_E_NONE) {
   4977             LOG_ERROR(BSL_LS_BCM_OAM,
   4978                       (BSL_META_U(unit,
   4979                                   "OAM(unit %d), ERR: %s Deleting RMEP entry failied\n"),
   4980                        unit, FUNCTION_NAME()));
   4981         }
   4982         return (rv);
   4983     }
   4984 
   4985     /* Set the MA group index. */
   4986     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 
   4987                           h_data_p->group_index);
   4988 
   4989     /*
   4990      * The following steps are necessary to enable CCM timeout events
   4991      * without having received any CCMs.
   4992      */
   4993     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1);
   4994 
   4995     BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   4996 
   4997     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time);
   4998 
   4999     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf,
   5000                          _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   5001     /* End of timeout setup */
   5002 
   5003 
   5004     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   5005 
   5006     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   5007                      &rmep_entry);
   5008     if (rv != BCM_E_NONE) {
   5009         LOG_ERROR(BSL_LS_BCM_OAM,
   5010                   (BSL_META_U(unit,
   5011                               "OAM(unit %d), ERR: %s Clearing RMEP entry failied\n"),
   5012                    unit, FUNCTION_NAME()));
   5013         return (rv);
   5014     }
   5015 
   5016     return BCM_E_NONE;
   5017 }
   5018 
   5019 
   5020 /*
   5021  * Function:
   5022  *     _bcm_sb2_oam_clear_ma_state
   5023  * Purpose:
   5024  *     Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 
   5025  *     Clearing the faults.
   5026  * Parameters:
   5027  *     unit       - (IN) BCM device number
   5028  *     group_info - (IN) Group info associated with MA_STATE entry being 
   5029  *                       cleared.
   5030  *     index      - (IN) H/w index of MA_STATE entry to be modified. 
   5031  *     valid      - (IN) 0 => Delete the H/w entry
   5032  *                       1 => Install fresh entry with faults cleared.
   5033  * Returns:
   5034  *     BCM_E_XXX
   5035  */
   5036 STATIC int
   5037 _bcm_sb2_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 
   5038                             int index, int valid)
   5039 {
   5040 
   5041     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
   5042     
   5043     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5044                 (BSL_META_U(unit,
   5045                             "OAM(unit %d): %s, *group_info %p, index %d, valid %d\n"), 
   5046                  unit, FUNCTION_NAME(), group_info, index, valid));
   5047                
   5048     if (group_info == NULL) {
   5049         LOG_ERROR(BSL_LS_BCM_OAM,
   5050                   (BSL_META_U(unit,
   5051                               "OAM(unit %d), ERR: %s Arg group_info NULL check failed\n"),
   5052                    unit, FUNCTION_NAME()));
   5053         return BCM_E_INTERNAL;
   5054     }
   5055 
   5056     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   5057     
   5058     /* Mark the entry as valid. */
   5059     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid);
   5060 
   5061     /* Set the lowest alarm priority info. */
   5062     if (valid) {
   5063         soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
   5064                                   group_info->lowest_alarm_priority);
   5065     }
   5066 
   5067     /* Write group information to hardware table. */
   5068     SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index,
   5069                                         &ma_state_entry));
   5070     return BCM_E_NONE;
   5071 }
   5072 
   5073 
   5074 /*
   5075  * Function:
   5076  *     _bcm_sb2_oam_group_recreate
   5077  * Purpose:
   5078  *     Recreate MA_STATE and RMEP entries, due to current H/w limitation
   5079  *     Currently there is a race condition between H/w and Software
   5080  *     When RMEP is deleted and if it has any faults then, 
   5081  *     MA_STATE remote fault counters need to be decremented by software.
   5082  *     However it may so happen that after reading RMEP faults and just
   5083  *     before RMEP deletion, the fault gets cleared and H/w already decremented
   5084  *     the MA_STATE table, now when software decrements the MA_STATE it would
   5085  *     get MA_STATE table into an inconsistent state.
   5086  *     As a solution we always recreate the entire group on a RMEP deletion.
   5087  * Parameters:
   5088  *     unit     - (IN) BCM device number
   5089  *     group_id - (IN) Group Index, 
   5090  *                as per current implementation this is same as MA_STATE index.
   5091  * Returns:
   5092  *     BCM_E_XXX
   5093  * Expects:
   5094  *      OAM LOCK
   5095  */
   5096 STATIC int
   5097 _bcm_sb2_oam_group_recreate(int unit, int index)
   5098 {
   5099     _bcm_oam_control_t      *oc;                /* OAM control structure.     */
   5100     _bcm_oam_group_data_t   *group_info;        /* OAM group info             */
   5101     _bcm_oam_ep_list_t      *cur_ep_ptr = NULL; /* Pointer to group's EP list */
   5102                                                 /* entry.                     */
   5103     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   5104 
   5105     /* Get OAM control structure handle. */
   5106     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   5107 
   5108     /* Get the handle to group info */
   5109     group_info = &(oc->group_info[index]);
   5110     
   5111     /*if unused Group, just clear the MA_STATE index, including the valid bit*/
   5112     if (!(group_info->in_use)) {
   5113         LOG_WARN(BSL_LS_BCM_OAM,
   5114                  (BSL_META_U(unit,
   5115                              "OAM(unit %d), WARN: Recieved group recreate request for " 
   5116                               "unused Group Id %d\n"), unit, index));
   5117     
   5118         rv = _bcm_sb2_oam_clear_ma_state(unit, group_info, index, 0);
   5119         if (BCM_FAILURE(rv)) {
   5120             LOG_ERROR(BSL_LS_BCM_OAM,
   5121                       (BSL_META_U(unit,
   5122                                   "OAM(unit %d) Error: MA_STATE clear failed group id %d - "
   5123                                    "%s.\n"), unit, index, bcm_errmsg(rv)));
   5124             return rv;
   5125         }
   5126 
   5127     }
   5128     
   5129     /* 1. Traverse and delete the RMEPs in the group */
   5130     if (group_info->ep_list != NULL) {
   5131         cur_ep_ptr = *(group_info->ep_list);
   5132     }
   5133     while (cur_ep_ptr) {
   5134         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   5135             rv = _bcm_sb2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0);
   5136             if (BCM_FAILURE(rv)) {
   5137                 LOG_ERROR(BSL_LS_BCM_OAM,
   5138                           (BSL_META_U(unit,
   5139                                       "OAM(unit %d) Error: RMEP delete failed Ep id %d - "
   5140                                        "%s.\n"), unit, cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   5141                 return rv;
   5142             }
   5143         }
   5144         cur_ep_ptr = cur_ep_ptr->next;
   5145     }
   5146 
   5147     /* 2. Clear the MA_STATE table faults */
   5148     rv = _bcm_sb2_oam_clear_ma_state(unit, group_info, index, 1);
   5149     if (BCM_FAILURE(rv)) {
   5150         LOG_ERROR(BSL_LS_BCM_OAM,
   5151                   (BSL_META_U(unit,
   5152                               "OAM(unit %d) Error: MA_STATE clear failed group id %d - "
   5153                                "%s.\n"), unit, index, bcm_errmsg(rv)));
   5154         return rv;
   5155     }
   5156 
   5157     /* 3. Recreate the RMEP table entries. Clearing the faults. */
   5158     if (group_info->ep_list != NULL) {
   5159         cur_ep_ptr = *(group_info->ep_list);
   5160     }
   5161     while (cur_ep_ptr) {
   5162         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   5163             rv = _bcm_sb2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1);
   5164             if (BCM_FAILURE(rv)) {
   5165                 LOG_ERROR(BSL_LS_BCM_OAM,
   5166                           (BSL_META_U(unit,
   5167                                       "OAM(unit %d) Error: RMEP clear failed EP id %d - "
   5168                                        "%s.\n"), unit, cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   5169                 return rv;
   5170             }
   5171         }
   5172         cur_ep_ptr = cur_ep_ptr->next;
   5173     }
   5174     
   5175     return rv;
   5176 }
   5177 
   5178 
   5179 /*
   5180  * Function:
   5181  *     _bcm_sb2_oam_ser_handler
   5182  * Purpose:
   5183  *     Soft Error Correction routine for MA_STATE and RMEP tables.
   5184  * Parameters:
   5185  *     unit       - (IN) BCM device number
   5186  *     mem        - (IN) Memory MA_STATE or RMEP.
   5187  *     index      - (IN) Memory Index.
   5188  * Returns:
   5189  *     BCM_E_XXX
   5190  */
   5191 STATIC int
   5192 _bcm_sb2_oam_ser_handler(int unit, soc_mem_t mem, int index)
   5193 {
   5194     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   5195     _bcm_oam_control_t      *oc = NULL;         /* OAM control structure.     */
   5196     bcm_oam_endpoint_t      remote_ep_index;    /* Remote Endpoint index.     */
   5197     _bcm_oam_hash_data_t    *ep_data = NULL;    /* Remote Endpoint hash data  */
   5198 
   5199     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5200                 (BSL_META_U(unit,
   5201                             "OAM(unit %d) SER on mem %s, index %d\n"), 
   5202                  unit, SOC_MEM_NAME(unit, mem), index));
   5203               
   5204     /* Get OAM control structure handle. */
   5205     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   5206 
   5207     switch(mem){
   5208         case MA_STATEm:
   5209             _BCM_OAM_GROUP_INDEX_VALIDATE(index);
   5210             _BCM_OAM_LOCK(oc);
   5211             rv = _bcm_sb2_oam_group_recreate(unit, index);
   5212             _BCM_OAM_UNLOCK(oc);
   5213             break;
   5214             
   5215         case RMEPm:
   5216             _BCM_OAM_RMEP_INDEX_VALIDATE(index);
   5217             _BCM_OAM_LOCK(oc);
   5218             /* Get the logical index from H/w RMEP index */
   5219             remote_ep_index = oc->remote_endpoints[index];
   5220             if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) {
   5221                 /* If endpoint not in use, just clear the RMEP entry in memory */
   5222                 rmep_entry_t rmep_entry;
   5223                 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   5224 
   5225                 LOG_WARN(BSL_LS_BCM_OAM,
   5226                         (BSL_META_U(unit,
   5227                                     "OAM(unit %d), WARN: Recieved Parity Error on"
   5228                                     "index %d invalid Remote Id\n"), unit, index));
   5229                 /* Just clear this entry including valid bit */
   5230                 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index,
   5231                                                        &rmep_entry);
   5232 
   5233             } else {
   5234                 /* Get handle to Hash data */
   5235                 ep_data = &(oc->oam_hash_data[remote_ep_index]);
   5236 
   5237                 if (!(ep_data->in_use)) {
   5238                     /* If endpoint not in use, just clear the RMEP entry in memory */
   5239                     LOG_WARN(BSL_LS_BCM_OAM,
   5240                             (BSL_META_U(unit,
   5241                                         "OAM(unit %d), WARN: Recieved Parity Error on"
   5242                                         "unused Remote Id %d\n"), unit, remote_ep_index));
   5243                     /* Just clear this entry including valid bit */
   5244                     rv = _bcm_sb2_oam_clear_rmep(unit, ep_data, 0);
   5245                 } else {
   5246                     /* Get the group Id from EP data, call group recreate routine */
   5247                     rv = _bcm_sb2_oam_group_recreate(unit, ep_data->group_index);
   5248                 }
   5249             }
   5250             _BCM_OAM_UNLOCK(oc);
   5251             break;
   5252 
   5253         default:
   5254             LOG_ERROR(BSL_LS_BCM_OAM,
   5255                       (BSL_META_U(unit,
   5256                                   "OAM(unit %d), ERR: Invalid mem in OAM SER correction "
   5257                                    "routine %s\n"), unit, SOC_MEM_NAME(unit, mem)));
   5258             return BCM_E_INTERNAL;
   5259     }
   5260 
   5261     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5262                 (BSL_META_U(unit,
   5263                             "OAM(unit %d) SER completed on mem %s, index %d, rv %d\n"), 
   5264                  unit, SOC_MEM_NAME(unit, mem), index, rv));
   5265     
   5266     return rv;
   5267     
   5268 }
   5269 
   5270 /*
   5271  * Function:
   5272  *     _bcm_sb2_oam_group_name_mangle
   5273  * Purpose:
   5274  *     Build tbe group name for hardware table write.
   5275  * Parameters:
   5276  *     name_p         -  (IN) OAM group name.
   5277  *     mangled_name_p -  (IN/OUT) Buffer to write the group name in hardware
   5278  *                       format.
   5279  * Retruns:
   5280  *     None
   5281  */
   5282 STATIC void
   5283 _bcm_sb2_oam_group_name_mangle(uint8 *name_p,
   5284                                uint8 *mangled_name_p)
   5285 {
   5286     uint8  *byte_p;    /* Pointer to group name buffer.       */
   5287     int    bytes_left; /* Number of bytes left in group name. */
   5288 
   5289     bytes_left = BCM_OAM_GROUP_NAME_LENGTH;
   5290     byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1);
   5291 
   5292     while (bytes_left > 0) {
   5293         *mangled_name_p = *byte_p;
   5294         ++mangled_name_p;
   5295         --byte_p;
   5296         --bytes_left;
   5297     }
   5298 }
   5299 
   5300 /*
   5301  * Function:
   5302  *      _bcm_sb2_oam_read_clear_faults
   5303  * Purpose:
   5304  *     Clear OAM group and endpoint faults on hardware table read operation.
   5305  * Parameters:
   5306  *     unit     - (IN) BCM device number
   5307  *     index    - (IN) Group/Endpoint hardware table index
   5308  *     mem      - (IN) Memory/table value
   5309  *     entry    - (IN) Pointer to group/endpoint entry
   5310  *     ma_mep   - (IN) Pointer to group/endpoint info structure
   5311  * Returns:
   5312  *     BCM_E_NONE      - No errors.
   5313  *     BCM_E_XXX       - Otherwise.
   5314  */
   5315 STATIC int
   5316 _bcm_sb2_oam_read_clear_faults(int unit, int index, soc_mem_t mem,
   5317                                uint32 *entry, void *ma_rmep)
   5318 {
   5319     bcm_oam_group_info_t    *group_info_p;  /* Pointer to group info         */
   5320                                             /* structure.                    */
   5321     bcm_oam_endpoint_info_t *ep_info_p;     /* Pointer to endpoint info      */
   5322                                             /* structure.                    */
   5323     _bcm_oam_fault_t        *faults_list;   /* Pointer to faults list.       */
   5324     uint32                  *faults;        /* Faults flag bits.             */
   5325     uint32                  *p_faults;      /* Persistent faults bits.       */
   5326     uint32                  clear_p_faults; /* Clear persistent faults bits. */
   5327     uint32                  rval = 0;       /* Hardware register value.      */
   5328     uint32                  clear_mask = 0; /* Mask to clear persistent faults*/
   5329 
   5330     LOG_DEBUG(BSL_LS_BCM_OAM,
   5331               (BSL_META_U(unit,
   5332                           "OAM(unit %d) Info: _bcm_sb2_oam_read_clear_faults index=%d "
   5333                            "Table=%d.\n"), unit, index, mem));
   5334 
   5335     /* Switch on memory name. */
   5336     switch (mem) {
   5337         /* OAM group state table. */
   5338         case MA_STATEm:
   5339             /* Set the pointer to the start of the group faults array. */
   5340             faults_list = _sb2_oam_group_faults;
   5341 
   5342             /* Typecast to group information structure pointer. */
   5343             group_info_p = (bcm_oam_group_info_t *) ma_rmep;
   5344 
   5345             /* Get group faults information. */
   5346             faults = &group_info_p->faults;
   5347             p_faults = &group_info_p->persistent_faults;
   5348             clear_p_faults = group_info_p->clear_persistent_faults;
   5349             break;
   5350 
   5351         /* OAM remote endpoint table. */
   5352         case RMEPm:
   5353             faults_list = _sb2_oam_endpoint_faults;
   5354             ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep;
   5355             faults = &ep_info_p->faults;
   5356             p_faults = &ep_info_p->persistent_faults;
   5357             clear_p_faults = ep_info_p->clear_persistent_faults;
   5358             break;
   5359 
   5360         default:
   5361             return (BCM_E_NONE);
   5362     }
   5363 
   5364     /* Loop on list of valid faults. */
   5365     for (;faults_list->mask != 0; ++faults_list) {
   5366 
   5367         /* Get  faults status. */
   5368         if (0 != soc_mem_field32_get(unit, mem, entry,
   5369                                      faults_list->current_field)) {
   5370             *faults |= faults_list->mask;
   5371         }
   5372 
   5373         /* Get sticky faults status. */
   5374         if (0 != soc_mem_field32_get(unit, mem, entry,
   5375                                      faults_list->sticky_field)) {
   5376 
   5377             *p_faults |= faults_list->mask;
   5378 
   5379             /*
   5380              * If user has request to clear persistent faults,
   5381              * then set BITS_TO_CLEARf field in the register buffer.
   5382              */
   5383             if (clear_p_faults) {
   5384                 clear_mask |= faults_list->clear_sticky_mask;
   5385             }
   5386         }
   5387     }
   5388 
   5389     /* Check if faults need to be cleared. */
   5390     if (clear_mask && clear_p_faults) {
   5391 
   5392         LOG_VERBOSE(BSL_LS_BCM_OAM,
   5393                     (BSL_META_U(unit,
   5394                                 "OAM(unit %d): clear_mask %d.\n"),
   5395                      unit, clear_mask));
   5396 
   5397         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf,
   5398                           clear_mask);
   5399 
   5400         /* Enable clearing of faults. */
   5401         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1);
   5402 
   5403         
   5404         if (MA_STATEm == mem) {
   5405             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0);
   5406         } else {
   5407             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1);
   5408         }
   5409 
   5410         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index);
   5411 
   5412         /* Update read control register. */
   5413         BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval));
   5414     }
   5415 
   5416     return (BCM_E_NONE);
   5417 }
   5418 
   5419 #if defined(INCLUDE_BHH)
   5420 /*
   5421  * Function:
   5422  *      _bcm_sb2_oam_get_group_sw_rdi
   5423  * Purpose:
   5424  *     Get OAM group SW RDI information.
   5425  * Parameters:
   5426  *     unit         - (IN) BCM device number
   5427  *     group_index  - (IN) Group hardware table index
   5428  *     group_sw_rdi - (OUT) Pointer to group SW RDI
   5429  * Returns:
   5430  *     BCM_E_NONE      - No errors.
   5431  *     BCM_E_XXX       - Otherwise.
   5432  */
   5433 STATIC int
   5434 _bcm_sb2_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index,
   5435                        uint8 *group_sw_rdi)
   5436 {
   5437     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   5438 
   5439     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   5440                                              group_index,
   5441                                              &maid_reduction_entry));
   5442 
   5443     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   5444                                              SW_RDIf)) {
   5445         *group_sw_rdi = 1;
   5446     }
   5447     return (BCM_E_NONE);
   5448 }
   5449 #endif
   5450 
   5451 /*
   5452  * Function:
   5453  *      _bcm_sb2_oam_get_group
   5454  * Purpose:
   5455  *     Get OAM group information.
   5456  * Parameters:
   5457  *     unit         - (IN) BCM device number
   5458  *     group_index  - (IN) Group hardware table index
   5459  *     group        - (IN) Pointer to group array list
   5460  *     group_info   - (IN/OUT) Pointer to group info structure
   5461  * Returns:
   5462  *     BCM_E_NONE      - No errors.
   5463  *     BCM_E_XXX       - Otherwise.
   5464  */
   5465 STATIC int
   5466 _bcm_sb2_oam_get_group(int unit, bcm_oam_group_t group_index,
   5467                        _bcm_oam_group_data_t *group_p,
   5468                        bcm_oam_group_info_t *group_info)
   5469 {
   5470     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   5471     ma_state_entry_t        ma_state_entry;       /* MA_STATE table entry.    */
   5472     int                     rv;                   /* Operation return status. */
   5473 
   5474     group_info->id = group_index;
   5475 
   5476     sal_memcpy(group_info->name, group_p[group_index].name,
   5477                BCM_OAM_GROUP_NAME_LENGTH);
   5478 
   5479     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   5480                                              group_index,
   5481                                              &maid_reduction_entry));
   5482 
   5483     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   5484                                              SW_RDIf)) {
   5485         group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
   5486     }
   5487 
   5488     BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY,
   5489                                        group_index,
   5490                                        &ma_state_entry));
   5491 
   5492     group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get
   5493                                             (unit, &ma_state_entry,
   5494                                              LOWESTALARMPRIf);
   5495 
   5496     rv = _bcm_sb2_oam_read_clear_faults(unit, group_index,
   5497                                         MA_STATEm,
   5498                                         (uint32 *) &ma_state_entry,
   5499                                         group_info);
   5500     if (BCM_FAILURE(rv)) {
   5501         LOG_ERROR(BSL_LS_BCM_OAM,
   5502                   (BSL_META_U(unit,
   5503                               "OAM(unit %d) Error: Clean Faults Group ID=%d- Failed.\n"),
   5504                    unit, group_index));
   5505         return (rv);
   5506     }
   5507     return (BCM_E_NONE);
   5508 }
   5509 
   5510 
   5511 /*
   5512  * Function:
   5513  *     _bcm_sb2_oam_endpoint_egress_interface_add
   5514  * Purpose:
   5515  *     Add an egress interface to an 
   5516  *     endpoint info egress interface linked list.
   5517  * Parameters:
   5518  *     unit          - (IN) BCM device number
   5519  *     h_data_p      - (IN) Endpoint hash data
   5520  *     egress_if     - (IN) Egress interface
   5521  *     gport         - (IN) corresponding gport
   5522  * Returns:
   5523  *     BCM_E_XXX
   5524  */
   5525 STATIC int
   5526 _bcm_sb2_oam_endpoint_egress_interface_add(int unit,
   5527                            _bcm_oam_hash_data_t *h_data_p,
   5528                            bcm_if_t egress_if,
   5529                            bcm_gport_t gport)
   5530 {
   5531     _bcm_oam_endpoint_egress_interface_list_t *egress_if_list_node = NULL;
   5532 
   5533     _BCM_OAM_ALLOC(egress_if_list_node, _bcm_oam_endpoint_egress_interface_list_t, 
   5534             sizeof(_bcm_oam_endpoint_egress_interface_list_t),
   5535             "Egress if lst");
   5536     if (NULL == egress_if_list_node) {
   5537         LOG_ERROR(BSL_LS_BCM_OAM,
   5538                 (BSL_META_U(unit,
   5539                             "OAM(unit %d) Error: Egress if list "
   5540                             "alloc for EP=%d failed"
   5541                             " %s.\n"), unit, h_data_p->ep_id,
   5542                             bcm_errmsg(BCM_E_MEMORY)));
   5543         return (BCM_E_MEMORY);
   5544     }
   5545 
   5546     egress_if_list_node->prev = NULL;
   5547     egress_if_list_node->egress_if = egress_if;
   5548     egress_if_list_node->gport = gport;
   5549     if (NULL == (h_data_p->egress_if_list)) {
   5550         /* Add endpoint as head node. */
   5551         egress_if_list_node->next = NULL;
   5552         h_data_p->egress_if_list = egress_if_list_node;
   5553     } else {
   5554         /* Add the endpoint to the linked list. */
   5555         egress_if_list_node->next = h_data_p->egress_if_list;
   5556         (h_data_p->egress_if_list)->prev = egress_if_list_node;
   5557         h_data_p->egress_if_list = egress_if_list_node;
   5558     }
   5559     LOG_DEBUG(BSL_LS_BCM_OAM,
   5560             (BSL_META_U(unit,
   5561                         "OAM(unit %d) Info: %s" 
   5562                         " (EP_ID=%d) (INTF=0x%x).\n"), unit, __FUNCTION__,
   5563                          h_data_p->ep_id,
   5564                          egress_if));
   5565     return (BCM_E_NONE);
   5566 }
   5567 
   5568 /*
   5569  * Function:
   5570  *     _bcm_sb2_oam_endpoint_egress_interface_delete
   5571  * Purpose:
   5572  *     Delete an egress interface from an 
   5573  *     endpoint info egress interface linked list.
   5574  * Parameters:
   5575  *     unit          - (IN) BCM device number
   5576  *     h_data_p      - (IN) Endpoint hash data
   5577  *     gport         - (IN) corresponding gport
   5578  * Returns:
   5579  *     BCM_E_XXX
   5580  */
   5581 STATIC int
   5582 _bcm_sb2_oam_endpoint_egress_interface_delete(int unit,
   5583                               _bcm_oam_hash_data_t *h_data_p,
   5584                               bcm_gport_t gport)
   5585 {
   5586     _bcm_oam_endpoint_egress_interface_list_t *temp;
   5587     _bcm_oam_endpoint_egress_interface_list_t *cur;/* Current endpoint node pointer.*/
   5588     _bcm_oam_endpoint_egress_interface_list_t *del_node;/* Pointer to a node to be deleted.*/
   5589 
   5590     cur =  h_data_p->egress_if_list;
   5591     if (NULL == cur) {
   5592         /* No endpoints to remove from this group. */
   5593         LOG_DEBUG(BSL_LS_BCM_OAM,
   5594                   (BSL_META_U(unit,
   5595                               "OAM(unit %d) Info: No egress ifs to delete assoc to endpoint"
   5596                                " EP_ID:%d.\n"), unit, h_data_p->ep_id));
   5597         return (BCM_E_NONE);
   5598     }
   5599 
   5600     /* Check if head node needs to be deleated. */
   5601     if (gport == cur->gport) {
   5602         /* Delete head node. */
   5603         del_node = h_data_p->egress_if_list;
   5604         if ((h_data_p->egress_if_list)->next) {
   5605             h_data_p->egress_if_list = (h_data_p->egress_if_list)->next;
   5606             (h_data_p->egress_if_list)->prev = NULL;
   5607         } else {
   5608             h_data_p->egress_if_list = NULL;
   5609         }
   5610         sal_free(del_node);
   5611         LOG_DEBUG(BSL_LS_BCM_OAM,
   5612                   (BSL_META_U(unit,
   5613                               "OAM(unit %d) Info: Head node delete EP_ID=%d - Success\n"),
   5614                    unit, h_data_p->ep_id));
   5615         return (BCM_E_NONE);
   5616     }
   5617 
   5618     /* Traverse the list and delete the matching node. */
   5619     while (NULL != cur->next->next) {
   5620         temp = cur->next;
   5621 
   5622         if (gport == temp->gport) {
   5623             del_node = cur->next;
   5624             cur->next = del_node->next;
   5625             del_node->next->prev = cur;
   5626             sal_free(del_node);
   5627             LOG_DEBUG(BSL_LS_BCM_OAM,
   5628                       (BSL_META_U(unit,
   5629                                   "OAM(unit %d) Info: Node delete EP_ID=%d - Success\n"),
   5630                        unit, h_data_p->ep_id));
   5631             return (BCM_E_NONE);
   5632         }
   5633         cur = cur->next;
   5634     }
   5635 
   5636     /* Check if tail node needs to be deleted. */
   5637     temp = cur->next;
   5638     if (gport == temp->gport) {
   5639         /* Delete tail node. */
   5640         del_node = cur->next;
   5641         cur->next = NULL;
   5642         sal_free(del_node);
   5643         LOG_DEBUG(BSL_LS_BCM_OAM,
   5644                   (BSL_META_U(unit,
   5645                               "OAM(unit %d) Info: Tail node delete EP_ID=%d - Success\n"),
   5646                    unit, h_data_p->ep_id));
   5647         return (BCM_E_NONE);
   5648     }
   5649 
   5650     return (BCM_E_NOT_FOUND);
   5651 }
   5652 
   5653 /*
   5654  * Function:
   5655  *     _bcm_sb2_oam_endpoint_egress_intf_add
   5656  * Purpose:
   5657  *     Add an egress interface to an 
   5658  *     endpoint info egress interface linked list.
   5659  * Parameters:
   5660  *     unit          - (IN) BCM device number
   5661  *     h_data_p      - (IN) Endpoint hash data
   5662  *     egress_if     - (IN) Egress interface
   5663  * Returns:
   5664  *     BCM_E_XXX
   5665  */
   5666 STATIC int
   5667 _bcm_sb2_oam_endpoint_egress_intf_add(int unit,
   5668                            _bcm_oam_hash_data_t *h_data_p,
   5669                            bcm_if_t egress_if)
   5670 {
   5671 
   5672     return _bcm_sb2_oam_endpoint_egress_interface_add(unit,
   5673             h_data_p,
   5674             egress_if,
   5675             BCM_GPORT_INVALID);
   5676 }
   5677 
   5678 /*
   5679  * Function:
   5680  *     _bcm_sb2_oam_endpoint_egress_intf_delete
   5681  * Purpose:
   5682  *     Delete an egress interface from an 
   5683  *     endpoint info egress interface linked list.
   5684  * Parameters:
   5685  *     unit          - (IN) BCM device number
   5686  *     h_data_p      - (IN) Endpoint hash data
   5687  *     egress_intf   - (IN) egress interface identifier
   5688  * Returns:
   5689  *     BCM_E_XXX
   5690  */
   5691 
   5692 STATIC int
   5693 _bcm_sb2_oam_endpoint_egress_intf_delete(int unit,
   5694                               _bcm_oam_hash_data_t *h_data_p,
   5695                               bcm_if_t egress_intf)
   5696 {
   5697     _bcm_oam_endpoint_egress_interface_list_t *temp;
   5698     _bcm_oam_endpoint_egress_interface_list_t *cur;/* Current endpoint node pointer.*/
   5699     _bcm_oam_endpoint_egress_interface_list_t *del_node;/* Pointer to a node to be deleted.*/
   5700 
   5701     cur = h_data_p->egress_if_list;
   5702     if (NULL == cur) {
   5703         /* No endpoints to remove from this group. */
   5704         LOG_DEBUG(BSL_LS_BCM_OAM,
   5705                   (BSL_META_U(unit,
   5706                               "OAM(unit %d) Info: No egress ifs to delete assoc to endpoint"
   5707                                " EP_ID:%d.\n"), unit, h_data_p->ep_id));
   5708         return (BCM_E_NONE);
   5709     }
   5710 
   5711     /* Check if head node needs to be deleted. */
   5712     if (egress_intf == cur->egress_if) {
   5713         /* Delete head node. */
   5714         del_node = h_data_p->egress_if_list;
   5715         if ((h_data_p->egress_if_list)->next) {
   5716             h_data_p->egress_if_list = (h_data_p->egress_if_list)->next;
   5717             (h_data_p->egress_if_list)->prev = NULL;
   5718         } else {
   5719             h_data_p->egress_if_list = NULL;
   5720         }
   5721         sal_free(del_node);
   5722         LOG_DEBUG(BSL_LS_BCM_OAM,
   5723                   (BSL_META_U(unit,
   5724                               "OAM(unit %d) Info: Head node delete EP_ID=%d - Success\n"),
   5725                    unit, h_data_p->ep_id));
   5726         return (BCM_E_NONE);
   5727     }
   5728 
   5729     /* Traverse the list and delete the matching node. */
   5730     while (NULL != cur->next->next) {
   5731         temp = cur->next;
   5732 
   5733         if (egress_intf == temp->egress_if) {
   5734             del_node = cur->next;
   5735             cur->next = del_node->next;
   5736             del_node->next->prev = cur;
   5737             sal_free(del_node);
   5738             LOG_DEBUG(BSL_LS_BCM_OAM,
   5739                       (BSL_META_U(unit,
   5740                                   "OAM(unit %d) Info: Node delete EP_ID=%d - Success\n"),
   5741                        unit, h_data_p->ep_id));
   5742             return (BCM_E_NONE);
   5743         }
   5744         cur = cur->next;
   5745     }
   5746 
   5747     /* Check if tail node needs to be deleted. */
   5748     temp = cur->next;
   5749     if (egress_intf == temp->egress_if) {
   5750         /* Delete tail node. */
   5751         del_node = cur->next;
   5752         cur->next = NULL;
   5753         sal_free(del_node);
   5754         LOG_DEBUG(BSL_LS_BCM_OAM,
   5755                   (BSL_META_U(unit,
   5756                               "OAM(unit %d) Info: Tail node delete EP_ID=%d - Success\n"),
   5757                    unit, h_data_p->ep_id));
   5758         return (BCM_E_NONE);
   5759     }
   5760 
   5761     return (BCM_E_NOT_FOUND);
   5762 }
   5763 
   5764 /*
   5765  * Function:
   5766  *     _bcm_sb2_oam_group_ep_list_add
   5767  * Purpose:
   5768  *     Add an endpoint to a group endpoint linked list.
   5769  * Parameters:
   5770  *     unit     - (IN) BCM device number
   5771  *     group_id - (IN) OAM group ID.
   5772  *     ep_id    - (IN) OAM endpoint ID.
   5773  * Retruns:
   5774  *     BCM_E_XXX
   5775  */
   5776 STATIC int
   5777 _bcm_sb2_oam_group_ep_list_add(int unit,
   5778                            bcm_oam_group_t group_id,
   5779                            bcm_oam_endpoint_t ep_id)
   5780 {
   5781     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   5782     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   5783     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   5784     _bcm_oam_ep_list_t    *ep_list_p = NULL; /* Pointer to endpoint list. */
   5785 
   5786     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   5787 
   5788     group_p = &oc->group_info[group_id];
   5789     /* coverity[dead_error_condition] */
   5790     if (NULL == group_p) {
   5791         LOG_ERROR(BSL_LS_BCM_OAM,
   5792                   (BSL_META_U(unit,
   5793                               "OAM(unit %d) Error: Group data access for GID=%d failed"
   5794         /* coverity[dead_error_begin] */
   5795                                " %s.\n"), unit, group_id, bcm_errmsg(BCM_E_INTERNAL)));
   5796         return (BCM_E_INTERNAL);
   5797     }
   5798 
   5799     h_data_p = &oc->oam_hash_data[ep_id];
   5800     /* coverity[dead_error_condition] */
   5801     if (NULL == h_data_p) {
   5802         LOG_ERROR(BSL_LS_BCM_OAM,
   5803                   (BSL_META_U(unit,
   5804                               "OAM(unit %d) Error: Endpoint data access for EP=%d failed"
   5805         /* coverity[dead_error_begin] */
   5806                                " %s.\n"), unit, ep_id, bcm_errmsg(BCM_E_INTERNAL)));
   5807         return (BCM_E_INTERNAL);
   5808     }
   5809 
   5810     _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t),
   5811                 "EP list");
   5812     if (NULL == ep_list_p) {
   5813         LOG_ERROR(BSL_LS_BCM_OAM,
   5814                   (BSL_META_U(unit,
   5815                               "OAM(unit %d) Error: Endpoint list alloc for EP=%d failed"
   5816                                " %s.\n"), unit, ep_id, bcm_errmsg(BCM_E_MEMORY)));
   5817         return (BCM_E_MEMORY);
   5818     }
   5819 
   5820     ep_list_p->prev = NULL;
   5821     ep_list_p->ep_data_p = h_data_p;
   5822     if (NULL == (*group_p->ep_list)) {
   5823         /* Add endpoint as head node. */
   5824         ep_list_p->next = NULL;
   5825         *group_p->ep_list = ep_list_p;
   5826     } else {
   5827         /* Add the endpoint to the linked list. */
   5828         ep_list_p->next = *group_p->ep_list;
   5829         (*group_p->ep_list)->prev = ep_list_p;
   5830         *group_p->ep_list = ep_list_p;
   5831     }
   5832     LOG_DEBUG(BSL_LS_BCM_OAM,
   5833               (BSL_META_U(unit,
   5834                           "OAM(unit %d) Info: _bcm_sb2_oam_group_ep_list_add" 
   5835                            " (GID=%d) (EP=%d).\n"), unit, group_id, ep_id));
   5836     return (BCM_E_NONE);
   5837 }
   5838 
   5839 /*
   5840  * Function:
   5841  *     _bcm_sb2_oam_group_ep_list_remove
   5842  * Purpose:
   5843  *     Remove an endpoint to a group endpoint linked list.
   5844  * Parameters:
   5845  *     unit     - (IN) BCM device number
   5846  *     group_id - (IN) OAM group ID.
   5847  *     ep_id    - (IN) OAM endpoint ID.
   5848  * Retruns:
   5849  *     BCM_E_XXX
   5850  */
   5851 STATIC int
   5852 _bcm_sb2_oam_group_ep_list_remove(int unit,
   5853                               bcm_oam_group_t group_id,
   5854                               bcm_oam_endpoint_t ep_id)
   5855 {
   5856     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   5857     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   5858     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   5859     _bcm_oam_ep_list_t    *cur;      /* Current endpoint node pointer.    */
   5860     _bcm_oam_ep_list_t    *del_node; /* Pointer to a node to be deleted.  */
   5861 
   5862     /* Control lock already taken by calling routine. */
   5863     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   5864 
   5865     group_p = &oc->group_info[group_id];
   5866     cur =  *group_p->ep_list;
   5867     if (NULL == cur) {
   5868         /* No endpoints to remove from this group. */
   5869         LOG_DEBUG(BSL_LS_BCM_OAM,
   5870                   (BSL_META_U(unit,
   5871                               "OAM(unit %d) Info: No endpoints to delete in group"
   5872                                " GID:%d.\n"), unit, group_id));
   5873         return (BCM_E_NONE);
   5874     }
   5875 
   5876     /* Check if head node needs to be deleated. */
   5877     if (ep_id == cur->ep_data_p->ep_id) {
   5878         /* Delete head node. */
   5879         del_node = *group_p->ep_list;
   5880         if ((*group_p->ep_list)->next) {
   5881             *group_p->ep_list = (*group_p->ep_list)->next;
   5882             (*group_p->ep_list)->prev = NULL;
   5883         } else {
   5884             *group_p->ep_list = NULL;
   5885         }
   5886         sal_free(del_node);
   5887         LOG_DEBUG(BSL_LS_BCM_OAM,
   5888                   (BSL_META_U(unit,
   5889                               "OAM(unit %d) Info: Head node delete GID=%d - Success\n"),
   5890                    unit, group_id));
   5891         return (BCM_E_NONE);
   5892     }
   5893 
   5894     /* Traverse the list and delete the matching node. */
   5895     while (NULL != cur->next->next) {
   5896         h_data_p = cur->next->ep_data_p;
   5897         if (NULL == h_data_p) {
   5898             LOG_ERROR(BSL_LS_BCM_OAM,
   5899                       (BSL_META_U(unit,
   5900                                   "OAM(unit %d) Error: Group=%d endpoints access failed -"
   5901                                    " %s.\n"), unit, group_id, bcm_errmsg(BCM_E_INTERNAL)));
   5902             return (BCM_E_INTERNAL);
   5903         }
   5904 
   5905         if (ep_id == h_data_p->ep_id) {
   5906             del_node = cur->next;
   5907             cur->next = del_node->next;
   5908             del_node->next->prev = cur;
   5909             sal_free(del_node);
   5910             LOG_DEBUG(BSL_LS_BCM_OAM,
   5911                       (BSL_META_U(unit,
   5912                                   "OAM(unit %d) Info: Node delete GID=%d - Success\n"),
   5913                        unit, group_id));
   5914             return (BCM_E_NONE);
   5915         }
   5916         cur = cur->next;
   5917     }
   5918 
   5919     /* Check if tail node needs to be deleted. */
   5920     h_data_p = cur->next->ep_data_p;
   5921     if (ep_id == h_data_p->ep_id) {
   5922         /* Delete tail node. */
   5923         del_node = cur->next;
   5924         cur->next = NULL;
   5925         sal_free(del_node);
   5926         LOG_DEBUG(BSL_LS_BCM_OAM,
   5927                   (BSL_META_U(unit,
   5928                               "OAM(unit %d) Info: Tail node delete GID=%d - Success\n"),
   5929                    unit, group_id));
   5930         return (BCM_E_NONE);
   5931     }
   5932 
   5933     return (BCM_E_NOT_FOUND);
   5934 }
   5935 
   5936 /*
   5937  * Function:
   5938  *     _bcm_oam_sb2_remote_mep_hw_set
   5939  * Purpose:
   5940  *     Configure hardware tables for a remote endpoint.
   5941  * Parameters:
   5942  *     unit      - (IN) BCM device number
   5943  *     ep_info_p - (IN) Pointer to remote endpoint information.
   5944  * Retruns:
   5945  *     BCM_E_XXX
   5946  */
   5947 STATIC int
   5948 _bcm_oam_sb2_remote_mep_hw_set(int unit,
   5949                            const bcm_oam_endpoint_info_t *ep_info_p)
   5950 {
   5951     l3_entry_1_entry_t   l3_entry;          /* Remote view entry.            */
   5952     rmep_entry_t         rmep_entry;        /* Remote MEP entry.             */
   5953     uint32               oam_cur_time;      /* Current time.                 */
   5954     _bcm_oam_hash_data_t *h_data_p = NULL;  /* Hash data pointer.            */
   5955     int                  rv;                /* Operation return status.      */
   5956     _bcm_oam_control_t   *oc;               /* Pointer to control structure. */
   5957     const bcm_oam_endpoint_info_t *ep_p;    /* Pointer to endpoint info.     */
   5958 
   5959     if (NULL == ep_info_p) {
   5960         return (BCM_E_INTERNAL);
   5961     }
   5962 
   5963     /* Initialize local endpoint info pointer. */
   5964     ep_p = ep_info_p;
   5965 
   5966     /* Lock already taken by the calling routine. */
   5967     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   5968 
   5969     /* Get endpoint hash data pointer. */
   5970     h_data_p = &oc->oam_hash_data[ep_p->id];
   5971     if (0 == h_data_p->in_use) {
   5972         return (BCM_E_INTERNAL);
   5973     }
   5974 
   5975     /* RMEP table programming. */
   5976     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   5977 
   5978     /* Set the MA group index. */
   5979     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf,
   5980                           ep_p->group);
   5981 
   5982     /*
   5983      * The following steps are necessary to enable CCM timeout events
   5984      * without having received any CCMs.
   5985      */
   5986     soc_RMEPm_field32_set(unit, &rmep_entry,
   5987                           RMEP_TIMESTAMP_VALIDf, 1);
   5988 
   5989     BCM_IF_ERROR_RETURN
   5990         (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   5991 
   5992     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf,
   5993                           oam_cur_time);
   5994 
   5995     soc_RMEPm_field32_set(unit, &rmep_entry,
   5996                           RMEP_RECEIVED_CCMf,
   5997                          _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   5998     /* End of timeout setup */
   5999 
   6000     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   6001 
   6002     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   6003                      &rmep_entry);
   6004     if (BCM_FAILURE(rv)) {
   6005         LOG_ERROR(BSL_LS_BCM_OAM,
   6006                   (BSL_META_U(unit,
   6007                               "OAM(unit %d) Error: RMEP table write failed EP=%d %s.\n"),
   6008                    unit, ep_info_p->id, bcm_errmsg(rv)));
   6009         return (rv);
   6010     }
   6011 
   6012     /* L3 unicast table programming. */
   6013     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   6014 
   6015     /* Set the CCM interval. */
   6016     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   6017         (unit, &l3_entry, RMEP__CCMf,
   6018         _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   6019 
   6020     /* Set the entry hardware index. */
   6021     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf,
   6022                                 h_data_p->remote_index);
   6023 
   6024     /*
   6025      * Construct endpoint RMEP view key for L3 Table entry
   6026      * insert operation.
   6027      */
   6028     _bcm_sb2_oam_rmep_key_construct(unit, h_data_p, &l3_entry);
   6029 
   6030     /* Mark the entry as valid. */
   6031     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1);
   6032 
   6033     /* Install entry in hardware. */
   6034     rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm,
   6035                         MEM_BLOCK_ALL, &l3_entry);
   6036     if (BCM_FAILURE(rv)) {
   6037         LOG_ERROR(BSL_LS_BCM_OAM,
   6038                   (BSL_META_U(unit,
   6039                               "OAM(unit %d) Error: L3 table insert failed EP=%d %s.\n"),
   6040                    unit, ep_p->id, bcm_errmsg(rv)));
   6041         return (rv);
   6042     }
   6043     /* Add the H/w index to logical index mapping for RMEP */
   6044     oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 
   6045 
   6046     return (BCM_E_NONE);
   6047 }
   6048 /*
   6049  * Function:
   6050  *     _bcm_sb2_oam_find_egr_lmep
   6051  * Purpose:
   6052  *     Search EGR_MP_GROUP table and return the match entry hardware index and
   6053  *     match entry data.
   6054  * Parameters:
   6055  *     unit       - (IN) BCM device number
   6056  *     h_data_p   - (IN) Pointer to endpoint hash data.
   6057  *     entry_idx  - (OUT) Pointer to match entry hardware index.
   6058  *     mp_group_entry_p - (OUT) Pointer to match entry data.
   6059  * Retruns:
   6060  *     BCM_E_XXX
   6061  */
   6062 STATIC int
   6063 _bcm_sb2_oam_find_egr_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p,
   6064                        int *entry_idx,
   6065                        egr_mp_group_entry_t *mp_group_entry_p)
   6066 {
   6067     egr_mp_group_entry_t mp_group_entry; /* MP group table
   6068                                            entry to search.      */
   6069     int                rv;       /* Operation return status. */
   6070 
   6071     if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) {
   6072         return (BCM_E_INTERNAL);
   6073     }
   6074 
   6075     sal_memset(&mp_group_entry, 0, sizeof(egr_mp_group_entry_t));
   6076 
   6077     /* Construct endpoint egress MP group  Table entry search operation. */
   6078     _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &mp_group_entry);
   6079 
   6080     soc_mem_lock(unit, EGR_MP_GROUPm);
   6081     /* Perform the search in EGR_MP_GROUP table. */
   6082     rv = soc_mem_search(unit, EGR_MP_GROUPm, MEM_BLOCK_ANY, entry_idx,
   6083                                   &mp_group_entry, mp_group_entry_p, 0);
   6084 
   6085     if (SAL_BOOT_BCMSIM) {
   6086         if(*entry_idx < 0) {
   6087             rv = BCM_E_NOT_FOUND;
   6088         }
   6089     }
   6090     soc_mem_unlock(unit, EGR_MP_GROUPm);
   6091     if (BCM_FAILURE(rv)) {
   6092         LOG_VERBOSE(BSL_LS_BCM_OAM,
   6093                   (BSL_META_U(unit,
   6094                               "OAM(unit %d) Error:  Egr MP group entry lookup "
   6095                               "failed vlan=%d port =%x %s.\n"),
   6096                    unit, h_data_p->vlan, h_data_p->dglp, bcm_errmsg(rv)));
   6097     }
   6098 
   6099     return (rv);
   6100 }
   6101 
   6102 /*
   6103  * Function:
   6104  *     _bcm_sb2_oam_find_lmep
   6105  * Purpose:
   6106  *     Search LMEP view table and return the match entry hardware index and
   6107  *     match entry data.
   6108  * Parameters:
   6109  *     unit       - (IN) BCM device number
   6110  *     h_data_p   - (IN) Pointer to endpoint hash data.
   6111  *     entry_idx  - (OUT) Pointer to match entry hardware index.
   6112  *     mp_group_entry_p - (OUT) Pointer to match entry data.
   6113  * Retruns:
   6114  *     BCM_E_XXX
   6115  */
   6116 STATIC int
   6117 _bcm_sb2_oam_find_lmep(int unit,  const _bcm_oam_hash_data_t *h_data_p,
   6118                        int *entry_idx,
   6119                        mp_group_entry_t *mp_group_entry_p)
   6120 {
   6121     mp_group_entry_t   mp_group_entry; /* MP group entry to search.      */
   6122     int                rv;       /* Operation return status. */
   6123 
   6124     if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) {
   6125         return (BCM_E_INTERNAL);
   6126     }
   6127 
   6128     sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t));
   6129 
   6130     /* Construct endpoint LMEP view key for L3 Table entry search operation. */
   6131     _bcm_sb2_oam_lmep_key_construct(unit, h_data_p, &mp_group_entry);
   6132 
   6133     /* Take L3 module protection mutex to block any updates. */
   6134     L3_LOCK(unit);
   6135 
   6136     BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   6137     /* Perform the search in MP_GROUP_ENTRY table. */
   6138     rv = soc_mem_search(unit, MP_GROUPm, MEM_BLOCK_ANY, entry_idx,
   6139                         &mp_group_entry, mp_group_entry_p, 0);
   6140     BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   6141     if (BCM_FAILURE(rv)) {
   6142         LOG_VERBOSE(BSL_LS_BCM_OAM,
   6143                   (BSL_META_U(unit,
   6144                   "OAM(unit %d) Error: MP group entry lookup vlan=%d port=%x %s.\n"),
   6145                    unit, h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv)));
   6146     }
   6147 
   6148     /* Release L3 module protection mutex. */
   6149     L3_UNLOCK(unit);
   6150 
   6151     return (rv);
   6152 }
   6153 
   6154 STATIC int
   6155 _bcm_sb2_oam_find_port_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p,
   6156                             int *stm_index, source_trunk_map_table_entry_t *stm_entry,
   6157                             uint8 *mdl)
   6158 {
   6159     port_tab_entry_t port_entry;
   6160     int rv = BCM_E_NONE;
   6161     int port_id, mod_id;
   6162 
   6163     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
   6164             h_data_p->src_pp_port, &port_entry);
   6165 
   6166     if (BCM_FAILURE(rv)) {
   6167         return rv;
   6168     }
   6169 
   6170     *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   6171 
   6172     if (*mdl == 0) {
   6173         /* No port mep enabled already on this port */
   6174         return BCM_E_NOT_FOUND;
   6175     }
   6176 
   6177     port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   6178     mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   6179 
   6180     /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/
   6181     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_id,
   6182                                                port_id, stm_index));
   6183     BCM_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   6184                                       *stm_index, stm_entry));
   6185     return BCM_E_NONE;
   6186 }
   6187 
   6188 STATIC
   6189 int _bcm_sb2_oam_lm_counters_mems_from_pool_get(int pool_id, soc_mem_t *mems)
   6190 {
   6191     switch(pool_id) {
   6192         case 0:
   6193             mems[0] = ING_OAM_LM_COUNTERS_0m;
   6194             mems[1] = EGR_OAM_LM_COUNTERS_0m;
   6195             break;
   6196         case 1:
   6197             mems[0] = ING_OAM_LM_COUNTERS_1m;
   6198             mems[1] = EGR_OAM_LM_COUNTERS_1m;
   6199             break;
   6200         case 2:
   6201             mems[0] = ING_OAM_LM_COUNTERS_2m;
   6202             mems[1] = EGR_OAM_LM_COUNTERS_2m;
   6203             break;
   6204         default:
   6205             /* should not happen */
   6206             return BCM_E_INTERNAL;
   6207             break;
   6208     }
   6209     return BCM_E_NONE;
   6210 }
   6211 
   6212 
   6213 STATIC int
   6214 _bcm_sb2_oam_lm_counters_hw_values_init(int unit, int pool_id, int ctr_index,
   6215                             bcm_oam_endpoint_info_t *ep_info_p)
   6216 {
   6217     ing_oam_lm_counters_0_entry_t entry;
   6218     /* Ingress and egress. 2 memories */
   6219     soc_mem_t mems[2] = {INVALIDm, INVALIDm};
   6220     int index, entry_offset;
   6221 
   6222     BCM_IF_ERROR_RETURN(
   6223         _bcm_sb2_oam_lm_counters_mems_from_pool_get(pool_id, mems));
   6224 
   6225     for (index = 0; index < 2; index++) { 
   6226         sal_memset(&entry, 0, sizeof(entry));
   6227 
   6228         /* Set counter type */
   6229         if (ep_info_p->lm_ctr_type == bcmOamLmCounterTypePkt) {
   6230             soc_mem_field32_set(unit, mems[index], &entry, LM_COUNT_TYPEf, 0);
   6231         } else if (ep_info_p->lm_ctr_type == bcmOamLmCounterTypeByte) {
   6232             soc_mem_field32_set(unit, mems[index], &entry, LM_COUNT_TYPEf, 1);
   6233         } else {
   6234             return BCM_E_PARAM;
   6235         }
   6236 
   6237         /* Set byte counter sample size and pdu ctr field size */
   6238         if (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize32Bit) {
   6239             soc_mem_field32_set(unit, mems[index], &entry,
   6240                                 LM_COUNTER_SAMPLE_SIZEf, 0);
   6241         } else if (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit) {
   6242             soc_mem_field32_set(unit, mems[index], &entry,
   6243                                 LM_COUNTER_SAMPLE_SIZEf, 1);
   6244         } else {
   6245             return BCM_E_PARAM;
   6246         }
   6247 
   6248         if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) {
   6249             soc_mem_field32_set(unit, mems[index], &entry,
   6250                             LM_PDU_COUNTER_FIELD_SIZEf, 1);
   6251         } else {
   6252             soc_mem_field32_set(unit, mems[index], &entry,
   6253                             LM_PDU_COUNTER_FIELD_SIZEf, 0);
   6254         }
   6255 
   6256         /* 8 entries allocated per endpoint */
   6257         for(entry_offset = 0; entry_offset < 8; entry_offset++) {
   6258             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mems[index], MEM_BLOCK_ALL,
   6259                         ctr_index + entry_offset, &entry));
   6260         }
   6261     }
   6262 
   6263     return BCM_E_NONE;
   6264 }
   6265 
   6266 STATIC int
   6267 _bcm_sb2_oam_lm_counters_hw_values_reset(int unit, int pool_id, int index)
   6268 {
   6269     bcm_oam_endpoint_info_t ep_info;
   6270 
   6271     /* Initialize the ep_info */
   6272     bcm_oam_endpoint_info_t_init(&ep_info);
   6273 
   6274     /* Resetting to default values */
   6275     ep_info.lm_ctr_type = bcmOamLmCounterTypePkt;
   6276     ep_info.lm_ctr_sample_size = bcmOamLmCounterSize32Bit;
   6277     /* The type is Ethernet to set the PDU ctr
   6278      * field size to 32
   6279      */
   6280     ep_info.type = bcmOAMEndpointTypeEthernet;
   6281 
   6282     return _bcm_sb2_oam_lm_counters_hw_values_init(unit, pool_id, index,
   6283                                                    &ep_info);
   6284 }
   6285 
   6286 /*
   6287  * Function:
   6288  *     _bcm_sb2_oam_free_counter
   6289  * Purpose:
   6290  *     Free counter from counter pool.
   6291  * Parameters:
   6292  *     unit      - (IN) BCM device number
   6293  * Retruns:
   6294  *     BCM_E_XXX
   6295  */
   6296 STATIC int
   6297 _bcm_sb2_oam_free_counter(int unit, 
   6298                           _bcm_oam_hash_data_t *hash_data) 
   6299 {
   6300     int                  rv = BCM_E_NONE;/* Operation return status.         */
   6301     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   6302     int                  pool_id = 0;
   6303 
   6304     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   6305 
   6306     if (hash_data->rx_ctr != _BCM_OAM_INVALID_INDEX) {
   6307         pool_id = (hash_data->rx_ctr >> 24);
   6308         rv =  shr_aidxres_list_free(oc->ing_lm_ctr_pool[pool_id], 
   6309                                        (hash_data->rx_ctr & 0xffffff));
   6310         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lm_counters_hw_values_reset(unit, pool_id,
   6311                                              hash_data->rx_ctr & 0xffffff));
   6312         if (BCM_FAILURE(rv)) {
   6313             LOG_ERROR(BSL_LS_BCM_OAM,
   6314                       (BSL_META_U(unit,
   6315                                   "OAM(unit %d) Error: LM counter block "
   6316                                   "free failed (EP=%d) - %s.\n"),
   6317                        unit, hash_data->ep_id, bcm_errmsg(rv)));
   6318             return (rv);
   6319         }
   6320         hash_data->rx_ctr = hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX;
   6321     }
   6322     return (rv);
   6323 }
   6324 /*
   6325  * Function:
   6326  *     _bcm_sb2_oam_alloc_counter
   6327  * Purpose:
   6328  *     Allocate counter from counter pool.
   6329  * Parameters:
   6330  *     unit      - (IN) BCM device number
   6331  * Retruns:
   6332  *     BCM_E_XXX
   6333  */
   6334 STATIC int
   6335 _bcm_sb2_oam_alloc_counter(int unit, bcm_oam_endpoint_info_t *ep_info_p, int pool_id, 
   6336                            shr_idxres_element_t *ctr_index)
   6337 {
   6338     int                  rv;             /* Operation return status.         */
   6339     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   6340 
   6341     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   6342 
   6343     /* Allocate 8 consecutive couters from the pool */
   6344     rv =  shr_aidxres_list_alloc_block(oc->ing_lm_ctr_pool[pool_id],
   6345                                  8, ctr_index);
   6346     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lm_counters_hw_values_init(unit, pool_id,
   6347                 *ctr_index, ep_info_p));
   6348     if (BCM_FAILURE(rv)) {
   6349         LOG_ERROR(BSL_LS_BCM_OAM,
   6350                   (BSL_META_U(unit,
   6351                               "OAM(unit %d) Error: LM counter block alloic failed "
   6352                               "- %s.\n"), unit, bcm_errmsg(rv)));
   6353         return (rv);
   6354     }
   6355     return (BCM_E_NONE);
   6356 }
   6357 
   6358 
   6359 /*
   6360  * Function:
   6361  *     _bcm_sb2_oam_counter_set
   6362  * Purpose:
   6363  *     Set Rx counter for MEP 
   6364  * Parameters:
   6365  *     unit      - (IN) BCM device number
   6366  * Retruns:
   6367  *     BCM_E_XXX
   6368  */
   6369 STATIC int
   6370 _bcm_sb2_oam_counter_set(int unit, soc_mem_t  mem,
   6371                          bcm_oam_endpoint_info_t *ep_info_p,
   6372                          uint32 *entry,
   6373                          shr_idxres_element_t *ctr_index,
   6374                          int *ctr_field_id,
   6375                          int *pool_id,
   6376                          int alloc_counter)
   6377 {
   6378 
   6379     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   6380     soc_field_t   ctr1_field;
   6381     soc_field_t   ctr2_field;
   6382     int           ctr1_valid = 0;
   6383     int           ctr2_valid = 0;
   6384     int           rv = BCM_E_NONE;/* Operation return status.         */
   6385 
   6386     /* Lock already taken by the calling routine. */
   6387     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   6388 
   6389     ctr1_field = CTR1_VALIDf;
   6390     ctr2_field = CTR2_VALIDf;
   6391 
   6392     ctr1_valid = soc_mem_field32_get(unit, mem, 
   6393                                           (uint32 *)entry, ctr1_field);
   6394     ctr2_valid = soc_mem_field32_get(unit, mem, 
   6395                                           (uint32 *)entry, ctr2_field);
   6396 
   6397     /* if both counters are already used, we can't enable LM on this endpoint */
   6398     if ((1 == ctr1_valid) && (1 == ctr2_valid)) {
   6399         rv =  BCM_E_RESOURCE;
   6400         LOG_ERROR(BSL_LS_BCM_OAM,
   6401                   (BSL_META_U(unit,
   6402                               "OAM(unit %d) Error: 2 counters are already "
   6403                                "allocated for EP on this service interface"
   6404                               "%s.\n"), unit, bcm_errmsg(rv)));
   6405         return (rv);
   6406     } else if ((0 == ctr1_valid) && (1 == ctr2_valid)) {
   6407         if (alloc_counter) {
   6408             /* Pool id is provided by the user. */
   6409             *pool_id = ep_info_p->lm_ctr_pool_id;
   6410             rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index);
   6411             if (BCM_FAILURE(rv)) {
   6412                 LOG_ERROR(BSL_LS_BCM_OAM,
   6413                         (BSL_META_U(unit,
   6414                                     "OAM(unit %d) Error: LM counter block alloc - %s.\n"),
   6415                          unit, bcm_errmsg(rv)));
   6416                 return (rv);
   6417             }
   6418         }
   6419         *ctr_field_id = 0;
   6420         ctr1_valid = 1;
   6421     } else if ((0 == ctr2_valid) && (1 == ctr1_valid)) {
   6422         if (alloc_counter) {
   6423             /* Pool id is provided by the user. */
   6424             *pool_id = ep_info_p->lm_ctr_pool_id;
   6425             rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index);
   6426             if (BCM_FAILURE(rv)) {
   6427                 LOG_ERROR(BSL_LS_BCM_OAM,
   6428                         (BSL_META_U(unit,
   6429                                     "OAM(unit %d) Error: LM counter block alloc - %s.\n"),
   6430                          unit, bcm_errmsg(rv)));
   6431                 return (rv);
   6432             }
   6433         }
   6434         *ctr_field_id = 1;
   6435         ctr2_valid = 1;
   6436     } else {
   6437         if (alloc_counter) {
   6438             /* Pool id is provided by the user. */
   6439             *pool_id = ep_info_p->lm_ctr_pool_id;
   6440             rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index);
   6441             if (BCM_FAILURE(rv)) {
   6442                 LOG_ERROR(BSL_LS_BCM_OAM,
   6443                         (BSL_META_U(unit,
   6444                                     "OAM(unit %d) Error: LM counter block alloc - %s.\n"),
   6445                          unit, bcm_errmsg(rv)));
   6446                 return (rv);
   6447             }
   6448         }
   6449         /* Since both ctrs are free, use ctr1 */
   6450         *ctr_field_id = 0;
   6451         ctr1_valid = 1;
   6452     }
   6453     return (rv);
   6454 }
   6455 
   6456 STATIC uint32
   6457 _bcm_sb2_oam_qos_flags_to_mp_group_pri_mode(uint32 flags)
   6458 {
   6459     switch (flags) {
   6460         case BCM_QOS_MAP_OAM_INTPRI:
   6461             return 0;
   6462             break;
   6463         case BCM_QOS_MAP_OAM_OUTER_VLAN_PCP:
   6464             return 2;
   6465             break;
   6466         case BCM_QOS_MAP_OAM_INNER_VLAN_PCP:
   6467             return 3;
   6468             break;
   6469         case BCM_QOS_MAP_OAM_MPLS_EXP:
   6470             return 1;
   6471             break;
   6472     }
   6473     /* Default value is that of internal priority */
   6474     return 0;
   6475 }
   6476 
   6477 /*
   6478  * Function:
   6479  *     _bcm_sb2_oam_lmep_counters_set
   6480  * Purpose:
   6481  *     Get Tx counters for LMEP 
   6482  * Parameters:
   6483  *     unit      - (IN) BCM device number
   6484  *     ep_info_p - (IN) Pointer to remote endpoint information.
   6485  * Retruns:
   6486  *     BCM_E_XXX
   6487  */
   6488 STATIC int
   6489 _bcm_sb2_oam_lmep_counters_set(int unit,
   6490                                   bcm_oam_endpoint_info_t *ep_info_p)
   6491 {
   6492     _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */
   6493     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   6494     mp_group_entry_t     mp_group_entry; /* MP group entry buffer.*/
   6495     int                  mp_group_index = -1;/* MP group entry hardware index.*/
   6496     shr_idxres_element_t ctr_index = 0;
   6497     int                  pool_id = 0;
   6498     int                  ctr_field_id = 0;
   6499     egr_mp_group_entry_t egr_mp_group;   /* Egress MP group tbl entry buffer */
   6500     int                  egr_mp_grp_index = 0;
   6501     int                  rv = BCM_E_NONE;/* Operation return status.         */
   6502     uint32               profile_index = 0;
   6503     uint32               direction = 0; /* Up MEP or Down MEP */
   6504     uint32               flags = 0; /* Int pri or Exp or Inner dot1p
   6505                                             or outer dot1p */
   6506     uint32               pri_mode = 0;
   6507     uint32               map_ptr  = 0;
   6508 
   6509     /* Lock already taken by the calling routine. */
   6510     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   6511 
   6512     /* Get the stored endpoint information from hash table. */
   6513     hash_data = &oc->oam_hash_data[ep_info_p->id];
   6514     if (0 == hash_data->in_use) {
   6515         return (BCM_E_INTERNAL);
   6516     }
   6517 
   6518     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   6519         direction = 1;
   6520     }
   6521 
   6522 
   6523     /*For downMEP Rx counters are in Ing Mp group table and for UpMEP
   6524       it is in egr mp group table */
   6525     if (BCM_SUCCESS
   6526         (_bcm_sb2_oam_find_lmep(unit, hash_data, &mp_group_index, &mp_group_entry))) {
   6527         if (hash_data->rx_ctr == _BCM_OAM_INVALID_INDEX) {
   6528             /* Allocate counters and configure the same in MP_Group entry */
   6529             rv = _bcm_sb2_oam_counter_set(unit, MP_GROUPm,
   6530                     ep_info_p,
   6531                     (uint32 *)&mp_group_entry,
   6532                     &ctr_index, 
   6533                     &ctr_field_id,
   6534                     &pool_id,
   6535                     1);
   6536             if (BCM_FAILURE(rv)) {
   6537                 LOG_ERROR(BSL_LS_BCM_OAM,
   6538                         (BSL_META_U(unit,
   6539                                     "OAM(unit %d) Error: MP_GROUP_ENTRY table update failed "
   6540                                     "for EP=%d due to counter allocation failure "
   6541                                     "%s.\n"), unit, ep_info_p->id, bcm_errmsg(rv)));
   6542                 return (rv);
   6543             }
   6544             /* MS 8 bits of counter Id is pool id. LS 24 bits are index */
   6545             hash_data->rx_ctr = pool_id << 24 | (ctr_index);
   6546         } else {
   6547             pool_id = hash_data->rx_ctr >> 24;
   6548         }
   6549         hash_data->ctr_field_id = ctr_field_id;
   6550         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6551                                   sb2_mep_ctr_info[ctr_field_id].ctr_valid, 1);
   6552         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6553                      sb2_mep_ctr_info[ctr_field_id].ctr_base_ptr,
   6554                      (hash_data->rx_ctr & 0xFFFFFF));
   6555         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6556                               sb2_mep_ctr_info[ctr_field_id].ctr_mep_type, direction);
   6557         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6558                        sb2_mep_ctr_info[ctr_field_id].ctr_mep_mdl, ep_info_p->level);
   6559         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6560                        sb2_mep_ctr_info[ctr_field_id].ctr_pool_id, pool_id);
   6561         
   6562         /* If no priority map id is associated by user, associate it to 
   6563          * default priority map id
   6564          */
   6565         if (0 == ep_info_p->pri_map_id) {
   6566             ep_info_p->pri_map_id = oc->default_pri_map_id;
   6567         }
   6568         rv = _bcm_sb2_ing_service_pri_map_info_get(unit, ep_info_p->pri_map_id,
   6569                                                      &profile_index, &flags);
   6570         hash_data->pri_map_index = ep_info_p->pri_map_id;
   6571 
   6572         map_ptr = 
   6573             _BCM_SB2_SERVICE_PRI_MAP_PROFILE_INDEX_TO_MAP_PTR(profile_index);
   6574 
   6575         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6576                      sb2_mep_ctr_info[ctr_field_id].ctr_profile, map_ptr);
   6577         pri_mode = _bcm_sb2_oam_qos_flags_to_mp_group_pri_mode(flags);
   6578         soc_MP_GROUPm_field32_set(unit, &mp_group_entry,
   6579                      sb2_mep_ctr_info[ctr_field_id].ctr_pri_mode, pri_mode);
   6580 
   6581         BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   6582         rv = soc_mem_write(unit, MP_GROUPm, MEM_BLOCK_ALL,
   6583                                                    mp_group_index, &mp_group_entry);
   6584         BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   6585         if (BCM_FAILURE(rv)) {
   6586             LOG_ERROR(BSL_LS_BCM_OAM,
   6587                       (BSL_META_U(unit,
   6588                                   "OAM(unit %d) Error: MP_GROUP_ENTRY table write failed "
   6589                                   "for EP=%d %s.\n"),
   6590                        unit, ep_info_p->id, bcm_errmsg(rv)));
   6591             return (rv);
   6592         }
   6593 
   6594     } else  {
   6595         LOG_ERROR(BSL_LS_BCM_OAM,
   6596                   (BSL_META_U(unit,
   6597                               "OAM(unit %d) Error: MP group tbl entry not found-%s.\n"),
   6598                    unit, bcm_errmsg(rv)));
   6599         return rv;
   6600     }
   6601 
   6602     /*For downMEP Tx counters are in Egr Mp group table and for UpMEP it
   6603       is in ING MP group table */
   6604     if (BCM_SUCCESS(_bcm_sb2_oam_find_egr_lmep(unit, hash_data,
   6605                                     &egr_mp_grp_index, &egr_mp_group))) {
   6606         if (SAL_BOOT_BCMSIM) {
   6607             /* Added as WAR for Cmodel issue */
   6608             /* Construct endpoint egress MP group Table entry key part */
   6609             _bcm_sb2_oam_egr_lmep_key_construct(unit, hash_data, &egr_mp_group);
   6610             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1);
   6611         }
   6612         if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) {
   6613             /* Dont allocate counters. It is already allocated when oam_counter_set
   6614              * is called before this(with MP_GROUP). 
   6615              * Just get the ctr_field_id. Set alloc_counter=0
   6616              */
   6617             rv = _bcm_sb2_oam_counter_set(unit, EGR_MP_GROUPm,
   6618                     ep_info_p,
   6619                     (uint32 *)&egr_mp_group,
   6620                     &ctr_index, 
   6621                     &ctr_field_id,
   6622                     &pool_id,
   6623                     0);
   6624             if (BCM_FAILURE(rv)) {
   6625                 LOG_ERROR(BSL_LS_BCM_OAM,
   6626                         (BSL_META_U(unit,
   6627                                     "OAM(unit %d) Error: EGR_MP_GROUP_ENTRY table update failed "
   6628                                     "for EP=%d due to counter allocation failure "
   6629                                     "%s.\n"), unit, ep_info_p->id, bcm_errmsg(rv)));
   6630                 return (rv);
   6631             }
   6632             /* MS 8 bits of counter Id is pool id. LS 24 bits are index */
   6633             hash_data->tx_ctr = pool_id << 24 | (ctr_index);
   6634         } else {
   6635             pool_id = hash_data->tx_ctr >> 24;
   6636         }
   6637         hash_data->egr_ctr_field_id = ctr_field_id;
   6638         ep_info_p->lm_counter_base_id = hash_data->tx_ctr;
   6639         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6640                      sb2_mep_ctr_info[ctr_field_id].ctr_valid, 1);
   6641         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6642                  sb2_mep_ctr_info[ctr_field_id].ctr_base_ptr,
   6643                  (hash_data->tx_ctr & 0xFFFFFF));
   6644         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6645                     sb2_mep_ctr_info[ctr_field_id].ctr_mep_type, direction);
   6646         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6647                  sb2_mep_ctr_info[ctr_field_id].ctr_mep_mdl, ep_info_p->level);
   6648         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6649                        sb2_mep_ctr_info[ctr_field_id].ctr_pool_id, pool_id);
   6650 
   6651         if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) {
   6652             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6653                     sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset,
   6654                     ep_info_p->lm_payload_offset);
   6655             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6656                     sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset,
   6657                     ep_info_p->lm_cos_offset);
   6658         }
   6659 
   6660         /* Profile ptr and priority mode is found already during
   6661            ingress mp_group processing */
   6662         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6663                  sb2_mep_ctr_info[ctr_field_id].ctr_profile, map_ptr);
   6664         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group,
   6665                  sb2_mep_ctr_info[ctr_field_id].ctr_pri_mode, pri_mode);
   6666         hash_data->egr_pri_map_index = ep_info_p->pri_map_id;
   6667 
   6668         rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL,
   6669                                                egr_mp_grp_index, &egr_mp_group);
   6670         if (BCM_FAILURE(rv)) {
   6671             LOG_ERROR(BSL_LS_BCM_OAM,
   6672                       (BSL_META_U(unit,
   6673                                   "OAM(unit %d) Error: EGR_MP_GROUP table update failed "
   6674                                   "for EP=%d %s.\n"),
   6675                        unit, ep_info_p->id, bcm_errmsg(rv)));
   6676             return (rv);
   6677         }
   6678     } else  {
   6679         LOG_ERROR(BSL_LS_BCM_OAM,
   6680                   (BSL_META_U(unit,
   6681                               "OAM(unit %d) Error: EGR MP group tbl entry not found-%s.\n"),
   6682                    unit, bcm_errmsg(rv)));
   6683         return rv;
   6684     }
   6685 
   6686     return (rv);
   6687 }
   6688 
   6689 STATIC int
   6690 _bcm_sb2_oam_lmep_down_modify_new_dest_port(int unit, _bcm_oam_hash_data_t *h_data_p)
   6691 {
   6692 
   6693     lmep_1_entry_t              lmep_1_entry;    /* LMEP_1 table entry.*/
   6694 
   6695     /* Get the LMEP_1 table entry. */
   6696     BCM_IF_ERROR_RETURN(READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry));
   6697 
   6698    
   6699     /* Set the queue number */ 
   6700     if (h_data_p->tx_gport == BCM_GPORT_INVALID) {
   6701         soc_LMEP_1m_field32_set(unit, &lmep_1_entry, QUEUE_NUMf,
   6702                 SOC_INFO(unit).port_uc_cosq_base[h_data_p->dst_pp_port] +
   6703                 h_data_p->int_pri);
   6704     }
   6705 
   6706     /* Set the PP port */
   6707     soc_LMEP_1m_field32_set(unit, &lmep_1_entry, PP_PORTf, h_data_p->dst_pp_port); 
   6708 
   6709     SOC_IF_ERROR_RETURN
   6710         (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   6711                      &lmep_1_entry));
   6712 
   6713 
   6714     return (BCM_E_NONE);
   6715 }
   6716 
   6717 /*
   6718  * Function:
   6719  *     _bcm_oam_sb2_local_tx_mep_hw_set
   6720  * Purpose:
   6721  *     Configure hardware tables for a local CCM Tx enabled endpoint.
   6722  * Parameters:
   6723  *     unit      - (IN) BCM device number
   6724  *     ep_info_p - (IN) Pointer to remote endpoint information.
   6725  * Retruns:
   6726  *     BCM_E_XXX
   6727  */
   6728 STATIC int
   6729 _bcm_oam_sb2_local_tx_mep_hw_set(int unit,
   6730                                 bcm_oam_endpoint_info_t *ep_info_p)
   6731 {
   6732     int                  rv = BCM_E_NONE;/* Operation return status.   */
   6733     _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */
   6734     lmep_entry_t         entry;      /* LMEP table entry.              */
   6735     lmep_1_entry_t       entry_1;    /* LMEP_1 table entry.            */
   6736     int                  word;       /* Word index.                    */
   6737     uint32               reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4];
   6738                                      /* Group name in Hw format.       */
   6739     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   6740     const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info.   */
   6741     int                  subport = 0;
   6742     int                  oam_replacement_offset = 0;
   6743     int                  tpid_index = 0;
   6744     _bcm_kt2_subport_info_t subport_info;
   6745     int                  up_mep = 0;
   6746     int                  pp_port = 0;
   6747     int                  pool = 0;
   6748     int                  vlan_tag_control = 0;
   6749     uint32               tag_type = 0;
   6750     bcm_port_t           local_tx_port = 0;
   6751     int                  cosq_base = -1, count = -1;
   6752     bcm_port_t           up_mep_tx_port = 0;
   6753     bcm_gport_t          gport = 0;
   6754     if (NULL == ep_info_p) {
   6755         return (BCM_E_INTERNAL);
   6756     }
   6757 
   6758     /* Initialize local endpoint info pointer. */
   6759     ep_p = ep_info_p;
   6760 
   6761     /* Lock already taken by the calling routine. */
   6762     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   6763 
   6764     /* Get the stored endpoint information from hash table. */
   6765     hash_data = &oc->oam_hash_data[ep_p->id];
   6766     if (0 == hash_data->in_use) {
   6767         return(BCM_E_INTERNAL);
   6768     }
   6769 
   6770     sal_memset(&entry, 0, sizeof(lmep_entry_t));
   6771     sal_memset(&entry_1, 0, sizeof(lmep_1_entry_t));
   6772 
   6773     /* Set the Group base index. */
   6774     soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group);
   6775 
   6776     /* Set source MAC address to be used on transmitted packets. */
   6777     soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address);
   6778 
   6779     /* Set the Maintenance Domain Level. */
   6780     soc_LMEP_1m_field32_set(unit, &entry_1, MDLf, ep_p->level);
   6781 
   6782     /* Set endpoint name. */
   6783     soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name);
   6784 
   6785     /*
   6786      * Set VLAN ID to be used in the transmitted packet.
   6787      * For link level MEPs, this VLAN_ID == 0.
   6788      */
   6789     soc_LMEPm_field32_set(unit, &entry, SVLAN_TAGf, ep_p->vlan);
   6790 
   6791     /* Set packet priority value to be used in transmitted packet. */
   6792     soc_LMEPm_field32_set(unit, &entry, PRIORITYf, ep_p->pkt_pri);
   6793 
   6794     /* Set CVLAN Id */
   6795     soc_LMEPm_field32_set(unit, &entry, CVLAN_TAGf, ((ep_p->inner_pkt_pri << 13) | ep_p->inner_vlan));
   6796 
   6797     /* Set interval between CCM packet transmissions. */
   6798     soc_LMEPm_field32_set
   6799         (unit, &entry, CCM_INTERVALf,
   6800         _bcm_sb2_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period));
   6801 
   6802     /* Set Port status TLV in CCM Tx packets. */
   6803     if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) {
   6804         if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) {
   6805             return BCM_E_PARAM;
   6806         }
   6807         soc_LMEPm_field32_set(unit, &entry, PORT_TLVf,
   6808                               (ep_p->port_state == BCM_OAM_PORT_TLV_UP)
   6809                               ? 1 : 0);
   6810     }
   6811 
   6812 
   6813     /* Set the MEP type - up/down */
   6814     soc_LMEPm_field32_set(unit, &entry, MEP_TYPEf, 
   6815                          ((ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) ? 1 : 0));
   6816     /*
   6817      * Construct group name for hardware.
   6818      * i.e Word-reverse the MAID bytes for hardware.
   6819      */
   6820     for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4); ++word) {
   6821         reversed_maid[word]
   6822             = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name)
   6823                 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]);
   6824     }
   6825 
   6826     /* Set the group name. */
   6827     soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid);
   6828     /* Set OAM replacement offset & default TPID */
   6829     if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(hash_data)) {
   6830         oam_replacement_offset = 1;
   6831         if(hash_data->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
   6832             oam_replacement_offset = 5;
   6833             vlan_tag_control = 3;
   6834             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   6835         } else if (hash_data->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   6836             oam_replacement_offset = 3;
   6837             vlan_tag_control = 1;
   6838             tag_type =_BCM_OAM_DOMAIN_CVLAN;
   6839         } else if (hash_data->vlan > 0) {
   6840             oam_replacement_offset = 3;
   6841             vlan_tag_control = 2;
   6842             tag_type =_BCM_OAM_DOMAIN_SVLAN;
   6843         }
   6844     }
   6845 
   6846     switch (hash_data->oam_domain) {
   6847         case _BCM_OAM_DOMAIN_PORT:
   6848             oam_replacement_offset = 1;
   6849             vlan_tag_control = 0;
   6850             break;
   6851 
   6852         case _BCM_OAM_DOMAIN_CVLAN:
   6853             vlan_tag_control = 1;
   6854             oam_replacement_offset = 3;
   6855             tag_type =_BCM_OAM_DOMAIN_CVLAN;
   6856             break;
   6857 
   6858         case _BCM_OAM_DOMAIN_SVLAN: 
   6859             oam_replacement_offset = 3;
   6860             vlan_tag_control = 2;
   6861             tag_type =_BCM_OAM_DOMAIN_SVLAN;
   6862             break;
   6863 
   6864         case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
   6865             oam_replacement_offset = 5;
   6866             vlan_tag_control = 3;
   6867             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
   6868             break;
   6869 
   6870         default:
   6871             break;
   6872     }
   6873 
   6874 
   6875     /* if S or S+C vlan - set outer tpid index */
   6876     if ((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 
   6877         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)
   6878         ) { 
   6879         rv = _bcm_sb2_tpid_entry_add(unit, 
   6880                                  (ep_p->outer_tpid ? ep_p->outer_tpid :
   6881                                                  BCM_OAM_DEFAULT_TPID), 
   6882                                  BCM_OAM_TPID_TYPE_OUTER, &tpid_index);
   6883         if (BCM_FAILURE(rv)) {
   6884             LOG_ERROR(BSL_LS_BCM_OAM,
   6885                       (BSL_META_U(unit,
   6886                                   "OAM(unit %d) Error: L3 entry config failed in TPID set "
   6887                                   "for EP=%d %s.\n"),
   6888                        unit, ep_p->id, bcm_errmsg(rv)));
   6889             return (rv);
   6890         }
   6891         hash_data->outer_tpid_profile_index = tpid_index;
   6892         soc_LMEPm_field32_set(unit, &entry, SVLAN_TPID_INDEXf, tpid_index); 
   6893     }
   6894     if ((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 
   6895         /* C or S+C */
   6896         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)
   6897         ) { 
   6898         rv = _bcm_sb2_tpid_entry_add(unit, 
   6899                                  (ep_p->inner_tpid ? ep_p->inner_tpid :
   6900                                                  BCM_OAM_DEFAULT_TPID), 
   6901                                  BCM_OAM_TPID_TYPE_INNER, &tpid_index);
   6902         if (BCM_FAILURE(rv)) {
   6903             LOG_ERROR(BSL_LS_BCM_OAM,
   6904                       (BSL_META_U(unit,
   6905                                   "OAM(unit %d) Error: L3 entry config failed in TPID set "
   6906                                   "for EP=%d""  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   6907             return (rv);
   6908         }
   6909         hash_data->inner_tpid_profile_index = tpid_index;
   6910     }
   6911 
   6912     gport = hash_data->gport;
   6913     if (BCM_GPORT_IS_TRUNK(ep_p->gport)) {
   6914         gport =  hash_data->resolved_trunk_gport;
   6915     }
   6916     if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) &&
   6917               (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) {
   6918         /* CoE port */
   6919         rv = _bcm_sb2_tpid_entry_add(unit, 
   6920                                  (ep_p->subport_tpid ? ep_p->subport_tpid :
   6921                                                  BCM_OAM_DEFAULT_TPID), 
   6922                                  BCM_OAM_TPID_TYPE_SUBPORT, &tpid_index);
   6923         if (BCM_FAILURE(rv)) {
   6924             LOG_ERROR(BSL_LS_BCM_OAM,
   6925                       (BSL_META_U(unit,
   6926                                   "OAM(unit %d) Error: L3 entry config failed in TPID set "
   6927                                   "for EP=%d  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   6928             return (rv);
   6929         }
   6930         soc_LMEPm_field32_set(unit, &entry, 
   6931                               SUBPORT_TAG_TPID_INDEXf, tpid_index); 
   6932         hash_data->subport_tpid_profile_index = tpid_index;
   6933     }
   6934     
   6935     /* Set LMEP_1 table entry */
   6936 
   6937     /* If COE or LINKPHY port replacement offset should be increased 
   6938        by 2 to accomodate - stream_id/subport tag */ 
   6939     if (BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   6940         if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) ||
   6941             (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, gport))) {
   6942             oam_replacement_offset += 2; 
   6943             subport = 1 << 2;
   6944         }
   6945     }
   6946 
   6947     soc_LMEP_1m_field32_set(unit, &entry_1, OAM_REPLACEMENT_OFFSETf, 
   6948                                                 oam_replacement_offset);
   6949   
   6950 
   6951     /* Set Tag status of the generated CCM packet 
   6952        we can set it based on incoming packet tag info 
   6953        if SUBPORT - vlan tag control = 1 << 2 | hash_data->oam_domain & 0x3 */
   6954     if (subport) {
   6955         soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 
   6956                                    (subport  | (vlan_tag_control & 0x3)));
   6957     } else {
   6958         soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 
   6959                                    (vlan_tag_control & 0x3));
   6960 
   6961     }
   6962     
   6963     /* allocate TX counters */
   6964     if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   6965         if (ep_info_p->lm_counter_base_id != _BCM_OAM_LM_COUNTER_IDX_INVALID) {
   6966             /* Get the counter pool id */
   6967             pool = ep_info_p->lm_counter_base_id >> 24;
   6968             switch(pool){
   6969                 case 0:
   6970                     /* Set Counter 1 ID and action */
   6971                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_IDf,
   6972                             (ep_info_p->lm_counter_base_id & 0xFFFF));
   6973                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_ACTIONf, 1);
   6974                     break;
   6975                 case 1:
   6976                     /* Set Counter 2 ID and action */
   6977                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_IDf,
   6978                             (ep_info_p->lm_counter_base_id & 0xFFFF));
   6979                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_ACTIONf, 1);
   6980                     break;
   6981                 case 2:
   6982                     /* Set Counter 3 ID and action */
   6983                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_IDf,
   6984                             (ep_info_p->lm_counter_base_id & 0xFFFF));
   6985                     soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_ACTIONf, 1);
   6986                     break;
   6987             }
   6988         }
   6989 
   6990         if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   6991             /* TX counter is located in IP */
   6992             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_LOCATIONf, 0);
   6993             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_LOCATIONf, 0);
   6994             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_LOCATIONf, 0);
   6995         } else {
   6996             /* TX counter is located in EP */
   6997             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_LOCATIONf, 1);
   6998             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_LOCATIONf, 1);
   6999             soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_LOCATIONf, 1);
   7000         } 
   7001     } else {
   7002         soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_ACTIONf, 0);
   7003         soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_ACTIONf, 0);
   7004         soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_ACTIONf, 0);
   7005     }
   7006  
   7007     if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7008         up_mep = 1;
   7009     } 
   7010     /* For DownMEP, set Queue number to which this packet must be enqueued */ 
   7011     if (!up_mep) {
   7012         /* For DownMEPs, the queue that the CCM needs to go out
   7013          * could be special type of queue apart from the queues that
   7014          * are statically allocated for the ports. In such a case,
   7015          * they need to pass the COSQ GPORT for the queue that needs to
   7016          * be used via tx_gport variable. We get the cosq_base from that
   7017          * and derive correct queue number by adding the cosq index got
   7018          * in the int_pri variable.
   7019          */
   7020         if ((ep_p->tx_gport != BCM_GPORT_INVALID) &&
   7021             (BCM_GPORT_IS_UCAST_QUEUE_GROUP(ep_p->tx_gport) ||
   7022             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(ep_p->tx_gport)) &&
   7023             !(BCM_GPORT_IS_SCHEDULER(ep_p->tx_gport))) {
   7024             BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_index_resolve(unit, ep_p->tx_gport, -1,
   7025                             _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7026                             &local_tx_port, &cosq_base, &count));
   7027             soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf,
   7028                     cosq_base + ep_p->int_pri);
   7029         } else {
   7030             soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf,
   7031                     SOC_INFO(unit).port_uc_cosq_base[hash_data->dst_pp_port] +
   7032                     ep_p->int_pri);
   7033         }
   7034      /* Set the destination port on which packet needs to Tx. */
   7035         pp_port = hash_data->dst_pp_port;
   7036     } else {
   7037         soc_LMEP_1m_field32_set(unit, &entry_1, INT_PRIf,
   7038                 ep_p->int_pri);
   7039      /* Set the source on which packet is received */
   7040         pp_port = hash_data->src_pp_port;
   7041     } 
   7042 
   7043     if (ep_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) {
   7044         up_mep_tx_port = _BCM_KT2_SUBPORT_PORT_ID_GET(ep_p->tx_gport);
   7045         hash_data->src_pp_port = up_mep_tx_port;
   7046         pp_port = hash_data->src_pp_port;
   7047     }
   7048      /* Set the PP port */
   7049     soc_LMEP_1m_field32_set(unit, &entry_1, PP_PORTf, pp_port); 
   7050 
   7051     /* Set Outgoing Subport tag to be inserted into CCM packet */
   7052     if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) &&
   7053         (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) {
   7054         /* Get the subport tag */
   7055         rv = bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 
   7056                                                          &subport_info);
   7057         if (BCM_FAILURE(rv)) {
   7058             LOG_ERROR(BSL_LS_BCM_OAM,
   7059                       (BSL_META_U(unit,
   7060                                   "OAM(unit %d) Error: failed to get subport tag EP=%d"
   7061                                    "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   7062             return (rv);
   7063         }
   7064         if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) {
   7065                 soc_LMEP_1m_field32_set(unit, &entry_1, SUBPORT_TAGf, 
   7066                                              subport_info.subtag);
   7067         }
   7068     }
   7069 
   7070     /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */
   7071     if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) {
   7072         if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP)
   7073             || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) {
   7074             return BCM_E_PARAM;
   7075         }
   7076         soc_LMEP_1m_field32_set(unit, &entry_1, INTERFACE_TLVf,
   7077                               ep_p->interface_state);
   7078     }
   7079     /*
   7080      * When this bit is '1', both port and interface TLV values are set in
   7081      *  CCM Tx packets - set in LMEP table.
   7082      */
   7083     if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX)
   7084         || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) {
   7085         soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1);
   7086     }
   7087 
   7088     /* Set CCM packet Destination MAC address value. */
   7089     soc_mem_mac_addr_set(unit, LMEP_1m, &entry_1, DAf,
   7090                          ep_p->dst_mac_address);
   7091 
   7092 
   7093     /* Write entry to hardware LMEP table. */
   7094     SOC_IF_ERROR_RETURN
   7095         (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   7096                      &entry));
   7097 
   7098     /* Write entry to hardware LMEP_1 table. */
   7099     SOC_IF_ERROR_RETURN
   7100         (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   7101                      &entry_1));
   7102 
   7103 
   7104     return (BCM_E_NONE);
   7105 }
   7106 
   7107 /*
   7108  * Function:
   7109  *     _bcm_sb2_oam_stm_table_update
   7110  * Purpose:
   7111  *     Update MA_BASE_PTR in source trunk MAP table 
   7112  * Parameters:
   7113  *     unit      - (IN) BCM device number
   7114  *     mod_id    - (IN) module id
   7115  *     port_id   - (IN) port id
   7116  *     h_data_p  - (IN) endpoint hash data
   7117  * Retruns:
   7118  *     BCM_E_XXX
   7119  */
   7120 STATIC int
   7121 _bcm_sb2_oam_stm_table_update(int unit, bcm_module_t mod_id,
   7122                               bcm_port_t port_id, 
   7123                               _bcm_oam_hash_data_t *h_data_p)
   7124 {
   7125     int   stm_index = 0;
   7126     int   rv = BCM_E_NONE;
   7127 
   7128     source_trunk_map_table_entry_t stm_entry;
   7129     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7130     /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/
   7131     rv = _bcm_esw_src_mod_port_table_index_get(unit, mod_id,
   7132                                                port_id, &stm_index);
   7133 
   7134     if(BCM_FAILURE(rv)) {
   7135         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7136         return rv;
   7137     }
   7138 
   7139     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   7140                                       stm_index, &stm_entry);
   7141     if(BCM_FAILURE(rv)) {
   7142         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7143         return rv;
   7144     }
   7145 
   7146     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf,
   7147                                             h_data_p->ma_base_index);
   7148     rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index,
   7149                                              &stm_entry);
   7150     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7151     return rv;
   7152 }
   7153 
   7154 
   7155 /*
   7156  * Function:
   7157  *     _bcm_sb2_oam_port_mdl_update
   7158  * Purpose:
   7159  *     Update MDL bitmap in port table
   7160  * Parameters:
   7161  *     unit      - (IN) BCM device number
   7162  *     pp_port   - (IN) pp port id
   7163  *     reset     - (IN) Reset MDL bitmap or not
   7164  *     h_data_p  - (IN) endpoint hash data
   7165  *     mdl       - (OUT) Maintenance domain level
   7166  * Retruns:
   7167  *     BCM_E_XXX
   7168  */
   7169 STATIC int
   7170 _bcm_sb2_oam_port_mdl_update(int unit, uint32  pp_port, int reset, 
   7171                              _bcm_oam_hash_data_t *h_data_p, uint8 *mdl) 
   7172 {
   7173     port_tab_entry_t     port_entry;
   7174 
   7175     if (NULL == h_data_p) {
   7176         return (BCM_E_INTERNAL);
   7177     }
   7178     BCM_IF_ERROR_RETURN
   7179           (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, pp_port, &port_entry));
   7180 
   7181     /* read and update MDL bitmap */
   7182     *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   7183     if (reset) {
   7184         /* Clear the MDL bit for this endpoint. */
   7185         *mdl &= ~(1 << h_data_p->level);
   7186 
   7187     } else {
   7188         *mdl |= (1 << h_data_p->level);
   7189     }
   7190     soc_PORT_TABm_field32_set(unit, &port_entry, MDL_BITMAPf, *mdl);
   7191     BCM_IF_ERROR_RETURN
   7192          (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, pp_port, &port_entry));
   7193 
   7194     return BCM_E_NONE;
   7195 }            
   7196   
   7197 /*
   7198  * Function:
   7199  *     _bcm_sb2_oam_port_mdl_passive_update
   7200  * Purpose:
   7201  *     Update passive MDL bitmap in egress port table
   7202  * Parameters:
   7203  *     unit      - (IN) BCM device number
   7204  *     reset     - (IN) Reset MDL bitmap
   7205  *     h_data_p  - (IN) endpoint hash data
   7206  * Retruns:
   7207  *     BCM_E_XXX
   7208  */
   7209 STATIC int
   7210 _bcm_sb2_oam_port_mdl_passive_update(int unit, int reset,
   7211                                      _bcm_oam_hash_data_t *h_data_p, uint8 mdl) 
   7212 {
   7213     egr_port_entry_t     egr_port_entry;
   7214     uint8                passive_mdl = 0; /* Maintenance domain level-passive */
   7215     
   7216     if (NULL == h_data_p) {
   7217         return (BCM_E_INTERNAL);
   7218     }
   7219 
   7220     /* Passive demux should not be done for MIP */
   7221     if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   7222         return BCM_E_NONE;
   7223     }
   7224 
   7225     /* Set MDL passive bitmap in EGR_PORT table */
   7226     BCM_IF_ERROR_RETURN
   7227          (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, h_data_p->dst_pp_port,
   7228                           &egr_port_entry));
   7229 
   7230     if (reset) {
   7231         if (mdl > 0) {
   7232             /* Passive MDL bitmap */
   7233             _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, mdl,
   7234                                     h_data_p->ma_base_index, &passive_mdl, 0);
   7235         } else {
   7236             passive_mdl = 0;
   7237         }
   7238         soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 
   7239                                             MDL_BITMAP_PASSIVEf, passive_mdl);
   7240     } else {
   7241         /* read and update MDL bitmap */
   7242         mdl = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 
   7243                                                        MDL_BITMAP_PASSIVEf);
   7244         mdl |= (1 << h_data_p->level);
   7245 
   7246         /* Set all the bits till the highest configured MDL, so that there are 
   7247            no holes in the bitmap */
   7248         mdl |= ((1 << h_data_p->level) - 1);
   7249 
   7250         soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 
   7251                                                   MDL_BITMAP_PASSIVEf, mdl);
   7252     }
   7253     BCM_IF_ERROR_RETURN
   7254         (soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   7255                            h_data_p->dst_pp_port, &egr_port_entry));
   7256     return BCM_E_NONE;
   7257 }            
   7258 
   7259 /*
   7260  * Function:
   7261  *     _bcm_sb2_oam_trunk_port_mdl_config
   7262  * Purpose:
   7263  *     Update port mdl and stm table for OAM on trunk case     
   7264  * Parameters:
   7265  *     unit      - (IN) BCM device number
   7266  *     h_data_p - (IN) Pointer to hash data 
   7267  * Retruns:
   7268  *     BCM_E_XXX
   7269  */
   7270 STATIC int
   7271 _bcm_sb2_oam_trunk_port_mdl_config(int unit,
   7272                           _bcm_oam_hash_data_t *h_data_p)
   7273 {
   7274     int                  rv = BCM_E_NONE;/* Operation return status.         */
   7275     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7276     int                  member_count = 0;
   7277     bcm_port_t           *member_array = NULL; /* Trunk member port array.   */
   7278     int                  local_member_count = 0;
   7279     int                  i = 0;
   7280     bcm_port_t           port = 0;
   7281     bcm_module_t         module_id;            /* Module ID                  */
   7282     uint8                mdl = 0;
   7283 
   7284     /* Lock already taken by the calling routine. */
   7285     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7286 
   7287     if(h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   7288         return BCM_E_PARAM;
   7289     }
   7290 
   7291     /* Get all the local member ports belonging to this trunk */
   7292     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   7293                                NULL, 0, NULL, &member_count));
   7294     if (0 == member_count) {
   7295         /* No members have been added to the trunk group yet */
   7296         LOG_ERROR(BSL_LS_BCM_OAM,
   7297                   (BSL_META_U(unit,
   7298                               "OAM(unit %d) Error: No local members have been added to "
   7299                               "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv)));
   7300         return BCM_E_PARAM;
   7301     }
   7302 
   7303     _BCM_OAM_ALLOC(member_array, bcm_port_t,
   7304                        sizeof(bcm_port_t) * member_count, "Trunk info");
   7305     if (NULL == member_array) {
   7306         return (BCM_E_MEMORY);
   7307     }
   7308 
   7309     /* Get members of the trunk belonging to this module */
   7310     if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   7311                                                      h_data_p->trunk_id, 
   7312                                                      member_count, member_array,
   7313                                                      &local_member_count))) {
   7314         if (local_member_count > 0) {
   7315             for(i = 0; i < local_member_count; i++) {
   7316                 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   7317                                                   &module_id, &port);
   7318                 if (BCM_FAILURE(rv)) {
   7319                     sal_free(member_array);
   7320                     return (rv);
   7321                 }
   7322                 rv = _bcm_sb2_oam_stm_table_update(unit, module_id,
   7323                                                member_array[i], h_data_p);
   7324                 if (BCM_FAILURE(rv)) {
   7325                     sal_free(member_array);
   7326                     return (rv);
   7327                 }
   7328                 rv =_bcm_sb2_oam_port_mdl_update(unit, member_array[i], 0, 
   7329                                                         h_data_p, &mdl); 
   7330                 if (BCM_FAILURE(rv)) {
   7331                     sal_free(member_array);
   7332                     return (rv);
   7333                 }
   7334             } 
   7335         }
   7336         h_data_p->active_mdl_bitmap = mdl;
   7337     }
   7338     sal_free(member_array);
   7339     return BCM_E_NONE;
   7340 }
   7341 
   7342 /*
   7343  * Function:
   7344  *     _bcm_sb2_port_domain_oam_hw_set
   7345  * Purpose:
   7346  *    Configure port table and stm table entries for port based MEP. 
   7347  * Parameters:
   7348  *     unit      - (IN) BCM device number
   7349  *     ep_info_p - (IN) Pointer to remote endpoint information.
   7350  * Retruns:
   7351  *     BCM_E_XXX
   7352  */
   7353 STATIC int
   7354 _bcm_sb2_port_domain_oam_hw_set(int unit,
   7355                           const bcm_oam_endpoint_info_t *ep_info_p)
   7356 {
   7357     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   7358     int                  rv = BCM_E_NONE;/* Operation return status.         */
   7359     uint8                mdl = 0;        /* Maintenance domain level.        */
   7360     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7361     const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info.        */
   7362     bcm_module_t         mod_id = 0;
   7363     bcm_port_t           port_id = 0;
   7364 
   7365     if (NULL == ep_info_p) {
   7366         return (BCM_E_INTERNAL);
   7367     }
   7368 
   7369     /* Initialize local endpoint info pointer. */
   7370     ep_p = ep_info_p;
   7371 
   7372     /* Lock already taken by the calling routine. */
   7373     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7374 
   7375     /* Get endpoint hash data pointer. */
   7376     h_data_p = &oc->oam_hash_data[ep_p->id];
   7377 
   7378     /*  Set port table and source trunk map table */
   7379     if (0 == ep_info_p->vlan) {
   7380         if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   7381             rv = _bcm_sb2_oam_trunk_port_mdl_config(unit, h_data_p);
   7382         } else {
   7383             port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   7384             mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   7385             BCM_IF_ERROR_RETURN
   7386                 (_bcm_sb2_oam_stm_table_update(unit, mod_id,
   7387                                                port_id, h_data_p));
   7388             BCM_IF_ERROR_RETURN
   7389                 (_bcm_sb2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 0, 
   7390                                              h_data_p,  &mdl)); 
   7391             h_data_p->active_mdl_bitmap = mdl;
   7392         }
   7393         BCM_IF_ERROR_RETURN
   7394             (_bcm_sb2_oam_port_mdl_passive_update(unit, 0, h_data_p, mdl)); 
   7395     }
   7396     return (rv);
   7397 }
   7398 
   7399 
   7400 /*
   7401  * Function:
   7402  *     _bcm_sb2_oam_ing_mp_group_entry_set
   7403  * Purpose:
   7404  *     Configure MP Group entry tables entry for a local CCM Rx enabled endpoint.
   7405  * Parameters:
   7406  *     unit      - (IN) BCM device number
   7407  *     ep_info_p - (IN) Pointer to remote endpoint information.
   7408  * Retruns:
   7409  *     BCM_E_XXX
   7410  */
   7411 STATIC int
   7412 _bcm_sb2_oam_ing_mp_group_entry_set(int unit,
   7413                           bcm_oam_endpoint_info_t *ep_info_p)
   7414 {
   7415     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   7416     mp_group_entry_t   mp_group_entry;       /* L3 entry buffer.                 */
   7417     int                  entry_index = -1;  /* L3 entry hardware index.         */
   7418     int                  rv;             /* Operation return status.         */
   7419     uint8                mdl = 0;        /* Maintenance domain level.        */
   7420     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7421     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   7422     soc_field_t          mdl_field = 0;             
   7423     int                  up_mep = 0;     /* Endpoint is an upMep             */
   7424 
   7425     if (NULL == ep_info_p) {
   7426         return (BCM_E_INTERNAL);
   7427     }
   7428 
   7429     /* Initialize local endpoint info pointer. */
   7430     ep_p = ep_info_p;
   7431 
   7432     /* Lock already taken by the calling routine. */
   7433     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7434 
   7435     /* Get endpoint hash data pointer. */
   7436     h_data_p = &oc->oam_hash_data[ep_p->id];
   7437 
   7438     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7439         up_mep = 1 ;
   7440         mdl_field = MDL_BITMAP_PASSIVEf;
   7441     } else {
   7442         mdl_field = MDL_BITMAP_ACTIVEf;
   7443     }
   7444     /* MP Group entry */
   7445     L3_LOCK(unit);
   7446     if (BCM_SUCCESS
   7447             (_bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry))) {
   7448 
   7449         if ((mdl_field == MDL_BITMAP_PASSIVEf) && 
   7450             (_BCM_OAM_EP_IS_MIP(h_data_p))) {
   7451             /* Passive demultiplexing should not be done on a MIP */
   7452             L3_UNLOCK(unit);
   7453             return BCM_E_NONE;
   7454         }
   7455         /* There's already an entry for this */
   7456         mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, mdl_field);
   7457 
   7458         /* If active bitmap is 0, so for first active endppoint in the mp_group 
   7459          * need to programme ma_base_ptr field  during down_mep creation */
   7460         if((mdl == 0) && (up_mep == 0)) {
   7461             soc_MP_GROUPm_field32_set(unit, &mp_group_entry, MA_BASE_PTRf,
   7462                     h_data_p->ma_base_index);
   7463         } 
   7464 
   7465         mdl |= (1 << ep_p->level);
   7466 
   7467         /* Set all the bits till the highest configured MDL, so that there are 
   7468            no holes in the passive bitmap */
   7469         if (up_mep) {
   7470             mdl |= ((1 << ep_p->level) - 1);
   7471         }
   7472         /* set MDL bitmap passive or active depending on up or down mep */
   7473         soc_MP_GROUPm_field32_set(unit, &mp_group_entry, mdl_field, mdl);
   7474 
   7475         BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   7476         rv = soc_mem_write(unit, MP_GROUPm, MEM_BLOCK_ALL, 
   7477                                                        entry_index, &mp_group_entry);
   7478         BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   7479         if (BCM_FAILURE(rv)) {
   7480             L3_UNLOCK(unit);
   7481             LOG_ERROR(BSL_LS_BCM_OAM,
   7482                       (BSL_META_U(unit,
   7483                                   "OAM(unit %d) Error: MP_GROUP table update failed for "
   7484                                   "EP=%d" "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   7485             return (rv);
   7486         }
   7487     } else {
   7488 
   7489         /* This is the first entry at this */
   7490         sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t));
   7491 
   7492         /* Passive demultiplexing should not be done on a MIP */
   7493         if (!((mdl_field == MDL_BITMAP_PASSIVEf) 
   7494             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7495             mdl |= (1 << ep_p->level);
   7496 
   7497             /* Set all the bits till the highest configured MDL, so that there are 
   7498                no holes in the passive bitmap */
   7499             if (up_mep) {
   7500                 mdl |= ((1 << ep_p->level) - 1);
   7501             }
   7502 
   7503             /* set MDL bitmap passive or active depending on up or down mep */
   7504             soc_MP_GROUPm_field32_set(unit, &mp_group_entry, mdl_field, mdl);
   7505         }
   7506 
   7507         if (mdl == 0) {
   7508             /* MDL = 0 for case of MIP. Dont make the entry valid by
   7509                programming other fields.  */
   7510             L3_UNLOCK(unit);
   7511             return BCM_E_NONE;
   7512         }
   7513 
   7514         soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 
   7515                                                MA_BASE_PTRf,
   7516                                                h_data_p->ma_base_index);
   7517 
   7518         /* Configure time stamp type 1588(PTP)/NTP */
   7519         soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 
   7520                                        TIMESTAMP_TYPEf,
   7521              ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0));
   7522 
   7523         h_data_p->ts_format = ep_p->timestamp_format;
   7524 
   7525         /* Construct LMEP view key for L3 Table insert operation. */
   7526         _bcm_sb2_oam_lmep_key_construct(unit, h_data_p, &mp_group_entry);
   7527 
   7528         
   7529 
   7530         soc_MP_GROUPm_field32_set(unit, &mp_group_entry, VALIDf, 1);
   7531 
   7532         BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   7533         rv = soc_mem_insert(unit, MP_GROUPm, MEM_BLOCK_ALL, &mp_group_entry);
   7534         BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   7535         if (BCM_FAILURE(rv)) {
   7536             LOG_ERROR(BSL_LS_BCM_OAM,
   7537                       (BSL_META_U(unit,
   7538                       "OAM(unit %d) Error: MP_GROUP table insert failed for "
   7539                       "EP=%d" "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   7540             L3_UNLOCK(unit);
   7541             return (rv);
   7542         }
   7543     }
   7544     if (up_mep == 0) {
   7545         h_data_p->active_mdl_bitmap = mdl;
   7546     }
   7547     L3_UNLOCK(unit);
   7548     return (BCM_E_NONE);
   7549 }
   7550         
   7551 /*
   7552  * Function:
   7553  *     _bcm_sb2_oam_egr_mp_group_entry_set
   7554  * Purpose:
   7555  *     Configure Egress MP group tables entry for local CCM Rx enabled endpoint.
   7556  * Parameters:
   7557  *     unit      - (IN) BCM device number
   7558  *     ep_info_p - (IN) Pointer to remote endpoint information.
   7559  *     ctr_index - (OUT) LM counter index
   7560  * Retruns:
   7561  *     BCM_E_XXX
   7562  */
   7563 STATIC int
   7564 _bcm_sb2_oam_egr_mp_group_entry_set(int unit,
   7565                           bcm_oam_endpoint_info_t *ep_info_p,
   7566                           shr_idxres_element_t *ctr_index)
   7567 {
   7568     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   7569     int                  rv;             /* Operation return status.         */
   7570     uint8                mdl = 0;        /* Maintenance domain level.        */
   7571     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7572     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   7573     soc_field_t          mdl_field = 0;             
   7574     egr_mp_group_entry_t egr_mp_group;   /* Egress MP group tbl entry buffer */
   7575     int                  up_mep = 0;     /* Endpoint is an upMep             */
   7576     int                  mp_grp_index = 0;
   7577 
   7578     if (NULL == ep_info_p) {
   7579         return (BCM_E_INTERNAL);
   7580     }
   7581 
   7582     /* Initialize local endpoint info pointer. */
   7583     ep_p = ep_info_p;
   7584 
   7585     /* Lock already taken by the calling routine. */
   7586     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7587 
   7588     /* Get endpoint hash data pointer. */
   7589     h_data_p = &oc->oam_hash_data[ep_p->id];
   7590 
   7591     if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   7592         up_mep = 1;
   7593         mdl_field = MDL_BITMAP_ACTIVEf;
   7594     } else {
   7595         if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) {
   7596             /* For MPLS LM DM configure active */
   7597             mdl_field = MDL_BITMAP_ACTIVEf;
   7598         } else {
   7599             mdl_field = MDL_BITMAP_PASSIVEf;
   7600         } 
   7601     }
   7602 
   7603     sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
   7604     
   7605     /* form the key to search EGR_MP_GRUP table */
   7606     if (BCM_SUCCESS
   7607         (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p,
   7608                                         &mp_grp_index, &egr_mp_group))) {
   7609 
   7610         /* There's already an entry for this */
   7611         if (SAL_BOOT_BCMSIM) {
   7612         /* Added as WAR for Cmodel issue */
   7613         /* Construct endpoint egress MP group  Table entry search operation. */
   7614             _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group);
   7615             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1);
   7616         }
   7617         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, mdl_field);
   7618 
   7619         /* If active bitmap is 0, so for first active endppoint in the mp_group 
   7620          * need to programme ma_base_ptr field  during up_mep creation */
   7621         if((mdl == 0) && up_mep) {
   7622             soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf,
   7623                     h_data_p->ma_base_index);
   7624         }
   7625         /* Passive demultiplexing should not be done on a MIP */
   7626         if (!((mdl_field == MDL_BITMAP_PASSIVEf) 
   7627             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7628             mdl |= (1 << ep_p->level);
   7629 
   7630             /* Set all the bits till the highest configured MDL, so that there are 
   7631                no holes in the passive bitmap */
   7632             if (mdl_field == MDL_BITMAP_PASSIVEf) {
   7633                 mdl |= ((1 << ep_p->level) - 1);
   7634             }
   7635         }
   7636         /* set MDL bitmap passive or active depending on up or down mep */
   7637         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl);
   7638 
   7639         soc_mem_lock(unit, EGR_MP_GROUPm);
   7640 
   7641         rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 
   7642                                              mp_grp_index, &egr_mp_group);
   7643         if (BCM_FAILURE(rv)) {
   7644             soc_mem_unlock(unit, EGR_MP_GROUPm);
   7645             return (rv);
   7646         }
   7647         soc_mem_unlock(unit, EGR_MP_GROUPm);
   7648     } else {
   7649 
   7650         /* This is the first entry at this */
   7651         sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
   7652 
   7653         /* Passive demultiplexing should not be done on a MIP */
   7654         if (!((mdl_field == MDL_BITMAP_PASSIVEf) 
   7655             && (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   7656             mdl = (1 << ep_p->level);
   7657             /* Set all the bits till the highest configured MDL, so that there are 
   7658                no holes in the passive bitmap */
   7659             if ( mdl_field == MDL_BITMAP_PASSIVEf && !(BHH_EP_TYPE(ep_info_p)) ) {
   7660                 mdl |= ((1 << ep_p->level) - 1);
   7661             }
   7662         }
   7663 
   7664         if (mdl == 0) {
   7665             /* MDL = 0 for case of MIP. Dont make the entry valid by
   7666                programming other fields.  */
   7667             return BCM_E_NONE;
   7668         }
   7669 
   7670         /* set MDL bitmap passive or active depending on up or down mep */
   7671         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl);
   7672 
   7673         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf,
   7674                                       h_data_p->ma_base_index);
   7675 
   7676         /* Configure time stamp type 1588(PTP)/NTP */
   7677         soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 
   7678                                        TIMESTAMP_TYPEf,
   7679              ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0));
   7680 
   7681         h_data_p->ts_format = ep_p->timestamp_format;
   7682 
   7683         /* Construct LMEP view key for L3 Table insert operation. */
   7684         _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group);
   7685 
   7686         soc_mem_lock(unit, EGR_MP_GROUPm);
   7687 
   7688         rv = soc_mem_insert(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, &egr_mp_group);
   7689         if (BCM_FAILURE(rv)) {
   7690             soc_mem_unlock(unit, EGR_MP_GROUPm);
   7691             return (rv);
   7692         }
   7693         soc_mem_unlock(unit, EGR_MP_GROUPm);
   7694     }
   7695     if (up_mep == 1) {
   7696         h_data_p->active_mdl_bitmap = mdl;
   7697     }
   7698     return (BCM_E_NONE);
   7699 }
   7700 
   7701 STATIC int
   7702 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op (int unit,
   7703                              _bcm_oam_hash_data_t *h_data_p,
   7704                              soc_mem_t mem,
   7705                              int delete)
   7706 {
   7707     uint32             mdl_value[1] = { 0 };
   7708     int                bit_pos = 0;
   7709     int                current_offset = 0;
   7710     int                new_offset = 0;
   7711     int                entry_count = 0;
   7712     shr_idxres_list_handle_t pool;
   7713     bcm_oam_endpoint_t *temp_array = NULL;
   7714     _bcm_oam_control_t   *oc = NULL;
   7715     int ma_base_index = _BCM_OAM_INVALID_INDEX;
   7716     int is_upmep = 0;
   7717     mp_group_entry_t   mp_group_entry; /* LMEP view table entry.            */
   7718     int                mp_grp_index = -1;  /*  hardware index.          */
   7719     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   7720     int                egr_mp_grp_index = -1;
   7721     int                     stm_index = 0;
   7722     source_trunk_map_table_entry_t stm_entry;
   7723     uint8 port_mdl = 0;
   7724     int rv = BCM_E_NONE;
   7725 
   7726     if (NULL == h_data_p) {
   7727         return (BCM_E_INTERNAL);
   7728     }
   7729 
   7730     /* Lock already taken by the calling routine. */
   7731     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7732 
   7733     if (mem == MA_INDEXm) { 
   7734         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit,
   7735                     h_data_p, &entry_count, &pool));
   7736     } else {
   7737         entry_count = 8;
   7738     }
   7739 
   7740     if (entry_count <= 0) {
   7741         return BCM_E_INTERNAL;
   7742     }
   7743 
   7744     ma_base_index = h_data_p->ma_base_index;
   7745     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   7746 
   7747     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   7748         rv = _bcm_sb2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &port_mdl);
   7749         if (BCM_SUCCESS(rv)) {
   7750             mdl_value[0] = port_mdl; 
   7751         } else {
   7752             /* If app is not initialized (say rc), then during detach (delete)
   7753              * we will not find the entry. simply return without error */
   7754             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   7755                 return BCM_E_NONE;
   7756             } else {
   7757                 return BCM_E_INTERNAL;
   7758             }
   7759         }
   7760     } else if (is_upmep) {
   7761         rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 
   7762                 &egr_mp_grp_index, &egr_mp_group);
   7763         if (BCM_SUCCESS(rv)) {
   7764             mdl_value[0] = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   7765                     MDL_BITMAP_ACTIVEf);
   7766         } else {
   7767             /* If app is not initialized (say rc), then during detach (delete)
   7768              * we will not find the entry. simply return without error */
   7769             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   7770                 return BCM_E_NONE;
   7771             } else {
   7772                 return BCM_E_INTERNAL;
   7773             }
   7774         }
   7775     } else {
   7776         rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &mp_grp_index, &mp_group_entry);
   7777         if (BCM_SUCCESS(rv)) {
   7778             mdl_value[0] = soc_MP_GROUPm_field32_get(unit, &mp_group_entry,
   7779                                                       MDL_BITMAP_ACTIVEf);
   7780         } else {
   7781             /* If app is not initialized (say rc), then during detach (delete)
   7782              * we will not find the entry. simply return without error */
   7783             if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) {
   7784                 return BCM_E_NONE;
   7785             } else {
   7786                 return BCM_E_INTERNAL;
   7787             }
   7788         }
   7789     }
   7790 
   7791     _BCM_OAM_ALLOC(temp_array, bcm_oam_endpoint_t,
   7792                        sizeof(bcm_oam_endpoint_t) * entry_count, "endpoint id array");
   7793     if (NULL == temp_array) {
   7794         return (BCM_E_MEMORY);
   7795     }
   7796     /* Initialize the entry buffer. */
   7797     sal_memset(temp_array, _BCM_OAM_INVALID_INDEX, sizeof(bcm_oam_endpoint_t) * entry_count);
   7798 
   7799 
   7800 
   7801     if (delete) {
   7802         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   7803             if (SHR_BITGET(mdl_value, bit_pos)) {
   7804                if (bit_pos == h_data_p->level) {
   7805                    current_offset++;
   7806                } else {
   7807                     temp_array[new_offset] =  
   7808                     oc->_bcm_oam_ma_idx_to_ep_id_map
   7809                     [_BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   7810                         (ma_base_index, current_offset, is_upmep)];
   7811                    new_offset++;
   7812                    current_offset++;
   7813                }    
   7814             }
   7815         }
   7816     } else {
   7817         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   7818             if (SHR_BITGET(mdl_value, bit_pos)) {
   7819                if (bit_pos == h_data_p->level) {
   7820                    temp_array[new_offset] = h_data_p->ep_id; 
   7821                    new_offset++;
   7822                } else {
   7823                    temp_array[new_offset] = 
   7824                     oc->_bcm_oam_ma_idx_to_ep_id_map[
   7825                     _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index,
   7826                             current_offset, is_upmep)];
   7827                    new_offset++;
   7828                    current_offset++;
   7829                }    
   7830             }
   7831         }
   7832     }
   7833 
   7834     sal_memcpy(&(oc->_bcm_oam_ma_idx_to_ep_id_map[
   7835                 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX
   7836                 (ma_base_index, 0, is_upmep)]), 
   7837                 temp_array, sizeof(bcm_oam_endpoint_t) * entry_count);
   7838 
   7839     sal_free(temp_array);
   7840     return (BCM_E_NONE);
   7841 }
   7842  
   7843 STATIC int
   7844 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add (int unit,
   7845                              _bcm_oam_hash_data_t *h_data_p)
   7846 {
   7847     int is_upmep = 0;
   7848     int is_remote = 0;
   7849     int is_rx_enabled = 0;
   7850     soc_mem_t mem = MA_INDEXm;
   7851     int rv = BCM_E_NONE;
   7852 
   7853     /* h_data_p being NULL could already be some other error
   7854      * scenario. Lets not return error for such a scenario.
   7855      */
   7856     if (h_data_p == NULL) {
   7857         return BCM_E_NONE;
   7858     }
   7859 
   7860     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   7861     if (is_upmep) {
   7862         mem = EGR_MA_INDEXm;
   7863     }
   7864     is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0;
   7865     is_rx_enabled =  (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX);
   7866     if (is_remote || !is_rx_enabled) {
   7867         /* Dont touch anything for remote endpoints or only tx enabled */
   7868         return BCM_E_NONE;
   7869     }
   7870     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 0); 
   7871     return rv;
   7872 }
   7873 
   7874 STATIC int
   7875 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete (int unit,
   7876                              _bcm_oam_hash_data_t *h_data_p)
   7877 {
   7878     int is_upmep = 0;
   7879     int is_remote = 0;
   7880     int is_rx_enabled = 0;
   7881     soc_mem_t mem = MA_INDEXm;
   7882     int rv = BCM_E_NONE;
   7883 
   7884     /* h_data_p being NULL could already be some other error
   7885      * scenario. Lets not return error for such a scenario.
   7886      */
   7887     if (h_data_p == NULL) {
   7888         return BCM_E_NONE;
   7889     }
   7890 
   7891     is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0;
   7892     if (is_upmep) {
   7893         mem = EGR_MA_INDEXm;
   7894     }
   7895     is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0;
   7896     is_rx_enabled =  (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX);
   7897     if (is_remote || !is_rx_enabled) {
   7898         /* Dont touch anything for remote endpoints or only tx enabled */
   7899         return BCM_E_NONE;
   7900     }
   7901     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 1); 
   7902     return rv;
   7903 }
   7904 
   7905 STATIC INLINE bcm_oam_endpoint_t
   7906 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t   *oc, int ma_idx)
   7907 {
   7908     return oc->_bcm_oam_ma_idx_to_ep_id_map[ma_idx];
   7909 }
   7910 
   7911 STATIC int _bcm_sb2_oam_ma_idx_to_ep_id_mapping_init (int unit)
   7912 {
   7913     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7914 
   7915     /* Lock already taken by the calling routine. */
   7916     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7917 
   7918     _BCM_OAM_ALLOC(oc->_bcm_oam_ma_idx_to_ep_id_map, bcm_oam_endpoint_t,
   7919                        _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE , "MA_IDX_TO_EP_ID map");
   7920 
   7921     if (oc->_bcm_oam_ma_idx_to_ep_id_map == NULL) {
   7922         return BCM_E_MEMORY;
   7923     }
   7924 
   7925     /* Init it to all invalid */
   7926     sal_memset(oc->_bcm_oam_ma_idx_to_ep_id_map, _BCM_OAM_INVALID_INDEX,
   7927                 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE);
   7928     return BCM_E_NONE;
   7929 }
   7930 
   7931 STATIC int _bcm_sb2_oam_ma_idx_to_ep_id_mapping_destroy (int unit)
   7932 {
   7933     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   7934 
   7935     /* Lock already taken by the calling routine. */
   7936     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   7937 
   7938     if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) {
   7939         sal_free(oc->_bcm_oam_ma_idx_to_ep_id_map);
   7940         oc->_bcm_oam_ma_idx_to_ep_id_map = NULL;
   7941     }
   7942 
   7943     return BCM_E_NONE;
   7944 }
   7945 
   7946 
   7947 
   7948 STATIC int
   7949 _bcm_sb2_oam_ma_index_entry_set(int unit,
   7950                              _bcm_oam_hash_data_t *h_data_p,
   7951                              soc_mem_t mem,
   7952                              void *ma_idx_ptr, int delete)
   7953 {
   7954     int                rv = BCM_E_NONE;
   7955     uint32             mdl_value[1] = { 0 };
   7956     int                bit_pos = 0;
   7957     int                current_offset = 0;
   7958     int                new_offset = 0;
   7959     int                entry_count = 0;
   7960     int                entry_mem_size = 0;
   7961     ma_index_entry_t *entry_buf;
   7962     ma_index_entry_t *entry;
   7963     ma_index_entry_t *entry_current;
   7964     shr_idxres_list_handle_t pool;
   7965 
   7966     if (NULL == h_data_p) {
   7967         return (BCM_E_INTERNAL);
   7968     }
   7969 
   7970     if (mem == MA_INDEXm) { 
   7971         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit,
   7972                     h_data_p, &entry_count, &pool));
   7973         new_offset = entry_count;
   7974         entry_mem_size = sizeof(ma_index_entry_t);
   7975     } else {
   7976         entry_mem_size = sizeof(egr_ma_index_entry_t);
   7977         new_offset = entry_count = 8;
   7978     }
   7979 
   7980     if (entry_count <= 0) {
   7981         return BCM_E_INTERNAL;
   7982     }
   7983 
   7984     /* Allocate buffer to store the DMAed table entries. */
   7985     entry_buf = soc_cm_salloc(unit, entry_mem_size * entry_count * 2,
   7986                               "MA index table entry buffer");
   7987     if (NULL == entry_buf) {
   7988         return (BCM_E_MEMORY);
   7989     }
   7990     /* Initialize the entry buffer. */
   7991     sal_memset(entry_buf, 0, entry_mem_size * entry_count * 2);
   7992 
   7993     /* Read the table entries into the buffer. */
   7994     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 
   7995                             (h_data_p->ma_base_index + entry_count - 1), 
   7996                             entry_buf);
   7997     if (BCM_FAILURE(rv)) {
   7998         if (entry_buf) {
   7999             soc_cm_sfree(unit, entry_buf);
   8000         }
   8001         return rv;
   8002     }
   8003 
   8004     mdl_value[0] = h_data_p->active_mdl_bitmap;
   8005 
   8006     if (delete) {
   8007         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   8008             if (SHR_BITGET(mdl_value, bit_pos)) {
   8009                if (bit_pos == h_data_p->level) {
   8010                    current_offset++;
   8011                } else {
   8012                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   8013                                                     ma_index_entry_t *,
   8014                                                     entry_buf, new_offset);
   8015                    entry_current = soc_mem_table_idx_to_pointer(unit, mem, 
   8016                                                     ma_index_entry_t *,
   8017                                                     entry_buf, current_offset);
   8018                    sal_memcpy(entry, entry_current, entry_mem_size);
   8019                    new_offset++;
   8020                    current_offset++;
   8021                }    
   8022             }
   8023         }
   8024     } else {
   8025         for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   8026             if (SHR_BITGET(mdl_value, bit_pos)) {
   8027                if (bit_pos == h_data_p->level) {
   8028                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   8029                                                     ma_index_entry_t *,
   8030                                                     entry_buf, new_offset);
   8031                    sal_memcpy(entry, ma_idx_ptr, entry_mem_size);
   8032                    /* Doing Mod entry_count since new_offset starts 
   8033                       from entry_count */
   8034                    h_data_p->local_rx_index = h_data_p->ma_base_index +
   8035                                              (new_offset%entry_count);
   8036                    new_offset++;
   8037                } else {
   8038                    entry = soc_mem_table_idx_to_pointer(unit, mem, 
   8039                                                     ma_index_entry_t *,
   8040                                                     entry_buf, new_offset);
   8041                    entry_current = soc_mem_table_idx_to_pointer(unit, mem, 
   8042                                                     ma_index_entry_t *,
   8043                                                     entry_buf, current_offset);
   8044                    sal_memcpy(entry, entry_current, entry_mem_size);
   8045                    new_offset++;
   8046                    current_offset++;
   8047                }    
   8048             }
   8049         }
   8050     }
   8051     /* Move to the entry_count index since from there the newly programmed
   8052      * ma_index table memory is present */
   8053     entry = soc_mem_table_idx_to_pointer(unit, mem, ma_index_entry_t *,
   8054                                                     entry_buf, entry_count);
   8055     rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index,
   8056                              (h_data_p->ma_base_index + entry_count - 1), 
   8057                              entry);
   8058     if (BCM_FAILURE(rv)) {
   8059         if (entry_buf) {
   8060             soc_cm_sfree(unit, entry_buf);
   8061         }
   8062         return rv;
   8063     }
   8064     if (entry_buf) {
   8065         soc_cm_sfree(unit, entry_buf);
   8066     }
   8067     return (BCM_E_NONE);
   8068 } 
   8069 
   8070 STATIC int
   8071 _bcm_sb2_oam_port_table_ma_index_offset_get(int unit, 
   8072                                             _bcm_oam_hash_data_t *h_data_p, 
   8073                                             int *ma_offset) 
   8074 {
   8075     int                rv = BCM_E_NONE;
   8076     uint32             mdl_value[1] = { 0 };
   8077     int                bit_pos = 0;
   8078     bcm_port_t         port_id;              /* Port ID.            */
   8079     int                local_member_count = 0;
   8080     port_tab_entry_t   port_entry;
   8081     int                offset_found = 0;
   8082 
   8083     if (NULL == h_data_p) {
   8084         return (BCM_E_INTERNAL);
   8085     }
   8086     if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   8087         rv = _bcm_sb2_oam_trunk_port_mdl_config(unit, h_data_p);
   8088 
   8089         /* Get a member of the trunk belonging to this module */
   8090         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   8091                                            h_data_p->trunk_id, 1,
   8092                                            &port_id,
   8093                                            &local_member_count))) {
   8094         } else {
   8095             return (BCM_E_INTERNAL);
   8096         }
   8097         BCM_IF_ERROR_RETURN
   8098               (soc_mem_read(unit, PORT_TABm, 
   8099                             MEM_BLOCK_ANY, port_id, &port_entry));
   8100     } else {
   8101          BCM_IF_ERROR_RETURN
   8102               (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 
   8103                             h_data_p->src_pp_port, &port_entry));
   8104     }
   8105     mdl_value[0] = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf);
   8106     for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   8107         if (SHR_BITGET(mdl_value, bit_pos)) {
   8108             if (bit_pos == h_data_p->level) {
   8109                 offset_found = 1; 
   8110                 break;   
   8111             } else {
   8112                 *ma_offset += 1;
   8113             }
   8114         }
   8115     }
   8116     h_data_p->active_mdl_bitmap = mdl_value[0];
   8117     /* Added the line below to avoid compiler warning - unused variable */  
   8118     mdl_value[0] = *ma_offset;
   8119     if (offset_found == 0) {
   8120 #if 0
   8121         return (BCM_E_INTERNAL);
   8122 #else
   8123 
   8124     /* Workaround for now. */
   8125 return (BCM_E_NOT_FOUND);
   8126 #endif
   8127     }
   8128     return rv;
   8129 }
   8130 
   8131 
   8132 STATIC int
   8133 _bcm_sb2_oam_mp_grp_table_ma_index_offset_get(int unit, 
   8134                                             _bcm_oam_hash_data_t *h_data_p, 
   8135                                             int *ma_offset) 
   8136 {
   8137     int                rv = BCM_E_NONE;
   8138     uint32             mdl_value[1] = { 0 };
   8139     int                bit_pos = 0;
   8140     soc_mem_t          mem = 0;
   8141     mp_group_entry_t   mp_group_entry;      /* Mp group entry buffer. */
   8142     int                entry_index = 0;
   8143     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   8144     void               *entry;
   8145     soc_field_t        mdl_field = 0;
   8146     int                offset_found = 0;
   8147 
   8148     if (NULL == h_data_p) {
   8149         return (BCM_E_INTERNAL);
   8150     }
   8151     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   8152         mem = EGR_MP_GROUPm;
   8153         mdl_field = MDL_BITMAP_ACTIVEf;
   8154         entry = &egr_mp_group;
   8155         if (BCM_FAILURE(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 
   8156                                                    &entry_index, 
   8157                                                    &egr_mp_group))) {
   8158             LOG_ERROR(BSL_LS_BCM_OAM,
   8159                       (BSL_META_U(unit,
   8160                                   "OAM(unit %d) Error: EGR MP group tbl entry not found-%s.\n"),
   8161                        unit, bcm_errmsg(rv)));
   8162             return rv;
   8163         }
   8164     } else {
   8165         mem = MP_GROUPm;
   8166         mdl_field = MDL_BITMAP_ACTIVEf;
   8167         entry = &mp_group_entry;
   8168         rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry);
   8169         if (rv  != BCM_E_NONE) {
   8170             /* If not found then it's a harm-less error. Treat it as not a error.*/
   8171             if (BCM_E_NOT_FOUND == rv) {
   8172                 LOG_VERBOSE(BSL_LS_BCM_OAM,
   8173                         (BSL_META_U(unit,
   8174                                     "OAM(unit %d) Error: MP group tbl entry not found - %s.\n"),
   8175                          unit, bcm_errmsg(rv)));
   8176             } else {
   8177                 LOG_ERROR(BSL_LS_BCM_OAM,
   8178                         (BSL_META_U(unit,
   8179                                     "OAM(unit %d) Error: MP group tbl entry not found - %s.\n"),
   8180                          unit, bcm_errmsg(rv)));
   8181             }
   8182             return rv;
   8183         }
   8184     }
   8185     mdl_value[0] = soc_mem_field32_get(unit, mem, entry, mdl_field);
   8186     *ma_offset = 0;
   8187     for (bit_pos = 0; bit_pos <= 7; bit_pos++) {
   8188         if (SHR_BITGET(mdl_value, bit_pos)) {
   8189             if (bit_pos == h_data_p->level) {
   8190                 offset_found = 1; 
   8191                 break;   
   8192             } else {
   8193                 *ma_offset += 1;
   8194             }
   8195         }
   8196     }
   8197     h_data_p->active_mdl_bitmap = mdl_value[0];
   8198     if (offset_found == 0) {
   8199         return (BCM_E_INTERNAL);
   8200     }
   8201     return rv;
   8202 }
   8203 
   8204 
   8205 STATIC int
   8206 _bcm_sb2_oam_ma_index_offset_get(int unit, _bcm_oam_hash_data_t *h_data_p, 
   8207                                  int *ma_offset) 
   8208 {
   8209     int                rv = BCM_E_NONE;
   8210     if (NULL == h_data_p) {
   8211         return (BCM_E_INTERNAL);
   8212     }
   8213     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   8214         rv = _bcm_sb2_oam_port_table_ma_index_offset_get(unit, h_data_p, 
   8215                                                          ma_offset);
   8216         /* BCM_E_NOT_FOUND is not an error when switch is re-initializing
   8217            as entry would have been already deleted by port module init */
   8218         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   8219             LOG_ERROR(BSL_LS_BCM_OAM,
   8220                       (BSL_META_U(unit,
   8221                                   "OAM(unit %d) Error: Port table read failed - %s.\n"),
   8222                        unit, bcm_errmsg(rv)));
   8223             return rv;
   8224         }
   8225     } else {
   8226         rv = _bcm_sb2_oam_mp_grp_table_ma_index_offset_get(unit, h_data_p, 
   8227                                                          ma_offset);
   8228         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   8229             LOG_ERROR(BSL_LS_BCM_OAM,
   8230                       (BSL_META_U(unit,
   8231                                   "OAM(unit %d) Error: MP group table read failed - %s.\n"),
   8232                        unit, bcm_errmsg(rv)));
   8233             return rv;
   8234         } 
   8235     }
   8236     return (BCM_E_NONE);
   8237 }
   8238 /*
   8239  * Function:
   8240  *     _bcm_sb2_oam_local_rx_mep_hw_set
   8241  * Purpose:
   8242  *     Configure hardware tables for a local CCM Rx enabled endpoint.
   8243  * Parameters:
   8244  *     unit      - (IN) BCM device number
   8245  *     ep_info_p - (IN) Pointer to remote endpoint information.
   8246  * Retruns:
   8247  *     BCM_E_XXX
   8248  */
   8249 STATIC int
   8250 _bcm_sb2_oam_local_rx_mep_hw_set(int unit,
   8251                              bcm_oam_endpoint_info_t *ep_info_p)
   8252 {
   8253     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   8254     ma_index_entry_t     ma_idx_entry;   /* MA_INDEX table entry buffer.     */
   8255     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/
   8256     oam_opcode_control_profile_entry_t *opcode_entry = NULL; /* Opcode control 
   8257                                                              profile entry.  */
   8258     egr_oam_opcode_control_profile_entry_t *egr_opcode_entry = NULL; /* Egress  
   8259                                                  Opcode control profile entry*/
   8260     void                 *entries[1];    /* Pointer to opcode control entry. */
   8261     uint32               profile_index = 0;  /* opcode control profile index.    */
   8262     int                  rv;             /* Operation return status.         */
   8263     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   8264     bcm_oam_endpoint_info_t *ep_p;       /* Pointer to endpoint info.        */
   8265     soc_mem_t            opcode_profile_mem = 0;
   8266     soc_mem_t            ma_index_mem = 0;
   8267     shr_idxres_element_t egr_ctr_index = 0;
   8268     soc_profile_mem_t    *opcode_control_profile; /* profile to be used 
   8269                                                         ingress or egress    */
   8270     void                 *ma_idx_ptr;
   8271     void                 *opcode_profile_entry;
   8272     
   8273 
   8274     if (NULL == ep_info_p) {
   8275         return (BCM_E_INTERNAL);
   8276     }
   8277 
   8278     /* Initialize local endpoint info pointer. */
   8279     ep_p = ep_info_p;
   8280 
   8281     /* Lock already taken by the calling routine. */
   8282     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   8283 
   8284     /* Get endpoint hash data pointer. */
   8285     h_data_p = &oc->oam_hash_data[ep_p->id];
   8286     if ( 0 == h_data_p->in_use) {
   8287         return (BCM_E_INTERNAL);
   8288     }
   8289 
   8290     if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   8291         opcode_profile_mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
   8292         opcode_control_profile = &oc->egr_oam_opcode_control_profile;
   8293         ma_index_mem   = EGR_MA_INDEXm;
   8294         ma_idx_ptr = &egr_ma_idx_entry;
   8295         egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE,
   8296                                      "egr opcode profile");
   8297         if(!egr_opcode_entry)
   8298         {
   8299             return BCM_E_MEMORY;
   8300         }
   8301         opcode_profile_entry = egr_opcode_entry;
   8302         /* Clear the entry data. */
   8303         sal_memset(egr_opcode_entry, 0, 
   8304                    _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE);
   8305         sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t));
   8306     } else {
   8307         opcode_profile_mem = OAM_OPCODE_CONTROL_PROFILEm;
   8308         opcode_control_profile = &oc->oam_opcode_control_profile;
   8309         ma_index_mem   = MA_INDEXm;
   8310         ma_idx_ptr = &ma_idx_entry;
   8311         opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE,
   8312                                  "opcode profile");
   8313         if(!opcode_entry)
   8314         {
   8315             return BCM_E_MEMORY;
   8316         }
   8317         opcode_profile_entry = opcode_entry;
   8318         /* Clear the entry data. */
   8319         sal_memset(opcode_entry, 0, 
   8320                    _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE);
   8321         sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t));
   8322     }
   8323 
   8324     /* Construct the opcode control profile table entry. */
   8325     if (ep_p->opcode_flags & _BCM_SB2_OAM_OPCODE_MASK) {
   8326         /* Use application specified opcode control settings. */
   8327         rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, h_data_p, opcode_profile_mem,
   8328                 ep_p->opcode_flags,
   8329                 opcode_profile_entry);
   8330         if (BCM_FAILURE(rv)) {
   8331             LOG_ERROR(BSL_LS_BCM_OAM,
   8332                     (BSL_META_U(unit,
   8333                                 "OAM(unit %d) Error: Opcode profile set failed for EP=%d"
   8334                                 "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8335             if(egr_opcode_entry) {
   8336                 sal_free(egr_opcode_entry);
   8337             }
   8338             if(opcode_entry) {
   8339                 sal_free(opcode_entry);
   8340             }
   8341             return (rv);
   8342         }
   8343     } else {
   8344         /* Use default opcode control profile settings. */
   8345         if (_BCM_OAM_EP_IS_MIP(h_data_p)) {
   8346             rv = _bcm_sb2_oam_mip_opcode_profile_entry_init(unit, opcode_profile_mem,
   8347                                                             opcode_profile_entry);
   8348         } else {
   8349             rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, opcode_profile_mem, 
   8350                                                         opcode_profile_entry);
   8351         }
   8352         if (BCM_FAILURE(rv)) {
   8353             LOG_ERROR(BSL_LS_BCM_OAM,
   8354                     (BSL_META_U(unit,
   8355                                 "OAM(unit %d) Error: Opcode profile init failed for EP=%d"
   8356                                 "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8357             if(egr_opcode_entry) {
   8358                 sal_free(egr_opcode_entry);
   8359             }
   8360             if(opcode_entry) {
   8361                 sal_free(opcode_entry);
   8362             }
   8363             return (rv);
   8364         }
   8365     }
   8366 
   8367     soc_mem_lock(unit, opcode_profile_mem);
   8368     /* Add entry to profile table.  */
   8369     entries[0] = opcode_profile_entry;
   8370 
   8371     rv = soc_profile_mem_add(unit, opcode_control_profile,
   8372             (void *)entries, 
   8373             _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index);
   8374     if (BCM_FAILURE(rv)) {
   8375         LOG_ERROR(BSL_LS_BCM_OAM,
   8376                 (BSL_META_U(unit,
   8377                             "OAM(unit %d) Error: Opcode profile add failed for EP=%d"
   8378                             "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8379         /* Release opcode control profile table lock. */
   8380         soc_mem_unlock(unit, opcode_profile_mem);
   8381         if(egr_opcode_entry) {
   8382             sal_free(egr_opcode_entry);
   8383         }
   8384         if(opcode_entry) {
   8385             sal_free(opcode_entry);
   8386         }
   8387         return (rv);
   8388     }
   8389 
   8390     /* Store endpoint OAM opcode profile table index value. */
   8391     h_data_p->profile_index = 
   8392         _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(profile_index);
   8393 
   8394     /* Release opcode control profile table lock. */
   8395     soc_mem_unlock(unit, opcode_profile_mem);
   8396 
   8397     if(egr_opcode_entry) {
   8398         sal_free(egr_opcode_entry);
   8399     }
   8400     if(opcode_entry) {
   8401         sal_free(opcode_entry);
   8402     }
   8403 
   8404     /*
   8405      * MA_INDEX table programming.
   8406      */
   8407 
   8408 
   8409     /* Set group index value. */
   8410     /* In case of BHH this needs to be the session Index */
   8411 #if defined(INCLUDE_BHH)
   8412     if ( BHH_EP_TYPE(ep_p) ) { 
   8413         soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf,
   8414                             BCM_OAM_BHH_GET_UKERNEL_EP(ep_p->id));
   8415     } else 
   8416 #endif
   8417     {
   8418         
   8419         soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf,
   8420                             ep_p->group);
   8421     }
   8422     
   8423 
   8424     
   8425     /* Set OAM opcode control profile table index. */
   8426     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
   8427                               OAM_OPCODE_CONTROL_PROFILE_PTRf,
   8428                               h_data_p->profile_index);
   8429 
   8430     /* Set CPU CoS queue value. */
   8431     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
   8432                                   INT_PRIf,
   8433                                   ep_p->int_pri);
   8434 #if defined (BCM_METROLITE_SUPPORT)
   8435     if(SOC_IS_METROLITE(unit)) {
   8436         h_data_p->lm_count_profile = ep_p->lm_count_profile;
   8437 
   8438         /* Set LM count profile index for the endpoint */
   8439         soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
   8440                 OAM_COUNT_PROFILEf,
   8441                 h_data_p->lm_count_profile);
   8442     }
   8443 #endif
   8444     /* If the OAM domain is port, set source trunk map table */
   8445     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   8446         rv = _bcm_sb2_port_domain_oam_hw_set(unit, ep_info_p);
   8447         if (BCM_FAILURE(rv)) {
   8448             LOG_ERROR(BSL_LS_BCM_OAM,
   8449                       (BSL_META_U(unit,
   8450                                   "OAM(unit %d) Error: port OAM config failed for EP=%d"
   8451                                    "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8452             return (rv);
   8453         }
   8454     } else {
   8455         rv = _bcm_sb2_oam_ing_mp_group_entry_set(unit, ep_info_p);
   8456         if (BCM_FAILURE(rv)) {
   8457             LOG_ERROR(BSL_LS_BCM_OAM,
   8458                       (BSL_META_U(unit,
   8459                                   "OAM(unit %d) Error: L3 entry config failed for EP=%d"
   8460                                    "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8461             return (rv);
   8462         }
   8463         rv = _bcm_sb2_oam_egr_mp_group_entry_set(unit, ep_info_p, 
   8464                                                        &egr_ctr_index);
   8465         if (BCM_FAILURE(rv)) {
   8466             LOG_ERROR(BSL_LS_BCM_OAM,
   8467                       (BSL_META_U(unit,
   8468                                   "OAM(unit %d) Error: Egress MP group entry config "
   8469                                   "failed for EP=%d %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8470             return (rv);
   8471         }
   8472 
   8473         if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   8474             rv = _bcm_sb2_oam_lmep_counters_set(unit, ep_info_p);
   8475             if (BCM_FAILURE(rv)) {
   8476                 LOG_ERROR(BSL_LS_BCM_OAM,
   8477                           (BSL_META_U(unit,
   8478                                       "OAM(unit %d) Error: Counter config failed for EP=%d"
   8479                                        "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8480                 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
   8481                     rv =  shr_aidxres_list_free(oc->ing_lm_ctr_pool[
   8482                                                   (h_data_p->rx_ctr >> 24)],
   8483                                                   (h_data_p->rx_ctr & 0xffffff));
   8484                     _bcm_sb2_oam_lm_counters_hw_values_reset(unit, h_data_p->rx_ctr >> 24,
   8485                                                   h_data_p->rx_ctr & 0xffffff);
   8486                     if (BCM_FAILURE(rv)) {
   8487                         LOG_ERROR(BSL_LS_BCM_OAM,
   8488                                   (BSL_META_U(unit,
   8489                                               "OAM(unit %d) Error: Ing LM counter block "
   8490                                               "free failed (EP=%d) - %s.\n"),
   8491                                    unit, ep_info_p->id, bcm_errmsg(rv)));
   8492                         return (rv);
   8493                     }
   8494                 }
   8495                 return (rv);
   8496             }
   8497         } else {
   8498             /* If loss measurement is not configured, set it to invalid */
   8499             ep_info_p->lm_counter_base_id = _BCM_OAM_LM_COUNTER_IDX_INVALID;
   8500         }
   8501     }
   8502     rv = _bcm_sb2_oam_ma_index_entry_set(unit, h_data_p, 
   8503                                          ma_index_mem, ma_idx_ptr, 0);
   8504     if (BCM_FAILURE(rv)) {
   8505         LOG_ERROR(BSL_LS_BCM_OAM,
   8506                   (BSL_META_U(unit,
   8507                               "OAM(unit %d) Error: MA_INDEX table write failed for EP=%d"
   8508                                "  %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8509         return (rv);
   8510     }
   8511     return rv;
   8512 }
   8513 
   8514 /*
   8515  * Function:
   8516  *     _bcm_sb2_oam_upmep_rx_endpoint_reserve
   8517  * Purpose:
   8518  *     Reserve an hardware index in the group state table to maintain the state
   8519  *     for a CCM Rx enabled endpoint.
   8520  * Parameters:
   8521  *     unit      - (IN) BCM device number
   8522  *     ep_info_p - (IN) Pointer to remote endpoint information.
   8523  * Retruns:
   8524  *     BCM_E_XXX
   8525  */
   8526 STATIC int
   8527 _bcm_sb2_oam_upmep_rx_endpoint_reserve(int unit,  
   8528                              const bcm_oam_endpoint_info_t *ep_info_p)
   8529 {
   8530     _bcm_oam_hash_data_t   *h_data_p;     /* Endpoint hash data pointer.      */
   8531     int                    rv;            /* Operation return status.         */
   8532     egr_mp_group_entry_t   egr_mp_grp_entry; /* egress mp group entry buffer. */
   8533     int                    mp_group_index = -1;/*MP group entry hardware index*/
   8534     int                    count = 0;     /* Successful Hw indices allocated. */
   8535     uint8                  mdl = 0;       /* Maintenance domain level.        */
   8536     uint32                 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   8537                                           /* Endpoint Rx hardware index.      */
   8538     uint16                 ma_base_idx;   /* Base pointer to endpoint state   */
   8539                                           /* table [MA_INDEX = (BASE + MDL)]. */
   8540     _bcm_oam_control_t     *oc;           /* Pointer to control structure.    */
   8541     const bcm_oam_endpoint_info_t *ep_p;  /* Pointer to endpoint information. */
   8542 
   8543     if (NULL == ep_info_p) {
   8544         return (BCM_E_INTERNAL);
   8545     }
   8546 
   8547     /* Lock already taken by the calling routine. */
   8548     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   8549 
   8550     /* Initialize local endpoint information pointer. */
   8551     ep_p = ep_info_p;
   8552 
   8553     /* Get endpoint hash data pointer. */
   8554     h_data_p = &oc->oam_hash_data[ep_p->id];
   8555     if (0 == h_data_p->in_use) {
   8556         return(BCM_E_INTERNAL);
   8557     }
   8558 
   8559     /* Initialize egress MP group table entry buffer. */
   8560     sal_memset(&egr_mp_grp_entry, 0, sizeof(egr_mp_group_entry_t));
   8561 
   8562     /* Find out if a matching entry already installed in hardware table. */
   8563     rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, &mp_group_index, 
   8564                                                         &egr_mp_grp_entry);
   8565     if (BCM_FAILURE(rv)) {
   8566         /*
   8567          * If NO match found, allocate a new hardware index from EGR_MA_INDEX
   8568          * pool.
   8569          */
   8570 
   8571         /*
   8572          * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   8573          * group endpoints. While allocating the base index, next 7 hardware
   8574          * indices are also reserved.
   8575          */
   8576         rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8,
   8577                                        (shr_idxres_element_t *) rx_index,
   8578                                        (shr_idxres_element_t *) &count);
   8579         if (BCM_FAILURE(rv)) {
   8580             LOG_ERROR(BSL_LS_BCM_OAM,
   8581                       (BSL_META_U(unit,
   8582                                   "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d"
   8583                                    " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8584             return (rv);
   8585         } else {
   8586             LOG_DEBUG(BSL_LS_BCM_OAM,
   8587                       (BSL_META_U(unit,
   8588                                   "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success"
   8589                                    " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   8590                        rx_index[0], count));
   8591             h_data_p->ma_base_index = rx_index[0];
   8592         }
   8593 
   8594     } else if (BCM_SUCCESS(rv)) {
   8595 
   8596         /* Matching entry found, get installed entry MDL value. */
   8597         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry,
   8598                                                        MDL_BITMAP_ACTIVEf);
   8599 
   8600         if (mdl == 0) {
   8601             /* This is the first one in the active bitmap. 
   8602                Allocate the hw indexes. */
   8603             /*
   8604              * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   8605              * group endpoints. While allocating the base index, next 7 hardware
   8606              * indices are also reserved.
   8607              */
   8608             rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8,
   8609                     (shr_idxres_element_t *) rx_index,
   8610                     (shr_idxres_element_t *) &count);
   8611             if (BCM_FAILURE(rv)) {
   8612                 LOG_ERROR(BSL_LS_BCM_OAM,
   8613                         (BSL_META_U(unit,
   8614                                     "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d"
   8615                                     " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8616                 return (rv);
   8617             } else {
   8618                 LOG_DEBUG(BSL_LS_BCM_OAM,
   8619                         (BSL_META_U(unit,
   8620                                     "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success"
   8621                                     " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   8622                          rx_index[0], count));
   8623                 h_data_p->ma_base_index = rx_index[0];
   8624             }
   8625         } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */
   8626             ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry,
   8627                                                       MA_BASE_PTRf);
   8628             h_data_p->ma_base_index = ma_base_idx;
   8629         } else {
   8630             /* Rx index already taken return error. */
   8631             LOG_ERROR(BSL_LS_BCM_OAM,
   8632                       (BSL_META_U(unit,
   8633                                   "OAM(unit %d) Error: No free Rx index found for EP:%d"
   8634                                    " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8635             return (BCM_E_RESOURCE);
   8636         }
   8637     }
   8638     return (rv);
   8639 }
   8640 
   8641 /*
   8642  * Function:
   8643  *     _bcm_sb2_oam_downmep_rx_endpoint_reserve
   8644  * Purpose:
   8645  *     Reserve an hardware index in the group state table to maintain the state
   8646  *     for a CCM Rx enabled endpoint.
   8647  * Parameters:
   8648  *     unit      - (IN) BCM device number
   8649  *     ep_info_p - (IN) Pointer to remote endpoint information.
   8650  * Retruns:
   8651  *     BCM_E_XXX
   8652  */
   8653 STATIC int
   8654 _bcm_sb2_oam_downmep_rx_endpoint_reserve(int unit, 
   8655                                 const bcm_oam_endpoint_info_t *ep_info_p)
   8656 {
   8657     _bcm_oam_hash_data_t   *h_data_p;     /* Endpoint hash data pointer.      */
   8658     int                    rv;            /* Operation return status.         */
   8659     mp_group_entry_t       mp_group_entry; /* MP Group entry buffer.          */
   8660     int                    entry_index = -1; /* MP group entry hardware index.*/
   8661     int                    count = 0;     /* Successful Hw indices allocated. */
   8662     uint8                  mdl = 0;       /* Maintenance domain level.        */
   8663     int                    rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   8664                                           /* Endpoint Rx hardware index.      */
   8665     uint16                 ma_base_idx;   /* Base pointer to endpoint state   */
   8666                                           /* table [MA_INDEX = (BASE + MDL)]. */
   8667     _bcm_oam_control_t     *oc;           /* Pointer to control structure.    */
   8668     const bcm_oam_endpoint_info_t *ep_p;  /* Pointer to endpoint information. */
   8669     int                     stm_index = 0;
   8670     source_trunk_map_table_entry_t stm_entry;
   8671     int                    ma_idx_entry_count = 0;
   8672     shr_idxres_list_handle_t pool = NULL;
   8673 
   8674     if (NULL == ep_info_p) {
   8675         return (BCM_E_INTERNAL);
   8676     }
   8677 
   8678     /* Lock already taken by the calling routine. */
   8679     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   8680 
   8681     /* Initialize local endpoint information pointer. */
   8682     ep_p = ep_info_p;
   8683 
   8684     /* Get endpoint hash data pointer. */
   8685     h_data_p = &oc->oam_hash_data[ep_p->id];
   8686     if ( 0 == h_data_p->in_use) {
   8687         return (BCM_E_INTERNAL);
   8688     }
   8689 
   8690     /* Initialize MP group entry buffer. */
   8691     sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t));
   8692     sal_memset(&stm_entry, 0, sizeof(source_trunk_map_table_entry_t));
   8693 
   8694     if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   8695         rv = _bcm_sb2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &mdl);
   8696     } else {
   8697         /* Find out if a matching entry already installed in hardware table. */
   8698         rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry);
   8699     }
   8700     if (BCM_FAILURE(rv)) {
   8701         /*
   8702          * If NO match found, allocate a new hardware index from MA_INDEX
   8703          * pool.
   8704          */
   8705         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   8706                                                           &ma_idx_entry_count, &pool));
   8707         /*
   8708          * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   8709          * group endpoints. While allocating the base index, next 7 hardware
   8710          * indices are also reserved.
   8711          */
   8712         rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count,
   8713                 (shr_idxres_element_t *) rx_index,
   8714                 (shr_idxres_element_t *) &count);
   8715 
   8716         if (BCM_FAILURE(rv)) {
   8717             LOG_ERROR(BSL_LS_BCM_OAM,
   8718                       (BSL_META_U(unit,
   8719                                   "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d"
   8720                                    " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8721             return (rv);
   8722         } else {
   8723             LOG_DEBUG(BSL_LS_BCM_OAM,
   8724                       (BSL_META_U(unit,
   8725                                   "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success."
   8726                                    " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   8727                        rx_index[0], count));
   8728         }
   8729 
   8730         h_data_p->ma_base_index = rx_index[0];
   8731     } else if (BCM_SUCCESS(rv)) {
   8732         if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   8733             /* MDL already found.*/
   8734             /* Findout if MDLs are same. */
   8735             if (0 == (mdl & (1 << ep_p->level))) {
   8736                 ma_base_idx =
   8737                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry,
   8738                             MA_BASE_PTRf);
   8739                 h_data_p->ma_base_index = ma_base_idx;
   8740             } else {
   8741                 /* Rx index already taken return error. */
   8742                 LOG_ERROR(BSL_LS_BCM_OAM,
   8743                         (BSL_META_U(unit,
   8744                                     "OAM Error: No free Rx index found for EP:%d"
   8745                                     " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   8746                 return (BCM_E_RESOURCE);
   8747             }
   8748         } else {
   8749             /* Matching entry found, get installed entry MDL value. */
   8750             mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 
   8751                     MDL_BITMAP_ACTIVEf);
   8752 
   8753             if (mdl == 0) {
   8754                 /* This is the first one in the active bitmap. 
   8755                    Allocate the hw indexes. */
   8756                 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   8757                             &ma_idx_entry_count, &pool));
   8758                 /*
   8759                  * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   8760                  * group endpoints. While allocating the base index, next 7 hardware
   8761                  * indices are also reserved.
   8762                  */
   8763                 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count,
   8764                         (shr_idxres_element_t *) rx_index,
   8765                         (shr_idxres_element_t *) &count);
   8766 
   8767                 if (BCM_FAILURE(rv)) {
   8768                     LOG_ERROR(BSL_LS_BCM_OAM,
   8769                             (BSL_META_U(unit,
   8770                                         "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d"
   8771                                         " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8772                     return (rv);
   8773                 } else {
   8774                     LOG_DEBUG(BSL_LS_BCM_OAM,
   8775                             (BSL_META_U(unit,
   8776                                         "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success."
   8777                                         " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id,
   8778                              rx_index[0], count));
   8779                 }
   8780 
   8781                 h_data_p->ma_base_index = rx_index[0];
   8782             } else if (0 == (mdl & (1 << ep_p->level))) {/* Findout if MDLs are same. */
   8783                 ma_base_idx = soc_MP_GROUPm_field32_get(unit, &mp_group_entry,
   8784                         MA_BASE_PTRf);
   8785                 h_data_p->ma_base_index = ma_base_idx;
   8786             } else {
   8787                 /* Rx index already taken return error. */
   8788                 LOG_ERROR(BSL_LS_BCM_OAM,
   8789                         (BSL_META_U(unit,
   8790                                     "OAM(unit %d) Error: No free Rx index found for EP:%d"
   8791                                     " %s.\n"), unit, ep_p->id, bcm_errmsg(rv)));
   8792                 return (BCM_E_RESOURCE);
   8793             }
   8794         }
   8795     }
   8796 
   8797     return (rv);
   8798 }
   8799 
   8800 /*
   8801  * Function:
   8802  *     _bcm_sb2_oam_remote_endpoint_delete
   8803  * Purpose:
   8804  *     Delete a remote endpoint.
   8805  * Parameters:
   8806  *     unit      - (IN) BCM device number
   8807  *     h_data_p  - (IN) Pointer to endpoint hash data
   8808  * Retruns:
   8809  *     BCM_E_XXX
   8810  */
   8811 STATIC int
   8812 _bcm_sb2_oam_remote_endpoint_delete(int unit,
   8813                                     _bcm_oam_hash_data_t *h_data_p)
   8814 {
   8815     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure.  */
   8816     l3_entry_1_entry_t l3_entry;       /* RMEP view table entry.             */
   8817     ma_state_entry_t   ma_state_entry; /* Group state machine table entry.   */
   8818     rmep_entry_t       rmep_entry;     /* Remote endpoint table entry.       */
   8819     int                rv;             /* Operation return status.           */
   8820     uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM  */
   8821                                          /* defects.                         */
   8822     uint32 some_rdi_defect_counter = 0;  /* No. of RMEPs in MA with RDI      */
   8823                                          /* defects.                         */
   8824     uint32 cur_some_rdi_defect = 0;      /* Any RMEP in MA with RDI defect.  */
   8825     uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect.  */
   8826     uint32 cur_rmep_ccm_defect = 0;      /* RMEP lookup failed or CCM        */
   8827                                          /* interval mismatch.               */
   8828     uint32 cur_rmep_last_rdi = 0;        /* Last CCM RDI Rx from this RMEP.  */
   8829     uint32 first, last, validLow, validHigh, freeCount, allocCount;
   8830 
   8831     
   8832     if(MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
   8833         return BCM_E_INTERNAL;
   8834     }
   8835 
   8836     /* Lock already taken by the calling routine. */
   8837     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   8838 
   8839     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   8840 
   8841     /* Get remote endpoint entry value from hardware. */
   8842     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
   8843     if (BCM_FAILURE(rv)) {
   8844         LOG_ERROR(BSL_LS_BCM_OAM,
   8845                   (BSL_META_U(unit,
   8846                               "OAM(unit %d) Error: RMEP table read failed for EP=%d"
   8847                                "%s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   8848         return (rv);
   8849     }
   8850 
   8851     cur_rmep_ccm_defect
   8852         = soc_RMEPm_field32_get(unit, &rmep_entry,
   8853                                 CURRENT_RMEP_CCM_DEFECTf);
   8854 
   8855     cur_rmep_last_rdi
   8856         = soc_RMEPm_field32_get(unit, &rmep_entry,
   8857                                 CURRENT_RMEP_LAST_RDIf);
   8858 
   8859     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry));
   8860     rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index,
   8861                         &ma_state_entry);
   8862     if (BCM_FAILURE(rv)) {
   8863         LOG_ERROR(BSL_LS_BCM_OAM,
   8864                   (BSL_META_U(unit,
   8865                               "OAM Error: Group state (GID=%d) table read"
   8866                                " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   8867         return (rv);
   8868     }
   8869 
   8870     if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) {
   8871         some_rmep_ccm_defect_counter
   8872             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   8873                                         SOME_RMEP_CCM_DEFECT_COUNTERf);
   8874         cur_some_rmep_ccm_defect
   8875             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   8876                                         CURRENT_SOME_RMEP_CCM_DEFECTf);
   8877 
   8878         if ((0 != cur_rmep_ccm_defect)
   8879             && (some_rmep_ccm_defect_counter > 0)) {
   8880             --some_rmep_ccm_defect_counter;
   8881             soc_MA_STATEm_field32_set
   8882                 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf,
   8883                  some_rmep_ccm_defect_counter);
   8884 
   8885             if (0 == some_rmep_ccm_defect_counter) {
   8886                 cur_some_rmep_ccm_defect = 0;
   8887                 soc_MA_STATEm_field32_set
   8888                     (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf,
   8889                      cur_some_rmep_ccm_defect);
   8890             }
   8891         }
   8892 
   8893         some_rdi_defect_counter
   8894             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   8895                                         SOME_RDI_DEFECT_COUNTERf);
   8896         cur_some_rdi_defect
   8897             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   8898                                         CURRENT_SOME_RDI_DEFECTf);
   8899 
   8900         if ((0 != cur_rmep_last_rdi)
   8901             && (some_rdi_defect_counter > 0)) {
   8902             --some_rdi_defect_counter;
   8903             soc_MA_STATEm_field32_set
   8904                 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf,
   8905                  some_rdi_defect_counter);
   8906 
   8907             if (0 == some_rdi_defect_counter) {
   8908                 cur_some_rdi_defect = 0;
   8909                 soc_MA_STATEm_field32_set
   8910                     (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf,
   8911                      cur_some_rdi_defect);
   8912             }
   8913         }
   8914 
   8915         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   8916                              &ma_state_entry);
   8917         if (BCM_FAILURE(rv)) {
   8918             LOG_ERROR(BSL_LS_BCM_OAM,
   8919                       (BSL_META_U(unit,
   8920                                   "OAM(unit %d) Error: Group state (GID=%d) table write"
   8921                                    " failed - %s.\n"), unit, h_data_p->group_index,
   8922                        bcm_errmsg(rv)));
   8923             return (rv);
   8924         }
   8925     }
   8926 
   8927     /* Clear RMEP table entry for this endpoint index. */
   8928     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   8929     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   8930                      &rmep_entry);
   8931     if (BCM_FAILURE(rv)) {
   8932         LOG_ERROR(BSL_LS_BCM_OAM,
   8933                   (BSL_META_U(unit,
   8934                               "OAM(unit %d) Error: RMEP table write index=%x (EP=%d)"
   8935                                " - %s.\n"), unit, h_data_p->remote_index,
   8936                    h_data_p->ep_id, bcm_errmsg(rv)));
   8937         return (rv);
   8938     }
   8939 
   8940     sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t));
   8941 
   8942     /* Construct endpoint RMEP view key for L3 Table entry delete operation. */
   8943     _bcm_sb2_oam_rmep_key_construct(unit, h_data_p, &l3_entry);
   8944 
   8945     rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry);
   8946     if (BCM_FAILURE(rv) && (oc->init)) {
   8947         LOG_ERROR(BSL_LS_BCM_OAM,
   8948                   (BSL_META_U(unit,
   8949                               "OAM(unit %d) Error: RMEP view update (EP=%d)"
   8950                                " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   8951         return (rv);
   8952     }
   8953 
   8954     /* Return ID back to free RMEP ID pool. */
   8955     BCM_IF_ERROR_RETURN
   8956         (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index));
   8957 
   8958     rv = shr_idxres_list_state(oc->rmep_pool,
   8959                                    &first, &last,
   8960                                    &validLow, &validHigh,
   8961                                    &freeCount, &allocCount);
   8962     if (BCM_FAILURE(rv)) {
   8963         LOG_ERROR(BSL_LS_BCM_OAM,
   8964                   (BSL_META_U(unit,
   8965                               "OAM Error: RMEP pool state get failed "
   8966                                " - %s.\n"), bcm_errmsg(rv)));
   8967         return (rv);
   8968     }
   8969 
   8970     if(allocCount == 0)
   8971     {
   8972         soc_MA_STATEm_field32_set
   8973             (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf,
   8974              0);
   8975         soc_MA_STATEm_field32_set
   8976             (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf,
   8977              0);
   8978         soc_MA_STATEm_field32_set
   8979             (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf,
   8980              0);
   8981         soc_MA_STATEm_field32_set
   8982             (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf,
   8983              0);
   8984         soc_MA_STATEm_field32_set
   8985             (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf,
   8986              0);
   8987         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   8988                 &ma_state_entry);
   8989         if (BCM_FAILURE(rv)) {
   8990             LOG_ERROR(BSL_LS_BCM_OAM,
   8991                     (BSL_META_U(unit,
   8992                                 "OAM Error: Group state (GID=%d) table write"
   8993                                 " failed - %s.\n"), h_data_p->group_index,
   8994                      bcm_errmsg(rv)));
   8995             return (rv);
   8996         }
   8997     }
   8998     /* Clear the H/w index to logical index Mapping for RMEP */
   8999     oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 
   9000 
   9001 
   9002     return (BCM_E_NONE);
   9003 }
   9004 
   9005 /*
   9006  * Function:
   9007  *     _bcm_sb2_oam_clear_counter
   9008  * Purpose:
   9009  *    Remove the counter associated with the endpoint being deleted 
   9010  * Parameters:
   9011  *     unit      - (IN) BCM device number
   9012  *     mem       - (IN) MP_GROUP/EGR_MP_GROUP
   9013  *     index     - (IN) Index of the table entry to be modified
   9014  *     h_data_p  - (IN) Pointer to endpoint hash data
   9015  *     entry     - (IN) pointer to table entry
   9016  * Retruns:
   9017  *     BCM_E_XXX
   9018  */
   9019 STATIC int
   9020 _bcm_sb2_oam_clear_counter(int unit, soc_mem_t mem,
   9021                            int index,
   9022                            _bcm_oam_hash_data_t *h_data_p, 
   9023                            void *entry)
   9024 {
   9025     int  rv = BCM_E_NONE;
   9026     sb2_mep_ctr_info_t  *ctr_info;
   9027     int           ctr_type = 0;
   9028     int           ctr1_valid = 0;
   9029     int           ctr2_valid = 0;
   9030     int           ctr_mdl = 0;
   9031     int           up_mep = 0;
   9032     int           ctr_field_id = 0;
   9033 
   9034     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9035         up_mep = 1;
   9036     }
   9037 
   9038     if (mem == MP_GROUPm) {
   9039         ctr_field_id = h_data_p->ctr_field_id;
   9040     } else if (mem == EGR_MP_GROUPm) {
   9041         ctr_field_id = h_data_p->egr_ctr_field_id;
   9042     } else {
   9043         return BCM_E_INTERNAL;
   9044     }
   9045 
   9046     ctr_info = sb2_mep_ctr_info;
   9047 
   9048     ctr1_valid = soc_mem_field32_get(unit, mem, 
   9049                                     (uint32 *)entry, ctr_info[0].ctr_valid);
   9050     if (ctr1_valid && ctr_field_id == 0) {
   9051         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   9052                                                  ctr_info[0].ctr_mep_type); 
   9053         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   9054                                                  ctr_info[0].ctr_mep_mdl); 
   9055         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
   9056             ctr1_valid = 0;
   9057             rv = soc_mem_field32_modify(unit, mem, index,
   9058                                                      ctr_info[0].ctr_valid, 0);
   9059         }
   9060     }   
   9061     ctr2_valid = soc_mem_field32_get(unit, mem, 
   9062                                     (uint32 *)entry, ctr_info[1].ctr_valid);
   9063     if (ctr2_valid && ctr_field_id == 1) {
   9064         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   9065                                                  ctr_info[1].ctr_mep_type); 
   9066         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
   9067                                                  ctr_info[1].ctr_mep_mdl); 
   9068         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
   9069             rv = soc_mem_field32_modify(unit, mem, index,
   9070                                                      ctr_info[1].ctr_valid, 0);
   9071             ctr2_valid = 0;
   9072         }
   9073     }
   9074     
   9075     /* return rx & tx counters allocated if any */
   9076     rv =_bcm_sb2_oam_free_counter(unit, h_data_p);
   9077     if (BCM_FAILURE(rv)) {
   9078         LOG_ERROR(BSL_LS_BCM_OAM,
   9079                 (BSL_META_U(unit,
   9080                             "OAM(unit %d) Error: LM counter block "
   9081                             "free failed (EP=%d) - %s.\n"),
   9082                  unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9083         return (rv);
   9084     }
   9085     
   9086     return rv;
   9087 }
   9088 
   9089 /*
   9090  * Function:
   9091  *     _bcm_sb2_oam_stm_table_clear
   9092  * Purpose:
   9093  *     Clear MA base ptr and return MA index to the pool
   9094  * Parameters:
   9095  *     unit      - (IN) BCM device number
   9096  *     mod_id    - (IN) Module Id
   9097  *     index     - (IN) stm member index
   9098  *     port_id   - (IN) port number
   9099  *     h_data_p - (IN) Pointer to hash data 
   9100  * Retruns:
   9101  *     BCM_E_XXX
   9102  */
   9103 STATIC int
   9104 _bcm_sb2_oam_stm_table_clear(int unit, bcm_module_t mod_id, int index,
   9105                               bcm_port_t port_id, 
   9106                               _bcm_oam_hash_data_t *h_data_p)
   9107 {
   9108     int                  rv = BCM_E_NONE;/* Operation return status.        */
   9109     int                  stm_index = 0;
   9110     source_trunk_map_table_entry_t stm_entry;
   9111     uint16               ma_base_idx;   /* Base pointer to endpoint state   */
   9112                                         /* table [MA_INDEX = (BASE + MDL)]. */
   9113     int                  idx = 0;    
   9114     _bcm_oam_control_t   *oc;           /* Pointer to control structure.    */
   9115     int                  count = 0;
   9116     int                  ma_idx_entry_count = 0;
   9117     shr_idxres_list_handle_t pool = NULL;
   9118 
   9119     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   9120 
   9121     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9122 
   9123     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9124 
   9125     rv = _bcm_esw_src_mod_port_table_index_get(unit,
   9126                                         mod_id, port_id, &stm_index);
   9127 
   9128     if(BCM_FAILURE(rv)) {
   9129         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9130         return rv;
   9131     }
   9132 
   9133     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
   9134                                                    stm_index, &stm_entry);
   9135 
   9136     if(BCM_FAILURE(rv)) {
   9137         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9138         return rv;
   9139     }
   9140 
   9141     ma_base_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 
   9142                                                  &stm_entry, MA_BASE_PTRf);
   9143     if (index == 0) {
   9144         /* Return Rx indices to free pool. */
   9145         for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   9146             rx_index[idx] = ma_base_idx + idx;
   9147         }
   9148 
   9149         rv = _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   9150                                                          &ma_idx_entry_count, &pool);
   9151         if(BCM_FAILURE(rv)) {
   9152             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9153             return rv;
   9154         }
   9155 
   9156         rv = shr_idxres_list_free_set(pool, ma_idx_entry_count,
   9157                 (shr_idxres_element_t *) rx_index,
   9158                 (shr_idxres_element_t *) &count);
   9159 
   9160         /* Sometimes during module de init source trunk map is fully wiped
   9161          * out before this is called. Hence ma_base_idx could be 0 instead
   9162          * of right value. So ignore if this free fails
   9163          */ 
   9164         if ((BCM_FAILURE(rv) || (8 != count)) && (ma_base_idx != 0)) {
   9165             LOG_ERROR(BSL_LS_BCM_OAM,
   9166                       (BSL_META_U(unit,
   9167                                   "OAM(unit %d) Error: Rx index list free (EP=%d)"
   9168                                    " (count=%d).\n"), unit, h_data_p->ep_id, count));
   9169             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9170             return (rv);
   9171         }
   9172     }
   9173 
   9174     /* Set MA_BASE_PTR to 0 */
   9175     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 0);
   9176 
   9177     rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index,
   9178                                                                 &stm_entry);
   9179     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   9180     return rv;
   9181 }
   9182 
   9183 /*
   9184  * Function:
   9185  *     _bcm_sb2_oam_trunk_port_mdl_update
   9186  * Purpose:
   9187  *     Modify port, egr port and stm table entry
   9188  * Parameters:
   9189  *     unit      - (IN) BCM device number
   9190  *     h_data_p - (IN) Pointer to hash data 
   9191  * Retruns:
   9192  *     BCM_E_XXX
   9193  */
   9194 STATIC int
   9195 _bcm_sb2_oam_trunk_port_mdl_update(int unit,
   9196                           _bcm_oam_hash_data_t *h_data_p)
   9197 {
   9198     int                  rv = BCM_E_NONE;      /* Operation return status.    */
   9199     _bcm_oam_control_t   *oc;                  /* Pointer to control structure*/
   9200     int                  member_count = 0;
   9201     bcm_port_t           *member_array = NULL; /* Trunk member port array.    */
   9202     int                  local_member_count = 0;
   9203     int                  i = 0;
   9204     bcm_port_t           pp_port = 0;
   9205     bcm_module_t         module_id;           /* Module ID                   */
   9206     uint8                mdl = 0;
   9207 
   9208     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9209 
   9210     if(h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   9211         return BCM_E_PARAM;
   9212     }
   9213 
   9214     /* Get all the local member ports belonging to this trunk */
   9215     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
   9216                                NULL, 0, NULL, &member_count));
   9217     if (0 == member_count) {
   9218         /* No members have been added to the trunk group yet */
   9219         LOG_ERROR(BSL_LS_BCM_OAM,
   9220                   (BSL_META_U(unit,
   9221                               "OAM(unit %d) Error: No local members have been added to "
   9222                               "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv)));
   9223         return BCM_E_PARAM;
   9224     }
   9225 
   9226     _BCM_OAM_ALLOC(member_array, bcm_port_t,
   9227                        sizeof(bcm_port_t) * member_count, "Trunk info");
   9228     if (NULL == member_array) {
   9229         return (BCM_E_MEMORY);
   9230     }
   9231 
   9232     /* Get members of the trunk belonging to this module */
   9233     if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
   9234                                                      h_data_p->trunk_id, 
   9235                                                      member_count, member_array,
   9236                                                      &local_member_count))) {
   9237         if (local_member_count > 0) {
   9238             for(i = 0; i < local_member_count; i++) {
   9239                 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
   9240                                                   &module_id, &pp_port);
   9241                 if (BCM_FAILURE(rv)) {
   9242                     sal_free(member_array);
   9243                     return (rv);
   9244                 }
   9245                 rv =_bcm_sb2_oam_port_mdl_update(unit, pp_port, 1, 
   9246                                                  h_data_p, &mdl); 
   9247                 if (BCM_FAILURE(rv)) {
   9248                     sal_free(member_array);
   9249                     return (rv);
   9250                 }
   9251             } 
   9252             if (mdl == 0) { 
   9253                 for(i = 0; i < local_member_count; i++) {
   9254                     rv = _bcm_sb2_oam_stm_table_clear(unit, module_id, i,
   9255                                                member_array[i], h_data_p);
   9256                     if (BCM_FAILURE(rv)) {
   9257                         sal_free(member_array);
   9258                         return (rv);
   9259                     }
   9260                 }
   9261             }
   9262             rv = _bcm_sb2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl); 
   9263             if (BCM_FAILURE(rv)) {
   9264                 sal_free(member_array);
   9265                 return (rv);
   9266             }
   9267 
   9268         }
   9269     }
   9270     sal_free(member_array);
   9271     return BCM_E_NONE;
   9272 }
   9273 /*
   9274  * Function:
   9275  *     _bcm_sb2_port_domain_mdl_bitmap_update
   9276  * Purpose:
   9277  *     Update Port table MDL bitmap and STM table MA_BASE_PTR. 
   9278  * Parameters:
   9279  *     unit      - (IN) BCM device number
   9280  *     h_data_p  - (IN) Pointer to endpoint hash data
   9281  * Retruns:
   9282  *     BCM_E_XXX
   9283  */
   9284 STATIC int
   9285 _bcm_sb2_port_domain_mdl_bitmap_update(int unit, _bcm_oam_hash_data_t *h_data_p)
   9286 {
   9287     int                  rv = BCM_E_NONE;/* Operation return status.         */
   9288     uint8                mdl;            /* Maintenance domain level.        */
   9289     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   9290     bcm_module_t         mod_id = 0;
   9291     bcm_port_t           port_id = 0;
   9292 
   9293     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9294 
   9295    /* If the OAM domain is port */
   9296     if (_BCM_OAM_DOMAIN_PORT != h_data_p->oam_domain) {
   9297         return (BCM_E_INTERNAL);
   9298     }
   9299 
   9300     if(h_data_p->trunk_id != BCM_TRUNK_INVALID) {
   9301         rv = _bcm_sb2_oam_trunk_port_mdl_update(unit, h_data_p);
   9302     } else {
   9303         port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
   9304         mod_id  = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
   9305         BCM_IF_ERROR_RETURN
   9306                 (_bcm_sb2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 
   9307                                              1, h_data_p, &mdl)); 
   9308         BCM_IF_ERROR_RETURN
   9309                 (_bcm_sb2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl)); 
   9310         if (mdl == 0) {
   9311             BCM_IF_ERROR_RETURN
   9312                 (_bcm_sb2_oam_stm_table_clear(unit, mod_id, 0,
   9313                                                port_id, h_data_p));
   9314         }
   9315     }
   9316     return (rv);
   9317 }
   9318 
   9319 /*
   9320  * Function:
   9321  *     _bcm_sb2_oam_ing_mp_group_entry_destroy
   9322  * Purpose:
   9323  *     Update Ingress MP group table(L3 Entry- LMEP view)entry.
   9324  * Parameters:
   9325  *     unit      - (IN) BCM device number
   9326  *     h_data_p  - (IN) Pointer to endpoint hash data
   9327  *     active_mdl -(IN) Active MDL bitmap value
   9328  * Retruns:
   9329  *     BCM_E_XXX
   9330  */
   9331 STATIC int
   9332 _bcm_sb2_oam_ing_mp_group_entry_destroy(int unit, _bcm_oam_hash_data_t *h_data_p, 
   9333                               uint8 *active_mdl)
   9334 {
   9335     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   9336     mp_group_entry_t   mp_group_entry; /* LMEP view table entry.            */
   9337     int                l3_index = -1;  /* L3 table hardware index.          */
   9338     int                rv;             /* Operation return status.          */
   9339     uint8              mdl;            /* Maintenance domain level.         */
   9340     uint8              other_mdl = 0;  /* Maintenance domain level.         */
   9341     uint32             ma_base_index;  /* Endpoint tbl base index. */
   9342     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   9343                                        /* Endpoint Rx hardware index.       */
   9344     uint32 count;                      /* No. of Rx indices freed           */
   9345                                        /* successfully.                     */
   9346     int                idx;            /* Iterator variable.                */
   9347     soc_field_t        mdl_field = 0;
   9348     soc_field_t        other_mdl_field = 0;
   9349     int                upmep = 0;
   9350     int                ma_idx_entry_count = 0;
   9351     shr_idxres_list_handle_t pool = NULL;
   9352 
   9353     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9354     /* Check whether up/down MEP */
   9355     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9356         mdl_field = MDL_BITMAP_PASSIVEf;
   9357         other_mdl_field = MDL_BITMAP_ACTIVEf;
   9358         upmep = 1;
   9359     } else {
   9360         mdl_field = MDL_BITMAP_ACTIVEf;
   9361         other_mdl_field = MDL_BITMAP_PASSIVEf;
   9362     }
   9363     rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &l3_index, &mp_group_entry);
   9364     if (BCM_SUCCESS(rv)) {
   9365         /* Endpoint found, get MDL bitmap value. */
   9366         mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry,
   9367                                                      mdl_field);
   9368 
   9369         /* Passive demultiplexing should not be done on a MIP.
   9370          * Hence do not touch PASSIVE bitmap when destroying
   9371          * also. 
   9372          */
   9373         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   9374              (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   9375             /* Clear the MDL bit for this endpoint. */
   9376             mdl &= ~(1 << h_data_p->level);
   9377 
   9378             if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9379                 /* Passive MDL bitmap */
   9380                 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 
   9381                                                 h_data_p->ma_base_index, &mdl, 1);
   9382             } else {
   9383                 *active_mdl = mdl;
   9384             }
   9385         }
   9386         /* Take L3 module protection mutex to block any updates. */
   9387         L3_LOCK(unit);
   9388         if (0 != mdl) {
   9389             BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   9390             /* Valid endpoints exist for other MDLs at this index. */
   9391             rv = soc_mem_field32_modify(unit, MP_GROUPm, l3_index,
   9392                                                      mdl_field, mdl);
   9393             BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   9394             if (BCM_FAILURE(rv)) {
   9395                 LOG_ERROR(BSL_LS_BCM_OAM,
   9396                           (BSL_META_U(unit,
   9397                                       "OAM(unit %d) Error:L3 entry LMEP view update(EP=%d) -"
   9398                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9399                 L3_UNLOCK(unit);
   9400                 return (rv);
   9401             }
   9402             /* Clear the counter, if any */
   9403             rv = _bcm_sb2_oam_clear_counter(unit, MP_GROUPm, 
   9404                                             l3_index, h_data_p, 
   9405                                             (void *)&mp_group_entry); 
   9406             if (BCM_FAILURE(rv)) {
   9407                 LOG_ERROR(BSL_LS_BCM_OAM,
   9408                           (BSL_META_U(unit,
   9409                                       "OAM(unit %d) Error: Clear counter failed (EP=%d) -"
   9410                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9411                 L3_UNLOCK(unit);
   9412                 return (rv);
   9413             }
   9414 
   9415         } else {
   9416             /* check if other MDL bitmap is also zero (passive bitmap incase 
   9417                of downmep and active bitmap in case of upmep), if so delete the
   9418                entry completely */
   9419             other_mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry,
   9420                                                      other_mdl_field);
   9421             if (0 == other_mdl) {
   9422                 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   9423                 rv = soc_mem_delete_index(unit, MP_GROUPm, 
   9424                                           MEM_BLOCK_ALL, l3_index);
   9425                 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   9426                 rv =_bcm_sb2_oam_free_counter(unit, h_data_p);
   9427                 if (BCM_FAILURE(rv)) {
   9428                     LOG_ERROR(BSL_LS_BCM_OAM,
   9429                               (BSL_META_U(unit,
   9430                                           "OAM(unit %d) Error: LM counter block "
   9431                                           "free failed (EP=%d) - %s.\n"),
   9432                                unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9433                     L3_UNLOCK(unit);
   9434                     return (rv);
   9435                 }
   9436             } else {
   9437                 /* Valid endpoints exist for other MDLs at this index. */
   9438                 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
   9439                 rv = soc_mem_field32_modify(unit, MP_GROUPm, 
   9440                                             l3_index, mdl_field, mdl);
   9441                 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
   9442                 if (BCM_FAILURE(rv)) {
   9443                     LOG_ERROR(BSL_LS_BCM_OAM,
   9444                               (BSL_META_U(unit,
   9445                                           "OAM(unit %d) Error: LMEP view update (EP=%d) -"
   9446                                            " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9447                     L3_UNLOCK(unit);
   9448                     return (rv);
   9449                 }
   9450                 /* Clear the counter, if any */
   9451                 rv = _bcm_sb2_oam_clear_counter(unit, MP_GROUPm, 
   9452                                                 l3_index, h_data_p, 
   9453                                                 (void *)&mp_group_entry); 
   9454                 if (BCM_FAILURE(rv)) {
   9455                     LOG_ERROR(BSL_LS_BCM_OAM,
   9456                               (BSL_META_U(unit,
   9457                                           "OAM(unit %d) Error: Clear counter failed (EP=%d) -"
   9458                                            " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9459                     L3_UNLOCK(unit);
   9460                     return (rv);
   9461                 }
   9462                    
   9463             }
   9464         }
   9465         L3_UNLOCK(unit);
   9466 
   9467         /* This is the last Rx endpoint in this OAM group. */
   9468         if ((0 == mdl) && (upmep == 0)) {
   9469             ma_base_index = soc_MP_GROUPm_field32_get(unit, 
   9470                                                             &mp_group_entry,
   9471                                                             MA_BASE_PTRf);
   9472             /* Return Rx indices to free pool. */
   9473             for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   9474                 rx_index[idx] = ma_base_index + idx;
   9475             }
   9476 
   9477             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
   9478                                                              &ma_idx_entry_count, &pool));
   9479             rv = shr_idxres_list_free_set(pool, ma_idx_entry_count,
   9480                     (shr_idxres_element_t *) rx_index,
   9481                     (shr_idxres_element_t *) &count);
   9482 
   9483             if (BCM_FAILURE(rv) || (8 != count)) {
   9484                 LOG_ERROR(BSL_LS_BCM_OAM,
   9485                           (BSL_META_U(unit,
   9486                                       "OAM(unit %d) Error: Rx index list free (EP=%d)"
   9487                                        " (count=%d).\n"), unit, h_data_p->ep_id, count));
   9488                 return (rv);
   9489             }
   9490         }
   9491         
   9492     } else if (BCM_FAILURE(rv) && (oc->init)) {
   9493         /* We do not program passive bitmap for MIP. So dont throw error
   9494          * if you don't find an entry, since we might not have created 
   9495          * such an entry at all. */
   9496         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   9497                     (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   9498             LOG_ERROR(BSL_LS_BCM_OAM,
   9499                     (BSL_META_U(unit,
   9500                                 "OAM(unit %d) Error:  L3 entry table lookup (EP=%d) -"
   9501                                 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9502             return (rv);
   9503         }
   9504     }
   9505     return (BCM_E_NONE);
   9506 }
   9507 
   9508 /* This is useful to find if an egr mp group has counters other
   9509  * than our endpoint's counters. This is useful in case of
   9510  * MPLS LSP endpoints which have the same lookup params and same
   9511  * mdl as well(hence in the same egr_mp_group entry and having
   9512  * same mdl bitmap) to know that there are endpoints with counters
   9513  * other than given endpoint. Therefore we could avoid touching the
   9514  * mdl bitmap or deleting the index itself during deleting of
   9515  * endpoint
   9516  */
   9517 #define MP_GRP_NUM_CTR_FIELD_IDS 2
   9518 int _bcm_sb2_oam_egr_mp_group_num_counters_other_than_mine_get(int unit,
   9519                                             egr_mp_group_entry_t *egr_mp_group,
   9520                                             _bcm_oam_hash_data_t *h_data_p)
   9521 {
   9522     int num_ctrs = 0;
   9523     int ctr_field_id;
   9524     int ctr_valid = 0;
   9525     sb2_mep_ctr_info_t  *ctr_info;
   9526 
   9527     if (!egr_mp_group || !h_data_p) {
   9528         return 0;
   9529     }
   9530 
   9531     ctr_info = sb2_mep_ctr_info;
   9532 
   9533     for (ctr_field_id = 0; ctr_field_id < MP_GRP_NUM_CTR_FIELD_IDS; 
   9534          ctr_field_id++) {
   9535         if (h_data_p->egr_ctr_field_id == ctr_field_id) {
   9536             /* If it is mine, skip counting */
   9537             continue;
   9538         }
   9539         ctr_valid = soc_mem_field32_get(unit, EGR_MP_GROUPm, 
   9540                 (uint32 *)egr_mp_group,
   9541                 ctr_info[ctr_field_id].ctr_valid);
   9542         if (ctr_valid) {
   9543             num_ctrs++;
   9544         }
   9545     }
   9546     return num_ctrs;
   9547 }
   9548 
   9549 /*
   9550  * Function:
   9551  *     _bcm_sb2_oam_egr_mp_group_entry_destroy
   9552  * Purpose:
   9553  *     Update Egress MP group table entry.
   9554  * Parameters:
   9555  *     unit      - (IN) BCM device number
   9556  *     h_data_p  - (IN) Pointer to endpoint hash data
   9557  * Retruns:
   9558  *     BCM_E_XXX
   9559  */
   9560 STATIC int
   9561 _bcm_sb2_oam_egr_mp_group_entry_destroy(int unit, 
   9562                                     _bcm_oam_hash_data_t *h_data_p,
   9563                                     uint8 *active_mdl)
   9564 {
   9565     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   9566     uint8              mdl;            /* Maintenance domain level.         */
   9567     uint8              other_mdl = 0;  /* Maintenance domain level.         */
   9568     int                rv;             /* Operation return status.          */
   9569     uint32             ma_base_index;  /* Endpoint tbl base index. */
   9570     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   9571                                        /* Endpoint Rx hardware index.       */
   9572     uint32 count;                      /* No. of Rx indices freed           */
   9573                                        /* successfully.                     */
   9574     int                idx;            /* Iterator variable.                */
   9575     soc_field_t        mdl_field = 0;
   9576     soc_field_t        other_mdl_field = 0;
   9577     egr_mp_group_entry_t egr_mp_group;  /* Egress MP group tbl entry buffer */
   9578     int                mp_grp_index = 0;
   9579     int                upmep = 0;
   9580     int                num_egr_mp_grp_counters_other_than_mine = 0;
   9581 
   9582     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9583 
   9584     /* Check whether up/down MEP */
   9585     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9586         mdl_field = MDL_BITMAP_ACTIVEf;
   9587         other_mdl_field = MDL_BITMAP_PASSIVEf;
   9588         upmep = 1;
   9589     } else {
   9590         if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
   9591             mdl_field = MDL_BITMAP_ACTIVEf;
   9592             other_mdl_field = MDL_BITMAP_PASSIVEf;
   9593         } else {
   9594             mdl_field = MDL_BITMAP_PASSIVEf;
   9595             other_mdl_field = MDL_BITMAP_ACTIVEf;
   9596         }
   9597     }
   9598     rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 
   9599                                           &mp_grp_index, &egr_mp_group);
   9600     if (BCM_SUCCESS(rv)) {
   9601         /* Endpoint found, get MDL bitmap value. */
   9602         mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   9603                                                      mdl_field);
   9604         /* Get number of counters other than mine */
   9605         num_egr_mp_grp_counters_other_than_mine = 
   9606             _bcm_sb2_oam_egr_mp_group_num_counters_other_than_mine_get(
   9607             unit, &egr_mp_group, h_data_p);
   9608 
   9609         /* Passive demultiplexing should not be done on a MIP.
   9610          * Hence do not touch PASSIVE bitmap when destroying
   9611          * also. 
   9612          */
   9613         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   9614              (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   9615             /* Clear the MDL bit for this endpoint. */
   9616             mdl &= ~(1 << h_data_p->level);
   9617 
   9618             if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9619                 *active_mdl = mdl;
   9620             } else{
   9621                 /* Passive MDL bitmap */
   9622                 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl,
   9623                                                  h_data_p->ma_base_index, &mdl, 0);
   9624             }
   9625         }
   9626         /* Take L3 module protection mutex to block any updates. */
   9627         soc_mem_lock(unit, EGR_MP_GROUPm);
   9628         if (0 != mdl) {
   9629             /* Valid endpoints exist for other MDLs at this index. */
   9630             rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index,
   9631                                                      mdl_field, mdl);
   9632             if (BCM_FAILURE(rv)) {
   9633                 LOG_ERROR(BSL_LS_BCM_OAM,
   9634                           (BSL_META_U(unit,
   9635                                       "OAM(unit %d) Error: EGR MP group table update (EP=%d) -"
   9636                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9637                 soc_mem_unlock(unit, EGR_MP_GROUPm);
   9638                 return (rv);
   9639             }
   9640             /* Clear the counter, if any */
   9641             rv = _bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index,
   9642                                             h_data_p, (void *)&egr_mp_group); 
   9643             if (BCM_FAILURE(rv)) {
   9644                 LOG_ERROR(BSL_LS_BCM_OAM,
   9645                           (BSL_META_U(unit,
   9646                                       "OAM(unit %d) Error:EGR MP group table update(EP=%d) -"
   9647                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9648                 soc_mem_unlock(unit, EGR_MP_GROUPm);
   9649                 return (rv);
   9650             }
   9651         } else {
   9652             /* check if other MDL bitmap is also zero (passive bitmap in case 
   9653                of downmep and active bitmap in case of upmep), if so delete the
   9654                entry completely */
   9655             other_mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   9656                                                      other_mdl_field);
   9657             if ((0 == other_mdl) &&
   9658                (!((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))&& 
   9659                   (num_egr_mp_grp_counters_other_than_mine >= 1)))) {
   9660                 rv = soc_mem_delete_index(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL,
   9661                                           mp_grp_index);
   9662                 rv =_bcm_sb2_oam_free_counter(unit, h_data_p);
   9663                 if (BCM_FAILURE(rv)) {
   9664                     LOG_ERROR(BSL_LS_BCM_OAM,
   9665                               (BSL_META_U(unit,
   9666                                           "OAM(unit %d) Error: LM counter block "
   9667                                           "free failed (EP=%d) - %s.\n"),
   9668                                unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9669                     soc_mem_unlock(unit, EGR_MP_GROUPm);
   9670                     return (rv);
   9671                 }
   9672             } else {
   9673                 if (!((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))&&
   9674                       (num_egr_mp_grp_counters_other_than_mine >= 1))) {
   9675                     rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index,
   9676                             mdl_field, mdl);
   9677                     if (BCM_FAILURE(rv)) {
   9678                         LOG_ERROR(BSL_LS_BCM_OAM,
   9679                                 (BSL_META_U(unit,
   9680                                             "OAM(unit %d) Error: EGR MP group table update "
   9681                                             "(EP=%d) -" " %s.\n"), unit, 
   9682                                  h_data_p->ep_id, bcm_errmsg(rv)));
   9683                         soc_mem_unlock(unit, EGR_MP_GROUPm);
   9684                         return (rv);
   9685                     }
   9686                 }
   9687                 /* Clear the counter, if any */
   9688                 rv = _bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index,
   9689                                                h_data_p, (void *)&egr_mp_group); 
   9690                 if (BCM_FAILURE(rv)) {
   9691                     LOG_ERROR(BSL_LS_BCM_OAM,
   9692                               (BSL_META_U(unit,
   9693                                           "OAM(unit %d) Error:EGR MP group tbl update(EP=%d)-"
   9694                                            " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9695                     soc_mem_unlock(unit, EGR_MP_GROUPm);
   9696                     return (rv);
   9697                 }
   9698             }
   9699         }
   9700         soc_mem_unlock(unit, EGR_MP_GROUPm);
   9701 
   9702         /* This is the last Rx endpoint in this OAM group. */
   9703         if ((0 == mdl) && (upmep)) {
   9704             ma_base_index = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
   9705                                                         MA_BASE_PTRf);
   9706             /* Return Rx indices to free pool. */
   9707             for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   9708                 rx_index[idx] = ma_base_index + idx;
   9709             }
   9710 
   9711             rv = shr_idxres_list_free_set(oc->egr_ma_idx_pool, 8,
   9712                                           (shr_idxres_element_t *) rx_index,
   9713                                           (shr_idxres_element_t *) &count);
   9714             if (BCM_FAILURE(rv) || (8 != count)) {
   9715                 LOG_ERROR(BSL_LS_BCM_OAM,
   9716                           (BSL_META_U(unit,
   9717                                       "OAM(unit %d) Error: Egr Rx index list free (EP=%d)"
   9718                                        " (count=%d).\n"), unit, h_data_p->ep_id, count));
   9719                 return (rv);
   9720             }
   9721         }
   9722     } else if (BCM_FAILURE(rv) && (oc->init)) {
   9723         /* We do not program passive bitmap for MIP. So dont throw error
   9724          * if you don't find an entry, since we might not have created 
   9725          * such an entry at all. */
   9726         if (!((mdl_field == MDL_BITMAP_PASSIVEf) &&
   9727                     (_BCM_OAM_EP_IS_MIP(h_data_p)))) {
   9728             LOG_ERROR(BSL_LS_BCM_OAM,
   9729                     (BSL_META_U(unit,
   9730                                 "OAM(unit %d) Error: LMEP table write (EP=%d) -"
   9731                                 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9732             return (rv);
   9733         }
   9734     }
   9735     return (BCM_E_NONE);
   9736 }
   9737 
   9738 /*
   9739  * Function:
   9740  *     _bcm_sb2_oam_local_endpoint_delete
   9741  * Purpose:
   9742  *     Delete a local endpoint.
   9743  * Parameters:
   9744  *     unit      - (IN) BCM device number
   9745  *     h_data_p  - (IN) Pointer to endpoint hash data
   9746  * Retruns:
   9747  *     BCM_E_XXX
   9748  */
   9749 STATIC int
   9750 _bcm_sb2_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
   9751 {
   9752     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   9753     lmep_entry_t       lmep_entry;     /* Local endpoint table entry.       */
   9754     int                rv;             /* Operation return status.          */
   9755     lmep_1_entry_t     lmep_1_entry;   /* LMEP_1 table entry.               */
   9756     soc_profile_mem_t  *opcode_control_profile; /* profile used -
   9757                                                         ingress or egress   */
   9758     soc_profile_mem_t  *dglp_profile;  /* dglp profile used -
   9759                                                         ingress or egress   */
   9760     ma_index_entry_t   ma_idx_entry;   /* MA_INDEX table entry buffer.      */
   9761     ma_index_entry_t   egr_ma_idx_entry;/* MA_INDEX table entry buffer.     */
   9762     void               *ma_idx_ptr;
   9763     soc_mem_t          ma_index_mem = 0;
   9764     uint8              active_mdl = 0;
   9765     int                ma_offset = 0;
   9766 
   9767     /* Lock already taken by the calling routine. */
   9768     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9769 
   9770     if (1 == h_data_p->local_tx_enabled) {
   9771 
   9772         /* Clear endpoint Tx config in hardware. */
   9773         sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   9774         sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t));
   9775         rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   9776                          &lmep_entry);
   9777 
   9778         if (BCM_FAILURE(rv)) {
   9779             LOG_ERROR(BSL_LS_BCM_OAM,
   9780                       (BSL_META_U(unit,
   9781                                   "OAM(unit %d) Error: LMEP table write (EP=%d)"
   9782                                    " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9783             return (rv);
   9784         }
   9785         rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   9786                          &lmep_1_entry);
   9787         if (BCM_FAILURE(rv)) {
   9788             LOG_ERROR(BSL_LS_BCM_OAM,
   9789                       (BSL_META_U(unit,
   9790                                   "OAM(unit %d) Error: LMEP_1 table write (EP=%d)"
   9791                                    " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9792             return (rv);
   9793         }
   9794 
   9795         /* Return ID back to free LMEP ID pool. */
   9796         BCM_IF_ERROR_RETURN
   9797             (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index));
   9798         
   9799     }
   9800 
   9801     if (1 == h_data_p->local_rx_enabled) {
   9802         /* Check whether up/down MEP */
   9803         if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9804             opcode_control_profile = &oc->egr_oam_opcode_control_profile;
   9805             dglp_profile = &oc->egr_oam_dglp_profile;
   9806             ma_index_mem = EGR_MA_INDEXm;
   9807             sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t));
   9808             ma_idx_ptr = &egr_ma_idx_entry;
   9809         } else {
   9810             opcode_control_profile = &oc->oam_opcode_control_profile;
   9811             dglp_profile = &oc->ing_oam_dglp_profile;
   9812             ma_index_mem = MA_INDEXm;
   9813             sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t));
   9814             ma_idx_ptr = &ma_idx_entry;
   9815         }
   9816 
   9817         /* Delete OAM opcode profile entry for this endpoint. */
   9818         rv = soc_profile_mem_delete(unit, opcode_control_profile,
   9819                 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index));
   9820         if (BCM_FAILURE(rv)) {
   9821             LOG_ERROR(BSL_LS_BCM_OAM,
   9822                       (BSL_META_U(unit,
   9823                                   "OAM(unit %d) Error: Profile table update error (idx=%d)"
   9824                                    "- %s.\n"), unit, h_data_p->profile_index, bcm_errmsg(rv)));
   9825             return (rv);
   9826         }
   9827         /* Delete DGLP  profile entry for this endpoint. */
   9828         if (h_data_p->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 
   9829             rv = soc_profile_mem_delete(unit, dglp_profile,
   9830                                         h_data_p->dglp1_profile_index);
   9831             if (BCM_FAILURE(rv)) {
   9832                 LOG_ERROR(BSL_LS_BCM_OAM,
   9833                           (BSL_META_U(unit,
   9834                                       "OAM(unit %d) Error: Profile table update "
   9835                                       "error (idx=%d)" "- %s.\n"), unit, 
   9836                            h_data_p->dglp1_profile_index, bcm_errmsg(rv)));
   9837                 return (rv);
   9838             }
   9839         }
   9840         if (h_data_p->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 
   9841             rv = soc_profile_mem_delete(unit, dglp_profile,
   9842                                         h_data_p->dglp2_profile_index);
   9843             if (BCM_FAILURE(rv)) {
   9844                 LOG_ERROR(BSL_LS_BCM_OAM,
   9845                           (BSL_META_U(unit,
   9846                                       "OAM(unit %d) Error: Profile table update "
   9847                                       "error (idx=%d)" "- %s.\n"), unit, 
   9848                            h_data_p->dglp2_profile_index, bcm_errmsg(rv)));
   9849                 return (rv);
   9850             }
   9851         }
   9852         /* Get MA_INDEX offset  */
   9853         rv = _bcm_sb2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset);
   9854         if (BCM_FAILURE(rv)) {
   9855             LOG_ERROR(BSL_LS_BCM_OAM,
   9856                       (BSL_META_U(unit,
   9857                                   "OAM(unit %d) Error: MA INDEX table offset get failed EP=%d"
   9858                                    "  %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9859             return (rv);
   9860         }
   9861 
   9862         h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
   9863 
   9864         /* Delete MA INDEX entry */
   9865         rv = _bcm_sb2_oam_ma_index_entry_set(unit, h_data_p, 
   9866                                          ma_index_mem, ma_idx_ptr, 1);
   9867         if (BCM_FAILURE(rv)) {
   9868             LOG_ERROR(BSL_LS_BCM_OAM,
   9869                       (BSL_META_U(unit,
   9870                                   "OAM(unit %d) Error: MA INDEX table delete failed EP=%d"
   9871                                    "  %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9872             return (rv);
   9873         }
   9874         if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) {
   9875             rv = _bcm_sb2_port_domain_mdl_bitmap_update(unit, h_data_p);
   9876             if (BCM_FAILURE(rv)) {
   9877                 LOG_ERROR(BSL_LS_BCM_OAM,
   9878                           (BSL_META_U(unit,
   9879                                       "OAM(unit %d) Error: port OAM MDL update failed EP=%d"
   9880                                        "  %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9881                 return (rv);
   9882             }
   9883         } else if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9884             rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 
   9885                                                          &active_mdl);
   9886             if (BCM_FAILURE(rv)) {
   9887                 LOG_ERROR(BSL_LS_BCM_OAM,
   9888                           (BSL_META_U(unit,
   9889                                       "OAM(unit %d) Error: Egr MP Group  update (EP=%d) -"
   9890                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9891                 return (rv);
   9892             }
   9893 
   9894             /* Update Ingress MP group table(MP_GROUP_ENTRY) */
   9895             rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, h_data_p, &active_mdl);
   9896             if (BCM_FAILURE(rv)) {
   9897                 LOG_ERROR(BSL_LS_BCM_OAM,
   9898                           (BSL_META_U(unit,
   9899                                       "OAM(unit %d) Error: LMEP view update (EP=%d) -"
   9900                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9901                 return (rv);
   9902             }
   9903         } else {
   9904             /* Update Ingress MP group table(MP_GROUP_ENTRY) */
   9905             rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, h_data_p, &active_mdl);
   9906             if (BCM_FAILURE(rv)) {
   9907                 LOG_ERROR(BSL_LS_BCM_OAM,
   9908                           (BSL_META_U(unit,
   9909                                       "OAM(unit %d) Error: LMEP view update (EP=%d) -"
   9910                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9911                 return (rv);
   9912 
   9913             }
   9914             rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, h_data_p,
   9915                                                          &active_mdl);
   9916             if (BCM_FAILURE(rv)) {
   9917                 LOG_ERROR(BSL_LS_BCM_OAM,
   9918                           (BSL_META_U(unit,
   9919                                       "OAM(unit %d) Error: Egr MP Group  update (EP=%d) -"
   9920                                        " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
   9921                 return (rv);
   9922             }
   9923         } 
   9924     }
   9925     return (BCM_E_NONE);
   9926 }
   9927 
   9928 
   9929 /*
   9930  * Function:
   9931  *     _bcm_sb2_oam_port_table_key_update1
   9932  * Purpose:
   9933  *     Update OAM_KEY1 and OAM_KEY2 in port table 
   9934  * Parameters:
   9935  *     unit          - (IN) BCM device number
   9936  *     mem           - (IN) PORT_TAB/EGR_PORT
   9937  *     pp_port       - (IN) PP port
   9938  *     h_data_p      - (IN/OUT) Pointer to endpoint hash data 
   9939  * Returns:
   9940  *      BCM_E_XXX
   9941  */
   9942 int 
   9943  _bcm_sb2_oam_port_table_key_update1(int unit, soc_mem_t mem, int pp_port,
   9944                                     _bcm_oam_hash_data_t *h_data_p)
   9945 {
   9946     _bcm_oam_control_t   *oc;            /* Pointer to OAM control structure. */
   9947     int                  rv = BCM_E_NONE;  /* Operation return status.        */
   9948     port_tab_entry_t     port_entry;
   9949     egr_port_entry_t egr_port_entry;
   9950     int                  key_type = 0;
   9951     int                  oam_key1 = 0;
   9952     int                  oam_key2 = 0;
   9953     void                 *port_entry_ptr;
   9954     uint16               *key1_ref_count = NULL;
   9955     uint16               *key2_ref_count = NULL;
   9956 
   9957     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
   9958 
   9959 
   9960     if(MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 
   9961        !MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
   9962         /* Not expected to happen. Should be called only 
   9963          * for mpls section 
   9964          */
   9965         return BCM_E_INTERNAL;
   9966     }
   9967 
   9968     if (BHH_EP_TYPE(h_data_p) &&
   9969         !BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
   9970         /* Not expected to happen. Should be called only 
   9971          * for mpls section 
   9972          */
   9973         return BCM_E_INTERNAL;
   9974     }
   9975 
   9976     /* Set the search key type. */
   9977     _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags,
   9978                                             h_data_p->vlan, 
   9979                                             h_data_p->inner_vlan, h_data_p->int_flags,
   9980                                             &key_type);
   9981 
   9982     if (mem == PORT_TABm) {
   9983         port_entry_ptr = &port_entry;
   9984         key1_ref_count = &oc->oam_key1_ref_count[0];
   9985         key2_ref_count = &oc->oam_key2_ref_count[0];
   9986     } else {
   9987         port_entry_ptr = &egr_port_entry;
   9988         key1_ref_count = &oc->egr_oam_key1_ref_count[0];
   9989         key2_ref_count = &oc->egr_oam_key2_ref_count[0];
   9990     }    
   9991 
   9992     /* 
   9993     We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 
   9994     EGR_PORT_TABLE based on the key_type of OAM */
   9995 
   9996     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port, port_entry_ptr);
   9997     if (BCM_FAILURE(rv)) {
   9998         LOG_ERROR(BSL_LS_BCM_OAM,
   9999                   (BSL_META_U(unit,
  10000                               "OAM(unit %d) Error: Port table read - %s.\n"),
  10001                    unit, bcm_errmsg(rv)));
  10002         return (rv);
  10003     }
  10004 
  10005     if(!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p) &&
  10006        !BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  10007         oam_key1 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY1f);
  10008         oam_key2 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY2f);
  10009     }
  10010 
  10011     if ((key_type != _BCM_OAM_DOMAIN_PORT)
  10012         && (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p))
  10013         && (!BHH_EP_MPLS_SECTION_TYPE(h_data_p))) {
  10014          if ((oam_key1 > 0) && (oam_key2 > 0)) {
  10015              if ((oam_key1 == key_type) || (oam_key2 == key_type)) {
  10016              } else {
  10017                  LOG_ERROR(BSL_LS_BCM_OAM,
  10018                            (BSL_META_U(unit,
  10019                                        "OAM(unit %d) Error: Invalid OAM domain to resolve "
  10020                                        "(EP=%d) - %s.\n"),
  10021                             unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10022                  return (BCM_E_PARAM);
  10023              }
  10024          }
  10025      }
  10026  
  10027     if (key_type != _BCM_OAM_DOMAIN_PORT) {
  10028         if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) ||
  10029             (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) {
  10030             soc_mem_field32_set(unit, mem, port_entry_ptr, 
  10031                                 MPLS_SECTION_OAM_KEYf, key_type);
  10032             /* Enable section OAM for this port */
  10033             if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  10034                 soc_mem_field32_set(unit, mem, port_entry_ptr,
  10035                         MPLS_SECTION_OAM_ENABLEf, 
  10036                         _BCM_SB2_MPLS_OAM_ENABLE_BHH);
  10037             } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
  10038                 soc_mem_field32_set(unit, mem, port_entry_ptr,
  10039                         MPLS_SECTION_OAM_ENABLEf, 
  10040                         _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM);
  10041             }
  10042         } else {
  10043             if ((oam_key1 == 0) && (oam_key2 == 0)) {
  10044                 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, key_type);
  10045                 key1_ref_count[pp_port]++;  
  10046             } else if ((oam_key1 != key_type) && (oam_key2 == 0)) {
  10047                 if (key_type > oam_key1) {
  10048                     soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY2f, 
  10049                             key_type);
  10050                     key2_ref_count[pp_port]++;  
  10051                 } else {
  10052                     key2_ref_count[pp_port] = key1_ref_count[pp_port];  
  10053                     soc_mem_field32_set(unit, mem, port_entry_ptr, 
  10054                             OAM_KEY1f, key_type);
  10055                     key1_ref_count[pp_port] = 1;
  10056                     soc_mem_field32_set(unit, mem, port_entry_ptr,
  10057                             OAM_KEY2f, oam_key1);
  10058                 }
  10059             } else if ((oam_key2 != key_type) && (oam_key1 == 0)) {
  10060                 if (key_type < oam_key2) {
  10061                     soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, 
  10062                             key_type);
  10063                     key1_ref_count[pp_port]++;
  10064                 } else {
  10065                     key1_ref_count[pp_port] = key2_ref_count[pp_port];  
  10066                     soc_mem_field32_set(unit, mem, port_entry_ptr, 
  10067                             OAM_KEY1f, oam_key2);
  10068                     soc_mem_field32_set(unit, mem, port_entry_ptr,
  10069                             OAM_KEY2f, key_type);
  10070                     key2_ref_count[pp_port] = 1;
  10071                 }
  10072             } else if (oam_key1 == key_type) {
  10073                 key1_ref_count[pp_port]++;
  10074             } else if (oam_key2 == key_type) {
  10075                 key2_ref_count[pp_port]++ ;
  10076             }
  10077         }
  10078         if (SOC_WARM_BOOT(unit)) {
  10079             return rv;
  10080         }
  10081         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, pp_port, port_entry_ptr);
  10082         if (BCM_FAILURE(rv)) {
  10083             LOG_ERROR(BSL_LS_BCM_OAM,
  10084                       (BSL_META_U(unit,
  10085                                   "OAM(unit %d) Error: Port table update failed  "
  10086                                   "%s.\n"), unit, bcm_errmsg(rv)));
  10087             return (rv);
  10088         }
  10089     }
  10090     return rv;
  10091 }
  10092 
  10093 /*
  10094  * Function:
  10095  *     _bcm_sb2_oam_port_table_key_update
  10096  * Purpose:
  10097  *     Update port table OAM key fields. 
  10098  * Parameters:
  10099  *     unit          - (IN) BCM device number
  10100  *     mem           - (IN) PORT_TAB/EGR_PORT
  10101  *     h_data_p      - (IN/OUT) Pointer to endpoint hash data
  10102  * Returns:
  10103  *      BCM_E_XXX
  10104  */
  10105 int 
  10106  _bcm_sb2_oam_port_table_key_update(int unit, soc_mem_t mem, 
  10107                                     _bcm_oam_hash_data_t *h_data_p)
  10108 {
  10109     int                  rv = BCM_E_NONE;      /* Operation return status. */
  10110     bcm_port_t           *member_array = NULL; /* Trunk member port array. */
  10111     bcm_module_t         module_id;            /* Module ID                */
  10112     bcm_port_t           pp_port = 0;
  10113     int                  member_count = 0;
  10114     int                  local_member_count = 0;
  10115     int                  i = 0; 
  10116 
  10117     if ((h_data_p->trunk_id != BCM_TRUNK_INVALID)) {
  10118         /* Get count of ports in this trunk. */
  10119         BCM_IF_ERROR_RETURN
  10120             (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
  10121                                NULL, 0, NULL, &member_count));
  10122         if (0 == member_count) {
  10123             /* No members have been added to the trunk group yet */
  10124             LOG_ERROR(BSL_LS_BCM_OAM,
  10125                       (BSL_META_U(unit,
  10126                                   "OAM(unit %d) Error: No local members have been added to "
  10127                                   "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv)));
  10128             return BCM_E_PARAM;
  10129         }
  10130 
  10131         _BCM_OAM_ALLOC(member_array, bcm_port_t,
  10132                        sizeof(bcm_port_t) * member_count, "Trunk info");
  10133         if (NULL == member_array) {
  10134             return (BCM_E_MEMORY);
  10135         
  10136         }
  10137 
  10138         /* Get a member of the trunk belonging to this module */
  10139         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
  10140                                         h_data_p->trunk_id, 
  10141                                         member_count, member_array,
  10142                                         &local_member_count))) {
  10143             if (local_member_count > 0) {
  10144                 for(i = 0; i < local_member_count; i++) {
  10145                     rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
  10146                                                          &module_id, &pp_port);
  10147                     if (BCM_FAILURE(rv)) {
  10148                         sal_free(member_array);
  10149                         return (rv);
  10150                     }
  10151                     rv = _bcm_sb2_oam_port_table_key_update1(unit, mem, 
  10152                                                      pp_port, h_data_p);
  10153                     if (BCM_FAILURE(rv)) {
  10154                         sal_free(member_array);
  10155                         return (rv);
  10156                     }
  10157                 }
  10158 
  10159             }
  10160         }
  10161         sal_free(member_array);
  10162     } else {
  10163         if (mem == PORT_TABm) {
  10164             if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) {
  10165                 /* Program OAM_KEY1 in physical and subport port table entries,
  10166                  * src_pp_port refers to WAR PP port
  10167                  * dst_pp_port refers to PP port on which UP MEP is configured */
  10168                 rv = _bcm_sb2_oam_port_table_key_update1(unit, mem,
  10169                         h_data_p->dst_pp_port, h_data_p);
  10170                 if (BCM_FAILURE(rv)) {
  10171                     return (rv);
  10172                 }
  10173             }
  10174             pp_port = h_data_p->src_pp_port;
  10175         } else {
  10176             pp_port = h_data_p->dst_pp_port;
  10177         }
  10178         rv = _bcm_sb2_oam_port_table_key_update1(unit, mem, pp_port, h_data_p);
  10179     }
  10180     return rv;
  10181 }
  10182 
  10183 /*
  10184  * Function:
  10185  *     _bcm_sb2_oam_decrement_key_ref_count1
  10186  * Purpose:
  10187  *     Decrement PORT tab key1/key2 usage ref count.
  10188  * Parameters:
  10189  *     unit        - (IN) BCM device number
  10190  *     src_pp_port - (IN) Source PP port
  10191  *     dst_pp_port - (IN) destination  PP port
  10192  *     h_data_p    - (IN) Endpoint hash data.
  10193  * Retruns:
  10194  *     BCM_E_XXX
  10195  */
  10196  int 
  10197 _bcm_sb2_oam_decrement_key_ref_count1(int unit, uint32 src_pp_port, 
  10198                                       uint32 dst_pp_port,
  10199                                       _bcm_oam_hash_data_t *h_data_p)
  10200 {
  10201     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  10202     int                  rv = BCM_E_NONE;  /* Operation return status.    */
  10203     port_tab_entry_t     port_entry;
  10204     egr_port_entry_t egr_port_entry;
  10205     int                  key_type = 0;
  10206     uint32               oam_key1 = 0;
  10207     uint32               oam_key2 = 0;
  10208     int                  update_entry = 0;
  10209 
  10210     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  10211     /* Set the search key type. */
  10212     _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags,
  10213                                             h_data_p->vlan, 
  10214                                             h_data_p->inner_vlan, h_data_p->int_flags, 
  10215                                             &key_type);
  10216 
  10217     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry);
  10218     if (BCM_FAILURE(rv)) {
  10219          LOG_ERROR(BSL_LS_BCM_OAM,
  10220                    (BSL_META_U(unit,
  10221                                "OAM(unit %d) Error: Port table entry read failed  - %s.\n"),
  10222                     unit, bcm_errmsg(rv)));
  10223         return (rv);
  10224     }
  10225     rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 
  10226                       dst_pp_port, &egr_port_entry);
  10227     if (BCM_FAILURE(rv)) {
  10228          LOG_ERROR(BSL_LS_BCM_OAM,
  10229                    (BSL_META_U(unit,
  10230                                "OAM(unit %d) Error: Port table entry read failed  - %s.\n"),
  10231                     unit, bcm_errmsg(rv)));
  10232         return (rv);
  10233     }
  10234 
  10235     oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 
  10236     oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 
  10237    
  10238     if (key_type != _BCM_OAM_DOMAIN_PORT) {
  10239         if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) ||
  10240                 (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) {
  10241             /* Update PORT table */
  10242             soc_PORT_TABm_field32_set(unit, &port_entry, 
  10243                     MPLS_SECTION_OAM_KEYf, 0);
  10244             /* Disable section OAM for this port */
  10245             if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  10246                 soc_PORT_TABm_field32_set(unit, &port_entry,
  10247                         MPLS_SECTION_OAM_ENABLEf, 
  10248                         0);
  10249             } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
  10250                 soc_PORT_TABm_field32_set(unit, &port_entry,
  10251                         MPLS_SECTION_OAM_ENABLEf, 
  10252                         0);
  10253             }
  10254             BCM_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 
  10255                     src_pp_port, &port_entry));
  10256 
  10257             /* Update EGR_PORT table */
  10258             soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 
  10259                     MPLS_SECTION_OAM_KEYf, 0);
  10260             /* Disable section OAM for this port */
  10261             if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  10262                 soc_EGR_PORTm_field32_set(unit, &egr_port_entry,
  10263                         MPLS_SECTION_OAM_ENABLEf, 
  10264                         0);
  10265             } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
  10266                 soc_EGR_PORTm_field32_set(unit, &egr_port_entry,
  10267                         MPLS_SECTION_OAM_ENABLEf, 
  10268                         0);
  10269             }
  10270             BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
  10271                     dst_pp_port, &egr_port_entry));
  10272         } else {
  10273             if (key_type == oam_key1) {
  10274                 oc->oam_key1_ref_count[src_pp_port]--;
  10275                 if (oc->oam_key1_ref_count[src_pp_port] == 0) {
  10276                     soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0);
  10277                     update_entry = 1;
  10278                 }
  10279             } else if (key_type == oam_key2) {
  10280                 oc->oam_key2_ref_count[src_pp_port]--;
  10281                 if (oc->oam_key2_ref_count[src_pp_port] == 0) {
  10282                     soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0);
  10283                     update_entry = 1;
  10284                 }
  10285             }
  10286             if (update_entry) {
  10287                 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 
  10288                         src_pp_port, &port_entry);
  10289                 update_entry = 0;
  10290             }
  10291 
  10292             oam_key1 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY1f); 
  10293             oam_key2 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY2f); 
  10294 
  10295             if (key_type == oam_key1) {
  10296                 oc->egr_oam_key1_ref_count[dst_pp_port]--;
  10297                 if (oc->egr_oam_key1_ref_count[dst_pp_port] == 0) {
  10298                     soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY1f, 0);
  10299                     update_entry = 1;
  10300                 }
  10301             } else if (key_type == oam_key2) {
  10302                 oc->egr_oam_key2_ref_count[dst_pp_port]--;
  10303                 if (oc->egr_oam_key2_ref_count[dst_pp_port] == 0) {
  10304                     soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY2f, 0);
  10305                     update_entry = 1;
  10306                 }
  10307             }
  10308             if (update_entry) {
  10309                 rv = soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
  10310                         dst_pp_port, &egr_port_entry);
  10311                 update_entry = 0;
  10312             }
  10313         }
  10314     }
  10315     return rv;
  10316 }
  10317 
  10318 /*
  10319  * Function:
  10320  *     _bcm_sb2_oam_decrement_pp_port_key_ref_count1
  10321  * Purpose:
  10322  *     Decrement PORT tab key1/key2 usage ref count.
  10323  * Parameters:
  10324  *     unit        - (IN) BCM device number
  10325  *     src_pp_port - (IN) Source PP port
  10326  *     h_data_p    - (IN) Endpoint hash data.
  10327  * Retruns:
  10328  *     BCM_E_XXX
  10329  */
  10330 STATIC int
  10331 _bcm_sb2_oam_decrement_pp_port_key_ref_count1(int unit, uint32 src_pp_port,
  10332                                       _bcm_oam_hash_data_t *h_data_p)
  10333 {
  10334     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  10335     int                  rv = BCM_E_NONE;  /* Operation return status.    */
  10336     port_tab_entry_t     port_entry;
  10337     int                  key_type = 0;
  10338     uint32               oam_key1 = 0;
  10339     uint32               oam_key2 = 0;
  10340     int                  update_entry = 0;
  10341 
  10342     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  10343     /* Set the search key type. */
  10344     _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags,
  10345                                             h_data_p->vlan,
  10346                                             h_data_p->inner_vlan, h_data_p->int_flags,
  10347                                             &key_type);
  10348 
  10349     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry);
  10350     if (BCM_FAILURE(rv)) {
  10351          LOG_ERROR(BSL_LS_BCM_OAM,
  10352                    (BSL_META_U(unit,
  10353                                "OAM(unit %d) Error: Port table entry read failed  - %s.\n"),
  10354                     unit, bcm_errmsg(rv)));
  10355         return (rv);
  10356     }
  10357 
  10358     oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f);
  10359     oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f);
  10360 
  10361     if (key_type != _BCM_OAM_DOMAIN_PORT) {
  10362         if (key_type == oam_key1) {
  10363             oc->oam_key1_ref_count[src_pp_port]--;
  10364             if (oc->oam_key1_ref_count[src_pp_port] == 0) {
  10365                 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0);
  10366                 update_entry = 1;
  10367             }
  10368         } else if (key_type == oam_key2) {
  10369             oc->oam_key2_ref_count[src_pp_port]--;
  10370             if (oc->oam_key2_ref_count[src_pp_port] == 0) {
  10371                 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0);
  10372                 update_entry = 1;
  10373             }
  10374         }
  10375         if (update_entry) {
  10376             rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
  10377                     src_pp_port, &port_entry);
  10378             update_entry = 0;
  10379         }
  10380     }
  10381     return rv;
  10382 }
  10383 
  10384 /*
  10385  * Function:
  10386  *     _bcm_sb2_oam_decrement_key_ref_count
  10387  * Purpose:
  10388  *     Decrement PORT tab key1/key2 usage ref count.
  10389  * Parameters:
  10390  *     unit   - (IN) BCM device number
  10391  *     h_data_p - (IN) Endpoint hash data.
  10392  * Retruns:
  10393  *     BCM_E_XXX
  10394  */
  10395  int 
  10396 _bcm_sb2_oam_decrement_key_ref_count(int unit, 
  10397                                      _bcm_oam_hash_data_t *h_data_p)
  10398 {
  10399     int                  rv = BCM_E_NONE;      /* Operation return status.    */
  10400     bcm_port_t           *member_array = NULL; /* Trunk member port array.    */
  10401     bcm_module_t         module_id;            /* Module ID                   */
  10402     bcm_port_t           src_pp_port = 0;
  10403     int                  member_count = 0;
  10404     int                  local_member_count = 0;
  10405     int                  i = 0; 
  10406 
  10407     if (h_data_p->trunk_id != BCM_TRUNK_INVALID) {
  10408         /* Get count of ports in this trunk. */
  10409         BCM_IF_ERROR_RETURN
  10410             (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 
  10411                                NULL, 0, NULL, &member_count));
  10412         if (0 == member_count) {
  10413             /* No members have been added to the trunk group yet */
  10414             LOG_ERROR(BSL_LS_BCM_OAM,
  10415                       (BSL_META_U(unit,
  10416                                   "OAM(unit %d) Error: No local members have been added to "
  10417                                   "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv)));
  10418             return BCM_E_PARAM;
  10419         }
  10420 
  10421         _BCM_OAM_ALLOC(member_array, bcm_port_t,
  10422                        sizeof(bcm_port_t) * member_count, "Trunk info");
  10423         if (NULL == member_array) {
  10424             return (BCM_E_MEMORY);
  10425         
  10426         }
  10427 
  10428         /* Get a member of the trunk belonging to this module */
  10429         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 
  10430                                         h_data_p->trunk_id, 
  10431                                         member_count, member_array,
  10432                                         &local_member_count))) {
  10433             if (local_member_count > 0) {
  10434                 for(i = 0; i < local_member_count; i++) {
  10435                     rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i],
  10436                                                      &module_id, &src_pp_port);
  10437                     if (BCM_FAILURE(rv)) {
  10438                         sal_free(member_array);
  10439                         return (rv);
  10440                     }
  10441                     rv = _bcm_sb2_oam_decrement_key_ref_count1(unit, src_pp_port,
  10442                                                h_data_p->dst_pp_port, h_data_p);
  10443                     if (BCM_FAILURE(rv)) {
  10444                         sal_free(member_array);
  10445                         return (rv);
  10446                     }
  10447                 }
  10448 
  10449             }
  10450         }
  10451         sal_free(member_array);
  10452     } else {
  10453         if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) {
  10454             /* Reset OAM_KEY1 in physical and subport port table entries,
  10455              * src_pp_port refers to WAR PP port
  10456              * dst_pp_port refers to PP port on which UP MEP is configured */
  10457             rv = _bcm_sb2_oam_decrement_pp_port_key_ref_count1(unit,
  10458                     h_data_p->dst_pp_port, h_data_p);
  10459             if (BCM_FAILURE(rv)) {
  10460                 return (rv);
  10461             }
  10462         }
  10463 
  10464         rv = _bcm_sb2_oam_decrement_key_ref_count1(unit, h_data_p->src_pp_port,
  10465                                               h_data_p->dst_pp_port, h_data_p);
  10466     }
  10467     return rv;
  10468 }
  10469 
  10470 
  10471      
  10472 /*
  10473  * Function: _bcm_sb2_oam_tpid_decrement_ref_count
  10474  *     
  10475  * Purpose:
  10476  *     Decrement TPID reference count.
  10477  * Parameters:
  10478  *     unit      - (IN) BCM device number
  10479  *     h_data_p  - (IN) Endpoint hash data.
  10480  * Retruns:
  10481  *     BCM_E_XXX
  10482  */
  10483 STATIC int 
  10484 _bcm_sb2_oam_tpid_decrement_ref_count(int unit, _bcm_oam_hash_data_t *h_data_p)
  10485 {
  10486     int    rv = BCM_E_NONE;
  10487     uint32 tag_type = 0;
  10488 
  10489     /* If local CCM tx generation was not enabled, then the tpid entries
  10490      * would not have been set. So do not try to delete them even though the
  10491      * h_data_p->outer/inner/subport_tpid has a non zero value */
  10492     if (!h_data_p->local_tx_enabled) {
  10493         return BCM_E_NONE;
  10494     }
  10495 
  10496     if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) {
  10497         if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
  10498             tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN;
  10499         } else if (h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
  10500             tag_type =_BCM_OAM_DOMAIN_CVLAN;
  10501         } else if (h_data_p->vlan > 0) {
  10502             tag_type =_BCM_OAM_DOMAIN_SVLAN;
  10503         }
  10504     } else {
  10505         tag_type =h_data_p->oam_domain;
  10506     }
  10507 
  10508     /* if S or S+C vlan - set outer tpid index */
  10509     if (((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 
  10510         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)
  10511         ) &&
  10512         (h_data_p->outer_tpid > 0)) { 
  10513         if (BCM_SUCCESS(rv)) {
  10514             rv = _bcm_sb2_tpid_entry_delete(unit,
  10515                                            h_data_p->outer_tpid_profile_index,
  10516                                            BCM_OAM_TPID_TYPE_OUTER);
  10517             if (BCM_FAILURE(rv)) {
  10518                 LOG_ERROR(BSL_LS_BCM_OAM,
  10519                           (BSL_META_U(unit,
  10520                                       "OAM(unit %d) Error: L3 entry config failed in Outer TPID "
  10521                                       "decrement ref count""  %s.\n"), unit, bcm_errmsg(rv)));
  10522                 return (rv);
  10523             }
  10524         }
  10525     }
  10526     if (((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 
  10527         (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)
  10528         ) &&
  10529         (h_data_p->inner_tpid > 0)) { 
  10530         /* C or S+C */
  10531         if (BCM_SUCCESS(rv)) {
  10532             rv = _bcm_sb2_tpid_entry_delete(unit, 
  10533                                            h_data_p->inner_tpid_profile_index,
  10534                                            BCM_OAM_TPID_TYPE_INNER);
  10535             if (BCM_FAILURE(rv)) {
  10536                 LOG_ERROR(BSL_LS_BCM_OAM,
  10537                           (BSL_META_U(unit,
  10538                                       "OAM(unit %d) Error: L3 entry config failed in Inner TPID "
  10539                                       "decrement ref count""  %s.\n"), unit, bcm_errmsg(rv)));
  10540                 return (rv);
  10541             }
  10542         }
  10543     }
  10544     if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) &&
  10545               (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport)) && 
  10546               (h_data_p->subport_tpid > 0)) {
  10547         /* CoE port */
  10548         if (BCM_SUCCESS(rv)) {
  10549             rv = _bcm_sb2_tpid_entry_delete(unit, 
  10550                                            h_data_p->subport_tpid_profile_index,
  10551                                            BCM_OAM_TPID_TYPE_SUBPORT);
  10552             if (BCM_FAILURE(rv)) {
  10553                 LOG_ERROR(BSL_LS_BCM_OAM,
  10554                           (BSL_META_U(unit,
  10555                                       "OAM(unit %d) Error: L3 entry config failed in Subport TPID  "
  10556                                       "decrement ref count""  %s.\n"), unit, bcm_errmsg(rv)));
  10557                 return (rv);
  10558             }
  10559         }
  10560     }
  10561     return rv;
  10562 }
  10563 
  10564 /*
  10565  * Function:
  10566  *     _bcm_sb2_oam_endpoint_destroy
  10567  * Purpose:
  10568  *     Delete an endpoint and free all its allocated resources.
  10569  * Parameters:
  10570  *     unit   - (IN) BCM device number
  10571  *     ep_id  - (IN) Endpoint ID value.
  10572  * Retruns:
  10573  *     BCM_E_XXX
  10574  */
  10575 STATIC int
  10576 _bcm_sb2_oam_endpoint_destroy(int unit,
  10577                               bcm_oam_endpoint_t ep_id)
  10578 {
  10579     _bcm_oam_control_t      *oc;        /* Pointer to OAM control structure. */
  10580     _bcm_oam_hash_data_t    *h_data_p;  /* Pointer to endpoint data.         */
  10581     _bcm_oam_hash_key_t     hash_key;   /* Hash key buffer for lookup.       */
  10582     bcm_oam_endpoint_info_t ep_info;    /* Endpoint information.             */
  10583     _bcm_oam_hash_data_t    h_data;     /* Pointer to endpoint data.         */
  10584     int                     rv;         /* Operation return status.          */
  10585 #if defined(INCLUDE_BHH)
  10586     uint16 reply_len;
  10587     bcm_oam_endpoint_t bhh_pool_ep_id;
  10588 #endif
  10589 
  10590     /* Lock already taken by the calling routine. */
  10591     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  10592 
  10593     /* Get the hash data pointer. */
  10594     h_data_p = &oc->oam_hash_data[ep_id];
  10595     if(0 == h_data_p->in_use){
  10596         return BCM_E_NOT_FOUND; 
  10597     } 
  10598     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  10599     if (BCM_FAILURE(rv)) {
  10600         LOG_ERROR(BSL_LS_BCM_OAM,
  10601                 (BSL_META_U(unit,
  10602                             "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  10603                             " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  10604         return (rv);
  10605     }
  10606 #if defined(INCLUDE_MPLS_LM_DM)
  10607     /* If endpoint is MPLS_LM_DM type and loss/Delay is enabled on the same,
  10608        Free the UKernel session first */
  10609     if (!SOC_WARM_BOOT(unit)) {
  10610         if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  10611             if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) {
  10612                 _bcm_sb2_mpls_lm_dm_loss_delete(unit, h_data_p);
  10613             }
  10614             if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) {
  10615                 _bcm_sb2_mpls_lm_dm_delay_delete(unit, h_data_p);
  10616             }
  10617         }
  10618     }
  10619 #endif
  10620 
  10621 #if defined(INCLUDE_ETH_LM_DM)
  10622     /* If endpoint is MPLS_LM_DM type and loss/Delay is enabled on the same,
  10623        Free the UKernel session first */
  10624     if (!SOC_WARM_BOOT(unit)) {
  10625         if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  10626             if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET) {
  10627                 _bcm_sb2_eth_lm_dm_loss_delete(unit, oc, h_data_p);
  10628             }
  10629             if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET) {
  10630                 _bcm_sb2_eth_lm_dm_delay_delete(unit, oc, h_data_p);
  10631             }
  10632         }
  10633     }
  10634 #endif
  10635 
  10636     /* Calling it commonly for MPLS LM/DM and BHH endpoints */
  10637 
  10638     if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) || 
  10639         (h_data_p->type == bcmOAMEndpointTypeBHHMPLS)) {
  10640         /* For rx disable the mpls oam for the label. */
  10641 
  10642         /* First check if the label is in l3 tunnel table and disable
  10643            MPLS OAM if true.  */
  10644         rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit,
  10645                 h_data_p, 0);
  10646         if (rv == BCM_E_NOT_FOUND) {
  10647             /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 
  10648                table */
  10649             rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit,
  10650                     h_data_p, 0);
  10651             /* This is called during de-init. MPLS module de-init happens before
  10652              * OAM de-init. So if it is not found, do not return error.
  10653              */
  10654             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  10655                 LOG_ERROR(BSL_LS_BCM_OAM,
  10656                         (BSL_META_U(unit,
  10657                                     "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"),
  10658                          unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10659                 return (rv);
  10660             }
  10661         } else if (rv != BCM_E_NONE) {
  10662             LOG_ERROR(BSL_LS_BCM_OAM,
  10663                     (BSL_META_U(unit,
  10664                                 "OAM(unit %d) Error: L3 tunnel table update failed (EP=%d) - %s.\n"),
  10665                      unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10666             return (rv);
  10667         }
  10668         /* For tx disable the mpls oam for the egress intf.
  10669            and write the mepid in egr_l3_next_hop table */
  10670         rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit,
  10671                 h_data_p, 0);
  10672         if (BCM_FAILURE(rv)) {
  10673             LOG_ERROR(BSL_LS_BCM_OAM,
  10674                     (BSL_META_U(unit,
  10675                                 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"),
  10676                      unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10677             return (rv);
  10678         }
  10679     } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) {
  10680         rv = _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(unit, 
  10681                 h_data_p, 0);
  10682         /* This is called during de-init. MPLS module de-init happens before
  10683          * OAM de-init. So if it is not found, do not return error.
  10684          */
  10685         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  10686             LOG_ERROR(BSL_LS_BCM_OAM,
  10687                     (BSL_META_U(unit,
  10688                                 "OAM(unit %d) Error: SVP table update failed (EP=%d) - %s.\n"),
  10689                      unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10690             return (rv);
  10691         }
  10692         /* For tx disable the mpls oam for the egress dvp.
  10693          */
  10694         rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, h_data_p, 0);
  10695         if (BCM_FAILURE(rv)) {
  10696             LOG_ERROR(BSL_LS_BCM_OAM,
  10697                     (BSL_META_U(unit,
  10698                                 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"),
  10699                      unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10700             return (rv);
  10701         }
  10702     } else if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  10703         rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit,
  10704                 h_data_p, 0);
  10705         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  10706             LOG_ERROR(BSL_LS_BCM_OAM,
  10707                     (BSL_META_U(unit,
  10708                                 "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"),
  10709                     unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10710             return (rv);
  10711         }
  10712         /* For tx disable the mpls oam for the egress dvp.
  10713          */
  10714         rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, h_data_p, 0);
  10715         if (BCM_FAILURE(rv)) {
  10716             LOG_ERROR(BSL_LS_BCM_OAM,
  10717                     (BSL_META_U(unit,
  10718                                 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"),
  10719                      unit, h_data_p->ep_id, bcm_errmsg(rv)));
  10720             return (rv);
  10721         }
  10722     }
  10723     if(bcmOAMEndpointTypeEthernet == h_data_p->type ||
  10724        (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)))
  10725     {
  10726 
  10727     if ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) &&
  10728         (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) {
  10729         BCM_IF_ERROR_RETURN
  10730             (_bcm_sb2_oam_remote_endpoint_delete(unit, h_data_p));
  10731 
  10732     } else {
  10733         BCM_IF_ERROR_RETURN
  10734             (_bcm_sb2_oam_local_endpoint_delete(unit, h_data_p));
  10735         if (bcmOAMEndpointTypeEthernet == h_data_p->type) {
  10736             /* decrement TPID ref count */
  10737             BCM_IF_ERROR_RETURN
  10738                 (_bcm_sb2_oam_tpid_decrement_ref_count(unit, h_data_p));
  10739         }
  10740     }
  10741 
  10742     /* Remove endpoint for group's endpoint list. */
  10743     rv = _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index,
  10744                                        h_data_p->ep_id);
  10745     if (BCM_FAILURE(rv)) {
  10746         LOG_ERROR(BSL_LS_BCM_OAM,
  10747                   (BSL_META_U(unit,
  10748                               "OAM(unit %d) Error: Remove from group list (EP=%d) -"
  10749                                " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  10750         return (rv);
  10751     }
  10752 
  10753     /* Return ID back to free MEP ID pool.*/
  10754     BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id));
  10755 
  10756     /* Decrement PORT tab key1/key2 usage ref count */
  10757     if (!(h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) && 
  10758         !(MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) || 
  10759           MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  10760         BCM_IF_ERROR_RETURN
  10761             (_bcm_sb2_oam_decrement_key_ref_count(unit, h_data_p));
  10762     }
  10763 
  10764     /* Initialize endpoint info structure. */
  10765     bcm_oam_endpoint_info_t_init(&ep_info);
  10766 
  10767     /* Set up endpoint information for key construction. */
  10768     ep_info.group = h_data_p->group_index;
  10769     ep_info.name = h_data_p->name;
  10770     ep_info.gport = h_data_p->gport;
  10771     ep_info.level = h_data_p->level;
  10772     ep_info.vlan = h_data_p->vlan;
  10773     ep_info.inner_vlan = h_data_p->inner_vlan;
  10774     ep_info.flags = h_data_p->flags;
  10775     if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  10776         ep_info.mpls_label = h_data_p->label;
  10777     }
  10778     ep_info.type       = h_data_p->type;
  10779 
  10780     /* Construct hash key for lookup + delete operation. */
  10781     _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
  10782 
  10783     /* Remove entry from hash table. */
  10784     BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key,
  10785                                      (shr_htb_data_t *)&h_data,
  10786                                      1));
  10787 
  10788     /* Clear the hash data memory previously occupied by this endpoint. */
  10789     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  10790     }
  10791     /*
  10792      * BHH specific
  10793      */
  10794     else if (soc_feature(unit, soc_feature_bhh) &&
  10795         (BHH_EP_TYPE(h_data_p))) {
  10796 #if defined(INCLUDE_BHH)
  10797 
  10798         if (h_data_p->is_remote) {
  10799             /*
  10800             * BHH uses same index for local and remote.  So, delete always goes through
  10801             * local endpoint destory
  10802             */
  10803             return (BCM_E_NONE);
  10804         } else {
  10805 
  10806             bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id);
  10807             if ((!SOC_WARM_BOOT(unit)) && (oc->ukernel_not_ready == 0)) {
  10808                 /* Send BHH Session Delete message to uC. Error response is not an  
  10809                    during switch re-init as uKernel is reloaded and its state is 
  10810                    cleared before oam init. As such endpoint wont exist during oam init*/
  10811                 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  10812                     _bcm_sb2_oam_bhh_msg_send_receive(unit,
  10813                             MOS_MSG_SUBCLASS_BHH_SESS_DELETE,
  10814                             (int)bhh_pool_ep_id, 0,
  10815                             MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY,
  10816                             &reply_len);
  10817                 }
  10818             }
  10819             rv = _bcm_sb2_oam_local_endpoint_delete(unit, h_data_p);
  10820             if (BCM_FAILURE(rv)) {
  10821                 LOG_ERROR(BSL_LS_BCM_OAM,
  10822                           (BSL_META_U(unit,
  10823                                       "OAM(unit %d) Error:BHH local_endpoint_delete failled "
  10824                                        "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  10825                 return (rv);
  10826             }
  10827             h_data_p->in_use = 0;
  10828         
  10829 
  10830              /* Remove endpoint for group's endpoint list. */
  10831             rv = _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index,
  10832                                        h_data_p->ep_id);
  10833             if (BCM_FAILURE(rv)) {
  10834                 LOG_ERROR(BSL_LS_BCM_OAM,
  10835                           (BSL_META_U(unit,
  10836                                       "OAM(unit %d) Error: Remove from group list (EP=%d) -"
  10837                                        " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  10838                 return (rv);
  10839             }
  10840 
  10841 
  10842             /* Return ID back to free MEP ID pool.*/
  10843             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id));
  10844 
  10845             /* Set up endpoint information for key construction. */
  10846             ep_info.group = h_data_p->group_index;
  10847             ep_info.name = h_data_p->name;
  10848             ep_info.gport = h_data_p->gport;
  10849             ep_info.level = h_data_p->level;
  10850             ep_info.vlan = h_data_p->vlan;
  10851             ep_info.inner_vlan = h_data_p->inner_vlan;
  10852             ep_info.flags = h_data_p->flags;
  10853             ep_info.mpls_label = h_data_p->label;
  10854             ep_info.type       = h_data_p->type;
  10855 
  10856             /* Construct hash key for lookup + delete operation. */
  10857             _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
  10858 
  10859             /* Remove entry from hash table. */
  10860             BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key,
  10861                                              (shr_htb_data_t *)&h_data,
  10862                                              1));
  10863 
  10864             /* Clear the hash data memory previously occupied by this endpoint. */
  10865             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  10866 
  10867         }
  10868 #else
  10869         return (BCM_E_UNAVAIL);
  10870 #endif /* INCLUDE_BHH */
  10871     }
  10872     else {
  10873         return (BCM_E_PARAM);
  10874     }
  10875     return (BCM_E_NONE);
  10876 }
  10877 
  10878 /*
  10879  * Function:
  10880  *     _bcm_sb2_oam_group_endpoints_destroy
  10881  * Purpose:
  10882  *     Delete all endpoints associated with a group and free all
  10883  *     resources allocated by these endpoints. 
  10884  * Parameters:
  10885  *     unit      - (IN) BCM device number
  10886  *     g_info_p  - (IN) Pointer to group information
  10887  * Retruns:
  10888  *     BCM_E_XXX
  10889  */
  10890 STATIC int
  10891 _bcm_sb2_oam_group_endpoints_destroy(int unit,
  10892                                      _bcm_oam_group_data_t *g_info_p)
  10893 {
  10894     bcm_oam_endpoint_t    ep_id; /* Endpoint ID.                   */
  10895     _bcm_oam_ep_list_t    *cur;  /* Pointer to endpoint list node. */
  10896     int                   rv;    /* Operation return status.       */
  10897 
  10898     if (NULL == g_info_p) {
  10899         return (BCM_E_INTERNAL);
  10900     }
  10901 
  10902     /* Get the endpoint list head pointer. */
  10903     cur = *(g_info_p->ep_list);
  10904     if (NULL == cur) {
  10905         LOG_DEBUG(BSL_LS_BCM_OAM,
  10906                   (BSL_META_U(unit,
  10907                               "OAM(unit %d) Info: No endpoints in group.\n"),
  10908                    unit));
  10909         return (BCM_E_NONE);
  10910     }
  10911 
  10912     while (NULL != cur) {
  10913         ep_id = cur->ep_data_p->ep_id;
  10914 
  10915         LOG_DEBUG(BSL_LS_BCM_OAM,
  10916                   (BSL_META_U(unit,
  10917                               "OAM(unit %d) Info: GID=%d EP:%d.\n"),
  10918                    unit, cur->ep_data_p->group_index, ep_id));
  10919 
  10920         cur = cur->next;
  10921 
  10922         rv = _bcm_sb2_oam_endpoint_destroy(unit, ep_id);
  10923         if (BCM_FAILURE(rv)) {
  10924             LOG_ERROR(BSL_LS_BCM_OAM,
  10925                       (BSL_META_U(unit,
  10926                                   "OAM(unit %d) Error: Endpoint destroy (EP=%d) - "
  10927                                    "%s.\n"), unit, ep_id, bcm_errmsg(rv)));
  10928             return (rv);
  10929         }
  10930     }
  10931 
  10932     return (BCM_E_NONE);
  10933 }
  10934 
  10935 /*
  10936  * Function:
  10937  *     _bcm_sb2_oam_endpoint_gport_resolve
  10938  * Purpose:
  10939  *     Resolve an endpoint GPORT value to SGLP and DGLP value.
  10940  * Parameters:
  10941  *     unit       - (IN) BCM device number
  10942  *     ep_info_p  - (IN/OUT) Pointer to endpoint information.
  10943  *     src_glp    - (IN/OUT) Pointer to source generic logical port value.
  10944  *     dst_glp    - (IN/OUT) Pointer to destination generic logical port value.
  10945  *     src_pp_port- (IN/OUT) Pointer to source pp port value.
  10946  *     dst_pp_port- (IN/OUT) Pointer to destination pp port value.
  10947  *     svp        - (IN/OUT) Pointer to VP value
  10948  *     trunk_id   - (IN/OUT) Pointer to trunk id
  10949  *     is_vp_valid - (OUT)   VP is valid or not
  10950  * Retruns:
  10951  *     BCM_E_XXX
  10952  */
  10953 STATIC int
  10954 _bcm_sb2_oam_endpoint_gport_resolve(int unit,
  10955                                 bcm_oam_endpoint_info_t *ep_info_p,
  10956                                 uint32 *src_glp,
  10957                                 uint32 *dst_glp,
  10958                                 bcm_port_t *src_pp_port,
  10959                                 bcm_port_t *dst_pp_port,
  10960                                 uint32 *svp,
  10961                                 bcm_trunk_t *trunk_id,
  10962                                 int *is_vp_valid,
  10963                                 bcm_trunk_member_t *trunk_member)
  10964 {
  10965     bcm_module_t       module_id;            /* Module ID           */
  10966     bcm_port_t         port_id;              /* Port ID.            */
  10967     bcm_port_t         port = 0;             /* Port ID.            */
  10968     int                local_id;             /* Hardware ID.        */
  10969     int                tx_enabled = 0;       /* CCM Tx enabled.     */
  10970     bcm_trunk_info_t   trunk_info;           /* Trunk information.  */
  10971     bcm_trunk_member_t *member_array = NULL; /* Trunk member array. */
  10972     int                member_count = 0;     /* Trunk Member count. */
  10973     int                rv = BCM_E_NONE;      /* Return status.      */
  10974     uint8              glp_valid = 0;        /* Logical port valid. */
  10975     int                local_member_count = 0;
  10976     bcm_trunk_t        tid = BCM_TRUNK_INVALID;
  10977     int                is_local = 0;
  10978     uint8              is_port_mep = 0;
  10979 
  10980     is_port_mep = ((ep_info_p->vlan == 0) && (ep_info_p->inner_vlan == 0));
  10981     /* Get Trunk ID or (Modid + Port) value from Gport */
  10982     BCM_IF_ERROR_RETURN
  10983         (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id,
  10984                                 &port_id, trunk_id, &local_id));
  10985  
  10986     /* Set CCM endpoint Tx status only for local endpoints. */
  10987     if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
  10988         tx_enabled
  10989             = (ep_info_p->ccm_period
  10990                 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0;
  10991     }
  10992 
  10993     /*
  10994      * If Gport is Trunk type, _bcm_esw_gport_resolve()
  10995      * sets trunk_id. Using Trunk ID, get Dst Modid and Port value.
  10996      */
  10997     if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) {
  10998 
  10999         if (BCM_TRUNK_INVALID == *trunk_id)  {
  11000             /* Has to be a valid Trunk. */
  11001             return (BCM_E_PARAM);
  11002         }
  11003 
  11004         /* Construct Hw SGLP value. */
  11005         _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id,
  11006             *src_glp);
  11007 
  11008         /* Get a member of the trunk belonging to this module */
  11009         if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1,
  11010                                         &port_id,
  11011                                         &local_member_count))) {
  11012             if(local_member_count) {
  11013                 BCM_IF_ERROR_RETURN
  11014                     (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
  11015                         &module_id, &port));
  11016                 *src_pp_port = port_id;
  11017             }
  11018         }
  11019         /*
  11020          * CCM Tx is enabled on a trunk member port.
  11021          * trunk_index value is required to derive the Modid and Port info.
  11022          */
  11023         if (1 == tx_enabled
  11024             && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) {
  11025             /* Invalid Trunk member index passed. */
  11026             return (BCM_E_PORT);
  11027         }
  11028 
  11029         /* Get count of ports in this trunk. */
  11030         BCM_IF_ERROR_RETURN
  11031             (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count));
  11032         if (0 == member_count) {
  11033             /* No members have been added to the trunk group yet */
  11034             return BCM_E_PARAM;
  11035         }
  11036 
  11037         _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
  11038                        sizeof(bcm_trunk_member_t) * member_count, "Trunk info");
  11039         if (NULL == member_array) {
  11040             return (BCM_E_MEMORY);
  11041         }
  11042 
  11043         /* Get Trunk Info for the Trunk ID. */
  11044         rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count,
  11045                                member_array, &member_count);
  11046         if (BCM_FAILURE(rv)) {
  11047             sal_free(member_array);
  11048             return (rv);
  11049         }
  11050 
  11051         /* Check if the input trunk_index is valid. */
  11052         if (ep_info_p->trunk_index >= member_count) {
  11053             sal_free(member_array);
  11054             return BCM_E_PARAM;
  11055         }
  11056 
  11057         /* Get the Modid and Port value using Trunk Index value. */
  11058         rv = _bcm_esw_gport_resolve
  11059                 (unit, member_array[ep_info_p->trunk_index].gport,
  11060                  &module_id, &port_id, &tid, &local_id);
  11061         if (BCM_FAILURE(rv)) {
  11062             sal_free(member_array);
  11063             return (rv);
  11064         }
  11065 
  11066         sal_free(member_array);
  11067 
  11068         /* Construct Hw DGLP value. */
  11069         _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
  11070             *dst_glp);
  11071 
  11072         /* Get HW PP port */
  11073         BCM_IF_ERROR_RETURN
  11074             (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
  11075                                          dst_pp_port));
  11076         *dst_glp = *src_glp;
  11077         glp_valid = 1;
  11078 
  11079         *trunk_member = member_array[ep_info_p->trunk_index];
  11080     }
  11081 
  11082     /*
  11083      * Application can resolve the trunk and pass the desginated
  11084      * port as Gport value. Check if the Gport belongs to a trunk.
  11085      */
  11086     if ((BCM_TRUNK_INVALID == (*trunk_id))
  11087         && (BCM_GPORT_IS_MODPORT(ep_info_p->gport)
  11088         || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) {
  11089 
  11090         /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve()
  11091          * returns Modid and Port value. Use these values to make the DGLP
  11092          * value.
  11093          */
  11094         _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
  11095             *dst_glp);
  11096         
  11097         /* get destination PP port */
  11098         BCM_IF_ERROR_RETURN
  11099             (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
  11100                                              dst_pp_port));
  11101 
  11102         /* Use the Modid, Port value and determine if the port
  11103          * belongs to a Trunk.
  11104          */
  11105         if (!is_port_mep) {
  11106             /* Dont find all other trunk members if it is a port mep */
  11107             rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
  11108         }
  11109         if (BCM_SUCCESS(rv) && !is_port_mep) {
  11110             /*
  11111              * Port is member of a valid trunk.
  11112              * Now create the SGLP value from Trunk ID.
  11113              */
  11114             /* Get a member of the trunk belonging to this module */
  11115             if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1,
  11116                                         &port_id,
  11117                                         &local_member_count))) {
  11118                 if(local_member_count) {
  11119                     BCM_IF_ERROR_RETURN
  11120                         (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
  11121                             &module_id, &port));
  11122                     *src_pp_port = port_id;
  11123                 }
  11124 
  11125                 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 
  11126                                              *trunk_id, *src_glp);
  11127                 *dst_glp = *src_glp;
  11128             } else {
  11129                 *src_pp_port = *dst_pp_port; 
  11130             }
  11131         } else {
  11132             /* Port not a member of trunk. DGLP and SGLP are the same. */
  11133             *src_glp = *dst_glp;
  11134             *src_pp_port = *dst_pp_port; 
  11135         }
  11136         glp_valid = 1;
  11137     }
  11138     if ((SOC_GPORT_IS_MIM_PORT(ep_info_p->gport)) ||
  11139         (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) ||
  11140         (SOC_GPORT_IS_VLAN_PORT(ep_info_p->gport))) {
  11141         *svp = local_id;
  11142         if(BCM_TRUNK_INVALID != (*trunk_id)){
  11143 
  11144             /* Construct Hw SGLP value. */
  11145             _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id,
  11146                     *src_glp);
  11147 
  11148             /* Get a member of the trunk belonging to this module */
  11149             if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1,
  11150                             &port_id,
  11151                             &local_member_count))) {
  11152                 if(local_member_count) {
  11153                     BCM_IF_ERROR_RETURN
  11154                         (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
  11155                             &module_id, &port));
  11156                     *src_pp_port = port_id;
  11157                 }
  11158             }
  11159             /*
  11160              * CCM Tx is enabled on a trunk member port.
  11161              * trunk_index value is required to derive the Modid and Port info.
  11162              */
  11163             if (1 == tx_enabled
  11164                     && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) {
  11165                 /* Invalid Trunk member index passed. */
  11166                 return (BCM_E_PORT);
  11167             }
  11168             /* Get count of ports in this trunk. */
  11169             BCM_IF_ERROR_RETURN
  11170                 (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count));
  11171             if (0 == member_count) {
  11172                 /* No members have been added to the trunk group yet */
  11173                 return BCM_E_PARAM;
  11174             }
  11175 
  11176             _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
  11177                     sizeof(bcm_trunk_member_t) * member_count, "Trunk info");
  11178             if (NULL == member_array) {
  11179                 return (BCM_E_MEMORY);
  11180             }
  11181 
  11182             /* Get Trunk Info for the Trunk ID. */
  11183             rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count,
  11184                     member_array, &member_count);
  11185             if (BCM_FAILURE(rv)) {
  11186                 sal_free(member_array);
  11187                 return (rv); 
  11188             }
  11189 
  11190             /* Check if the input trunk_index is valid. */
  11191             if (ep_info_p->trunk_index >= member_count) {
  11192                 sal_free(member_array);
  11193                 return BCM_E_PARAM;
  11194             }
  11195 
  11196             /* Get the Modid and Port value using Trunk Index value. */
  11197             rv = _bcm_esw_gport_resolve
  11198                 (unit, member_array[ep_info_p->trunk_index].gport,
  11199                  &module_id, &port_id, &tid, &local_id);
  11200             if (BCM_FAILURE(rv)) {
  11201                 sal_free(member_array);
  11202                 return (rv); 
  11203             }
  11204 
  11205             sal_free(member_array);
  11206 
  11207             /* Construct Hw DGLP value. */
  11208             _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
  11209                     *dst_glp);
  11210 
  11211             /* Get HW PP port */
  11212             BCM_IF_ERROR_RETURN
  11213                 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
  11214                                                  dst_pp_port));
  11215             *dst_glp = *src_glp;
  11216 
  11217             *trunk_member = member_array[ep_info_p->trunk_index];
  11218 
  11219         }else {
  11220             rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
  11221             if(BCM_SUCCESS(rv) && (is_local)) {  
  11222                 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, 
  11223                         -1, *dst_glp);
  11224                 *src_glp = *dst_glp;
  11225                 /* get destination PP port */
  11226                 BCM_IF_ERROR_RETURN
  11227                     (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
  11228                                                      dst_pp_port));
  11229                 *src_pp_port =  *dst_pp_port; 
  11230             }
  11231         }
  11232         glp_valid = 1;
  11233         *is_vp_valid = 1;
  11234     } 
  11235 
  11236     /* LinkPhy/CoE case */
  11237     if ((BCM_GPORT_IS_SUBPORT_PORT(ep_info_p->gport))) {
  11238         if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, ep_info_p->gport)) ||
  11239             (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, ep_info_p->gport))) {
  11240             BCM_IF_ERROR_RETURN
  11241                 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
  11242                                                 dst_pp_port));
  11243             *src_pp_port = *dst_pp_port; 
  11244             _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
  11245                                              *dst_glp);
  11246                 /* Use the Modid, Port value and determine if the port
  11247                  * belongs to a Trunk.
  11248                  */
  11249             if (!is_port_mep) {
  11250                 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
  11251             }
  11252             if (BCM_SUCCESS(rv) && !is_port_mep) {
  11253                 /*
  11254                  * Port is member of a valid trunk.
  11255                  * Now create the SGLP value from Trunk ID.
  11256                  */
  11257                 /* Get a member of the trunk belonging to this module */
  11258                 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit,  
  11259                                         *trunk_id, 1,
  11260                                         &port_id,
  11261                                         &local_member_count))) {
  11262                     if(local_member_count) {
  11263                         BCM_IF_ERROR_RETURN
  11264                             (_bcm_kt2_pp_port_to_modport_get(unit, port_id,
  11265                                 &module_id, &port));
  11266                         *src_pp_port = port_id;
  11267                     }
  11268                    _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 
  11269                                                 *trunk_id, *src_glp);
  11270                    *dst_glp = *src_glp;
  11271                 }
  11272             } else {
  11273                 *src_glp = *dst_glp;
  11274             }
  11275             glp_valid = 1;
  11276         } 
  11277     }
  11278 
  11279     /*
  11280      * At this point, both src_glp and dst_glp should be valid.
  11281      * Gport types other than TRUNK, MODPORT or LOCAL are not valid.
  11282      */
  11283     if (0 == glp_valid) {
  11284         return (BCM_E_PORT);
  11285     }
  11286     return (BCM_E_NONE);
  11287 }
  11288 
  11289 /*
  11290  * Function:
  11291  *     _bcm_sb2_oam_mepid_validate
  11292  * Purpose:
  11293  *     Validate an endpoint MEP id.
  11294  * Parameters:
  11295  *     unit      - (IN) BCM device number
  11296  *     ep_info_p - (IN) Pointer to endpoint information.
  11297  * Retruns:
  11298  *     BCM_E_XXX
  11299  */
  11300 STATIC int
  11301 _bcm_sb2_oam_mepid_validate(int unit,  
  11302                             bcm_oam_endpoint_info_t *ep_info_p)
  11303 {
  11304     _bcm_oam_control_t *oc;
  11305     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  11306     _bcm_oam_ep_list_t    *cur;     /* Current head node pointer.       */
  11307     _bcm_oam_hash_data_t  *h_data_p = NULL; /* Endpoint hash data pointer. */
  11308 
  11309     /* Get OAM control structure. */
  11310     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  11311 
  11312     /* Get the group memory pointer. */
  11313     group_p = &oc->group_info[ep_info_p->group];
  11314 
  11315     if (1 != group_p->in_use) {
  11316         return BCM_E_NONE;
  11317     }    
  11318     cur =  *group_p->ep_list;
  11319 
  11320     /* Traverse the list and delete the matching node. */
  11321     while (NULL != cur) {
  11322         h_data_p = cur->ep_data_p;
  11323         if (NULL == h_data_p) {
  11324             LOG_ERROR(BSL_LS_BCM_OAM,
  11325                      (BSL_META_U(unit,
  11326                      "OAM(unit %d) Error: Hash data is empty\n"),
  11327                      unit));
  11328             return (BCM_E_INTERNAL);
  11329         }
  11330         if (ep_info_p->name  == h_data_p->name) { 
  11331             /* MEP NAME should be independently unique for RMEPs and LMEPs */
  11332             if (((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 
  11333                 (cur->ep_data_p->ep_id == ep_info_p->id)) || 
  11334                 ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) != 
  11335                 (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE))) {
  11336             } else {
  11337                 return BCM_E_PARAM;
  11338             }    
  11339         }
  11340         cur = cur->next;
  11341     }    
  11342     return (BCM_E_NONE);
  11343 }        
  11344 
  11345 /* Returns 0/1.
  11346  * 0 - indicates either an invalid egress intf or mepid passed
  11347  *     did not match the earlier mepid.
  11348  * 1 - indicates the egress intf doesnt have oam enabled already or
  11349  *     the mepid check passed.
  11350  */
  11351 STATIC int
  11352 _bcm_sb2_oam_check_mepid_for_egress_mpls_lmdm_lsp(int unit,
  11353                          bcm_oam_endpoint_info_t *ep_info_p)
  11354 {
  11355 #if defined(INCLUDE_L3)
  11356     int egr_nh_index = 0;
  11357     egr_l3_next_hop_entry_t egr_nh_entry;
  11358     int rv = BCM_E_NONE;
  11359     int oam_enable = 0, mep_id = -1;
  11360 
  11361     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  11362 
  11363     if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, ep_info_p->intf_id)) {
  11364         egr_nh_index = ep_info_p->intf_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  11365     }
  11366     else {
  11367         egr_nh_index = ep_info_p->intf_id - BCM_XGS3_EGRESS_IDX_MIN(unit);
  11368     }
  11369 
  11370     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
  11371             egr_nh_index, &egr_nh_entry);
  11372     if (BCM_FAILURE(rv)) {
  11373         /* not a valid egress intf. return check failed */
  11374         return 0;
  11375     }
  11376 
  11377     oam_enable = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
  11378             MPLS__MPLS_OAM_DOWNMEP_ENABLEf);
  11379     if (!oam_enable) {
  11380         return 1;
  11381     }
  11382     if (oam_enable == _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM) {
  11383         mep_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
  11384                 MPLS__MEPIDf);
  11385 
  11386         if (mep_id == ep_info_p->name) {
  11387             /* Match found */
  11388             return 1;
  11389         }
  11390     }
  11391     return 0;
  11392 #endif
  11393     return 1;
  11394 }
  11395 
  11396 /*
  11397  * Function:
  11398  *     _bcm_sb2_oam_endpoint_params_validate
  11399  * Purpose:
  11400  *     Validate an endpoint parameters.
  11401  * Parameters:
  11402  *     unit      - (IN) BCM device number
  11403  *     oc        - (IN) Pointer to OAM control structure.
  11404  *     hash_key  - (IN) Pointer to endpoint hash key value.
  11405  *     ep_info_p - (IN) Pointer to endpoint information.
  11406  * Retruns:
  11407  *     BCM_E_XXX
  11408  */
  11409 STATIC int
  11410 _bcm_sb2_oam_endpoint_params_validate(int unit,
  11411                                   _bcm_oam_control_t *oc,
  11412                                   _bcm_oam_hash_key_t *hash_key,
  11413                                   bcm_oam_endpoint_info_t *ep_info_p)
  11414 {
  11415     int                 rv;  /* Operation return status. */
  11416     _bcm_oam_hash_data_t h_stored_data;
  11417     int remote  = 0;
  11418 
  11419 
  11420     /* Get MEP remote endpoint status. */
  11421     remote = (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  11422 
  11423     LOG_DEBUG(BSL_LS_BCM_OAM,
  11424               (BSL_META_U(unit,
  11425                           "OAM(unit %d) Info: "
  11426                           "_bcm_sb2_oam_endpoint_params_validate.\n"), unit));
  11427 
  11428     /* Endpoint must be 802.1ag/Ethernet OAM type. */
  11429     if ((bcmOAMEndpointTypeEthernet != ep_info_p->type) 
  11430 #if defined(INCLUDE_BHH)
  11431         &&  /* BHH/Y.1731 OAM type */
  11432         !(BHH_EP_TYPE(ep_info_p))
  11433 #endif /* INCLUDE_BHH */
  11434         && !(MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p))
  11435         )
  11436     {
  11437         /* Other OAM types are not supported, return error. */
  11438         return BCM_E_UNAVAIL;
  11439     }
  11440 
  11441     /* Supported MDL level is 0 - 7. */
  11442     if ((!remote) && 
  11443         ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX))) {
  11444         LOG_ERROR(BSL_LS_BCM_OAM,
  11445                   (BSL_META_U(unit,
  11446                               "OAM(unit %d) Error: EP Level should be in the range(0-%d).\n"),
  11447                    unit, _BCM_OAM_EP_LEVEL_MAX ));
  11448         return (BCM_E_PARAM);
  11449      }
  11450 
  11451      /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP and MPLS LM/DM  */
  11452      if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN)
  11453          || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) &&
  11454          !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
  11455          (!MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p))) {
  11456         LOG_ERROR(BSL_LS_BCM_OAM,
  11457                   (BSL_META_U(unit,
  11458                               "OAM Error: MEP Name should be in the range(%d-%d).\n"),
  11459                    _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX));
  11460         return (BCM_E_PARAM);
  11461      }
  11462 
  11463     /*
  11464      * Check and return error if invalid flag bits are set for remote
  11465      * endpoint.
  11466      */
  11467     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)
  11468         && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) {
  11469 
  11470         return (BCM_E_PARAM);
  11471 
  11472     }
  11473 
  11474     /* There are no remote end-points in MPLS LM DM */
  11475     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) &&
  11476         (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p))) {
  11477         return (BCM_E_PARAM);
  11478     }
  11479 
  11480     /*
  11481      * Check and return error if MEPID is not unique within the group
  11482      * For MPLS LM/DM endpoints, MEPIDs need not be validated to be unique
  11483      * within a group.
  11484      */
  11485     if( (!MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) &&
  11486          _bcm_sb2_oam_mepid_validate(unit, ep_info_p) ) {
  11487         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  11488              "OAM(unit %d) Error: MEPID:%x passed is not unique in group %x\n"),
  11489              unit, ep_info_p->name, ep_info_p->group));
  11490 
  11491         return (BCM_E_EXISTS);
  11492     }
  11493 
  11494     /* Check if the egr intf given is common for some other endpoint.
  11495      * In such a case the mepid for both endpoints should be same. Else
  11496      * return error
  11497      */
  11498     if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep_info_p)) &&
  11499         (!_bcm_sb2_oam_check_mepid_for_egress_mpls_lmdm_lsp(unit, ep_info_p))) {
  11500         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  11501              "OAM(unit %d) Error: MEPID:%x given is wrong for the given "
  11502              "egress interface %x\n"),
  11503              unit, ep_info_p->name, ep_info_p->intf_id));
  11504         return (BCM_E_PARAM);
  11505     }
  11506 
  11507     /* For replace operation, endpoint ID is required. */
  11508     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)
  11509         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) {
  11510 
  11511         return (BCM_E_PARAM);
  11512 
  11513     }
  11514     /* Port based MEP is supported only for down MEP */
  11515     if ((0 == ep_info_p->vlan) && (0 == ep_info_p->inner_vlan) &&
  11516         (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) && (!remote)) {
  11517         return (BCM_E_PARAM);
  11518     }
  11519 
  11520     /* If it is a Port + CVlan based MEP or Section Port + CVlan
  11521      * based MEP and the CVlan (inner_vlan) is 0, return E_PARAM
  11522      */
  11523     if ((0 == ep_info_p->inner_vlan) &&
  11524         ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) ||
  11525          (ep_info_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan))) {
  11526         return (BCM_E_PARAM);
  11527     }
  11528 
  11529     /* If it is a Port + S + CVlan based MEP or Section Port + S + CVlan
  11530      * based MEP and one of SVlan(vlan) or CVlan (inner_vlan) is 0,
  11531      * return E_PARAM
  11532      */
  11533     if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) &&
  11534         ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) ||
  11535     (ep_info_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan))) {
  11536         return (BCM_E_PARAM);
  11537     }
  11538 
  11539     /* Validate the LM Counter pool id */
  11540     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) &&
  11541        !(_BCM_SB2_OAM_VALID_CTR_POOL_ID(ep_info_p->lm_ctr_pool_id))) {
  11542         return (BCM_E_PARAM);
  11543     }
  11544 
  11545     /* MPLS LM DM should not have level other than 7 */
  11546     if ((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) &&
  11547         (ep_info_p->level != 7)) {
  11548         return (BCM_E_PARAM);
  11549     }
  11550 
  11551     /* MPLS LM DM is supported only for down MEP */
  11552     if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) &&
  11553         (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING)){
  11554         return (BCM_E_PARAM);
  11555     }
  11556 
  11557     /* MPLS LM Packet count cannot have 64 bit counter */
  11558     if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) &&
  11559        (ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) &&
  11560        (ep_info_p->lm_ctr_type == bcmOamLmCounterTypePkt) &&
  11561        (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit)) {
  11562         return (BCM_E_PARAM);
  11563     }
  11564 
  11565     /* MPLS LM+DM cannot have 64 bit counter */
  11566     if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) &&
  11567        ((ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) &&
  11568         (ep_info_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) &&
  11569         (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit)) {
  11570         return (BCM_E_PARAM);
  11571     }
  11572 
  11573     /* Validate endpoint index value. */
  11574     if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  11575         _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id);
  11576     }
  11577 
  11578     /* MIP's are not created with non-zero ccm period */
  11579     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
  11580         (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) {
  11581          return (BCM_E_PARAM);
  11582     }
  11583 
  11584     /* Validate endpoint group id. */
  11585     _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group);
  11586 
  11587     rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group);
  11588     if (BCM_E_EXISTS != rv) {
  11589         LOG_ERROR(BSL_LS_BCM_OAM,
  11590                   (BSL_META_U(unit,
  11591                               "OAM(unit %d) Error: Group (GID:%d) does not exist.\n"),
  11592                    unit, ep_info_p->group));
  11593         return (BCM_E_PARAM);
  11594     }
  11595   
  11596     if(soc_feature(unit, soc_feature_bhh)) {
  11597 #if defined(INCLUDE_BHH)
  11598         /*
  11599          * BHH can have multiple LSPs/endpoint on same port/MDL
  11600          * BHH does not have h/w support.  So, return here
  11601          */
  11602         if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) ||
  11603             (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) {
  11604             return (BCM_E_NONE);
  11605         }
  11606 #endif
  11607     }
  11608 
  11609 #if defined(KEY_PRINT)
  11610     _bcm_oam_hash_key_print(hash_key);
  11611 #endif
  11612 
  11613     /*
  11614      * Lookup using hash key value.
  11615      * Last param value '0' specifies keep the match entry.
  11616      * Value '1' would mean remove the entry from the table.
  11617      * Matched Params:
  11618      *      Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport.
  11619      */
  11620     rv = shr_htb_find(oc->ma_mep_htbl, *hash_key,
  11621                       (shr_htb_data_t *)&h_stored_data, 0);
  11622     if (BCM_SUCCESS(rv)
  11623         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) {
  11624 
  11625         LOG_ERROR(BSL_LS_BCM_OAM,
  11626                   (BSL_META_U(unit,
  11627                               "OAM(unit %d) Error: Endpoint ID=%d %s.\n"),
  11628                    unit, ep_info_p->id, bcm_errmsg(BCM_E_EXISTS)));
  11629 
  11630         /* Endpoint must not be in use expect for Replace operation. */
  11631         return (BCM_E_EXISTS);
  11632 
  11633     } else {
  11634 
  11635         LOG_DEBUG(BSL_LS_BCM_OAM,
  11636                   (BSL_META_U(unit,
  11637                               "OAM(unit %d) Info: Endpoint ID=%d Available. %s.\n"),
  11638                    unit, ep_info_p->id, bcm_errmsg(rv)));
  11639 
  11640     }
  11641 
  11642     
  11643 
  11644     return (BCM_E_NONE);
  11645 }
  11646 
  11647 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type1_s {
  11648     uint32            start_index;
  11649     uint32            end_index;
  11650     soc_field_t       tag_source_1;
  11651     soc_field_t       tag_source_2;
  11652     soc_field_t       data_processing;
  11653     soc_field_t       oam_processing;
  11654 } _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t;
  11655 
  11656 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_s {
  11657     uint32            start_index;
  11658     uint32            no_entries;
  11659     uint32            increment;
  11660     soc_field_t       tag_source_1;
  11661     soc_field_t       tag_source_2;
  11662     soc_field_t       data_processing;
  11663     soc_field_t       oam_processing;
  11664 } _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t;
  11665 
  11666 /*
  11667  * Function:
  11668  *     _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set
  11669  * Purpose:
  11670  *    Set the default values for ingress flexible oam domain control 
  11671  * Parameters:
  11672  *     unit - (IN) BCM device number
  11673  * Retruns:
  11674  *     BCM_E_XXX
  11675  * Index to the ing flexible domain control table is
  11676  *        index[5] = pars_inner_pri_tagged;
  11677  *        index[4] = pars_inner_tagged;
  11678  *        index[3] = pars_outer_tagged;
  11679  *        index[2] = vxlt_inner_tagged;
  11680  *        index[1] = vxlt_outer_tagged;
  11681  *        index[0] = svp_valid;
  11682  */
  11683 STATIC int
  11684 _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set(int unit)
  11685 {
  11686     int      rv = BCM_E_NONE;
  11687     oam_flexible_domain_control_entry_t *ent_buf;
  11688     oam_flexible_domain_control_entry_t *ent;
  11689     int      max_index = 0; 
  11690     int      index = 0; 
  11691     int      end_index = 0; 
  11692     int      loop_index = 0; 
  11693     int      entry_mem_size = 0;
  11694     int      entry_index = 0;
  11695     int      max_array_index = 0;
  11696     uint32   action_set = 1;
  11697 
  11698 
  11699     _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t c_vlan_ctrl_info[] = {
  11700       /* Set values for C VLAN MEP pre-VXLT actions */
  11701            /* Action for incoming untagged packets  */
  11702            { 4,   7, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0,
  11703                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
  11704                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
  11705            /* Action for incoming single inner tagged but not 
  11706              priority tagged packets */
  11707            { 16, 23, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0,
  11708                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
  11709                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
  11710            /* Action for incoming single inner priority tagged packets */
  11711            { 52, 55, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0,
  11712                      CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
  11713                      CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
  11714        /* Set values for C VLAN MEP post-VXLT actions */
  11715            /* Action for incoming untagged packets */
  11716            { 4,   7, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0,
  11717                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
  11718                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
  11719            /* Action for incoming single inner tagged but not 
  11720              priority tagged packets */
  11721            { 20, 23, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0,
  11722                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
  11723                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
  11724            /* Action for incoming single inner priority tagged packets */
  11725            { 52, 55, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0,
  11726                      CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
  11727                      CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
  11728 
  11729            {0, 63, MPLS_SECTION_DOMAIN_CVLAN_TAG_SOURCEf,
  11730                MPLS_SECTION_DOMAIN_SVLAN_TAG_SOURCEf,
  11731                MPLS_SECTION_DOMAIN_OAM_PROCESSING_ENABLEf,
  11732                MPLS_SECTION_DOMAIN_DATA_PROCESSING_ENABLEf},
  11733 
  11734     };
  11735 
  11736     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t s_vlan_ctrl_info[] = {
  11737 
  11738         /* Set values for S VLAN MEP actions */
  11739            /* Action for incoming packet with single outer tagged after 
  11740               VXLT  */
  11741            { 2, 2, 8,  SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0,
  11742                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11743                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf},
  11744            /* Action for incoming packet with double tag after VXLT  */
  11745            { 6, 2, 8,  SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0,
  11746                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11747                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11748 
  11749        /* Set values for S+C VLAN MEP actions */
  11750            /* Action for incoming packet with double tag after VXLT  */
  11751            { 6, 2, 8,  SVLAN_CVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 
  11752                        SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 
  11753                        SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11754                        SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11755            { 6, 2, 8,  0, 0, 
  11756                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11757                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11758            { 6, 2, 8,  0, 0, 
  11759                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf, 
  11760                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf },
  11761            { 6, 2, 8,  0, 
  11762                        0, 
  11763                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf, 
  11764                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf },
  11765            { 0, 0 } /* table terminator */ 
  11766     };
  11767 
  11768     _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t *ctrl_info;
  11769     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *s_ctrl_info;
  11770 
  11771 
  11772     /* Read the table entries into the buffer. */
  11773     max_index = soc_mem_index_max(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm);
  11774 
  11775     entry_mem_size = sizeof(oam_flexible_domain_control_entry_t);
  11776     /* Allocate buffer to store the DMAed table entries. */
  11777     ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1),
  11778                             "OAM flexible domain control table entry buffer");
  11779     if (NULL == ent_buf) {
  11780         return (BCM_E_MEMORY);
  11781     }
  11782     /* Initialize the entry buffer. */
  11783     sal_memset(ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1));
  11784     max_array_index = 
  11785      sizeof(c_vlan_ctrl_info) / 
  11786      sizeof(_bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t);
  11787 
  11788     /* Set action for C vlan */ 
  11789     for (index = 0; index < max_array_index;index++) { 
  11790         ctrl_info = &c_vlan_ctrl_info[index];
  11791 
  11792         for (entry_index = ctrl_info->start_index; 
  11793              entry_index <= ctrl_info->end_index; entry_index++) {
  11794             ent = soc_mem_table_idx_to_pointer
  11795                     (unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11796                      oam_flexible_domain_control_entry_t *,
  11797                      ent_buf, entry_index);
  11798             if (ctrl_info->tag_source_1 != 0) {
  11799                 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11800                         (uint32 *)ent, ctrl_info->tag_source_1, &action_set);
  11801             }
  11802             if (ctrl_info->tag_source_2 != 0) {
  11803                 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11804                         (uint32 *)ent, ctrl_info->tag_source_2, &action_set);
  11805             }
  11806             soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11807                         (uint32 *)ent, ctrl_info->data_processing, &action_set);
  11808             soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11809                          (uint32 *)ent, ctrl_info->oam_processing, &action_set);
  11810         }
  11811     } 
  11812 
  11813     /* Set action for S and S+C vlan */ 
  11814     for (index = 0; ;index++) { 
  11815         s_ctrl_info = &s_vlan_ctrl_info[index];
  11816         if(s_ctrl_info->start_index == 0) {
  11817             /* End of table */
  11818             break;
  11819         }
  11820         entry_index = s_ctrl_info->start_index;
  11821         loop_index = s_ctrl_info->start_index;
  11822         end_index = entry_index + s_ctrl_info->no_entries;
  11823         while (entry_index <= max_index) {  
  11824             for (; loop_index < end_index; loop_index++) {
  11825                 ent = soc_mem_table_idx_to_pointer(unit, 
  11826                                       OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11827                                       oam_flexible_domain_control_entry_t *,
  11828                                       ent_buf, loop_index);
  11829                 if (s_ctrl_info->tag_source_1 != 0) {
  11830                     soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11831                          (uint32 *)ent, s_ctrl_info->tag_source_1, &action_set);
  11832                 }    
  11833                 if (s_ctrl_info->tag_source_2 != 0) {
  11834                     soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11835                          (uint32 *)ent, s_ctrl_info->tag_source_2, &action_set);
  11836                 }
  11837                 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11838                       (uint32 *)ent, s_ctrl_info->data_processing, &action_set);
  11839                 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11840                        (uint32 *)ent, s_ctrl_info->oam_processing, &action_set);
  11841             }
  11842             entry_index += s_ctrl_info->increment;
  11843             loop_index = entry_index;
  11844             end_index = (entry_index + s_ctrl_info->no_entries);
  11845         } 
  11846     }    
  11847 
  11848     rv = soc_mem_write_range(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11849                              MEM_BLOCK_ALL, 0, max_index, ent_buf); 
  11850     if (BCM_FAILURE(rv)) {
  11851         if (ent_buf) {
  11852             soc_cm_sfree(unit, ent_buf);
  11853         }
  11854         return rv;
  11855     }
  11856     if (ent_buf) {
  11857         soc_cm_sfree(unit, ent_buf);
  11858     }
  11859 
  11860     return rv;
  11861 }
  11862 /*
  11863  * Function:
  11864  *     _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set
  11865  * Purpose:
  11866  *    Set the default values for egress flexible oam domain control 
  11867  * Parameters:
  11868  *     unit - (IN) BCM device number
  11869  * Retruns:
  11870  *     BCM_E_XXX
  11871  */
  11872 
  11873 STATIC int
  11874 _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set(int unit)
  11875 {
  11876     int      rv = BCM_E_NONE;
  11877     egr_oam_flexible_domain_control_entry_t *egr_ent_buf;
  11878     egr_oam_flexible_domain_control_entry_t *ent;
  11879     int      max_index = 0; 
  11880     int      index = 0; 
  11881     int      end_index = 0; 
  11882     int      loop_index = 0; 
  11883     int      entry_mem_size = 0;
  11884     int      entry_index = 0;
  11885     uint32   action_set = 1;
  11886 
  11887     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t vlan_ctrl_info[] = {
  11888 
  11889           /*  CVLAN MEP before VXLT */
  11890            { 16, 2, 4, 0, 0, 
  11891                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
  11892                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
  11893           /* CVLAN MEP after VXLT */
  11894            { 4,  2, 8, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 
  11895                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
  11896                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
  11897           /* SVLAN MEP */
  11898            { 8,  8, 16, 0, 0, 
  11899                         SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11900                         SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11901 
  11902         /* Set values for Section MEP actions */
  11903            { 8, 8, 16,  MPLS_SECTION_DOMAIN_CVLAN_TAG_SOURCEf,
  11904                        MPLS_SECTION_DOMAIN_SVLAN_TAG_SOURCEf,
  11905                        MPLS_SECTION_DOMAIN_OAM_PROCESSING_ENABLEf, 
  11906                        MPLS_SECTION_DOMAIN_DATA_PROCESSING_ENABLEf},
  11907           /* S+C VLAN MEP */
  11908            { 14, 2, 18, SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 0, 
  11909                         SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11910                         SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11911 
  11912            { 24, 8, 8, 0, 0, 
  11913                        SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11914                        SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11915            { 24, 8, 8, 0, 0, 
  11916                        CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 
  11917                        CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf },
  11918            { 26, 2, 2, 0, 0, 
  11919                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11920                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11921            { 30, 2, 2, 0, 0, 
  11922                        SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 
  11923                        SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf },
  11924            { 30, 2, 2, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 
  11925                        CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 
  11926                        CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf },
  11927            { 0, 0 } /* table terminator */ 
  11928     };
  11929 
  11930     _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *ctrl_info;
  11931 
  11932 
  11933     /* Read the table entries into the buffer. */
  11934     max_index = soc_mem_index_max(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm);
  11935 
  11936     entry_mem_size = sizeof(egr_oam_flexible_domain_control_entry_t);
  11937     /* Allocate buffer to store the DMAed table entries. */
  11938     egr_ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1),
  11939                             "OAM flexible domain control table entry buffer");
  11940     if (NULL == egr_ent_buf) {
  11941         return (BCM_E_MEMORY);
  11942     }
  11943     /* Initialize the entry buffer. */
  11944     sal_memset(egr_ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1));
  11945 
  11946     /* Set action for C, S and S+C vlan */ 
  11947     for (index = 0; ;index++) { 
  11948         ctrl_info = &vlan_ctrl_info[index];
  11949         if(ctrl_info->start_index == 0) {
  11950             /* End of table */
  11951             break;
  11952         }
  11953         entry_index = ctrl_info->start_index;
  11954         loop_index = ctrl_info->start_index;
  11955         end_index = entry_index + ctrl_info->no_entries;
  11956         while (entry_index <= max_index) {  
  11957             for (; loop_index < end_index; loop_index++) {
  11958                 ent = soc_mem_table_idx_to_pointer
  11959                     (unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11960                      egr_oam_flexible_domain_control_entry_t *,
  11961                      egr_ent_buf, loop_index);
  11962 
  11963                 if (ctrl_info->tag_source_1 != 0) {
  11964                     soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11965                            (uint32 *)ent, ctrl_info->tag_source_1, &action_set);
  11966                 }
  11967                 if (ctrl_info->tag_source_2 != 0) {
  11968                     soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11969                            (uint32 *)ent, ctrl_info->tag_source_2, &action_set);
  11970                 }
  11971                 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11972                         (uint32 *)ent, ctrl_info->data_processing, &action_set);
  11973                 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11974                          (uint32 *)ent, ctrl_info->oam_processing, &action_set);
  11975             }
  11976             entry_index += ctrl_info->increment;
  11977             loop_index = entry_index;
  11978             end_index = (entry_index + ctrl_info->no_entries);
  11979         } 
  11980     }    
  11981 
  11982     rv = soc_mem_write_range(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 
  11983                              MEM_BLOCK_ALL, 0, max_index, egr_ent_buf); 
  11984     if (BCM_FAILURE(rv)) {
  11985         if (egr_ent_buf) {
  11986             soc_cm_sfree(unit, egr_ent_buf);
  11987         }
  11988         return rv;
  11989     }
  11990     if (egr_ent_buf) {
  11991         soc_cm_sfree(unit, egr_ent_buf);
  11992     }
  11993     return rv;
  11994 }
  11995 
  11996 
  11997 /*
  11998  * Function:
  11999  *     _bcm_sb2_oam_flexible_oam_domain_ctrl_set
  12000  * Purpose:
  12001  *    Set the default values for flexible oam domain control 
  12002  * Parameters:
  12003  *     unit - (IN) BCM device number
  12004  * Retruns:
  12005  *     BCM_E_XXX
  12006  */
  12007 STATIC int
  12008 _bcm_sb2_oam_flexible_oam_domain_ctrl_set(int unit)
  12009 {
  12010     int      rv = BCM_E_NONE;
  12011     /* Set ingress flexible domain control */
  12012     rv = _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set(unit); 
  12013     if (BCM_FAILURE(rv)) {
  12014         return (rv);
  12015     }
  12016 
  12017     /* Set egress flexible domain control */
  12018     rv = _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set(unit); 
  12019     if (BCM_FAILURE(rv)) {
  12020         return (rv);
  12021     }
  12022     return rv;
  12023 }
  12024 
  12025 
  12026 typedef struct _bcm_oam_ing_flexible_drop_ctrl_s {
  12027     soc_reg_t         drop_ctrl_reg;
  12028     uint32            vfp_drop_ctrl;
  12029     uint32            olp_drop_ctrl;
  12030     uint32            spst_drop_ctrl;
  12031     uint32            tag_drop_ctrl;
  12032     uint32            cvlan_bfr_vxlt_drop_ctrl;
  12033     uint32            cvlan_after_vxlt_drop_ctrl;
  12034     uint32            e2e_drop_ctrl;
  12035     uint32            vlan_drop_ctrl;
  12036     uint32            disc_drop_ctrl;
  12037 } _bcm_oam_ing_flexible_drop_ctrl_t;
  12038 
  12039 typedef struct _bcm_oam_egr_flexible_drop_ctrl_s {
  12040     soc_reg_t         drop_ctrl_reg;
  12041     uint32            egr_drop_ctrl;
  12042     uint32            evxlt_payload_drop_ctrl;
  12043     uint32            cvlan_after_vxlt_drop_ctrl;
  12044     uint32            cvlan_before_vxlt_drop_ctrl;
  12045 } _bcm_oam_egr_flexible_drop_ctrl_t;
  12046 
  12047 /*
  12048  * Function:
  12049  *     _bcm_sb2_oam_ing_flexible_drop_ctrl_set
  12050  * Purpose:
  12051  *    Set the default values for flexible ingress drop control 
  12052  * Parameters:
  12053  *     unit - (IN) BCM device number
  12054  * Retruns:
  12055  *     BCM_E_XXX
  12056  */
  12057     STATIC int
  12058 _bcm_sb2_oam_ing_flexible_drop_ctrl_set(int unit)
  12059 {
  12060     uint64 en_rval;
  12061     uint64 write_val;
  12062     int index = 0;
  12063     _bcm_oam_ing_flexible_drop_ctrl_t *flex_drop_info;
  12064     _bcm_oam_ing_flexible_drop_ctrl_t ing_flex_drop[] = {
  12065         { OAM_PORT_INTERFACE_DROP_CONTROL_64r,        0, 1, 0, 0, 0, 0, 1, 0, 0xe01c1 },
  12066         { OAM_C_INTERFACE_DROP_CONTROL_64r,           1, 1, 0, 0, 0, 1, 1, 0, 0xe01fd },
  12067         { OAM_S_INTERFACE_DROP_CONTROL_64r,           1, 1, 0, 1, 1, 1, 1, 5, 0xe01fd },
  12068         { OAM_S_C_INTERFACE_DROP_CONTROL_64r,         1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
  12069         { OAM_SECTION_INTERFACE_DROP_CONTROL_64r,  1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
  12070         { OAM_LSP_INTERFACE_DROP_CONTROL_64r,      1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
  12071         { OAM_PW_INTERFACE_DROP_CONTROL_64r,       1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd },
  12072         { 0 }, /* End of table */
  12073     };
  12074 
  12075     COMPILER_64_ZERO(en_rval);
  12076     COMPILER_64_ZERO(write_val);
  12077 
  12078     for (index = 0; ;index++) { 
  12079         flex_drop_info = &ing_flex_drop[index];
  12080         if(flex_drop_info->drop_ctrl_reg == 0) {
  12081             /* End of table */
  12082             break;
  12083         }
  12084 
  12085         SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 
  12086                     REG_PORT_ANY, 0, &en_rval));
  12087         COMPILER_64_SET(write_val, 0, flex_drop_info->vfp_drop_ctrl);
  12088         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12089                 &en_rval, VFP_DROP_CTRLf,
  12090                 write_val);
  12091         COMPILER_64_SET(write_val, 0, flex_drop_info->olp_drop_ctrl);
  12092         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12093                 &en_rval, OLP_ERROR_DROP_CTRLf,
  12094                 write_val);
  12095         COMPILER_64_SET(write_val, 0, flex_drop_info->spst_drop_ctrl);
  12096         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12097                 &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf,
  12098                 write_val);
  12099         COMPILER_64_SET(write_val, 0, flex_drop_info->tag_drop_ctrl);
  12100         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12101                 &en_rval, DISCARD_TAG_UNTAG_CTRLf,
  12102                 write_val);
  12103         COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_bfr_vxlt_drop_ctrl);
  12104         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12105                 &en_rval, 
  12106                 CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf,
  12107                 write_val);
  12108         COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl);
  12109         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12110                 &en_rval, 
  12111                 CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf,
  12112                 write_val);
  12113         COMPILER_64_SET(write_val, 0, flex_drop_info->e2e_drop_ctrl);
  12114         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12115                 &en_rval, ERRORED_E2E_PKT_DROP_CTRLf,
  12116                 write_val);
  12117         COMPILER_64_SET(write_val, 0, flex_drop_info->vlan_drop_ctrl);
  12118         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12119                 &en_rval, VLAN_DROP_VECTOR_CTRLf,
  12120                 write_val);
  12121         COMPILER_64_SET(write_val, 0, flex_drop_info->disc_drop_ctrl);
  12122         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12123                 &en_rval, DISC_DROP_VECTOR_CTRLf,
  12124                 write_val);
  12125         SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg,
  12126                     REG_PORT_ANY, 0, en_rval));
  12127     }
  12128     return (BCM_E_NONE);
  12129 }
  12130 
  12131 /*
  12132  * Function:
  12133  *     _bcm_sb2_oam_egr_flexible_drop_ctrl_set
  12134  * Purpose:
  12135  *    Set the default values for flexible egress drop control 
  12136  * Parameters:
  12137  *     unit - (IN) BCM device number
  12138  * Retruns:
  12139  *     BCM_E_XXX
  12140  */
  12141     STATIC int
  12142 _bcm_sb2_oam_egr_flexible_drop_ctrl_set(int unit)
  12143 {
  12144     uint64 en_rval;
  12145     uint64 write_val;
  12146     int index = 0;
  12147 
  12148     _bcm_oam_egr_flexible_drop_ctrl_t *flex_drop_info;
  12149     _bcm_oam_egr_flexible_drop_ctrl_t egr_flex_drop[] = {
  12150         { EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r, 0x1e0787d, 1, 1, 1 },
  12151         { EGR_OAM_C_INTERFACE_DROP_CONTROL_64r,    0x1e0787c, 1, 1, 0 },
  12152         { EGR_OAM_S_INTERFACE_DROP_CONTROL_64r,    0x1e06848, 1, 0, 0 },
  12153         { EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r,  0x1e06048, 1, 0, 0 },
  12154         { EGR_OAM_SECTION_INTERFACE_DROP_CONTROL_64r,  0x1e06049, 1, 0, 0 },
  12155         { EGR_OAM_LSP_INTERFACE_DROP_CONTROL_64r,      0x1e06049, 1, 0, 0 },
  12156         { EGR_OAM_PW_INTERFACE_DROP_CONTROL_64r,    0x1e06049, 1, 0, 0 },
  12157         { 0 }, /* End of table */
  12158     };
  12159 
  12160     COMPILER_64_ZERO(en_rval); 
  12161     COMPILER_64_ZERO(write_val); 
  12162 
  12163     for (index = 0; ;index++) { 
  12164         flex_drop_info = &egr_flex_drop[index];
  12165         if(flex_drop_info->drop_ctrl_reg == 0) {
  12166             /* End of table */
  12167             break;
  12168         }
  12169 
  12170         SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 
  12171                     REG_PORT_ANY, 0, &en_rval));
  12172 
  12173         COMPILER_64_SET(write_val, 0, flex_drop_info->egr_drop_ctrl);
  12174         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12175                 &en_rval, EGR_DROP_VECTOR_CTRLf,
  12176                 write_val);
  12177 
  12178         COMPILER_64_SET(write_val, 0, flex_drop_info->evxlt_payload_drop_ctrl);
  12179         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12180                 &en_rval, 
  12181                 EVXLT_APPLIED_TO_PAYLOAD_VXLT_MISS_DROP_CTRLf,
  12182                 write_val);
  12183 
  12184         COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl);
  12185         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12186                 &en_rval, 
  12187                 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf,
  12188                 write_val);
  12189 
  12190         COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_before_vxlt_drop_ctrl);
  12191         soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 
  12192                 &en_rval,
  12193                 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf,
  12194                 write_val);
  12195 
  12196         SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg,
  12197                     REG_PORT_ANY, 0, en_rval));
  12198     }
  12199     return (BCM_E_NONE);
  12200 }
  12201 
  12202 /*
  12203  * Function:
  12204  *     _bcm_sb2_oam_flexible_drop_ctrl_set
  12205  * Purpose:
  12206  *    Set the default values for flexible ingress and egress drop control 
  12207  * Parameters:
  12208  *     unit - (IN) BCM device number
  12209  * Retruns:
  12210  *     BCM_E_XXX
  12211  */
  12212 STATIC int
  12213 _bcm_sb2_oam_flexible_drop_ctrl_set(int unit)
  12214 {
  12215     int rv = BCM_E_NONE;
  12216     /* Set ingress flexible drop control */
  12217     rv = _bcm_sb2_oam_ing_flexible_drop_ctrl_set(unit); 
  12218     if (BCM_FAILURE(rv)) {
  12219         return (rv);
  12220     }
  12221 
  12222     /* Set egress flexible drop control */
  12223     rv = _bcm_sb2_oam_egr_flexible_drop_ctrl_set(unit); 
  12224     if (BCM_FAILURE(rv)) {
  12225         return (rv);
  12226     }
  12227     return rv;
  12228 }
  12229 
  12230 /*
  12231  * Function:
  12232  *     _bcm_sb2_oam_s_intf_passive_proc_ctrl_set
  12233  * Purpose:
  12234  *    Set the default values for s-interface passive processing control 
  12235  * Parameters:
  12236  *     unit - (IN) BCM device number
  12237  * Retruns:
  12238  *     BCM_E_XXX
  12239  */
  12240 STATIC int
  12241 _bcm_sb2_oam_s_intf_passive_proc_ctrl_set(int unit)
  12242 {
  12243     uint32 en_rval = 0;
  12244     /* Set ingress s_intf passive processing control */
  12245     SOC_IF_ERROR_RETURN(
  12246         soc_reg32_get(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
  12247                       REG_PORT_ANY, 0, &en_rval));
  12248 
  12249     soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
  12250                         &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf,
  12251                         0x1);
  12252     /* Set ENIFILTER_DROP, INVALID_TPID_DROP and INVALID_VLAN_DROP  */
  12253     soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
  12254                         &en_rval, VLAN_DROP_VECTOR_CTRLf,
  12255                         0x7);
  12256     SOC_IF_ERROR_RETURN(
  12257         soc_reg32_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr,
  12258                         REG_PORT_ANY, 0, en_rval));
  12259 
  12260     en_rval = 0;
  12261     /* Set egress s_intf passive processing control */
  12262     SOC_IF_ERROR_RETURN(
  12263         soc_reg32_get(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
  12264                       REG_PORT_ANY, 0, &en_rval));
  12265 
  12266 
  12267     /* Set NOT_VLAN_MEMBER_DROP, STG_BLOCK_DROP, STG_DISABLE_DROP 
  12268        For details - refer to EGR_DROP_VECTOR */ 
  12269     soc_reg_field_set(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 
  12270                         &en_rval, EGR_DROP_VECTOR_CTRLf,
  12271                         0x1030);
  12272 
  12273     SOC_IF_ERROR_RETURN(soc_reg32_set(unit,
  12274                         EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr,
  12275                         REG_PORT_ANY, 0, en_rval));
  12276     return (BCM_E_NONE);
  12277 }
  12278 
  12279 /*
  12280  * Function:
  12281  *     _bcm_sb2_oam_hg_olp_enable
  12282  * Purpose:
  12283  *    Enable OLP handling on HG ports 
  12284  * Parameters:
  12285  *     unit - (IN) BCM device number
  12286  * Retruns:
  12287  *     BCM_E_XXX
  12288  */
  12289 STATIC int
  12290 _bcm_sb2_oam_hg_olp_enable(int unit)
  12291 {
  12292     bcm_pbmp_t ports;
  12293     bcm_port_t port;
  12294     iarb_ing_physical_port_entry_t entry;
  12295 
  12296     BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit));
  12297     PBMP_ITER(ports, port) {
  12298         if (IS_HG_PORT(unit, port)) {
  12299             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 
  12300                                              MEM_BLOCK_ANY, port, &entry));
  12301             soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 
  12302                                                     OLP_ENABLEf, 1);
  12303             SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 
  12304                                               MEM_BLOCK_ALL, port, &entry));
  12305         } else {
  12306             soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 
  12307                                                     OLP_ENABLEf, 0);
  12308         }
  12309         SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 
  12310                                               MEM_BLOCK_ALL, port, &entry));
  12311     }
  12312     return (BCM_E_NONE);
  12313 }
  12314 
  12315 /*
  12316  * Function:
  12317  *     _bcm_sb2_oam_olp_header_type_mapping_set
  12318  * Purpose:
  12319  *    Set default olp header type mapping
  12320  * Parameters:
  12321  *     unit - (IN) BCM device number
  12322  * Retruns:
  12323  *     BCM_E_XXX
  12324  */
  12325 STATIC int
  12326 _bcm_sb2_oam_olp_header_type_mapping_set(int unit)
  12327 {
  12328     int                                 index           = 0;
  12329     int                                 mem_index_count = 0;
  12330     egr_olp_header_type_mapping_entry_t entry;
  12331 
  12332     mem_index_count = soc_mem_index_count(unit, EGR_OLP_HEADER_TYPE_MAPPINGm);
  12333 
  12334     if (sb2_olp_hdr_type_count > mem_index_count) {
  12335         return BCM_E_RESOURCE;
  12336     }
  12337 
  12338     for (index = 0; index < sb2_olp_hdr_type_count; index++) {
  12339         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
  12340                                                      &entry,
  12341                                                      HDR_TYPEf,
  12342                                                      _BCM_SB2_OLP_HDR_TYPE_RX);
  12343 
  12344         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(
  12345                                             unit,
  12346                                             &entry,
  12347                                             HDR_SUBTYPEf,
  12348                                             sb2_olp_hdr_type_mapping[index].subtype);
  12349 
  12350         SOC_IF_ERROR_RETURN(
  12351               WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(
  12352                                        unit,
  12353                                        MEM_BLOCK_ALL,
  12354                                        sb2_olp_hdr_type_mapping[index].mem_index,
  12355                                        &entry));
  12356     }
  12357 
  12358     return BCM_E_NONE;
  12359 }
  12360 
  12361 /*
  12362  * Function: _bcm_sb2_oam_olp_fp_hw_index_get
  12363  *
  12364  * Purpose:
  12365  *     Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype
  12366  * Parameters:
  12367  *     unit - (IN) BCM device number
  12368  * Returns:
  12369  *     BCM_E_XXX
  12370  */
  12371 int
  12372 _bcm_sb2_oam_olp_fp_hw_index_get(int unit,
  12373                                   bcm_field_olp_header_type_t olp_hdr_type,
  12374                                   int *hwindex)
  12375 {
  12376     int index;
  12377 
  12378     switch (olp_hdr_type) {
  12379         /* SB2 does not allow IFP to program UpMEP header type for
  12380          * ADD_OLP_HEADER action, as the OLP_HDR_TYPE_COMPRESSED in
  12381          * FP_POLICY_TABLE is not wide enough to index Up MEP subtypes
  12382          * in EGR_OLP_HEADER_TYPE_MAPPING
  12383          */
  12384         case bcmFieldOlpHeaderTypeEthOamUpMepCcm:
  12385         case bcmFieldOlpHeaderTypeEthOamUpMepLm:
  12386         case bcmFieldOlpHeaderTypeEthOamUpMepDm:
  12387         case bcmFieldOlpHeaderTypeEthOamUpMepOthers:
  12388         case bcmFieldOlpHeaderTypeUpSat:
  12389             return BCM_E_PARAM;
  12390 
  12391         default:
  12392             break;
  12393     }
  12394 
  12395     for (index = 0; index < sb2_olp_hdr_type_count; index++) {
  12396         if (sb2_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) {
  12397             *hwindex = sb2_olp_hdr_type_mapping[index].mem_index;
  12398             return BCM_E_NONE;
  12399         }
  12400     }
  12401 
  12402     return BCM_E_NOT_FOUND;
  12403 }
  12404 
  12405 /*
  12406  * Function: _bcm_sb2_oam_olp_hw_index_olp_type_get
  12407  *
  12408  * Purpose:
  12409  *     Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED
  12410  * Parameters:
  12411  *     unit - (IN) BCM device number
  12412  * Returns:
  12413  *     BCM_E_XXX
  12414  */
  12415 int
  12416 _bcm_sb2_oam_olp_hw_index_olp_type_get(int unit,
  12417                                         int hwindex,
  12418                                         bcm_field_olp_header_type_t *olp_hdr_type)
  12419 {
  12420     int index;
  12421 
  12422     for (index = 0; index < sb2_olp_hdr_type_count; index++) {
  12423         if (sb2_olp_hdr_type_mapping[index].mem_index == hwindex) {
  12424 
  12425             *olp_hdr_type =
  12426                       sb2_olp_hdr_type_mapping[hwindex].field_olp_hdr_type;
  12427 
  12428             return BCM_E_NONE;
  12429         }
  12430     }
  12431     return BCM_E_PARAM;
  12432 }
  12433 
  12434 /*
  12435  * Function:
  12436  *     _bcm_sb2_oam_drop_ctrl_set
  12437  * Purpose:
  12438  *    Set OAM drop control to not to drop wrong version OAM packets 
  12439  * Parameters:
  12440  *     unit - (IN) BCM device number
  12441  * Retruns:
  12442  *     BCM_E_XXX
  12443  */
  12444 STATIC int
  12445 _bcm_sb2_oam_drop_ctrl_set(int unit) 
  12446 {
  12447     uint32   drop_ctrl = 0;
  12448     soc_reg_field_set(unit, OAM_DROP_CONTROLr, &drop_ctrl,
  12449                       IFP_OAM_UNKNOWN_OPCODE_VERSION_DROPf, 0);
  12450     
  12451     SOC_IF_ERROR_RETURN(WRITE_OAM_DROP_CONTROLr(unit, drop_ctrl));
  12452     return (BCM_E_NONE);
  12453 }
  12454 
  12455 /*
  12456  * Function:
  12457  *     _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default
  12458  * Purpose:
  12459  *     Set OAM LM cng and cpu data control
  12460  * Parameters:
  12461  *     unit - (IN) BCM device number
  12462  * Retruns:
  12463  *     BCM_E_XXX
  12464  */
  12465 STATIC int
  12466 _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default(int unit) 
  12467 {
  12468     uint32   rval = 0;
  12469     /* Set OAM LM CNG control such that
  12470        1. All colored packets are counted, 
  12471        2. Use LM_COLOR_MODE bit to qualify pre FP CNG for UPMEP TX 
  12472           counters in IP
  12473        3. Use LM_COLOR_MODE bit to qualify post FP CNG for DOWNMEP RX 
  12474           counters in IP     
  12475     */
  12476     soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12477                       LM_COLOR_MODEf, 1);
  12478     soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12479                       UPMEP_TX_CNG_SOURCEf, 1);
  12480     soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12481                       DOWNMEP_RX_CNG_SOURCEf, 0);
  12482     soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12483                       MPLS_OAM_LM_COLOR_MODEf, 0);
  12484     SOC_IF_ERROR_RETURN(WRITE_ING_OAM_LM_CNG_CONTROLr(unit, rval));
  12485 
  12486     rval = 0;
  12487     /* include all colored packets for LM accounting on egress side */
  12488     soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval,
  12489                                             LM_COLOR_MODEf, 1);
  12490     soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval,
  12491                                             MPLS_OAM_LM_COLOR_MODEf, 0);
  12492     SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, rval));
  12493 
  12494     rval = 0;
  12495 
  12496     /* Set OAM_LM_CPU_DATA_CONTROL to not to count
  12497        CPU generated data packets for loss measurement */
  12498     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12499                                  OAM_LCPU_TX_CNT_DISABLEf, 1);
  12500     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12501                                  OAM_LCPU_RX_CNT_DISABLEf, 1);
  12502     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12503                                  OAM_SRCPORT0_TX_CNT_DISABLEf, 1);
  12504     soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12505                                  OAM_SRCPORT0_RX_CNT_DISABLEf, 1);
  12506     SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval));
  12507 
  12508     return (BCM_E_NONE);
  12509 } 
  12510 /*
  12511  * Function:
  12512  *     _bcm_sb2_oam_lm_cng_cpu_ctrl_set
  12513  * Purpose:
  12514  *     Set OAM LM cng and cpu data control
  12515  * Parameters:
  12516  *     unit - (IN) BCM device number
  12517  * Retruns:
  12518  *     BCM_E_XXX
  12519  */
  12520 STATIC int
  12521 _bcm_sb2_oam_lm_cng_cpu_ctrl_set (int unit, bcm_oam_endpoint_info_t *ep) 
  12522 {
  12523     uint32   rval = 0;
  12524     uint32   egr_rval = 0;
  12525     soc_field_t field;
  12526     int      up_mep = 0;
  12527     int      color_mode = 0;
  12528     int      cng_source = 0;
  12529     int      count_pkt = 1;
  12530     if (ep->lm_flags) {
  12531         /* read LM CNG register */
  12532         SOC_IF_ERROR_RETURN(READ_ING_OAM_LM_CNG_CONTROLr(unit, &rval));
  12533         SOC_IF_ERROR_RETURN(READ_EGR_OAM_LM_CNG_CONTROLr(unit, &egr_rval));
  12534 
  12535         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_GREEN_AND_YELLOW) {
  12536             color_mode = 1;
  12537         } 
  12538 
  12539         if(MPLS_LM_DM_ENDPOINT_TYPE(ep)){
  12540             field = MPLS_OAM_LM_COLOR_MODEf;
  12541         }else{
  12542             field = LM_COLOR_MODEf;
  12543         }
  12544  
  12545         soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12546                           field, color_mode);
  12547         soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &egr_rval,
  12548                           field, color_mode);
  12549 
  12550         if (ep->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  12551             up_mep = 1;
  12552         }
  12553         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_POST_TRAFFIC_CONDITIONING) {
  12554             cng_source = 1;
  12555         }
  12556         if (up_mep) {
  12557             soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12558                               UPMEP_TX_CNG_SOURCEf, cng_source);
  12559         } else {
  12560             soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval,
  12561                                   DOWNMEP_RX_CNG_SOURCEf, cng_source);
  12562         }
  12563          /* write back the registrs */  
  12564         SOC_IF_ERROR_RETURN(WRITE_ING_OAM_LM_CNG_CONTROLr(unit, rval));
  12565         SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, egr_rval));
  12566          /* Read LM CPU data control */
  12567         SOC_IF_ERROR_RETURN(READ_OAM_LM_CPU_DATA_CONTROLr(unit, &rval));
  12568         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_RX_PKT) {
  12569             count_pkt = 0; 
  12570         }
  12571         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12572                           OAM_LCPU_RX_CNT_DISABLEf, count_pkt);
  12573         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12574                           OAM_SRCPORT0_RX_CNT_DISABLEf, count_pkt);
  12575 
  12576         if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_TX_PKT) {
  12577             count_pkt = 0; 
  12578         } else {
  12579             count_pkt = 1; 
  12580         }
  12581         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12582                           OAM_LCPU_TX_CNT_DISABLEf, count_pkt);
  12583         soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval,
  12584                           OAM_SRCPORT0_TX_CNT_DISABLEf, count_pkt);
  12585         SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval));
  12586     }
  12587     return (BCM_E_NONE);
  12588 }
  12589 
  12590 /*
  12591  * Function:
  12592  *     _bcm_sb2_oam_olp_magic_port_set
  12593  * Purpose:
  12594  *     Set Magic port used in OLP-XGS communication 
  12595  * Parameters:
  12596  *     unit - (IN) BCM device number
  12597  * Retruns:
  12598  *     BCM_E_XXX
  12599  */
  12600 STATIC int
  12601 _bcm_sb2_oam_olp_magic_port_set(int unit)
  12602 {
  12603     uint64 rval, set_val;
  12604     int    modid;
  12605     COMPILER_64_ZERO(rval); 
  12606     /* configure modid and the magic port */
  12607     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
  12608     SOC_IF_ERROR_RETURN(READ_IARB_OLP_CONFIG_1r(unit, &rval));
  12609 
  12610     COMPILER_64_SET(set_val, 0, modid);
  12611     soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_MODIDf, set_val);
  12612     COMPILER_64_SET(set_val, 0, _BCM_OAM_OLP_COMMUNICATION_PORT);
  12613     soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_PORT_NUMf, set_val);
  12614 
  12615     SOC_IF_ERROR_RETURN(WRITE_IARB_OLP_CONFIG_1r(unit, rval));
  12616     return (BCM_E_NONE);
  12617 }
  12618 
  12619 int
  12620 _bcm_sb2_oam_set_egr_oam_rx_mode(int unit, int enable)
  12621 {
  12622     /* Since it is just one bit register, we directly write it with
  12623      * the value.
  12624      */
  12625     BCM_IF_ERROR_RETURN(WRITE_EGR_OAM_RX_MODE_FOR_CPUr(unit, enable));
  12626  
  12627     return BCM_E_NONE;
  12628 }
  12629 
  12630 /*
  12631  * Function:
  12632  *     _bcm_sb2_oam_macsa_zero_check_disable
  12633  * Purpose:
  12634  *     Disable MACSA Zero check  
  12635  * Parameters:
  12636  *     unit - (IN) BCM device number
  12637  * Retruns:
  12638  *     BCM_E_XXX
  12639  */
  12640 STATIC int
  12641 _bcm_sb2_oam_macsa_zero_check_disable(int unit)
  12642 {
  12643     uint32   rval = 0;
  12644     soc_reg_field_set(unit, OAM_CONTROLr, &rval,
  12645                       MACSA_ZERO_CHECK_ENABLEf, 0);
  12646     SOC_IF_ERROR_RETURN(WRITE_OAM_CONTROLr(unit, rval));
  12647     soc_reg_field_set(unit, EGR_OAM_CONTROLr, &rval,
  12648                       MACSA_ZERO_CHECK_ENABLEf, 0);
  12649     SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_CONTROLr(unit, rval));
  12650     return (BCM_E_NONE);
  12651 }
  12652 
  12653 /*
  12654  * Function:
  12655  *     _bcm_sb2_oam_endpoint_cleanup
  12656  * Purpose:
  12657  *     Free all the counters and the indexes allocated on endpoint create
  12658  *     failure  
  12659  * Parameters:
  12660  *     unit - (IN) BCM device number
  12661  *     upmep- (IN) UpMep/DownMep
  12662  *     hash_key (IN)
  12663  *     hash_data (IN) Pointer to endpoint hash data
  12664  * Retruns:
  12665  *     BCM_E_XXX
  12666  */
  12667 void
  12668 _bcm_sb2_oam_endpoint_cleanup(int unit, int upmep, 
  12669                               _bcm_oam_hash_key_t  hash_key,
  12670                               _bcm_oam_hash_data_t *hash_data)
  12671 {
  12672     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
  12673     int                  rv = BCM_E_NONE;
  12674     _bcm_oam_hash_data_t h_data_stored;     /* Stored hash data.            */
  12675     uint8              active_mdl = 0;
  12676 
  12677     rv = _bcm_sb2_oam_control_get(unit, &oc);
  12678     if (BCM_FAILURE(rv)) {
  12679         return;
  12680     }
  12681     if (upmep) {
  12682         /* Delete Egress MP group entry, if already added */
  12683         rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, hash_data, 
  12684                                                          &active_mdl);
  12685         /* Update Ingress MP group table(MP_GROUP_ENTRY) */
  12686         rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, hash_data, &active_mdl);
  12687     } else {
  12688         /* Update Ingress MP group table(MP_GROUP_ENTRY) */
  12689         rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, hash_data, &active_mdl);
  12690         /* Delete Egress MP group table entry, if already added */
  12691         rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, hash_data, 
  12692                                                          &active_mdl);
  12693     }
  12694     /* return rx & tx counters allocated if any */
  12695     rv =_bcm_sb2_oam_free_counter(unit, hash_data);
  12696 
  12697     /* Clear opcode profile entry, if any */
  12698     if (hash_data->profile_index != _BCM_OAM_INVALID_INDEX) { 
  12699         if (upmep) {
  12700             rv = soc_profile_mem_delete(unit, 
  12701                     &oc->egr_oam_opcode_control_profile, 
  12702                     _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(hash_data->profile_index));
  12703         } else {
  12704             rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile, 
  12705                     _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(hash_data->profile_index));
  12706         }
  12707     }
  12708     /* Clear dglp profile, if any */
  12709     if (hash_data->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) {
  12710         if (upmep) {
  12711             rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 
  12712                                     hash_data->dglp1_profile_index);
  12713         } else {
  12714             rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 
  12715                                     hash_data->dglp1_profile_index);
  12716         }
  12717     }
  12718  
  12719     if (hash_data->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) {
  12720         if (upmep) {
  12721             rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 
  12722                                     hash_data->dglp2_profile_index);
  12723         } else {
  12724             rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 
  12725                                     hash_data->dglp2_profile_index);
  12726         }
  12727     }
  12728     
  12729     /* Decrement TPID ref count, if already incremented */
  12730     if (hash_data->outer_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  12731         rv = _bcm_sb2_tpid_entry_delete(unit, 
  12732                                         hash_data->outer_tpid_profile_index,
  12733                                         BCM_OAM_TPID_TYPE_OUTER);
  12734     }
  12735     if (hash_data->subport_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  12736         rv = _bcm_sb2_tpid_entry_delete(unit, 
  12737                                         hash_data->subport_tpid_profile_index,
  12738                                         BCM_OAM_TPID_TYPE_SUBPORT);
  12739     }
  12740     if (hash_data->inner_tpid_profile_index != _BCM_OAM_INVALID_INDEX) {
  12741         rv = _bcm_sb2_tpid_entry_delete(unit, 
  12742                                         hash_data->inner_tpid_profile_index,
  12743                                         BCM_OAM_TPID_TYPE_INNER);
  12744     }
  12745     
  12746     /* It might already have been deleted as well. 
  12747      * So just log it as debug, in case it fails */
  12748     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, hash_data);
  12749     if (BCM_FAILURE(rv)) {
  12750         LOG_DEBUG(BSL_LS_BCM_OAM,
  12751                   (BSL_META_U(unit,
  12752                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  12753                                " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv)));
  12754     }
  12755 #if defined(INCLUDE_BHH)
  12756     if(BHH_EP_TYPE(hash_data)) {
  12757         shr_idxres_list_free(oc->bhh_pool, BCM_OAM_BHH_GET_UKERNEL_EP(hash_data->ep_id));
  12758     } else 
  12759 #endif    
  12760     if (1 == hash_data->is_remote) {
  12761         /* If remote endpoint, return index to remp pool */
  12762         shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index);
  12763     } else {
  12764         /* If local endpoint, return index to lmep pool */
  12765         shr_idxres_list_free(oc->lmep_pool, hash_data->local_tx_index);
  12766     }
  12767 
  12768     /* return index to mep pool */
  12769     /* For BHH endpoints it needs to remain reserved. */
  12770     if (!BHH_EP_TYPE(hash_data)) {
  12771         shr_idxres_list_free(oc->mep_pool, hash_data->ep_id);
  12772     }
  12773 
  12774     /* Return entry to hash data entry to free pool. */
  12775     shr_htb_find(oc->ma_mep_htbl, hash_key, 
  12776                                  (shr_htb_data_t *)&h_data_stored, 1);
  12777 
  12778     /* Clear contents of hash data element. */
  12779     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  12780 }
  12781 
  12782 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
  12783 void
  12784 _bcm_sb2_oam_group_info_dump(int unit, bcm_oam_group_t group_index,
  12785                              _bcm_oam_group_data_t *group_p)
  12786 {
  12787     int                     rv;
  12788     bcm_oam_group_info_t    group_info;
  12789 
  12790     /* Initialize the group information structure. */
  12791     bcm_oam_group_info_t_init(&group_info);
  12792 
  12793     /* Retrieve group information and set in group_info structure. */
  12794     rv = _bcm_sb2_oam_get_group(unit, group_index, group_p, &group_info);
  12795     if (BCM_FAILURE(rv)) {
  12796         LOG_ERROR(BSL_LS_BCM_OAM,
  12797                   (BSL_META_U(unit,
  12798                               "OAM(unit %d) Error: _bcm_tr3_oam_group_info_dump"
  12799                               " (GID=%d) - %s.\n"),
  12800                               unit, group_index, bcm_errmsg(rv)));
  12801         return;
  12802     }
  12803     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  12804     LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index));
  12805     LOG_CLI((BSL_META_U(unit,"Group Name =  %s\r\n"), group_info.name));
  12806     LOG_CLI((BSL_META_U(unit,"Flags =  %d\r\n"), group_info.flags));
  12807     LOG_CLI((BSL_META_U(unit,"Faults =  %d\r\n"), group_info.faults));
  12808     LOG_CLI((BSL_META_U(unit,"Persistent_faults =  %d\r\n"),
  12809                               group_info.persistent_faults));
  12810     LOG_CLI((BSL_META_U(unit,"clear_persistent_faults =  %d\r\n"),
  12811                               group_info.clear_persistent_faults));
  12812     LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority =  %d\r\n"),
  12813                               group_info.lowest_alarm_priority));
  12814     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  12815 }
  12816 
  12817 void
  12818 _bcm_sb2_oam_hash_data_dump(int unit, _bcm_oam_hash_data_t *h_data_p)
  12819 {
  12820     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  12821     LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id));
  12822     LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type));
  12823     LOG_CLI((BSL_META_U(unit,"In use = %d\r\n"),h_data_p->in_use));
  12824     LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote));
  12825     LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name));
  12826     LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level));
  12827     LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan));             
  12828     LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan));
  12829     LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport));
  12830     LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp));             
  12831     LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp));              
  12832     LOG_CLI((BSL_META_U(unit,"Tx ena = %d\r\n"),h_data_p->local_tx_enabled));
  12833     LOG_CLI((BSL_META_U(unit,"Rx ena = %d\r\n"),h_data_p->local_rx_enabled));  
  12834     LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index));  
  12835     LOG_CLI((BSL_META_U(unit,"Remote idx = %d\r\n"),h_data_p->remote_index));       
  12836     LOG_CLI((BSL_META_U(unit,"LM ctr idx = %d\r\n"),h_data_p->lm_counter_index));
  12837     LOG_CLI((BSL_META_U(unit,"Pri map idx = %d\r\n"),h_data_p->pri_map_index));  
  12838     LOG_CLI((BSL_META_U(unit,"Profile Idx = %d\r\n"),h_data_p->profile_index));     
  12839     LOG_CLI((BSL_META_U(unit,"Local Tx index = %d\r\n"),h_data_p->local_tx_index));     
  12840     LOG_CLI((BSL_META_U(unit,"Local Rx index = %d\r\n"),h_data_p->local_rx_index));     
  12841     LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp));                 
  12842     LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags));              
  12843     LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2));             
  12844     LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period));             
  12845     LOG_CLI((BSL_META_U(unit,"Opcode flags = 0x%x\r\n"),h_data_p->opcode_flags));       
  12846     LOG_CLI((BSL_META_U(unit,"TS format = %d\r\n"),h_data_p->ts_format));   
  12847     LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label));              
  12848     LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri));           
  12849     LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if));          
  12850     LOG_CLI((BSL_META_U(unit,"Domain = %d\r\n"),h_data_p->oam_domain));         
  12851     LOG_CLI((BSL_META_U(unit,"Egr pri map idx = %d\r\n"),h_data_p->egr_pri_map_index));  
  12852     LOG_CLI((BSL_META_U(unit,"Rx ctr = %d\r\n"),h_data_p->rx_ctr));             
  12853     LOG_CLI((BSL_META_U(unit,"Tx ctr = %d\r\n"),h_data_p->tx_ctr));             
  12854     LOG_CLI((BSL_META_U(unit,"src_pp_port = %d\r\n"),h_data_p->src_pp_port));        
  12855     LOG_CLI((BSL_META_U(unit,"dst_pp_port = %d\r\n"),h_data_p->dst_pp_port));        
  12856     LOG_CLI((BSL_META_U(unit,"DGLP1 = %d\r\n"),h_data_p->dglp1));              
  12857     LOG_CLI((BSL_META_U(unit,"DGLP2 = %d\r\n"),h_data_p->dglp2));              
  12858     LOG_CLI((BSL_META_U(unit,"DGLP1 Profile idx = %d\r\n"),h_data_p->dglp1_profile_index));
  12859     LOG_CLI((BSL_META_U(unit,"DGLP2 Profile idx = %d\r\n"),h_data_p->dglp2_profile_index));
  12860     LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid));         
  12861     LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid));         
  12862     LOG_CLI((BSL_META_U(unit,"SubPort TPID = %d\r\n"),h_data_p->subport_tpid));       
  12863     LOG_CLI((BSL_META_U(unit,"Outer TPID profile idx = %d\r\n"),h_data_p->outer_tpid_profile_index));
  12864     LOG_CLI((BSL_META_U(unit,"Inner TPID profile idx = %d\r\n"),h_data_p->inner_tpid_profile_index));
  12865     LOG_CLI((BSL_META_U(unit,"SubPort TPID profile idx = %d\r\n"),h_data_p->subport_tpid_profile_index));
  12866     LOG_CLI((BSL_META_U(unit,"MA Base idx = %d\r\n"),h_data_p->ma_base_index));      
  12867     LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id));           
  12868     LOG_CLI((BSL_META_U(unit,"Active MDL BITMAP = 0x%x\r\n"),h_data_p->active_mdl_bitmap));  
  12869     LOG_CLI((BSL_META_U(unit,"Internal flags = 0x%x\r\n"),h_data_p->int_flags));          
  12870 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  12871     LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  12872              h_data_p->src_mac_address[0], h_data_p->src_mac_address[1],
  12873              h_data_p->src_mac_address[2], h_data_p->src_mac_address[3],
  12874              h_data_p->src_mac_address[4], h_data_p->src_mac_address[5]));
  12875     LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  12876              h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1],
  12877              h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3],
  12878              h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5]));
  12879     LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"),h_data_p->inner_vlan_pri));
  12880 #endif
  12881     LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type));
  12882     LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn));
  12883     LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"),h_data_p->pm_profile_attached));
  12884     LOG_CLI((BSL_META_U(unit,"CTR Field id = %d\r\n"),h_data_p->ctr_field_id));
  12885     LOG_CLI((BSL_META_U(unit,"EGR CTR Field id = %d\r\n"),h_data_p->egr_ctr_field_id));
  12886 #if defined (INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM)
  12887     LOG_CLI((BSL_META_U(unit,"LM DM Internal flag = %u\r\n"),h_data_p->lm_dm_int_flag));
  12888     LOG_CLI((BSL_META_U(unit,"LM DM Session Id = %u\r\n"),h_data_p->lm_dm_uc_session_id));
  12889 #endif
  12890     LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk " 
  12891                         "index 0x%x\r\n"),
  12892                         h_data_p->resolved_trunk_gport));
  12893     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
  12894 }
  12895 
  12896 /*
  12897  * Function:
  12898  *     _bcm_oam_sw_dump
  12899  * Purpose:
  12900  *     Displays oam information maintained by software.
  12901  * Parameters:
  12902  *     unit - Device unit number
  12903  * Returns:
  12904  *     None
  12905  */
  12906 void
  12907 _bcm_sb2_oam_sw_dump(int unit)
  12908 {
  12909     int                          rv;
  12910     int                          grp_idx;
  12911     _bcm_oam_control_t           *oc;
  12912     _bcm_oam_group_data_t        *group_p = NULL;
  12913     _bcm_oam_ep_list_t           *ep_list_p = NULL;
  12914     _bcm_oam_hash_data_t         *ep_data_p = NULL;
  12915 
  12916     LOG_CLI((BSL_META_U(unit,"OAM\n")));
  12917     /* Get OAM control structure. */
  12918     rv = _bcm_sb2_oam_control_get(unit, &oc);
  12919     if(BCM_FAILURE(rv)) {
  12920         LOG_ERROR(BSL_LS_BCM_OAM,
  12921                 (BSL_META_U(unit,
  12922                 "OAM(unit %d) Error: Get oam control variable\n"),
  12923                  unit));
  12924 
  12925         return;
  12926     }
  12927 
  12928     _BCM_OAM_LOCK(oc);
  12929 
  12930     group_p = oc->group_info;
  12931     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) {
  12932         if (group_p[grp_idx].in_use == 1) {
  12933             ep_list_p = *(group_p[grp_idx].ep_list);
  12934             _bcm_sb2_oam_group_info_dump(unit, grp_idx, group_p);
  12935             while (ep_list_p != NULL) {
  12936                 ep_data_p = ep_list_p->ep_data_p;
  12937                 _bcm_sb2_oam_hash_data_dump(unit, ep_data_p);
  12938                 ep_list_p = ep_list_p->next;
  12939             }
  12940         }
  12941     }
  12942 
  12943     _BCM_OAM_UNLOCK(oc);
  12944 
  12945 }
  12946 void _bcm_sb2_oam_ma_idx_to_ep_id_mapping_print(int unit)
  12947 {
  12948     _bcm_oam_control_t   *oc = NULL;            /* Pointer to control structure.    */
  12949     int i = 0;
  12950     int rv = BCM_E_NONE;
  12951 
  12952     rv = _bcm_sb2_oam_control_get(unit, &oc);
  12953     if ((BCM_FAILURE(rv)) || (oc == NULL)) {
  12954         return;
  12955     }
  12956     _BCM_OAM_LOCK(oc);
  12957 
  12958     if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) {
  12959         for (i = 0; i < (oc->ma_idx_count + oc->egr_ma_idx_count);i++) {
  12960             if (oc->_bcm_oam_ma_idx_to_ep_id_map[i] != _BCM_OAM_INVALID_INDEX) {
  12961                 LOG_CLI((BSL_META_U(unit,"MA_IDX = %d EP_ID = %d\r\n"),
  12962                         i, oc->_bcm_oam_ma_idx_to_ep_id_map[i]));
  12963             } 
  12964         }
  12965     }
  12966     _BCM_OAM_UNLOCK(oc);
  12967 } 
  12968 #endif
  12969 
  12970 #if defined(BCM_WARM_BOOT_SUPPORT)
  12971 #ifdef _SABER2_DEBUG
  12972 /*
  12973  * Function:
  12974  *     _bcm_sb2_oam_tx_counter_recover
  12975  * Purpose:
  12976  *     Recover Rx counter for MEP 
  12977  * Parameters:
  12978  *     unit      - (IN) BCM device number
  12979  * Retruns:
  12980  *     BCM_E_XXX
  12981  */
  12982 STATIC int
  12983 _bcm_sb2_oam_tx_counter_recover(int unit, soc_mem_t  mem, 
  12984                                 uint32 *entry,
  12985                                 _bcm_oam_hash_data_t   *h_data_p)
  12986 {
  12987     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
  12988     int           rv = BCM_E_NONE;/* Operation return status.         */
  12989     int           up_mep = 0;
  12990     sb2_mep_ctr_info_t  *ctr_info;
  12991     shr_aidxres_list_handle_t *ctr_pool;
  12992     int           *map_id;
  12993     int           ctr_type = 0;
  12994     int           ctr_valid = 0;
  12995     int           ctr_mdl = 0;
  12996     int           ctr_pool_id = 0;
  12997     uint32        profile_index = 0;
  12998     uint32        map_ptr = 0;
  12999 
  13000     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  13001     ctr_info = sb2_mep_ctr_info;
  13002     if (mem == MP_GROUPm) {
  13003         up_mep = 1;
  13004         map_id = &h_data_p->pri_map_index;
  13005     } else if (mem == EGR_MP_GROUPm) {
  13006         map_id = &h_data_p->egr_pri_map_index;
  13007     } else {
  13008         return BCM_E_INTERNAL; 
  13009     }
  13010     ctr_pool = oc->ing_lm_ctr_pool;
  13011     ctr_valid = soc_mem_field32_get(unit, mem, 
  13012                                     (uint32 *)entry, ctr_info[0].ctr_valid);
  13013     ctr_pool_id = soc_mem_field32_get(unit, mem,
  13014                                     (uint32 *)entry, ctr_info[0].ctr_pool_id);
  13015 
  13016     if (ctr_valid) {
  13017         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13018                                                  ctr_info[0].ctr_mep_type); 
  13019         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13020                                                  ctr_info[0].ctr_mep_mdl); 
  13021         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  13022             h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13023                                                  ctr_info[0].ctr_base_ptr);
  13024 
  13025             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  13026             map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13027                                                   ctr_info[0].ctr_profile);
  13028 
  13029             profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr);
  13030             rv = _bcm_sb2_service_pri_map_info_id_get(unit, 
  13031                    profile_index, 
  13032                     map_id);
  13033 
  13034             if (BCM_FAILURE(rv)) {
  13035                 LOG_ERROR(BSL_LS_BCM_OAM,
  13036                           (BSL_META_U(unit,
  13037                                       "OAM(unit %d) Error: Service pri map id get failed "
  13038                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13039                 return (rv);
  13040             }
  13041             /* Allocate 8 consecutive couters from the pool */
  13042             rv =  shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id],
  13043                                                        h_data_p->tx_ctr, 8);
  13044             if (BCM_FAILURE(rv)) {
  13045                 LOG_ERROR(BSL_LS_BCM_OAM,
  13046                           (BSL_META_U(unit,
  13047                                       "OAM(unit %d) Error: LM counter block alloc failed "
  13048                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13049                 return (rv);
  13050             }
  13051         }
  13052     }
  13053     ctr_valid = soc_mem_field32_get(unit, mem, 
  13054                                     (uint32 *)entry, ctr_info[1].ctr_valid);
  13055     ctr_pool_id = soc_mem_field32_get(unit, mem,
  13056                                     (uint32 *)entry, ctr_info[1].ctr_pool_id);
  13057     if (ctr_valid) {
  13058         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13059                                                  ctr_info[1].ctr_mep_type); 
  13060         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13061                                                  ctr_info[1].ctr_mep_mdl); 
  13062         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  13063             h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13064                                                  ctr_info[1].ctr_base_ptr);
  13065 
  13066             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  13067             map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13068                                                   ctr_info[1].ctr_profile);
  13069             profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr);
  13070             rv = _bcm_sb2_service_pri_map_info_id_get(unit, 
  13071                    profile_index, 
  13072                     map_id);
  13073 
  13074             if (BCM_FAILURE(rv)) {
  13075                 LOG_ERROR(BSL_LS_BCM_OAM,
  13076                           (BSL_META_U(unit,
  13077                                       "OAM(unit %d) Error: Service pri map id get failed "
  13078                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13079                 return (rv);
  13080             }
  13081             /* Allocate 8 consecutive couters from the pool */
  13082             rv =  shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id],
  13083                                                         h_data_p->tx_ctr, 8);
  13084             if (BCM_FAILURE(rv)) {
  13085                 LOG_ERROR(BSL_LS_BCM_OAM,
  13086                           (BSL_META_U(unit,
  13087                                       "OAM(unit %d) Error: LM counter block alloc failed "
  13088                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13089                 return (rv);
  13090             }
  13091         }
  13092     }
  13093     return (rv);
  13094 }
  13095 
  13096 #endif /* _SABER2_DEBUG */
  13097 
  13098 /*
  13099  * Function:
  13100  *     _bcm_sb2_oam_rx_counter_recover
  13101  * Purpose:
  13102  *     Recover Rx counter for MEP 
  13103  * Parameters:
  13104  *     unit      - (IN) BCM device number
  13105  * Retruns:
  13106  *     BCM_E_XXX
  13107  */
  13108 STATIC int
  13109 _bcm_sb2_oam_rx_counter_recover(int unit, soc_mem_t  mem, 
  13110                                 uint32 *entry,
  13111                                 _bcm_oam_hash_data_t   *h_data_p)
  13112 {
  13113     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
  13114     int           rv = BCM_E_NONE;/* Operation return status.         */
  13115     int           up_mep = 0;
  13116     sb2_mep_ctr_info_t  *ctr_info;
  13117     shr_aidxres_list_handle_t *ctr_pool;
  13118     int           *map_id;
  13119     int           ctr_valid = 0;
  13120     int           ctr_mdl = 0;
  13121     int           ctr_type = 0;
  13122     int           ctr_pool_id = 0;
  13123     int           ctr_base_ptr = 0;
  13124     uint32        profile_index = 0;
  13125     uint32        map_ptr       = 0;
  13126     
  13127                                                         
  13128 
  13129     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  13130     ctr_info = sb2_mep_ctr_info;
  13131     if (mem == EGR_MP_GROUPm) {
  13132         if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 
  13133             up_mep = 1;
  13134         }
  13135         map_id = &h_data_p->egr_pri_map_index;
  13136     } else {
  13137         map_id = &h_data_p->pri_map_index;
  13138     } 
  13139     ctr_pool = oc->ing_lm_ctr_pool;
  13140     ctr_valid = soc_mem_field32_get(unit, mem, 
  13141                                     (uint32 *)entry, ctr_info[0].ctr_valid);
  13142     ctr_pool_id = soc_mem_field32_get(unit, mem,
  13143                                     (uint32 *)entry, ctr_info[0].ctr_pool_id);
  13144 
  13145     if (ctr_valid) {
  13146         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13147                                                  ctr_info[0].ctr_mep_type); 
  13148         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13149                                                  ctr_info[0].ctr_mep_mdl); 
  13150         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  13151             ctr_base_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13152                                                  ctr_info[0].ctr_base_ptr);
  13153             /* Encode pool id as well in the ctr id */
  13154             h_data_p->rx_ctr = ctr_base_ptr | (ctr_pool_id << 24);  
  13155 
  13156             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  13157             map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13158                                                   ctr_info[0].ctr_profile);
  13159             profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr);
  13160             rv = _bcm_sb2_service_pri_map_info_id_get(unit, 
  13161                    profile_index, 
  13162                     map_id);
  13163             
  13164             if (BCM_FAILURE(rv)) {
  13165                 LOG_ERROR(BSL_LS_BCM_OAM,
  13166                           (BSL_META_U(unit,
  13167                                       "OAM(unit %d) Error: Failed to get map"
  13168                                       "id from hw idx(EP=%d) - %s.\n"), unit,
  13169                            h_data_p->ep_id, bcm_errmsg(rv)));
  13170                 return (rv);
  13171             }
  13172             rv = _bcm_sb2_service_pri_map_reference_add(unit, *map_id);
  13173             if (BCM_FAILURE(rv)) {
  13174                 LOG_ERROR(BSL_LS_BCM_OAM,
  13175                           (BSL_META_U(unit,
  13176                                       "OAM(unit %d) Error: LM counter profile ref count "
  13177                                       "increment failed (EP=%d) - %s.\n"), unit,
  13178                            h_data_p->ep_id, bcm_errmsg(rv)));
  13179                 return (rv);
  13180             }
  13181             /* Allocate 8 consecutive couters from the pool */
  13182             rv =  shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id],
  13183                                                        ctr_base_ptr, 8);
  13184             if (BCM_FAILURE(rv)) {
  13185                 LOG_ERROR(BSL_LS_BCM_OAM,
  13186                           (BSL_META_U(unit,
  13187                                       "OAM(unit %d) Error: LM counter block alloc failed "
  13188                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13189                 return (rv);
  13190             }
  13191             h_data_p->ctr_field_id = 0;
  13192         }
  13193     }
  13194     ctr_valid = soc_mem_field32_get(unit, mem, 
  13195                                     (uint32 *)entry, ctr_info[1].ctr_valid);
  13196     ctr_pool_id = soc_mem_field32_get(unit, mem,
  13197                                     (uint32 *)entry, ctr_info[1].ctr_pool_id);
  13198     if (ctr_valid) {
  13199         ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13200                                                  ctr_info[1].ctr_mep_type); 
  13201         ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry,
  13202                                                  ctr_info[1].ctr_mep_mdl); 
  13203         if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) {
  13204             ctr_base_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13205                                                  ctr_info[1].ctr_base_ptr);
  13206             /* Encode pool id as well in the ctr id */
  13207             h_data_p->rx_ctr = ctr_base_ptr | (ctr_pool_id << 24);  
  13208 
  13209             h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  13210             map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  13211                                                   ctr_info[1].ctr_profile);
  13212             profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr);
  13213             rv = _bcm_sb2_service_pri_map_info_id_get(unit, 
  13214                    profile_index, 
  13215                     map_id);
  13216             
  13217             if (BCM_FAILURE(rv)) {
  13218                 LOG_ERROR(BSL_LS_BCM_OAM,
  13219                           (BSL_META_U(unit,
  13220                                       "OAM(unit %d) Error: Failed to get map"
  13221                                       "id from hw idx(EP=%d) - %s.\n"), unit,
  13222                            h_data_p->ep_id, bcm_errmsg(rv)));
  13223                 return (rv);
  13224             }
  13225             rv = _bcm_sb2_service_pri_map_reference_add(unit, *map_id);
  13226             if (BCM_FAILURE(rv)) {
  13227                 LOG_ERROR(BSL_LS_BCM_OAM,
  13228                           (BSL_META_U(unit,
  13229                                       "OAM(unit %d) Error: LM counter profile ref count  "
  13230                                       "increment failed (EP=%d) - %s.\n"), unit,
  13231                            h_data_p->ep_id, bcm_errmsg(rv)));
  13232                 return (rv);
  13233             }
  13234             /* Allocate 8 consecutive couters from the pool */
  13235             rv =  shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id],
  13236                                                       ctr_base_ptr, 8);
  13237             if (BCM_FAILURE(rv)) {
  13238                 LOG_ERROR(BSL_LS_BCM_OAM,
  13239                           (BSL_META_U(unit,
  13240                                       "OAM(unit %d) Error: LM counter block alloc failed "
  13241                                       "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  13242                 return (rv);
  13243             }
  13244             h_data_p->ctr_field_id = 1;
  13245         }
  13246     }
  13247     return (rv);
  13248 }
  13249 /*
  13250  * Function:
  13251  *     _bcm_sb2_oam_endpoint_alloc
  13252  * Purpose:
  13253  *     Allocate an endpoint memory element.
  13254  * Parameters:
  13255  *     ep_pp - (IN/OUT) Pointer to endpoint address pointer.
  13256  * Returns:
  13257  *     BCM_E_XXX
  13258  */
  13259 STATIC int
  13260 _bcm_sb2_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp)
  13261 {
  13262     bcm_oam_endpoint_info_t *ep_p = NULL;
  13263 
  13264     _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t,
  13265                    sizeof(bcm_oam_endpoint_info_t), "Endpoint info");
  13266     if (NULL == ep_p) {
  13267         return (BCM_E_MEMORY);
  13268     }
  13269     
  13270     *ep_pp = ep_p;
  13271 
  13272     return (BCM_E_NONE);
  13273 
  13274 }
  13275 
  13276 STATIC void
  13277 _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data(
  13278                                                _bcm_lmdm_oam_scache_info_t *src,
  13279                                                _bcm_oam_hash_data_t *dest)
  13280 {
  13281 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  13282     dest->vlan = src->vlan;
  13283     dest->inner_vlan = src->inner_vlan;
  13284     dest->inner_tpid = src->inner_tpid;
  13285     dest->outer_tpid = src->outer_tpid;
  13286     dest->vlan_pri    = src->vlan_pri;
  13287     dest->inner_vlan_pri = src->inner_vlan_pri;
  13288     sal_memcpy(&(dest->dst_mac_address), &(src->dst_mac_address),
  13289             sizeof(bcm_mac_t));
  13290     sal_memcpy(&(dest->src_mac_address), &(src->src_mac_address),
  13291             sizeof(bcm_mac_t));
  13292     dest->lm_dm_int_flag      = src->lm_dm_int_flag;
  13293     dest->lm_dm_uc_session_id = src->lm_dm_uc_session_id;
  13294 #endif
  13295 #if defined(INCLUDE_MPLS_LM_DM)
  13296     dest->group_index = src->group_index;
  13297 #endif
  13298     dest->vpn = src->vpn;
  13299     dest->egr_ctr_field_id         = src->egr_ctr_field_id;
  13300 }
  13301 
  13302 STATIC void
  13303 _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info(
  13304                                          _bcm_oam_hash_data_t *src,
  13305                                          _bcm_lmdm_oam_scache_info_t *dest)
  13306 {
  13307 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  13308     dest->vlan = src->vlan;
  13309     dest->inner_vlan = src->inner_vlan;
  13310     dest->inner_tpid = src->inner_tpid;
  13311     dest->outer_tpid = src->outer_tpid;
  13312     dest->vlan_pri    = src->vlan_pri;
  13313     dest->inner_vlan_pri = src->inner_vlan_pri;
  13314     sal_memcpy(&(dest->dst_mac_address), &(src->dst_mac_address),
  13315             sizeof(bcm_mac_t));
  13316     sal_memcpy(&(dest->src_mac_address), &(src->src_mac_address),
  13317             sizeof(bcm_mac_t));
  13318     dest->lm_dm_int_flag      = src->lm_dm_int_flag;
  13319     dest->lm_dm_uc_session_id = src->lm_dm_uc_session_id;
  13320 #endif
  13321 #if defined(INCLUDE_MPLS_LM_DM)
  13322     dest->group_index = src->group_index;
  13323 #endif
  13324     dest->vpn = src->vpn;
  13325     dest->egr_ctr_field_id         = src->egr_ctr_field_id;
  13326 } 
  13327 
  13328 #if defined(INCLUDE_MPLS_LM_DM)
  13329 STATIC void
  13330 _bcm_sb2_oam_copy_egr_label_to_scache(
  13331         _bcm_oam_hash_data_t *src, _bcm_sb2_oam_egr_label_scache_info_t *dest)
  13332 {
  13333     dest->egr_label = src->egr_label;
  13334     dest->exp = src->egr_label_exp;
  13335     dest->ttl = src->egr_label_ttl;
  13336 }
  13337 
  13338 STATIC void
  13339 _bcm_sb2_oam_copy_egr_label_scache_to_hash_data(
  13340         _bcm_sb2_oam_egr_label_scache_info_t *src, _bcm_oam_hash_data_t *dst)
  13341 {
  13342     dst->egr_label = src->egr_label;
  13343     dst->egr_label_exp = src->exp;
  13344     dst->egr_label_ttl = src->ttl;
  13345 }
  13346 #endif
  13347 
  13348 STATIC void
  13349 _bcm_sb2_oam_lmdm_scache_info_set(_bcm_oam_hash_data_t *h_data_p,
  13350                                   uint8 *scache,
  13351                                   _bcm_oam_control_t  *oc)
  13352 {
  13353     _bcm_lmdm_oam_scache_info_t *scache_info;
  13354 
  13355     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  13356 #if defined(INCLUDE_ETH_LM_DM)
  13357         scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache +
  13358          _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index));
  13359         _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info(h_data_p, scache_info);
  13360 #endif
  13361     } else {
  13362         scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache +
  13363          _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index));
  13364         _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info(h_data_p, scache_info);
  13365     }
  13366 }
  13367 
  13368 STATIC void
  13369 _bcm_sb2_oam_lmdm_info_recover(_bcm_oam_hash_data_t *h_data_p,
  13370                                uint8 *scache,
  13371                                _bcm_oam_control_t  *oc)
  13372 {
  13373     _bcm_lmdm_oam_scache_info_t *scache_info;
  13374 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM)
  13375     int                         rv = BCM_E_NONE;
  13376 #endif
  13377 
  13378     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  13379 #if defined(INCLUDE_ETH_LM_DM)
  13380         scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache +
  13381          _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index));
  13382         _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data(scache_info, h_data_p);
  13383 #endif
  13384     } else {
  13385         scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache +
  13386          _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index));
  13387         _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data(scache_info, h_data_p);
  13388     }
  13389 
  13390    if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  13391 #if defined(INCLUDE_MPLS_LM_DM)
  13392        if (h_data_p->lm_dm_uc_session_id != 0) {
  13393            rv = shr_idxres_list_reserve(oc->mpls_lm_dm_pool,
  13394                 h_data_p->lm_dm_uc_session_id, h_data_p->lm_dm_uc_session_id);
  13395 
  13396            if (BCM_FAILURE(rv)) {
  13397                LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "MPLS_LM_DM (unit %d) Error:"
  13398                                " Session Id alloc failed EP:%d %s.\n"), oc->unit, h_data_p->ep_id,
  13399                            bcm_errmsg(rv)));
  13400                return;
  13401            }
  13402            if(mpls_oam_id_map != NULL) {
  13403                mpls_oam_id_map[h_data_p->lm_dm_uc_session_id - 1] = h_data_p->ep_id;
  13404            }
  13405            oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = h_data_p->ep_id;
  13406        }
  13407 #endif
  13408     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  13409 #if defined(INCLUDE_ETH_LM_DM)
  13410         if (h_data_p->lm_dm_uc_session_id != 0) {
  13411             rv = shr_idxres_list_reserve(oc->eth_lm_dm_pool,
  13412                 h_data_p->lm_dm_uc_session_id, h_data_p->lm_dm_uc_session_id);
  13413 
  13414             if (BCM_FAILURE(rv)) {
  13415                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "ETH_LM_DM (unit %d) Error:"
  13416                                 " Session Id alloc failed EP:%d %s.\n"), oc->unit, h_data_p->ep_id,
  13417                             bcm_errmsg(rv)));
  13418                 return;
  13419             }
  13420             if(eth_oam_id_map != NULL) {
  13421                 eth_oam_id_map[h_data_p->lm_dm_uc_session_id - 1] = h_data_p->ep_id;
  13422             }
  13423             oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = h_data_p->ep_id;
  13424         }
  13425 #endif
  13426     }
  13427 }
  13428 
  13429 /*
  13430  * Function:
  13431  *     _bcm_sb2_oam_sync
  13432  * Purpose:
  13433  *     Store OAM configuration to level two storage cache memory.
  13434  * Parameters:
  13435  *     unit - (IN) Device unit number
  13436  * Returns:
  13437  *     BCM_E_XXX
  13438  */
  13439 int
  13440 _bcm_sb2_oam_sync(int unit)
  13441 {
  13442     int                 rv;  /* Operation return status. */
  13443     _bcm_oam_control_t  *oc;
  13444     int                 stable_size;
  13445     soc_scache_handle_t scache_handle;
  13446     uint8               *oam_scache = NULL;
  13447     uint8               *lm_dm_scache_info_ptr  = NULL;
  13448     int                 grp_idx;
  13449     int                 ma_offset;
  13450     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  13451     int                 group_count = 0;
  13452 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH)
  13453     int                 itr;
  13454     _bcm_oam_pm_profile_control_t *pmc = NULL;
  13455 #endif
  13456     _bcm_oam_ep_list_t  *ep_list_p = NULL;
  13457     _bcm_oam_hash_data_t ep_data;
  13458 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  13459     uint8                 trunk_index;
  13460 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  13461     _bcm_oam_hash_data_t *h_data_p = NULL;
  13462     int                   idx = 0;
  13463     uint8               *tmp_oam_scache = NULL;
  13464     int                  trunk_idx_size = 0; 
  13465 
  13466     /* Get OAM module storage size. */
  13467     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  13468 
  13469     /* If level 2 store is not configured return from here. */
  13470     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
  13471         return BCM_E_NONE;
  13472     }
  13473 
  13474     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  13475 
  13476     /* Check if memory has already been allocated */
  13477     rv = _bcm_esw_scache_ptr_get(unit,
  13478                                  scache_handle,
  13479                                  0,
  13480                                  0,
  13481                                  &oam_scache,
  13482                                  BCM_WB_DEFAULT_VERSION,
  13483                                  NULL
  13484                                  );
  13485     if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) {
  13486         BCM_IF_ERROR_RETURN(bcm_sb2_oam_scache_alloc(unit));
  13487         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, &oam_scache,
  13488                                      BCM_WB_DEFAULT_VERSION, NULL);
  13489         if (BCM_FAILURE(rv)) {
  13490             /*
  13491              * COVERITY
  13492              *
  13493              * Coverity complains that oam_scache is not freed when it goes out
  13494              * of scope, but the ptr should be freed by the scache module
  13495              */
  13496             /* coverity[leaked_storage] */
  13497             return rv;
  13498         }
  13499         if (NULL == oam_scache) {
  13500             return BCM_E_NOT_FOUND;
  13501         }
  13502     } else if (BCM_FAILURE(rv)) {
  13503         /*
  13504          * COVERITY
  13505          *
  13506          * Coverity complains that oam_scache is not freed when it goes out
  13507          * of scope, but the ptr should be freed by the scache module
  13508          */
  13509         /* coverity[leaked_storage : FALSE] */
  13510         return rv;
  13511     }
  13512 
  13513     /* Get handle to control structure. */
  13514     rv = _bcm_sb2_oam_control_get(unit, &oc);
  13515     if (BCM_FAILURE(rv)) {
  13516         /*
  13517          * COVERITY
  13518          *
  13519          * Coverity complains that oam_scache is not freed when it goes out
  13520          * of scope, but the ptr should be freed by the scache module
  13521          */
  13522         /* coverity[leaked_storage] */
  13523         return rv;
  13524     }
  13525     _BCM_OAM_LOCK(oc);
  13526 
  13527     /* Store the FP groups */
  13528     sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t));
  13529     oam_scache += sizeof(bcm_field_group_t);
  13530 
  13531     sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t));
  13532     oam_scache += sizeof(bcm_field_group_t);
  13533 
  13534     sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t));
  13535     oam_scache += sizeof(bcm_field_group_t);
  13536 
  13537     sal_memcpy(oam_scache, &group_count, sizeof(int));
  13538     oam_scache += sizeof(int);
  13539 
  13540     group_p = oc->group_info;
  13541     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
  13542     {
  13543         /* Check if the group is in use. */
  13544         if (BCM_E_EXISTS
  13545                 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
  13546 
  13547             sal_memcpy(oam_scache, group_p[grp_idx].name,
  13548                        BCM_OAM_GROUP_NAME_LENGTH);
  13549 
  13550             oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
  13551         }
  13552     }
  13553 #if defined(INCLUDE_BHH)
  13554     if (oc->ukernel_not_ready == 0) {
  13555         /*Store MA_INDEX allocated to BHH*/
  13556         for (idx = 0; idx < _SHR_BITDCLSIZE (oc->ma_idx_count); idx++) {
  13557             sal_memcpy(oam_scache, &oc->bhh_ma_index_in_use[idx],
  13558                        sizeof(SHR_BITDCL));
  13559             oam_scache += sizeof(SHR_BITDCL);
  13560         }
  13561 
  13562         /*Store BHH endpoint group ids */
  13563         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  13564             sal_memcpy(oam_scache, &oc->bhh_ep_grp_id[idx], sizeof(short));
  13565             oam_scache += sizeof(short);
  13566         }
  13567 
  13568         /*Store BHH endpoint VPN */
  13569         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  13570             sal_memcpy(oam_scache, &oc->bhh_ep_vpn[idx], sizeof(short));
  13571             oam_scache += sizeof(short);
  13572         }
  13573     }
  13574 #endif
  13575 
  13576     /* Store logical endpoint indexes
  13577        Following is scache allocation for different types of EPs
  13578        -----------------------------------------------------------------------
  13579       | Rx DownMEP indexes | Rx UpMEP indexes | RMEP indexes | Tx MEP indexes |
  13580        -----------------------------------------------------------------------
  13581      */
  13582     sal_memset(oam_scache, 0,
  13583                _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE +
  13584                _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE);
  13585 
  13586     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
  13587     {
  13588         if (group_p[grp_idx].in_use == 1) {
  13589             ep_list_p = *(group_p[grp_idx].ep_list);
  13590             while (ep_list_p != NULL) {
  13591                 sal_memcpy(&ep_data, ep_list_p->ep_data_p, sizeof(_bcm_oam_hash_data_t)); 
  13592                 if (ep_data.type == bcmOAMEndpointTypeEthernet ||
  13593                     MPLS_LM_DM_ENDPOINT_TYPE((&ep_data))) {
  13594 
  13595                     if (ep_data.is_remote) {
  13596                         sal_memcpy(oam_scache + 
  13597                                 (_BCM_SB2_OAM_RMEP_SCACHE_LOCATION(ep_data.remote_index)), 
  13598                                 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 
  13599                     } else {
  13600                         if (ep_data.local_tx_enabled) {
  13601                             sal_memcpy(oam_scache + 
  13602                                 (_BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(ep_data.local_tx_index)),
  13603                                     &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  13604                         }
  13605                         if (ep_data.local_rx_enabled) {
  13606                             if (ep_data.flags & BCM_OAM_ENDPOINT_UP_FACING) {
  13607                                 sal_memcpy(oam_scache + 
  13608                                         (_BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(ep_data.local_rx_index)),
  13609                                         &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  13610                             } else {
  13611                             _bcm_sb2_oam_ma_index_offset_get(unit, &ep_data, &ma_offset);
  13612                             ep_data.local_rx_index = ep_data.ma_base_index + ma_offset;
  13613                             sal_memcpy(oam_scache + 
  13614                                     (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ep_data.local_rx_index)),
  13615                                         &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
  13616                             }
  13617 
  13618                             lm_dm_scache_info_ptr = oam_scache +
  13619                                 _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  13620 
  13621                             _bcm_sb2_oam_lmdm_scache_info_set(&ep_data, lm_dm_scache_info_ptr, oc);
  13622 #if defined(INCLUDE_MPLS_LM_DM)
  13623                             if (MPLS_LM_DM_ENDPOINT_TYPE((&ep_data))) {
  13624                                 lm_dm_scache_info_ptr += _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE +
  13625                                     _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(ep_data.local_rx_index);
  13626                                 _bcm_sb2_oam_copy_egr_label_to_scache(&ep_data,
  13627                                     (_bcm_sb2_oam_egr_label_scache_info_t *)lm_dm_scache_info_ptr);
  13628                             }
  13629 #endif
  13630                         }
  13631                     }
  13632                 }
  13633                 ep_list_p = ep_list_p->next;
  13634             }
  13635         }
  13636     }
  13637     oam_scache +=  _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  13638     oam_scache += _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE;
  13639     oam_scache += _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE;
  13640 
  13641 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH)
  13642     /* Store pm profile */
  13643     if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 
  13644             (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  13645             (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  13646 
  13647         pmc = pm_profile_control[unit];
  13648 
  13649         if (!pmc) {
  13650             _BCM_OAM_UNLOCK(oc);
  13651             /*
  13652              * COVERITY
  13653              *
  13654              * Coverity complains that oam_scache is not freed when it goes out
  13655              * of scope, but freeing the ptr is scache module's responsibility
  13656              */
  13657             /* coverity[leaked_storage] */
  13658             return (BCM_E_INIT);
  13659         }
  13660         for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) {
  13661             sal_memcpy(oam_scache,
  13662                     &(pmc->profile_info[itr]), sizeof(_bcm_oam_pm_profile_int_info_t));
  13663             oam_scache += sizeof(_bcm_oam_pm_profile_int_info_t);
  13664         }
  13665 
  13666         /* Store Ep id to PM mapping */
  13667         sal_memset(oam_scache, -1, _bcm_sb2_oam_pmid_scache_size(unit));
  13668 
  13669         for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) {
  13670             if (group_p[grp_idx].in_use == 1) {
  13671                 ep_list_p = *(group_p[grp_idx].ep_list);
  13672                 while (ep_list_p != NULL) {
  13673 
  13674                     if (!(ep_list_p->ep_data_p->is_remote) &&
  13675                             (ep_list_p->ep_data_p->local_rx_enabled)) {
  13676 #if defined(INCLUDE_ETH_LM_DM)
  13677                         if (ETH_TYPE(ep_list_p->ep_data_p->type) &&
  13678                                 (ep_list_p->ep_data_p->lm_dm_uc_session_id)) {
  13679                             int8 profile_id;
  13680                             profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached);
  13681 
  13682                             sal_memcpy(oam_scache +
  13683                                     _bcm_sb2_oam_eth_pmid_scache_loc(unit,
  13684                                         ep_list_p->ep_data_p->lm_dm_uc_session_id - 1),
  13685                                     &(profile_id),
  13686                                     sizeof (int8));
  13687                         }
  13688 #endif
  13689 #if defined(INCLUDE_MPLS_LM_DM)
  13690                         if(MPLS_LM_DM_ENDPOINT_TYPE(ep_list_p->ep_data_p) &&
  13691                                 (ep_list_p->ep_data_p->lm_dm_uc_session_id)) {
  13692                             int8 profile_id;
  13693                             profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached);
  13694 
  13695                             sal_memcpy(oam_scache +
  13696                                     _bcm_sb2_oam_mpls_pmid_scache_loc(unit,
  13697                                         ep_list_p->ep_data_p->lm_dm_uc_session_id - 1),
  13698                                     &(profile_id),
  13699                                     sizeof (int8));
  13700                         }
  13701 #endif
  13702 #if defined(INCLUDE_BHH)
  13703                         if(BHH_TYPE(ep_list_p->ep_data_p->type)) {
  13704                             int8 profile_id;
  13705                             profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached);
  13706 
  13707                             sal_memcpy(oam_scache + _bcm_sb2_oam_bhh_pmid_scache_loc(unit,
  13708                                         BCM_OAM_BHH_GET_UKERNEL_EP(ep_list_p->ep_data_p->ep_id)),
  13709                                     &(profile_id),
  13710                                     sizeof (int8));
  13711                         }
  13712 #endif
  13713                     }
  13714                     ep_list_p = ep_list_p->next;
  13715                 }
  13716             }
  13717         }
  13718         oam_scache += _bcm_sb2_oam_pmid_scache_size(unit);
  13719     }
  13720 #endif /* defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) */
  13721 
  13722 #if defined(INCLUDE_BHH)
  13723     sal_memcpy(oam_scache, &bhh_lsp_egr_lookup_key, sizeof(uint8));
  13724     oam_scache += sizeof(uint8);
  13725 #endif /* INCLUDE_BHH */
  13726 
  13727 #if defined(INCLUDE_MPLS_LM_DM)
  13728     /* Hardcoded to MEP_ID for now */
  13729     *((uint8 *)(oam_scache)) = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID;
  13730     oam_scache += sizeof(uint8);
  13731 #endif /* INCLUDE_MPLS_LM_DM */
  13732 
  13733 #if defined(INCLUDE_BHH)
  13734     if(soc_feature(unit, soc_feature_bhh)) {
  13735         if (oc->ukernel_not_ready == 0) {
  13736 
  13737             /*Store BHH endpoint VLAN_PRI and INNER_VLAN_PRI*/
  13738             for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  13739                 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)];
  13740                 if(h_data_p->in_use) {
  13741                     sal_memcpy(oam_scache, &h_data_p->vlan_pri, sizeof(uint8));
  13742                     oam_scache += sizeof(uint8);
  13743                     sal_memcpy(oam_scache, &h_data_p->inner_vlan_pri, sizeof(uint8));
  13744                     oam_scache += sizeof(uint8);
  13745                 } else {
  13746                     oam_scache += sizeof(uint8) *  2;
  13747                 }
  13748             }
  13749         }
  13750     }
  13751 #endif
  13752 
  13753     sal_memcpy(oam_scache, &(oc->eth_oam_mp_group_vlan_key), sizeof(uint8));
  13754     oam_scache += sizeof(uint8);
  13755 
  13756     tmp_oam_scache = oam_scache;
  13757 #if defined(INCLUDE_BHH)
  13758     if(soc_feature(unit, soc_feature_bhh)) {
  13759         if (oc->ukernel_not_ready == 0) {
  13760             for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  13761                 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)];
  13762                 if (h_data_p->in_use) {
  13763                     trunk_index = h_data_p->trunk_index;
  13764                     sal_memcpy(oam_scache, &trunk_index, sizeof(uint8));
  13765                     oam_scache += sizeof(uint8);
  13766                 }
  13767             }
  13768             trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  13769         }
  13770     }
  13771 #endif /* INCLUDE_BHH */
  13772 #if defined(INCLUDE_MPLS_LM_DM)
  13773     if (oc->mpls_lm_dm_ukernel_ready) {
  13774         for (idx = 0; idx < oc->ep_count; idx++) {
  13775             h_data_p = &oc->oam_hash_data[idx];
  13776             if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && (h_data_p->in_use)) {
  13777                 trunk_index = h_data_p->trunk_index;
  13778                 sal_memcpy(oam_scache, &trunk_index, sizeof(uint8));
  13779                 oam_scache += sizeof(uint8);
  13780             }
  13781         }
  13782         trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  13783     }
  13784 #endif /* INCLUDE_MPLS_LM_DM */
  13785     /* The above code doesnt move the scache pointer to the end of
  13786      * its allocated section size. So we move it here.
  13787      */
  13788     oam_scache = tmp_oam_scache + trunk_idx_size;
  13789 
  13790     for (idx = 0; idx < oc->ep_count; idx++) {
  13791         h_data_p = &oc->oam_hash_data[idx];
  13792         if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) {
  13793             sal_memcpy(oam_scache, &(h_data_p->flags), sizeof(uint32));
  13794         }
  13795         oam_scache += sizeof(uint32);
  13796     }
  13797 
  13798 #if defined(INCLUDE_BHH)
  13799     sal_memcpy(oam_scache, &sb2_oam_mpls_tp_ach_channel_type,
  13800                sizeof(sb2_oam_mpls_tp_ach_channel_type));
  13801     oam_scache += sizeof(sb2_oam_mpls_tp_ach_channel_type);
  13802 #endif /* INCLUDE_BHH */
  13803 
  13804     _BCM_OAM_UNLOCK(oc);
  13805     /*
  13806      * COVERITY
  13807      *
  13808      * Coverity complains that oam_scache is not freed when it goes out
  13809      * of scope, but freeing the ptr is scache module's responsibility
  13810      */
  13811     /* coverity[leaked_storage] */
  13812     return (BCM_E_NONE);
  13813 }
  13814 
  13815 /*
  13816  * Function:
  13817  *     _bcm_sb2_oam_wb_group_recover
  13818  * Purpose:
  13819  *     Recover OAM group configuration.
  13820  * Parameters:
  13821  *     unit        - (IN) BCM device number
  13822  *     stable_size - (IN) OAM module Level2 storage size.
  13823  *     oam_scache  - (IN) Pointer to scache address pointer.
  13824  * Returns:
  13825  *     BCM_E_XXX
  13826  */
  13827 STATIC int
  13828 _bcm_sb2_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache)
  13829 {
  13830     int                    index;                    /* Hw table index.     */
  13831     _bcm_oam_group_data_t  *group_p;                 /* Group info pointer. */
  13832     maid_reduction_entry_t maid_entry;               /* Group entry info.   */
  13833     ma_state_entry_t       ma_state_ent;             /* Group state info.   */
  13834     int                    maid_reduction_valid = 0; /* Group valid.        */
  13835     int                    ma_state_valid = 0;       /* Group state valid.  */
  13836     _bcm_oam_control_t     *oc;                      /* Pointer to Control  */
  13837                                                      /* structure.          */
  13838     int                     rv;                      /* Operation return    */
  13839                                                      /* status.             */
  13840 
  13841     /* Control lock taken by calling routine. */
  13842     /* Get OAM control structure. */
  13843     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  13844 
  13845     for (index = 0; index < oc->group_count; index++) {
  13846 
  13847         rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index,
  13848                                   &maid_entry);
  13849         if (BCM_FAILURE(rv)) {
  13850             LOG_ERROR(BSL_LS_BCM_OAM,
  13851                       (BSL_META_U(unit,
  13852                                   "OAM(unit %d) Error: (GID=%d) MAID_REDUCTION table read"
  13853                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  13854             goto cleanup;
  13855         }
  13856 
  13857         rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent);
  13858         if (BCM_FAILURE(rv)) {
  13859             LOG_ERROR(BSL_LS_BCM_OAM,
  13860                       (BSL_META_U(unit,
  13861                                   "OAM(unit %d) Error: (GID=%d) MA_STATE table read"
  13862                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  13863             goto cleanup;
  13864         }
  13865 
  13866         maid_reduction_valid
  13867             = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf);
  13868 
  13869         ma_state_valid
  13870             = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf);
  13871 
  13872         if (maid_reduction_valid || ma_state_valid) {
  13873 
  13874             /* Entry must be valid in both the tables, else return error. */
  13875             if (!maid_reduction_valid || !ma_state_valid) {
  13876                 rv = BCM_E_INTERNAL;
  13877                 goto cleanup;
  13878             }
  13879 
  13880             /* Get the group memory pointer. */
  13881             group_p = &oc->group_info[index];
  13882             if (1 == group_p->in_use) {
  13883                 rv = BCM_E_INTERNAL;
  13884                 goto cleanup;
  13885             }
  13886 
  13887             if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
  13888 
  13889                 /* Set group name as zeros. */
  13890                 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH);
  13891 
  13892             } else {
  13893 
  13894                 /* Get the group name from stored info. */
  13895                 sal_memcpy(group_p->name, *oam_scache, 
  13896                                                   BCM_OAM_GROUP_NAME_LENGTH);
  13897                 *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH);
  13898             }
  13899 
  13900             /* Reserve the group index. */
  13901             rv = shr_idxres_list_reserve(oc->group_pool, index, index);
  13902             if (BCM_FAILURE(rv)) {
  13903                 LOG_ERROR(BSL_LS_BCM_OAM,
  13904                           (BSL_META_U(unit,
  13905                                       "OAM(unit %d) Error: (GID=%d) Index reserve "
  13906                                        " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  13907                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  13908                 goto cleanup;
  13909             }
  13910 
  13911             /* Create the linked list to maintain group endpoint information. */
  13912             _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *,
  13913                            sizeof(_bcm_oam_ep_list_t *), "EP list head");
  13914             if (NULL == group_p->ep_list) {
  13915                 rv = BCM_E_MEMORY;
  13916                 goto cleanup;
  13917             }
  13918 
  13919             /* Initialize head node.*/
  13920             *group_p->ep_list =  NULL;
  13921             group_p->in_use = 1;
  13922         }
  13923     }
  13924 
  13925     return (BCM_E_NONE);
  13926 
  13927 cleanup:
  13928 
  13929     if (BCM_E_EXISTS
  13930         == shr_idxres_list_elem_state(oc->group_pool, index)) {
  13931         shr_idxres_list_free(oc->group_pool, index);
  13932     }
  13933 
  13934     return (rv);
  13935 
  13936 }
  13937 
  13938 /*
  13939  * Function:
  13940  *     _bcm_sb2_oam_rmep_recover
  13941  * Purpose:
  13942  *     Recover OAM remote endpoint configuration.
  13943  * Parameters:
  13944  *     unit        - (IN) BCM device number
  13945  *     index       - (IN) Remote MEP hardware index.
  13946  *     l3_entry    - (IN) RMEP view table entry pointer.
  13947  * Returns:
  13948  *     BCM_E_XXX
  13949  */
  13950 STATIC int
  13951 _bcm_sb2_oam_rmep_recover(int unit,
  13952                           int index,
  13953                           l3_entry_1_entry_t *l3_entry,
  13954                           uint8 **scache,
  13955                           uint16 recovered_ver)
  13956 {
  13957     rmep_entry_t            rmep_entry;      /* Remote table entry.           */
  13958     _bcm_oam_hash_data_t    *h_data_p;       /* Endpoint hash data pointer.   */
  13959     _bcm_oam_control_t      *oc;             /* Pointer to control structure. */
  13960     int                     rv;              /* Operation return status.      */
  13961     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  13962     _bcm_oam_hash_key_t     hash_key;        /* Hash key buffer for lookup.   */
  13963     int                     ep_id;           /* Endpoint ID.                  */
  13964     int                     rmep_index;      /* Index of RMEP table           */ 
  13965 
  13966     LOG_DEBUG(BSL_LS_BCM_OAM,
  13967               (BSL_META_U(unit,
  13968                           "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover.\n"),
  13969                unit));
  13970     /*
  13971      * Get OAM control structure.
  13972      *     Note: Lock taken by calling routine.
  13973      */
  13974     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  13975 
  13976     rmep_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf);
  13977     if (recovered_ver >= BCM_WB_VERSION_1_1) {
  13978         /* Recover EP index from scache */ 
  13979         sal_memcpy(&ep_id, *scache + (_BCM_SB2_OAM_RMEP_SCACHE_LOCATION(rmep_index)),
  13980                 sizeof(bcm_oam_endpoint_t));
  13981         rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  13982         if (BCM_FAILURE(rv)) {
  13983             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  13984             LOG_ERROR(BSL_LS_BCM_OAM,
  13985                     (BSL_META_U(unit,
  13986                                 "OAM Error: (EP_ID=%d) Index reserve "
  13987                                 " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  13988             return (rv);
  13989         }
  13990 
  13991     } else {
  13992 
  13993         /* Allocate the next available endpoint index. */
  13994         rv = shr_idxres_list_alloc(oc->mep_pool,
  13995                 (shr_idxres_element_t *)&ep_id);
  13996         if (BCM_FAILURE(rv)) {
  13997             LOG_ERROR(BSL_LS_BCM_OAM,
  13998                     (BSL_META_U(unit,
  13999                                 "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"),
  14000                      unit, ep_id, bcm_errmsg(rv)));
  14001             return (rv);
  14002         }
  14003     }
  14004     h_data_p = &oc->oam_hash_data[ep_id];
  14005     if (1 == h_data_p->in_use) {
  14006         return(BCM_E_INTERNAL);
  14007     }
  14008 
  14009     /* 
  14010      * Clear the hash data element contents before
  14011      * storing values.
  14012      */
  14013     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  14014     h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14015     h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14016     h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  14017     h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  14018     h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  14019     h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  14020     h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  14021     h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  14022     h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14023     h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14024     h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14025     h_data_p->trunk_id = BCM_TRUNK_INVALID;
  14026     h_data_p->gport = 0;
  14027     /* Get RMEP table index from LMEP view entry. */
  14028     h_data_p->remote_index = rmep_index;
  14029     /* Get RMEP table entry contents. */
  14030     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
  14031     if (BCM_FAILURE(rv)) {
  14032         LOG_ERROR(BSL_LS_BCM_OAM,
  14033                   (BSL_META_U(unit,
  14034                               "OAM(unit %d) Error: RMEP (index=%d) read failed  - %s.\n"),
  14035                    unit, h_data_p->remote_index, bcm_errmsg(rv)));
  14036         goto cleanup;
  14037     }
  14038 
  14039    /* Has to be a valid RMEP, return error otherwise. */
  14040     if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) {
  14041         rv = BCM_E_INTERNAL;
  14042         goto cleanup;
  14043     }
  14044     h_data_p->ep_id = ep_id;
  14045 
  14046     h_data_p->is_remote = 1;
  14047 
  14048     h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE;
  14049     h_data_p->group_index
  14050         = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf);
  14051 
  14052     h_data_p->period
  14053         = _bcm_sb2_oam_ccm_hw_encode_to_msecs
  14054             ((int) soc_RMEPm_field32_get(unit, &rmep_entry,
  14055                                          RMEP_RECEIVED_CCMf));
  14056     h_data_p->name
  14057         = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__MEPIDf);
  14058 
  14059     h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX;
  14060     h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX;
  14061     h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14062     h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14063 
  14064     rv = shr_idxres_list_reserve(oc->rmep_pool,
  14065                                  h_data_p->remote_index,
  14066                                  h_data_p->remote_index);
  14067     if (BCM_FAILURE(rv)) {
  14068         LOG_ERROR(BSL_LS_BCM_OAM,
  14069                   (BSL_META_U(unit,
  14070                               "OAM(unit %d) Error: (RMEP=%d) Index reserve failed  - %s.\n"),
  14071                    unit, h_data_p->remote_index, bcm_errmsg(rv)));
  14072         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  14073         goto cleanup;
  14074     }
  14075 
  14076     h_data_p->in_use = 1;
  14077 
  14078     rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  14079     if (BCM_FAILURE(rv)) {
  14080         goto cleanup;
  14081     }
  14082 
  14083     rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  14084     if (BCM_FAILURE(rv)) {
  14085         _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
  14086         goto cleanup;
  14087     }
  14088 
  14089     bcm_oam_endpoint_info_t_init(ep_info);
  14090 
  14091     /* Set up endpoint information for key construction. */
  14092     ep_info->group = h_data_p->group_index;
  14093     ep_info->name = h_data_p->name;
  14094     ep_info->gport = h_data_p->gport;
  14095     ep_info->id= h_data_p->ep_id;
  14096 
  14097     if ((recovered_ver < BCM_WB_VERSION_1_9) 
  14098             || (!ETH_TYPE(h_data_p->type))) {
  14099         /* Calculate hash key for hash table insert operation. */
  14100         _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  14101 
  14102         rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  14103         if (BCM_FAILURE(rv)) {
  14104             LOG_ERROR(BSL_LS_BCM_OAM,
  14105                     (BSL_META_U(unit,
  14106                                 "OAM(unit %d) Error: Hash table insert failed "
  14107                                 "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  14108             _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
  14109             goto cleanup;
  14110         } else {
  14111             LOG_DEBUG(BSL_LS_BCM_OAM,
  14112                     (BSL_META_U(unit,
  14113                                 "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted"
  14114                                 " - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14115         }
  14116     }
  14117 
  14118     /* Add the H/w index to logical index mapping for RMEP */
  14119     oc->remote_endpoints[h_data_p->remote_index] = ep_info->id;
  14120 
  14121     sal_free(ep_info);
  14122     LOG_DEBUG(BSL_LS_BCM_OAM,
  14123               (BSL_META_U(unit,
  14124                           "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover - done.\n"),
  14125                unit));
  14126 
  14127     return (rv);
  14128 cleanup:
  14129     if (NULL != ep_info) {
  14130         sal_free(ep_info);
  14131     }
  14132     /* Release the endpoint ID if in use. */
  14133     if (BCM_E_EXISTS
  14134         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  14135         shr_idxres_list_free(oc->mep_pool, ep_id);
  14136     }
  14137 
  14138     /* Release the remote index if in use. */
  14139     if ((1 == h_data_p->in_use)
  14140         && (BCM_E_EXISTS
  14141             == shr_idxres_list_elem_state(oc->rmep_pool,
  14142                                           h_data_p->remote_index))) {
  14143         shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index);
  14144 
  14145     }
  14146     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  14147 
  14148     LOG_DEBUG(BSL_LS_BCM_OAM,
  14149               (BSL_META_U(unit,
  14150                           "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover - error_done.\n"),
  14151                unit));
  14152     return (rv);
  14153 }
  14154 
  14155 /*
  14156  * Function:
  14157  *     _bcm_sb2_oam_port_lmep_rx_config_recover
  14158  * Purpose:
  14159  *     Recover OAM local endpoint Rx configuration for port based DownMEPs.
  14160  * Parameters:
  14161  *     unit        - (IN) BCM device number
  14162  *     index       - (IN) Port entry hardware index.
  14163  *     port_entry  - (IN) port table entry pointer.
  14164  * Returns:
  14165  *     BCM_E_XXX
  14166  */
  14167 STATIC int
  14168 _bcm_sb2_oam_port_lmep_rx_config_recover(int unit,
  14169                          int index,
  14170                          port_tab_entry_t *port_entry,
  14171                          uint8 **scache,
  14172                          uint16 recovered_ver)
  14173 {
  14174 
  14175     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  14176     ma_index_entry_t        ma_idx_entry; /* MA_INDEX table entry.           */
  14177     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  14178     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  14179     uint8                   mdl;          /* Maintenance domain level.       */
  14180     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  14181     int                     rv, tmp_rv;   /* Operation return status.        */
  14182     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  14183     bcm_gport_t             gport;        /* Gport value.                    */
  14184     int                     ep_id;        /* Endpoint ID.                    */
  14185     bcm_module_t            my_modid;
  14186     int                     stm_index = 0;
  14187     source_trunk_map_table_entry_t stm_entry;
  14188     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  14189     int                     ma_offset = 0;
  14190     int                     ma_idx;       /* MA_TABLE index                  */ 
  14191     int                     ma_base_idx = 0;
  14192     int                     ma_idx_entry_count = 0;
  14193     shr_idxres_list_handle_t pool = NULL;
  14194     uint8                   *lm_dm_scache_info_ptr = NULL;
  14195 
  14196     LOG_DEBUG(BSL_LS_BCM_OAM,
  14197               (BSL_META_U(unit,
  14198                           "OAM(unit %d) Info: _bcm_sb2_oam_port_lmep_rx_config_recover .\n"),
  14199                unit));
  14200     /*
  14201      * Get OAM control structure.
  14202      *     Note: Lock taken by calling routine.
  14203      */
  14204     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  14205 
  14206     /* recover port based DownMEPs */
  14207     mdl_bitmap = soc_PORT_TABm_field32_get(unit, port_entry, MDL_BITMAPf); 
  14208     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  14209 
  14210         if (mdl_bitmap & (1 << mdl)) {
  14211 
  14212             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  14213             BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit,
  14214                         my_modid, index, &stm_index));
  14215             SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 
  14216                         MEM_BLOCK_ANY, stm_index, &stm_entry));
  14217             ma_base_idx = 
  14218                 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 
  14219                         MA_BASE_PTRf);
  14220 
  14221             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14222 
  14223                 ma_idx = ma_base_idx + ma_offset;
  14224                 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)),
  14225                          sizeof(bcm_oam_endpoint_t));
  14226                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  14227                 if (BCM_FAILURE(rv)) {
  14228                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  14229                     LOG_ERROR(BSL_LS_BCM_OAM, 
  14230                             (BSL_META_U(unit,
  14231                                         "OAM Error: (EP_ID=%d) Index reserve "
  14232                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  14233                     return (rv);
  14234                 }
  14235             } else {
  14236                 /* Allocate the next available endpoint index. */
  14237                 rv = shr_idxres_list_alloc(oc->mep_pool,
  14238                         (shr_idxres_element_t *)&ep_id);
  14239                 if (BCM_FAILURE(rv)) {
  14240                     LOG_ERROR(BSL_LS_BCM_OAM,
  14241                             (BSL_META_U(unit,
  14242                                         "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"),
  14243                              unit, ep_id, bcm_errmsg(rv)));
  14244                     goto cleanup;
  14245                 }
  14246             }
  14247 
  14248             h_data_p = &oc->oam_hash_data[ep_id];
  14249             if (1 == h_data_p->in_use) {
  14250                 rv = BCM_E_INTERNAL;
  14251                 goto cleanup;
  14252             }
  14253 
  14254             /* 
  14255              * Clear the hash data element contents before
  14256              * storing values.
  14257              */
  14258             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  14259             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  14260             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14261             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14262             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  14263             h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  14264             h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  14265             h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  14266             h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  14267             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  14268             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14269             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14270             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14271             h_data_p->trunk_id = BCM_TRUNK_INVALID;
  14272 #if defined (BCM_METROLITE_SUPPORT)
  14273             if(SOC_IS_METROLITE(unit)) {
  14274                 h_data_p->lm_count_profile = _BCM_OAM_INVALID_INDEX;
  14275             }
  14276 #endif
  14277             h_data_p->ep_id = ep_id;
  14278             h_data_p->ma_base_index = ma_base_idx;
  14279             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  14280             ma_offset++;
  14281 
  14282             rv = READ_MA_INDEXm(unit, MEM_BLOCK_ANY, 
  14283                                  h_data_p->local_rx_index, &ma_idx_entry);
  14284             if (BCM_FAILURE(rv)) {
  14285                 LOG_ERROR(BSL_LS_BCM_OAM,
  14286                           (BSL_META_U(unit,
  14287                                       "OAM(unit %d) Error: MA_INDEX(index:%d) "
  14288                                       "read failed -" " %s.\n"), unit, 
  14289                            h_data_p->local_rx_index, bcm_errmsg(rv)));
  14290                 goto cleanup;
  14291             }
  14292 
  14293             h_data_p->in_use = 1;
  14294             h_data_p->is_remote = 0;
  14295             h_data_p->local_rx_enabled = 1;
  14296             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  14297             h_data_p->active_mdl_bitmap = mdl_bitmap;
  14298             h_data_p->group_index
  14299                 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  14300 
  14301             h_data_p->profile_index
  14302                 = soc_MA_INDEXm_field32_get
  14303                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  14304 
  14305             rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
  14306                     _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 
  14307                     _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE);
  14308             if (BCM_FAILURE(rv)) {
  14309                 LOG_ERROR(BSL_LS_BCM_OAM,
  14310                           (BSL_META_U(unit,
  14311                                       "OAM(unit %d) Error: Profile entry recover failed "
  14312                                       "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14313                 goto cleanup;
  14314             }
  14315 #if defined(BCM_METROLITE_SUPPORT)
  14316             if(SOC_IS_METROLITE(unit)) {
  14317                 h_data_p->lm_count_profile = soc_MA_INDEXm_field32_get (unit, &ma_idx_entry, 
  14318                         OAM_COUNT_PROFILEf);
  14319                 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile,
  14320                         h_data_p->lm_count_profile, 
  14321                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  14322                 if (BCM_FAILURE(rv)) {
  14323                     LOG_ERROR(BSL_LS_BCM_OAM,
  14324                             (BSL_META_U(unit,
  14325                                         "OAM(unit %d) Error: Profile entry recover failed "
  14326                                         "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14327                     goto cleanup;
  14328                 }
  14329                 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile,
  14330                         h_data_p->lm_count_profile, 
  14331                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  14332                 if (BCM_FAILURE(rv)) {
  14333                     LOG_ERROR(BSL_LS_BCM_OAM,
  14334                             (BSL_META_U(unit,
  14335                                         "OAM(unit %d) Error: Profile entry recover failed "
  14336                                         "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14337                     goto cleanup;
  14338                 }            
  14339             }
  14340 #endif
  14341 
  14342             h_data_p->name = 0x0; /* No need to set it to 0xffff */
  14343             h_data_p->level = mdl;
  14344             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14345             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14346             h_data_p->oam_domain = 0;
  14347 
  14348             /* Generic logical port type, construct gport from GLP.  */
  14349             _bcm_gport_dest_t_init(&gport_dest);
  14350 
  14351             gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  14352             gport_dest.modid = my_modid;
  14353             gport_dest.port = index;
  14354             h_data_p->sglp = index;
  14355             h_data_p->dglp = index;
  14356             h_data_p->src_pp_port = index;
  14357 
  14358             rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  14359             if (BCM_FAILURE(rv)) {
  14360                 LOG_ERROR(BSL_LS_BCM_OAM,
  14361                           (BSL_META_U(unit,
  14362                                       "OAM(unit %d) Error: Gport construct failed -"
  14363                                        " %s.\n"), unit, bcm_errmsg(rv)));
  14364                  goto cleanup;
  14365             }
  14366             h_data_p->gport = gport;
  14367 
  14368             rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  14369             if (BCM_FAILURE(rv)) {
  14370                 goto cleanup;
  14371             }
  14372             rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  14373             if (BCM_FAILURE(rv)) {
  14374                 LOG_ERROR(BSL_LS_BCM_OAM,
  14375                         (BSL_META_U(unit,
  14376                                     "OAM(unit %d) Error: Remove mapping from ma_idx_to_ep_id list (EP=%d) -"
  14377                                     " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14378                 _bcm_sb2_oam_group_ep_list_remove(unit,
  14379                                               h_data_p->group_index,
  14380                                               ep_id);
  14381                 goto cleanup;
  14382             }
  14383 
  14384             rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  14385             if (BCM_FAILURE(rv)) {
  14386                 _bcm_sb2_oam_group_ep_list_remove(unit,
  14387                                               h_data_p->group_index,
  14388                                               ep_id);
  14389                 goto cleanup;
  14390             }
  14391 
  14392             bcm_oam_endpoint_info_t_init(ep_info);
  14393 
  14394             /* Set up endpoint information for key construction. */
  14395             ep_info->group = h_data_p->group_index;
  14396             ep_info->name = h_data_p->name;
  14397             ep_info->gport = h_data_p->gport;
  14398             ep_info->level = h_data_p->level;
  14399             ep_info->vlan = 0;
  14400             ep_info->inner_vlan = 0;
  14401 
  14402             if ((recovered_ver < BCM_WB_VERSION_1_9) 
  14403                     || (!ETH_TYPE(h_data_p->type))) {
  14404                 /*
  14405                  * Calculate hash key for hash table insert
  14406                  * operation.
  14407                  */
  14408                 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  14409 
  14410 
  14411                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  14412                 if (BCM_FAILURE(rv)) {
  14413                     LOG_ERROR(BSL_LS_BCM_OAM,
  14414                             (BSL_META_U(unit,
  14415                                         "OAM(unit %d) Error: Hash table insert"
  14416                                         " (EP=%d) failed - %s.\n"), unit,
  14417                              h_data_p->ep_id, bcm_errmsg(rv)));
  14418 
  14419                     _bcm_sb2_oam_group_ep_list_remove(unit,
  14420                             h_data_p->group_index,
  14421                             ep_id);
  14422                     goto cleanup;
  14423                 } else {
  14424                     LOG_DEBUG(BSL_LS_BCM_OAM,
  14425                             (BSL_META_U(unit,
  14426                                         "OAM(unit %d) Info: Hash Tbl (EP=%d)"
  14427                                         " inserted  - %s.\n"), unit, ep_id,
  14428                              bcm_errmsg(rv)));
  14429                 }
  14430             }
  14431 
  14432             /* Now we support DM for Port MEPs. Hence try recovering it in case
  14433              * there is an LM/DM session on the PORT MEP.
  14434              */
  14435             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14436                 if (bcmOAMEndpointTypeEthernet == h_data_p->type) {
  14437                     lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  14438                     _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc);
  14439                 }
  14440             }
  14441             sal_free(ep_info);
  14442             /* Make it NULL to avoid dangling pointer free in cleanup */
  14443             ep_info = NULL;
  14444         }
  14445     } /* end of for loop */
  14446     if (mdl_bitmap) {
  14447         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p,
  14448                     &ma_idx_entry_count,&pool));
  14449         rv = shr_idxres_list_reserve(pool,
  14450                 h_data_p->ma_base_index,
  14451                 h_data_p->ma_base_index + ma_idx_entry_count - 1);
  14452 
  14453         if (BCM_FAILURE(rv)) {
  14454             LOG_ERROR(BSL_LS_BCM_OAM,
  14455                       (BSL_META_U(unit,
  14456                                   "OAM(unit %d) Error: (LMEP=%d) MA Index reserve "
  14457                                   "failed" "  - %s.\n"), unit, h_data_p->remote_index,
  14458                        bcm_errmsg(rv)));
  14459             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  14460             goto cleanup;
  14461         }
  14462     }
  14463 
  14464     LOG_DEBUG(BSL_LS_BCM_OAM,
  14465               (BSL_META_U(unit,
  14466                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  14467                            " - done.\n"), unit));
  14468     return (BCM_E_NONE);
  14469 
  14470 cleanup:
  14471     /* Lets not check return value of delete during cleanup */
  14472     tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  14473     if (BCM_FAILURE(tmp_rv)) {
  14474         LOG_DEBUG(BSL_LS_BCM_OAM,
  14475                   (BSL_META_U(unit,
  14476                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  14477                                " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  14478     }
  14479 
  14480     if (NULL != ep_info) {
  14481         sal_free(ep_info);
  14482     }
  14483 
  14484     if (BCM_E_EXISTS
  14485         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  14486         shr_idxres_list_free(oc->mep_pool, ep_id);
  14487     }
  14488     if (NULL != h_data_p
  14489         && (BCM_E_EXISTS
  14490             == shr_idxres_list_elem_state(pool,
  14491                                           h_data_p->ma_base_index))) {
  14492         shr_idxres_list_free(pool, h_data_p->ma_base_index);
  14493     }
  14494     if (NULL != h_data_p) {
  14495         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  14496     }
  14497 
  14498     LOG_DEBUG(BSL_LS_BCM_OAM,
  14499               (BSL_META_U(unit,
  14500                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  14501                            " - error_done.\n"), unit));
  14502     return (rv);
  14503 
  14504 }
  14505 
  14506 #if defined(INCLUDE_L3)
  14507 STATIC void
  14508 _bcm_sb2_egr_l3_nxt_hop_egress_if_get_from_mepid(int unit, _bcm_oam_hash_data_t *h_data_p)
  14509 {
  14510     int mem_index = 0, mem_idx_count = 0;
  14511     egr_l3_next_hop_entry_t egr_nh_entry;
  14512     int rv = BCM_E_NONE;
  14513     int oam_enable = 0;
  14514     uint16 mep_id = 0;
  14515     bcm_l3_egress_t nh_info;
  14516 
  14517 
  14518     mem_idx_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
  14519 
  14520     for (mem_index = 0; mem_index < mem_idx_count; mem_index++) {
  14521         sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  14522 
  14523         rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, mem_index, &egr_nh_entry);
  14524         if (BCM_FAILURE(rv)) {
  14525             continue;
  14526         }
  14527         oam_enable = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 
  14528                 MPLS__MPLS_OAM_DOWNMEP_ENABLEf);   
  14529         if (!oam_enable) {
  14530             continue;
  14531         }
  14532         if (oam_enable == _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM) {
  14533             mep_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
  14534                     MPLS__MEPIDf);
  14535 
  14536             if (mep_id == h_data_p->name) {
  14537                 /* Match found */
  14538                 sal_memset(&nh_info, 0, sizeof(nh_info));
  14539                 rv = bcm_xgs3_nh_get(unit, mem_index, &nh_info);
  14540                 if (BCM_FAILURE(rv)) {
  14541                     LOG_DEBUG(BSL_LS_BCM_OAM,
  14542                             (BSL_META_U(unit,
  14543                                         "OAM(unit %d) : NH info get failed for"
  14544                                         " %d - %s.\n"), unit, mem_index, 
  14545                                         bcm_errmsg(rv)));
  14546                     continue;
  14547                 }
  14548                 if (nh_info.encap_id > 0 &&
  14549                         nh_info.encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit)) {
  14550                     h_data_p->egress_if = mem_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  14551                 } else {
  14552                     h_data_p->egress_if = mem_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
  14553                 }
  14554             }
  14555         }
  14556     }
  14557 }
  14558 #endif
  14559 
  14560 STATIC int
  14561 _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(_bcm_oam_control_t *oc,
  14562                                                         uint32 egr_ctr_pool_id,
  14563                                                         uint32 egr_ctr_idx)
  14564 {
  14565     int                 grp_idx;
  14566     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  14567     _bcm_oam_ep_list_t  *ep_list_p = NULL;
  14568     _bcm_oam_hash_data_t *ep_data_p = NULL;
  14569     uint32 ep_ctr_pool_id;
  14570     uint32 ep_ctr_idx;
  14571 
  14572     /* Initialize to group array pointer. */
  14573     group_p = oc->group_info;
  14574 
  14575     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
  14576     {
  14577         if (group_p[grp_idx].in_use == 1) {
  14578             ep_list_p = *(group_p[grp_idx].ep_list);
  14579             while (ep_list_p != NULL) {
  14580                 ep_data_p = ep_list_p->ep_data_p; 
  14581                 if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep_data_p)) &&
  14582                     (ep_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
  14583                     ep_ctr_pool_id = (ep_data_p->rx_ctr >> 24) & 0xFF;
  14584                     ep_ctr_idx     = ep_data_p->rx_ctr & 0xFFFFFF;
  14585                     if ((ep_ctr_pool_id == egr_ctr_pool_id) &&
  14586                         (ep_ctr_idx     == egr_ctr_idx)) {
  14587                         return ep_data_p->ep_id;
  14588                     }
  14589                 }
  14590                 ep_list_p = ep_list_p->next;
  14591             }
  14592         }
  14593     }
  14594     return -1;
  14595 }
  14596 
  14597 STATIC int
  14598 _bcm_sb2_oam_mpls_lmdm_tx_config_recover_for_ep_id(int unit,
  14599                                                    _bcm_oam_hash_data_t    *h_data_p,
  14600                                                    egr_mp_group_entry_t *egr_mp_grp_entry)
  14601 {
  14602     _bcm_oam_hash_data_t    hash_data; /* Endpoint hash data pointer. */
  14603     bcm_oam_endpoint_info_t ep_info; /* Endpoint information */
  14604     _bcm_oam_hash_key_t     hash_key; /* Hash key buffer for lookup */
  14605     _bcm_oam_control_t      *oc; /* Pointer to control structure.*/
  14606     int rv = BCM_E_NONE;
  14607 
  14608 
  14609     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  14610     /* This endpoint id should have already been recovered during
  14611        downmep recover. If not return ERROR */
  14612     if (1 != h_data_p->in_use) {
  14613         return (BCM_E_INTERNAL);
  14614     }
  14615 
  14616     /* Egress parameters to (EGR_)MP_GROUP varies only for LSP 
  14617      * endpoints only. Retrieve for LSP.
  14618      */
  14619     if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  14620 
  14621         bcm_oam_endpoint_info_t_init(&ep_info);
  14622 
  14623         /* Set up endpoint information for key construction. */
  14624         ep_info.group = h_data_p->group_index;
  14625         ep_info.name = h_data_p->name;
  14626         ep_info.gport = h_data_p->gport;
  14627         ep_info.level = h_data_p->level;
  14628         ep_info.vlan = h_data_p->vlan;
  14629         ep_info.inner_vlan = h_data_p->inner_vlan;
  14630         ep_info.flags = h_data_p->flags;
  14631         ep_info.mpls_label = h_data_p->label;
  14632         ep_info.type       = h_data_p->type;
  14633 
  14634         /*
  14635          * Calculate hash key for hash table remove
  14636          * operation.
  14637          */
  14638         _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, 
  14639                 &hash_key);
  14640 
  14641         /*
  14642          * Delete insert done by Downmep Rx endpoint recovery code.
  14643          */
  14644         rv = shr_htb_find(oc->ma_mep_htbl, hash_key,
  14645                 (shr_htb_data_t *)&hash_data, 1);
  14646         if (BCM_E_NOT_FOUND == rv) {
  14647             return BCM_E_INTERNAL;
  14648         }
  14649 
  14650         h_data_p->name = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14651                 MEPIDf);
  14652         /*
  14653          * Endpoint name has been recovered and will result
  14654          * in a different hash index. Insert with the new hash index.
  14655          */
  14656         ep_info.name = h_data_p->name;
  14657 
  14658         /*
  14659          * Calculate hash key for hash table insert
  14660          * operation.
  14661          */
  14662         _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, 
  14663                 &hash_key);
  14664         BCM_IF_ERROR_RETURN(shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p));
  14665 #if defined(INCLUDE_L3)
  14666         /* Recover egress if from EGR_L3_NEXT_HOP using MEPID */
  14667         _bcm_sb2_egr_l3_nxt_hop_egress_if_get_from_mepid(unit, h_data_p);
  14668 #endif
  14669     }
  14670     return BCM_E_NONE;
  14671 }
  14672 
  14673 STATIC int
  14674 _bcm_sb2_oam_mpls_lmdm_tx_config_recover(_bcm_oam_control_t *oc,
  14675                                          int ma_idx,
  14676                                          uint8 *scache,
  14677                                          egr_mp_group_entry_t *egr_mp_grp_entry)
  14678 {
  14679     int ep_id[2] = {0,0}; /* Atmost 2 endpoints could be associated with 
  14680                              same egr_mp_group entry */
  14681     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  14682     int unit = oc->unit;
  14683     int num_ep_id = 0;
  14684     uint32 key_type = 0;
  14685     int id = 0;
  14686     int ctr1_valid = 0, ctr2_valid = 0;
  14687     uint32 ctr1_pool_id = 0, ctr2_pool_id = 0, ctr1_base_idx = 0, ctr2_base_idx = 0;
  14688 
  14689     key_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, KEY_TYPEf);
  14690 
  14691     /* Only LSPs could have 2 endpoints associated with same egr_mp_group entry */
  14692     if (key_type == _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP) { 
  14693         ctr1_valid = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14694                 CTR1_VALIDf);
  14695         ctr2_valid = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14696                 CTR2_VALIDf);
  14697         if (ctr1_valid && ctr2_valid) {
  14698             ctr1_pool_id = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14699                     CTR1_POOL_IDf);
  14700             ctr2_pool_id = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14701                     CTR2_POOL_IDf);
  14702             ctr1_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14703                     CTR1_BASE_PTRf);
  14704             ctr2_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14705                     CTR2_BASE_PTRf);
  14706             ep_id[0] = _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(oc, 
  14707                     ctr1_pool_id,
  14708                     ctr1_base_idx);
  14709             if (ep_id[0] != -1) {
  14710                 num_ep_id++;
  14711             }
  14712             ep_id[1] = _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(oc, 
  14713                     ctr2_pool_id,
  14714                     ctr2_base_idx);
  14715             if (ep_id[1] != -1) {
  14716                 num_ep_id++;
  14717             }
  14718         } else {
  14719             /* Else take it from scache itself since it will match */
  14720             sal_memcpy(&(ep_id[0]), scache + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 
  14721                     sizeof(bcm_oam_endpoint_t));
  14722             num_ep_id++;
  14723         }
  14724     } else {
  14725         /* Else take it from scache itself since it will match */
  14726         sal_memcpy(&(ep_id[0]), scache + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 
  14727                 sizeof(bcm_oam_endpoint_t));
  14728         num_ep_id++;
  14729     }
  14730     
  14731     for (id = 0; id < num_ep_id; id++) {
  14732         h_data_p = &oc->oam_hash_data[ep_id[id]];
  14733         if (h_data_p->in_use != 1) {
  14734             return BCM_E_INTERNAL;
  14735         }
  14736         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lmdm_tx_config_recover_for_ep_id(unit, 
  14737                     h_data_p, egr_mp_grp_entry));
  14738     }
  14739 
  14740     return BCM_E_NONE;
  14741 }
  14742 
  14743 
  14744 /*
  14745  * Function:
  14746  *     _bcm_sb2_oam_lmep_upmep_rx_config_recover
  14747  * Purpose:
  14748  *     Recover OAM local endpoint Rx configuration for UpMEPS
  14749  *     and the BHH endpoint type.
  14750  * Parameters:
  14751  *     unit        - (IN) BCM device number
  14752  *     index       - (IN) Remote MEP hardware index.
  14753  *     egr_mp_grp_entry - (IN) Egress MP group table entry pointer.
  14754  * Returns:
  14755  *     BCM_E_XXX
  14756  */
  14757 STATIC int
  14758 _bcm_sb2_oam_lmep_upmep_rx_config_recover(int unit,
  14759                          int index,
  14760                          egr_mp_group_entry_t *egr_mp_grp_entry,
  14761                          uint8 **scache,
  14762                          uint16 recovered_ver)
  14763 {
  14764     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  14765     ma_index_entry_t        ma_idx_entry; /* MA_INDEX table entry.           */
  14766     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  14767     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  14768     uint8                   mdl;          /* Maintenance domain level.       */
  14769     int                     rv,tmp_rv;    /* Operation return status.        */
  14770     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  14771     bcm_gport_t             gport;        /* Gport value.                    */
  14772     uint16                  glp;          /* Generic logical port value.     */
  14773     int                     ep_id;        /* Endpoint ID.                    */
  14774     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  14775     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.        */
  14776     int                     lmep_type = 0;
  14777     int                     timestamp_type = 0;
  14778     int                     ma_offset = 0;
  14779     uint8                   oam_domain = 0;
  14780     int                     ma_base_idx = 0;
  14781     int                     ma_idx      = 0;
  14782     uint8                   *lm_dm_scache_info_ptr = NULL;
  14783     bcm_port_t              pp_port;
  14784     mp_group_entry_t        mp_group_entry;
  14785     int                     entry_index = -1;
  14786     uint8                   mdl_mip = 0;
  14787 
  14788     LOG_DEBUG(BSL_LS_BCM_OAM,
  14789               (BSL_META_U(unit,
  14790                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_upmep_rx_config_recover .\n"),
  14791                unit));
  14792     /*
  14793      * Get OAM control structure.
  14794      *     Note: Lock taken by calling routine.
  14795      */
  14796     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  14797 
  14798     /* recover UpMEPs */
  14799     mdl_bitmap = soc_EGR_MP_GROUPm_field32_get(unit,
  14800                                                egr_mp_grp_entry,
  14801                                                MDL_BITMAP_ACTIVEf);
  14802 
  14803     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  14804 
  14805         if (mdl_bitmap & (1 << mdl)) {
  14806 
  14807             ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry,
  14808                                                         MA_BASE_PTRf);
  14809             ma_idx = ma_base_idx + ma_offset;
  14810 
  14811             oam_domain = soc_EGR_MP_GROUPm_field32_get(unit,
  14812                                                        egr_mp_grp_entry,
  14813                                                        KEY_TYPEf);
  14814 
  14815             if ((oam_domain >= _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW) &&
  14816                 (oam_domain <= _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN)) {
  14817                 /* MPLS LM/DM endpoints doesnt have UP MEPs. But active bitmap is
  14818                    configured. We could recover some tx configs from it. 
  14819                    Handle it separately. */
  14820                  BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lmdm_tx_config_recover(
  14821                                                       oc, ma_idx, *scache, egr_mp_grp_entry));
  14822                  continue;
  14823             }
  14824 
  14825             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14826                 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(ma_idx)), 
  14827                         sizeof(bcm_oam_endpoint_t));
  14828                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  14829                 if (BCM_FAILURE(rv)) {
  14830                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  14831                     LOG_ERROR(BSL_LS_BCM_OAM, 
  14832                             (BSL_META_U(unit,
  14833                                         "OAM Error: (EP_ID=%d) Index reserve "
  14834                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  14835                     return (rv);
  14836                 }
  14837             } else {
  14838 
  14839                 /* Allocate the next available endpoint index. */
  14840                 rv = shr_idxres_list_alloc(oc->mep_pool,
  14841                         (shr_idxres_element_t *)&ep_id);
  14842                 if (BCM_FAILURE(rv)) {
  14843                     LOG_ERROR(BSL_LS_BCM_OAM,
  14844                             (BSL_META_U(unit,
  14845                                         "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"),
  14846                              unit, ep_id, bcm_errmsg(rv)));
  14847                     goto cleanup;
  14848                 }
  14849             }
  14850 
  14851             h_data_p = &oc->oam_hash_data[ep_id];
  14852             if (1 == h_data_p->in_use) {
  14853                 rv = BCM_E_INTERNAL;
  14854                 goto cleanup;
  14855             }
  14856 
  14857             /* 
  14858              * Clear the hash data element contents before
  14859              * storing values.
  14860              */
  14861             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  14862             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  14863             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14864             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14865             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  14866             h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  14867             h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  14868             h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  14869             h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  14870             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  14871             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14872             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14873             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  14874             h_data_p->trunk_id = BCM_TRUNK_INVALID;
  14875 #if defined (BCM_METROLITE_SUPPORT)
  14876             if(SOC_IS_METROLITE(unit)) {
  14877                 h_data_p->lm_count_profile = _BCM_OAM_INVALID_INDEX;
  14878             }
  14879 #endif
  14880             h_data_p->ep_id = ep_id;
  14881             h_data_p->ma_base_index = ma_base_idx;
  14882             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  14883             h_data_p->active_mdl_bitmap = mdl_bitmap;
  14884             ma_offset++;
  14885 
  14886             rv = READ_EGR_MA_INDEXm(unit, MEM_BLOCK_ANY, 
  14887                                  h_data_p->local_rx_index, &ma_idx_entry);
  14888             if (BCM_FAILURE(rv)) {
  14889                 LOG_ERROR(BSL_LS_BCM_OAM,
  14890                           (BSL_META_U(unit,
  14891                                       "OAM(unit %d) Error: EGR_MA_INDEX(index:%d) "
  14892                                       "read failed -" " %s.\n"), unit, 
  14893                            h_data_p->local_rx_index, bcm_errmsg(rv)));
  14894                 goto cleanup;
  14895             }
  14896 
  14897             h_data_p->flags |= BCM_OAM_ENDPOINT_UP_FACING;
  14898             h_data_p->in_use = 1;
  14899             h_data_p->is_remote = 0;
  14900             h_data_p->local_rx_enabled = 1;
  14901             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  14902             h_data_p->group_index
  14903                 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  14904 
  14905             h_data_p->profile_index
  14906                 = soc_EGR_MA_INDEXm_field32_get
  14907                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  14908 
  14909             rv = soc_profile_mem_reference(unit, &oc->egr_oam_opcode_control_profile,
  14910                     _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 
  14911                     _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE);
  14912             if (BCM_FAILURE(rv)) {
  14913                 LOG_ERROR(BSL_LS_BCM_OAM,
  14914                           (BSL_META_U(unit,
  14915                                       "OAM(unit %d) Error: Profile entry recover failed "
  14916                                       "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14917                 goto cleanup;
  14918             }
  14919 
  14920 #if defined(BCM_METROLITE_SUPPORT)
  14921             if(SOC_IS_METROLITE(unit)) {
  14922                 h_data_p->lm_count_profile = soc_EGR_MA_INDEXm_field32_get (unit, &ma_idx_entry, 
  14923                         OAM_COUNT_PROFILEf);
  14924                 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile,
  14925                         h_data_p->lm_count_profile, 
  14926                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  14927                 if (BCM_FAILURE(rv)) {
  14928                     LOG_ERROR(BSL_LS_BCM_OAM,
  14929                             (BSL_META_U(unit,
  14930                                 "OAM(unit %d) Error: LM Profile entry recover failed "
  14931                                 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14932                     goto cleanup;
  14933                 }
  14934                 
  14935                 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile,
  14936                         h_data_p->lm_count_profile, 
  14937                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  14938                 if (BCM_FAILURE(rv)) {
  14939                     LOG_ERROR(BSL_LS_BCM_OAM,
  14940                             (BSL_META_U(unit,
  14941                                 "OAM(unit %d) Error: LM Profile entry recover failed "
  14942                                 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14943                     goto cleanup;
  14944                 }            
  14945             }
  14946 #endif
  14947 
  14948             h_data_p->dglp1_profile_index =
  14949                      soc_MA_INDEXm_field32_get
  14950                                 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  14951             rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile,
  14952                                          h_data_p->dglp1_profile_index, 1);
  14953             if (BCM_FAILURE(rv)) {
  14954                 LOG_ERROR(BSL_LS_BCM_OAM,
  14955                           (BSL_META_U(unit,
  14956                                       "OAM(unit %d) Error: DGLP profile ref count  "
  14957                                       "increment failed (EP=%d) - %s.\n"), unit,
  14958                            h_data_p->ep_id, bcm_errmsg(rv)));
  14959                 goto cleanup;
  14960             }
  14961             h_data_p->dglp2_profile_index =
  14962                 soc_MA_INDEXm_field32_get
  14963                     (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  14964             rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile,
  14965                                          h_data_p->dglp2_profile_index, 1);
  14966             if (BCM_FAILURE(rv)) {
  14967                 LOG_ERROR(BSL_LS_BCM_OAM,
  14968                           (BSL_META_U(unit,
  14969                                       "OAM(unit %d) Error: DGLP profile ref count  "
  14970                                       "increment failed (EP=%d) - %s.\n"), unit,
  14971                            h_data_p->ep_id, bcm_errmsg(rv)));
  14972                 goto cleanup;
  14973             }
  14974 #if defined(INCLUDE_BHH)
  14975             h_data_p->cpu_qid
  14976                 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf);
  14977 #endif
  14978             h_data_p->name = 0x0; /* No need to set it to 0xffff */
  14979             h_data_p->level = mdl;
  14980             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  14981             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  14982             /* recover counters */
  14983             rv = _bcm_sb2_oam_rx_counter_recover(unit, EGR_MP_GROUPm, 
  14984                                          (uint32 *)egr_mp_grp_entry, h_data_p);
  14985             if (BCM_FAILURE(rv)) {
  14986                 LOG_ERROR(BSL_LS_BCM_OAM,
  14987                           (BSL_META_U(unit,
  14988                                       "OAM(unit %d) Error: LM RX counter recover failed "
  14989                                       "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  14990                 goto cleanup;
  14991             }
  14992             /* rx and tx counters are located at same index, but on diff mem */
  14993             if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  14994                 h_data_p->tx_ctr = h_data_p->rx_ctr;
  14995             }
  14996 
  14997             /* time stamp */
  14998             timestamp_type = soc_EGR_MP_GROUPm_field32_get(unit,
  14999                                             egr_mp_grp_entry, TIMESTAMP_TYPEf);  
  15000             if (timestamp_type) {
  15001                 h_data_p->ts_format = !timestamp_type;
  15002             } 
  15003 
  15004             h_data_p->oam_domain = oam_domain;
  15005 
  15006             switch (h_data_p->oam_domain) {
  15007                 case _BCM_OAM_DOMAIN_CVLAN:
  15008                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN;
  15009                     h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  15010                                                      egr_mp_grp_entry, CVIDf);
  15011                     break;
  15012 
  15013                 case _BCM_OAM_DOMAIN_SVLAN:
  15014                     h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  15015                                                      egr_mp_grp_entry, SVIDf);
  15016                     break;
  15017 
  15018                 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
  15019                     h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  15020                                                      egr_mp_grp_entry, SVIDf);
  15021                     h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 
  15022                                                        egr_mp_grp_entry, CVIDf);
  15023                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN;
  15024                     break;
  15025                 
  15026                 case _BCM_OAM_DOMAIN_VP:
  15027                     h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit, 
  15028                                                      egr_mp_grp_entry, VPf);
  15029                     h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  15030                     break;
  15031                 default :
  15032                     break;
  15033   
  15034             }
  15035 
  15036             glp = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, GLPf);
  15037 
  15038             lmep_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 
  15039                                                                  KEY_TYPEf);
  15040 
  15041             if (lmep_type == _BCM_OAM_DOMAIN_VP) { 
  15042 #if defined(INCLUDE_L3)
  15043                 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
  15044 
  15045                     BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  15046 
  15047                 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
  15048 
  15049                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  15050 
  15051                 } else {
  15052                     LOG_ERROR(BSL_LS_BCM_OAM,
  15053                               (BSL_META_U(unit,
  15054                                           "OAM(unit %d) Error: Invalid Virtual Port (SVP=%d)"
  15055                                            " - %s.\n"), unit, h_data_p->vp,
  15056                                bcm_errmsg(BCM_E_INTERNAL)));
  15057                     return (BCM_E_INTERNAL);
  15058                 }
  15059 #endif
  15060             } else {
  15061                 /*
  15062                  * Generic logical port type, construct gport from GLP.
  15063                  */
  15064                 h_data_p->dglp = glp;
  15065 
  15066                 _bcm_gport_dest_t_init(&gport_dest);
  15067 
  15068                 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) {
  15069                     gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  15070                     gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  15071                     h_data_p->trunk_id =  _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  15072                     rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  15073                 } else {
  15074                     gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  15075                     gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp);
  15076                     gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp);
  15077                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 
  15078                                 gport_dest.port, &pp_port));
  15079                     /* Check if the pp_port corresponding to mod port is in
  15080                      * subport port range.
  15081                      */
  15082                     if (SOC_PP_PORT_VALID(unit, pp_port)) {
  15083                         _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
  15084                         /* Get gport for subport port case */
  15085                         rv = BCM_E_NONE;
  15086                         if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
  15087                             _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY);
  15088                         } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
  15089                             _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG);
  15090                         } else {
  15091                             rv = BCM_E_PORT;
  15092                         }
  15093                     } else {
  15094                         /* Go through original gport construction */
  15095                         rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  15096                     }
  15097                 }
  15098 
  15099                 if (BCM_FAILURE(rv)) {
  15100                     LOG_ERROR(BSL_LS_BCM_OAM,
  15101                               (BSL_META_U(unit,
  15102                                           "OAM(unit %d) Error: Gport construct failed -"
  15103                                            " %s.\n"), unit, bcm_errmsg(rv)));
  15104                     goto cleanup;
  15105                 }
  15106 
  15107                 h_data_p->gport = gport;
  15108             }
  15109             h_data_p->dglp = glp;
  15110             h_data_p->sglp = glp;
  15111 
  15112             sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t));
  15113             L3_LOCK(unit);
  15114             if (BCM_SUCCESS
  15115                     (_bcm_sb2_oam_find_lmep(unit, h_data_p,
  15116                                             &entry_index, &mp_group_entry))) {
  15117                 mdl_mip = soc_MP_GROUPm_field32_get(unit, &mp_group_entry,
  15118                         MDL_BITMAP_PASSIVEf);
  15119             }
  15120             L3_UNLOCK(unit);
  15121 
  15122             if (!(mdl_mip & (1 << h_data_p->level))) {
  15123                 /* Set the MIP flag */
  15124                 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  15125             }
  15126 
  15127             /* Recover ETH LM/DM info */
  15128             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  15129                 if (bcmOAMEndpointTypeEthernet == h_data_p->type) {
  15130                     lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  15131                     _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc);
  15132                 }
  15133             }
  15134 
  15135             rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  15136             if (BCM_FAILURE(rv)) {
  15137                 goto cleanup;
  15138             }
  15139 
  15140             rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  15141             if (BCM_FAILURE(rv)) {
  15142                 LOG_ERROR(BSL_LS_BCM_OAM,
  15143                         (BSL_META_U(unit,
  15144                                     "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  15145                                     " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15146                 _bcm_sb2_oam_group_ep_list_remove(unit,
  15147                                               h_data_p->group_index,
  15148                                               ep_id);
  15149                 goto cleanup;
  15150             }
  15151 
  15152 
  15153             rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  15154             if (BCM_FAILURE(rv)) {
  15155                 _bcm_sb2_oam_group_ep_list_remove(unit,
  15156                                               h_data_p->group_index,
  15157                                               ep_id);
  15158                 goto cleanup;
  15159             }
  15160 
  15161             bcm_oam_endpoint_info_t_init(ep_info);
  15162 
  15163             /* Set up endpoint information for key construction. */
  15164             ep_info->group = h_data_p->group_index;
  15165             ep_info->name = h_data_p->name;
  15166             ep_info->gport = h_data_p->gport;
  15167             ep_info->level = h_data_p->level;
  15168             ep_info->vlan = h_data_p->vlan;
  15169             ep_info->inner_vlan = h_data_p->inner_vlan;
  15170             ep_info->flags = h_data_p->flags;
  15171             if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  15172                 ep_info->mpls_label = h_data_p->label;
  15173             }
  15174             ep_info->type       = h_data_p->type;
  15175             if ((recovered_ver < BCM_WB_VERSION_1_9) 
  15176                 || (!ETH_TYPE(h_data_p->type))) {
  15177                 /*
  15178                  * Calculate hash key for hash table insert
  15179                  * operation.
  15180                  */
  15181                 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  15182 
  15183 
  15184                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  15185                 if (BCM_FAILURE(rv)) {
  15186                     LOG_ERROR(BSL_LS_BCM_OAM,
  15187                             (BSL_META_U(unit,
  15188                                         "OAM(unit %d) Error: Hash table insert"
  15189                                         " (EP=%d) failed - %s.\n"), unit,
  15190                              h_data_p->ep_id, bcm_errmsg(rv)));
  15191 
  15192                     _bcm_sb2_oam_group_ep_list_remove(unit,
  15193                             h_data_p->group_index,
  15194                             ep_id);
  15195                     goto cleanup;
  15196                 } else {
  15197                     LOG_DEBUG(BSL_LS_BCM_OAM,
  15198                             (BSL_META_U(unit,
  15199                                         "OAM(unit %d) Info: Hash Tbl (EP=%d)"
  15200                                         " inserted  - %s.\n"), unit, ep_id,
  15201                              bcm_errmsg(rv)));
  15202                 }
  15203             }
  15204             sal_free(ep_info);
  15205             /* Make it NULL to avoid dangling pointer free in cleanup */
  15206             ep_info = NULL;
  15207         }
  15208     } /* end of for loop */
  15209     if (mdl_bitmap) {
  15210         if (!((oam_domain >= _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW) &&
  15211         (oam_domain <= _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN))) {
  15212             /* MPLS LM/DM endpoints doesnt have UP MEPs. But active bitmap 
  15213                is configured. So there would not be h_data_p here. do not 
  15214                touch egr_ma_idx_pool.*/
  15215             rv = shr_idxres_list_reserve(oc->egr_ma_idx_pool,
  15216                     h_data_p->ma_base_index,
  15217                     h_data_p->ma_base_index + 7);
  15218             if (BCM_FAILURE(rv)) {
  15219                 LOG_ERROR(BSL_LS_BCM_OAM,
  15220                         (BSL_META_U(unit,
  15221                                     "OAM(unit %d) Error: (LMEP=%d) EGR MA Index reserve "
  15222                                     "failed" "  - %s.\n"), unit, h_data_p->remote_index,
  15223                          bcm_errmsg(rv)));
  15224                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  15225                 goto cleanup;
  15226             }
  15227         }
  15228     }
  15229 
  15230     LOG_DEBUG(BSL_LS_BCM_OAM,
  15231               (BSL_META_U(unit,
  15232                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  15233                            " - done.\n"), unit));
  15234     return (BCM_E_NONE);
  15235 
  15236 cleanup:
  15237     /* Lets not check return value of delete during cleanup */
  15238     tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  15239     if (BCM_FAILURE(tmp_rv)) {
  15240         LOG_DEBUG(BSL_LS_BCM_OAM,
  15241                   (BSL_META_U(unit,
  15242                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  15243                                " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  15244     }
  15245 
  15246 
  15247     if (NULL != ep_info) {
  15248         sal_free(ep_info);
  15249     }
  15250 
  15251     if (BCM_E_EXISTS
  15252         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  15253         shr_idxres_list_free(oc->mep_pool, ep_id);
  15254     }
  15255     /* return rx & tx counters allocated if any */
  15256     if (NULL != h_data_p) {
  15257         rv =_bcm_sb2_oam_free_counter(unit, h_data_p);
  15258         if (BCM_FAILURE(rv)) {
  15259             LOG_ERROR(BSL_LS_BCM_OAM,
  15260                       (BSL_META_U(unit,
  15261                                   "OAM(unit %d) Error: LM counter block "
  15262                                   "free failed (EP=%d) - %s.\n"),
  15263                        unit, ep_id, bcm_errmsg(rv)));
  15264         }
  15265     }
  15266     if (NULL != h_data_p
  15267         && (BCM_E_EXISTS
  15268             == shr_idxres_list_elem_state(oc->egr_ma_idx_pool,
  15269                                           h_data_p->ma_base_index))) {
  15270 
  15271         shr_idxres_list_free(oc->egr_ma_idx_pool, h_data_p->ma_base_index);
  15272 
  15273     }
  15274 
  15275     if (NULL != h_data_p) {
  15276         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  15277     }
  15278     LOG_DEBUG(BSL_LS_BCM_OAM,
  15279               (BSL_META_U(unit,
  15280                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  15281                            " - error_done.\n"), unit));
  15282     return (rv);
  15283 }
  15284 
  15285 /*
  15286  * Function:
  15287  *     _bcm_sb2_oam_lmep_downmep_rx_config_recover
  15288  * Purpose:
  15289  *     Recover OAM local endpoint Rx configuration for DownMEPS.
  15290  * Parameters:
  15291  *     unit        - (IN) BCM device number
  15292  *     index       - (IN) Remote MEP hardware index.
  15293  *     mp_group_entry    - (IN) LMEP view table entry pointer.
  15294  * Returns:
  15295  *     BCM_E_XXX
  15296  */
  15297 STATIC int
  15298 _bcm_sb2_oam_lmep_downmep_rx_config_recover(int unit,
  15299                                     int index,
  15300                                     mp_group_entry_t *mp_group_entry,
  15301                                     uint8 **scache,
  15302                                     uint16 recovered_ver)
  15303 {
  15304     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
  15305     ma_index_entry_t        ma_idx_entry; /* IA_INDEX table entry.           */
  15306     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
  15307     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
  15308     uint8                   mdl;          /* Maintenance domain level.       */
  15309     int                     rv, tmp_rv;   /* Operation return status.        */
  15310     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
  15311     bcm_gport_t             gport;        /* Gport value.                    */
  15312     uint16                  glp;          /* Generic logical port value.     */
  15313     int                     ep_id;        /* Endpoint ID.                    */
  15314     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
  15315     bcm_oam_endpoint_info_t *ep_info = NULL;  /* Endpoint information.        */
  15316     int                     timestamp_type = 0;
  15317     int                     ma_offset = 0;
  15318     int                     ma_base_idx = 0;
  15319     int                     ma_idx      = 0;
  15320 #if defined(INCLUDE_L3)
  15321     bcm_mpls_port_t         mpls_port;
  15322 #endif
  15323     uint8                   *lm_dm_scache_info_ptr = NULL;
  15324 #if defined(INCLUDE_BHH)
  15325     bcm_oam_endpoint_t      bhh_endpoint_index = 0;
  15326     bhh_sdk_msg_ctrl_sess_get_t msg;
  15327     mpls_entry_entry_t mpls_entry;
  15328     uint16 buffer_len, reply_len;
  15329     uint8 *buffer, *buffer_ptr;
  15330     int mpls_index = -1;
  15331     bcm_l3_egress_t l3_egress;
  15332     bcm_l3_intf_t l3_intf;
  15333     uint8*  encap_data = NULL;
  15334     uint32               sglp = 0;          /* Source global logical port.  */
  15335     uint32               dglp = 0;          /* Dest global logical port.    */
  15336     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID;
  15337     uint32               svp = 0;           /* Source virtual port          */
  15338     int                  is_vp_valid = 0;
  15339     bcm_trunk_member_t   trunk_member;
  15340     bcm_port_t           src_pp_port, dst_pp_port;
  15341     bcm_cos_t int_pri;
  15342     _mpls_label_t label;
  15343 #endif
  15344     int                     ma_idx_entry_count = 0;
  15345     shr_idxres_list_handle_t pool = NULL;
  15346     bcm_port_t  pp_port;
  15347     egr_mp_group_entry_t egr_mp_group;
  15348     int  mp_grp_index = 0;
  15349     uint8 mdl_mip = 0;
  15350 
  15351     LOG_DEBUG(BSL_LS_BCM_OAM,
  15352               (BSL_META_U(unit,
  15353                           "OAM(unit %d) Info: "
  15354                           "_bcm_sb2_oam_lmep_downmep_rx_config_recover .\n"), unit));
  15355     /*
  15356      * Get OAM control structure.
  15357      *     Note: Lock taken by calling routine.
  15358      */
  15359     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  15360 
  15361     /* recover DownMEPs */
  15362     mdl_bitmap = soc_MP_GROUPm_field32_get(unit, 
  15363             mp_group_entry, MDL_BITMAP_ACTIVEf);
  15364     ma_base_idx = soc_MP_GROUPm_field32_get(unit, mp_group_entry, MA_BASE_PTRf);
  15365 
  15366     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
  15367 
  15368         if (mdl_bitmap & (1 << mdl)) {
  15369 #if defined(INCLUDE_BHH)
  15370             if (soc_feature(unit, soc_feature_bhh) &&
  15371                 oc->ukernel_not_ready == 0 &&
  15372                 SHR_BITGET(oc->bhh_ma_index_in_use, ma_base_idx) &&
  15373                 BHH_UC_FEATURE_CHECK(BHH_WB_SESS_GET)) {
  15374                 /* Read MA_INDEX_ENTRY */
  15375 
  15376                 rv = READ_MA_INDEXm (unit, MEM_BLOCK_ANY,
  15377                                      ma_base_idx,
  15378                                      &ma_idx_entry);
  15379                 if (BCM_FAILURE(rv)) {
  15380                     LOG_ERROR(BSL_LS_BCM_OAM,
  15381                               (BSL_META_U(unit,
  15382                                           "BHH(unit %d) Error: MA_INDEX (index:%d) read failed -"
  15383                                            " %s.\n"), unit, ma_base_idx,
  15384                                 bcm_errmsg(rv)));
  15385                     goto cleanup;
  15386                 }
  15387 
  15388                 /*Fetch endpoint id from MA_INDEX_ENTRY  and reserve in bhh_pool*/
  15389                 bhh_endpoint_index = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  15390                 ep_id = BCM_OAM_BHH_GET_SDK_EP(bhh_endpoint_index);
  15391 
  15392                 h_data_p = &oc->oam_hash_data[ep_id];
  15393 
  15394                 h_data_p->ep_id = ep_id;
  15395                 h_data_p->bhh_endpoint_index = ep_id;
  15396                 h_data_p->ma_base_index = ma_base_idx;
  15397                 h_data_p->local_rx_index = h_data_p->ma_base_index + _BCM_OAM_EP_LEVEL_MAX + 1;
  15398                 h_data_p->oam_domain = _BCM_SB2_OAM_DOMAIN_BHH;
  15399                 h_data_p->group_index = oc->bhh_ep_grp_id[bhh_endpoint_index];
  15400                 h_data_p->vpn = oc->bhh_ep_vpn[bhh_endpoint_index];
  15401                 h_data_p->local_tx_enabled = 0;
  15402                 h_data_p->local_rx_enabled = 1;
  15403                 h_data_p->level = mdl;
  15404                 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  15405                 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  15406                     /* Get the endpoint parameters from firmware */
  15407                     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  15408                             MOS_MSG_SUBCLASS_BHH_SESS_GET,
  15409                             bhh_endpoint_index, 0,
  15410                             MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  15411                             &reply_len);
  15412                     if (BCM_FAILURE(rv)) {
  15413                         LOG_ERROR(BSL_LS_BCM_OAM,
  15414                                 (BSL_META_U(unit,
  15415                                             "BHH(unit %d) Error: ukernel msg " 
  15416                                             "failed for"
  15417                                             " EP=%d %s.\n"), unit, 
  15418                                             bhh_endpoint_index, 
  15419                                             bcm_errmsg(rv)));
  15420                         goto cleanup;
  15421                     }
  15422 
  15423                     buffer = oc->dma_buffer;
  15424                     buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  15425                     buffer_len = buffer_ptr - buffer;
  15426 
  15427                     if (reply_len != buffer_len) {
  15428                         rv = BCM_E_INTERNAL;
  15429                         LOG_ERROR(BSL_LS_BCM_OAM,
  15430                                 (BSL_META_U(unit,
  15431                                             "BHH(unit %d) Error: ukernel msg " 
  15432                                             "failed for"
  15433                                             " EP=%d %s.\n"), unit, 
  15434                                             bhh_endpoint_index, 
  15435                                             bcm_errmsg(rv)));
  15436                         goto cleanup;
  15437                     }
  15438 
  15439                     h_data_p->name = msg.mep_id;
  15440                     h_data_p->egress_if = msg.if_num;
  15441                     h_data_p->period = msg.local_period;
  15442                     h_data_p->label = msg.mpls_label;
  15443                     /* Set the flags */
  15444                     if (msg.flags & SHR_BHH_SESS_SET_F_LB)
  15445                         h_data_p->flags |= BCM_OAM_ENDPOINT_LOOPBACK;
  15446                     else if (msg.flags & SHR_BHH_SESS_SET_F_DM)
  15447                         h_data_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
  15448                     else if (msg.flags & SHR_BHH_SESS_SET_F_LM)
  15449                         h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  15450                     else if (msg.flags & SHR_BHH_SESS_SET_F_MIP)
  15451                         h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  15452                     if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  15453                         bcm_oam_endpoint_info_t ep_info;
  15454                         uint8   ts_mode;
  15455                         uint8 lm_pdu_counter_offset = 0;
  15456                         int i = 0;
  15457                         uint8     counter_action[BCM_OAM_LM_COUNTER_MAX];
  15458                         /* If this feature is valid, then encap_data is valid */
  15459                         if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit,
  15460                                         msg.encap_data,
  15461                                        &(ep_info.ccm_tx_update_lm_counter_size),
  15462                                        ep_info.ccm_tx_update_lm_counter_base_id,
  15463                                         ep_info.ccm_tx_update_lm_counter_offset,
  15464                                         counter_action,
  15465                                         &ts_mode,
  15466                                         &lm_pdu_counter_offset,
  15467                                         &int_pri,
  15468                                         NULL)))
  15469                         {
  15470                             LOG_ERROR(BSL_LS_BCM_OAM,
  15471                                     (BSL_META_U(unit,
  15472                                                 "BHH(unit %d) Error: Failed to "
  15473                                                 "decap OLP TX header EP=%d\n"),
  15474                                                 unit, bhh_endpoint_index));
  15475                             goto cleanup;
  15476                         }
  15477                         for (i = 0; i < ep_info.ccm_tx_update_lm_counter_size;
  15478                              i++) {
  15479                             if (counter_action[i] ==
  15480                                     bcmOamCounterActionSample) {
  15481                                 if (SOC_IS_METROLITE (unit)) {
  15482                                     h_data_p->int_flags |=
  15483                                              _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM;
  15484                                 }
  15485                             }
  15486                         }
  15487                     }
  15488                     _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p,
  15489                                                                  msg.encap_data,
  15490                                                                  msg.encap_length,
  15491                                                                  &label);
  15492                     h_data_p->egr_label = label.label;
  15493                 }
  15494                 h_data_p->active_mdl_bitmap = soc_MP_GROUPm_field32_get(unit,
  15495                                                                     mp_group_entry,
  15496                                                                     MDL_BITMAP_ACTIVEf);
  15497 
  15498                 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  15499                     /* port value from l3_egress_if*/
  15500                     bcm_l3_egress_t_init(&l3_egress);
  15501                     if (BCM_FAILURE (bcm_esw_l3_egress_get(unit,
  15502                                                            h_data_p->egress_if, &l3_egress))) {
  15503                         LOG_ERROR(BSL_LS_BCM_OAM,
  15504                             (BSL_META_U(unit,
  15505                                     "BHH(unit %d) Error: Failed to get L3 egress object"
  15506                                     " EP=%d egress_if=%d %s.\n"), unit, bhh_endpoint_index,
  15507                                     h_data_p->egress_if, bcm_errmsg(rv)));
  15508                         goto cleanup;
  15509                     }
  15510 
  15511                     l3_intf.l3a_intf_id = l3_egress.intf;
  15512                     if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  15513                         LOG_ERROR(BSL_LS_BCM_OAM,
  15514                             (BSL_META_U(unit,
  15515                                     "BHH(unit %d) Error: Failed to get L3 interface"
  15516                                     " EP=%d l3a_intf_id=%d %s.\n"), unit, bhh_endpoint_index,
  15517                                     l3_intf.l3a_intf_id, bcm_errmsg(rv)));
  15518                         goto cleanup;
  15519                     }
  15520                     sal_memcpy(h_data_p->dst_mac_address, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
  15521                     sal_memcpy(h_data_p->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
  15522 
  15523                     h_data_p->sglp = l3_egress.port;
  15524                     h_data_p->src_pp_port = l3_egress.port;
  15525                     h_data_p->dst_pp_port = l3_egress.port;
  15526                     h_data_p->dglp = l3_egress.port;
  15527                     h_data_p->vlan = l3_intf.l3a_vid;
  15528                 } else {
  15529                     encap_data = msg.encap_data;
  15530                     sal_memcpy(h_data_p->dst_mac_address, encap_data, _BHH_MAC_ADDR_LENGTH);
  15531                     encap_data += _BHH_MAC_ADDR_LENGTH;
  15532 
  15533                     sal_memcpy(h_data_p->src_mac_address, encap_data, _BHH_MAC_ADDR_LENGTH);
  15534                     encap_data += _BHH_MAC_ADDR_LENGTH;
  15535                 }
  15536 
  15537 
  15538                 /*Construct gprort */
  15539                 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  15540                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  15541                 } else {
  15542                     _bcm_gport_dest_t_init(&gport_dest);
  15543 
  15544                     if (_BCM_OAM_GLP_TRUNK_BIT_GET(h_data_p->sglp)) {
  15545                         gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(h_data_p->sglp);
  15546                         gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  15547                         h_data_p->trunk_id =  _BCM_OAM_GLP_TRUNK_ID_GET(h_data_p->sglp);
  15548                     } else {
  15549                         gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  15550                         gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp);
  15551                         gport_dest.port = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp);
  15552                     }
  15553 
  15554                     rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  15555                     if (BCM_FAILURE(rv)) {
  15556                         LOG_ERROR(BSL_LS_BCM_OAM,
  15557                             (BSL_META_U(unit,
  15558                                         "BHH(unit %d) Error: Gport construct failed -"
  15559                                         " %s.\n"), unit, bcm_errmsg(rv)));
  15560                         goto cleanup;
  15561                     }
  15562 
  15563                     h_data_p->gport = gport;
  15564                 }
  15565                 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  15566                     /* get vccv_type from MPLS_ENTRY */
  15567                     rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, h_data_p->label,
  15568                                                               h_data_p->sglp,
  15569                                                               &mpls_index,
  15570                                                               &mpls_entry);
  15571                     if(rv != BCM_E_NONE) {
  15572                         /* Not found or some other error */
  15573                         LOG_ERROR(BSL_LS_BCM_OAM,
  15574                                  (BSL_META_U(unit,
  15575                                              "BHH(unit %d) Error: (Label=%u) - %s.\n"),
  15576                                              unit, h_data_p->label, bcm_errmsg(rv)));
  15577                         goto cleanup;
  15578                     }
  15579                     h_data_p->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf);
  15580                     h_data_p->vccv_type--;
  15581                 }
  15582 
  15583 
  15584                 timestamp_type = soc_MP_GROUPm_field32_get(unit, mp_group_entry,TIMESTAMP_TYPEf);
  15585 
  15586                 h_data_p->ts_format = !(timestamp_type);
  15587 
  15588                 h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf);
  15589 
  15590                 /* Populate the hardware indicies */
  15591                 h_data_p->profile_index = soc_MA_INDEXm_field32_get (unit,
  15592                                             &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  15593 
  15594                 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
  15595                         _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index),
  15596                         _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE);
  15597                 if (BCM_FAILURE(rv)) {
  15598                     LOG_ERROR(BSL_LS_BCM_OAM,
  15599                               (BSL_META_U(unit,
  15600                                           "BHH(unit %d) Error: Profile entry recover failed "
  15601                                           "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15602                     goto cleanup;
  15603                 }
  15604 
  15605                 /* Recover Rx counters */
  15606                 rv = _bcm_sb2_oam_rx_counter_recover(unit,
  15607                        MP_GROUPm, (uint32 *)mp_group_entry, h_data_p);
  15608                 if (BCM_FAILURE(rv)) {
  15609                     LOG_ERROR(BSL_LS_BCM_OAM,
  15610                              (BSL_META_U(unit,
  15611                                      "OAM(unit %d) Error: LM rx counter recover failed "
  15612                                      "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15613                     goto cleanup;
  15614                 }
  15615 
  15616                 /* rx and tx counters are located at same index, but on diff mem */
  15617                 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  15618                     h_data_p->tx_ctr = h_data_p->rx_ctr;
  15619                 }
  15620 
  15621                 /* Add endpoint to group */
  15622                 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index,
  15623                                                     h_data_p->ep_id);
  15624 
  15625                 if (BCM_FAILURE(rv)) {
  15626                     /* Return ID back to free MEP ID pool.*/
  15627                     BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_endpoint_index));
  15628                     LOG_ERROR(BSL_LS_BCM_OAM,
  15629                                 (BSL_META_U(unit,
  15630                                             "BHH(unit %d) Error: Tx config failed for EP=%d %s.\n"),
  15631                                 unit, h_data_p->ep_id, bcm_errmsg(rv)));
  15632                     goto cleanup;
  15633                 }
  15634 
  15635                 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  15636                 if (BCM_FAILURE(rv)) {
  15637                     LOG_ERROR(BSL_LS_BCM_OAM,
  15638                             (BSL_META_U(unit,
  15639                                         "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  15640                                         " %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15641                     _bcm_sb2_oam_group_ep_list_remove(unit,
  15642                                                       h_data_p->group_index,
  15643                                                       h_data_p->ep_id);
  15644                     goto cleanup;
  15645                 } 
  15646 
  15647                 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  15648                 if (BCM_FAILURE(rv)) {
  15649                     _bcm_sb2_oam_group_ep_list_remove(unit,
  15650                                                       h_data_p->group_index,
  15651                                                       h_data_p->ep_id);
  15652                     goto cleanup;
  15653                 }
  15654 
  15655                 bcm_oam_endpoint_info_t_init(ep_info);
  15656 
  15657                 /* Set up endpoint information for key construction. */
  15658                 ep_info->group = h_data_p->group_index;
  15659                 ep_info->name = h_data_p->name;
  15660                 ep_info->gport = h_data_p->gport;
  15661                 ep_info->level = h_data_p->level;
  15662                 ep_info->vlan = h_data_p->vlan;
  15663                 ep_info->inner_vlan = h_data_p->inner_vlan;
  15664                 ep_info->mpls_label = h_data_p->label;
  15665                 ep_info->type       = h_data_p->type;
  15666 
  15667                 /* Resolve given endpoint gport value to SGLP and DGLP values. */
  15668                 rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, ep_info, &sglp,
  15669                         &dglp, &src_pp_port, &dst_pp_port, 
  15670                         &svp, &trunk_id, &is_vp_valid,
  15671                         &trunk_member);
  15672                 if (BCM_FAILURE(rv)) {
  15673                     LOG_ERROR(BSL_LS_BCM_OAM,
  15674                             (BSL_META_U(unit,
  15675                                         "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  15676                              unit, h_data_p->ep_id, bcm_errmsg(rv)));
  15677                     _BCM_OAM_UNLOCK(oc);
  15678                     return (rv);
  15679                 }
  15680                 if (BCM_TRUNK_INVALID != trunk_id) {
  15681                     h_data_p->trunk_id = trunk_id;
  15682                     h_data_p->resolved_trunk_gport = trunk_member.gport;
  15683                 }
  15684 
  15685                 /*
  15686                  * Calculate hash key for hash table insert
  15687                  * operation.
  15688                  */
  15689                 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  15690 
  15691                 sal_free(ep_info);
  15692 
  15693                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  15694                 if (BCM_FAILURE(rv)) {
  15695                     LOG_ERROR(BSL_LS_BCM_OAM,
  15696                              (BSL_META_U(unit,
  15697                                          "BHH(unit %d) Error: Hash table insert"
  15698                                          "(EP=%d) failed - %s.\n"), unit,
  15699                                          h_data_p->ep_id, bcm_errmsg(rv)));
  15700                     goto cleanup;
  15701                 } else {
  15702                     LOG_DEBUG(BSL_LS_BCM_OAM,
  15703                              (BSL_META_U(unit,
  15704                                          "BHH(unit %d) Info: Hash Tbl (EP=%d)"
  15705                                          " inserted  - %s.\n"), unit, ep_id,
  15706                     bcm_errmsg(rv)));
  15707                 }
  15708                 h_data_p->in_use = 1;
  15709 
  15710                 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
  15711                 if (BCM_SUCCESS
  15712                         (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p,
  15713                                                     &mp_grp_index,
  15714                                                     &egr_mp_group))) {
  15715                     mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  15716                             MDL_BITMAP_PASSIVEf);
  15717                 }
  15718 
  15719                 if (!(mdl_mip & (1 << h_data_p->level))) {
  15720                     /* Set the MIP flag */
  15721                     h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  15722                 }
  15723 
  15724             } else
  15725 #endif /* BHH*/
  15726         {
  15727 
  15728             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  15729                 ma_idx = ma_base_idx + ma_offset;
  15730                 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)),
  15731                         sizeof(bcm_oam_endpoint_t));
  15732                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  15733                 if (BCM_FAILURE(rv)) {
  15734                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  15735                     LOG_ERROR(BSL_LS_BCM_OAM, 
  15736                             (BSL_META_U(unit,
  15737                                         "OAM Error: (EP_ID=%d) Index reserve "
  15738                                         " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  15739                     return (rv);
  15740                 }
  15741             } else {
  15742                 /* Allocate the next available endpoint index. */
  15743                 rv = shr_idxres_list_alloc(oc->mep_pool,
  15744                         (shr_idxres_element_t *)&ep_id);
  15745                 if (BCM_FAILURE(rv)) {
  15746                     LOG_ERROR(BSL_LS_BCM_OAM,
  15747                             (BSL_META_U(unit,
  15748                                         "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"),
  15749                              unit, ep_id, bcm_errmsg(rv)));
  15750                     goto cleanup;
  15751                 }
  15752             }
  15753             h_data_p = &oc->oam_hash_data[ep_id];
  15754             if (1 == h_data_p->in_use) {
  15755                 return(BCM_E_INTERNAL);
  15756             }
  15757 
  15758             /* 
  15759              * Clear the hash data element contents before
  15760              * storing values.
  15761              */
  15762             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  15763 
  15764             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  15765             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  15766             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  15767             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  15768             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  15769             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15770             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15771             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  15772             h_data_p->trunk_id =  BCM_TRUNK_INVALID;
  15773             h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  15774 
  15775             h_data_p->ep_id = ep_id;
  15776             h_data_p->ma_base_index = 
  15777                 soc_MP_GROUPm_field32_get(unit, mp_group_entry,
  15778                         MA_BASE_PTRf);
  15779             h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  15780             ma_offset++;
  15781 
  15782             rv = READ_MA_INDEXm
  15783                     (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index,
  15784                      &ma_idx_entry);
  15785             if (BCM_FAILURE(rv)) {
  15786                 LOG_ERROR(BSL_LS_BCM_OAM,
  15787                           (BSL_META_U(unit,
  15788                                       "OAM(unit %d) Error: MA_INDEX (index:%d) read failed -"
  15789                                        " %s.\n"), unit, h_data_p->local_rx_index,
  15790                            bcm_errmsg(rv)));
  15791                 goto cleanup;
  15792             }
  15793 
  15794             h_data_p->in_use = 1;
  15795 
  15796             h_data_p->is_remote = 0;
  15797 
  15798             h_data_p->local_rx_enabled = 1;
  15799 
  15800             h_data_p->group_index
  15801                 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  15802 
  15803             h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf);
  15804 
  15805             h_data_p->active_mdl_bitmap = 
  15806                 soc_MP_GROUPm_field32_get(unit, mp_group_entry, 
  15807                                             MDL_BITMAP_ACTIVEf);
  15808 
  15809             h_data_p->profile_index
  15810                 = soc_MA_INDEXm_field32_get
  15811                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
  15812             rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
  15813                     _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index),
  15814                     _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE);
  15815             if (BCM_FAILURE(rv)) {
  15816                 LOG_ERROR(BSL_LS_BCM_OAM,
  15817                           (BSL_META_U(unit,
  15818                                       "OAM(unit %d) Error: Profile entry recover failed "
  15819                                       "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15820                 goto cleanup;
  15821             }
  15822 
  15823 #if defined(BCM_METROLITE_SUPPORT)
  15824             if(SOC_IS_METROLITE(unit)) {
  15825                 h_data_p->lm_count_profile = soc_MA_INDEXm_field32_get (unit, &ma_idx_entry, 
  15826                         OAM_COUNT_PROFILEf);
  15827                 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile,
  15828                         h_data_p->lm_count_profile, 
  15829                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  15830                 if (BCM_FAILURE(rv)) {
  15831                     LOG_ERROR(BSL_LS_BCM_OAM,
  15832                             (BSL_META_U(unit,
  15833                                         "OAM(unit %d) Error: Profile entry recover failed "
  15834                                         "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15835                     goto cleanup;
  15836                 }
  15837                 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile,
  15838                         h_data_p->lm_count_profile, 
  15839                         _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE);
  15840                 if (BCM_FAILURE(rv)) {
  15841                     LOG_ERROR(BSL_LS_BCM_OAM,
  15842                             (BSL_META_U(unit,
  15843                                         "OAM(unit %d) Error: Profile entry recover failed "
  15844                                         "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15845                     goto cleanup;
  15846                 }            
  15847             }
  15848 #endif
  15849 
  15850             h_data_p->dglp1_profile_index =
  15851                      soc_MA_INDEXm_field32_get
  15852                                 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  15853             rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile,
  15854                                          h_data_p->dglp1_profile_index, 1);
  15855             if (BCM_FAILURE(rv)) {
  15856                 LOG_ERROR(BSL_LS_BCM_OAM,
  15857                           (BSL_META_U(unit,
  15858                                       "OAM(unit %d) Error: DGLP profile ref count  "
  15859                                       "increment failed (EP=%d) - %s.\n"), unit,
  15860                            h_data_p->ep_id, bcm_errmsg(rv)));
  15861                 goto cleanup;
  15862             }
  15863             h_data_p->dglp2_profile_index =
  15864                 soc_MA_INDEXm_field32_get
  15865                     (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf);
  15866             rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile,
  15867                                          h_data_p->dglp2_profile_index, 1);
  15868             if (BCM_FAILURE(rv)) {
  15869                 LOG_ERROR(BSL_LS_BCM_OAM,
  15870                           (BSL_META_U(unit,
  15871                                       "OAM(unit %d) Error: DGLP profile ref count  "
  15872                                       "increment failed (EP=%d) - %s.\n"), unit,
  15873                            h_data_p->ep_id, bcm_errmsg(rv)));
  15874                 goto cleanup;
  15875             }
  15876 
  15877             h_data_p->name = 0x0; /* No need to set it to 0xffff */
  15878             
  15879             h_data_p->level = mdl;
  15880 
  15881             h_data_p->oam_domain = soc_MP_GROUPm_field32_get(unit,
  15882                                                  mp_group_entry,
  15883                                                  KEY_TYPEf);
  15884 
  15885             switch (h_data_p->oam_domain) {
  15886                 case _BCM_OAM_DOMAIN_CVLAN:
  15887                     h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN;
  15888                     h_data_p->inner_vlan = 
  15889                           soc_MP_GROUPm_field32_get(unit, 
  15890                                                          mp_group_entry, CVIDf);
  15891                     h_data_p->type = bcmOAMEndpointTypeEthernet;
  15892                     break;
  15893 
  15894                 case _BCM_OAM_DOMAIN_SVLAN:
  15895                     h_data_p->vlan = soc_MP_GROUPm_field32_get(unit,
  15896                                                      mp_group_entry, SVIDf);
  15897                     h_data_p->type = bcmOAMEndpointTypeEthernet;
  15898                     break;
  15899 
  15900                 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
  15901                     h_data_p->vlan = soc_MP_GROUPm_field32_get(unit,
  15902                                                      mp_group_entry, SVIDf);
  15903                     h_data_p->inner_vlan = 
  15904                              soc_MP_GROUPm_field32_get(unit, 
  15905                                                          mp_group_entry, CVIDf);
  15906                     h_data_p->flags |= 
  15907                                    BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN;
  15908                     h_data_p->type = bcmOAMEndpointTypeEthernet;
  15909                     break;
  15910                 
  15911                 case _BCM_OAM_DOMAIN_VP:
  15912                     h_data_p->vp = soc_MP_GROUPm_field32_get(unit, 
  15913                                                      mp_group_entry, VPf);
  15914                     h_data_p->type = bcmOAMEndpointTypeEthernet;
  15915                     h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  15916                     break;
  15917                 case _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW:
  15918                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmPw;
  15919                     /* Get the SVP */
  15920                     h_data_p->vp   = soc_MP_GROUPm_field32_get(unit, 
  15921                             mp_group_entry, VPf);
  15922                     h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  15923                     break;
  15924                 case _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP:
  15925                 case _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP:
  15926                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmLsp;
  15927                     h_data_p->label = soc_MP_GROUPm_field32_get(unit,
  15928                             mp_group_entry, MPLS_LABELf);
  15929                     break;
  15930                 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION:       
  15931                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionPort;
  15932                     break;
  15933                 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN:
  15934                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionInnervlan;
  15935                     h_data_p->inner_vlan = soc_MP_GROUPm_field32_get(unit,
  15936                             mp_group_entry, CVIDf);
  15937                     break;
  15938                 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN:      
  15939                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionOuterVlan;
  15940                     h_data_p->vlan = soc_MP_GROUPm_field32_get(unit,
  15941                             mp_group_entry, SVIDf);
  15942                     break;
  15943                 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN:
  15944                     h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan;
  15945                     h_data_p->inner_vlan = soc_MP_GROUPm_field32_get(unit,
  15946                             mp_group_entry, CVIDf);
  15947                     h_data_p->vlan = soc_MP_GROUPm_field32_get(unit,
  15948                             mp_group_entry, SVIDf);
  15949                     break;
  15950                 default :
  15951                     break;
  15952   
  15953             }
  15954 
  15955             rv = _bcm_sb2_oam_rx_counter_recover(unit, 
  15956                        MP_GROUPm, (uint32 *)mp_group_entry, h_data_p);
  15957             if (BCM_FAILURE(rv)) {
  15958                 LOG_ERROR(BSL_LS_BCM_OAM,
  15959                           (BSL_META_U(unit,
  15960                                       "OAM(unit %d) Error: LM counter recover failed "
  15961                                       "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  15962                 goto cleanup;
  15963             }
  15964             /* rx and tx counters are located at same index, but on diff mem */
  15965             if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  15966                 h_data_p->tx_ctr = h_data_p->rx_ctr;
  15967             }
  15968 
  15969             /* time stamp */
  15970             timestamp_type = soc_MP_GROUPm_field32_get(unit,
  15971                                                mp_group_entry, TIMESTAMP_TYPEf);
  15972             if (timestamp_type) {
  15973                 h_data_p->ts_format = !timestamp_type;
  15974             } 
  15975             glp = soc_MP_GROUPm_field32_get(unit, mp_group_entry, 
  15976                                                             GLPf);
  15977 
  15978             if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_VP) { 
  15979 #if defined(INCLUDE_L3)
  15980                 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
  15981 
  15982                     BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  15983 
  15984                 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
  15985 
  15986                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  15987 
  15988                 } else {
  15989                     LOG_ERROR(BSL_LS_BCM_OAM,
  15990                               (BSL_META_U(unit,
  15991                                           "OAM(unit %d) Error: Invalid Virtual Port (SVP=%d)"
  15992                                            " - %s.\n"), unit, h_data_p->vp,
  15993                                bcm_errmsg(BCM_E_INTERNAL)));
  15994                     return (BCM_E_INTERNAL);
  15995                 }
  15996 #endif
  15997             } else {
  15998                 /* Not resolving GPORT for PW MPLS LM/DM endpoints and 
  15999                  * MPLS LSP endpoints with port independent label
  16000                  */
  16001 #if defined(INCLUDE_L3)
  16002                 if ((!MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) ||
  16003                     (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) && 
  16004                      (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 
  16005                      BCM_GPORT_INVALID) != BCM_E_NONE))) 
  16006 #endif
  16007                 {
  16008                     /*
  16009                      * Generic logical port type, construct gport from GLP.
  16010                      */
  16011                     _bcm_gport_dest_t_init(&gport_dest);
  16012 
  16013                     if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) {
  16014                         gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  16015                         gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  16016                         h_data_p->trunk_id =  _BCM_OAM_GLP_TRUNK_ID_GET(glp);
  16017                         rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  16018                     } else {
  16019                         gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  16020                         gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp);
  16021                         gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp);
  16022 
  16023                         BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 
  16024                                     gport_dest.port, &pp_port));
  16025                         /* Check if the pp_port corresponding to mod port is in
  16026                          * subport port range.
  16027                          */
  16028                         if (SOC_PP_PORT_VALID(unit, pp_port)) {
  16029                             _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
  16030                             /* Get gport for subport port case */
  16031                             rv = BCM_E_NONE;
  16032                             if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
  16033                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY);
  16034                             } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
  16035                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG);
  16036                             } else {
  16037                                 rv =  BCM_E_PORT;
  16038                             }
  16039                         } else {
  16040                             /* Go through original gport construction */
  16041                             rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  16042                         }
  16043                     }
  16044 
  16045 
  16046                     if (BCM_FAILURE(rv)) {
  16047                         LOG_ERROR(BSL_LS_BCM_OAM,
  16048                                 (BSL_META_U(unit,
  16049                                             "OAM(unit %d) Error: Gport construct failed -"
  16050                                             " %s.\n"), unit, bcm_errmsg(rv)));
  16051                         goto cleanup;
  16052                     }
  16053 
  16054                     h_data_p->gport = gport;
  16055                 }
  16056             }
  16057             h_data_p->dglp = glp;
  16058             h_data_p->sglp = glp;
  16059 
  16060             /* If it is ETH/MPLS LM/DM endpoint, retrieve
  16061              * back the parameters stored in scache.
  16062              */
  16063             if (recovered_ver >= BCM_WB_VERSION_1_1) {
  16064                 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ||
  16065                     bcmOAMEndpointTypeEthernet == h_data_p->type) {
  16066 
  16067                     lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE;
  16068                     _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc);
  16069                 }
  16070             }
  16071 #if defined(INCLUDE_MPLS_LM_DM)
  16072             if (recovered_ver >= BCM_WB_VERSION_1_2) {
  16073                 if (MPLS_LM_DM_ENDPOINT_TYPE (h_data_p)) {
  16074                     lm_dm_scache_info_ptr =
  16075                      *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE +
  16076                      _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE +
  16077                      _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(h_data_p->local_rx_index);
  16078                     _bcm_sb2_oam_copy_egr_label_scache_to_hash_data(
  16079                         (_bcm_sb2_oam_egr_label_scache_info_t *)lm_dm_scache_info_ptr, h_data_p);
  16080                 }
  16081             }
  16082 #endif
  16083 
  16084 #if defined(INCLUDE_L3)
  16085             if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) {
  16086                 if (_bcm_vp_used_get(unit, h_data_p->vp, _bcmVpTypeMpls)) {
  16087                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
  16088                     bcm_mpls_port_t_init(&mpls_port);
  16089                     mpls_port.mpls_port_id = h_data_p->gport;
  16090                     rv = bcm_esw_mpls_port_get(unit, h_data_p->vpn,
  16091                             &mpls_port);
  16092                     if (BCM_FAILURE(rv)) {
  16093                         LOG_ERROR(BSL_LS_BCM_OAM,
  16094                                 (BSL_META_U(unit,
  16095                                             "OAM(unit %d) Error: PW MPLS port info recover failed "
  16096                                             "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  16097                         goto cleanup;
  16098                     }
  16099                     h_data_p->egress_if = mpls_port.egress_tunnel_if;
  16100                     h_data_p->label     = mpls_port.match_label;
  16101                     /* Doing minus 1 to fit the range 1-4 into range 0-3 for vccv type */
  16102                     h_data_p->vccv_type = mpls_port.vccv_type - 1;
  16103                 } else {
  16104                     /* The VP is not of type MPLS. Should not happen */
  16105                     LOG_ERROR(BSL_LS_BCM_OAM,
  16106                             (BSL_META_U(unit,
  16107                                         "OAM(unit %d) Error: LM counter recover failed "
  16108                                         "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  16109                     goto cleanup;
  16110 
  16111                 }
  16112             }
  16113 #endif
  16114 
  16115             if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  16116                 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
  16117             }
  16118 
  16119             sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t));
  16120             if (BCM_SUCCESS
  16121                     (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p,
  16122                                                 &mp_grp_index,
  16123                                                 &egr_mp_group))) {
  16124                 mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  16125                         MDL_BITMAP_PASSIVEf);
  16126             }
  16127 
  16128             if (!(mdl_mip & (1 << h_data_p->level))) {
  16129                 /* Set the MIP flag */
  16130                 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  16131             }
  16132 
  16133             rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
  16134             if (BCM_FAILURE(rv)) {
  16135                 goto cleanup;
  16136             }
  16137 
  16138             rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p);
  16139             if (BCM_FAILURE(rv)) {
  16140                 _bcm_sb2_oam_group_ep_list_remove(unit,
  16141                         h_data_p->group_index,
  16142                         ep_id);
  16143                 goto cleanup;
  16144             }
  16145 
  16146             rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  16147             if (BCM_FAILURE(rv)) {
  16148                 _bcm_sb2_oam_group_ep_list_remove(unit,
  16149                                               h_data_p->group_index,
  16150                                               ep_id);
  16151                 goto cleanup;
  16152             }
  16153 
  16154             bcm_oam_endpoint_info_t_init(ep_info);
  16155 
  16156             /* Set up endpoint information for key construction. */
  16157             ep_info->group = h_data_p->group_index;
  16158             ep_info->name = h_data_p->name;
  16159             ep_info->gport = h_data_p->gport;
  16160             ep_info->level = h_data_p->level;
  16161             ep_info->vlan = h_data_p->vlan;
  16162             ep_info->inner_vlan = h_data_p->inner_vlan;
  16163             if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  16164                 ep_info->mpls_label = h_data_p->label;
  16165             }
  16166             ep_info->type       = h_data_p->type;
  16167             if ((recovered_ver < BCM_WB_VERSION_1_9)
  16168                 || (!ETH_TYPE(h_data_p->type))) {
  16169                 /*
  16170                  * Calculate hash key for hash table insert
  16171                  * operation.
  16172                  */
  16173                 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  16174 
  16175 
  16176                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  16177                 if (BCM_FAILURE(rv)) {
  16178                     LOG_ERROR(BSL_LS_BCM_OAM,
  16179                             (BSL_META_U(unit,
  16180                                         "OAM(unit %d) Error: Hash table insert"
  16181                                         " (EP=%d) failed - %s.\n"), unit,
  16182                              h_data_p->ep_id, bcm_errmsg(rv)));
  16183 
  16184                     _bcm_sb2_oam_group_ep_list_remove(unit,
  16185                             h_data_p->group_index,
  16186                             ep_id);
  16187                     goto cleanup;
  16188                 } else {
  16189                     LOG_DEBUG(BSL_LS_BCM_OAM,
  16190                             (BSL_META_U(unit,
  16191                                         "OAM(unit %d) Info: Hash Tbl (EP=%d)"
  16192                                         " inserted  - %s.\n"), unit, ep_id,
  16193                              bcm_errmsg(rv)));
  16194                 }
  16195             }
  16196             sal_free(ep_info);
  16197             /* Make it NULL to avoid dangling pointer free in cleanup */
  16198             ep_info = NULL;
  16199         }
  16200     }
  16201 
  16202     } /* end of for loop */
  16203     if (mdl_bitmap) {
  16204         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit,
  16205                     h_data_p, &ma_idx_entry_count, &pool));
  16206         rv = shr_idxres_list_reserve(pool,
  16207                 h_data_p->ma_base_index,
  16208                 h_data_p->ma_base_index + ma_idx_entry_count -1);
  16209         if (BCM_FAILURE(rv)) {
  16210             LOG_ERROR(BSL_LS_BCM_OAM,
  16211                       (BSL_META_U(unit,
  16212                                   "OAM(unit %d) Error: (RMEP=%d) Index reserve failed"
  16213                                    "  - %s.\n"), unit, h_data_p->remote_index,
  16214                        bcm_errmsg(rv)));
  16215             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  16216             goto cleanup;
  16217         }
  16218     }
  16219 
  16220     LOG_DEBUG(BSL_LS_BCM_OAM,
  16221               (BSL_META_U(unit,
  16222                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  16223                            " - done.\n"), unit));
  16224     return (BCM_E_NONE);
  16225 
  16226 cleanup:
  16227 
  16228     tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p);
  16229     if (BCM_FAILURE(tmp_rv)) {
  16230         LOG_DEBUG(BSL_LS_BCM_OAM,
  16231                   (BSL_META_U(unit,
  16232                               "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -"
  16233                                " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  16234     }
  16235 
  16236 
  16237     if (NULL != ep_info) {
  16238         sal_free(ep_info);
  16239     }
  16240 
  16241     if (BCM_E_EXISTS
  16242         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  16243         shr_idxres_list_free(oc->mep_pool, ep_id);
  16244     }
  16245 #if defined(INCLUDE_BHH)
  16246     if (BCM_E_EXISTS
  16247          == shr_idxres_list_elem_state(oc->bhh_pool,bhh_endpoint_index)) {
  16248             shr_idxres_list_free(oc->bhh_pool,bhh_endpoint_index);
  16249     }
  16250 #endif
  16251     /* return rx & tx counters allocated if any */
  16252     if (NULL != h_data_p) {
  16253         rv =_bcm_sb2_oam_free_counter(unit, h_data_p);
  16254         if (BCM_FAILURE(rv)) {
  16255             LOG_ERROR(BSL_LS_BCM_OAM,
  16256                       (BSL_META_U(unit,
  16257                                   "OAM(unit %d) Error: LM counter block "
  16258                                   "free failed (EP=%d) - %s.\n"),
  16259                        unit, ep_id, bcm_errmsg(rv)));
  16260         }
  16261     }
  16262     if (NULL != h_data_p && (BCM_E_EXISTS
  16263             == shr_idxres_list_elem_state(pool,
  16264                                           h_data_p->ma_base_index))) {
  16265 
  16266         shr_idxres_list_free(pool, h_data_p->ma_base_index);
  16267 
  16268     }
  16269 
  16270     if (NULL != h_data_p) {
  16271         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  16272     }
  16273     LOG_DEBUG(BSL_LS_BCM_OAM,
  16274               (BSL_META_U(unit,
  16275                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover"
  16276                            " - error_done.\n"), unit));
  16277     return (rv);
  16278 
  16279 }
  16280 
  16281 /*
  16282  * Function:
  16283  *      _bcm_sb2_oam_lmep_tx_config_recover
  16284  * Purpose:
  16285  *     Recover OAM local endpoint Tx configuration.
  16286  * Parameters:
  16287  *     unit        - (IN) BCM device number
  16288  * Returns:
  16289  *     BCM_E_XXX
  16290  */
  16291 STATIC int
  16292 _bcm_sb2_oam_lmep_tx_config_recover(int unit, uint8 **scache, 
  16293                                     uint16 recovered_ver)
  16294 {
  16295     _bcm_gport_dest_t       gport_dest;   /* Gport specification.             */
  16296     bcm_gport_t             gport;        /* Gport value.                     */
  16297     int                     index;        /* Hardware index.                  */
  16298     lmep_entry_t            lmep_entry;   /* LMEP table entry buffer.         */
  16299     lmep_1_entry_t          lmep_1_entry; /* LMEP table entry buffer.         */
  16300     maid_reduction_entry_t  maid_red_ent; /* MAID_REDUCTION table entry buf.  */
  16301     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.      */
  16302     _bcm_oam_group_data_t   *g_info_p;    /* Group information pointer.       */
  16303     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
  16304     bcm_module_t            modid;        /* Module ID.                       */
  16305     bcm_port_t              port_id;      /* Port ID.                         */
  16306     bcm_trunk_t             trunk_id;     /* Trunk ID.                        */
  16307     uint32                  grp_idx;      /* Group index.                     */
  16308     uint16                  glp;          /* Generic logical port.            */
  16309     uint16                  vlan;         /* VLAN ID.                         */
  16310     uint16                  inner_vlan;   /* Inner VLAN ID.                   */
  16311     uint8                   level;        /* Maintenance domain level.        */
  16312     _bcm_oam_ep_list_t      *cur;         /* Current head node pointer.       */
  16313     int                     ep_id = -1;   /* Endpoint ID.                     */
  16314     uint8                   match_found = 0; /* Matching endpoint found.      */
  16315     int                     rv;           /* Operation return status.         */
  16316     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
  16317     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer.  */
  16318     _bcm_oam_hash_data_t    sh_data; /* Endpoint hash data pointer. */
  16319     uint32                  ccm_period = 0;
  16320     bcm_port_t              pp_port;
  16321     egr_port_entry_t        egr_port_entry;
  16322     uint8                   mdl_mip = 0;
  16323     int                     trunk_index = -1;
  16324     int                     tpid_index = 0; 
  16325 
  16326     LOG_DEBUG(BSL_LS_BCM_OAM,
  16327               (BSL_META_U(unit,
  16328                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover.\n"),
  16329                unit));
  16330 
  16331     /*
  16332      * Get OAM control structure.
  16333      *     Note: Lock taken by calling routine.
  16334      */
  16335     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  16336 
  16337     rv = _bcm_sb2_oam_endpoint_alloc(&ep_info);
  16338     if (BCM_FAILURE(rv)) {
  16339         return (rv);
  16340     }
  16341 
  16342     /*
  16343      * At this point, Remote MEP and Local MEP Rx config has been
  16344      *  recovered. Now, recover the Tx config for Local MEPs.
  16345      */
  16346     for (index = 0; index < oc->lmep_count; index++) {
  16347 
  16348         /* Get the LMEP table entry. */
  16349         rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry);
  16350         if (BCM_FAILURE(rv)) {
  16351             LOG_ERROR(BSL_LS_BCM_OAM,
  16352                       (BSL_META_U(unit,
  16353                                   "OAM(unit %d) Error: LMEP table read (index=%d) failed "
  16354                                    "- %s.\n"), unit, index, bcm_errmsg(rv)));
  16355             goto cleanup;
  16356         }
  16357 
  16358         /* Get the LMEP_1 table entry. */
  16359         rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry);
  16360         if (BCM_FAILURE(rv)) {
  16361             LOG_ERROR(BSL_LS_BCM_OAM,
  16362                       (BSL_META_U(unit,
  16363                                   "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed "
  16364                                    "- %s.\n"), unit, index, bcm_errmsg(rv)));
  16365             goto cleanup;
  16366         }
  16367         ccm_period = _bcm_sb2_oam_ccm_hw_encode_to_msecs
  16368                       ((int) soc_LMEPm_field32_get(unit, &lmep_entry,
  16369                                                    CCM_INTERVALf));
  16370         if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) {
  16371             continue;
  16372         } 
  16373         grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf);
  16374 
  16375         rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent);
  16376         if (BCM_FAILURE(rv)) {
  16377             LOG_ERROR(BSL_LS_BCM_OAM,
  16378                       (BSL_META_U(unit,
  16379                                   "OAM(unit %d) Error: MAID_REDU read (GID=%d) failed "
  16380                                    "- %s.\n"), unit, grp_idx, bcm_errmsg(rv)));
  16381             goto cleanup;
  16382         }
  16383 
  16384         if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) {
  16385 
  16386             /* Get pointer to group memory. */
  16387             g_info_p = &oc->group_info[grp_idx];
  16388             if (0 == g_info_p->in_use) {
  16389                 rv = BCM_E_INTERNAL;
  16390                 goto cleanup;
  16391             }
  16392 
  16393             vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf);
  16394             inner_vlan = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf);
  16395             /* Only extract the VLAN ID portion of the tag. */
  16396             inner_vlan = inner_vlan & 0xfff;
  16397             rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry);
  16398             if (BCM_FAILURE(rv)) {
  16399                 LOG_ERROR(BSL_LS_BCM_OAM,
  16400                           (BSL_META_U(unit,
  16401                                       "OAM(unit %d) Error: LMEP_1 table read (index=%d) "
  16402                                       "failed " "- %s.\n"), unit, index, bcm_errmsg(rv)));
  16403                 goto cleanup;
  16404             }
  16405 
  16406             glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf);
  16407             rv = _bcm_kt2_pp_port_to_modport_get(unit, glp,
  16408                     &modid, &port_id);
  16409             if (BCM_FAILURE(rv)) {
  16410                 goto cleanup;
  16411             }
  16412 
  16413             level = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, MDLf);
  16414 
  16415             trunk_id = BCM_TRUNK_INVALID;
  16416             if (vlan != 0 || inner_vlan != 0) {
  16417                 rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id);
  16418                 if (BCM_FAILURE(rv)
  16419                         && (BCM_E_NOT_FOUND != rv)) {
  16420                     goto cleanup;
  16421                 }
  16422             }
  16423 
  16424             _bcm_gport_dest_t_init(&gport_dest);
  16425 
  16426             if (BCM_TRUNK_INVALID != trunk_id) {
  16427                 gport_dest.tgid = trunk_id;
  16428                 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  16429                 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  16430  
  16431                 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 
  16432                         trunk_id, 
  16433                         port_id,
  16434                         &trunk_index);
  16435 
  16436                 if(BCM_FAILURE(rv)) {
  16437                     goto cleanup;
  16438                 }
  16439  
  16440             } else {
  16441                 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  16442                 gport_dest.modid = modid;
  16443                 gport_dest.port = port_id;
  16444 
  16445                 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 
  16446                             gport_dest.port, &pp_port));
  16447                 /* Check if the pp_port corresponding to mod port is in
  16448                  * subport port range.
  16449                  */
  16450                 rv = BCM_E_NONE;
  16451                 if (SOC_PP_PORT_VALID(unit, pp_port)) {
  16452                     _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
  16453                     /* Get gport for subport port case */
  16454                     if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
  16455                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY);
  16456                     } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
  16457                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG);
  16458                     } else {
  16459                         rv = BCM_E_PORT;
  16460                     }
  16461                 } else {
  16462                     /* Go through original gport construction */
  16463                     rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
  16464                 }
  16465             }
  16466             if (BCM_FAILURE(rv)) {
  16467                 LOG_ERROR(BSL_LS_BCM_OAM,
  16468                           (BSL_META_U(unit,
  16469                                       "OAM(unit %d) Error: Gport construct "
  16470                                       "failed - %s.\n"),
  16471                            unit, bcm_errmsg(rv)));
  16472                 goto cleanup;
  16473             }
  16474             /* Get the endpoint list head pointer. */
  16475             cur = *(g_info_p->ep_list);
  16476             if (NULL != cur) {
  16477                 while (NULL != cur) {
  16478                     h_data_p = cur->ep_data_p;
  16479                     if (NULL == h_data_p) {
  16480                         LOG_ERROR(BSL_LS_BCM_OAM,
  16481                                   (BSL_META_U(unit,
  16482                                               "OAM(unit %d) Error: Group (GID=%d) NULL"
  16483                                                " endpoint list.\n"), unit, grp_idx));
  16484                         rv = BCM_E_INTERNAL;
  16485                         goto cleanup;
  16486                     }
  16487                     
  16488 
  16489                     if (vlan == h_data_p->vlan &&
  16490                         inner_vlan == h_data_p->inner_vlan 
  16491                         && gport == h_data_p->gport
  16492                         && level == h_data_p->level
  16493                         && 1 == h_data_p->local_rx_enabled) {
  16494                         match_found = 1;
  16495                         break;
  16496                     }
  16497                     cur = cur->next;
  16498                 }
  16499             }
  16500 
  16501             if (1 == match_found) {
  16502 
  16503                 bcm_oam_endpoint_info_t_init(ep_info);
  16504 
  16505                 /* Set up endpoint information for key construction. */
  16506                 ep_info->group = h_data_p->group_index;
  16507                 ep_info->name = h_data_p->name;
  16508                 ep_info->gport = h_data_p->gport;
  16509                 ep_info->level = h_data_p->level;
  16510                 ep_info->vlan = h_data_p->vlan;
  16511                 ep_info->inner_vlan = h_data_p->inner_vlan;
  16512                 ep_info->flags = h_data_p->flags;
  16513                 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  16514                     ep_info->mpls_label = h_data_p->label;
  16515                 }
  16516                 ep_info->type       = h_data_p->type;
  16517 
  16518                 if ((recovered_ver < BCM_WB_VERSION_1_9) 
  16519                         || (!ETH_TYPE(h_data_p->type))) {
  16520                     /*
  16521                      * Calculate hash key for hash table insert
  16522                      * operation.
  16523                      */
  16524                     _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, 
  16525                             &hash_key);
  16526 
  16527 
  16528                     /*
  16529                      * Delete insert done by Local Rx endpoint recovery code.
  16530                      * Endpoint name has been recovered and will result
  16531                      * in a different hash index.
  16532                      */
  16533                     rv = shr_htb_find(oc->ma_mep_htbl, hash_key,
  16534                             (shr_htb_data_t *)&sh_data, 1);
  16535                     if (BCM_E_NOT_FOUND == rv) {
  16536                         goto cleanup;
  16537                     }
  16538                 }
  16539 
  16540             } else {
  16541 
  16542                 if (recovered_ver >= BCM_WB_VERSION_1_1) {
  16543 
  16544                     sal_memcpy(&ep_id, 
  16545                     *(scache) + _BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(index), 
  16546                             sizeof(bcm_oam_endpoint_t));                
  16547 
  16548                     rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
  16549                     if (BCM_FAILURE(rv)) {
  16550                         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  16551                         LOG_ERROR(BSL_LS_BCM_OAM,
  16552                                 (BSL_META_U(unit,
  16553                                             "OAM Error: (EP_ID=%d) Index reserve "
  16554                                             " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
  16555                         goto cleanup;
  16556                     }
  16557                 } else {
  16558                     /* Allocate the next available endpoint index. */
  16559                     rv = shr_idxres_list_alloc(oc->mep_pool,
  16560                             (shr_idxres_element_t *)&ep_id);
  16561                     if (BCM_FAILURE(rv)) {
  16562                         LOG_ERROR(BSL_LS_BCM_OAM,
  16563                                 (BSL_META_U(unit,
  16564                                             "OAM(unit %d) Error: Endpoint alloc (EP=%d)"
  16565                                             " - %s.\n"), unit, ep_id, bcm_errmsg(rv)));
  16566                         goto cleanup;
  16567                     }
  16568                 }
  16569 
  16570                 h_data_p = &oc->oam_hash_data[ep_id];
  16571                 if (1 == h_data_p->in_use) {
  16572                     rv = BCM_E_INTERNAL;
  16573                     goto cleanup;
  16574                 }
  16575 
  16576                 _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  16577 
  16578                 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
  16579 
  16580                 rv = _bcm_sb2_oam_group_ep_list_add(unit, grp_idx, ep_id);
  16581                 if (BCM_FAILURE(rv)) {
  16582                     LOG_ERROR(BSL_LS_BCM_OAM,
  16583                               (BSL_META_U(unit,
  16584                                           "OAM(unit %d) Error: Adding (EP=%d)"
  16585                                            " to (GID=%d) failed - %s.\n"),
  16586                                unit, ep_id, grp_idx, bcm_errmsg(rv)));
  16587                     goto cleanup;
  16588                 }
  16589 
  16590                 h_data_p->ep_id = ep_id;
  16591                 h_data_p->group_index = grp_idx;
  16592                 h_data_p->local_rx_enabled = 0;
  16593                 h_data_p->vlan = vlan;
  16594                 h_data_p->inner_vlan = inner_vlan;
  16595                 h_data_p->gport = gport;
  16596                 h_data_p->level = level;
  16597                 if ((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) {
  16598                     h_data_p->oam_domain = _BCM_OAM_DOMAIN_PORT; 
  16599                 } 
  16600                 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  16601                 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  16602                 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  16603                 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  16604                 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  16605                 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 
  16606                 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 
  16607                 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  16608                 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16609                 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16610                 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16611                 h_data_p->trunk_id =  BCM_TRUNK_INVALID;
  16612             }
  16613             if((-1) != trunk_index) {
  16614                 h_data_p->trunk_index = trunk_index;
  16615             }
  16616 
  16617             h_data_p->src_pp_port = glp;
  16618             h_data_p->dst_pp_port = glp;
  16619             h_data_p->is_remote = 0;
  16620             h_data_p->in_use = 1;
  16621             h_data_p->local_tx_enabled = 1;
  16622             h_data_p->local_tx_index = index;
  16623             h_data_p->name
  16624                 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf);
  16625             h_data_p->period
  16626                 = _bcm_sb2_oam_ccm_hw_encode_to_msecs
  16627                       ((int) soc_LMEPm_field32_get(unit, &lmep_entry,
  16628                                                    CCM_INTERVALf));
  16629 
  16630             if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) {
  16631                 h_data_p->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW;
  16632             }
  16633             if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_PORT) {
  16634                 rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, h_data_p);
  16635                 if (BCM_FAILURE(rv)) {
  16636                     LOG_ERROR(BSL_LS_BCM_OAM,
  16637                               (BSL_META_U(unit,
  16638                                           "OAM(unit %d) Error: Unable to increment key ref count "
  16639                                            " - %s.\n"), unit, bcm_errmsg(rv)));
  16640                     goto cleanup;
  16641                 } 
  16642                 rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, h_data_p);
  16643                 if (BCM_FAILURE(rv)) {
  16644                     LOG_ERROR(BSL_LS_BCM_OAM,
  16645                               (BSL_META_U(unit,
  16646                                           "OAM(unit %d) Error: Unable to increment key ref count "
  16647                                            " - %s.\n"), unit, bcm_errmsg(rv)));
  16648                     goto cleanup;
  16649                 }
  16650             } else {
  16651                 BCM_IF_ERROR_RETURN
  16652                     (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY,
  16653                                   h_data_p->dst_pp_port, &egr_port_entry));
  16654                 mdl_mip = soc_EGR_PORTm_field32_get(unit, &egr_port_entry,
  16655                         MDL_BITMAP_PASSIVEf);
  16656                 if (!(mdl_mip & (1 << h_data_p->level))) {
  16657                     /* Set the MIP flag */
  16658                     h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
  16659                 }
  16660             }
  16661 
  16662             /* For ethernet CCM TX endpoints, fetch TPIDs from HW.
  16663              */
  16664             if (h_data_p->vlan != 0) {
  16665                 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 
  16666                         SVLAN_TPID_INDEXf);
  16667                 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_OUTER,
  16668                         tpid_index, &(h_data_p->outer_tpid));
  16669                 if (BCM_FAILURE(rv)) {
  16670                     LOG_ERROR(BSL_LS_BCM_OAM,
  16671                             (BSL_META_U(unit,
  16672                                         "OAM(unit %d) Error: Outer TPID fetch failed"
  16673                                         " EP=%d %s.\n"), unit, ep_id, 
  16674                              bcm_errmsg(rv)));
  16675                     goto cleanup;
  16676                 }
  16677                 h_data_p->outer_tpid_profile_index = tpid_index;
  16678                 SB2_OAM_OUTER_TPID_REF_COUNT(unit, tpid_index)++;
  16679             }
  16680 
  16681             if (h_data_p->inner_vlan != 0) {
  16682                 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_INNER,
  16683                         0, &(h_data_p->inner_tpid));
  16684                 if (BCM_FAILURE(rv)) {
  16685                     LOG_ERROR(BSL_LS_BCM_OAM,
  16686                             (BSL_META_U(unit,
  16687                                         "OAM(unit %d) Error: Inner TPID fetch failed"
  16688                                         " EP=%d %s.\n"), unit, ep_id, 
  16689                              bcm_errmsg(rv)));
  16690                     goto cleanup;
  16691                 }
  16692                 h_data_p->inner_tpid_profile_index = 0;
  16693                 SB2_OAM_INNER_TPID_REF_COUNT(unit, 0)++;
  16694             }
  16695 
  16696             if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) &&
  16697                     (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport))) {
  16698                 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 
  16699                         SUBPORT_TAG_TPID_INDEXf);
  16700                 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_SUBPORT,
  16701                         tpid_index, &(h_data_p->subport_tpid));
  16702                 if (BCM_FAILURE(rv)) {
  16703                     LOG_ERROR(BSL_LS_BCM_OAM,
  16704                             (BSL_META_U(unit,
  16705                                         "OAM(unit %d) Error: Subport TPID fetch failed"
  16706                                         " EP=%d %s.\n"), unit, ep_id, 
  16707                              bcm_errmsg(rv)));
  16708                     goto cleanup;
  16709                 }
  16710                 h_data_p->subport_tpid_profile_index = tpid_index;
  16711                 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, tpid_index)++;
  16712             }
  16713 
  16714             rv = shr_idxres_list_reserve(oc->lmep_pool,
  16715                                          h_data_p->local_tx_index,
  16716                                          h_data_p->local_tx_index);
  16717             if (BCM_FAILURE(rv)) {
  16718                 LOG_ERROR(BSL_LS_BCM_OAM,
  16719                           (BSL_META_U(unit,
  16720                                       "OAM(unit %d) Error: Tx index=%d reserve failed"
  16721                                        " - %s.\n"), unit, index, bcm_errmsg(rv)));
  16722 
  16723                 _bcm_sb2_oam_group_ep_list_remove(unit,
  16724                                               h_data_p->group_index,
  16725                                               h_data_p->ep_id);
  16726 
  16727                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  16728                 goto cleanup;
  16729             }
  16730 
  16731             bcm_oam_endpoint_info_t_init(ep_info);
  16732 
  16733             /* Set up endpoint information for key construction. */
  16734             ep_info->group = h_data_p->group_index;
  16735             ep_info->name = h_data_p->name;
  16736             ep_info->gport = h_data_p->gport;
  16737             ep_info->level = h_data_p->level;
  16738             ep_info->vlan = h_data_p->vlan;
  16739             ep_info->inner_vlan = h_data_p->inner_vlan;
  16740             ep_info->flags = h_data_p->flags;
  16741             if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  16742                 ep_info->mpls_label = h_data_p->label;
  16743             }
  16744             ep_info->type       = h_data_p->type;
  16745 
  16746             if ((recovered_ver < BCM_WB_VERSION_1_9) 
  16747                     || (!ETH_TYPE(h_data_p->type))) {
  16748                 /*
  16749                  * Calculate hash key for hash table insert
  16750                  * operation.
  16751                  */
  16752                 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
  16753 
  16754                 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  16755                 if (BCM_FAILURE(rv)) {
  16756                     LOG_ERROR(BSL_LS_BCM_OAM,
  16757                             (BSL_META_U(unit,
  16758                                         "OAM(unit %d) Error: Hash table insert"
  16759                                         " (EP=%d) failed - %s.\n"), unit,
  16760                              h_data_p->ep_id, bcm_errmsg(rv)));
  16761 
  16762                     _bcm_sb2_oam_group_ep_list_remove(unit,
  16763                             h_data_p->group_index,
  16764                             h_data_p->ep_id);
  16765 
  16766                     goto cleanup;
  16767                 } else {
  16768                     LOG_DEBUG(BSL_LS_BCM_OAM,
  16769                             (BSL_META_U(unit,
  16770                                         "OAM(unit %d) Info: Hash Tbl (EP=%d)"
  16771                                         " inserted  - %s.\n"), unit, h_data_p->ep_id,
  16772                              bcm_errmsg(rv)));
  16773                 }
  16774             }
  16775 
  16776         }
  16777 
  16778         match_found = 0;
  16779         h_data_p = NULL;
  16780     }
  16781 
  16782     LOG_DEBUG(BSL_LS_BCM_OAM,
  16783               (BSL_META_U(unit,
  16784                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover"
  16785                            " - done.\n"), unit));
  16786     sal_free(ep_info);
  16787     return (rv);
  16788 
  16789 cleanup:
  16790 
  16791     if (NULL != ep_info) {
  16792         sal_free(ep_info);
  16793     }
  16794 
  16795     if (0 == match_found && NULL != h_data_p) {
  16796         /* Return endpoint index to MEP pool. */
  16797         if (BCM_E_EXISTS
  16798             == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
  16799             shr_idxres_list_free(oc->mep_pool, ep_id);
  16800         }
  16801         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  16802     }
  16803 
  16804     if (BCM_E_EXISTS
  16805         == shr_idxres_list_elem_state(oc->lmep_pool, index)) {
  16806         shr_idxres_list_free(oc->lmep_pool, index);
  16807     }
  16808 
  16809     LOG_DEBUG(BSL_LS_BCM_OAM,
  16810               (BSL_META_U(unit,
  16811                           "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover"
  16812                            " - error_done.\n"), unit));
  16813     return (rv);
  16814 }
  16815 
  16816 #if defined(INCLUDE_BHH)
  16817 /*
  16818  * Function:
  16819  *     _bcm_sb2_oam_bhh_endpoint_type_recover
  16820  * Purpose:
  16821  *     Recover BHH endpoint type from EGR_MP_GROUP table.
  16822  * Parameters:
  16823  *     unit        - Device unit number.
  16824  * Returns:
  16825  *     BCM_E_XXX
  16826  */
  16827 STATIC int
  16828 _bcm_sb2_oam_bhh_endpoint_type_recover(int unit)
  16829 {
  16830     uint32                 entry_count;
  16831     uint32                 index;
  16832     egr_mp_group_entry_t   egr_mp_grp_entry;
  16833     ma_index_entry_t       ma_idx_entry;
  16834     uint32                 ma_base_idx = 0;
  16835     _bcm_oam_control_t     *oc;
  16836     int                    bhh_endpoint;
  16837     bcm_oam_endpoint_t     ep_id, bhh_endpoint_index;
  16838     _bcm_oam_hash_data_t   *h_data_p = NULL;
  16839     int                    key_type;
  16840     int                    rv = BCM_E_NONE;
  16841 
  16842     /*
  16843      * Get OAM control structure.
  16844      *     Note: Lock taken by calling routine.
  16845      */
  16846     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  16847 
  16848 
  16849     if (!soc_feature(unit, soc_feature_bhh) || (oc->ukernel_not_ready != 0)) {
  16850         return BCM_E_NONE;
  16851     }
  16852 
  16853     entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm);
  16854     for (index = 0; index < entry_count; index++) {
  16855         bhh_endpoint = 0;
  16856         rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry);
  16857         if (BCM_FAILURE(rv)) {
  16858             return (rv);
  16859         }
  16860         if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) {
  16861             ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit,
  16862                                                         &egr_mp_grp_entry,
  16863                                                         MA_BASE_PTRf);
  16864 
  16865             if (SHR_BITGET(oc->bhh_ma_index_in_use, ma_base_idx)) {
  16866                 bhh_endpoint = 1;
  16867             }
  16868         }
  16869         if (1 == bhh_endpoint) {
  16870             /* Read the MA_INDEX table (EGR_MA_INDEX is not programmed
  16871              * for BHH endpoints)
  16872              */
  16873             rv = READ_MA_INDEXm (unit, MEM_BLOCK_ANY,
  16874                                  ma_base_idx,
  16875                                  &ma_idx_entry);
  16876             if (BCM_FAILURE(rv)) {
  16877                 LOG_ERROR(BSL_LS_BCM_OAM,
  16878                           (BSL_META_U(unit,
  16879                            "BHH(unit %d) Error: MA_INDEX (index:%d) read failed -"
  16880                                       " %s.\n"), unit, ma_base_idx,
  16881                            bcm_errmsg(rv)));
  16882                 return rv;
  16883             }
  16884 
  16885             /*Fetch endpoint id from MA_INDEX_ENTRY  and reserve in bhh_pool*/
  16886             bhh_endpoint_index = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
  16887             ep_id = BCM_OAM_BHH_GET_SDK_EP(bhh_endpoint_index);
  16888 
  16889             h_data_p = &oc->oam_hash_data[ep_id];
  16890             if (1 == h_data_p->in_use) {
  16891                 return (BCM_E_INTERNAL);
  16892             }
  16893             rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_endpoint_index,
  16894                                          bhh_endpoint_index);
  16895             if (BCM_FAILURE(rv)) {
  16896                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  16897                 LOG_ERROR(BSL_LS_BCM_OAM,
  16898                           (BSL_META_U(unit,
  16899                                       "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"),
  16900                            unit, bhh_endpoint_index, bcm_errmsg(rv)));
  16901                 return rv;
  16902             }
  16903 
  16904             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
  16905             h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX;
  16906             h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX;
  16907             h_data_p->remote_index = _BCM_OAM_INVALID_INDEX;
  16908             h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX;
  16909             h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX;
  16910             h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX;
  16911             h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX;
  16912             h_data_p->profile_index = _BCM_OAM_INVALID_INDEX;
  16913             h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX;
  16914             h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  16915             h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16916             h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16917             h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  16918             h_data_p->ma_base_index = _BCM_OAM_INVALID_INDEX;
  16919             h_data_p->trunk_id =  BCM_TRUNK_INVALID;
  16920             h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  16921 
  16922             h_data_p->ep_id = ep_id;
  16923             h_data_p->bhh_endpoint_index = ep_id;
  16924 
  16925             key_type = soc_EGR_MP_GROUPm_field32_get(unit,
  16926                                                      &egr_mp_grp_entry,
  16927                                                      KEY_TYPEf);
  16928 
  16929             switch (key_type) {
  16930             case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION:
  16931                 h_data_p->type = bcmOAMEndpointTypeBhhSection;
  16932                 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit,
  16933                                                                &egr_mp_grp_entry,
  16934                                                                GLPf);
  16935                 break;
  16936 
  16937             case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN:
  16938                 h_data_p->type = bcmOAMEndpointTypeBhhSectionInnervlan;
  16939                 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit,
  16940                                                                &egr_mp_grp_entry,
  16941                                                                GLPf);
  16942                 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit,
  16943                                                                      &egr_mp_grp_entry,
  16944                                                                      CVIDf);
  16945                 break;
  16946 
  16947             case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN:
  16948                 h_data_p->type = bcmOAMEndpointTypeBhhSectionOuterVlan;
  16949                 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit,
  16950                                                                &egr_mp_grp_entry,
  16951                                                                GLPf);
  16952                 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit,
  16953                                                                &egr_mp_grp_entry,
  16954                                                                SVIDf);
  16955                 break;
  16956 
  16957             case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN:
  16958                 h_data_p->type = bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan;
  16959                 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit,
  16960                                                                &egr_mp_grp_entry,
  16961                                                                GLPf);
  16962                 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit,
  16963                                                                &egr_mp_grp_entry,
  16964                                                                SVIDf);
  16965                 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit,
  16966                                                                      &egr_mp_grp_entry,
  16967                                                                      CVIDf);
  16968                 break;
  16969 
  16970             case _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP:
  16971                 h_data_p->type = bcmOAMEndpointTypeBHHMPLS;
  16972                 h_data_p->label = soc_EGR_MP_GROUPm_field32_get(unit,
  16973                                                                 &egr_mp_grp_entry,
  16974                                                                 MPLS_LABELf);
  16975                 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit,
  16976                                                                &egr_mp_grp_entry,
  16977                                                                GLPf);
  16978                 break;
  16979             case _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW:
  16980                 h_data_p->type = bcmOAMEndpointTypeBHHMPLSVccv;
  16981                 h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit,
  16982                                                              &egr_mp_grp_entry,
  16983                                                              VPf);
  16984                 break;
  16985             }
  16986             h_data_p->in_use = 1;
  16987         }
  16988     }
  16989     return BCM_E_NONE;
  16990 }
  16991 #endif
  16992 
  16993 /*
  16994  * Function:
  16995  *     _bcm_sb2_oam_wb_endpoints_recover
  16996  * Purpose:
  16997  *     Recover OAM local endpoint Rx configuration.
  16998  * Parameters:
  16999  *     unit        - Device unit number.
  17000  *     stable_size - OAM module Level2 memory size.
  17001  *     oam_scache  - Pointer to secondary storage buffer pointer.
  17002  * Returns:
  17003  *     BCM_E_XXX
  17004  */
  17005 STATIC int
  17006 _bcm_sb2_oam_wb_endpoints_recover(int unit,
  17007                                   int stable_size,
  17008                                   uint8 **oam_scache, uint16 recovered_ver)
  17009 {
  17010     int                     index;        /* Hardware index.                  */
  17011     uint32                  entry_count;  /* Max entries in MP_GROUP/
  17012                                                           EGR_MP_GROUP table. */
  17013     l3_entry_1_entry_t      l3_entry;     /* RMEP view table entry.           */
  17014     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
  17015     int                     rv;           /* Operation return status.         */
  17016     mp_group_entry_t        mp_group_entry; /* MP group tbl entry buffer        */
  17017     egr_mp_group_entry_t    egr_mp_grp_entry;/* Egr MP group tbl entry buffer */
  17018     port_tab_entry_t        port_entry;   /* Port table entry buffer          */
  17019 
  17020     /*
  17021      * Get OAM control structure.
  17022      *     Note: Lock taken by calling routine.
  17023      */
  17024     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17025 
  17026     /* Get number of L3 table entries. */
  17027     entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm);
  17028 
  17029     /* Now get valid OAM endpoint entries. */
  17030     for (index = 0; index < entry_count; index++) {
  17031 
  17032         rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, index, &l3_entry);
  17033         if (BCM_FAILURE(rv)) {
  17034             LOG_ERROR(BSL_LS_BCM_OAM,
  17035                       (BSL_META_U(unit,
  17036                                   "OAM(unit %d) Error: L3_ENTRY (index=%d) read"
  17037                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  17038                 return (rv);
  17039         }
  17040 
  17041         if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf)) {
  17042 
  17043             switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 
  17044                                                           KEY_TYPEf)) {
  17045 
  17046                 case SOC_MEM_KEY_L3_ENTRY_RMEP:
  17047                     rv = _bcm_sb2_oam_rmep_recover(unit, index,
  17048                                                    &l3_entry, oam_scache, recovered_ver);
  17049                     if (BCM_FAILURE(rv)) {
  17050                         LOG_ERROR(BSL_LS_BCM_OAM,
  17051                                   (BSL_META_U(unit,
  17052                                               "OAM(unit %d) Error: Remote endpoint"
  17053                                                " (index=%d) reconstruct failed  - %s.\n"),
  17054                                    unit, index, bcm_errmsg(rv)));
  17055                         return (rv);
  17056                     }
  17057                     break;
  17058 
  17059                 default:
  17060                     /* Not an OAM entry. */
  17061                     continue;
  17062             }
  17063         }
  17064     }
  17065 
  17066 #if defined(INCLUDE_BHH)
  17067     /* Recover BHH endpoint types from EGR)_MP_GROUP table */
  17068     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_bhh_endpoint_type_recover(unit));
  17069 #endif /* BHH */
  17070 
  17071     /* Recover all downMEP's */
  17072     entry_count = soc_mem_index_count(unit, MP_GROUPm);
  17073     for (index = 0; index < entry_count; index++) {
  17074         BCM_SB2_TCAM_ATOMICITY_DISABLE(unit);
  17075         rv = READ_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &mp_group_entry);
  17076         BCM_SB2_TCAM_ATOMICITY_ENABLE(unit);
  17077         if (BCM_FAILURE(rv)) {
  17078             LOG_ERROR(BSL_LS_BCM_OAM,
  17079                       (BSL_META_U(unit,
  17080                                   "OAM(unit %d) Error: MP_GROUP ENTRY (index=%d) read"
  17081                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  17082                 return (rv);
  17083         }
  17084         if (soc_MP_GROUPm_field32_get(unit, &mp_group_entry, VALIDf)) {
  17085             rv = _bcm_sb2_oam_lmep_downmep_rx_config_recover(unit,
  17086                     index,
  17087                     &mp_group_entry, oam_scache, recovered_ver);
  17088             if (BCM_FAILURE(rv)) {
  17089                 LOG_ERROR(BSL_LS_BCM_OAM,
  17090                         (BSL_META_U(unit,
  17091                                     "OAM(unit %d) Error: Local endpoint DownMEP"
  17092                                     " (index=%d) reconstruct failed  - %s.\n"),
  17093                          unit, index, bcm_errmsg(rv)));
  17094                 return (rv);
  17095             }
  17096         }
  17097     }
  17098 
  17099     /* Recover all UpMEPs */
  17100     /* Get number of EGR_MP_GROUP table entries. */
  17101     entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm);
  17102 
  17103     /* Now get valid OAM endpoint entries. */
  17104     for (index = 0; index < entry_count; index++) {
  17105         rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry);
  17106         if (BCM_FAILURE(rv)) {
  17107             LOG_ERROR(BSL_LS_BCM_OAM,
  17108                       (BSL_META_U(unit,
  17109                                   "OAM(unit %d) Error: EGR_MP_GROUP ENTRY (index=%d) read"
  17110                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  17111                 return (rv);
  17112         }
  17113         if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) {
  17114             rv = _bcm_sb2_oam_lmep_upmep_rx_config_recover(unit, index,
  17115                                                              &egr_mp_grp_entry,
  17116                                                              oam_scache, recovered_ver);
  17117             if (BCM_FAILURE(rv)) {
  17118                 LOG_ERROR(BSL_LS_BCM_OAM,
  17119                           (BSL_META_U(unit,
  17120                                       "OAM(unit %d) Error: Local endpoint UpMEP"
  17121                                        " (index=%d) reconstruct failed  - %s.\n"),
  17122                            unit, index, bcm_errmsg(rv)));
  17123                 return (rv);
  17124             }
  17125         }
  17126     }
  17127 
  17128 
  17129     /* recover endpoints from Port table */
  17130     /* Get number of PORT_TABLE table entries. */
  17131     entry_count = soc_mem_index_count(unit, PORT_TABm);
  17132     /* Now get valid OAM endpoint entries. */
  17133     for (index = 0; index < entry_count; index++) {
  17134         rv = READ_PORT_TABm(unit, MEM_BLOCK_ANY, index, &port_entry);
  17135         if (BCM_FAILURE(rv)) {
  17136             LOG_ERROR(BSL_LS_BCM_OAM,
  17137                       (BSL_META_U(unit,
  17138                                   "OAM(unit %d) Error: Port table ENTRY (index=%d) read"
  17139                                    " failed  - %s.\n"), unit, index, bcm_errmsg(rv)));
  17140                 return (rv);
  17141         }
  17142         if (soc_PORT_TABm_field32_get(unit, &port_entry, OAM_ENABLEf)) {
  17143             rv = _bcm_sb2_oam_port_lmep_rx_config_recover(unit, index,
  17144                                                              &port_entry, 
  17145                                                              oam_scache, recovered_ver);
  17146             if (BCM_FAILURE(rv)) {
  17147                 LOG_ERROR(BSL_LS_BCM_OAM,
  17148                           (BSL_META_U(unit,
  17149                                       "OAM(unit %d) Error: Port based local endpoint "
  17150                                        " (index=%d) reconstruct failed  - %s.\n"),
  17151                            unit, index, bcm_errmsg(rv)));
  17152                 return (rv);
  17153             }
  17154         }
  17155     } 
  17156     rv = _bcm_sb2_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver);
  17157     if (BCM_FAILURE(rv)) {
  17158         LOG_ERROR(BSL_LS_BCM_OAM,
  17159                   (BSL_META_U(unit,
  17160                               "OAM(unit %d) Error: Endpoint Tx config recovery"
  17161                                " failed  - %s.\n"), unit, bcm_errmsg(rv)));
  17162         return (rv);
  17163     }
  17164 
  17165     return (BCM_E_NONE);
  17166 }
  17167 
  17168 /*
  17169  * Function:
  17170  *       bcm_sb2_oam_scache_alloc
  17171  * Purpose:
  17172  *     Allocate scache memory for OAM module 
  17173  * Parameters:
  17174  *     unit - (IN) BCM device number
  17175  * Returns:
  17176  *     BCM_E_UNIT    - Invalid BCM unit number.
  17177  *     BCM_E_UNAVAIL - OAM not support on this device.
  17178  *     BCM_E_MEMORY  - Allocation failure
  17179  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
  17180  *     BCM_E_NONE    - Success
  17181  */
  17182 STATIC int
  17183 bcm_sb2_oam_scache_alloc(int unit) {
  17184     _bcm_oam_control_t *oc;
  17185     soc_scache_handle_t scache_handle;
  17186     uint8 *oam_scache;
  17187     int alloc_sz = 0;
  17188     int trunk_idx_size;
  17189 
  17190     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17191 
  17192     alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
  17193 
  17194     /* Number of oam groups */
  17195     alloc_sz += sizeof(int);
  17196 
  17197     /* VFP group, IFP VP group, IFP GLP group */
  17198     alloc_sz += 3 * sizeof(bcm_field_group_t);
  17199 
  17200 #if defined(INCLUDE_BHH)
  17201     if(soc_feature(unit, soc_feature_bhh)) {
  17202         if (oc->ukernel_not_ready == 0) {
  17203             /*Allocate to store BHH endpoint ids at corresponding MA_INDEX*/
  17204             alloc_sz += SHR_BITALLOCSIZE(oc->ma_idx_count);
  17205             alloc_sz += sizeof(short) * oc->bhh_endpoint_count; /*bhh_ep_grp_id*/
  17206             alloc_sz += sizeof(short) * oc->bhh_endpoint_count; /*bhh_ep_vpn*/
  17207         }
  17208     }
  17209 #endif
  17210     /* Allocate memory to store logical endpoint Ids */
  17211     alloc_sz += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  17212     alloc_sz += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE);
  17213     alloc_sz += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE);
  17214 
  17215 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH)
  17216     if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17217             (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17218             (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  17219         /* Allocate memory for PM profile */
  17220         alloc_sz += (_BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE);
  17221         /* Endpoint id to pm id map */
  17222         alloc_sz += _bcm_sb2_oam_pmid_scache_size(unit);
  17223     }
  17224 #endif
  17225 
  17226     /* Allocate memory to store LSP lookup key_type in EGR_MP_GROUP */
  17227 #if defined(INCLUDE_BHH)
  17228     alloc_sz += sizeof(uint8);
  17229 #endif /* INCLUDE_BHH */
  17230 #if defined(INCLUDE_MPLS_LM_DM)
  17231     alloc_sz += sizeof(uint8);
  17232 #endif /* INCLUDE_MPLS_LM_DM */
  17233 
  17234 #if defined(INCLUDE_BHH)
  17235     if(soc_feature(unit, soc_feature_bhh)) {
  17236         if (oc->ukernel_not_ready == 0) {
  17237             /* vlan_pri and inner_vlan_pri */
  17238             alloc_sz += sizeof(uint8) * oc->bhh_endpoint_count * 2;
  17239         }
  17240     }
  17241 #endif
  17242 
  17243     /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */
  17244     alloc_sz += sizeof(uint8);
  17245 
  17246     /* Store trunk index for BHH and MPLS LM/DM endpoints */
  17247     trunk_idx_size = 0;
  17248 #if defined(INCLUDE_BHH)
  17249     if(soc_feature(unit, soc_feature_bhh)) {
  17250         if (oc->ukernel_not_ready == 0) {
  17251             trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17252         }
  17253     }
  17254 #endif /* INCLUDE_BHH */
  17255 #if defined(INCLUDE_MPLS_LM_DM)
  17256     if (oc->mpls_lm_dm_ukernel_ready) {
  17257         if (trunk_idx_size == 0 ) {
  17258             /* No BHH */
  17259             trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17260         }
  17261     }
  17262 #endif /* INCLUDE_MPLS_LM_DM */
  17263     alloc_sz += trunk_idx_size;
  17264 
  17265     /* FLAGS are stored for all ethernet OAM endpoints */
  17266     alloc_sz += (sizeof(uint32) * oc->ep_count);
  17267 
  17268 #if defined(INCLUDE_BHH)
  17269     /* Allocate memory to store oam_mpls_tp_ach_channel_type */
  17270     alloc_sz += sizeof(sb2_oam_mpls_tp_ach_channel_type);
  17271 #endif
  17272 
  17273 
  17274     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  17275     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
  17276                         alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL));
  17277     return BCM_E_NONE;
  17278 }
  17279 
  17280 /* Given h_data_p, this function fills the endpoint_info required for
  17281  * hash_key generation and inserts it at appropriate location.
  17282  *
  17283  * oc->lock is already assumed to be taken by caller */
  17284 int _bcm_sb2_oam_hash_tbl_insert_hash_data_entry(int unit, _bcm_oam_hash_data_t *h_data_p)
  17285 {
  17286     bcm_oam_endpoint_info_t ep_info;
  17287     _bcm_oam_control_t  *oc = NULL;                  /* Pointer to OAM control structure. */
  17288     _bcm_oam_hash_key_t     hash_key;                /* Hash key buffer for lookup.      */
  17289     int rv = BCM_E_NONE;
  17290 
  17291 
  17292     if (h_data_p == NULL) {
  17293         return BCM_E_INTERNAL;
  17294     }
  17295 
  17296     /* Get OAM control structure. */
  17297     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17298 
  17299     /* Initialize endpoint info structure. */
  17300     bcm_oam_endpoint_info_t_init(&ep_info);
  17301 
  17302     /* Set up endpoint information for key construction. */
  17303     ep_info.group = h_data_p->group_index;
  17304     ep_info.name = h_data_p->name;
  17305     ep_info.gport = h_data_p->gport;
  17306     ep_info.level = h_data_p->level;
  17307     ep_info.vlan = h_data_p->vlan;
  17308     ep_info.inner_vlan = h_data_p->inner_vlan;
  17309     ep_info.flags = h_data_p->flags;
  17310     if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) {
  17311         ep_info.mpls_label = h_data_p->label;
  17312     }
  17313     ep_info.type       = h_data_p->type;
  17314 
  17315     /* Construct hash key for lookup */
  17316     _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
  17317 
  17318     /* Insert entry from hash table. */
  17319     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
  17320     if (BCM_FAILURE(rv)) {
  17321         LOG_ERROR(BSL_LS_BCM_OAM,
  17322                   (BSL_META_U(unit,
  17323                               "OAM(unit %d) Error: Hash table insert failed "
  17324                                "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  17325     } else {
  17326         LOG_DEBUG(BSL_LS_BCM_OAM,
  17327                   (BSL_META_U(unit,
  17328                               "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted"
  17329                                " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  17330     }
  17331 
  17332     return rv;
  17333 }
  17334 
  17335 /*
  17336  * Function:
  17337  *     _bcm_sb2_oam_reinit
  17338  * Purpose:
  17339  *     Reconstruct OAM module software state.
  17340  * Parameters:
  17341  *     unit - (IN) BCM device number
  17342  * Retruns:
  17343  *     BCM_E_XXX
  17344  */
  17345 STATIC int
  17346 _bcm_sb2_oam_reinit(int unit)
  17347 {
  17348     uint32              group_count;          /* Stored OAM group count.           */
  17349     int                 stable_size;          /* Secondary storage size.           */
  17350     uint8               *oam_scache = NULL;   /* Pointer to scache memory.         */
  17351     soc_scache_handle_t scache_handle;        /* Scache memory handler.            */
  17352     _bcm_oam_control_t  *oc;                  /* Pointer to OAM control structure. */
  17353     int                 rv;                   /* Operation return status.          */
  17354     int                 realloc_size = 0;
  17355     uint16              recovered_ver = 0;
  17356     int                 trunk_idx_size = 0;
  17357 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  17358     uint8                 trunk_index;
  17359 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  17360     _bcm_oam_hash_data_t *h_data_p = NULL;
  17361     uint8               *tmp_oam_scache = NULL;
  17362     int idx = 0;
  17363 
  17364 
  17365     LOG_DEBUG(BSL_LS_BCM_OAM,
  17366               (BSL_META_U(unit,
  17367                           "OAM(unit %d) Info: OAM warm boot recovery.....\n"),
  17368                unit));
  17369 
  17370     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  17371 
  17372     /* Get OAM control structure. */
  17373     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17374 
  17375     _BCM_OAM_LOCK(oc);
  17376 
  17377     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
  17378 
  17379         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
  17380 
  17381         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
  17382                                      &oam_scache, BCM_WB_DEFAULT_VERSION,
  17383                                      &recovered_ver);
  17384         if (BCM_E_NOT_FOUND == rv) {
  17385             /* Upgrading from SDK release that does not have warmboot state */
  17386             bcm_sb2_oam_scache_alloc(unit);
  17387             _BCM_OAM_UNLOCK(oc);
  17388             return BCM_E_NONE;
  17389         } else if (BCM_FAILURE(rv)) {
  17390             goto cleanup;
  17391         }
  17392 
  17393         if (recovered_ver < BCM_WB_VERSION_1_3 && MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) {
  17394             LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Warn:"
  17395                             " Warm upgrade from a older version which does not support "
  17396                             "flexible endpoint hw index allocation. Reverting to older "
  17397                             "scheme.\n")));
  17398             oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL;
  17399             /* Destroy the previous allocation and re-allocate based on this scheme */
  17400             rv = _bcm_sb2_oam_ma_idx_pool_destroy(oc);
  17401             if (BCM_FAILURE(rv)) {
  17402                 goto cleanup;
  17403             }
  17404             rv = _bcm_sb2_oam_ma_idx_pool_create(oc); 
  17405             if (BCM_FAILURE(rv)) {
  17406                 goto cleanup;
  17407             }
  17408         }
  17409 
  17410         /* Recover the FP groups */
  17411         sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t));
  17412         oam_scache += sizeof(bcm_field_group_t);
  17413 
  17414         sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t));
  17415         oam_scache += sizeof(bcm_field_group_t);
  17416 
  17417         sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t));
  17418         oam_scache += sizeof(bcm_field_group_t);
  17419 
  17420         /* Recover the OAM groups */
  17421         sal_memcpy(&group_count, oam_scache, sizeof(int));
  17422         oam_scache += sizeof(int);
  17423 
  17424     } else {
  17425         rv = BCM_E_NONE;
  17426         goto cleanup;
  17427     }
  17428 
  17429     rv = _bcm_sb2_oam_wb_group_recover(unit, stable_size, &oam_scache);
  17430     if (BCM_FAILURE(rv)) {
  17431         LOG_ERROR(BSL_LS_BCM_OAM,
  17432                   (BSL_META_U(unit,
  17433                               "OAM(unit %d) Error: Group recovery failed  - %s.\n"),
  17434                    unit, bcm_errmsg(rv)));
  17435         goto cleanup;
  17436     }
  17437 
  17438 #if defined(INCLUDE_BHH)
  17439     if(soc_feature(unit, soc_feature_bhh)) {
  17440         if(0 == oc->ukernel_not_ready  &&
  17441            NULL != oam_scache) {
  17442 
  17443             /*Store MA_INDEX allocated to BHH*/
  17444             for (idx = 0; idx < _SHR_BITDCLSIZE (oc->ma_idx_count); idx++) {
  17445                 sal_memcpy( &oc->bhh_ma_index_in_use[idx], oam_scache, 
  17446                             sizeof(SHR_BITDCL));
  17447                 oam_scache += sizeof(SHR_BITDCL);
  17448             }
  17449 
  17450             /*Store BHH endpoint group ids */
  17451             for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  17452                 sal_memcpy(&oc->bhh_ep_grp_id[idx], oam_scache, sizeof(short));
  17453                 oam_scache += sizeof(short);
  17454             }
  17455 
  17456             /*Store BHH endpoint VPN */
  17457             for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  17458                 sal_memcpy(&oc->bhh_ep_vpn[idx], oam_scache, sizeof(short));
  17459                 oam_scache += sizeof(short);
  17460             }
  17461         }
  17462     }
  17463 #endif
  17464 #if defined(INCLUDE_ETH_LM_DM)
  17465     /* sessId to EpId cache */
  17466     if(eth_oam_id_map == NULL) {
  17467         eth_oam_id_map = sal_alloc(oc->eth_lm_dm_sess_count *
  17468                 sizeof(bcm_oam_endpoint_t), "eth_oam_sess_id_map");
  17469     }
  17470 #endif
  17471 #if defined(INCLUDE_MPLS_LM_DM)
  17472     if(mpls_oam_id_map == NULL) {
  17473         mpls_oam_id_map = sal_alloc(oc->mpls_lm_dm_sess_count *
  17474                 sizeof(bcm_oam_endpoint_t), "eth_oam_sess_id_map");
  17475     }
  17476 #endif
  17477     rv = _bcm_sb2_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, recovered_ver);
  17478     if (BCM_FAILURE(rv)) {
  17479         LOG_ERROR(BSL_LS_BCM_OAM,
  17480                   (BSL_META_U(unit,
  17481                               "OAM(unit %d) Error: Endpoint recovery failed  - %s.\n"),
  17482                    unit, bcm_errmsg(rv)));
  17483         goto cleanup;
  17484     }
  17485 
  17486     if (recovered_ver >= BCM_WB_VERSION_1_1) {
  17487         oam_scache += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  17488         oam_scache += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE);
  17489     }
  17490     if (recovered_ver >= BCM_WB_VERSION_1_2) {
  17491         oam_scache += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE);
  17492     }
  17493 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  17494     /* PM recovery */
  17495     if (recovered_ver >= BCM_WB_VERSION_1_4) {
  17496         if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17497                 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17498                 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  17499 
  17500             int8 pm_id;
  17501             _bcm_oam_hash_data_t *h_data_p = NULL;
  17502             int itr;
  17503             _bcm_oam_pm_profile_control_t *pmc = NULL;
  17504             pmc = pm_profile_control[unit];
  17505 
  17506             if (!pmc) {
  17507                 _BCM_OAM_UNLOCK(oc);
  17508                 return BCM_E_INIT;
  17509             }
  17510             for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) { 
  17511                 sal_memcpy(&(pmc->profile_info[itr]), oam_scache, 
  17512                             sizeof(_bcm_oam_pm_profile_int_info_t));
  17513                 oam_scache += sizeof(_bcm_oam_pm_profile_int_info_t);
  17514             }
  17515 #if defined(INCLUDE_ETH_LM_DM)
  17516             for(itr = 0; itr < oc->eth_lm_dm_sess_count; itr++) {
  17517                 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id));
  17518                 oam_scache += sizeof(pm_id);
  17519                 if(pm_id >= 0) {
  17520                     h_data_p = &oc->oam_hash_data[eth_oam_id_map[itr]];
  17521                     if(h_data_p->in_use) {
  17522                         h_data_p->pm_profile_attached = pm_id;
  17523                     }
  17524                 }
  17525             }
  17526             sal_free(eth_oam_id_map);
  17527             eth_oam_id_map = NULL;
  17528 #endif
  17529 #if defined(INCLUDE_MPLS_LM_DM)
  17530             for(itr = 0; itr < oc->mpls_lm_dm_sess_count; itr++) {
  17531                 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id));
  17532                 oam_scache += sizeof(pm_id);
  17533                 if(pm_id >= 0) {
  17534                     h_data_p = &oc->oam_hash_data[mpls_oam_id_map[itr]];
  17535                     if(h_data_p->in_use) {
  17536                         h_data_p->pm_profile_attached = pm_id;
  17537                     }
  17538                 }
  17539             }
  17540             sal_free(mpls_oam_id_map);
  17541             mpls_oam_id_map = NULL;
  17542 #endif
  17543 #if defined(INCLUDE_BHH)
  17544             for(itr = 0; itr < oc->bhh_endpoint_count; itr++) {
  17545                 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id));
  17546                 oam_scache += sizeof(pm_id);
  17547                 if(pm_id >= 0) {
  17548                     h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(itr)];
  17549                     if(h_data_p->in_use) {
  17550                         h_data_p->pm_profile_attached = pm_id;
  17551                     }
  17552                 }
  17553             }
  17554 #endif
  17555         } 
  17556     }
  17557 #endif
  17558 
  17559     if (recovered_ver >= BCM_WB_VERSION_1_5) {
  17560 #if defined(INCLUDE_BHH)
  17561         sal_memcpy(&bhh_lsp_egr_lookup_key, oam_scache, sizeof(uint8));
  17562         oam_scache += sizeof(uint8);
  17563 #endif /* INCLUDE_BHH */
  17564 #if defined(INCLUDE_MPLS_LM_DM)
  17565         /* Skip over not used currently */
  17566         oam_scache += sizeof(uint8);
  17567 #endif /* INCLUDE_MPLS_LM_DM */
  17568     } else {
  17569 #if defined(INCLUDE_BHH)
  17570         /* Warm booting from an older SDK release which had onl
  17571          *  MEP_ID based lookup
  17572          */
  17573         bhh_lsp_egr_lookup_key = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID;
  17574 #endif /* INCLUDE_BHH */
  17575     }
  17576 
  17577     if (recovered_ver >= BCM_WB_VERSION_1_6) {
  17578 #if defined(INCLUDE_BHH)
  17579         if(soc_feature(unit, soc_feature_bhh)) {
  17580             if(0 == oc->ukernel_not_ready  &&
  17581                     NULL != oam_scache) {
  17582                 uint8 vlan_pri;
  17583                 uint8 inner_vlan_pri;
  17584                 /* Store BHH endpoint VLAN_PRI and INNER_VLAN_PRI */
  17585 
  17586                 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  17587                     h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)];
  17588                     if(h_data_p->in_use) {
  17589                         sal_memcpy(&vlan_pri, oam_scache, sizeof(uint8));
  17590                         h_data_p->vlan_pri = vlan_pri;
  17591                         oam_scache += sizeof(uint8);
  17592                         sal_memcpy(&inner_vlan_pri, oam_scache, sizeof(uint8));
  17593                         h_data_p->inner_vlan_pri = inner_vlan_pri;
  17594                         oam_scache += sizeof(uint8);
  17595                     } else {
  17596                         oam_scache += sizeof(uint8) * 2;
  17597                     }
  17598                 }
  17599             }
  17600         }
  17601 #endif
  17602     }
  17603 
  17604     if (recovered_ver >= BCM_WB_VERSION_1_7) {
  17605         sal_memcpy(&oc->eth_oam_mp_group_vlan_key, oam_scache, sizeof(uint8));
  17606         oam_scache += sizeof(uint8);
  17607     } else {
  17608         oc->eth_oam_mp_group_vlan_key =
  17609                                 _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT;
  17610     }
  17611 
  17612     tmp_oam_scache = oam_scache;
  17613     if (recovered_ver >= BCM_WB_VERSION_1_8) {
  17614 #if defined(INCLUDE_BHH)
  17615         if(soc_feature(unit, soc_feature_bhh)) {
  17616             if (oc->ukernel_not_ready == 0) {
  17617                 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
  17618                     h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)];
  17619                     if (h_data_p->in_use) {
  17620                         sal_memcpy(&trunk_index, oam_scache, sizeof(uint8));
  17621                         oam_scache += sizeof(uint8);
  17622                         h_data_p->trunk_index = trunk_index;
  17623                     }
  17624                 }
  17625                 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17626             }
  17627         }
  17628 #endif /* INCLUDE_BHH */
  17629 #if defined(INCLUDE_MPLS_LM_DM)
  17630         if (oc->mpls_lm_dm_ukernel_ready) {
  17631             for (idx = 0; idx < oc->ep_count; idx++) {
  17632                 h_data_p = &oc->oam_hash_data[idx];
  17633                 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && (h_data_p->in_use)) {
  17634                     sal_memcpy(&trunk_index, oam_scache, sizeof(uint8));
  17635                     oam_scache += sizeof(uint8);
  17636                     h_data_p->trunk_index = trunk_index;
  17637                 }
  17638             }
  17639             trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17640         }
  17641 #endif /* INCLUDE_MPLS_LM_DM */
  17642 
  17643     }
  17644 
  17645     /* The above code doesnt move the scache pointer to the end of
  17646      * its allocated section size. So we move it here.
  17647      */
  17648     oam_scache = tmp_oam_scache + trunk_idx_size;
  17649 
  17650     if (recovered_ver >= BCM_WB_VERSION_1_9) {
  17651         for (idx = 0; idx < oc->ep_count; idx++) {
  17652             h_data_p = &oc->oam_hash_data[idx];
  17653             if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) {
  17654                 sal_memcpy(&(h_data_p->flags), oam_scache, sizeof(uint32));
  17655                 rv = _bcm_sb2_oam_hash_tbl_insert_hash_data_entry(unit, h_data_p);
  17656                 if (BCM_FAILURE(rv)) {
  17657                     LOG_ERROR(BSL_LS_BCM_OAM,
  17658                             (BSL_META_U(unit,
  17659                                         "OAM(unit %d) Error: Endpoint %d hash tbl insert failed  - %s.\n"),
  17660                              unit, h_data_p->ep_id, bcm_errmsg(rv)));
  17661                     goto cleanup;
  17662                 }
  17663             }
  17664             oam_scache += sizeof(uint32);
  17665         }
  17666     }
  17667 
  17668 #if defined(INCLUDE_BHH)
  17669     if (recovered_ver >= BCM_WB_VERSION_1_10) {
  17670         sal_memcpy(&sb2_oam_mpls_tp_ach_channel_type, oam_scache,
  17671                    sizeof(sb2_oam_mpls_tp_ach_channel_type));
  17672         oam_scache += sizeof(sb2_oam_mpls_tp_ach_channel_type);
  17673     }
  17674 #endif /* INCLUDE_BHH */
  17675 
  17676     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
  17677         /* In BCM_WB_VERSION_1_1 onwards we allocate memory for storing EP indexes
  17678            also, as such while upgrading from any version lower than 
  17679            BCM_WB_VERSION_1_1 we must add the differential.
  17680          */
  17681         if (recovered_ver < BCM_WB_VERSION_1_1) {
  17682             realloc_size += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE);
  17683             realloc_size += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE);
  17684         }
  17685         /* In BCM_WB_VERSION_1_2 onwards addition memory is used to store
  17686            egress_label, as such adding the differential */
  17687         if (recovered_ver < BCM_WB_VERSION_1_2) {
  17688             realloc_size += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE);
  17689         }
  17690         /* BCM_WB_VERSION_1_4 onwards SDK recovers PM profile info */
  17691         if (recovered_ver < BCM_WB_VERSION_1_4) {
  17692 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH)
  17693             if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17694                     (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  17695                     (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  17696                 realloc_size += (_BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE);
  17697                 realloc_size += (_bcm_sb2_oam_pmid_scache_size(unit));
  17698             }
  17699 #endif
  17700         }
  17701 
  17702         /* BCM_WB_VERSION_1_4 onwards SDK recovers the lookup key_type for
  17703          * LSP MEPs in EGR_MP_GROUP
  17704          */
  17705         if (recovered_ver < BCM_WB_VERSION_1_5) {
  17706 #if defined(INCLUDE_BHH)
  17707             realloc_size += sizeof(uint8);
  17708 #endif /* INCLUDE_BHH */
  17709 #if defined(INCLUDE_MPLS_LM_DM)
  17710             realloc_size += sizeof(uint8);
  17711 #endif /* INCLUDE_MPLS_LM_DM */
  17712         }
  17713 
  17714         if (recovered_ver < BCM_WB_VERSION_1_6) {
  17715 #if defined(INCLUDE_BHH)
  17716             if(soc_feature(unit, soc_feature_bhh)) {
  17717                 if(0 == oc->ukernel_not_ready) {
  17718                     realloc_size += sizeof(uint8) * oc->bhh_endpoint_count * 2;
  17719                 }
  17720             }
  17721 #endif
  17722         }
  17723 
  17724         if (recovered_ver < BCM_WB_VERSION_1_7) {
  17725             /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */
  17726             realloc_size += sizeof(uint8);
  17727         }
  17728 
  17729         if (recovered_ver < BCM_WB_VERSION_1_8) {
  17730             /* Store trunk index for BHH and MPLS LM/DM endpoints */
  17731             trunk_idx_size = 0;
  17732 #if defined(INCLUDE_BHH)
  17733             if(soc_feature(unit, soc_feature_bhh)) {
  17734                 if (oc->ukernel_not_ready == 0) {
  17735                     trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17736                 }
  17737             }
  17738 #endif /* INCLUDE_BHH */
  17739 #if defined(INCLUDE_MPLS_LM_DM)
  17740             if (oc->mpls_lm_dm_ukernel_ready) {
  17741                 if (trunk_idx_size == 0 ) {
  17742                     /* No BHH */
  17743                     trunk_idx_size = sizeof(uint8) * oc->ma_idx_count;
  17744                 }
  17745             }
  17746 #endif /* INCLUDE_MPLS_LM_DM */
  17747             realloc_size += trunk_idx_size;
  17748         }
  17749 
  17750         if (recovered_ver < BCM_WB_VERSION_1_9) {
  17751             realloc_size += (sizeof(uint32) * oc->ep_count);
  17752         }
  17753 
  17754         if (recovered_ver < BCM_WB_VERSION_1_10) {
  17755             /* Store the BHH ACH Channel Type */
  17756 #if defined(INCLUDE_BHH)
  17757             realloc_size += sizeof(sb2_oam_mpls_tp_ach_channel_type);
  17758 #endif /* INCLUDE_BHH */
  17759         }
  17760 
  17761         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 
  17762         rv = soc_scache_realloc(unit, scache_handle, realloc_size); 
  17763         if (SOC_FAILURE(rv)) {
  17764             LOG_ERROR(BSL_LS_BCM_OAM,
  17765                     (BSL_META_U(unit,"OAM Error: scache alloc failed  - %s.\n"),
  17766                      bcm_errmsg(rv)));
  17767             goto cleanup;
  17768         }
  17769     }
  17770     
  17771 cleanup:
  17772     _BCM_OAM_UNLOCK(oc);
  17773     return (rv);
  17774 }
  17775 
  17776 
  17777 #if defined(INCLUDE_BHH)
  17778 int bcmi_xgs5_bhh_version_exchange(int unit)
  17779 {
  17780     uint8 *buffer_reply, *buffer_req, *buffer_ptr;
  17781     uint16 buffer_len, reply_len;
  17782     bhh_sdk_version_exchange_msg_t sdk_msg,uc_msg;
  17783 	_bcm_oam_control_t   *oc;            /* Pointer to OAM control structure. */
  17784     int rv = BCM_E_NONE;
  17785 
  17786     _BCM_OAM_BHH_IS_VALID(unit);
  17787 
  17788     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17789 
  17790     /* Pack control message data into DMA */
  17791     sdk_msg.version = BHH_SDK_VERSION;
  17792 
  17793     buffer_req      = oc->dma_buffer;
  17794     buffer_ptr      = bhh_sdk_version_exchange_msg_pack(buffer_req, &sdk_msg);
  17795     buffer_len      = buffer_ptr - buffer_req;
  17796 
  17797     /* Send Message to exchange version value*/
  17798     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, MOS_MSG_SUBCLASS_BHH_VERSION_EXCHANGE,
  17799                                         buffer_len, 0,
  17800                                         MOS_MSG_SUBCLASS_BHH_VER_EXCHANGE_REPLY,
  17801                                         &reply_len);
  17802     if (rv == BCM_E_UNAVAIL) {
  17803         bhh_firmware_version = BHH_UC_MIN_VERSION;
  17804         return BCM_E_NONE;
  17805     } else if (rv < 0) {
  17806         return rv;
  17807     }
  17808 
  17809     sal_memset(&uc_msg, 0, sizeof(uc_msg));
  17810     buffer_reply = oc->dma_buffer;
  17811     buffer_ptr   = bhh_sdk_version_exchange_msg_unpack(buffer_reply, &uc_msg);
  17812     buffer_len   = buffer_ptr - buffer_reply;
  17813 
  17814     if (reply_len != buffer_len) {
  17815         return BCM_E_INTERNAL;
  17816     }
  17817 
  17818     bhh_firmware_version = uc_msg.version;
  17819     return BCM_E_NONE;
  17820 }
  17821 
  17822 /*
  17823  * Function:
  17824  *     _bcm_sb2_oam_bhh_cos_map_recover
  17825  * Purpose:
  17826  *     Recover cos mappings done for BHH
  17827  * Parameters:
  17828  *     unit - (IN) BCM device number
  17829  * Retruns:
  17830  *     BCM_E_XXX
  17831  */
  17832 STATIC int
  17833 _bcm_sb2_oam_bhh_cos_map_recover(int unit)
  17834 {
  17835     int                    rv = BCM_E_NONE;
  17836     _bcm_oam_control_t     *oc;
  17837     int                    index;
  17838     int                    cosq_map_size;
  17839     bcm_rx_reasons_t       reasons, reasons_mask;
  17840     bcm_rx_reasons_t       ach_error_reasons, invalid_error_reasons;
  17841     bcm_rx_reasons_t       bhh_lb_reasons;
  17842     uint8                  int_prio, int_prio_mask;
  17843     uint32                 packet_type, packet_type_mask;
  17844     bcm_cos_queue_t        cosq;
  17845 
  17846     /* Get OAM Control Structure. */
  17847     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17848     _BCM_OAM_LOCK(oc);
  17849 
  17850     if (oc->ukernel_not_ready) {
  17851         _BCM_OAM_UNLOCK(oc);
  17852         return BCM_E_NONE;
  17853     }
  17854 
  17855     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  17856     if(BCM_FAILURE(rv)) {
  17857         LOG_ERROR(BSL_LS_BCM_OAM,
  17858                   (BSL_META_U(unit,
  17859                               "BHH Error:hw init. cosq maps size %s.\n"),
  17860                    bcm_errmsg(rv)));
  17861         _BCM_OAM_UNLOCK(oc);
  17862         return (rv);
  17863     }
  17864 
  17865     BCM_RX_REASON_CLEAR_ALL(ach_error_reasons);
  17866     BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonBHHOAM);
  17867     BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonOAMCCMSlowpath);
  17868 
  17869     BCM_RX_REASON_CLEAR_ALL(invalid_error_reasons);
  17870     BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonBHHOAM);
  17871     BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonOAMLMDM);
  17872 
  17873     BCM_RX_REASON_CLEAR_ALL(bhh_lb_reasons);
  17874     BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonBHHOAM);
  17875     BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonOAMSlowpath);
  17876 
  17877     oc->cpu_cosq_ach_error_index       = -1;
  17878     oc->cpu_cosq_invalid_error_index   = -1;
  17879     oc->bhh_lb_index                   = -1;
  17880     for (index = 0; index < cosq_map_size; index++) {
  17881         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  17882                                          &reasons, &reasons_mask,
  17883                                          &int_prio, &int_prio_mask,
  17884                                          &packet_type, &packet_type_mask,
  17885                                          &cosq);
  17886         if (rv == BCM_E_NONE) {
  17887 
  17888             if (BCM_RX_REASON_EQ(reasons, ach_error_reasons) &&
  17889                 BCM_RX_REASON_EQ(reasons_mask, ach_error_reasons)) {
  17890                 oc->cpu_cosq_ach_error_index = index;
  17891                 oc->cpu_cosq = cosq;
  17892             } else if (BCM_RX_REASON_EQ(reasons, invalid_error_reasons) &&
  17893                        BCM_RX_REASON_EQ(reasons_mask, invalid_error_reasons)) {
  17894                 oc->cpu_cosq_invalid_error_index = index;
  17895             } else if (BCM_RX_REASON_EQ(reasons, bhh_lb_reasons) &&
  17896                        BCM_RX_REASON_EQ(reasons_mask, bhh_lb_reasons)) {
  17897                 oc->bhh_lb_index = index;
  17898             }
  17899 
  17900             if( -1 != oc->cpu_cosq_ach_error_index         &&
  17901                 -1 != oc->cpu_cosq_invalid_error_index     &&
  17902                 -1 != oc->bhh_lb_index) {
  17903                 break;
  17904             }
  17905         }
  17906     }
  17907 
  17908     if (index >= cosq_map_size) {
  17909         LOG_ERROR(BSL_LS_BCM_OAM,
  17910                   (BSL_META_U(unit,
  17911                             "BHH Error: Could not recover cos map entry \n")));
  17912     }
  17913 
  17914     _BCM_OAM_UNLOCK(oc);
  17915     return rv;
  17916 }
  17917 #endif /* INCLUDE_BHH */
  17918 
  17919 #if defined(INCLUDE_ETH_LM_DM)
  17920 /*
  17921  * Function:
  17922  *      _bcm_sb2_oam_eth_lm_dm_cos_map_recover
  17923  * Purpose:
  17924  *      Recover cos mapping done for ETH_LM_DM packet processing.
  17925  * Parameters:
  17926  *      unit - (IN) Unit number.
  17927  * Returns:
  17928  *      BCM_E_XXX
  17929  * Notes:
  17930  */
  17931 STATIC int
  17932 _bcm_sb2_oam_eth_lm_dm_cos_map_recover(int unit)
  17933 {
  17934     int                    rv = BCM_E_NONE;
  17935     _bcm_oam_control_t     *oc;
  17936     int                    index;
  17937     int                    cosq_map_size;
  17938     bcm_rx_reasons_t       reasons, reasons_mask;
  17939     bcm_rx_reasons_t       eth_lm_dm_reasons;
  17940     uint8                  int_prio, int_prio_mask;
  17941     uint32                 packet_type, packet_type_mask;
  17942     bcm_cos_queue_t        cosq;
  17943 
  17944     /* Get OAM Control Structure. */
  17945     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  17946     _BCM_OAM_LOCK(oc);
  17947 
  17948     if (oc->eth_lm_dm_ukernel_not_ready) {
  17949         _BCM_OAM_UNLOCK(oc);
  17950         return BCM_E_NONE;
  17951     }
  17952 
  17953     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  17954     if(BCM_FAILURE(rv)) {
  17955         LOG_ERROR(BSL_LS_BCM_OAM,
  17956                   (BSL_META_U(unit,
  17957                               "ETH LM/DM Error:hw init. cosq maps size %s.\n"),
  17958                    bcm_errmsg(rv)));
  17959         _BCM_OAM_UNLOCK(oc);
  17960         return (rv);
  17961     }
  17962 
  17963     BCM_RX_REASON_CLEAR_ALL(eth_lm_dm_reasons);
  17964     BCM_RX_REASON_SET(eth_lm_dm_reasons, bcmRxReasonOAMLMDM);
  17965 
  17966     oc->eth_lm_dm_cosq_index           = -1;
  17967     for (index = 0; index < cosq_map_size; index++) {
  17968         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  17969                                          &reasons, &reasons_mask,
  17970                                          &int_prio, &int_prio_mask,
  17971                                          &packet_type, &packet_type_mask,
  17972                                          &cosq);
  17973         if (rv == BCM_E_NONE) {
  17974 
  17975             if (BCM_RX_REASON_EQ(reasons, eth_lm_dm_reasons) &&
  17976                 BCM_RX_REASON_EQ(reasons_mask, eth_lm_dm_reasons)) {
  17977                 oc->eth_lm_dm_cosq_index = index;
  17978                 oc->eth_lm_dm_cpu_cosq = cosq;
  17979             }
  17980         }
  17981         if( -1 != oc->eth_lm_dm_cosq_index) {
  17982             break;
  17983         }
  17984     }
  17985 
  17986     if (index >= cosq_map_size) {
  17987         LOG_VERBOSE(BSL_LS_BCM_OAM,
  17988                   (BSL_META_U(unit,
  17989                     "ETH LM/DM Error: Could not recover cos map entry \n")));
  17990     }
  17991 
  17992     _BCM_OAM_UNLOCK(oc);
  17993     return rv;
  17994 }
  17995 #endif /* INCLUDE_ETH_LM_DM */
  17996 
  17997 #if defined(INCLUDE_MPLS_LM_DM)
  17998 /*
  17999  * Function:
  18000  *      _bcm_sb2_oam_mpls_lm_dm_cos_map_recover
  18001  * Purpose:
  18002  *      Recover the cos mapping config done for MPLS_LM_DM packet processing.
  18003  * Parameters:
  18004  *      unit - (IN) Unit number.
  18005  * Returns:
  18006  *      BCM_E_XXX
  18007  * Notes:
  18008  */
  18009 STATIC int
  18010 _bcm_sb2_oam_mpls_lm_dm_cos_map_recover(int unit)
  18011 {
  18012     int                    rv = BCM_E_NONE;
  18013     _bcm_oam_control_t     *oc;
  18014     int                    index;
  18015     int                    cosq_map_size;
  18016     bcm_rx_reasons_t       reasons, reasons_mask;
  18017     bcm_rx_reasons_t       mpls_lm_dm_reasons;
  18018     uint8                  int_prio, int_prio_mask;
  18019     uint32                 packet_type, packet_type_mask;
  18020     bcm_cos_queue_t        cosq;
  18021 
  18022     /* Get OAM Control Structure. */
  18023     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  18024     _BCM_OAM_LOCK(oc);
  18025 
  18026     if (!oc->mpls_lm_dm_ukernel_ready) {
  18027         _BCM_OAM_UNLOCK(oc);
  18028         return BCM_E_NONE;
  18029     }
  18030 
  18031     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  18032     if(BCM_FAILURE(rv)) {
  18033         LOG_ERROR(BSL_LS_BCM_OAM,
  18034                   (BSL_META_U(unit,
  18035                               "MPLS LM/DM Error:hw init. cosq maps size %s.\n"),
  18036                    bcm_errmsg(rv)));
  18037         _BCM_OAM_UNLOCK(oc);
  18038         return (rv);
  18039     }
  18040 
  18041     BCM_RX_REASON_CLEAR_ALL(mpls_lm_dm_reasons);
  18042     BCM_RX_REASON_SET(mpls_lm_dm_reasons, bcmRxReasonOAMMplsLmDm);
  18043 
  18044     oc->mpls_lm_dm_cosq_index           = -1;
  18045     for (index = 0; index < cosq_map_size; index++) {
  18046         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  18047                                          &reasons, &reasons_mask,
  18048                                          &int_prio, &int_prio_mask,
  18049                                          &packet_type, &packet_type_mask,
  18050                                          &cosq);
  18051         if (rv == BCM_E_NONE) {
  18052 
  18053             if (BCM_RX_REASON_EQ(reasons, mpls_lm_dm_reasons) &&
  18054                 BCM_RX_REASON_EQ(reasons_mask, mpls_lm_dm_reasons)) {
  18055                 oc->mpls_lm_dm_cosq_index = index;
  18056                 oc->mpls_lm_dm_cpu_cosq = cosq;
  18057             }
  18058         }
  18059         if( -1 != oc->mpls_lm_dm_cosq_index) {
  18060             break;
  18061         }
  18062     }
  18063 
  18064     if (index >= cosq_map_size) {
  18065         LOG_VERBOSE(BSL_LS_BCM_OAM,
  18066                   (BSL_META_U(unit,
  18067                     "MPLS LM/DM Error: Could not recover cos map entry \n")));
  18068     }
  18069 
  18070     _BCM_OAM_UNLOCK(oc);
  18071     return rv;
  18072 }
  18073 #endif /* INCLUDE_MPLS_LM_DM */
  18074 
  18075 #endif /* BCM_WARM_BOOT_SUPPORT */
  18076 
  18077 STATIC int
  18078 _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(int unit,
  18079                        _bcm_oam_hash_data_t *h_data_p,
  18080                               int *num_ma_idx_entries,
  18081                        shr_idxres_list_handle_t *pool)
  18082 {
  18083     _bcm_oam_control_t *oc = NULL; 
  18084 
  18085     /* Get OAM control structure handle. */
  18086     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  18087 
  18088     if ((h_data_p == NULL) || (h_data_p->in_use == 0)) {
  18089         return BCM_E_PARAM;
  18090     }
  18091 
  18092     switch (oc->ma_idx_alloc_scheme) {
  18093         case _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL:
  18094             *num_ma_idx_entries = 8;
  18095             *pool = oc->ma_idx_pool;
  18096             return BCM_E_NONE;
  18097             break;
  18098         case _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL:
  18099             if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  18100                 *num_ma_idx_entries = 8;
  18101                 *pool = oc->ma_idx_pool;
  18102             } else if (BHH_EP_TYPE(h_data_p) ||
  18103                     (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) {
  18104                 *num_ma_idx_entries = 1;
  18105                 *pool = oc->mpls_oam_ma_idx_pool;
  18106             }
  18107             return BCM_E_NONE;
  18108             break;
  18109         default:
  18110             /* Should not hit */
  18111             break;
  18112     }
  18113     return BCM_E_INTERNAL; 
  18114 }
  18115 
  18116 STATIC int
  18117 _bcm_sb2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc)
  18118 {
  18119     int rv = BCM_E_NONE;
  18120 
  18121     if (MA_INDEX_ALLOC_SCHEME_COMBINED_POOL) {
  18122         rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, 
  18123                 oc->ma_idx_count - 1,
  18124                 0, oc->ma_idx_count -1, "ma_idx pool");
  18125         if (BCM_FAILURE(rv)) {
  18126             return (rv);
  18127 
  18128         }
  18129     } else if (MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) {
  18130         if (_BCM_ETH_OAM_NUM_SESSIONS != 0) {
  18131             rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, _BCM_ETH_OAM_NUM_SESSIONS-1,
  18132                     0, _BCM_ETH_OAM_NUM_SESSIONS-1, "ma_idx pool");
  18133             if (BCM_FAILURE(rv)) {
  18134                 return (rv);
  18135 
  18136             }
  18137         }
  18138 
  18139         if (_BCM_MPLS_OAM_NUM_SESSIONS != 0) {
  18140             rv = shr_idxres_list_create(&oc->mpls_oam_ma_idx_pool, 
  18141                     _BCM_ETH_OAM_NUM_SESSIONS, 
  18142                     _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1,
  18143                     _BCM_ETH_OAM_NUM_SESSIONS, 
  18144                     _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1,
  18145                     "mpls oam ma_idx pool");
  18146             if (BCM_FAILURE(rv)) {
  18147                 return (rv);
  18148 
  18149             }
  18150         }
  18151     } else {
  18152         return (BCM_E_INTERNAL);
  18153 
  18154     }
  18155     return rv;
  18156 }
  18157 
  18158 STATIC int
  18159 _bcm_sb2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc)
  18160 {
  18161     if (NULL != oc->ma_idx_pool) {
  18162         shr_idxres_list_destroy(oc->ma_idx_pool);
  18163         oc->ma_idx_pool = NULL;
  18164     }
  18165     if (NULL != oc->mpls_oam_ma_idx_pool) {
  18166         shr_idxres_list_destroy(oc->mpls_oam_ma_idx_pool);
  18167         oc->mpls_oam_ma_idx_pool = NULL;
  18168     }
  18169     return BCM_E_NONE;
  18170 }
  18171 
  18172 
  18173 /* * * * * * * * * * * * * * * * * * * *
  18174  *            OAM BCM APIs             *
  18175  */
  18176 /*
  18177  * Function: bcm_sb2_oam_init
  18178  *
  18179  * Purpose:
  18180  *     Initialize OAM module.
  18181  * Parameters:
  18182  *     unit - (IN) BCM device number
  18183  * Returns:
  18184  *     BCM_E_UNIT    - Invalid BCM unit number.
  18185  *     BCM_E_UNAVAIL - OAM not support on this device.
  18186  *     BCM_E_MEMORY  - Allocation failure
  18187  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
  18188  *     BCM_E_NONE    - Success
  18189  */
  18190 int
  18191 bcm_sb2_oam_init(int unit)
  18192 {
  18193     _bcm_oam_control_t *oc = NULL;  /* OAM control structure.     */
  18194     int             rv;             /* Operation return value.    */
  18195     uint32          size;           /* Size of memory allocation. */
  18196     bcm_port_t      port;           /* Port number.               */
  18197     int             index = 0;
  18198     bcm_oam_endpoint_t   ep_index;  /* Endpoint index.               */
  18199     bcm_pbmp_t      all_pbmp;
  18200 #if defined(INCLUDE_BHH) ||  defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  18201     uint8 *buffer, *buffer_ptr;
  18202     uint16 buffer_len, reply_len;
  18203     int             uc_status;      /* uController Status */
  18204 #endif
  18205 #if defined(INCLUDE_BHH)
  18206     int uc;
  18207 #endif
  18208 
  18209 #if defined(INCLUDE_BHH)
  18210     uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  18211     char *carrier_code_str;
  18212     uint32 node_id = 0;
  18213     bhh_sdk_msg_ctrl_init_t msg_init;
  18214     int priority;
  18215     int ukernel_not_ready = 0;
  18216     uint8 bhh_consolidate_final_event = 0;
  18217 #endif
  18218 
  18219 #if defined(INCLUDE_ETH_LM_DM)
  18220     eth_lm_dm_sdk_msg_ctrl_init_t eth_msg_init;
  18221     uint8 eth_lm_dm_ukernel_not_ready = 1;
  18222     uint8 eth_lm_dm_default_cosq;
  18223 #endif
  18224 
  18225 #if defined(INCLUDE_MPLS_LM_DM)
  18226 #if defined(BCM_METROLITE_SUPPORT)
  18227 int mpls_lmdm_uc;
  18228 #endif
  18229     mpls_lm_dm_sdk_msg_ctrl_init_t mpls_lm_dm_msg_init;
  18230 #endif
  18231 
  18232     /* Ensure that the unit has OAM support. */
  18233     if (!soc_feature(unit, soc_feature_oam)) {
  18234         LOG_ERROR(BSL_LS_BCM_OAM,
  18235                   (BSL_META_U(unit,
  18236                               "OAM(unit %d) Error: OAM not supported \n"),
  18237                    unit));
  18238         return (BCM_E_UNAVAIL);
  18239     }
  18240 
  18241     /* Detach first if the module has been previously initialized. */
  18242     if (NULL != _sb2_oam_control[unit]) {
  18243         _sb2_oam_control[unit]->init = FALSE;
  18244         rv = bcm_sb2_oam_detach(unit);
  18245         if (BCM_FAILURE(rv)) {
  18246             LOG_ERROR(BSL_LS_BCM_OAM,
  18247                       (BSL_META_U(unit,
  18248                                   "OAM(unit %d) Error: Module deinit - %s.\n"),
  18249                        unit, bcm_errmsg(rv)));
  18250             return (rv);
  18251         }
  18252     }
  18253 
  18254     /* Allocate OAM control memeory for this unit. */
  18255     _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t),
  18256                "OAM control");
  18257     if (NULL == oc) {
  18258         return (BCM_E_MEMORY);
  18259     }
  18260 
  18261     if (soc_feature(unit, soc_feature_bhh)) {
  18262 #ifdef INCLUDE_BHH
  18263         /*
  18264          * Initialize uController side
  18265          */
  18266 
  18267         /*
  18268          * Start BHH application in BTE (Broadcom Task Engine) uController,
  18269          * if not already running (warm boot).
  18270          * Determine which uController is running BHH  by choosing the first
  18271          * uC that returns successfully.
  18272          */
  18273         for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
  18274             rv = soc_uc_status(unit, uc, &uc_status);
  18275             if ((rv == SOC_E_NONE) && (uc_status != 0)) {
  18276                 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH,
  18277                                            _BHH_UC_MSG_TIMEOUT_USECS,
  18278                                            BHH_SDK_VERSION,
  18279                                            BHH_UC_MIN_VERSION,
  18280                                            _bcm_oam_bhh_appl_callback, NULL);
  18281                 if (SOC_E_NONE == rv) {
  18282                     /* BHH started successfully */
  18283                     oc->uc_num = uc;
  18284                     break;
  18285                 }
  18286             }
  18287         }
  18288 
  18289         if (uc >= SOC_INFO(unit).num_ucs) {  /* Could not find or start BHH appl */
  18290             ukernel_not_ready = 1;
  18291             LOG_ERROR(BSL_LS_BCM_OAM,
  18292                       (BSL_META_U(unit,
  18293                                   "uKernel Not Ready, bhh not started\n")));
  18294         }
  18295 #endif
  18296     }
  18297 
  18298  if (soc_feature(unit, soc_feature_eth_lm_dm)) {
  18299 #ifdef INCLUDE_ETH_LM_DM
  18300      /*
  18301       * Initialize uController side
  18302       */
  18303 
  18304      /*
  18305       * Start ETH LM/DM application in BTE (Broadcom Task Engine) uController,
  18306       * if not already running (warm boot).
  18307       */
  18308      if (SOC_IS_METROLITE(unit)) {
  18309          oc->eth_lm_dm_uc_num = ML_ETH_LM_DM_UC_NUM;
  18310      } else {
  18311          oc->eth_lm_dm_uc_num = SB2_ETH_LM_DM_UC_NUM;
  18312      }
  18313 
  18314      rv = soc_uc_status(unit, oc->eth_lm_dm_uc_num, &uc_status);
  18315      if ((rv == SOC_E_NONE) && (uc_status != 0)) {
  18316          rv = soc_cmic_uc_appl_init(unit, oc->eth_lm_dm_uc_num,
  18317                                     MOS_MSG_CLASS_ETH_LM_DM,
  18318                                     _ETH_LM_DM_UC_MSG_TIMEOUT_USECS,
  18319                                     ETH_LM_DM_SDK_VERSION,
  18320                                     ETH_LM_DM_UC_MIN_VERSION, 
  18321                                     _bcm_oam_eth_lm_dm_appl_callback, NULL);
  18322 
  18323          if (SOC_E_NONE == rv) {
  18324              /* ETH_LM_DM started successfully */
  18325              eth_lm_dm_ukernel_not_ready = 0;
  18326          } else {
  18327              LOG_ERROR(BSL_LS_BCM_OAM,
  18328                        (BSL_META_U(unit,
  18329                                   "uKernel Not Ready, ETH_LM_DM not started\n")));
  18330          }
  18331      }
  18332      oc->eth_lm_dm_ukernel_not_ready = eth_lm_dm_ukernel_not_ready;
  18333      
  18334 #endif
  18335  }
  18336 
  18337     /* Get number of endpoints and groups supported by this unit. */
  18338     rv = _bcm_sb2_oam_group_endpoint_count_init(unit, oc);
  18339     if (BCM_FAILURE(rv)) {
  18340         _bcm_sb2_oam_control_free(unit, oc);
  18341         return (rv);
  18342     }
  18343     oc->unit = unit;
  18344     if (soc_feature(unit, soc_feature_bhh)) {
  18345 #if defined(INCLUDE_BHH)
  18346 
  18347     oc->ukernel_not_ready = ukernel_not_ready;
  18348     /* Get SOC properties for BHH */
  18349     oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128);
  18350     oc->bhh_max_encap_length =
  18351                             soc_property_get(unit,
  18352                                              spn_BHH_ENCAP_MAX_LENGTH,
  18353                                              _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH);
  18354 
  18355     if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) {
  18356         LOG_ERROR(BSL_LS_BCM_OAM,
  18357                   (BSL_META_U(unit,
  18358                               "Invalid max encap_length=%u\n"),
  18359                               oc->bhh_max_encap_length));
  18360         return BCM_E_CONFIG;
  18361     }
  18362 
  18363     carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE);
  18364     if (carrier_code_str != NULL) {
  18365         /*
  18366          * Note that the carrier code is specified in colon separated
  18367          * MAC address format.
  18368          */
  18369         if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) {
  18370             _bcm_sb2_oam_control_free(unit, oc);
  18371             return (BCM_E_INTERNAL);
  18372         }
  18373     }
  18374 
  18375     node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0);
  18376     bhh_consolidate_final_event = soc_property_get(unit,
  18377                                            spn_BHH_CONSOLIDATED_FINAL_EVENT, 0);
  18378 
  18379     if(oc->ep_count > _BCM_OAM_SABER2_ENDPOINT_MAX) {
  18380         LOG_ERROR(BSL_LS_BCM_OAM,
  18381                   (BSL_META_U(unit,
  18382                               "OAM(unit %d) Error: OAM EP count %d not supported \n"),
  18383                    unit, oc->ep_count));
  18384         _bcm_sb2_oam_control_free(unit, oc);
  18385         return (BCM_E_PARAM);
  18386     }
  18387 #endif /* INCLUDE_BHH */
  18388     }
  18389 
  18390 #if defined(INCLUDE_MPLS_LM_DM)
  18391     oc->mpls_lm_dm_ukernel_ready = 0;
  18392 
  18393 #if defined(BCM_METROLITE_SUPPORT)
  18394     if (SOC_IS_METROLITE(unit)) {
  18395         for (mpls_lmdm_uc = 0; mpls_lmdm_uc < SOC_INFO(unit).num_ucs; mpls_lmdm_uc++) {
  18396              rv = soc_uc_status(unit, mpls_lmdm_uc, &uc_status);
  18397              if ((rv == SOC_E_NONE) && (uc_status != 0)) {
  18398                 rv = soc_cmic_uc_appl_init(unit, mpls_lmdm_uc, MOS_MSG_CLASS_MPLS_LM_DM,
  18399                                            _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS,
  18400                                            MPLS_LM_DM_SDK_VERSION,
  18401                                            MPLS_LM_DM_UC_MIN_VERSION, 
  18402                                            _bcm_oam_mpls_lm_dm_appl_callback, NULL);
  18403                 if (SOC_E_NONE == rv) {
  18404                     /* MPLS_LM_DM started successfully */
  18405                     oc->mpls_lm_dm_uc_num = mpls_lmdm_uc;
  18406                     break;
  18407                 }
  18408             }
  18409         }
  18410         if (mpls_lmdm_uc >= SOC_INFO(unit).num_ucs) {
  18411             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  18412                             "uKernel Not Ready, MPLS_LM_DM not started\n")));
  18413         } else {
  18414             oc->mpls_lm_dm_ukernel_ready = 1;
  18415         }
  18416     } else
  18417 #endif
  18418     {
  18419         
  18420         /* Core #2 is used for MPLS_LMDM in Saber2*/
  18421         if (soc_uc_in_reset(unit, MPLS_LM_DM_UC_NUM)) {
  18422 
  18423             LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM Warn:"
  18424                       " uKernel Not Ready, MPLS_LM_DM not started.\n If MPLS_LM_DM"
  18425                       " app is not not needed, compile SDK by excluding MPLS_LM_DM"
  18426                     " from FEATURE_LIST.\n")));
  18427         } else {
  18428 
  18429             /* Initialize uController side
  18430              * Start MPLS_LM_DM application in BTE (Broadcom Task Engine) uController.
  18431             * MPLS_LM_DM_UC_NUM runs the MPLS_LM_DM Application.
  18432             */
  18433             rv = soc_cmic_uc_appl_init(unit, MPLS_LM_DM_UC_NUM, MOS_MSG_CLASS_MPLS_LM_DM,
  18434                     _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS, MPLS_LM_DM_SDK_VERSION,
  18435                     MPLS_LM_DM_UC_MIN_VERSION, 
  18436                     _bcm_oam_mpls_lm_dm_appl_callback, NULL);
  18437             
  18438             if (SOC_E_NONE == rv) {
  18439                 oc->mpls_lm_dm_uc_num = MPLS_LM_DM_UC_NUM;
  18440                 oc->mpls_lm_dm_ukernel_ready = 1;
  18441             }
  18442         }
  18443     }
  18444     if (SOC_E_NONE == rv) {
  18445 
  18446         /* MPLS_LM_DM started successfully */
  18447         oc->mpls_lm_dm_sess_count = MPLS_LM_DM_MAX_SESSIONS;
  18448 
  18449         size = sizeof(uint32) * oc->mpls_lm_dm_sess_count;
  18450         _BCM_OAM_ALLOC(oc->mpls_lm_dm_sess_id_ep_id, uint32, size,
  18451                        "MPLS LM DM SESSION TO EP ID MAP");
  18452 
  18453         /* Create MPLS_LM_DM session pool */
  18454         rv = shr_idxres_list_create(&oc->mpls_lm_dm_pool, 1,
  18455                 oc->mpls_lm_dm_sess_count, 1, oc->mpls_lm_dm_sess_count,
  18456                 "mpls_lm_dm pool");
  18457 
  18458         if (BCM_FAILURE(rv)) {
  18459             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d) Error:"
  18460                 " Creating Session Id pool failed \n"), unit));
  18461             _bcm_sb2_oam_control_free(unit, oc);
  18462             return (rv);
  18463         }
  18464     } else {
  18465         /* Could not start MPLS_LM_DM appl */
  18466         LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  18467             "OAM(unit %d) WARN: MPLS LM DM init failed\n"), unit));
  18468     }
  18469 #endif
  18470     _BCM_MPLS_OAM_NUM_SESSIONS = soc_property_get(unit, spn_MPLS_OAM_NUM_SESSIONS, 
  18471               _BCM_MPLS_OAM_NUM_SESSIONS_INVALID);
  18472 
  18473     if(_BCM_MPLS_OAM_NUM_SESSIONS ==
  18474             _BCM_MPLS_OAM_NUM_SESSIONS_INVALID) {
  18475         /* Entry does not exist. Revert to old scheme */
  18476         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL; 
  18477     } else if (_BCM_MPLS_OAM_NUM_SESSIONS > soc_mem_index_max(unit, MA_INDEXm)){
  18478         /* If it is greater than max index of MA_INDEX table,
  18479          * set it to max_index value and set it to newer index alloc scheme.
  18480          */
  18481         _BCM_MPLS_OAM_NUM_SESSIONS = soc_mem_index_max(unit, MA_INDEXm);
  18482         _BCM_ETH_OAM_NUM_SESSIONS  = 0;
  18483         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 
  18484     } else {
  18485         _BCM_ETH_OAM_NUM_SESSIONS = 
  18486         soc_mem_index_count(unit, MA_INDEXm) - _BCM_MPLS_OAM_NUM_SESSIONS;
  18487         oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 
  18488     }
  18489 
  18490     /* Mem_1: Allocate hash data memory */
  18491     /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */
  18492     size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_SABER2_ENDPOINT_MAX;
  18493 
  18494     _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data");
  18495     if (NULL == oc->oam_hash_data) {
  18496         _bcm_sb2_oam_control_free(unit, oc);
  18497         return (BCM_E_MEMORY);
  18498     }
  18499 
  18500     /* Mem_2: Allocate group memory */
  18501     size = sizeof(_bcm_oam_group_data_t) * oc->group_count;
  18502 
  18503     _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info");
  18504 
  18505     if (NULL == oc->group_info) {
  18506         _bcm_sb2_oam_control_free(unit, oc);
  18507         return (BCM_E_MEMORY);
  18508     }
  18509 
  18510     /* Allocate RMEP H/w to logical index mapping memory */
  18511     size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count;
  18512 
  18513     _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping");
  18514     if (NULL == oc->remote_endpoints) {
  18515         _bcm_sb2_oam_control_free(unit, oc);
  18516         return (BCM_E_MEMORY);
  18517     }
  18518     /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 
  18519     for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) {
  18520         oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID;
  18521     }
  18522 
  18523     /* Mem_3: Create application endpoint list. */
  18524     rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->ep_count - 1,
  18525                                 0, oc->ep_count -1, "endpoint pool");
  18526     if (BCM_FAILURE(rv)) {
  18527         _bcm_sb2_oam_control_free(unit, oc);
  18528         return (rv);
  18529     }
  18530 
  18531     /* Mem_4: Create local MEP endpoint list. */
  18532     rv = shr_idxres_list_create(&oc->lmep_pool, 0, oc->lmep_count - 1,
  18533                                 0, oc->lmep_count -1, "lmep pool");
  18534     if (BCM_FAILURE(rv)) {
  18535         _bcm_sb2_oam_control_free(unit, oc);
  18536         return (rv);
  18537     }
  18538 
  18539     /* Mem_5: Create Remote MEP endpoint list. */
  18540     rv = shr_idxres_list_create(&oc->rmep_pool, 0, oc->rmep_count - 1,
  18541                                 0, oc->rmep_count -1, "rmep pool");
  18542     if (BCM_FAILURE(rv)) {
  18543         _bcm_sb2_oam_control_free(unit, oc);
  18544         return (rv);
  18545     }
  18546 
  18547     /* Mem_6: Create MEP Rx state tracker table index endpoint list - DnMEP */
  18548 
  18549     rv =_bcm_sb2_oam_ma_idx_pool_create(oc);
  18550     if (BCM_FAILURE(rv)) {
  18551         _bcm_sb2_oam_control_free(unit, oc);
  18552         return (rv);
  18553     }
  18554 
  18555     /* Mem_7: Create MEP Rx state tracker table index endpoint list -UpMEP */
  18556     rv = shr_idxres_list_create(&oc->egr_ma_idx_pool, 0, 
  18557                                 oc->egr_ma_idx_count - 1,
  18558                                 0, oc->egr_ma_idx_count -1, "egr_ma_idx pool");
  18559     if (BCM_FAILURE(rv)) {
  18560         _bcm_sb2_oam_control_free(unit, oc);
  18561         return (rv);
  18562 
  18563     }
  18564 
  18565     /* Initialize to domain specific key by default, WB recovery might
  18566      * overwrite it, depending on older SDK.
  18567      */
  18568     oc->eth_oam_mp_group_vlan_key = _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC;
  18569 
  18570     if(soc_feature(unit, soc_feature_bhh)) {
  18571 #if defined(INCLUDE_BHH)
  18572     /* Create BHH endpoint list. */
  18573     rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1,
  18574                                 0, oc->bhh_endpoint_count - 1, "bhh pool");
  18575     if (BCM_FAILURE(rv)) {
  18576         LOG_ERROR(BSL_LS_BCM_OAM,
  18577                   (BSL_META_U(unit,
  18578                               "OAM(unit %d) Error: Creating BHH pool failed \n"),
  18579                    unit));
  18580         _bcm_sb2_oam_control_free(unit, oc);
  18581         return (rv);
  18582     }
  18583 
  18584     /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */
  18585     rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc),
  18586                 _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) + oc->bhh_endpoint_count - 1);
  18587 
  18588     if (BCM_FAILURE(rv)) {
  18589         LOG_ERROR(BSL_LS_BCM_OAM,
  18590                   (BSL_META_U(unit,
  18591                               "OAM(unit %d) Error: Reserving BHH endpoints from mep_pool "
  18592                               "failed rv %d\n"), unit, rv));
  18593         _bcm_sb2_oam_control_free(unit, oc);
  18594         return (rv);
  18595     }
  18596 
  18597 #endif /* INCLUDE_BHH */
  18598     }
  18599 
  18600     /* Mem_4: Create group list. */
  18601     rv = shr_idxres_list_create(&oc->group_pool, 0, oc->group_count - 1,
  18602                                 0, oc->group_count - 1, "group pool");
  18603     if (BCM_FAILURE(rv)) {
  18604         _bcm_sb2_oam_control_free(unit, oc);
  18605         return (rv);
  18606     }
  18607 
  18608     /* Index management for Ingress LM counter pool 1 */
  18609     rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[0]), 0, 
  18610                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_0(unit) - 1, 0, 
  18611                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_0(unit) - 1, 8, 
  18612                          "ing_lm_idx pool1");
  18613     if (BCM_FAILURE(rv)) {
  18614         _bcm_sb2_oam_control_free(unit, oc);
  18615         return (rv);
  18616 
  18617     }
  18618     /* Index management for Ingress LM counter pool 2 */
  18619     rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[1]), 0, 
  18620                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_1(unit) - 1, 0,
  18621                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_1(unit) - 1, 8,
  18622                          "ing_lm_idx pool2");
  18623     if (BCM_FAILURE(rv)) {
  18624         _bcm_sb2_oam_control_free(unit, oc);
  18625         return (rv);
  18626     }
  18627 
  18628     /* Index management for Ingress LM counter pool 3 */
  18629     rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[2]), 0, 
  18630                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_2(unit) - 1, 0,
  18631                          _BCM_SB2_MAX_OAM_LM_CTRS_POOL_2(unit) - 1, 8,
  18632                          "ing_lm_idx pool3");
  18633     if (BCM_FAILURE(rv)) {
  18634         _bcm_sb2_oam_control_free(unit, oc);
  18635         return (rv);
  18636     }
  18637 
  18638     
  18639     /* Mem_5: Create MA group and MEP hash table. */
  18640 
  18641 #if defined(BCM_METROLITE_SUPPORT)
  18642     if (SOC_IS_METROLITE(unit)) {
  18643         rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_METROLITE_ENDPOINT_MAX,
  18644                 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash");
  18645     } else
  18646 #endif
  18647     {
  18648         rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_SABER2_ENDPOINT_MAX,
  18649                 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash");
  18650     }
  18651     
  18652     if (BCM_FAILURE(rv)) {
  18653         _bcm_sb2_oam_control_free(unit, oc);
  18654         return (rv);
  18655     }
  18656 
  18657     /* Create protection mutex. */
  18658     oc->oc_lock = sal_mutex_create("oam_control.lock");
  18659     if (NULL == oc->oc_lock) {
  18660         _bcm_sb2_oam_control_free(unit, oc);
  18661         return (BCM_E_MEMORY);
  18662     }
  18663 
  18664     /* Register device OAM interrupt handler & SER handler call back routine.*/
  18665     soc_kt2_oam_handler_register(unit, _bcm_sb2_oam_handle_interrupt);
  18666     soc_kt2_oam_ser_handler_register(unit, _bcm_sb2_oam_ser_handler);
  18667 
  18668     /* Set up the unit OAM control structure. */
  18669     _sb2_oam_control[unit] = oc;
  18670 
  18671     if (soc_feature(unit, soc_feature_oam_pm)) {
  18672         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_pm_init(unit));
  18673     }
  18674     
  18675     /* Init OAM opcode group */ 
  18676     rv =_bcm_sb2_oam_opcode_group_init(unit);
  18677     if (BCM_FAILURE(rv)) {
  18678         _bcm_sb2_oam_control_free(unit, oc);
  18679         return (rv);
  18680     }
  18681     
  18682     /* Set up OAM module related profile tables. */
  18683     rv = _bcm_sb2_oam_profile_tables_init(unit, oc);
  18684     if (BCM_FAILURE(rv)) {
  18685         _bcm_sb2_oam_control_free(unit, oc);
  18686         return (rv);
  18687     }
  18688 
  18689     /* Initialize all the TPID tables */
  18690     rv =  _bcm_sb2_outer_tpid_init(unit); 
  18691     if (BCM_FAILURE(rv)) {
  18692         _bcm_sb2_oam_control_free(unit, oc);
  18693         return (rv);
  18694     }
  18695     rv =  _bcm_sb2_inner_tpid_init(unit); 
  18696     if (BCM_FAILURE(rv)) {
  18697         _bcm_sb2_oam_control_free(unit, oc);
  18698         return (rv);
  18699     }
  18700     rv =  _bcm_sb2_subport_tpid_init(unit); 
  18701     if (BCM_FAILURE(rv)) {
  18702         _bcm_sb2_oam_control_free(unit, oc);
  18703         return (rv);
  18704     }
  18705 
  18706 #if defined(BCM_WARM_BOOT_SUPPORT)
  18707     if(!SOC_WARM_BOOT(unit))
  18708 #endif
  18709     {
  18710         BCM_PBMP_CLEAR(all_pbmp);
  18711         BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
  18712 
  18713         if (soc_feature(unit, soc_feature_flex_port)) {
  18714 #if defined(BCM_METROLITE_SUPPORT)
  18715             if (SOC_IS_METROLITE(unit)) {
  18716                 BCM_IF_ERROR_RETURN(bcm_ml_flexio_pbmp_update(unit, &all_pbmp));
  18717 	    }else
  18718 #endif
  18719 	    {
  18720                 BCM_IF_ERROR_RETURN(bcm_sb2_flexio_pbmp_update(unit, &all_pbmp));
  18721 	    }
  18722         }
  18723         if (soc_feature(unit, soc_feature_linkphy_coe) ||
  18724             soc_feature(unit, soc_feature_subtag_coe)) {
  18725             _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
  18726         }
  18727 
  18728         if(SOC_IS_SABER2(unit)){
  18729             int oamp_enable = 0;
  18730             BCM_IF_ERROR_RETURN(bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable));
  18731             /* Skip OAMP port for saber2 device */
  18732             if(oamp_enable) {
  18733                 SOC_PBMP_PORT_REMOVE(all_pbmp,
  18734                         _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER);
  18735             }
  18736         }
  18737 
  18738         /* Enable OAM processing on all ports of this unit. */
  18739         PBMP_ITER(all_pbmp, port) {
  18740             rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable,
  18741                                           TRUE);
  18742             if (BCM_FAILURE(rv)) {
  18743                 _bcm_sb2_oam_control_free(unit, oc);
  18744                 return (rv);
  18745             }
  18746         }
  18747 
  18748         /* Enable CCM Rx timeouts. */
  18749         rv = _bcm_sb2_oam_ccm_rx_timeout_set(unit, 1);
  18750         if (BCM_FAILURE(rv)) {
  18751             _bcm_sb2_oam_control_free(unit, oc);
  18752             return (rv);
  18753         }
  18754 
  18755         /* Enable CCM Tx control. */
  18756         rv = _bcm_sb2_oam_ccm_tx_config_set(unit, 1);
  18757         if (BCM_FAILURE(rv)) {
  18758             _bcm_sb2_oam_control_free(unit, oc);
  18759             return (rv);
  18760         }
  18761 
  18762 
  18763         /* 
  18764          * Misc config: Enable IFP lookup on the CPU port. 
  18765          */
  18766         rv = _bcm_sb2_oam_misc_config(unit);
  18767         if (BCM_FAILURE(rv)) {
  18768             _bcm_sb2_oam_control_free(unit, oc);
  18769             return (rv);
  18770         }
  18771         /* Set all the non CFM opcodes in opcode group -1 */
  18772         oc->opcode_grp_bmp[0] = ~(_BCM_OAM_OPCODE_TYPE_CFM_MASK);
  18773         oc->opcode_grp_1_bmp[0] = 0; 
  18774         oc->opcode_grp_2_bmp[0] = 0; 
  18775         for (index = 1; index < 8; index ++) {
  18776             oc->opcode_grp_bmp[index] = _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK; 
  18777             oc->opcode_grp_1_bmp[index] = 0; 
  18778             oc->opcode_grp_2_bmp[index] = 0; 
  18779         }
  18780 
  18781         /* Init MPLS OAM ach type config */
  18782         rv = _bcm_sb2_oam_mpls_oam_ach_type_config_init(unit);
  18783         if (BCM_FAILURE(rv)) {
  18784             _bcm_sb2_oam_control_free(unit, oc);
  18785             return (rv);
  18786         }
  18787         /* Init OAM_KEY_SELECT_CONTROL registers */
  18788         rv = _bcm_sb2_oam_lookup_key_priorities_init(unit);
  18789         if (BCM_FAILURE(rv)) {
  18790             _bcm_sb2_oam_control_free(unit, oc);
  18791             return (rv);
  18792         }
  18793         /* Init OAM_INTF_PROC_SELECT_CONTROL registers */
  18794         rv = _bcm_sb2_oam_lookup_interface_priorities_init(unit);
  18795         if (BCM_FAILURE(rv)) {
  18796             _bcm_sb2_oam_control_free(unit, oc);
  18797             return (rv);
  18798         }
  18799 
  18800         /* Set default values for flexible oam domain control  */
  18801         rv = _bcm_sb2_oam_flexible_oam_domain_ctrl_set(unit); 
  18802         if (BCM_FAILURE(rv)) {
  18803             _bcm_sb2_oam_control_free(unit, oc);
  18804             return (rv);
  18805         }
  18806         /* Set default values for flexible ingress and egress drop control */
  18807         rv = _bcm_sb2_oam_flexible_drop_ctrl_set(unit);
  18808         if (BCM_FAILURE(rv)) {
  18809             _bcm_sb2_oam_control_free(unit, oc);
  18810             return (rv);
  18811         }
  18812         /* Set default values for s-interface passive processing control */
  18813         rv = _bcm_sb2_oam_s_intf_passive_proc_ctrl_set(unit);
  18814         if (BCM_FAILURE(rv)) {
  18815             _bcm_sb2_oam_control_free(unit, oc);
  18816             return (rv);
  18817         } 
  18818         /* Enable OLP handling on HG ports */
  18819         rv = _bcm_sb2_oam_hg_olp_enable(unit);
  18820         if (BCM_FAILURE(rv)) {
  18821             _bcm_sb2_oam_control_free(unit, oc);
  18822             return (rv);
  18823         }
  18824         /* Set default olp header type mapping */
  18825         rv = _bcm_sb2_oam_olp_header_type_mapping_set(unit); 
  18826         if (BCM_FAILURE(rv)) {
  18827             _bcm_sb2_oam_control_free(unit, oc);
  18828             return (rv);
  18829         }
  18830         /* Set default behavior to add olp header for oam pkts to CPU */
  18831         rv = _bcm_sb2_oam_set_egr_oam_rx_mode(unit, 1);
  18832         if (BCM_FAILURE(rv)) {
  18833             _bcm_sb2_oam_control_free(unit, oc);
  18834             return (rv);
  18835         }
  18836         /* Set OAM drop control to not to drop wrong version OAM packets */
  18837         rv = _bcm_sb2_oam_drop_ctrl_set(unit); 
  18838         if (BCM_FAILURE(rv)) {
  18839             _bcm_sb2_oam_control_free(unit, oc);
  18840             return (rv);
  18841         }
  18842         /* Set OAM LM cng and cpu data control*/
  18843         rv = _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default(unit); 
  18844         if (BCM_FAILURE(rv)) {
  18845             _bcm_sb2_oam_control_free(unit, oc);
  18846             return (rv);
  18847         }
  18848         /* Set Magic port used in OLP-XGS communication */
  18849         rv = _bcm_sb2_oam_olp_magic_port_set(unit); 
  18850         if (BCM_FAILURE(rv)) {
  18851             _bcm_sb2_oam_control_free(unit, oc);
  18852             return (rv);
  18853         }
  18854         /* Disable MACSA Zero check  */
  18855         rv = _bcm_sb2_oam_macsa_zero_check_disable(unit); 
  18856         if (BCM_FAILURE(rv)) {
  18857             _bcm_sb2_oam_control_free(unit, oc);
  18858             return (rv);
  18859         }
  18860     }
  18861 
  18862 
  18863     /*
  18864      * BHH init
  18865      */
  18866     if(soc_feature(unit, soc_feature_bhh)) {
  18867 #if defined(INCLUDE_BHH)
  18868         if(ukernel_not_ready == 0){
  18869             /*
  18870              * Initialize HOST side
  18871              */
  18872             oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, 
  18873                                             BHH_COSQ_INVALID);
  18874 
  18875             /*
  18876              * Allocate DMA buffers
  18877              *
  18878              * DMA buffer will be used to send and receive 'long' messages
  18879              * between SDK Host and uController (BTE).
  18880              */
  18881             oc->dma_buffer_len = sizeof(bhh_sdk_msg_ctrl_t);
  18882 
  18883             /* Adding  feature specific for dma_buf_len as currently 
  18884              * required buffer length for faults_get can be configurable 
  18885              * by user during init. So, taking the max value of either of
  18886              * them for the purpose.Putting it under fature_check for 
  18887              * giving flexibility to user.
  18888              */
  18889 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET
  18890             if(soc_feature(unit, soc_feature_faults_multi_ep_get)) {
  18891                 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len);
  18892             }
  18893 #endif
  18894             oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len,
  18895                                            "BHH DMA buffer");
  18896             if (!oc->dma_buffer) {
  18897                 _bcm_sb2_oam_control_free(unit, oc);
  18898                 return (BCM_E_MEMORY);
  18899             }
  18900             sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len);
  18901 
  18902             oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len,
  18903                                              "BHH uC reply");
  18904             if (!oc->dmabuf_reply) {
  18905                 _bcm_sb2_oam_control_free(unit, oc);
  18906                 return (BCM_E_MEMORY);
  18907             }
  18908 
  18909             sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len);
  18910 
  18911             _BCM_OAM_ALLOC(oc->bhh_ma_index_in_use, SHR_BITDCL, 
  18912                            SHR_BITALLOCSIZE(oc->ma_idx_count),
  18913                            "MA_INDEX ALLOCATED FOR BHH");
  18914 
  18915             _BCM_OAM_ALLOC(oc->bhh_ep_grp_id, short, 
  18916                            sizeof(short) * oc->bhh_endpoint_count,
  18917                            "BHH endpoint group ids");
  18918 
  18919             _BCM_OAM_ALLOC(oc->bhh_ep_vpn, short, 
  18920                            sizeof(short) * oc->bhh_endpoint_count,
  18921                            "BHH endpoint VPN ids");
  18922 
  18923             /* RX DMA channel (0..3) local to the uC */
  18924             oc->rx_channel = BCM_KT_BHH_RX_CHANNEL;
  18925 
  18926 #ifdef BCM_WARM_BOOT_SUPPORT
  18927             if (!SOC_WARM_BOOT(unit)) {
  18928 #endif
  18929                 /* Set control message data */
  18930                 sal_memset(&msg_init, 0, sizeof(msg_init));
  18931                 msg_init.num_sessions       = oc->bhh_endpoint_count;
  18932                 msg_init.rx_channel         = oc->rx_channel;
  18933                 msg_init.node_id            = node_id;
  18934                 sal_memcpy(msg_init.carrier_code, carrier_code, 
  18935                            SHR_BHH_CARRIER_CODE_LEN);
  18936                 if (soc_feature(unit, soc_feature_oam_pm)) {
  18937                     msg_init.data_collection_mode = oc->pm_bhh_lmdm_data_collection_mode;
  18938                 }
  18939                 msg_init.max_encap_length = oc->bhh_max_encap_length;
  18940                 if (bhh_consolidate_final_event) {
  18941                     msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT;
  18942                 }
  18943  
  18944                 /* Pack control message data into DMA buffer */
  18945                 buffer     = oc->dma_buffer;
  18946                 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init);
  18947                 buffer_len = buffer_ptr - buffer;
  18948 
  18949                 /* Send BHH Init message to uC */
  18950                 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  18951                                                  MOS_MSG_SUBCLASS_BHH_INIT,
  18952                                                  buffer_len, 0,
  18953                                                  MOS_MSG_SUBCLASS_BHH_INIT_REPLY,
  18954                                                  &reply_len);
  18955 
  18956                 if (BCM_FAILURE(rv) || (reply_len != 0)) {
  18957                     _bcm_sb2_oam_control_free(unit, oc);
  18958                     return (BCM_E_INTERNAL);
  18959                 }
  18960 
  18961 #ifdef BCM_WARM_BOOT_SUPPORT
  18962             }
  18963 #endif
  18964 
  18965             /*
  18966              * End BHH init
  18967              */
  18968         }
  18969     /*
  18970      * Initialize HW
  18971      */
  18972 #ifdef BCM_WARM_BOOT_SUPPORT
  18973         if (SOC_WARM_BOOT(unit)) {
  18974             rv = _bcm_sb2_oam_bhh_cos_map_recover(unit);
  18975         } else
  18976 #endif
  18977         {
  18978             rv = _bcm_sb2_oam_bhh_hw_init(unit);
  18979         }
  18980 
  18981         if (BCM_FAILURE(rv)) {
  18982             BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  18983             return rv;
  18984         }
  18985 
  18986 
  18987 #endif
  18988     }
  18989 
  18990     /*
  18991      * ETH_LM_DM init
  18992      */
  18993     if(soc_feature(unit, soc_feature_eth_lm_dm)) {
  18994 #if defined(INCLUDE_ETH_LM_DM)
  18995 
  18996         if(!oc->eth_lm_dm_ukernel_not_ready) {
  18997 
  18998             /* Get number of sessions SOC properties for ETH_LM_DM */
  18999             oc->eth_lm_dm_sess_count = soc_property_get(unit,
  19000                                                         spn_ETH_LM_DM_NUM_SESSIONS,
  19001                                                         128);
  19002 
  19003             size = sizeof(uint32) * oc->eth_lm_dm_sess_count;
  19004             _BCM_OAM_ALLOC(oc->eth_lm_dm_sess_id_ep_id, uint32, size,
  19005                            "ETHLM DM SESSION TO EP ID MAP");
  19006 
  19007             /* Create ETH_LM_DM session pool */
  19008             rv = shr_idxres_list_create(&oc->eth_lm_dm_pool, 1,
  19009                                         oc->eth_lm_dm_sess_count, 1,
  19010                                         oc->eth_lm_dm_sess_count,
  19011                                         "eth_lm_dm pool");
  19012 
  19013             if (BCM_FAILURE(rv)) {
  19014                 LOG_ERROR(BSL_LS_BCM_OAM,
  19015                           (BSL_META_U(unit, "ETH_LM_DM(unit %d) Error:"
  19016                                       " Creating Session Id pool failed \n"), unit));
  19017                 _bcm_sb2_oam_control_free(unit, oc);
  19018                 return (rv);
  19019             }
  19020 
  19021             /*
  19022              * Initialize HOST side
  19023              */
  19024             if (SOC_IS_METROLITE(unit)) {
  19025                 eth_lm_dm_default_cosq = BCM_ML_ETH_LM_DM_CPU_COS;
  19026             } else {
  19027                 eth_lm_dm_default_cosq = BCM_SB2_ETH_LM_DM_CPU_COS;
  19028             }
  19029             oc->eth_lm_dm_cpu_cosq = soc_property_get(unit,
  19030                                                       spn_ETH_LM_DM_COSQ,
  19031                                                       eth_lm_dm_default_cosq);
  19032             /*
  19033              * Allocate DMA buffers
  19034              *
  19035              * DMA buffer will be used to send and receive 'long' messages
  19036              * between SDK Host and uController (BTE).
  19037              */
  19038             oc->eth_lm_dm_dma_buffer_len = sizeof(shr_eth_lm_dm_msg_ctrl_t);
  19039             oc->eth_lm_dm_dma_buffer = soc_cm_salloc(unit, oc->eth_lm_dm_dma_buffer_len,
  19040                     "ETH_LM_DM DMA buffer");
  19041             if (!oc->eth_lm_dm_dma_buffer) {
  19042                 _bcm_sb2_oam_control_free(unit, oc);
  19043                 return (BCM_E_MEMORY);
  19044             }
  19045             sal_memset(oc->eth_lm_dm_dma_buffer, 0, oc->eth_lm_dm_dma_buffer_len);
  19046 
  19047             oc->eth_lm_dm_dmabuf_reply =
  19048                 soc_cm_salloc(unit, sizeof(shr_eth_lm_dm_msg_ctrl_t),
  19049                         "ETH_LM_DM uC reply");
  19050             if (!oc->eth_lm_dm_dmabuf_reply) {
  19051                 _bcm_sb2_oam_control_free(unit, oc);
  19052                 return (BCM_E_MEMORY);
  19053             }
  19054             sal_memset(oc->eth_lm_dm_dmabuf_reply, 0, sizeof(shr_eth_lm_dm_msg_ctrl_t));
  19055 
  19056             /* RX DMA channel */
  19057             if (SOC_IS_METROLITE(unit)) {
  19058                 oc->eth_lm_dm_rx_channel = BCM_ML_ETH_LM_DM_RX_CHANNEL;
  19059             } else {
  19060                 oc->eth_lm_dm_rx_channel = BCM_SB2_ETH_LM_DM_RX_CHANNEL;
  19061             }
  19062 
  19063 #ifdef BCM_WARM_BOOT_SUPPORT
  19064             if (!SOC_WARM_BOOT(unit)) {
  19065 #endif
  19066                 /* Set control message data */
  19067                 sal_memset(&eth_msg_init, 0, sizeof(eth_msg_init));
  19068                 eth_msg_init.num_sessions = oc->eth_lm_dm_sess_count;
  19069                 eth_msg_init.rx_channel   = BCM_SB2_ETH_LM_DM_UC_RX_CHANNEL;
  19070                 eth_msg_init.data_collection_mode =
  19071                     oc->pm_eth_lmdm_data_collection_mode;
  19072 
  19073                 /* Pack control message data into DMA buffer */
  19074                 buffer     = oc->eth_lm_dm_dma_buffer;
  19075                 buffer_ptr = eth_lm_dm_sdk_msg_ctrl_init_pack(buffer,
  19076                         &eth_msg_init);
  19077                 buffer_len = buffer_ptr - buffer;
  19078 
  19079                 /* Send ETH_LM_DM Init message to uC */
  19080                 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  19081                         MOS_MSG_SUBCLASS_ETH_LM_DM_INIT,
  19082                         buffer_len, 0,
  19083                         MOS_MSG_SUBCLASS_ETH_LM_DM_INIT_REPLY,
  19084                         &reply_len);
  19085 
  19086                 if (BCM_FAILURE(rv) || (reply_len != 0)) {
  19087                     _bcm_sb2_oam_control_free(unit, oc);
  19088                     return (BCM_E_INTERNAL);
  19089                 }
  19090 #ifdef BCM_WARM_BOOT_SUPPORT
  19091             }
  19092 #endif
  19093         }
  19094         /*
  19095          * Initialize HW.If the app is not processed in uKernel(uKernel not Ready)
  19096          * still pipeleine or HW programming is required to send the LM/DM packets
  19097          * to correct CPU
  19098          */
  19099 #ifdef BCM_WARM_BOOT_SUPPORT
  19100         if (SOC_WARM_BOOT(unit)) {
  19101             rv = _bcm_sb2_oam_eth_lm_dm_cos_map_recover(unit);
  19102         } else
  19103 #endif
  19104         {
  19105             rv = _bcm_sb2_oam_eth_lm_dm_hw_init(unit);
  19106         }
  19107 
  19108         if (BCM_FAILURE(rv)) {
  19109             BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19110             return rv;
  19111         }
  19112 
  19113 #endif
  19114     }
  19115 
  19116 #if defined(INCLUDE_MPLS_LM_DM)
  19117     if(oc->mpls_lm_dm_ukernel_ready) {
  19118 
  19119         /*
  19120          * Allocate DMA buffers
  19121          * DMA buffer will be used to send and receive 'long' messages
  19122          * between SDK Host and uController (BTE).
  19123          */
  19124         oc->mpls_lm_dm_dma_buffer_len = sizeof(mpls_lm_dm_sdk_msg_ctrl_t);
  19125         oc->mpls_lm_dm_dma_buffer = soc_cm_salloc(unit, 
  19126             oc->mpls_lm_dm_dma_buffer_len, "MPLS_LM_DM DMA buffer");
  19127         if (!oc->mpls_lm_dm_dma_buffer) {
  19128             _bcm_sb2_oam_control_free(unit, oc);
  19129             return (BCM_E_MEMORY);
  19130         }
  19131         sal_memset(oc->mpls_lm_dm_dma_buffer, 0, oc->mpls_lm_dm_dma_buffer_len);
  19132 
  19133         oc->mpls_lm_dm_dmabuf_reply = soc_cm_salloc(unit, 
  19134                     sizeof(shr_mpls_lm_dm_msg_ctrl_t), "MPLS_LM_DM uC reply");
  19135         if (!oc->mpls_lm_dm_dmabuf_reply) {
  19136             _bcm_sb2_oam_control_free(unit, oc);
  19137             return (BCM_E_MEMORY);
  19138         }
  19139         sal_memset(oc->mpls_lm_dm_dmabuf_reply, 0, 
  19140                                             sizeof(mpls_lm_dm_sdk_msg_ctrl_t));
  19141 
  19142 #ifdef BCM_WARM_BOOT_SUPPORT
  19143         /* If We are warm rebooting dont re-initialize the App */
  19144         if (!SOC_WARM_BOOT(unit)) {
  19145 #endif
  19146 
  19147         /* Send Initialize MPLS LM/DM App on UKERNEL */
  19148         /* Set control message data */
  19149         sal_memset(&mpls_lm_dm_msg_init, 0, sizeof(mpls_lm_dm_msg_init));
  19150         mpls_lm_dm_msg_init.num_sessions = oc->mpls_lm_dm_sess_count;
  19151         mpls_lm_dm_msg_init.rx_channel = MPLS_LM_DM_RX_CHANNEL_UC_VIEW;
  19152 
  19153         /* Add PM data collection mode to init message */
  19154         if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
  19155             if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc))
  19156             {
  19157                 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_RAW;
  19158             }
  19159             else {
  19160                 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_STATS;
  19161             }
  19162         }
  19163 
  19164         /* Pack control message data into DMA buffer */
  19165         buffer = oc->mpls_lm_dm_dma_buffer;
  19166         buffer_ptr = mpls_lm_dm_sdk_msg_ctrl_init_pack(buffer, &mpls_lm_dm_msg_init);
  19167         buffer_len = buffer_ptr - buffer;
  19168 
  19169         /* Send MPLS_LM_DM Init message to uC */
  19170         rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit,
  19171                 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT, buffer_len, 0,
  19172                 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT_REPLY, &reply_len);
  19173 
  19174         if (BCM_FAILURE(rv) || (reply_len != 0)) {
  19175             /* Could not start MPLS_LM_DM appl */
  19176             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  19177                 "MPLS LM DM Session alloc msg failed\n"), unit));
  19178             BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19179             return rv;
  19180         }
  19181 
  19182 #ifdef BCM_WARM_BOOT_SUPPORT
  19183         }
  19184 #endif
  19185         /*
  19186          * Initialize HW. If the app is not processed in uKernel(uKernel not
  19187          * Ready) still pipeleine or HW programming is required to send the 
  19188          * LM/DM packets to correct CPU
  19189          */
  19190 
  19191         /* RX DMA channel (0..3) local to the uC */
  19192         oc->mpls_lm_dm_rx_channel = MPLS_LM_DM_RX_CHANNEL_SDK_VIEW;
  19193         oc->mpls_lm_dm_cpu_cosq = MPLS_LM_DM_COSQ_INVALID;
  19194 #ifdef BCM_WARM_BOOT_SUPPORT
  19195         if (SOC_WARM_BOOT(unit)) {
  19196             rv = _bcm_sb2_oam_mpls_lm_dm_cos_map_recover(unit);
  19197         } else
  19198 #endif
  19199 #if defined(BCM_METROLITE_SUPPORT)
  19200         if (SOC_IS_METROLITE(unit)) {
  19201             rv = _bcm_ml_oam_mpls_lm_dm_hw_init(unit);
  19202         } else
  19203 #endif
  19204         {
  19205             rv = _bcm_sb2_oam_mpls_lm_dm_hw_init(unit);
  19206         }
  19207 
  19208         if (BCM_FAILURE(rv)) {
  19209             BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19210             return rv;
  19211         }
  19212 
  19213     }
  19214 #endif
  19215 
  19216     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_init(unit);
  19217     if (BCM_FAILURE(rv)) {
  19218         BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19219         return rv;
  19220     }
  19221 
  19222 #if defined(BCM_WARM_BOOT_SUPPORT)
  19223     if (!SOC_WARM_BOOT(unit)) {
  19224          bcm_sb2_oam_scache_alloc(unit);
  19225     }
  19226 
  19227 #if defined(INCLUDE_BHH)
  19228     if(soc_feature(unit, soc_feature_bhh)) {
  19229         if(ukernel_not_ready == 0) {
  19230             rv = bcmi_xgs5_bhh_version_exchange(unit);
  19231             if (BCM_FAILURE(rv)) {
  19232                 _bcm_sb2_oam_control_free(unit, oc);
  19233                 return rv;
  19234             }
  19235         }
  19236     }
  19237 #endif
  19238 
  19239     if (SOC_WARM_BOOT(unit)) {
  19240         rv = _bcm_sb2_oam_reinit(unit);
  19241         if (BCM_FAILURE(rv)) {
  19242             _bcm_sb2_oam_control_free(unit, oc);
  19243             return (rv);
  19244         }
  19245     }
  19246 #endif
  19247 
  19248     if(soc_feature(unit, soc_feature_bhh)) {
  19249 #if defined(INCLUDE_BHH)
  19250         if(ukernel_not_ready == 0){
  19251             /*
  19252              * Start event message callback thread
  19253              */
  19254             priority = soc_property_get(unit, spn_BHH_THREAD_PRI,
  19255                     BHH_THREAD_PRI_DFLT);
  19256 
  19257             if (oc->event_thread_id == NULL) {
  19258                 sal_thread_t thread_id;
  19259                 thread_id = sal_thread_create("bcmBHH", SAL_THREAD_STKSZ,
  19260                         priority, _bcm_sb2_oam_bhh_callback_thread,
  19261                         (void*)oc);
  19262                 if (thread_id == SAL_THREAD_ERROR) {
  19263                     BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19264                     return (BCM_E_MEMORY);
  19265                 } else {
  19266                     oc->event_thread_id = thread_id;
  19267                 }
  19268             }
  19269         }
  19270 #endif
  19271     }
  19272 
  19273     if(soc_feature(unit, soc_feature_eth_lm_dm)) {
  19274 #if defined(INCLUDE_ETH_LM_DM)
  19275         if(!eth_lm_dm_ukernel_not_ready) {
  19276             /*
  19277              * Start event message callback thread
  19278              */
  19279             if (oc->eth_lm_dm_pm_event_thread_id == NULL) {
  19280                 if ((oc->eth_lm_dm_pm_event_thread_id =
  19281                             sal_thread_create("bcmETHLMDM", SAL_THREAD_STKSZ,
  19282                                 ETH_LMDM_EVENT_THREAD_PRIORITY,
  19283                                 _bcm_sb2_oam_pm_ethlmdm_callback_thread,
  19284                                 (void*)oc)) == SAL_THREAD_ERROR) {
  19285                     oc->eth_lm_dm_pm_event_thread_id = NULL;
  19286                     BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19287                     return (BCM_E_MEMORY);
  19288                 }
  19289             }
  19290         }
  19291 #endif
  19292     }
  19293 
  19294 #if defined(INCLUDE_MPLS_LM_DM)
  19295     if(oc->mpls_lm_dm_ukernel_ready) {
  19296         /*
  19297          * Start event message callback thread
  19298          */
  19299         if (oc->mpls_lm_dm_pm_event_thread_id == NULL) {
  19300             if ((oc->mpls_lm_dm_pm_event_thread_id =
  19301                         sal_thread_create("bcmMPLSLMDM", SAL_THREAD_STKSZ,
  19302                             MPLS_LMDM_EVENT_THREAD_PRIORITY,
  19303                             _bcm_sb2_oam_pm_mplslmdm_callback_thread,
  19304                             (void*)oc)) == SAL_THREAD_ERROR) {
  19305                 oc->mpls_lm_dm_pm_event_thread_id = NULL;
  19306                 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit));
  19307                 return (BCM_E_MEMORY);
  19308             }
  19309         }
  19310     }
  19311 #endif
  19312 
  19313     /* OAM initialization complete. */
  19314     _sb2_oam_control[unit]->init = TRUE;
  19315     return (BCM_E_NONE);
  19316 }
  19317 
  19318 /*
  19319  * Function:
  19320  *     bcm_sb2_oam_detach
  19321  * Purpose:
  19322  *     Shut down OAM subsystem
  19323  * Parameters:
  19324  *     unit - (IN) BCM device number
  19325  * Returns:
  19326  *     BCM_E_XXX
  19327  */
  19328 int
  19329 bcm_sb2_oam_detach(int unit)
  19330 {
  19331     _bcm_oam_control_t *oc;  /* Pointer to OAM control structure. */
  19332     bcm_port_t         port; /* Port number.                      */
  19333     int                rv;   /* Operation return status.          */
  19334     bcm_pbmp_t         all_pbmp;
  19335 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  19336     uint16 reply_len;
  19337     int uc_status;
  19338 #endif
  19339 
  19340     /* Get the device OAM module handle. */
  19341     oc = _sb2_oam_control[unit];
  19342     if (NULL == oc) {
  19343         /* Module already uninitialized. */
  19344         return (BCM_E_NONE);
  19345     }
  19346 
  19347     /* Unregister all OAM interrupt event handlers and SER handler. */
  19348     soc_kt2_oam_handler_register(unit, NULL);
  19349     soc_kt2_oam_ser_handler_register(unit, NULL);
  19350 
  19351     if (NULL != oc->oc_lock) {
  19352         _BCM_OAM_LOCK(oc);
  19353     }
  19354 
  19355     rv = _bcm_sb2_oam_events_unregister(unit, oc);
  19356     if (BCM_FAILURE(rv)) {
  19357         if (NULL != oc->oc_lock) {
  19358             _BCM_OAM_UNLOCK(oc);
  19359         }
  19360         return (rv);
  19361     }
  19362 
  19363     /* Disable CCM Rx Timeouts. */
  19364     rv = _bcm_sb2_oam_ccm_rx_timeout_set(unit, 0);
  19365     if (BCM_FAILURE(rv)) {
  19366         if (NULL != oc->oc_lock) {
  19367             _BCM_OAM_UNLOCK(oc);
  19368         }
  19369         return (rv);
  19370     }
  19371 
  19372     /* Disable CCM Tx control for the device. */
  19373     rv = _bcm_sb2_oam_ccm_tx_config_set(unit, 0);
  19374     if (BCM_FAILURE(rv)) {
  19375         if (NULL != oc->oc_lock) {
  19376             _BCM_OAM_UNLOCK(oc);
  19377         }
  19378         return (rv);
  19379     }
  19380 
  19381     BCM_PBMP_CLEAR(all_pbmp);
  19382     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
  19383     
  19384     if (soc_feature(unit, soc_feature_flex_port)) {
  19385 #if defined(BCM_METROLITE_SUPPORT)
  19386             if (SOC_IS_METROLITE(unit)) {
  19387                 rv =bcm_ml_flexio_pbmp_update(unit, &all_pbmp);
  19388 	    }else
  19389 #endif
  19390 	    {
  19391                 rv = bcm_sb2_flexio_pbmp_update(unit, &all_pbmp);
  19392 	    }
  19393         if (BCM_FAILURE(rv)) { 
  19394             _BCM_OAM_UNLOCK(oc);
  19395             return (rv);
  19396         }
  19397     }
  19398     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  19399         soc_feature(unit, soc_feature_subtag_coe)) {
  19400         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
  19401     }
  19402 
  19403 #if defined(BCM_SABER2_SUPPORT)
  19404     if(SOC_IS_SABER2(unit)){
  19405         int oamp_enable;
  19406         (void)bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable);
  19407         /* Skip OAMP port for saber2 device */
  19408         if(oamp_enable) {
  19409             SOC_PBMP_PORT_REMOVE(all_pbmp,
  19410                     _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER);
  19411         }
  19412     }
  19413 #endif
  19414 
  19415     /* Disable OAM PDU Rx processing on all ports. */
  19416     PBMP_ITER(all_pbmp, port) {
  19417         rv = bcm_esw_port_control_set(unit, port,
  19418                                       bcmPortControlOAMEnable, 0);
  19419         if (BCM_FAILURE(rv)) {
  19420             if (NULL != oc->oc_lock) {
  19421                 _BCM_OAM_UNLOCK(oc);
  19422             }
  19423             return (rv);
  19424         }
  19425     }
  19426 
  19427     
  19428 
  19429      /*
  19430      * BHH specific
  19431      */
  19432     if (soc_feature(unit, soc_feature_bhh)) {
  19433 #if defined(INCLUDE_BHH)
  19434         if (oc->ukernel_not_ready == 0) {
  19435             /*
  19436              * Event Handler thread exit signal
  19437              */
  19438             sal_usecs_t timeout = sal_time_usecs() + 5000000;
  19439             while (NULL !=  oc->event_thread_id) {
  19440                 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num,
  19441                                                MOS_MSG_CLASS_BHH_EVENT);
  19442 
  19443                 if (sal_time_usecs() < timeout) {
  19444                     /*give some time to already running bhh callback thread
  19445                      * to schedule and exit */
  19446                     sal_usleep(10000);
  19447                 } else {
  19448                     /*timeout*/
  19449                     LOG_ERROR(BSL_LS_BCM_OAM,
  19450                               (BSL_META_U(unit,
  19451                                           "BHH event thread did not exit.\n")));
  19452                     _BCM_OAM_UNLOCK(oc);
  19453                     return BCM_E_INTERNAL;
  19454                 }
  19455             }
  19456             if (!SOC_WARM_BOOT(unit)) {
  19457                 /*
  19458                  * Send BHH Uninit message to uC
  19459                  * Ignore error since that may indicate uKernel was reloaded.
  19460                  */
  19461                 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->uc_num, &uc_status));
  19462                 if (uc_status) {
  19463                     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  19464                                     MOS_MSG_SUBCLASS_BHH_UNINIT,
  19465                                     0, 0,
  19466                                     MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY,
  19467                                     &reply_len);
  19468                     if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  19469                         if (NULL != oc->oc_lock) {
  19470                             _BCM_OAM_UNLOCK(oc);
  19471                         }
  19472                         return BCM_E_INTERNAL;
  19473                     }
  19474                 }
  19475 
  19476                 /*
  19477                  * Delete CPU COS queue mapping entries for BHH packets
  19478                  */
  19479                 if (oc->cpu_cosq_ach_error_index >= 0) {
  19480                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  19481                             oc->cpu_cosq_ach_error_index);
  19482                     if (BCM_FAILURE(rv)) {
  19483                         if (NULL != oc->oc_lock) {
  19484                             _BCM_OAM_UNLOCK(oc);
  19485                         }
  19486                         return (rv);
  19487                     }
  19488                     oc->cpu_cosq_ach_error_index = -1;
  19489                 }
  19490                 if (oc->cpu_cosq_invalid_error_index >= 0) {
  19491                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  19492                             oc->cpu_cosq_invalid_error_index);
  19493                     if (BCM_FAILURE(rv)) {
  19494                         if (NULL != oc->oc_lock) {
  19495                             _BCM_OAM_UNLOCK(oc);
  19496                         }
  19497                         return (rv);
  19498                     }
  19499                     oc->cpu_cosq_invalid_error_index = -1;
  19500                 }
  19501                 if (oc->bhh_lb_index >= 0) {
  19502                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
  19503                             oc->bhh_lb_index);
  19504                     if (BCM_FAILURE(rv)) {
  19505                         if (NULL != oc->oc_lock) {
  19506                             _BCM_OAM_UNLOCK(oc);
  19507                         }
  19508                         return (rv);
  19509                     }
  19510                     oc->bhh_lb_index = -1;
  19511                 }
  19512             }
  19513         }
  19514 
  19515 #endif /* INCLUDE_BHH */
  19516     }
  19517 
  19518     /*
  19519      * ETH_LM_DM specific
  19520      */
  19521     if (soc_feature(unit, soc_feature_eth_lm_dm)) {
  19522 #if defined(INCLUDE_ETH_LM_DM)
  19523     if(!oc->eth_lm_dm_ukernel_not_ready) {
  19524        /*
  19525         * Event Handler thread exit signal
  19526         */
  19527         sal_usecs_t timeout = sal_time_usecs() + 5000000;
  19528         while (NULL !=  oc->eth_lm_dm_pm_event_thread_id) {
  19529             soc_cmic_uc_msg_receive_cancel(unit, oc->eth_lm_dm_uc_num,
  19530                                            MOS_MSG_CLASS_ETH_LM_DM_EVENT);
  19531 
  19532             if (sal_time_usecs() < timeout) {
  19533                 /*give some time to already running ETH LM/DM callback thread
  19534                  * to schedule and exit */
  19535                 sal_usleep(10000);
  19536             } else {
  19537                 /*timeout*/
  19538                 LOG_ERROR(BSL_LS_BCM_OAM,
  19539                           (BSL_META_U(unit,
  19540                                       "ETH LM/DM event thread did not exit.\n")));
  19541                 _BCM_OAM_UNLOCK(oc);
  19542                 return BCM_E_INTERNAL;
  19543             }
  19544         }
  19545 
  19546         /*
  19547          * Send ETH_LM_DM Uninit message to uC
  19548          * Ignore error since that may indicate uKernel was reloaded.
  19549          */
  19550         if (!SOC_WARM_BOOT(unit)) {
  19551             SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->eth_lm_dm_uc_num, &uc_status));
  19552             if (uc_status) {
  19553                 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  19554                                                 MOS_MSG_SUBCLASS_ETH_LM_DM_UNINIT,
  19555                                                 0, 0,
  19556                                                 MOS_MSG_SUBCLASS_ETH_LM_DM_UNINIT_REPLY,
  19557                                                 &reply_len);
  19558                 if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  19559                     if (NULL != oc->oc_lock) {
  19560                         _BCM_OAM_UNLOCK(oc);
  19561                     }
  19562                     return BCM_E_INTERNAL;
  19563                 }
  19564             }
  19565 
  19566             /*
  19567              * Delete CPU COS queue mapping entries for ETH_LM_DM packets
  19568              */
  19569             if (oc->eth_lm_dm_cosq_index >= 0) {
  19570                 rv = bcm_esw_rx_cosq_mapping_delete(unit,
  19571                                                     oc->eth_lm_dm_cosq_index);
  19572                 if (BCM_FAILURE(rv)) {
  19573                     if (NULL != oc->oc_lock) {
  19574                         _BCM_OAM_UNLOCK(oc);
  19575                     }
  19576                     return (rv);
  19577                 }
  19578                 oc->eth_lm_dm_cosq_index = -1;
  19579             }
  19580         }
  19581     }
  19582 #endif /* INCLUDE_ETH_LM_DM */
  19583     }
  19584 
  19585  
  19586 /* MPLS_LM_DM specific */
  19587 #if defined(INCLUDE_MPLS_LM_DM)
  19588     if(oc->mpls_lm_dm_ukernel_ready) {
  19589         /*
  19590          * Send MPLS_LM_DM Uninit message to uC
  19591          * Ignore error since that may indicate uKernel was reloaded.
  19592          */
  19593         if (!SOC_WARM_BOOT(unit)) {
  19594             SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->mpls_lm_dm_uc_num, &uc_status));
  19595             if (uc_status) {
  19596                 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit,
  19597                      MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT, 0, 0,
  19598                      MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT_REPLY, &reply_len);
  19599                 if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  19600                     if (NULL != oc->oc_lock) {
  19601                         _BCM_OAM_UNLOCK(oc);
  19602                     }
  19603                     return BCM_E_INTERNAL;
  19604                 }
  19605             }
  19606 
  19607             /* Delete CPU COS queue mapping entries for ETH_LM_DM packets */
  19608             if (oc->mpls_lm_dm_cosq_index >= 0) {
  19609                 rv = bcm_esw_rx_cosq_mapping_delete(unit, oc->mpls_lm_dm_cosq_index);
  19610                 if (BCM_FAILURE(rv)) {
  19611                     if (NULL != oc->oc_lock) {
  19612                         _BCM_OAM_UNLOCK(oc);
  19613                     }
  19614                     return (rv);
  19615                 }
  19616                 oc->mpls_lm_dm_cosq_index = -1;
  19617             }
  19618         }
  19619         /*
  19620          * Event Handler thread exit signal
  19621          */
  19622         sal_usecs_t timeout = sal_time_usecs() + 5000000;
  19623         while (NULL !=  oc->mpls_lm_dm_pm_event_thread_id) {
  19624             soc_cmic_uc_msg_receive_cancel(unit, oc->mpls_lm_dm_uc_num,
  19625                                            MOS_MSG_CLASS_MPLS_LM_DM_EVENT);
  19626 
  19627             if (sal_time_usecs() < timeout) {
  19628                 /*give some time to already running MPLS LM/DM callback thread
  19629                  * to schedule and exit */
  19630                 sal_usleep(10000);
  19631             } else {
  19632                 /*timeout*/
  19633                 LOG_ERROR(BSL_LS_BCM_OAM,
  19634                           (BSL_META_U(unit,
  19635                                       "MPLS LM/DM event thread did not exit.\n")));
  19636                 _BCM_OAM_UNLOCK(oc);
  19637                 return BCM_E_INTERNAL;
  19638             }
  19639         }
  19640     }
  19641 #endif /* INCLUDE_MPLS_LM_DM */
  19642 
  19643     /* Destroy all groups and assoicated endpoints and free the resources. */
  19644     rv = bcm_sb2_oam_group_destroy_all(unit);
  19645     if (BCM_FAILURE(rv)) {
  19646         if (NULL != oc->oc_lock) {
  19647             _BCM_OAM_UNLOCK(oc);
  19648         }
  19649         return (rv);
  19650     }
  19651     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_destroy(unit);
  19652     if (BCM_FAILURE(rv)) {
  19653         if (NULL != oc->oc_lock) {
  19654             _BCM_OAM_UNLOCK(oc);
  19655         }
  19656         return (rv);
  19657     }
  19658 
  19659     /* Release the protection mutex. */
  19660     _BCM_OAM_UNLOCK(oc);
  19661 
  19662     /* Free OAM module allocated resources. */
  19663     _bcm_sb2_oam_control_free(unit, oc);
  19664 
  19665     return (BCM_E_NONE);
  19666 }
  19667 
  19668 /*
  19669  * Function:
  19670  *     bcm_sb2_oam_group_create
  19671  * Purpose:
  19672  *     Create or replace an OAM group object
  19673  * Parameters:
  19674  *     unit       - (IN) BCM device number
  19675  *     group_info - (IN/OUT) Pointer to an OAM group information.
  19676  * Returns:
  19677  *     BCM_E_XXX
  19678  */
  19679 int
  19680 bcm_sb2_oam_group_create(int unit, bcm_oam_group_info_t *group_info)
  19681 {
  19682     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
  19683     uint8                  grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */
  19684                                                  /* name.                     */
  19685     maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table     */
  19686     _bcm_oam_group_data_t  *ma_group;            /* Pointer to group info.    */
  19687     _bcm_oam_control_t     *oc;                  /* OAM control structure.    */
  19688     int                    rv;                   /* Operation return status.  */
  19689                                                  /* entry.                    */
  19690     uint8                  sw_rdi;               /* Remote defect indicator.  */
  19691 
  19692 #if defined(BCM_SABER2_SUPPORT)  && defined(INCLUDE_BHH)
  19693     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
  19694     uint8 *buffer, *buffer_ptr;
  19695     uint16 buffer_len, reply_len;
  19696     uint32 session_flags = 0;
  19697     _bcm_oam_hash_data_t *h_data_p;
  19698     _bcm_oam_ep_list_t      *cur;
  19699 #endif
  19700 
  19701 
  19702     /* Validate input parameter. */
  19703     if (NULL == group_info) {
  19704         return (BCM_E_PARAM);
  19705     }
  19706 
  19707     /* Get OAM control structure handle. */
  19708     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  19709 
  19710     /* Validate group id. */
  19711     if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  19712         _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id);
  19713     }
  19714 
  19715     _BCM_OAM_LOCK(oc);
  19716 
  19717     /*
  19718      * If MA group create is called with replace flag bit set.
  19719      *  - Check and return error if a group does not exist with the ID.
  19720      */
  19721     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
  19722         if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  19723 
  19724             /* Search the list with the MA Group ID value. */
  19725             rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id);
  19726             if (BCM_E_EXISTS != rv) {
  19727                 _BCM_OAM_UNLOCK(oc);
  19728                 LOG_ERROR(BSL_LS_BCM_OAM,
  19729                           (BSL_META_U(unit,
  19730                                       "OAM(unit %d) Error: Group does not exist.\n"),
  19731                            unit));
  19732                 return (BCM_E_PARAM);
  19733             }
  19734         } else {
  19735             _BCM_OAM_UNLOCK(oc);
  19736             LOG_ERROR(BSL_LS_BCM_OAM,
  19737                       (BSL_META_U(unit,
  19738                                   "OAM(unit %d) Error: Replace command needs a "
  19739                                   "valid Group ID.\n"), unit));
  19740             return (BCM_E_PARAM);
  19741         }
  19742     } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
  19743         /*
  19744          * If MA group create is called with ID flag bit set.
  19745          *  - Check and return error if the ID is already in use.
  19746          */
  19747         rv = shr_idxres_list_reserve(oc->group_pool, group_info->id,
  19748                                      group_info->id);
  19749         if (BCM_FAILURE(rv)) {
  19750             _BCM_OAM_UNLOCK(oc);
  19751             return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
  19752         }
  19753     } else {
  19754         /* Reserve the next available group index. */
  19755          rv = shr_idxres_list_alloc(oc->group_pool,
  19756                                     (shr_idxres_element_t *) &group_info->id);
  19757         if (BCM_FAILURE(rv)) {
  19758             _BCM_OAM_UNLOCK(oc);
  19759             LOG_ERROR(BSL_LS_BCM_OAM,
  19760                       (BSL_META_U(unit,
  19761                                   "OAM(unit %d) Error: Group allocation (GID=%d)"
  19762                                    " %s\n"), unit, group_info->id, bcm_errmsg(rv)));
  19763             return (rv);
  19764         }
  19765     }
  19766 
  19767     /* Get this group memory to store group information. */
  19768     ma_group = &oc->group_info[group_info->id];
  19769 
  19770     /* Store the group name. */
  19771     sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH);
  19772 
  19773     /* Store Lowest Alarm Priority */
  19774     ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority;
  19775 
  19776     if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) {
  19777         _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *,
  19778                sizeof(_bcm_oam_ep_list_t *), "EP list head");
  19779 
  19780         /* Initialize head to NULL.*/
  19781         *ma_group->ep_list =  NULL;
  19782     }
  19783 
  19784     /*
  19785      * Maintenance Association ID - Reduction table update.
  19786      */
  19787 
  19788     /* Prepare group name for hardware write. */
  19789     _bcm_sb2_oam_group_name_mangle(ma_group->name, grp_name_hw_buf);
  19790 
  19791     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
  19792 
  19793     /* Calculate CRC32 value for the group name string and set in entry. */
  19794     soc_MAID_REDUCTIONm_field32_set
  19795         (unit, &maid_reduction_entry, REDUCED_MAIDf,
  19796          soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH));
  19797 
  19798     /* Check if software RDI flag bit needs to be set in hardware. */
  19799     sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0);
  19800 
  19801     /* Set RDI status for out going CCM PDUs. */
  19802     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf,
  19803                                     sw_rdi);
  19804 
  19805     if (soc_feature(unit, soc_feature_bhh)) {
  19806 #if defined(BCM_SABER2_SUPPORT)  && defined(INCLUDE_BHH)
  19807         /* Send message to uC to set the Soft RDI   */
  19808         if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 
  19809 
  19810             /* Get the endpoint list head pointer. */
  19811             cur = *(ma_group->ep_list);
  19812 
  19813             while (NULL != cur) {
  19814                 h_data_p = cur->ep_data_p;
  19815                 if (NULL == h_data_p) {
  19816                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  19817                         "OAM(unit %d) Error: Group=%d endpoints access failed -"
  19818                          " %s.\n"), unit, group_info->id, 
  19819                          bcm_errmsg(BCM_E_INTERNAL)));
  19820                     _BCM_OAM_UNLOCK(oc);
  19821                     return (BCM_E_INTERNAL);
  19822                 }
  19823                 if (h_data_p->oam_domain == _BCM_SB2_OAM_DOMAIN_BHH) {
  19824                     /* Set the RDI flag in session bits */
  19825                     session_flags |= SHR_BHH_SESS_SET_F_RDI;
  19826 
  19827                     /* Get the session is from endpoint */
  19828                     msg_sess.sess_id =
  19829                           BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
  19830                 
  19831                     /* Pack control message data into DMA buffer */
  19832                     msg_sess.flags = session_flags;
  19833 
  19834                     buffer     = oc->dma_buffer;
  19835                     buffer_ptr = 
  19836                         bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  19837                     buffer_len = buffer_ptr - buffer;
  19838 
  19839                     /* Send BHH Session Update message to uC */
  19840                     rv =  _bcm_sb2_oam_bhh_msg_send_receive(unit,
  19841                                          MOS_MSG_SUBCLASS_BHH_SESS_SET,
  19842                                          buffer_len, 0,
  19843                                          MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
  19844                                          &reply_len);
  19845                     if (BCM_FAILURE(rv)) {
  19846                         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  19847                                    "OAM(unit %d) Error: ukernel msg failed for"
  19848                                    "%s.\n"), unit, bcm_errmsg(rv)));
  19849                         _BCM_OAM_UNLOCK(oc);
  19850                         return (BCM_E_INTERNAL);
  19851                     }
  19852                 }
  19853                 cur = cur->next;
  19854             }    
  19855         }
  19856 #endif
  19857     }
  19858 
  19859     /* Enable hardware lookup for this entry. */
  19860     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1);
  19861 
  19862 
  19863     /* Write entry to hardware. */
  19864     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id,
  19865                                &maid_reduction_entry);
  19866     if (BCM_FAILURE(rv)) {
  19867         _BCM_OAM_UNLOCK(oc);
  19868         return rv;
  19869     }
  19870 
  19871     /*
  19872      * Maintenance Association State table update.
  19873      */
  19874     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
  19875 
  19876     /*
  19877      * If it is a group info replace operation, retain previous group
  19878      * defect status.
  19879      */
  19880     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
  19881         rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id,
  19882                             &ma_state_entry);
  19883         if (BCM_FAILURE(rv)) {
  19884             _BCM_OAM_UNLOCK(oc);
  19885             return rv;
  19886         }
  19887     }
  19888 
  19889     /* Set the lowest alarm priority info. */
  19890     soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
  19891                               group_info->lowest_alarm_priority);
  19892 
  19893     /* Mark the entry as valid. */
  19894     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1);
  19895 
  19896     /* Write group information to hardware table. */
  19897     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id,
  19898                                         &ma_state_entry);
  19899     if (BCM_FAILURE(rv)) {
  19900         _BCM_OAM_UNLOCK(oc);
  19901         return rv;
  19902     }
  19903 
  19904     /* Make the group as in used status. */
  19905     ma_group->in_use = 1;
  19906 
  19907     _BCM_OAM_UNLOCK(oc);
  19908 
  19909 #ifdef BCM_WARM_BOOT_SUPPORT
  19910     SOC_CONTROL_LOCK(unit);
  19911     SOC_CONTROL(unit)->scache_dirty = 1;
  19912     SOC_CONTROL_UNLOCK(unit);
  19913 #endif
  19914     return BCM_E_NONE;
  19915 }
  19916 
  19917 /*
  19918  * Function:
  19919  *     bcm_sb2_oam_group_get
  19920  * Purpose:
  19921  *     Get an OAM group object
  19922  * Parameters:
  19923  *     unit       - (IN) BCM device number
  19924  *     group      - (IN) OAM Group ID.
  19925  *     group_info - (OUT) Pointer to group information buffer.
  19926  * Returns:
  19927  *      BCM_E_XXX
  19928  */
  19929 int
  19930 bcm_sb2_oam_group_get(int unit, bcm_oam_group_t group,
  19931                       bcm_oam_group_info_t *group_info)
  19932 {
  19933     _bcm_oam_control_t    *oc;      /* Pointer to OAM control structure. */
  19934     _bcm_oam_group_data_t *group_p; /* Pointer to group list.            */
  19935     int                   rv;       /* Operation return status.          */
  19936 
  19937 #if defined(INCLUDE_BHH)
  19938     bhh_sdk_msg_ctrl_sess_get_t msg;
  19939     uint8 *buffer, *buffer_ptr;
  19940     uint16 buffer_len, reply_len;
  19941     _bcm_oam_hash_data_t *h_data_p;
  19942     _bcm_oam_ep_list_t      *cur = NULL;
  19943     int sess_id = 0;
  19944 #endif
  19945 
  19946     /* Validate input parameter. */
  19947     if (NULL == group_info) {
  19948         return (BCM_E_PARAM);
  19949     }
  19950 
  19951     /* Get OAM device control structure. */
  19952     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  19953 
  19954     /* Validate group index. */
  19955     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  19956 
  19957     _BCM_OAM_LOCK(oc);
  19958 
  19959     /* Check if the group is in use. */
  19960     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  19961     if (BCM_E_EXISTS != rv) {
  19962         _BCM_OAM_UNLOCK(oc);
  19963         LOG_ERROR(BSL_LS_BCM_OAM,
  19964                   (BSL_META_U(unit,
  19965                               "OAM(unit %d) Error: GID=%d - %s.\n"),
  19966                    unit, group, bcm_errmsg(rv)));
  19967         return (rv);
  19968     }
  19969 
  19970     /* Get pointer to this group in the group list. */
  19971     group_p = oc->group_info;
  19972 
  19973     /* Get the group information. */
  19974     rv = _bcm_sb2_oam_get_group(unit, group, group_p, group_info);
  19975     if (BCM_FAILURE(rv)) {
  19976         _BCM_OAM_UNLOCK(oc);
  19977         LOG_ERROR(BSL_LS_BCM_OAM,
  19978                   (BSL_META_U(unit,
  19979                               "OAM(unit %d) Error: bcm_sb2_oam_group_get Group ID=%d "
  19980                                "- Failed.\n"), unit, group));
  19981         return (rv);
  19982     }
  19983 
  19984     if (soc_feature(unit, soc_feature_bhh)) {
  19985 #if defined(INCLUDE_BHH)
  19986         if (!oc->ukernel_not_ready) {
  19987             group_p = &oc->group_info[group_info->id];
  19988             /* Get the endpoint list head pointer. */
  19989             if (group_p->ep_list != NULL) {
  19990                 cur = *(group_p->ep_list);
  19991             }
  19992 
  19993             while (NULL != cur) {
  19994                 h_data_p = cur->ep_data_p;
  19995                 if (NULL == h_data_p) {
  19996                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  19997                                                           "OAM(unit %d) Error: Group=%d endpoints access failed -"
  19998                                                           " %s.\n"), unit, group_info->id,
  19999                                                bcm_errmsg(BCM_E_INTERNAL)));
  20000                     _BCM_OAM_UNLOCK(oc);
  20001                     return (BCM_E_INTERNAL);
  20002                 }
  20003                 if ((h_data_p->oam_domain == _BCM_SB2_OAM_DOMAIN_BHH) &&
  20004                     !(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  20005                     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
  20006                     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  20007                                              MOS_MSG_SUBCLASS_BHH_SESS_GET,
  20008                                              sess_id, 0,
  20009                                              MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  20010                                              &reply_len);
  20011                     if (BCM_FAILURE(rv)) {
  20012                         LOG_ERROR(BSL_LS_BCM_OAM,
  20013                                   (BSL_META_U(unit,
  20014                                   "OAM(unit %d) Error: ukernel msg failed for"
  20015                                   " EP=%d %s.\n"), unit, h_data_p->ep_id,
  20016                                    bcm_errmsg(rv)));
  20017                         _BCM_OAM_UNLOCK(oc);
  20018                         return (rv);
  20019                     }
  20020 
  20021                     /* Pack control message data into DMA buffer */
  20022                     buffer = oc->dma_buffer;
  20023                     buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  20024                     buffer_len = buffer_ptr - buffer;
  20025 
  20026                     if (reply_len != buffer_len) {
  20027                         rv = BCM_E_INTERNAL;
  20028                         LOG_ERROR(BSL_LS_BCM_OAM,
  20029                                   (BSL_META_U(unit,
  20030                                   "OAM(unit %d) Error: ukernel msg failed for"
  20031                                   " EP=%d %s.\n"), unit, h_data_p->ep_id,
  20032                                    bcm_errmsg(rv)));
  20033                         _BCM_OAM_UNLOCK(oc);
  20034                         return (rv);
  20035                     } else {
  20036                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
  20037                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  20038                         }
  20039                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
  20040                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  20041                         }
  20042                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  20043                             group_info->faults |=
  20044                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  20045                         }
  20046                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  20047                             group_info->faults |=
  20048                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  20049                         }
  20050                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  20051                             group_info->faults |=
  20052                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  20053                         }
  20054                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  20055                             group_info->faults |=
  20056                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  20057                         }
  20058                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  20059                             group_info->faults |=
  20060                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  20061                         }
  20062                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
  20063                             group_info->faults |=
  20064                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
  20065                         }
  20066                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
  20067                             group_info->faults |=
  20068                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
  20069                         }
  20070                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
  20071                             group_info->faults |=
  20072                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
  20073                         }
  20074                     }
  20075                 }
  20076                 cur = cur->next;
  20077             }
  20078         }
  20079 #endif
  20080     }
  20081 
  20082     _BCM_OAM_UNLOCK(oc);
  20083     return (BCM_E_NONE);
  20084 }
  20085 
  20086 /*
  20087  * Function:
  20088  *     bcm_sb2_oam_group_destroy
  20089  * Purpose:
  20090  *     Destroy an OAM group object and its associated endpoints.
  20091  * Parameters:
  20092  *     unit  - (IN) BCM device number
  20093  *     group - (IN) The ID of the OAM group object to destroy
  20094  * Returns:
  20095  *     BCM_E_XXX
  20096  */
  20097 int
  20098 bcm_sb2_oam_group_destroy(int unit,
  20099                           bcm_oam_group_t group)
  20100 {
  20101     _bcm_oam_control_t     *oc;       /* Pointer to OAM control structure. */
  20102     _bcm_oam_group_data_t  *g_info_p; /* Pointer to group list.            */
  20103     int                    rv;        /* Operation return status.          */
  20104     maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry.  */
  20105     ma_state_entry_t       ma_state_entry; /* MA_STATE table entry.        */
  20106 
  20107     /* Get OAM device control structure. */
  20108     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20109 
  20110     /* Validate group index. */
  20111     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  20112 
  20113     _BCM_OAM_LOCK(oc);
  20114 
  20115     /* Check if the group is in use. */
  20116     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  20117     if (BCM_E_EXISTS != rv) {
  20118         _BCM_OAM_UNLOCK(oc);
  20119         LOG_ERROR(BSL_LS_BCM_OAM,
  20120                   (BSL_META_U(unit,
  20121                               "OAM(unit %d) Error: GID=%d - %s.\n"),
  20122                    unit, group, bcm_errmsg(rv)));
  20123         return (rv);
  20124     }
  20125 
  20126     /* Get pointer to this group in the group list. */
  20127     g_info_p = &oc->group_info[group];
  20128 
  20129     rv = _bcm_sb2_oam_group_endpoints_destroy(unit, g_info_p);
  20130     if (BCM_FAILURE(rv)) {
  20131         _BCM_OAM_UNLOCK(oc);
  20132         LOG_ERROR(BSL_LS_BCM_OAM,
  20133                   (BSL_META_U(unit,
  20134                               "OAM(unit %d) Error: bcm_sb2_oam_endpoint_destroy_all"
  20135                                " (GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv)));
  20136         return (rv);
  20137     }
  20138 
  20139     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
  20140     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group,
  20141                           &maid_reduction_entry);
  20142     if (BCM_FAILURE(rv)) {
  20143         _BCM_OAM_UNLOCK(oc);
  20144         LOG_DEBUG(BSL_LS_BCM_OAM,
  20145                   (BSL_META_U(unit,
  20146                               "OAM(unit %d) Error: MAID REDUCTION write "
  20147                                "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv)));
  20148         return (rv);
  20149     }
  20150 
  20151     /*
  20152      * Maintenance Association State table update.
  20153      */
  20154     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
  20155 
  20156     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry);
  20157     if (BCM_FAILURE(rv)) {
  20158         _BCM_OAM_UNLOCK(oc);
  20159         LOG_ERROR(BSL_LS_BCM_OAM,
  20160                   (BSL_META_U(unit,
  20161                               "OAM(unit %d) Error: MA STATE write "
  20162                                "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv)));
  20163         return (rv);
  20164     }
  20165 
  20166     /* Return Group ID back to free group. */
  20167     rv = shr_idxres_list_free(oc->group_pool, group);
  20168     if (BCM_FAILURE(rv)) {
  20169         _BCM_OAM_UNLOCK(oc);
  20170         return (rv);
  20171     }
  20172 
  20173 #ifdef BCM_WARM_BOOT_SUPPORT
  20174     SOC_CONTROL_LOCK(unit);
  20175     SOC_CONTROL(unit)->scache_dirty = 1;
  20176     SOC_CONTROL_UNLOCK(unit);
  20177 #endif
  20178     _BCM_OAM_UNLOCK(oc);
  20179     return (BCM_E_NONE);
  20180 }
  20181 
  20182 /*
  20183  * Function:
  20184  *     bcm_sb2_oam_group_destroy_all
  20185  * Purpose:
  20186  *     Destroy all OAM group objects and their associated endpoints.
  20187  * Parameters:
  20188  *     unit  - (IN) BCM device number
  20189  * Returns:
  20190  *     BCM_E_XXX
  20191  */
  20192 int
  20193 bcm_sb2_oam_group_destroy_all(int unit)
  20194 {
  20195     _bcm_oam_control_t *oc;   /* Pointer to OAM control structure.    */
  20196     int                group; /* Maintenance Association group index. */
  20197     int                rv;    /* Operation return status .            */
  20198 
  20199     /* Get device OAM control structure handle. */
  20200     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20201 
  20202     _BCM_OAM_LOCK(oc);
  20203     for (group = 0; group < oc->group_count; group++) {
  20204 
  20205         /* Check if the group is in use. */
  20206         rv = shr_idxres_list_elem_state(oc->group_pool, group);
  20207         if (BCM_E_EXISTS != rv) {
  20208             continue;
  20209         }
  20210 
  20211         rv = bcm_sb2_oam_group_destroy(unit, group);
  20212         if (BCM_FAILURE(rv)) {
  20213             _BCM_OAM_UNLOCK(oc);
  20214             LOG_ERROR(BSL_LS_BCM_OAM,
  20215                       (BSL_META_U(unit,
  20216                                   "OAM(unit %d) Error: Group destroy failed "
  20217                                    "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv)));
  20218             return (rv);
  20219         }
  20220     }
  20221 
  20222 #ifdef BCM_WARM_BOOT_SUPPORT
  20223     SOC_CONTROL_LOCK(unit);                                      
  20224     SOC_CONTROL(unit)->scache_dirty = 1;
  20225     SOC_CONTROL_UNLOCK(unit);
  20226 #endif
  20227 
  20228     _BCM_OAM_UNLOCK(oc);
  20229     return (BCM_E_NONE);
  20230 }
  20231 
  20232 /*
  20233  * Function:
  20234  *     bcm_sb2_oam_group_traverse
  20235  * Purpose:
  20236  *     Traverse the entire set of OAM groups, calling a specified
  20237  *     callback for each one
  20238  * Parameters:
  20239  *     unit  - (IN) BCM device number
  20240  *     cb        - (IN) Pointer to call back function.
  20241  *     user_data - (IN) Pointer to user supplied data.
  20242  * Returns:
  20243  *     BCM_E_XXX
  20244  */
  20245 int
  20246 bcm_sb2_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
  20247                            void *user_data)
  20248 {
  20249     _bcm_oam_control_t    *oc;        /* OAM control structure pointer. */
  20250     bcm_oam_group_info_t  group_info; /* Group information to be set.   */
  20251     bcm_oam_group_t       grp_idx;    /* MA Group index.                */
  20252     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
  20253     int                   rv;         /* Operation return status.       */
  20254 
  20255     if (NULL == cb) {
  20256         return (BCM_E_PARAM);
  20257     }
  20258 
  20259     /* Get device OAM control structure handle. */
  20260     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20261 
  20262     _BCM_OAM_LOCK(oc);
  20263 
  20264     /* Initialize to group array pointer. */
  20265     group_p = oc->group_info;
  20266 
  20267     for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
  20268 
  20269         /* Check if the group is in use. */
  20270         if (BCM_E_EXISTS
  20271             == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
  20272 
  20273             /* Initialize the group information structure. */
  20274             bcm_oam_group_info_t_init(&group_info);
  20275 
  20276             /* Retrieve group information and set in group_info structure. */
  20277             rv = _bcm_sb2_oam_get_group(unit, grp_idx, group_p, &group_info);
  20278             if (BCM_FAILURE(rv)) {
  20279                 _BCM_OAM_UNLOCK(oc);
  20280                 LOG_ERROR(BSL_LS_BCM_OAM,
  20281                           (BSL_META_U(unit,
  20282                                       "OAM(unit %d) Error: _bcm_sb2_oam_get_group "
  20283                                        "(GID=%d) - %s.\n"), unit, grp_idx, bcm_errmsg(rv)));
  20284                 return (rv);
  20285             }
  20286 
  20287             /* Call the user call back routine with group information. */
  20288             rv = cb(unit, &group_info, user_data);
  20289             if (BCM_FAILURE(rv)) {
  20290                 _BCM_OAM_UNLOCK(oc);
  20291                 LOG_ERROR(BSL_LS_BCM_OAM,
  20292                           (BSL_META_U(unit,
  20293                                       "OAM(unit %d) Error: User call back routine "
  20294                                        "(GID=%d) - %s.\n"), unit, grp_idx, bcm_errmsg(rv)));
  20295                 return (rv);
  20296             }
  20297         }
  20298     }
  20299 
  20300     _BCM_OAM_UNLOCK(oc);
  20301 
  20302     return BCM_E_NONE;
  20303 }
  20304 
  20305 int
  20306 _bcm_sb2_oam_mpls_lsp_label_l3_tunnel_entry_get(int unit, 
  20307                                                 _bcm_oam_hash_data_t *hash_data,
  20308                                                 soc_tunnel_term_t *tnl_entry)
  20309 {
  20310 #if defined(INCLUDE_L3)
  20311     soc_tunnel_term_t tnl_key;
  20312     bcm_mpls_tunnel_switch_t tnl_info;
  20313     int rv = BCM_E_NONE;
  20314     int index;
  20315 
  20316     sal_memset(&tnl_key, 0, sizeof(tnl_key));
  20317     sal_memset(&tnl_info, 0, sizeof(tnl_info));
  20318     
  20319     /* Forming key only based on label */
  20320     if (bcm_tr_mpls_port_independent_range(unit, hash_data->label,
  20321                 BCM_GPORT_INVALID) != BCM_E_NONE) {
  20322         /* Use Gport as the port if label is port dependent */
  20323         tnl_info.port = hash_data->gport;
  20324     } else {
  20325         /* Port is invalid if label is port independent. */
  20326         tnl_info.port = BCM_GPORT_INVALID;
  20327     }
  20328     tnl_info.label = hash_data->label;
  20329 
  20330     /* Setup TCAM key */
  20331     rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(unit, &tnl_info, &tnl_key);
  20332     BCM_IF_ERROR_RETURN(rv);
  20333 
  20334     /* Find tunnel terminator in TCAM. */
  20335     BCM_IF_ERROR_RETURN(soc_tunnel_term_match(unit, &tnl_key, tnl_entry, &index));
  20336     return BCM_E_NONE;
  20337 #endif
  20338     return BCM_E_UNAVAIL;
  20339 }
  20340 
  20341 int
  20342 _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(int unit, 
  20343                                             _bcm_oam_hash_data_t *hash_data, int enable)
  20344 {
  20345 #if defined(INCLUDE_L3)
  20346     soc_tunnel_term_t tnl_entry;
  20347     uint32 tnl_index = 0;
  20348     int rv = BCM_E_NONE;
  20349 
  20350     sal_memset(&tnl_entry, 0, sizeof(tnl_entry));
  20351 
  20352     rv = _bcm_sb2_oam_mpls_lsp_label_l3_tunnel_entry_get(unit, hash_data,
  20353                                                          &tnl_entry);
  20354     if (BCM_FAILURE(rv)) {
  20355         return rv;
  20356     }
  20357 
  20358     if (BHH_EP_TYPE(hash_data)) {
  20359         soc_L3_TUNNELm_field32_set(unit, &tnl_entry, MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  20360                 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0);
  20361     } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) {
  20362         soc_L3_TUNNELm_field32_set(unit, &tnl_entry, MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  20363                 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0);
  20364     } else {
  20365         return BCM_E_PARAM;
  20366     }
  20367 
  20368     /* Add tunnel terminator in TCAM. It will update the entry if it is already 
  20369        present. which is our case. */
  20370     rv = soc_tunnel_term_insert(unit, &tnl_entry, &tnl_index);
  20371     return rv;
  20372 #endif
  20373     return BCM_E_UNAVAIL;
  20374 }
  20375 
  20376 int
  20377 _bcm_sb2_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label,
  20378                                      uint32 sglp, int *mpls_index,
  20379                                      mpls_entry_entry_t *found_entry)
  20380 {
  20381 #if defined(INCLUDE_L3)
  20382     mpls_entry_entry_t mpls_key_entry;
  20383     int rv = BCM_E_NONE;
  20384 
  20385     sal_memset(&mpls_key_entry, 0, sizeof(mpls_key_entry));
  20386 
  20387     soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, MPLS_LABELf, label);
  20388     soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, VALIDf, 1);
  20389     if (bcm_tr_mpls_port_independent_range(unit, label,
  20390         BCM_GPORT_INVALID) != BCM_E_NONE)
  20391     {
  20392         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, PORT_NUMf, sglp);
  20393     }
  20394     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
  20395     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, mpls_index, 
  20396                         &mpls_key_entry, found_entry, 0);
  20397     bcm_tr_mpls_unlock(unit);
  20398 
  20399     return rv;
  20400 #endif /* INCLUDE_L3 */
  20401     return BCM_E_UNAVAIL;
  20402 }
  20403 
  20404 int
  20405 _bcm_sb2_oam_mpls_lmdm_pw_svp_get(int unit, bcm_mpls_label_t label,
  20406                                   uint32 sglp,
  20407                                   uint32 *svp)
  20408 {
  20409     mpls_entry_entry_t mpls_entry;
  20410     int rv = BCM_E_NONE;
  20411     int mpls_index = -1;
  20412 
  20413     sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
  20414 
  20415     /* Lookup for the PW label */
  20416     rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, label, sglp,
  20417                                                  &mpls_index, 
  20418                                                  &mpls_entry);
  20419     if(rv != BCM_E_NONE) {
  20420         /* Not found or some other error */
  20421         LOG_ERROR(BSL_LS_BCM_OAM,
  20422                 (BSL_META_U(unit,
  20423                             "OAM(unit %d) Error: (Label=%u) - %s.\n"),
  20424                  unit, label, bcm_errmsg(rv)));
  20425         return rv;
  20426     }
  20427 
  20428     /* Return error if not valid */
  20429     if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 0x1)) {
  20430         return (BCM_E_PARAM);
  20431     }
  20432 
  20433     *svp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf);
  20434 
  20435     return BCM_E_NONE;
  20436 }
  20437 
  20438 int
  20439 _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(int unit,
  20440                              _bcm_oam_hash_data_t *hash_data, int enable)
  20441 {
  20442 #if defined(INCLUDE_L3)
  20443     int egr_nh_index = 0;
  20444     egr_l3_next_hop_entry_t egr_nh_entry;
  20445     int rv = BCM_E_NONE;
  20446     _bcm_oam_control_t   *oc;
  20447 #if defined(INCLUDE_BHH)
  20448     uint16  bhh_lsp_key;
  20449 #endif /* INCLUDE_BHH */
  20450 
  20451     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20452 
  20453     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  20454 
  20455     /* Enable MPLS OAM in the EGR_L3_NEXT_HOP table */
  20456     if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, hash_data->egress_if)) {
  20457         egr_nh_index = hash_data->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  20458     }
  20459     else {
  20460         egr_nh_index = hash_data->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
  20461     }
  20462 
  20463     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 
  20464             egr_nh_index, &egr_nh_entry);
  20465     if (BCM_FAILURE(rv)) {
  20466         return (rv);
  20467     }
  20468 
  20469     if (BHH_EP_TYPE(hash_data)) {
  20470 #if defined(INCLUDE_BHH)
  20471         bhh_lsp_key = enable ? BCM_OAM_BHH_GET_LSP_KEY(hash_data) : 0;
  20472         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  20473                                          MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  20474                                          enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0);
  20475 
  20476         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  20477                                          MPLS__MEPIDf,
  20478                                          bhh_lsp_key);
  20479 #endif /* INCLUDE_BHH */
  20480     } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) {
  20481         soc_EGR_L3_NEXT_HOPm_field32_set(
  20482                                 unit, &egr_nh_entry,
  20483                                 MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  20484                                 enable ? _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM : 0);
  20485 
  20486         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  20487                                          MPLS__MEPIDf,
  20488                                          enable ? hash_data->name : 0);
  20489     } else {
  20490         return BCM_E_PARAM;
  20491     }
  20492 
  20493 
  20494     rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL,
  20495             egr_nh_index, &egr_nh_entry);
  20496     if (BCM_FAILURE(rv)) {
  20497         return (rv);
  20498     }
  20499 
  20500     return BCM_E_NONE;
  20501 #endif /* INCLUDE_L3 */
  20502     return BCM_E_UNAVAIL;
  20503 }
  20504 
  20505 int
  20506 _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable)
  20507 {
  20508     int vp = -1;
  20509     egr_dvp_attribute_entry_t entry;
  20510     
  20511     sal_memset(&entry, 0, sizeof(entry));
  20512 
  20513     vp = BCM_GPORT_MPLS_PORT_ID_GET(hash_data->gport);
  20514 
  20515     if (vp == -1) {
  20516         return BCM_E_PARAM;
  20517     }
  20518 
  20519     BCM_IF_ERROR_RETURN(READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &entry));
  20520     if (BHH_EP_TYPE(hash_data)) {
  20521         soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20522                 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0);
  20523     } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) {
  20524         soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20525                 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0);
  20526     } else {
  20527         return BCM_E_PARAM;
  20528     }
  20529     BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &entry));
  20530 
  20531     return BCM_E_NONE;
  20532 }
  20533 
  20534 int 
  20535 _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable)
  20536 {
  20537 #if defined(INCLUDE_L3)
  20538     mpls_entry_entry_t mpls_entry;
  20539     int rv = BCM_E_NONE;
  20540     int mpls_index = -1;
  20541     int vccv_type = 0;
  20542 
  20543     sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
  20544 
  20545     /* Lookup for the LSP label */
  20546     rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, hash_data->label,
  20547                                                  hash_data->sglp,
  20548                                                  &mpls_index, 
  20549                                                  &mpls_entry);
  20550     if (rv != BCM_E_NONE) {
  20551         /* Not found or some other error */
  20552         if ((BCM_E_NOT_FOUND == rv) && (!enable)) {
  20553             LOG_VERBOSE(BSL_LS_BCM_OAM,
  20554                     (BSL_META_U(unit,
  20555                                 "OAM(unit %d) Error: (EP=%d) - %s.\n"),
  20556                      unit, hash_data->ep_id, bcm_errmsg(rv)));
  20557         } else {
  20558             LOG_ERROR(BSL_LS_BCM_OAM,
  20559                     (BSL_META_U(unit,
  20560                                 "OAM(unit %d) Error: (EP=%d) - %s.\n"),
  20561                      unit, hash_data->ep_id, bcm_errmsg(rv)));
  20562         }
  20563         return rv;
  20564     }
  20565 
  20566     /* Return error if not valid */
  20567     if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 0x1)) {
  20568         return (BCM_E_PARAM);
  20569     }
  20570 
  20571     if (BHH_EP_TYPE(hash_data)) {
  20572         /* Enable/Disable BHH on this label */
  20573         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20574                 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0);
  20575     } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) {
  20576         /* Enable/Disable MPLS LMDM on this label */
  20577         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20578                 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0);
  20579     } else {
  20580         return BCM_E_PARAM;
  20581     }
  20582 
  20583     if (hash_data->type == bcmOAMEndpointTypeBHHMPLSVccv ||
  20584         hash_data->type == bcmOAMEndpointTypeMplsLmDmPw) {
  20585 
  20586         /* Get the control channel type */
  20587         vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf);
  20588         if (vccv_type == 0) { /* No VCCV type configured */
  20589             soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, PW_CC_TYPEf,
  20590                                         (hash_data->vccv_type + 1));
  20591         } else if (vccv_type != (hash_data->vccv_type + 1)) {
  20592             /* Endpoint add configuration conflicts with MPLS port add config */
  20593             return BCM_E_PARAM;
  20594         }
  20595     }
  20596 
  20597     /* Write the MPLS entry back into the hw */
  20598     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
  20599     rv = WRITE_MPLS_ENTRYm(unit, MEM_BLOCK_ALL, mpls_index, &mpls_entry);
  20600     bcm_tr_mpls_unlock(unit);
  20601     
  20602     return rv;
  20603 #endif /* INCLUDE_L3 */
  20604     return BCM_E_UNAVAIL;
  20605 }
  20606 
  20607 int 
  20608 _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable)
  20609 {
  20610 #if defined(INCLUDE_L3)
  20611     mpls_entry_entry_t mpls_entry;
  20612     int rv = BCM_E_NONE;
  20613     int mpls_index = -1;
  20614     source_vp_entry_t svp_entry;
  20615     int svp = 0, vccv_type = 0;
  20616     
  20617     sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
  20618     /* Lookup for PW label */
  20619     rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, hash_data->label,
  20620                                               hash_data->sglp,
  20621                                               &mpls_index,
  20622                                               &mpls_entry);
  20623     
  20624     /* If this is called during de-init,  and error is not found, do not print it.
  20625      * MPLS module de-init happens before OAM de-init.
  20626      */
  20627 
  20628     if(rv != BCM_E_NONE) {
  20629         /* Not found or some other error */
  20630         if ((rv != BCM_E_NOT_FOUND) || (enable)) {
  20631             LOG_ERROR(BSL_LS_BCM_OAM,
  20632                     (BSL_META_U(unit,
  20633                                 "OAM(unit %d) Error: (EP=%d) - %s.\n"),
  20634                      unit, hash_data->ep_id, bcm_errmsg(rv)));
  20635         }
  20636             return rv;
  20637     }
  20638     
  20639     /* Return error if not valid */
  20640     if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 1)) {
  20641         return (BCM_E_PARAM);
  20642     }
  20643     
  20644     /* Get the source vp table index */
  20645     svp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf);
  20646     
  20647     /* Get the control channel type */
  20648     vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf);
  20649 
  20650     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
  20651 
  20652 
  20653     if (vccv_type == 0) { /* No VCCV type configured */
  20654         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, PW_CC_TYPEf,
  20655                                     (hash_data->vccv_type + 1));
  20656 
  20657     } else if (vccv_type != (hash_data->vccv_type + 1)) {
  20658         /* Endpoint add configuration conflicts with MPLS port add config */
  20659         bcm_tr_mpls_unlock(unit);
  20660         return BCM_E_PARAM;
  20661     }
  20662 
  20663 
  20664     if(hash_data->vccv_type == bcmOamBhhVccvGal13) {
  20665         /* vccv type 4. GAL over PW. */
  20666         /* So it is not bottom of the stack. so set MPLS_ACTION_IF_NOT_BOS 
  20667            to 5 (POP_SVP) */
  20668         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_ACTION_IF_NOT_BOSf,
  20669                                     enable?5:0);
  20670     }
  20671 
  20672     /* Write the MPLS entry back into the hw */
  20673     rv = WRITE_MPLS_ENTRYm(unit, MEM_BLOCK_ALL, mpls_index,
  20674                            &mpls_entry);
  20675     if (rv != SOC_E_NONE) {
  20676         bcm_tr_mpls_unlock(unit);
  20677         return rv;
  20678     }
  20679 
  20680     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, svp, &svp_entry);
  20681 
  20682     if (rv < 0) {
  20683         bcm_tr_mpls_unlock(unit);
  20684         return rv;
  20685     }
  20686     
  20687     if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) {
  20688         /* Enable MPLS LMDM on this label */
  20689         soc_SOURCE_VPm_field32_set(unit, &svp_entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20690                 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0);
  20691     } else if (BHH_EP_TYPE(hash_data)) {
  20692         soc_SOURCE_VPm_field32_set(unit, &svp_entry, MPLS_OAM_DOWNMEP_ENABLEf,
  20693                 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0);
  20694     } else {
  20695         bcm_tr_mpls_unlock(unit);
  20696         return BCM_E_PARAM;
  20697     }
  20698 
  20699  
  20700     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, svp, &svp_entry); 
  20701 
  20702     if (rv < 0) {
  20703         bcm_tr_mpls_unlock(unit);
  20704         return rv;
  20705     }
  20706 
  20707     bcm_tr_mpls_unlock(unit);
  20708     
  20709     return BCM_E_NONE;
  20710 #endif /* INCLUDE_L3 */
  20711     return BCM_E_UNAVAIL;
  20712 }
  20713 
  20714 /*
  20715  * Function:
  20716  *      bcm_sb2_oam_hw_ccm_tx_ctr_update
  20717  * Purpose:
  20718  *      Update CCM CTR params
  20719  * Parameters:
  20720  *      unit - (IN) Unit number.
  20721  *      ep_info - (IN) Pointer to endpoint parameters
  20722  * Returns:
  20723  *      BCM_E_XXX
  20724  * Notes:
  20725  */
  20726 STATIC int
  20727 bcm_sb2_oam_hw_ccm_tx_ctr_update(int unit,
  20728         bcm_oam_endpoint_info_t *ep_info) 
  20729 {
  20730 
  20731     _bcm_oam_hash_data_t        *h_data_p;
  20732     _bcm_oam_control_t          *oc;
  20733     int                         rv=BCM_E_NONE;      
  20734     lmep_1_entry_t              lmep_1_entry;    /* LMEP_1 table entry.*/
  20735     uint8                       num_counter;
  20736     uint32                      counter_id;
  20737     uint32                      pool;
  20738 
  20739     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20740 
  20741     h_data_p =  &oc->oam_hash_data[ep_info->id];
  20742 
  20743     /* Get the LMEP_1 table entry. for the endpoint*/
  20744     rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry);
  20745     if (BCM_FAILURE(rv)) {
  20746         LOG_ERROR(BSL_LS_BCM_OAM,
  20747                 (BSL_META_U(unit,
  20748                             "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed "
  20749                             "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv)));
  20750         return rv;
  20751     }
  20752     
  20753     if (_SB2_OAM_COUNTER_SIZE < ep_info->ccm_tx_update_lm_counter_size) {
  20754         return BCM_E_PARAM;
  20755     }
  20756 
  20757     for(num_counter = 0; num_counter < ep_info->ccm_tx_update_lm_counter_size;
  20758             num_counter++) {
  20759 
  20760         /* Get the counter pool id */
  20761         counter_id = ep_info->ccm_tx_update_lm_counter_base_id[num_counter] + 
  20762             ep_info->ccm_tx_update_lm_counter_offset[num_counter];
  20763         pool = counter_id >> 24;
  20764 
  20765         switch(pool){
  20766             case 0:
  20767                 /* Set Counter 1 ID and action */
  20768                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_IDf, 
  20769                         (counter_id & 0xFFFF));
  20770                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_ACTIONf, 1);
  20771                 break;
  20772             case 1:
  20773                 /* Set Counter 2 ID and action */
  20774                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_IDf, 
  20775                         (counter_id & 0xFFFF));
  20776                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_ACTIONf, 1);
  20777                 break;
  20778             case 2:
  20779                 /* Set Counter 3 ID and action */
  20780                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_IDf, 
  20781                         (counter_id & 0xFFFF));
  20782                 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_ACTIONf, 1);
  20783                 break;
  20784             default:
  20785                 return BCM_E_PARAM;
  20786         }
  20787 
  20788         if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  20789             /* TX counter is located in IP (0) */
  20790             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_LOCATIONf, 0); 
  20791             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_LOCATIONf, 0); 
  20792             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_LOCATIONf, 0); 
  20793         } else {
  20794             /* TX counter is located in EP (1) */
  20795             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_LOCATIONf, 1); 
  20796             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_LOCATIONf, 1); 
  20797             soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_LOCATIONf, 1); 
  20798         } 
  20799     }
  20800     
  20801     rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
  20802             &lmep_1_entry);
  20803     if (BCM_FAILURE(rv)) {
  20804         LOG_ERROR(BSL_LS_BCM_OAM,
  20805                 (BSL_META_U(unit,
  20806                             "OAM(unit %d) Error: LMEP_1 table write (EP=%d)"
  20807                             " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv)));
  20808         return rv;
  20809     }
  20810 
  20811     return rv;
  20812 }
  20813 
  20814 /*
  20815  * Function:
  20816  *     bcm_sb2_oam_endpoint_lm_update
  20817  * Purpose:
  20818  *     Update LM related params of an endpoint
  20819  * Parameters:
  20820  *     unit          - (IN) BCM device number
  20821  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  20822  * Returns:
  20823  *      BCM_E_XXX
  20824  */
  20825 STATIC int
  20826 bcm_sb2_oam_endpoint_lm_update(int unit, bcm_oam_endpoint_info_t *ep_info)
  20827 {
  20828     _bcm_oam_hash_data_t         *h_data_p;
  20829     _bcm_oam_control_t           *oc;
  20830     int                           loss_add, loss_del;
  20831     int                           loss_configured;
  20832     soc_mem_t                     mems[2] = {INVALIDm, INVALIDm};
  20833     uint32                        lm_payload_offset = -1;
  20834     uint32                        lm_cos_offset = -1;
  20835     bcm_oam_lm_counter_type_t     lm_ctr_type = bcmOamLmCounterTypeCount;
  20836     bcm_oam_lm_counter_size_t     lm_ctr_sample_size = bcmOamLmCounterSizeCount;
  20837     int                           lm_ctr_pool_id = -1;
  20838     int                           mem_index;
  20839     int                           ctr_field_id = -1;
  20840     ing_oam_lm_counters_0_entry_t lm_entry;
  20841     egr_mp_group_entry_t          egr_mp_group;
  20842     mp_group_entry_t              mp_group_entry;
  20843 
  20844     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  20845 
  20846     if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  20847         /* Only LMEPs can update Loss parameters */
  20848         return BCM_E_PARAM;
  20849     }
  20850 
  20851     if (ep_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) {
  20852         /* Only MEPs can update LM */
  20853         return BCM_E_PARAM;
  20854     }
  20855 
  20856     /* Validate endpoint index value. */
  20857     _BCM_OAM_EP_INDEX_VALIDATE(ep_info->id);
  20858 
  20859     h_data_p =  &oc->oam_hash_data[ep_info->id];
  20860     if (0 == h_data_p->in_use) {
  20861         return BCM_E_NOT_FOUND;
  20862     }
  20863 
  20864     /* Figure out if loss is being added or deleted */
  20865     loss_add = loss_del = 0;
  20866     loss_configured = 1; /* Indicates if BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is
  20867                           * present in new & old config
  20868                           */
  20869     if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  20870         if (!(ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
  20871             loss_del = 1;
  20872         }
  20873     } else {
  20874         if (ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  20875             loss_add = 1;
  20876         } else {
  20877             /* BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is not present in old/new
  20878              * config.
  20879              */
  20880             loss_configured = 0;
  20881         }
  20882     }
  20883 
  20884     /* If loss configuration is present in either old & new configuration, then
  20885      * find out if something is being modified in loss, updates will result in
  20886      * delete and add.
  20887      */
  20888     if (1 == loss_configured && 0 == loss_add && 0 == loss_del) {
  20889 
  20890         lm_ctr_pool_id = (h_data_p->rx_ctr >> 24) & 0xFF;
  20891         if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info)) {
  20892             ctr_field_id = h_data_p->egr_ctr_field_id;
  20893             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p,
  20894                                                            &mem_index,
  20895                                                            &egr_mp_group));
  20896             BCM_IF_ERROR_RETURN(
  20897                       _bcm_sb2_oam_lm_counters_mems_from_pool_get(lm_ctr_pool_id,
  20898                                                                   mems));
  20899             /* Getting info from one of the LM Counter pools (ingress or egress)
  20900              * is enough
  20901              */
  20902             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mems[0], MEM_BLOCK_ANY,
  20903                                              (h_data_p->rx_ctr & 0xFFFFFF),
  20904                                              &lm_entry));
  20905 
  20906             lm_ctr_type = soc_mem_field32_get(unit, mems[0], &lm_entry,
  20907                                               LM_COUNT_TYPEf);
  20908             lm_ctr_sample_size = soc_mem_field32_get(unit, mems[0], &lm_entry,
  20909                                                      LM_COUNTER_SAMPLE_SIZEf);
  20910 
  20911             lm_payload_offset =
  20912                 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  20913                         sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset);
  20914 
  20915             lm_cos_offset =
  20916                 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  20917                         sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset);
  20918         }
  20919 
  20920         if (lm_ctr_pool_id != ep_info->lm_ctr_pool_id) {
  20921             loss_del = loss_add = 1;
  20922         }
  20923 
  20924         if (0 == ep_info->pri_map_id) {
  20925             ep_info->pri_map_id = oc->default_pri_map_id;
  20926         }
  20927         if (ep_info->pri_map_id != h_data_p->pri_map_index) {
  20928             loss_del = loss_add = 1;
  20929         }
  20930 
  20931         if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info)) {
  20932             if (lm_ctr_type != ep_info->lm_ctr_type) {
  20933                 loss_del = loss_add = 1;
  20934             }
  20935 
  20936             if (lm_ctr_sample_size != ep_info->lm_ctr_sample_size) {
  20937                 loss_del = loss_add = 1;
  20938             }
  20939 
  20940             if (lm_payload_offset != ep_info->lm_payload_offset) {
  20941                 loss_del = loss_add = 1;
  20942             }
  20943 
  20944             if (lm_cos_offset != ep_info->lm_cos_offset) {
  20945                 loss_del = loss_add = 1;
  20946             }
  20947         }
  20948     }
  20949 
  20950     if (1 == loss_del) {
  20951         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_lmep(unit, h_data_p, &mem_index,
  20952                                                    &mp_group_entry));
  20953         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_clear_counter(unit, MP_GROUPm,
  20954                                                        mem_index, h_data_p,
  20955                                                        (void *)&mp_group_entry));
  20956 
  20957         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p,
  20958                                                        &mem_index,
  20959                                                        &egr_mp_group));
  20960         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm,
  20961                                                        mem_index, h_data_p,
  20962                                                        (void *)&egr_mp_group));
  20963         h_data_p->flags &= ~BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  20964     }
  20965 
  20966     if (1 == loss_add) {
  20967         h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
  20968         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lmep_counters_set(unit, ep_info));
  20969     }
  20970 
  20971     if(ep_info->type == bcmOAMEndpointTypeEthernet) {
  20972         if((ep_info->ccm_tx_update_lm_counter_size) && 
  20973         (_BCM_OAM_INVALID_INDEX != h_data_p->local_tx_index)) {
  20974             BCM_IF_ERROR_RETURN(bcm_sb2_oam_hw_ccm_tx_ctr_update(unit, ep_info)); 
  20975         }
  20976     }
  20977     /* Update ctrs incremented/sampled by CCM */
  20978 #if defined(INCLUDE_BHH)
  20979     if(BHH_EP_TYPE(h_data_p)) {
  20980         BCM_IF_ERROR_RETURN(bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(unit,
  20981                                                                     ep_info));
  20982     }
  20983 #endif /* INCLUDE_BHH */
  20984 
  20985     return BCM_E_NONE;
  20986 }
  20987 
  20988 /*
  20989  * Function:
  20990  *     bcm_sb2_oam_endpoint_create
  20991  * Purpose:
  20992  *     Create or replace an OAM endpoint object
  20993  * Parameters:
  20994  *     unit          - (IN) BCM device number
  20995  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  20996  * Returns:
  20997  *      BCM_E_XXX
  20998  */
  20999 int
  21000 bcm_sb2_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info)
  21001 {
  21002     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
  21003     _bcm_oam_hash_key_t  hash_key;          /* Hash Key buffer.             */
  21004     int                  ep_req_index;      /* Requested endpoint index.    */
  21005     int                  rv;                /* Operation return status.     */
  21006     _bcm_oam_control_t   *oc;               /* Pointer to OAM control       */
  21007                                             /* structure.                   */
  21008     uint32               sglp = 0;          /* Source global logical port.  */
  21009     uint32               dglp = 0;          /* Dest global logical port.    */
  21010     uint32               svp = 0;           /* Source virtual port          */
  21011     bcm_port_t           src_pp_port = 0;   /* Source pp port.              */
  21012     bcm_port_t           dst_pp_port = 0;   /* Dest pp port.                */
  21013     int                  mep_ccm_tx = 0;    /* Endpoint CCM Tx status.      */
  21014     int                  mep_ccm_rx = 0;    /* Endpoint CCM Rx status.      */
  21015     int                  remote = 0;        /* Remote endpoint status.      */
  21016     int                  up_mep = 0;        /* Endpoint is an upMep         */
  21017     int                  key_type = 0;
  21018     port_tab_entry_t     port_entry;
  21019     int                  oam_key1 = 0;
  21020     int                  oam_key2 = 0;
  21021     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID;
  21022     bcm_trunk_member_t   trunk_member = {0};
  21023 #if defined(INCLUDE_L3)
  21024     bcm_mpls_port_t      mpls_port;
  21025 #endif
  21026     int                  is_vp_valid = 0;
  21027     LOG_DEBUG(BSL_LS_BCM_OAM,
  21028               (BSL_META_U(unit,
  21029                           "OAM(unit %d) Info: bcm_sb2_oam_endpoint_create "
  21030                            "Endpoint ID=%d.\n"), unit, endpoint_info->id));
  21031 
  21032     /* Validate input parameter. */
  21033     if (NULL == endpoint_info) {
  21034         return (BCM_E_PARAM);
  21035     }
  21036     /* Get OAM Control Structure. */
  21037     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  21038 
  21039     _BCM_OAM_LOCK(oc);
  21040 
  21041 #if defined(KEY_PRINT)
  21042     _bcm_oam_hash_key_print(&hash_key);
  21043 #endif
  21044 
  21045     /* Calculate the hash key for given enpoint input parameters. */
  21046     _bcm_sb2_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key);
  21047 
  21048     /* Validate endpoint input parameters. */
  21049     rv = _bcm_sb2_oam_endpoint_params_validate(unit, oc, &hash_key,
  21050                                                endpoint_info);
  21051     if (BCM_FAILURE(rv)) {
  21052         LOG_ERROR(BSL_LS_BCM_OAM,
  21053                   (BSL_META_U(unit,
  21054                               "OAM(unit %d) Error: (EP=%d) - %s.\n"),
  21055                    unit, endpoint_info->id, bcm_errmsg(rv)));
  21056         _BCM_OAM_UNLOCK(oc);
  21057         return (rv);
  21058     }
  21059 
  21060     if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) &&
  21061         (endpoint_info->flags2 & BCM_OAM_ENDPOINT2_UPDATE_COUNTER_ACTION)) {
  21062         /* Update LM parameters */
  21063         rv =  bcm_sb2_oam_endpoint_lm_update(unit, endpoint_info);
  21064         _BCM_OAM_UNLOCK(oc);
  21065         return rv;
  21066     }
  21067 
  21068     if(soc_feature(unit, soc_feature_bhh)) {
  21069 #if defined(INCLUDE_BHH)
  21070         if(BHH_EP_TYPE(endpoint_info))
  21071         {
  21072             if ((oc->ukernel_not_ready == 1) && 
  21073                 (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){
  21074                 LOG_ERROR(BSL_LS_BCM_OAM,
  21075                           (BSL_META_U(unit,
  21076                                       "OAM(unit %d) Error: BTE(ukernel) "
  21077                                       "not ready.\n"), unit));
  21078                 _BCM_OAM_UNLOCK(oc);
  21079                 return (BCM_E_INIT);
  21080             }
  21081 
  21082             rv = bcm_sb2_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key);
  21083             if (BCM_FAILURE(rv)) {
  21084                 LOG_ERROR(BSL_LS_BCM_OAM,
  21085                           (BSL_META_U(unit,
  21086                                       "OAM(unit %d) Error: BHH Endpoint create (EP=%d) - %s.\n"),
  21087                            unit, endpoint_info->id, bcm_errmsg(rv)));
  21088             }
  21089             _BCM_OAM_UNLOCK(oc);
  21090 
  21091             return (rv);
  21092         }
  21093 #endif /* INCLUDE_BHH */
  21094     }
  21095 
  21096     /* Get MEP remote endpoint status. */
  21097     remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  21098 
  21099     /* For remote endpoints gport is not required.
  21100        Only group and MEP ID info is required. */
  21101     if (!remote) {
  21102         /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */
  21103         rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, &dglp,
  21104                 &src_pp_port, &dst_pp_port, &svp, &trunk_id,
  21105                 &is_vp_valid, &trunk_member);
  21106 
  21107         if (BCM_FAILURE(rv)) {
  21108             LOG_ERROR(BSL_LS_BCM_OAM,
  21109                     (BSL_META_U(unit,
  21110                                 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  21111                      unit, endpoint_info->id, bcm_errmsg(rv)));
  21112             _BCM_OAM_UNLOCK(oc);
  21113             return (rv);
  21114         }
  21115     }
  21116 
  21117     /* Get MEP CCM Tx status. */
  21118     mep_ccm_tx
  21119         = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)
  21120             ? 1 : 0);
  21121 
  21122     /* Get MEP CCM Rx status. */
  21123     mep_ccm_rx
  21124         = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0);
  21125     /* The rx settings need to be enabled for MPLS LM DM endpoints as well */
  21126     if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) {
  21127         mep_ccm_rx = 1;
  21128     }
  21129 
  21130   
  21131     /* Check whether up/down MEP */
  21132     if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  21133         up_mep = 1;
  21134     }
  21135     /* Set the search key type. */
  21136     _bcm_sb2_oam_key_type_from_endpoint_get(endpoint_info->type,
  21137                                             endpoint_info->flags,
  21138                                             endpoint_info->vlan,
  21139                                             endpoint_info->inner_vlan,
  21140                                             is_vp_valid?_BCM_OAM_ENDPOINT_IS_VP_BASED:0,
  21141                                             &key_type);
  21142 
  21143     /* We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 
  21144        EGR_PORT_TABLE based on the key_type of OAM */
  21145     if (trunk_id != BCM_TRUNK_INVALID) {
  21146         rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 
  21147                                                  src_pp_port, &port_entry);
  21148         if (BCM_FAILURE(rv)) {
  21149             LOG_ERROR(BSL_LS_BCM_OAM,
  21150                       (BSL_META_U(unit,
  21151                                   "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"),
  21152                        unit, endpoint_info->id, bcm_errmsg(rv)));
  21153             _BCM_OAM_UNLOCK(oc);
  21154             return (rv);
  21155         }
  21156 
  21157         oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 
  21158         oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 
  21159 
  21160         if (key_type != _BCM_OAM_DOMAIN_PORT) {
  21161              if ((oam_key1 > 0) && (oam_key2 > 0)) {
  21162                 if ((oam_key1 == key_type) || (oam_key2 == key_type)) {
  21163                 } else {
  21164                     LOG_ERROR(BSL_LS_BCM_OAM,
  21165                               (BSL_META_U(unit,
  21166                                           "OAM(unit %d) Error: Invalid OAM domain to "
  21167                                           "resolve (EP=%d) - %s.\n"),
  21168                                unit, endpoint_info->id, bcm_errmsg(rv)));
  21169                     _BCM_OAM_UNLOCK(oc);
  21170                     return (BCM_E_PARAM);
  21171                 }
  21172             }
  21173         }
  21174     }
  21175 
  21176     /* For Downmep CCM tx purposes, int_pri variable is used like a cosq.
  21177      * Hence verify if it is in the valid range, Else return error.
  21178      * For UPMEP CCM tx purposes, int_pri is used as internal priority only.
  21179      * Hence verify if it is in valid range of internal priority
  21180      */
  21181     if (mep_ccm_tx &&  !up_mep && 
  21182         (!BCM_COSQ_QUEUE_VALID(unit, endpoint_info->int_pri))) {
  21183         _BCM_OAM_UNLOCK(oc);
  21184         return (BCM_E_PARAM);
  21185     } else if (mep_ccm_tx &&  up_mep && 
  21186       (!(endpoint_info->int_pri >= 0 && endpoint_info->int_pri < BCM_OAM_INTPRI_MAX))) {
  21187         _BCM_OAM_UNLOCK(oc);
  21188         return (BCM_E_PARAM);
  21189     }
  21190 
  21191     /* Replace an existing endpoint. */
  21192     if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
  21193         
  21194         rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint_info->id);
  21195         if (BCM_FAILURE(rv)) {
  21196             LOG_ERROR(BSL_LS_BCM_OAM,
  21197                       (BSL_META_U(unit,
  21198                                   "OAM(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"),
  21199                        unit, endpoint_info->id, bcm_errmsg(rv)));
  21200             _BCM_OAM_UNLOCK(oc);
  21201             return (rv);
  21202         }
  21203     }
  21204 
  21205     /* Create a new endpoint with the requested ID. */
  21206     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  21207         ep_req_index = endpoint_info->id;
  21208         rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index,
  21209                                      ep_req_index);
  21210         if (BCM_FAILURE(rv)) {
  21211             LOG_ERROR(BSL_LS_BCM_OAM,
  21212                       (BSL_META_U(unit,
  21213                                   "OAM(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"),
  21214                        unit, endpoint_info->id, bcm_errmsg(rv)));
  21215             _BCM_OAM_UNLOCK(oc);
  21216             return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv);
  21217         }
  21218     } else {
  21219         /* Allocate the next available endpoint index. */
  21220         rv = shr_idxres_list_alloc(oc->mep_pool,
  21221                                    (shr_idxres_element_t *)&ep_req_index);
  21222         if (BCM_FAILURE(rv)) {
  21223             LOG_ERROR(BSL_LS_BCM_OAM,
  21224                       (BSL_META_U(unit,
  21225                                   "OAM(unit %d) Error: Endpoint alloc failed - %s.\n"),
  21226                        unit, bcm_errmsg(rv)));
  21227             _BCM_OAM_UNLOCK(oc);
  21228             return (rv);
  21229         }
  21230         /* Set the allocated endpoint id value. */
  21231         endpoint_info->id =  ep_req_index;
  21232     }
  21233 
  21234     /* Get the hash data pointer where the data is to be stored. */
  21235     hash_data = &oc->oam_hash_data[ep_req_index];
  21236 
  21237     /* Clear the hash data element contents before storing the values. */
  21238     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  21239     hash_data->type = endpoint_info->type;
  21240     hash_data->vccv_type = endpoint_info->vccv_type;
  21241     hash_data->ep_id = endpoint_info->id;
  21242     hash_data->is_remote = remote;
  21243     hash_data->local_tx_enabled = mep_ccm_tx;
  21244     hash_data->local_rx_enabled = mep_ccm_rx;
  21245     hash_data->group_index = endpoint_info->group;
  21246     hash_data->name  = endpoint_info->name;
  21247     if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) {
  21248         /* For MPLS LM DM endpoints, the mdl level
  21249          * should be hard coded to 7
  21250          */
  21251         endpoint_info->level = 7;
  21252     }
  21253     hash_data->level = endpoint_info->level;
  21254     hash_data->vlan = endpoint_info->vlan;
  21255     hash_data->inner_vlan = endpoint_info->inner_vlan;
  21256     hash_data->gport = endpoint_info->gport;
  21257     hash_data->sglp = sglp;
  21258     hash_data->dglp = dglp;
  21259     hash_data->src_pp_port = src_pp_port;
  21260     hash_data->dst_pp_port = dst_pp_port;
  21261     hash_data->flags = endpoint_info->flags;
  21262     hash_data->flags2 = endpoint_info->flags2;
  21263     hash_data->tx_gport = endpoint_info->tx_gport;
  21264     hash_data->opcode_flags = ( endpoint_info->opcode_flags &
  21265             _BCM_SB2_OAM_OPCODE_MASK );
  21266     hash_data->period = endpoint_info->ccm_period;
  21267     hash_data->in_use = 1;
  21268     hash_data->oam_domain = key_type;
  21269     hash_data->outer_tpid = endpoint_info->outer_tpid;
  21270     hash_data->inner_tpid = endpoint_info->inner_tpid;
  21271     hash_data->subport_tpid = endpoint_info->subport_tpid;
  21272     hash_data->vpn = endpoint_info->vpn;
  21273     hash_data->int_pri = endpoint_info->int_pri;
  21274     hash_data->trunk_index = endpoint_info->trunk_index;
  21275 
  21276     if ((MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) &&
  21277             (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(endpoint_info))) {
  21278         if (MPLS_LM_DM_PW_ENDPOINT_TYPE(endpoint_info)) {
  21279 #if defined(INCLUDE_L3)
  21280             bcm_mpls_port_t_init(&mpls_port);
  21281             mpls_port.mpls_port_id = hash_data->gport;
  21282             rv = bcm_esw_mpls_port_get(unit, hash_data->vpn,
  21283                     &mpls_port);
  21284             if (BCM_FAILURE(rv)) {
  21285                 LOG_ERROR(BSL_LS_BCM_OAM,
  21286                         (BSL_META_U(unit,
  21287                                     "OAM(unit %d) Error: MPLS port get failed - %s.\n"),
  21288                          unit, bcm_errmsg(rv)));
  21289                 _BCM_OAM_UNLOCK(oc);
  21290                 return (rv);
  21291             }
  21292             hash_data->egress_if = mpls_port.egress_tunnel_if;
  21293             hash_data->label     = mpls_port.match_label;
  21294 #endif
  21295         } else {
  21296             hash_data->label = endpoint_info->mpls_label;
  21297             hash_data->egress_if = endpoint_info->intf_id;
  21298         }
  21299     }
  21300     if (is_vp_valid) {
  21301         hash_data->vp = svp;
  21302         if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  21303             /* For implementation of VP based lookup on egress side (UP MEP)
  21304              * We need to set EGR_DVP_ATTRIBUTE OAM_KEY3 = 1.
  21305              */
  21306             rv = bcm_esw_port_control_set(unit, endpoint_info->gport,
  21307                     bcmPortControlOamLookupWithDvp,
  21308                     1);
  21309             if (BCM_FAILURE(rv)) {
  21310                 _BCM_OAM_UNLOCK(oc);
  21311                 return (rv);
  21312             }
  21313         }
  21314         hash_data->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED;
  21315     }
  21316     hash_data->trunk_id = trunk_id;
  21317 
  21318     if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
  21319         hash_data->resolved_trunk_gport = trunk_member.gport;
  21320     }
  21321 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM)
  21322     memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address,
  21323             sizeof(bcm_mac_t));
  21324     memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address,
  21325             sizeof(bcm_mac_t));
  21326 #endif
  21327 #if defined (INCLUDE_MPLS_LM_DM)
  21328     if ( MPLS_LM_DM_ENDPOINT_TYPE(hash_data) ) {
  21329         hash_data->egr_label = endpoint_info->egress_label.label;
  21330         hash_data->egr_label_exp = endpoint_info->egress_label.exp;
  21331         hash_data->egr_label_ttl = endpoint_info->egress_label.ttl;
  21332     }
  21333 #endif
  21334 
  21335     /* Initialize hardware index as invalid indices. */
  21336     hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
  21337     hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
  21338     hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
  21339     hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX;
  21340     hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX;
  21341     hash_data->profile_index = _BCM_OAM_INVALID_INDEX;
  21342     hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX;
  21343     hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX;
  21344     hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX;
  21345     hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  21346     hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  21347     hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  21348     hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  21349     hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX;
  21350     hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  21351     hash_data->ctr_field_id = _BCM_OAM_INVALID_INDEX;
  21352     hash_data->egr_ctr_field_id = _BCM_OAM_INVALID_INDEX;
  21353 
  21354     if (1 == remote) {
  21355         /* Allocate the next available index for RMEP table. */
  21356         rv = shr_idxres_list_alloc
  21357                 (oc->rmep_pool,
  21358                  (shr_idxres_element_t *)&hash_data->remote_index);
  21359         if (BCM_FAILURE(rv)) {
  21360             _BCM_OAM_UNLOCK(oc);
  21361             LOG_ERROR(BSL_LS_BCM_OAM,
  21362                       (BSL_META_U(unit,
  21363                                   "OAM(unit %d) Error: RMEP index alloc failed EP:%d %s.\n"),
  21364                        unit, endpoint_info->id, bcm_errmsg(rv)));
  21365             return (rv);
  21366         }
  21367     } else {
  21368         /* Allocate the next available index for LMEP table. */
  21369         if (1 == mep_ccm_tx) {
  21370             rv = shr_idxres_list_alloc
  21371                     (oc->lmep_pool,
  21372                      (shr_idxres_element_t *)&hash_data->local_tx_index);
  21373             if (BCM_FAILURE(rv)) {
  21374                 _BCM_OAM_UNLOCK(oc);
  21375                 LOG_ERROR(BSL_LS_BCM_OAM,
  21376                           (BSL_META_U(unit,
  21377                                       "OAM(unit %d) Error: LMEP Tx index alloc failed EP:%d "
  21378                                        "%s.\n"), unit, endpoint_info->id, bcm_errmsg(rv)));
  21379                 return (rv);
  21380             }
  21381         }
  21382 
  21383         /* Allocate the next available index for MA_INDEX table. */
  21384         if (1 == mep_ccm_rx) {
  21385            /* check up or down MEP */
  21386             if (1 == up_mep) {
  21387                 rv =  _bcm_sb2_oam_upmep_rx_endpoint_reserve(unit, 
  21388                                                           endpoint_info);
  21389                 if (BCM_FAILURE(rv)) {
  21390                     if (1 == mep_ccm_tx) {
  21391                     /* Return Tx index to the LMEP pool. */
  21392                         shr_idxres_list_free(oc->lmep_pool,
  21393                                          hash_data->local_tx_index);
  21394                     }
  21395 
  21396                     /* Return endpoint index to MEP pool. */
  21397                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
  21398 
  21399                     _BCM_OAM_UNLOCK(oc);
  21400                     LOG_ERROR(BSL_LS_BCM_OAM,
  21401                               (BSL_META_U(unit,
  21402                                           "OAM(unit %d) Error: LMEP Rx index alloc failed "
  21403                                           "EP:%d " "%s.\n"), unit, 
  21404                                endpoint_info->id, bcm_errmsg(rv)));
  21405                     return (rv);
  21406                 }
  21407             } else { /* down Mep */
  21408                 rv =  _bcm_sb2_oam_downmep_rx_endpoint_reserve(unit, 
  21409                                                                endpoint_info);
  21410                 if (BCM_FAILURE(rv)) {
  21411                     if (1 == mep_ccm_tx) {
  21412                     /* Return Tx index to the LMEP pool. */
  21413                         shr_idxres_list_free(oc->lmep_pool,
  21414                                          hash_data->local_tx_index);
  21415                     }
  21416 
  21417                     /* Return endpoint index to MEP pool. */
  21418                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
  21419 
  21420                     _BCM_OAM_UNLOCK(oc);
  21421                     LOG_ERROR(BSL_LS_BCM_OAM,
  21422                               (BSL_META_U(unit,
  21423                                           "OAM(unit %d) Error: LMEP Rx index alloc "
  21424                                           "failed EP:%d " "%s.\n"), unit, endpoint_info->id, 
  21425                                bcm_errmsg(rv)));
  21426                     return (rv);
  21427                 }
  21428             }
  21429         }
  21430     }
  21431     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
  21432     if (BCM_FAILURE(rv)) {
  21433         LOG_ERROR(BSL_LS_BCM_OAM,
  21434                 (BSL_META_U(unit,
  21435                             "OAM(unit %d) Error: Hash table insert failed EP=%d %s.\n"),
  21436                  unit, endpoint_info->id, bcm_errmsg(rv)));
  21437         _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21438         _BCM_OAM_UNLOCK(oc);
  21439         return (rv);
  21440     }
  21441 
  21442     if (1 == remote) {
  21443         rv = _bcm_oam_sb2_remote_mep_hw_set(unit, endpoint_info);
  21444         if (BCM_FAILURE(rv)) {
  21445             LOG_DEBUG(BSL_LS_BCM_OAM,
  21446                       (BSL_META_U(unit,
  21447                                   "OAM(unit %d) Error: Remote MEP set failed EP=%d %s.\n"),
  21448                        unit, endpoint_info->id, bcm_errmsg(rv)));
  21449             _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21450             _BCM_OAM_UNLOCK(oc);
  21451             return (rv);
  21452         }
  21453     } else {
  21454         if (mep_ccm_rx) {
  21455             rv = _bcm_sb2_oam_local_rx_mep_hw_set(unit, endpoint_info);
  21456             if (BCM_FAILURE(rv)) {
  21457                 LOG_ERROR(BSL_LS_BCM_OAM,
  21458                           (BSL_META_U(unit,
  21459                                       "OAM(unit %d) Error: Rx config failed for EP=%d %s.\n"),
  21460                            unit, endpoint_info->id, bcm_errmsg(rv)));
  21461                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep,
  21462                                               hash_key, hash_data);
  21463                 _BCM_OAM_UNLOCK(oc);
  21464                 return (rv);
  21465             }
  21466         }
  21467         if (mep_ccm_tx) {
  21468             rv = _bcm_oam_sb2_local_tx_mep_hw_set(unit, endpoint_info);
  21469             if (BCM_FAILURE(rv)) {
  21470                 LOG_ERROR(BSL_LS_BCM_OAM,
  21471                           (BSL_META_U(unit,
  21472                                       "OAM(unit %d) Error: Tx config failed for EP=%d %s.\n"),
  21473                            unit, endpoint_info->id, bcm_errmsg(rv)));
  21474                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep,
  21475                                               hash_key, hash_data);
  21476                 _BCM_OAM_UNLOCK(oc);
  21477                 return (rv);
  21478             }
  21479         }
  21480 
  21481         if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(endpoint_info)) {
  21482             /* For rx enable the mpls oam for the label. */
  21483 
  21484             /* First check if the label is in l3 tunnel table and enable
  21485                MPLS OAM if true.  */
  21486             rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit,
  21487                     hash_data, 1);
  21488             if (rv == BCM_E_NOT_FOUND) {
  21489                 /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 
  21490                    table */
  21491                 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit,
  21492                         hash_data, 1);
  21493                 if (BCM_FAILURE(rv)) {
  21494                     LOG_ERROR(BSL_LS_BCM_OAM,
  21495                             (BSL_META_U(unit,
  21496                                         "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"),
  21497                              unit, endpoint_info->id, bcm_errmsg(rv)));
  21498                     _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21499                     _BCM_OAM_UNLOCK(oc);
  21500                     return (rv);
  21501                 }
  21502             } else if (rv != BCM_E_NONE) {
  21503                 LOG_ERROR(BSL_LS_BCM_OAM,
  21504                         (BSL_META_U(unit,
  21505                                     "OAM(unit %d) Error: L3 tunnel table update failed (EP=%d) - %s.\n"),
  21506                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21507                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21508                 _BCM_OAM_UNLOCK(oc);
  21509                 return (rv);
  21510             }
  21511             /* For tx enable the mpls oam for the egress intf.
  21512                and write the mepid in egr_l3_next_hop table */
  21513             rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit,
  21514                                                                     hash_data, 1);
  21515             if (BCM_FAILURE(rv)) {
  21516                 LOG_ERROR(BSL_LS_BCM_OAM,
  21517                         (BSL_META_U(unit,
  21518                                     "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"),
  21519                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21520                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21521                 _BCM_OAM_UNLOCK(oc);
  21522                 return (rv);
  21523             }
  21524         } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(endpoint_info)) {
  21525             rv = _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(unit, 
  21526                     hash_data, 1);
  21527             if (BCM_FAILURE(rv)) {
  21528                 LOG_ERROR(BSL_LS_BCM_OAM,
  21529                         (BSL_META_U(unit,
  21530                                     "OAM(unit %d) Error: SVP table update failed (EP=%d) - %s.\n"),
  21531                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21532                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21533                 _BCM_OAM_UNLOCK(oc);
  21534                 return (rv);
  21535             }
  21536             /* For tx enable the mpls oam for the egress dvp.
  21537              */
  21538             rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, hash_data, 1);
  21539             if (BCM_FAILURE(rv)) {
  21540                 LOG_ERROR(BSL_LS_BCM_OAM,
  21541                         (BSL_META_U(unit,
  21542                                     "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"),
  21543                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21544                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21545                 _BCM_OAM_UNLOCK(oc);
  21546                 return (rv);
  21547             }
  21548         } else {   
  21549             /* Ethernet OAM and MPLS Section OAM */
  21550             rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, hash_data);
  21551             if (BCM_FAILURE(rv)) {
  21552                 LOG_ERROR(BSL_LS_BCM_OAM,
  21553                         (BSL_META_U(unit,
  21554                                     "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"),
  21555                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21556                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21557                 _BCM_OAM_UNLOCK(oc);
  21558                 return (rv);
  21559             }
  21560             rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, hash_data);
  21561             if (BCM_FAILURE(rv)) {
  21562                 LOG_ERROR(BSL_LS_BCM_OAM,
  21563                         (BSL_META_U(unit,
  21564                                     "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"),
  21565                          unit, endpoint_info->id, bcm_errmsg(rv)));
  21566                 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21567                 _BCM_OAM_UNLOCK(oc);
  21568                 return (rv);
  21569             }
  21570         }
  21571         /* Set OAM LM cng and cpu data control from LM flags*/
  21572         if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  21573             _bcm_sb2_oam_lm_cng_cpu_ctrl_set(unit, endpoint_info); 
  21574         }
  21575     }
  21576 
  21577     rv = _bcm_sb2_oam_group_ep_list_add(unit, endpoint_info->group,
  21578                                         endpoint_info->id);
  21579     if (BCM_FAILURE(rv)) {
  21580         LOG_ERROR(BSL_LS_BCM_OAM,
  21581                   (BSL_META_U(unit,
  21582                               "OAM(unit %d) Error: failed to add entry to ep list "
  21583                               "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv)));
  21584         _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21585         _BCM_OAM_UNLOCK(oc);
  21586         return (rv);
  21587     }
  21588 
  21589     rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data);
  21590     if (BCM_FAILURE(rv)) {
  21591         LOG_ERROR(BSL_LS_BCM_OAM,
  21592                 (BSL_META_U(unit,
  21593                             "OAM(unit %d) Error: failed to add mapping to ma_idx_to_ep_id list "
  21594                             "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv)));
  21595         _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data);
  21596         _BCM_OAM_UNLOCK(oc);
  21597         return (rv);
  21598     }
  21599     _BCM_OAM_UNLOCK(oc);
  21600 
  21601 #ifdef BCM_WARM_BOOT_SUPPORT
  21602     SOC_CONTROL_LOCK(unit);
  21603     SOC_CONTROL(unit)->scache_dirty = 1;
  21604     SOC_CONTROL_UNLOCK(unit);
  21605 #endif
  21606 
  21607     return (BCM_E_NONE);
  21608 }
  21609 
  21610 /*
  21611  * Function:
  21612  *      bcm_sb2_oam_hw_ccm_tx_ctr_get
  21613  * Purpose:
  21614  *      Update CCM CTR params
  21615  * Parameters:
  21616  *      unit - (IN) Unit number.
  21617  *      lmep_1_entry - (IN) lemp_1 entry read from HW
  21618  *      ep_info - (OUT) Pointer to get endpoint parameters
  21619  * Returns:
  21620  *      BCM_E_XXX
  21621  * Notes:
  21622  */
  21623 void
  21624 bcm_sb2_oam_hw_ccm_tx_ctr_get(int                       unit, 
  21625                                 lmep_1_entry_t          *lmep_1_entry,
  21626                                 bcm_oam_endpoint_info_t *endpoint_info)
  21627 {
  21628     int num_counter = 0;
  21629     uint32 counter_base_id = 0;
  21630 
  21631     if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_ACTIONf)) {
  21632 
  21633         counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_IDf);
  21634         endpoint_info->ccm_tx_update_lm_counter_base_id[0] = (counter_base_id & 0xFFF8);
  21635         endpoint_info->ccm_tx_update_lm_counter_offset[0] = counter_base_id % 8;
  21636         num_counter++;
  21637     }
  21638 
  21639     if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_ACTIONf)) {
  21640 
  21641         counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_IDf);
  21642         endpoint_info->ccm_tx_update_lm_counter_base_id[1] = (counter_base_id & 0xFFF8) + (1 << 24);
  21643         endpoint_info->ccm_tx_update_lm_counter_offset[1] = counter_base_id % 8;
  21644         num_counter++;
  21645     }
  21646 
  21647     if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_3_ACTIONf)) {
  21648 
  21649         counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_3_IDf);
  21650         endpoint_info->ccm_tx_update_lm_counter_base_id[2] = (counter_base_id & 0xFFF8) + (2 << 24);
  21651         endpoint_info->ccm_tx_update_lm_counter_offset[2] = counter_base_id % 8;
  21652         num_counter++;
  21653     }
  21654 
  21655     endpoint_info->ccm_tx_update_lm_counter_size = num_counter;
  21656     
  21657     return;
  21658 }
  21659 
  21660  /*
  21661  * Function:
  21662  *      bcm_sb2_oam_endpoint_get
  21663  * Purpose:
  21664  *      Get an OAM endpoint object
  21665  * Parameters:
  21666  *     unit          - (IN) BCM device number
  21667  *     endpoint      - (IN) Endpoint ID
  21668  *     endpoint_info - (OUT) Pointer to OAM endpoint information buffer.
  21669  * Returns:
  21670  *     BCM_E_XXX
  21671  */
  21672 int
  21673 bcm_sb2_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint,
  21674                          bcm_oam_endpoint_info_t *endpoint_info)
  21675 {
  21676     _bcm_oam_hash_data_t *h_data_p;      /* Pointer to endpoint hash data.    */
  21677     int                  rv = BCM_E_NONE;/* Operation return status.          */
  21678     _bcm_oam_control_t   *oc;            /* Pointer to OAM control structure. */
  21679     rmep_entry_t         rmep_entry;     /* Remote MEP entry buffer.          */
  21680     lmep_entry_t         lmep_entry;     /* Local MEP entry buffer.           */
  21681     lmep_1_entry_t       lmep_1_entry;   /* Local MEP entry buffer.           */
  21682     uint16               inner_vlan_pri = 0; /* Inner vlan and pri */
  21683 #if defined(INCLUDE_BHH)
  21684     bhh_sdk_msg_ctrl_sess_get_t msg;
  21685     uint8 *buffer, *buffer_ptr;
  21686     uint16 buffer_len, reply_len;
  21687     int sess_id = 0;
  21688     bcm_l3_egress_t l3_egress;
  21689     bcm_l3_intf_t l3_intf;
  21690     uint8   ts_mode;
  21691     uint8 lm_pdu_counter_offset = 0;
  21692     bcm_cos_t int_pri;
  21693     _mpls_label_t label;
  21694 #endif
  21695     egr_mp_group_entry_t egr_mp_group;
  21696     int ctr_field_id = 0;
  21697     int egr_mp_grp_idx = -1;
  21698     /* Ingress and egress. 2 memories */
  21699     soc_mem_t mems[2] = {INVALIDm, INVALIDm};
  21700     ing_oam_lm_counters_0_entry_t lm_entry;
  21701     int pool_id = -1;
  21702     bcm_gport_t             tx_gport = 0;    /* Gport value. */ 
  21703     bcm_port_t              pp_port = 0;
  21704 
  21705     if (NULL == endpoint_info) {
  21706         return (BCM_E_PARAM);
  21707     }
  21708 
  21709     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  21710     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  21711     _BCM_OAM_LOCK(oc);
  21712 
  21713 
  21714     h_data_p =  &oc->oam_hash_data[endpoint];
  21715 
  21716     if (0 == h_data_p->in_use) {
  21717         LOG_DEBUG(BSL_LS_BCM_OAM,
  21718                 (BSL_META_U(unit,
  21719                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  21720                  unit, endpoint));
  21721         _BCM_OAM_UNLOCK(oc);
  21722         return (BCM_E_NOT_FOUND);
  21723     }
  21724 
  21725     LOG_DEBUG(BSL_LS_BCM_OAM,
  21726               (BSL_META_U(unit,
  21727                           "OAM(unit %d) Info: Endpoint (EP=%d) remote=%d local_tx=%d"
  21728                            "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d oam_domain=%d\n"),
  21729                unit, endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled,
  21730                h_data_p->local_tx_index, h_data_p->local_rx_enabled,
  21731                h_data_p->local_rx_index, h_data_p->oam_domain));
  21732     if ((bcmOAMEndpointTypeEthernet == h_data_p->type) || 
  21733         (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) {
  21734         if (1 == h_data_p->is_remote) {
  21735 
  21736             sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
  21737 
  21738             /* Get hardware table entry information.  */
  21739             rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index,
  21740                             &rmep_entry);
  21741             if (BCM_FAILURE(rv)) {
  21742                     LOG_ERROR(BSL_LS_BCM_OAM,
  21743                               (BSL_META_U(unit,
  21744                                           "OAM(unit %d) Error: RMEP table read failed for"
  21745                                            " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  21746                     _BCM_OAM_UNLOCK(oc);
  21747                     return (rv);
  21748             }
  21749 
  21750             rv = _bcm_sb2_oam_read_clear_faults(unit, h_data_p->remote_index,
  21751                                             RMEPm, (uint32 *) &rmep_entry,
  21752                                             (void *) endpoint_info);
  21753             if (BCM_FAILURE(rv)) {
  21754                 LOG_ERROR(BSL_LS_BCM_OAM,
  21755                           (BSL_META_U(unit,
  21756                                       "OAM(unit %d) Error: RMEP table read failed for"
  21757                                        " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  21758                     _BCM_OAM_UNLOCK(oc);
  21759                     return (rv);
  21760             }
  21761         } else {
  21762             if (1 == h_data_p->local_tx_enabled) {
  21763 
  21764                 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
  21765 
  21766                 /* Get hardware table entry information.  */
  21767                 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
  21768                                 &lmep_entry);
  21769                 if (BCM_FAILURE(rv)) {
  21770                     LOG_ERROR(BSL_LS_BCM_OAM,
  21771                               (BSL_META_U(unit,
  21772                                           "OAM(unit %d) Error: LMEP table read failed for EP=%d"
  21773                                            " %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  21774                     _BCM_OAM_UNLOCK(oc);
  21775                     return (rv);
  21776                 }
  21777 
  21778                 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf,
  21779                                    endpoint_info->src_mac_address);
  21780 
  21781                 endpoint_info->pkt_pri
  21782                     = soc_LMEPm_field32_get(unit, &lmep_entry, PRIORITYf);
  21783 
  21784                 endpoint_info->port_state
  21785                     = (soc_LMEPm_field32_get
  21786                         (unit, &lmep_entry, PORT_TLVf)
  21787                         ? BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED);
  21788 
  21789                 inner_vlan_pri = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf);
  21790                 endpoint_info->inner_vlan = 0xFFF & inner_vlan_pri;
  21791                 endpoint_info->inner_pkt_pri = inner_vlan_pri >> 13;
  21792 
  21793                 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t));
  21794 
  21795                 /* Get hardware table entry information.  */
  21796                 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
  21797                                 &lmep_1_entry);
  21798                 if (BCM_FAILURE(rv)) {
  21799                     LOG_ERROR(BSL_LS_BCM_OAM,
  21800                               (BSL_META_U(unit,
  21801                                           "OAM(unit %d) Error: LMEP_1 table read failed "
  21802                                           "for EP=%d"" %s.\n"), unit, endpoint, bcm_errmsg(rv)));
  21803                     _BCM_OAM_UNLOCK(oc);
  21804                     return (rv);
  21805                 }
  21806                 soc_LMEP_1m_mac_addr_get(unit, &lmep_1_entry, DAf,
  21807                                      endpoint_info->dst_mac_address);
  21808 
  21809                 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  21810                     endpoint_info->int_pri = soc_LMEP_1m_field32_get(unit,
  21811                             &lmep_1_entry, INT_PRIf);
  21812                 } else {
  21813                     endpoint_info->int_pri = h_data_p->int_pri;
  21814                 }
  21815 
  21816                 endpoint_info->interface_state
  21817                    = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, INTERFACE_TLVf);
  21818             
  21819                 bcm_sb2_oam_hw_ccm_tx_ctr_get(unit, &lmep_1_entry, endpoint_info);
  21820                 pp_port = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf);
  21821                 _BCM_KT2_SUBPORT_PORT_ID_SET(tx_gport, pp_port);
  21822                 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, pp_port)) {
  21823                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(tx_gport, _BCM_KT2_SUBPORT_TYPE_GENERAL);
  21824                     endpoint_info->tx_gport = tx_gport;
  21825                     endpoint_info->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW;
  21826                 }
  21827             }
  21828         }
  21829     }
  21830     else if (soc_feature(unit, soc_feature_bhh) &&
  21831             (BHH_EP_TYPE(h_data_p))) {
  21832 #if defined(INCLUDE_BHH)
  21833         if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  21834             sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint);
  21835             rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  21836                     MOS_MSG_SUBCLASS_BHH_SESS_GET,
  21837                     sess_id, 0,
  21838                     MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  21839                     &reply_len);
  21840             if (BCM_FAILURE(rv)) {
  21841                 LOG_ERROR(BSL_LS_BCM_OAM,
  21842                         (BSL_META_U(unit,
  21843                                     "OAM(unit %d) Error: ukernel msg failed for"
  21844                                     " EP=%d %s.\n"), unit, endpoint, 
  21845                                     bcm_errmsg(rv)));
  21846                 _BCM_OAM_UNLOCK(oc);
  21847                 return (rv);
  21848             }
  21849 
  21850             /* Pack control message data into DMA buffer */
  21851             buffer = oc->dma_buffer;
  21852             buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  21853             buffer_len = buffer_ptr - buffer;
  21854 
  21855             if (reply_len != buffer_len) {
  21856                 rv = BCM_E_INTERNAL;
  21857                 LOG_ERROR(BSL_LS_BCM_OAM,
  21858                         (BSL_META_U(unit,
  21859                                     "OAM(unit %d) Error: ukernel msg failed for"
  21860                                     " EP=%d %s.\n"), unit, endpoint, 
  21861                                     bcm_errmsg(rv)));
  21862                 _BCM_OAM_UNLOCK(oc);
  21863                 return (rv);
  21864             } else {
  21865                 endpoint_info->int_pri = msg.tx_cos;
  21866                 endpoint_info->pkt_pri = msg.tx_pri;
  21867                 endpoint_info->mpls_exp = msg.priority;
  21868 
  21869                 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
  21870                     endpoint_info->name       = msg.remote_mep_id;
  21871                     endpoint_info->ccm_period = msg.remote_period;
  21872                 } else {
  21873                     endpoint_info->name       = msg.mep_id;
  21874                     endpoint_info->ccm_period = msg.local_period;
  21875                 }
  21876 
  21877                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
  21878                     endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  21879                 }  
  21880                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
  21881                     endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  21882                 }  
  21883                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  21884                     endpoint_info->faults |= 
  21885                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  21886                 }  
  21887                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  21888                     endpoint_info->faults |= 
  21889                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  21890                 }  
  21891                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  21892                     endpoint_info->faults |= 
  21893                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  21894                 }  
  21895                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  21896                     endpoint_info->faults |= 
  21897                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  21898                 }  
  21899                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  21900                     endpoint_info->faults |= 
  21901                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  21902                 } 
  21903                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
  21904                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
  21905                 }
  21906                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
  21907                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
  21908                 }
  21909                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
  21910                     endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
  21911                 }
  21912 
  21913                 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  21914                     /* If this feature is valid, then encap_data is valid */
  21915                     if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 
  21916                                                           msg.encap_data,
  21917                                      &(endpoint_info->ccm_tx_update_lm_counter_size), 
  21918                                      endpoint_info->ccm_tx_update_lm_counter_base_id,
  21919                                      endpoint_info->ccm_tx_update_lm_counter_offset,
  21920                                      endpoint_info->ccm_tx_update_lm_counter_action,
  21921                                                             &ts_mode,
  21922                                                             &lm_pdu_counter_offset,
  21923                                                             &int_pri,
  21924                                                             NULL)))
  21925                     {
  21926                         _BCM_OAM_UNLOCK(oc);
  21927                         return (BCM_E_INTERNAL);
  21928                     }
  21929                     endpoint_info->int_pri = int_pri;
  21930                 }
  21931                 endpoint_info->egress_label.label = h_data_p->egr_label;
  21932                 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p,
  21933                                                              msg.encap_data,
  21934                                                              msg.encap_length,
  21935                                                              &label);
  21936                 endpoint_info->egress_label.exp = label.exp;
  21937                 endpoint_info->egress_label.ttl = label.ttl;
  21938             }
  21939         } else {
  21940            endpoint_info->ccm_period = h_data_p->period;
  21941            endpoint_info->int_pri = h_data_p->int_pri; 
  21942            endpoint_info->pkt_pri = h_data_p->vlan_pri;
  21943         }
  21944         endpoint_info->intf_id    = h_data_p->egress_if;
  21945         endpoint_info->cpu_qid    =  h_data_p->cpu_qid;
  21946         endpoint_info->mpls_label = h_data_p->label;
  21947         endpoint_info->gport      = h_data_p->gport;
  21948         endpoint_info->vpn        = h_data_p->vpn;
  21949         endpoint_info->trunk_index = h_data_p->trunk_index;
  21950         endpoint_info->pkt_pri = h_data_p->vlan_pri;
  21951         endpoint_info->inner_pkt_pri = h_data_p->inner_vlan_pri;
  21952         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
  21953             endpoint_info->name = msg.remote_mep_id;
  21954             endpoint_info->local_id = endpoint;
  21955         }
  21956         if(!BHH_EP_MPLS_SECTION_TYPE(h_data_p)){
  21957             /*
  21958              * Get MAC address
  21959              */
  21960             bcm_l3_egress_t_init(&l3_egress);
  21961             bcm_l3_intf_t_init(&l3_intf);
  21962 
  21963             if (BCM_FAILURE
  21964                     (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  21965                 _BCM_OAM_UNLOCK(oc);
  21966                 return (BCM_E_INTERNAL);
  21967             }
  21968 
  21969             l3_intf.l3a_intf_id = l3_egress.intf;
  21970             if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  21971                 _BCM_OAM_UNLOCK(oc);
  21972                 return (BCM_E_INTERNAL);
  21973             }
  21974 
  21975             sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, 
  21976                     _BHH_MAC_ADDR_LENGTH);
  21977         }else {
  21978             sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address,
  21979                     _BHH_MAC_ADDR_LENGTH);
  21980         }
  21981 #else
  21982         _BCM_OAM_UNLOCK(oc);
  21983         return (BCM_E_UNAVAIL);
  21984 #endif /* INCLUDE_BHH */
  21985     }
  21986     else {
  21987         _BCM_OAM_UNLOCK(oc);
  21988         return (BCM_E_PARAM);
  21989     }
  21990 
  21991     endpoint_info->id = endpoint;
  21992     endpoint_info->group = h_data_p->group_index;
  21993 
  21994     /* BHH MEP Id & period already filled from uC msg */
  21995     if (!BHH_EP_TYPE(h_data_p)) {
  21996         endpoint_info->name = h_data_p->name;
  21997         endpoint_info->ccm_period = h_data_p->period;
  21998     }
  21999 
  22000     endpoint_info->vlan = h_data_p->vlan;
  22001     endpoint_info->inner_vlan = h_data_p->inner_vlan;
  22002     endpoint_info->level = h_data_p->level;
  22003     endpoint_info->gport = h_data_p->gport;
  22004     endpoint_info->trunk_index = h_data_p->trunk_index;
  22005     endpoint_info->flags |= h_data_p->flags;
  22006     endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID);
  22007     endpoint_info->opcode_flags = h_data_p->opcode_flags;
  22008     endpoint_info->flags2 = h_data_p->flags2;
  22009     endpoint_info->type = h_data_p->type;
  22010     endpoint_info->vccv_type  = h_data_p->vccv_type;
  22011     endpoint_info->lm_counter_base_id = h_data_p->tx_ctr;
  22012     endpoint_info->outer_tpid = h_data_p->outer_tpid;
  22013     endpoint_info->inner_tpid = h_data_p->inner_tpid;
  22014     endpoint_info->subport_tpid = h_data_p->subport_tpid;
  22015     endpoint_info->timestamp_format = h_data_p->ts_format;
  22016 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM)
  22017     sal_memcpy(&(endpoint_info->dst_mac_address),
  22018             &(h_data_p->dst_mac_address), sizeof(bcm_mac_t));
  22019     sal_memcpy(&(endpoint_info->src_mac_address),
  22020             &(h_data_p->src_mac_address), sizeof(bcm_mac_t));
  22021 #endif
  22022     if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) {
  22023         endpoint_info->intf_id    = h_data_p->egress_if;
  22024         endpoint_info->mpls_label = h_data_p->label;
  22025         endpoint_info->vpn        = h_data_p->vpn;
  22026 #if defined(INCLUDE_MPLS_LM_DM) 
  22027         endpoint_info->egress_label.label = h_data_p->egr_label;
  22028         endpoint_info->egress_label.exp = h_data_p->egr_label_exp;
  22029         endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl;
  22030 #endif
  22031     }
  22032 
  22033 #if defined(BCM_METROLITE_SUPPORT)
  22034     if(SOC_IS_METROLITE(unit)) {
  22035         endpoint_info->lm_count_profile = h_data_p->lm_count_profile;
  22036     }
  22037 #endif
  22038     if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  22039         ctr_field_id = h_data_p->egr_ctr_field_id;
  22040         if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) {
  22041             rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, &egr_mp_grp_idx,
  22042                                          &egr_mp_group);
  22043             if (BCM_FAILURE(rv)) {
  22044                 _BCM_OAM_UNLOCK(oc);
  22045                 return (rv);
  22046             } 
  22047             endpoint_info->lm_payload_offset = 
  22048                 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  22049                         sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset);
  22050             endpoint_info->lm_cos_offset = 
  22051                 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group,
  22052                         sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset);
  22053         }
  22054         if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) {
  22055             pool_id = (h_data_p->rx_ctr >> 24) & 0xFF;
  22056             endpoint_info->lm_ctr_pool_id = pool_id;
  22057             rv = _bcm_sb2_oam_lm_counters_mems_from_pool_get(pool_id, mems);
  22058             if (BCM_FAILURE(rv)) {
  22059                 _BCM_OAM_UNLOCK(oc);
  22060                 return (rv);
  22061             } 
  22062             /* Getting info from one of the LM Counter pools (ingress or egress)
  22063              * is enough
  22064              */
  22065             rv = soc_mem_read(unit, mems[0], MEM_BLOCK_ANY,
  22066                     (h_data_p->rx_ctr & 0xFFFFFF), &lm_entry);
  22067             if (BCM_FAILURE(rv)) {
  22068                 _BCM_OAM_UNLOCK(oc);
  22069                 return (rv);
  22070             }
  22071             endpoint_info->lm_ctr_type = 
  22072                 soc_mem_field32_get(unit, mems[0], &lm_entry, LM_COUNT_TYPEf);
  22073             endpoint_info->lm_ctr_sample_size = 
  22074                 soc_mem_field32_get(unit, mems[0], &lm_entry, LM_COUNTER_SAMPLE_SIZEf);
  22075         }
  22076         endpoint_info->pri_map_id = h_data_p->pri_map_index;
  22077     }
  22078     _BCM_OAM_UNLOCK(oc);
  22079     return (BCM_E_NONE);
  22080 }
  22081 
  22082 
  22083 /*
  22084  * Function:
  22085  *     bcm_sb2_oam_endpoint_destroy
  22086  * Purpose:
  22087  *     Destroy an OAM endpoint object
  22088  * Parameters:
  22089  *     unit     - (IN) BCM device number
  22090  *     endpoint - (IN) Endpoint ID to destroy.
  22091  * result =s:
  22092  *     BCM_E_XXX
  22093  */
  22094 int
  22095 bcm_sb2_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint)
  22096 {
  22097     _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */
  22098     int rv;                 /* Operation return status.          */
  22099 
  22100     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22101     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  22102     _BCM_OAM_LOCK(oc);
  22103 
  22104     rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint);
  22105     if (BCM_FAILURE(rv)) {
  22106         LOG_ERROR(BSL_LS_BCM_OAM,
  22107                   (BSL_META_U(unit,
  22108                               "OAM(unit %d) Error: Endpoint destroy EP=%d failed - "
  22109                                "%s.\n"), unit, endpoint, bcm_errmsg(rv)));
  22110     }
  22111 
  22112     _BCM_OAM_UNLOCK(oc);
  22113     return (rv);
  22114 }
  22115 
  22116 /*
  22117  * Function:
  22118  *     bcm_sb2_oam_endpoint_destroy_all
  22119  * Purpose:
  22120  *     Destroy all OAM endpoint objects associated with a group.
  22121  * Parameters:
  22122  *     unit  - (IN) BCM device number
  22123  *     group - (IN) The OAM group whose endpoints should be destroyed
  22124  * Returns:
  22125  *     BCM_E_XXX
  22126  */
  22127 int
  22128 bcm_sb2_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group)
  22129 {
  22130     _bcm_oam_control_t    *oc; /* Pointer to OAM control structure. */
  22131     int                   rv;  /* Operation return status.          */
  22132     _bcm_oam_group_data_t *g_info_p;
  22133 
  22134     /* Get OAM device control structure. */
  22135     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22136 
  22137     /* Validate group index. */
  22138     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  22139 
  22140     _BCM_OAM_LOCK(oc);
  22141 
  22142     /* Check if the group is in use. */
  22143     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  22144     if (BCM_E_EXISTS != rv) {
  22145         _BCM_OAM_UNLOCK(oc);
  22146         LOG_ERROR(BSL_LS_BCM_OAM,
  22147                   (BSL_META_U(unit,
  22148                               "OAM(unit %d) Error: Group ID=%d does not exist.\n"),
  22149                    unit, group));
  22150         return (rv);
  22151     }
  22152 
  22153     /* Get the group data pointer. */
  22154     g_info_p = &oc->group_info[group];
  22155     rv = _bcm_sb2_oam_group_endpoints_destroy(unit, g_info_p);
  22156     if (BCM_FAILURE(rv)) {
  22157         LOG_ERROR(BSL_LS_BCM_OAM,
  22158                   (BSL_META_U(unit,
  22159                               "OAM(unit %d) Error: Group (GID=%d) endpoints destroy"
  22160                                " failed - %s.\n"), unit, group, bcm_errmsg(rv)));
  22161         _BCM_OAM_UNLOCK(oc);
  22162         return (rv);
  22163     }
  22164     _BCM_OAM_UNLOCK(oc);
  22165     return (rv);
  22166 }
  22167 
  22168 /*
  22169  * Function:
  22170  *     bcm_sb2_oam_endpoint_traverse
  22171  * Purpose:
  22172  *     Traverse the set of OAM endpoints associated with the
  22173  *     specified group, calling a specified callback for each one
  22174  * Parameters:
  22175  *     unit      - (IN) BCM device number
  22176  *     group     - (IN) The OAM group whose endpoints should be traversed
  22177  *     cb        - (IN) A pointer to the callback function to call for each OAM
  22178  *                      endpoint in the specified group
  22179  *     user_data - (IN) Pointer to user data to supply in the callback
  22180  * Returns:
  22181  *      BCM_E_XXX
  22182  */
  22183 int
  22184 bcm_sb2_oam_endpoint_traverse(int unit, bcm_oam_group_t group,
  22185                               bcm_oam_endpoint_traverse_cb cb,
  22186                               void *user_data)
  22187 {
  22188     _bcm_oam_control_t      *oc; /* Pointer to OAM control structure. */
  22189     int                     rv;  /* Operation return status.          */
  22190     bcm_oam_endpoint_info_t ep_info;
  22191     _bcm_oam_hash_data_t    *h_data_p;
  22192     _bcm_oam_ep_list_t      *cur;
  22193     _bcm_oam_group_data_t   *g_info_p;
  22194 
  22195     /* Validate input parameter. */
  22196     if (NULL == cb) {
  22197         return (BCM_E_PARAM);
  22198     }
  22199 
  22200     /* Get OAM device control structure. */
  22201     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22202 
  22203     /* Validate group index. */
  22204     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  22205 
  22206     _BCM_OAM_LOCK(oc);
  22207 
  22208     /* Check if the group is in use. */
  22209     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  22210     if (BCM_E_EXISTS != rv) {
  22211         _BCM_OAM_UNLOCK(oc);
  22212         LOG_ERROR(BSL_LS_BCM_OAM,
  22213                   (BSL_META_U(unit,
  22214                               "OAM(unit %d) Error: Group ID=%d does not exist.\n"),
  22215                    unit, group));
  22216         return (rv);
  22217     }
  22218 
  22219     /* Get the group data pointer. */
  22220     g_info_p = &oc->group_info[group];
  22221 
  22222     /* Get the endpoint list head pointer. */
  22223     cur = *(g_info_p->ep_list);
  22224     if (NULL == cur) {
  22225         _BCM_OAM_UNLOCK(oc);
  22226         LOG_DEBUG(BSL_LS_BCM_OAM,
  22227                   (BSL_META_U(unit,
  22228                               "OAM(unit %d) Info: No endpoints in group GID=%d.\n"),
  22229                    unit, group));
  22230         return (BCM_E_NONE);
  22231     }
  22232 
  22233     /* Traverse to the tail of the list. */
  22234     while (NULL != cur->next) {
  22235         LOG_DEBUG(BSL_LS_BCM_OAM,
  22236                   (BSL_META_U(unit,
  22237                               "OAM(unit %d) Info: GID=%d EP:%d.\n"),
  22238                    unit, cur->ep_data_p->group_index, cur->ep_data_p->ep_id));
  22239         cur = cur->next;
  22240     }
  22241 
  22242     while (NULL != cur) {
  22243         h_data_p = cur->ep_data_p;
  22244         if (NULL == h_data_p) {
  22245             LOG_ERROR(BSL_LS_BCM_OAM,
  22246                       (BSL_META_U(unit,
  22247                                   "OAM(unit %d) Error: Group=%d endpoints access failed -"
  22248                                    " %s.\n"), unit, group, bcm_errmsg(BCM_E_INTERNAL)));
  22249             _BCM_OAM_UNLOCK(oc);
  22250             return (BCM_E_INTERNAL);
  22251         }
  22252         bcm_oam_endpoint_info_t_init(&ep_info);
  22253 
  22254         rv = bcm_sb2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info);
  22255         if (BCM_FAILURE(rv)) {
  22256             _BCM_OAM_UNLOCK(oc);
  22257             LOG_ERROR(BSL_LS_BCM_OAM,
  22258                       (BSL_META_U(unit,
  22259                                   "OAM(unit %d) Error: EP=%d info get failed %s.\n"),
  22260                        unit, h_data_p->ep_id, bcm_errmsg(rv)));
  22261             return (rv);
  22262         }
  22263 
  22264         rv = cb(unit, &ep_info, user_data);
  22265         if (BCM_FAILURE(rv)) {
  22266             _BCM_OAM_UNLOCK(oc);
  22267             LOG_ERROR(BSL_LS_BCM_OAM,
  22268                       (BSL_META_U(unit,
  22269                                   "OAM(unit %d) Error: EP=%d callback failed - %s.\n"),
  22270                        unit, h_data_p->ep_id, bcm_errmsg(rv)));
  22271             return (rv);
  22272         }
  22273         cur = cur->prev;
  22274     }
  22275     _BCM_OAM_UNLOCK(oc);
  22276     return (rv);
  22277 }
  22278 
  22279 /*
  22280  * Function:
  22281  *     bcm_sb2_oam_pm_event_register
  22282  * Purpose:
  22283  *     Register a callback for handling OAM PM events
  22284  * Parameters:
  22285  *     unit        - (IN) BCM device number
  22286  *     event_types - (IN) The set of OAM PM events for which the specified
  22287  *                        callback should be called.
  22288  *     cb          - (IN) A pointer to the callback function to call for
  22289  *                        the specified OAM PM events
  22290  *     user_data   - (IN) Pointer to user data to supply in the callback
  22291  * Returns:
  22292  *      BCM_E_XXX
  22293  */
  22294 int
  22295 bcm_sb2_oam_pm_event_register(int unit, bcm_oam_event_types_t event_types,
  22296                            bcm_oam_pm_event_cb cb, void *user_data)
  22297 {
  22298     _bcm_oam_control_t       *oc;
  22299     _bcm_oam_pm_event_handler_t *event_h_p;
  22300     _bcm_oam_pm_event_handler_t *prev_p = NULL;
  22301     bcm_oam_event_type_t     e_type;
  22302     int                      rv;             /* Operation return status. */
  22303     uint16                   reply_len = 0;
  22304     uint8                    msg_class = 0;
  22305     uint8                    msg_subclass = 0;
  22306     uint8                    msg_reply_subclass = 0;
  22307     uint8                   *dma_buffer = NULL;
  22308 
  22309     /* Validate event callback input parameter. */
  22310     if (NULL == cb) {
  22311         return (BCM_E_PARAM);
  22312     }
  22313     
  22314     /* Validate the event type to be of PM event type */
  22315     if (!(_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types))) {
  22316         return (BCM_E_PARAM);
  22317     }
  22318 
  22319     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22320 
  22321     _BCM_OAM_LOCK(oc);
  22322 
  22323     for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL;
  22324          event_h_p = event_h_p->next_p) {
  22325         if (event_h_p->cb == cb) {
  22326             break;
  22327         }
  22328         prev_p = event_h_p;
  22329     }
  22330 
  22331     if (NULL == event_h_p) {
  22332 
  22333         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_pm_event_handler_t,
  22334              sizeof(_bcm_oam_pm_event_handler_t), "OAM event handler");
  22335 
  22336         if (NULL == event_h_p) {
  22337             LOG_ERROR(BSL_LS_BCM_OAM,
  22338                       (BSL_META_U(unit,
  22339                                   "OAM(unit %d) Error: Event handler alloc failed -"
  22340                                    " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY)));
  22341             _BCM_OAM_UNLOCK(oc);
  22342             return (BCM_E_MEMORY);
  22343         }
  22344 
  22345         event_h_p->next_p = NULL;
  22346         event_h_p->cb = cb;
  22347 
  22348         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
  22349         if (prev_p != NULL) {
  22350             prev_p->next_p = event_h_p;
  22351         } else {
  22352             oc->pm_event_handler_list_p = event_h_p;
  22353         }
  22354     }
  22355 
  22356     for (e_type = bcmOAMEventBHHRawData; 
  22357          e_type <= bcmOAMEventMplsLmDmRawData; 
  22358          ++e_type) {
  22359         if (SHR_BITGET(event_types.w, e_type)) {
  22360             if (!SHR_BITGET(event_h_p->event_types.w, e_type)) {
  22361                 /* Add this event to the registered events list. */
  22362                 SHR_BITSET(event_h_p->event_types.w, e_type);
  22363                 if (e_type ==  bcmOAMEventBHHRawData) {
  22364                     msg_class   = MOS_MSG_CLASS_BHH; 
  22365                     msg_subclass = 
  22366                         MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET;
  22367                     msg_reply_subclass = 
  22368                         MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET_REPLY;
  22369 #if defined (INCLUDE_BHH)
  22370                     dma_buffer = oc->pm_bhh_dma_buffer;
  22371 #endif
  22372                 }
  22373                 if (e_type == bcmOAMEventMplsLmDmRawData) {
  22374                     msg_class   = MOS_MSG_CLASS_MPLS_LM_DM; 
  22375                     msg_subclass = 
  22376                         MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET;
  22377                     msg_reply_subclass = 
  22378                         MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY;
  22379 #if defined (INCLUDE_MPLS_LM_DM)
  22380                     dma_buffer = oc->pm_mpls_lm_dm_dma_buffer;
  22381 #endif
  22382                 }
  22383                 if (e_type == bcmOAMEventEthLmDmRawData) {
  22384                     msg_class   = MOS_MSG_CLASS_ETH_LM_DM; 
  22385                     msg_subclass = 
  22386                         MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_SET;
  22387                     msg_reply_subclass = 
  22388                         MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY;
  22389 #if defined (INCLUDE_ETH_LM_DM)
  22390                     dma_buffer = oc->pm_eth_lm_dm_dma_buffer;
  22391 #endif
  22392                 }
  22393                 rv = _bcm_sb2_oam_pm_msg_send_receive 
  22394                     (unit, msg_class, 
  22395                      msg_subclass,
  22396                      0, soc_cm_l2p(unit, dma_buffer), /* Send dma_buffer ptr in data */
  22397                      msg_reply_subclass,
  22398                      &reply_len);
  22399 
  22400                 if(BCM_FAILURE(rv)) {
  22401                     _BCM_OAM_UNLOCK(oc);
  22402                     return BCM_E_INTERNAL;
  22403                 }
  22404                 oc->pm_event_handler_cnt[e_type] += 1;
  22405             }
  22406         }
  22407     }
  22408 
  22409 
  22410     event_h_p->user_data = user_data;
  22411 
  22412     _BCM_OAM_UNLOCK(oc);
  22413 
  22414     return (BCM_E_NONE);
  22415 }
  22416 
  22417 /*
  22418  * Function:
  22419  *     bcm_sb2_oam_event_register
  22420  * Purpose:
  22421  *     Register a callback for handling OAM events
  22422  * Parameters:
  22423  *     unit        - (IN) BCM device number
  22424  *     event_types - (IN) The set of OAM events for which the specified
  22425  *                        callback should be called.
  22426  *     cb          - (IN) A pointer to the callback function to call for
  22427  *                        the specified OAM events
  22428  *     user_data   - (IN) Pointer to user data to supply in the callback
  22429  * Returns:
  22430  *      BCM_E_XXX
  22431  */
  22432 int
  22433 bcm_sb2_oam_event_register(int unit, bcm_oam_event_types_t event_types,
  22434                            bcm_oam_event_cb cb, void *user_data)
  22435 {
  22436     _bcm_oam_control_t       *oc;
  22437     _bcm_oam_event_handler_t *event_h_p;
  22438     _bcm_oam_event_handler_t *prev_p = NULL;
  22439     bcm_oam_event_type_t     e_type;
  22440     uint32                   rval;
  22441     int                      hw_update = 0;
  22442     uint32                   event_bmp;
  22443     int                      rv;             /* Operation return status. */
  22444 
  22445     /* Validate event callback input parameter. */
  22446     if (NULL == cb) {
  22447         return (BCM_E_PARAM);
  22448     }
  22449 
  22450     /* Check if an event is set for register in the events bitmap. */
  22451     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  22452     if (0 == event_bmp) {
  22453         /* No events specified. */
  22454         LOG_ERROR(BSL_LS_BCM_OAM,
  22455                   (BSL_META_U(unit,
  22456                               "OAM(unit %d) Error: No events specified for register.\n"),
  22457                    unit));
  22458         return (BCM_E_PARAM);
  22459     }
  22460 
  22461     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22462 
  22463     _BCM_OAM_LOCK(oc);
  22464 
  22465     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  22466          event_h_p = event_h_p->next_p) {
  22467         if (event_h_p->cb == cb) {
  22468             break;
  22469         }
  22470         prev_p = event_h_p;
  22471     }
  22472 
  22473     if (NULL == event_h_p) {
  22474 
  22475         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t,
  22476              sizeof(_bcm_oam_event_handler_t), "OAM event handler");
  22477 
  22478         if (NULL == event_h_p) {
  22479             LOG_ERROR(BSL_LS_BCM_OAM,
  22480                       (BSL_META_U(unit,
  22481                                   "OAM(unit %d) Error: Event handler alloc failed -"
  22482                                    " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY)));
  22483             _BCM_OAM_UNLOCK(oc);
  22484             return (BCM_E_MEMORY);
  22485         }
  22486 
  22487         event_h_p->next_p = NULL;
  22488         event_h_p->cb = cb;
  22489 
  22490         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
  22491         if (prev_p != NULL) {
  22492             prev_p->next_p = event_h_p;
  22493         } else {
  22494             oc->event_handler_list_p = event_h_p;
  22495         }
  22496     }
  22497 
  22498     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  22499     if (BCM_FAILURE(rv)) {
  22500         _BCM_OAM_UNLOCK(oc);
  22501         LOG_ERROR(BSL_LS_BCM_OAM,
  22502                   (BSL_META_U(unit,
  22503                               "OAM(unit %d) Error: CCM interrupt control read failed -"
  22504                                " %s.\n"), unit, bcm_errmsg(rv)));
  22505         return (rv);
  22506     }
  22507 
  22508     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  22509         if (SHR_BITGET(event_types.w, e_type)) {
  22510             if(soc_feature(unit, soc_feature_bhh)) {
  22511 #if defined(INCLUDE_BHH)
  22512                 /*
  22513                 * BHH events are generated by the uKernel
  22514                 */
  22515                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  22516                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  22517                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  22518                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  22519                     (e_type == bcmOAMEventBHHCCMState) ||
  22520                     (e_type == bcmOAMEventBHHCCMRdi) ||
  22521                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  22522                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  22523                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  22524                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  22525                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  22526                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  22527                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  22528                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  22529                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  22530                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  22531                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 
  22532                     (e_type == bcmOAMEventBhhPmCounterRollover) ||
  22533                     (e_type == bcmOAMEventCsfLos) ||
  22534                     (e_type == bcmOAMEventCsfFdi) ||
  22535                     (e_type == bcmOAMEventCsfRdi) ||
  22536                     (e_type == bcmOAMEventCsfDci)) {
  22537                     SHR_BITSET(event_h_p->event_types.w, e_type);
  22538                     oc->event_handler_cnt[e_type] += 1;
  22539                     continue;
  22540                 }
  22541 #endif
  22542             }
  22543             if ((e_type == bcmOAMEventEthLmDmPmCounterRollover)) {
  22544 #if defined(INCLUDE_ETH_LM_DM)
  22545                 /*
  22546                  * ETH_LM_DM events are generated by the uKernel
  22547                  */
  22548                 SHR_BITSET(event_h_p->event_types.w, e_type);
  22549                 oc->event_handler_cnt[e_type] += 1;
  22550                 continue;
  22551 #endif
  22552             }
  22553             if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) {
  22554 #if defined(INCLUDE_MPLS_LM_DM)
  22555                 /*
  22556                  * MPLS_LM_DM events are generated by the uKernel
  22557                  */
  22558                 SHR_BITSET(event_h_p->event_types.w, e_type);
  22559                 oc->event_handler_cnt[e_type] += 1;
  22560                 continue;
  22561 #endif
  22562             }
  22563 
  22564             if (!soc_reg_field_valid
  22565                     (unit, CCM_INTERRUPT_CONTROLr,
  22566                      _sb2_oam_intr_en_fields[e_type].field)) {
  22567                 continue;
  22568             }
  22569 
  22570             if (!SHR_BITGET(event_h_p->event_types.w, e_type)) {
  22571                 /* Add this event to the registered events list. */
  22572                 SHR_BITSET(event_h_p->event_types.w, e_type);
  22573                 oc->event_handler_cnt[e_type] += 1;
  22574                 if (1 == oc->event_handler_cnt[e_type]) {
  22575                     hw_update = 1;
  22576                      soc_reg_field_set
  22577                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  22578                          _sb2_oam_intr_en_fields[e_type].field, 1);
  22579                 }
  22580             }
  22581         }
  22582     }
  22583 
  22584     event_h_p->user_data = user_data;
  22585 
  22586     if (1 == hw_update) {
  22587         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  22588         if (BCM_FAILURE(rv)) {
  22589             _BCM_OAM_UNLOCK(oc);
  22590             LOG_ERROR(BSL_LS_BCM_OAM,
  22591                       (BSL_META_U(unit,
  22592                                   "OAM(unit %d) Error: CCM interrupt control write failed -"
  22593                                    " %s.\n"), unit, bcm_errmsg(rv)));
  22594             return (rv);
  22595         }
  22596     }
  22597     if (soc_feature(unit, soc_feature_bhh)) {
  22598 #if defined(INCLUDE_BHH)
  22599         /*
  22600          * Update BHH Events mask
  22601          */
  22602         rv = _bcm_sb2_oam_bhh_event_mask_set(unit);
  22603 #endif /* INCLUDE_BHH */
  22604     }
  22605 #if defined(INCLUDE_ETH_LM_DM)
  22606     if(!oc->eth_lm_dm_ukernel_not_ready) {
  22607         /*
  22608          * Update ETH_LM_DM Events mask
  22609          */
  22610         rv = _bcm_sb2_eth_lm_dm_event_mask_set(unit);
  22611         if (BCM_FAILURE(rv)) {
  22612             _BCM_OAM_UNLOCK(oc);
  22613             LOG_ERROR(BSL_LS_BCM_OAM,
  22614                     (BSL_META_U(unit,
  22615                                 "OAM(unit %d) Error: failed to set ETH LM DM event mask-"
  22616                                 " %s.\n"), unit, bcm_errmsg(rv)));
  22617             return (rv);
  22618         }
  22619     }
  22620 #endif
  22621 #if defined(INCLUDE_MPLS_LM_DM)
  22622     if(oc->mpls_lm_dm_ukernel_ready) {
  22623         /*
  22624          * Update MPLS_LM_DM Events mask
  22625          */
  22626         rv = _bcm_sb2_mpls_lm_dm_event_mask_set(unit);
  22627         if (BCM_FAILURE(rv)) {
  22628             _BCM_OAM_UNLOCK(oc);
  22629             LOG_ERROR(BSL_LS_BCM_OAM,
  22630                     (BSL_META_U(unit,
  22631                                 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-"
  22632                                 " %s.\n"), unit, bcm_errmsg(rv)));
  22633             return (rv);
  22634         }
  22635     }
  22636 #endif
  22637 
  22638     _BCM_OAM_UNLOCK(oc);
  22639 
  22640     return (BCM_E_NONE);
  22641 }
  22642 
  22643 /*
  22644  * Function:
  22645  *     bcm_sb2_oam_event_unregister
  22646  * Purpose:
  22647  *     Remove a registered event from the event handler list.
  22648  * Parameters:
  22649  *     unit        - (IN) BCM device number
  22650  *     event_types - (IN) The set of OAM events for which the specified
  22651  *                        callback should not be called
  22652  *     cb          - (IN) A pointer to the callback function to unregister
  22653  *                        from the specified OAM events
  22654  * Returns:
  22655  *      BCM_E_XXX
  22656  */
  22657 int
  22658 bcm_sb2_oam_event_unregister(int unit, bcm_oam_event_types_t event_types,
  22659                              bcm_oam_event_cb cb)
  22660 {
  22661     _bcm_oam_control_t       *oc;
  22662     _bcm_oam_event_handler_t *event_h_p;
  22663     _bcm_oam_event_handler_t *prev_p = NULL;
  22664     bcm_oam_event_type_t     e_type;
  22665     uint32                   rval;
  22666     int                      hw_update = 0;
  22667     uint32                   event_bmp;
  22668     int                      rv;             /* Operation return status. */
  22669   
  22670     /* Validate event callback input parameter. */
  22671     if (NULL == cb) {
  22672         return (BCM_E_PARAM);
  22673     }
  22674 
  22675     /* Check if an event is set for unregister in the events bitmap. */
  22676     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  22677     if (0 == event_bmp) {
  22678         /* No events specified. */
  22679         LOG_ERROR(BSL_LS_BCM_OAM,
  22680                   (BSL_META_U(unit,
  22681                               "OAM(unit %d) Error: No events specified for register.\n"),
  22682                    unit));
  22683         return (BCM_E_PARAM);
  22684     }
  22685 
  22686     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22687 
  22688     _BCM_OAM_LOCK(oc);
  22689 
  22690     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  22691          event_h_p = event_h_p->next_p) {
  22692         if (event_h_p->cb == cb) {
  22693             break;
  22694         }
  22695         prev_p = event_h_p;
  22696     }
  22697 
  22698     if (NULL == event_h_p) {
  22699         _BCM_OAM_UNLOCK(oc);
  22700         return (BCM_E_NOT_FOUND);
  22701     }
  22702  
  22703     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  22704     if (BCM_FAILURE(rv)) {
  22705         _BCM_OAM_UNLOCK(oc);
  22706         LOG_ERROR(BSL_LS_BCM_OAM,
  22707                   (BSL_META_U(unit,
  22708                               "OAM(unit %d) Error: CCM interrupt control read failed -"
  22709                                " %s.\n"), unit, bcm_errmsg(rv)));
  22710         return (rv);
  22711     }
  22712 
  22713     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  22714 
  22715         if (SHR_BITGET(event_types.w, e_type)) {
  22716             if(soc_feature(unit, soc_feature_bhh)) {
  22717 #if defined(INCLUDE_BHH)
  22718                 /*
  22719                 * BHH events are generated by the uKernel
  22720                 */
  22721                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  22722                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  22723                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  22724                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  22725                     (e_type == bcmOAMEventBHHCCMState) ||
  22726                     (e_type == bcmOAMEventBHHCCMRdi) ||
  22727                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  22728                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  22729                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  22730                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  22731                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  22732                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  22733                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  22734                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  22735                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  22736                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  22737                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  22738                     (e_type == bcmOAMEventBhhPmCounterRollover) ||
  22739                     (e_type == bcmOAMEventCsfLos) ||
  22740                     (e_type == bcmOAMEventCsfFdi) ||
  22741                     (e_type == bcmOAMEventCsfRdi) ||
  22742                     (e_type == bcmOAMEventCsfDci)) {
  22743                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  22744                     oc->event_handler_cnt[e_type] -= 1;
  22745                     continue;
  22746                 }
  22747 #endif
  22748             }
  22749             if ((e_type == bcmOAMEventEthLmDmPmCounterRollover)) {
  22750 #if defined(INCLUDE_ETH_LM_DM)
  22751                 /*
  22752                  * ETH_LM_DM events are generated by the uKernel
  22753                  */
  22754                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  22755                 oc->event_handler_cnt[e_type] -= 1;
  22756                 continue;
  22757 #endif
  22758             }
  22759             if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) {
  22760 #if defined(INCLUDE_MPLS_LM_DM)
  22761                 /*
  22762                  * MPLS_LM_DM events are generated by the uKernel
  22763                  */
  22764                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  22765                 oc->event_handler_cnt[e_type] -= 1;
  22766                 continue;
  22767 #endif
  22768             }
  22769 
  22770             if (!soc_reg_field_valid
  22771                     (unit, CCM_INTERRUPT_CONTROLr,
  22772                      _sb2_oam_intr_en_fields[e_type].field)) {
  22773                 _BCM_OAM_UNLOCK(oc);
  22774                 return (BCM_E_UNAVAIL);
  22775             }
  22776 
  22777             if ((oc->event_handler_cnt[e_type] > 0)
  22778                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
  22779 
  22780                 /* Remove this event from the registered events list. */
  22781                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  22782 
  22783                 oc->event_handler_cnt[e_type] -= 1;
  22784 
  22785                 if (0 == oc->event_handler_cnt[e_type]) {
  22786                     hw_update = 1;
  22787                      soc_reg_field_set
  22788                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  22789                          _sb2_oam_intr_en_fields[e_type].field, 0);
  22790                 }
  22791             }
  22792         }
  22793     }
  22794 
  22795     if (1 == hw_update) {
  22796         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  22797         if (BCM_FAILURE(rv)) {
  22798             _BCM_OAM_UNLOCK(oc);
  22799             LOG_ERROR(BSL_LS_BCM_OAM,
  22800                       (BSL_META_U(unit,
  22801                                   "OAM(unit %d) Error: CCM interrupt control write failed -"
  22802                                    " %s.\n"), unit, bcm_errmsg(rv)));
  22803             return (rv);
  22804         }
  22805     }
  22806 
  22807     SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp);
  22808 
  22809     if (0 == event_bmp) {
  22810 
  22811         if (NULL != prev_p) {
  22812 
  22813             prev_p->next_p = event_h_p->next_p;
  22814             
  22815         } else {
  22816 
  22817             oc->event_handler_list_p = event_h_p->next_p;
  22818 
  22819         }
  22820         sal_free(event_h_p);
  22821     }
  22822     if(soc_feature(unit, soc_feature_bhh)) {
  22823 #if defined(INCLUDE_BHH)
  22824         /*
  22825          * Update BHH Events mask
  22826          */
  22827         rv = _bcm_sb2_oam_bhh_event_mask_set(unit);
  22828 #endif /* INCLUDE_BHH */
  22829     }
  22830 #if defined(INCLUDE_ETH_LM_DM)
  22831     if(!oc->eth_lm_dm_ukernel_not_ready) {
  22832         /*
  22833          * Update ETH_LM_DM Events mask
  22834          */
  22835         rv = _bcm_sb2_eth_lm_dm_event_mask_set(unit);
  22836         if (BCM_FAILURE(rv)) {
  22837             _BCM_OAM_UNLOCK(oc);
  22838             LOG_ERROR(BSL_LS_BCM_OAM,
  22839                     (BSL_META_U(unit,
  22840                                 "OAM(unit %d) Error: failed to set ETH LM DM event mask-"
  22841                                 " %s.\n"), unit, bcm_errmsg(rv)));
  22842             return (rv);
  22843         }
  22844     }
  22845 #endif
  22846 #if defined(INCLUDE_MPLS_LM_DM)
  22847     if(oc->mpls_lm_dm_ukernel_ready) {
  22848         /*
  22849          * Update MPLS_LM_DM Events mask
  22850          */
  22851         rv = _bcm_sb2_mpls_lm_dm_event_mask_set(unit);
  22852         if (BCM_FAILURE(rv)) {
  22853             _BCM_OAM_UNLOCK(oc);
  22854             LOG_ERROR(BSL_LS_BCM_OAM,
  22855                     (BSL_META_U(unit,
  22856                                 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-"
  22857                                 " %s.\n"), unit, bcm_errmsg(rv)));
  22858             return (rv);
  22859         }
  22860     }
  22861 #endif
  22862 
  22863     _BCM_OAM_UNLOCK(oc);
  22864     return (BCM_E_NONE);
  22865 }
  22866 
  22867 /*
  22868  * Function:
  22869  *     bcm_sb2_oam_pm_event_unregister
  22870  * Purpose:
  22871  *     Remove a registered event from the event handler list.
  22872  * Parameters:
  22873  *     unit        - (IN) BCM device number
  22874  *     event_types - (IN) The set of OAM PM events for which the specified
  22875  *                        callback should not be called
  22876  *     cb          - (IN) A pointer to the callback function to unregister
  22877  *                        from the specified OAM PM events
  22878  * Returns:
  22879  *      BCM_E_XXX
  22880  */
  22881 int
  22882 bcm_sb2_oam_pm_event_unregister(int unit, bcm_oam_event_types_t event_types,
  22883                              bcm_oam_pm_event_cb cb)
  22884 {
  22885     _bcm_oam_control_t       *oc;
  22886     _bcm_oam_pm_event_handler_t *event_h_p;
  22887     _bcm_oam_pm_event_handler_t *prev_p = NULL;
  22888     bcm_oam_event_type_t     e_type;
  22889     int                      rv;             /* Operation return status. */
  22890     uint8                    msg_class = 0;
  22891     uint16                   reply_len = 0;
  22892     uint8                    msg_subclass = 0;
  22893     uint8                    msg_reply_subclass = 0;
  22894   
  22895     /* Validate event callback input parameter. */
  22896     if (NULL == cb) {
  22897         return (BCM_E_PARAM);
  22898     }
  22899 
  22900     /* Validate the event type to be of PM event type */
  22901     if (!_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types)) {
  22902         return (BCM_E_PARAM);
  22903     }
  22904 
  22905     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  22906 
  22907     _BCM_OAM_LOCK(oc);
  22908 
  22909     for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL;
  22910          event_h_p = event_h_p->next_p) {
  22911         if (event_h_p->cb == cb) {
  22912             break;
  22913         }
  22914         prev_p = event_h_p;
  22915     }
  22916 
  22917     if (NULL == event_h_p) {
  22918         _BCM_OAM_UNLOCK(oc);
  22919         return (BCM_E_NOT_FOUND);
  22920     }
  22921  
  22922     for (e_type = bcmOAMEventBHHRawData;
  22923          e_type <= bcmOAMEventMplsLmDmRawData; 
  22924          ++e_type) {
  22925 
  22926         if (SHR_BITGET(event_types.w, e_type)) {
  22927             if ((oc->pm_event_handler_cnt[e_type] > 0)
  22928                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
  22929 
  22930                 /* Remove this event from the registered events list. */
  22931                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  22932 
  22933                 oc->pm_event_handler_cnt[e_type] -= 1;
  22934 
  22935                 if (oc->pm_event_handler_cnt[e_type] == 0) {
  22936                     /* There are no event handlers for this event type
  22937                      * Send msg to uKernel to stop notifying this event.
  22938                      */
  22939                     if (e_type == bcmOAMEventBHHRawData) {
  22940                         msg_class  = MOS_MSG_CLASS_BHH; 
  22941                         msg_subclass = 
  22942                             MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET;
  22943                         msg_reply_subclass =
  22944                             MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET_REPLY;
  22945                     }
  22946                     if (e_type == bcmOAMEventMplsLmDmRawData) {
  22947                         msg_class  = MOS_MSG_CLASS_MPLS_LM_DM; 
  22948                         msg_subclass = 
  22949                             MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET;
  22950                         msg_reply_subclass =
  22951                             MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY;
  22952                     }
  22953                     if (e_type == bcmOAMEventEthLmDmRawData) {
  22954                         msg_class  = MOS_MSG_CLASS_ETH_LM_DM; 
  22955                         msg_subclass = 
  22956                             MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_UNSET;
  22957                         msg_reply_subclass = 
  22958                             MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY;
  22959                     }
  22960                     rv = _bcm_sb2_oam_pm_msg_send_receive 
  22961                         (unit, msg_class, 
  22962                          msg_subclass,
  22963                          0, 0, 
  22964                          msg_reply_subclass,
  22965                          &reply_len);
  22966                     if(BCM_FAILURE(rv)) {
  22967                         _BCM_OAM_UNLOCK(oc);
  22968                         return BCM_E_INTERNAL;
  22969                     }
  22970                 }
  22971             }
  22972         }
  22973     }
  22974 
  22975     if (!_BCM_SB2_EVENT_TYPE_PM_EVENT(event_h_p->event_types)) {
  22976         /* No more PM events for this callback registered 
  22977            Delete the node. */
  22978         if (NULL != prev_p) {
  22979             prev_p->next_p = event_h_p->next_p;
  22980 
  22981         } else {
  22982             oc->pm_event_handler_list_p = event_h_p->next_p;
  22983         }
  22984         sal_free(event_h_p);
  22985     }
  22986 
  22987     _BCM_OAM_UNLOCK(oc);
  22988     return (BCM_E_NONE);
  22989 }
  22990 
  22991 /*
  22992  * Function:
  22993  *     bcm_sb2_oam_endpoint_action_set
  22994  * Purpose:
  22995  *     Remove a registered event from the event handler list.
  22996  * Parameters:
  22997  *     unit        - (IN) BCM device number
  22998  *     endpoint    - (IN) Endpoint id
  22999  *     action      - (IN) Set of OAM endpoint actions, for a set of
  23000  *                        opcodes specified.
  23001  * Returns:
  23002  *      BCM_E_XXX
  23003  *  In order to put the opcodes into opcode group1 and group2, first call the
  23004  *  action set API with opcode action and set of opcodes that need to use 
  23005  *  this action. This will put all these opcodes under group1. To put
  23006  *  the opcode to group2, call the set API with an action(with all the opcodes 
  23007  *  that need this action) which is differing compared to group1. This will 
  23008  *  classify the opcode to group2 
  23009  */
  23010 int bcm_sb2_oam_endpoint_action_set(int unit, bcm_oam_endpoint_t endpoint, 
  23011                                     bcm_oam_endpoint_action_t *action) 
  23012 {
  23013     int            rv = BCM_E_NONE;  /* Operation return status.          */
  23014     _bcm_oam_hash_data_t *h_data_p;  /* Pointer to endpoint hash data.    */
  23015     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  23016     void                 *entries[1]; 
  23017     oam_opcode_control_profile_entry_t *opcode_profile = NULL;
  23018     egr_oam_opcode_control_profile_entry_t *egr_opcode_profile = NULL;
  23019     soc_profile_mem_t    *profile_mem_ptr;
  23020     soc_mem_t     ma_index_mem = MA_INDEXm;
  23021     ma_index_entry_t     ma_idx_entry;   /* MA_INDEX table entry buffer.     */
  23022     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/
  23023     void                 *ma_idx_ptr;
  23024     int                  ma_offset = 0;
  23025     uint32               profile_index = 0,old_profile_index = 0;
  23026     char                 free_old_profile = 0;
  23027     /*setting default value to 0 whcih will be converted to 1 
  23028      * if opcode control profile set is touched */
  23029     uint8                opcode_profile_changed = 0;
  23030 
  23031     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  23032     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  23033     _BCM_OAM_LOCK(oc);
  23034 
  23035     /* Check endpoint status. */
  23036     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint);
  23037     if ((BCM_E_EXISTS != rv)) {
  23038         /* Endpoint not in use. */
  23039         LOG_ERROR(BSL_LS_BCM_OAM,
  23040                   (BSL_META_U(unit,
  23041                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  23042                    unit, endpoint, bcm_errmsg(rv)));
  23043         _BCM_OAM_UNLOCK(oc);
  23044         return (rv);
  23045     }
  23046 
  23047     h_data_p =  &oc->oam_hash_data[endpoint];
  23048     if (NULL == h_data_p) {
  23049         _BCM_OAM_UNLOCK(oc);
  23050         return (BCM_E_INTERNAL);
  23051     }
  23052 
  23053     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  23054         egr_opcode_profile = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE,
  23055                 "egr opcode profile");
  23056         if(!egr_opcode_profile) {
  23057             _BCM_OAM_UNLOCK(oc);
  23058             return BCM_E_MEMORY;
  23059         }
  23060         sal_memset(egr_opcode_profile, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE);
  23061         entries[0] = egr_opcode_profile;
  23062         profile_mem_ptr =  &oc->egr_oam_opcode_control_profile;
  23063         ma_index_mem = EGR_MA_INDEXm;
  23064         ma_idx_ptr = &egr_ma_idx_entry; 
  23065     } else {
  23066         opcode_profile = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE,
  23067                 "opcode profile");
  23068         if(!opcode_profile) {
  23069             _BCM_OAM_UNLOCK(oc);
  23070             return BCM_E_MEMORY;
  23071         }
  23072         sal_memset(opcode_profile, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE);
  23073         entries[0] = opcode_profile;
  23074         profile_mem_ptr =  &oc->oam_opcode_control_profile;
  23075         ma_idx_ptr = &ma_idx_entry; 
  23076     }
  23077 
  23078     /* Get MA_INDEX offset  */
  23079     rv = _bcm_sb2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset);
  23080 
  23081     h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset;
  23082     
  23083     /* Using the profile index, get the profile */
  23084     if ((h_data_p->profile_index == _BCM_OAM_INVALID_INDEX) ||
  23085         (h_data_p->profile_index == 0)) {
  23086       /* No profile exists or default profile is used, create one */
  23087       /* convert action into opcode profile entry */
  23088         rv = _bcm_sb2_oam_convert_action_to_opcode_entry(unit, action, 
  23089                                                     endpoint, 
  23090                                                     entries[0],
  23091                                                     &opcode_profile_changed);
  23092         if (BCM_FAILURE(rv)) {
  23093             _BCM_OAM_UNLOCK(oc);
  23094             LOG_ERROR(BSL_LS_BCM_OAM,
  23095                       (BSL_META_U(unit,
  23096                                   "OAM(unit %d) Error: Failed to convert action to "
  23097                                   "profile -" " %s.\n"), unit, bcm_errmsg(rv)));
  23098             if(opcode_profile) {
  23099                 sal_free(opcode_profile);
  23100             }
  23101             if(egr_opcode_profile) {
  23102                 sal_free(egr_opcode_profile);
  23103             }
  23104             return (rv);
  23105         }
  23106         if(opcode_profile_changed) {
  23107             rv = soc_profile_mem_add(unit, profile_mem_ptr,
  23108                     (void *)entries, _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, 
  23109                     &profile_index);
  23110             if (BCM_FAILURE(rv)) {
  23111                 _BCM_OAM_UNLOCK(oc);
  23112                 LOG_ERROR(BSL_LS_BCM_OAM,
  23113                         (BSL_META_U(unit,
  23114                                     "OAM(unit %d) Error: Soc profile mem add failed -"
  23115                                     " %s.\n"), unit, bcm_errmsg(rv)));
  23116                 if(opcode_profile) {
  23117                     sal_free(opcode_profile);
  23118                 }
  23119                 if(egr_opcode_profile) {
  23120                     sal_free(egr_opcode_profile);
  23121                 }
  23122                 return (rv);
  23123             }
  23124         }
  23125     } else {
  23126         free_old_profile = 1;
  23127         old_profile_index = h_data_p->profile_index;
  23128 
  23129         rv = soc_profile_mem_get(unit, profile_mem_ptr,
  23130                 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(old_profile_index),
  23131                 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, entries);
  23132         if (BCM_FAILURE(rv)) {
  23133             _BCM_OAM_UNLOCK(oc);
  23134             LOG_ERROR(BSL_LS_BCM_OAM,
  23135                       (BSL_META_U(unit,
  23136                                   "OAM(unit %d) Error: Soc profile mem get failed -"
  23137                                    " %s.\n"), unit, bcm_errmsg(rv)));
  23138             if(opcode_profile) {
  23139                 sal_free(opcode_profile);
  23140             }
  23141             if(egr_opcode_profile) {
  23142                 sal_free(egr_opcode_profile);
  23143             }
  23144             return (rv);
  23145         }
  23146 
  23147         /* convert action into opcode profile entry */
  23148         _bcm_sb2_oam_convert_action_to_opcode_entry(unit, action, 
  23149                                                     endpoint, 
  23150                                                     entries[0],
  23151                                                     &opcode_profile_changed);
  23152 
  23153         /* Add new profile */
  23154         rv = soc_profile_mem_add(unit, profile_mem_ptr,
  23155                                  (void *)entries, _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, 
  23156                                  &profile_index);
  23157         if (BCM_FAILURE(rv)) {
  23158             _BCM_OAM_UNLOCK(oc);
  23159             LOG_ERROR(BSL_LS_BCM_OAM,
  23160                       (BSL_META_U(unit,
  23161                                   "OAM(unit %d) Error: Soc profile mem add failed -"
  23162                                    " %s.\n"), unit, bcm_errmsg(rv)));
  23163             if(opcode_profile) {
  23164                 sal_free(opcode_profile);
  23165             }
  23166             if(egr_opcode_profile) {
  23167                 sal_free(egr_opcode_profile);
  23168             }
  23169             return (rv);
  23170         }
  23171     } 
  23172     /* Set OAM opcode control profile table index. */
  23173     rv = soc_mem_read(unit, ma_index_mem, MEM_BLOCK_ANY, 
  23174                       h_data_p->local_rx_index, ma_idx_ptr);
  23175     if (BCM_FAILURE(rv)) {
  23176         _BCM_OAM_UNLOCK(oc);
  23177         LOG_ERROR(BSL_LS_BCM_OAM,
  23178                   (BSL_META_U(unit,
  23179                               "OAM(unit %d) Error: MA index table entry  read failed  "
  23180                               "%s.\n"), unit,  bcm_errmsg(rv)));
  23181         if(opcode_profile) {
  23182             sal_free(opcode_profile);
  23183         }
  23184         if(egr_opcode_profile) {
  23185             sal_free(egr_opcode_profile);
  23186         }
  23187         return (rv);
  23188     }
  23189     h_data_p->profile_index = 
  23190             _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(profile_index);
  23191     soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr,
  23192                               OAM_OPCODE_CONTROL_PROFILE_PTRf,
  23193                               h_data_p->profile_index);
  23194     rv = soc_mem_write(unit, ma_index_mem, MEM_BLOCK_ALL,
  23195                   h_data_p->local_rx_index, ma_idx_ptr);
  23196 
  23197     /* Delete old profile once ma_index is pointing to new one*/
  23198     if(free_old_profile) {
  23199         rv = soc_profile_mem_delete(unit, profile_mem_ptr,
  23200                 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(old_profile_index)
  23201                 );
  23202         if (BCM_FAILURE(rv)) {
  23203             _BCM_OAM_UNLOCK(oc);
  23204             LOG_ERROR(BSL_LS_BCM_OAM,
  23205                       (BSL_META_U(unit,
  23206                                   "OAM(unit %d) Error: Soc profile mem delete failed -"
  23207                                    " %s.\n"), unit, bcm_errmsg(rv)));
  23208             if(opcode_profile) {
  23209                 sal_free(opcode_profile);
  23210             }
  23211             if(egr_opcode_profile) {
  23212                 sal_free(egr_opcode_profile);
  23213             }
  23214             return (rv);
  23215         }
  23216     }
  23217     _BCM_OAM_UNLOCK(oc);
  23218     if(opcode_profile) {
  23219         sal_free(opcode_profile);
  23220     }
  23221     if(egr_opcode_profile) {
  23222         sal_free(egr_opcode_profile);
  23223     }
  23224     return rv;
  23225 }
  23226 
  23227 int
  23228 _bcm_sb2_oam_mpls_lm_dm_endpoint_actions_verify(int unit, 
  23229                                           _bcm_oam_hash_data_t *h_data_p,
  23230                                            bcm_oam_action_type_t action)
  23231 {
  23232     switch(action) {
  23233         case  bcmOAMActionMcDrop:
  23234         case  bcmOAMActionMcCopyToCpu:
  23235         case  bcmOAMActionMcFwdAsData:
  23236         case  bcmOAMActionMcFwd:
  23237         case  bcmOAMActionMCProcessInInternalOamEngine:
  23238             /* Multicast actions are not applicable for MPLS LM DM endpoints */
  23239         case  bcmOAMActionL2StationHitProcessInInternalOamEngine:
  23240         case  bcmOAMActionL2StationMissProcessInInternalOamEngine:
  23241         case  bcmOAMActionLowMdlProcessInInternalOamEngine:
  23242         case  bcmOAMActionProcessInHw:
  23243             /* Process in CCM/LB engine and HW are not applicable for MPLS LM/DM 
  23244                 endpoints */
  23245         case  bcmOAMActionMyStationMissCopyToCpu:
  23246         case  bcmOAMActionMyStationMissDrop:
  23247         case  bcmOAMActionMyStationMissFwdAsData:
  23248         case  bcmOAMActionMyStationMissFwd:
  23249         case  bcmOAMActionLowMdlDrop:
  23250         case  bcmOAMActionLowMdlCopyToCpu:
  23251         case  bcmOAMActionLowMdlFwdAsData:
  23252         case  bcmOAMActionLowMdlFwd:
  23253             /* My station miss and low mdl actions are not applicable for 
  23254                MPLS LM/DM endpoints */
  23255             if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ||
  23256                 BHH_EP_TYPE(h_data_p)) {
  23257                 return BCM_E_PARAM;
  23258             }
  23259             break;
  23260         default: 
  23261             return BCM_E_NONE;
  23262             break;
  23263     }
  23264     return BCM_E_NONE;
  23265 }
  23266 
  23267 /*
  23268  * Function:
  23269  *     _sb2_oam_opcode_control_field_set
  23270  * Purpose:
  23271  *   Set the fields of opcode profile entry 
  23272  * Parameters:
  23273  *     unit        - (IN) BCM device number
  23274  *     field_index - (IN) Opcode profile action to be set
  23275  *     mem         - (IN) Opcode profile memory - ing/egr
  23276  *     oam_opcode  - (IN) Oam opcode for which action needs to be set
  23277  *     value       - (IN) value for the field to be set
  23278  *     profile     - (OUT) Pointer to the opcode profile table index.
  23279  * Returns:
  23280  *      BCM_E_XXX
  23281  */
  23282 int
  23283 _sb2_oam_opcode_control_field_set(int unit, _bcm_oam_hash_data_t *h_data_p,
  23284                                   bcm_oam_action_type_t action, 
  23285                                   soc_mem_t mem, int oam_opcode, uint32 value,
  23286                                   void *profile) 
  23287 {
  23288     soc_field_t fields[3] = {0, 0, 0};
  23289     int         index, num_fields = 0;
  23290     int         do_nothing = 0;
  23291     int         opcode_group_index = 0;
  23292     oam_opcode_control_profile_entry_t *temp_entry = NULL;
  23293     oam_opcode_control_profile_entry_t *actual_entry = NULL;
  23294     
  23295     
  23296     /* Verify actions that are set on MPLS LM DM endpoints is valid */
  23297     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lm_dm_endpoint_actions_verify(unit,
  23298                                                          h_data_p,
  23299                                                          action));
  23300 
  23301     opcode_group_index = _bcm_sb2_opcode_to_opcode_group_index(unit, h_data_p,
  23302                                                                oam_opcode);
  23303     if(opcode_group_index < 0)
  23304     {
  23305         return BCM_E_PARAM;
  23306     }
  23307     temp_entry = (oam_opcode_control_profile_entry_t *)profile;
  23308     actual_entry = &(temp_entry[opcode_group_index]);
  23309 
  23310     switch (action) {
  23311         /* General: Both UC and MC */
  23312         case bcmOAMActionCopyToCpu:
  23313             fields[0] = UC_MY_STATION_HIT_COPYTO_CPUf;
  23314             num_fields = 1;
  23315             if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) &&
  23316                 !BHH_EP_TYPE(h_data_p)) {
  23317                 fields[1] = MC_COPYTO_CPUf;
  23318                 num_fields = 2;
  23319                 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) {
  23320                     fields[2] = UC_MY_STATION_MISS_COPYTO_CPUf;
  23321                     num_fields = 3;
  23322                 }
  23323             }
  23324             break;
  23325 
  23326         case bcmOAMActionFwdAsData:
  23327             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23328             num_fields = 1;
  23329             if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) &&
  23330                 !BHH_EP_TYPE(h_data_p)) {
  23331                 fields[1] = MC_ACTIONf;
  23332                 num_fields = 2;
  23333                 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) {
  23334                     fields[2] = UC_MY_STATION_MISS_ACTIONf;
  23335                     num_fields = 3;
  23336                 }
  23337             }
  23338             break;
  23339 
  23340         case bcmOAMActionFwd:
  23341             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23342             num_fields = 1;
  23343             if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) &&
  23344                 !BHH_EP_TYPE(h_data_p)) {
  23345                 fields[1] = MC_ACTIONf;
  23346                 num_fields = 2;
  23347                 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) {
  23348                     fields[2] = UC_MY_STATION_MISS_ACTIONf;
  23349                     num_fields = 3;
  23350                 }
  23351             }
  23352             break;
  23353 
  23354         case bcmOAMActionProcessInHw:
  23355             if((oam_opcode == _BCM_OAM_OPCODE_TYPE_LBM) ||
  23356                (oam_opcode == _BCM_OAM_OPCODE_TYPE_LBR)){
  23357                 fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23358                 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_LBM) {
  23359                     /* Only LBM can be UC or MC. */
  23360                     fields[1] = MC_ACTIONf;
  23361                     num_fields = 2;
  23362                 } else {
  23363                     num_fields = 1;
  23364                 }
  23365             } else if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) {
  23366                 fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23367                 fields[1] = UC_MY_STATION_MISS_ACTIONf;
  23368                 fields[2] = MC_ACTIONf;
  23369                 num_fields = 3;
  23370             }
  23371             break;
  23372 
  23373         case bcmOAMActionDrop:
  23374             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23375             num_fields = 1;
  23376             if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) &&
  23377                 !BHH_EP_TYPE(h_data_p)) {
  23378                 fields[1] = MC_ACTIONf;
  23379                 num_fields = 2;
  23380                 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) {
  23381                     fields[2] = UC_MY_STATION_MISS_ACTIONf;
  23382                     num_fields = 3;
  23383                 }
  23384             }
  23385             break;
  23386 
  23387         /* UC actions */
  23388         case bcmOAMActionUcCopyToCpu:
  23389             fields[0] = UC_MY_STATION_HIT_COPYTO_CPUf;
  23390             num_fields = 1;
  23391             break;
  23392 
  23393         case bcmOAMActionUcFwdAsData:
  23394             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23395             num_fields = 1;
  23396             break;
  23397 
  23398         case bcmOAMActionUcFwd:
  23399             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23400             num_fields = 1;
  23401             break;
  23402             
  23403 
  23404         case bcmOAMActionL2StationHitProcessInInternalOamEngine:
  23405             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23406             num_fields = 1;
  23407             break;
  23408 
  23409         case bcmOAMActionUcDrop:
  23410             fields[0] = UC_MY_STATION_HIT_ACTIONf;
  23411             num_fields = 1;
  23412             break;
  23413 
  23414         /* MC actions */
  23415         case bcmOAMActionMcDrop:
  23416             fields[0] = MC_ACTIONf;
  23417             num_fields = 1;
  23418             break;
  23419 
  23420         case bcmOAMActionMcCopyToCpu:
  23421             fields[0] = MC_COPYTO_CPUf;
  23422             num_fields = 1;
  23423             break;
  23424 
  23425         case bcmOAMActionMcFwdAsData:
  23426             fields[0] = MC_ACTIONf;
  23427             num_fields = 1;
  23428             break;
  23429 
  23430         case bcmOAMActionMcFwd:
  23431             fields[0] = MC_ACTIONf;
  23432             num_fields = 1;
  23433             break;
  23434 
  23435         case bcmOAMActionMCProcessInInternalOamEngine:
  23436             fields[0] = MC_ACTIONf;
  23437             num_fields = 1;
  23438             break;
  23439 
  23440         /* Low MDL actions */
  23441         case bcmOAMActionLowMdlDrop:
  23442             fields[0] = LOW_MDL_ACTIONf;
  23443             num_fields = 1;
  23444             break; 
  23445 
  23446         case bcmOAMActionLowMdlCopyToCpu:
  23447             fields[0] = LOW_MDL_COPYTO_CPUf;
  23448             num_fields = 1;
  23449             break;
  23450         
  23451         case bcmOAMActionLowMdlFwdAsData:
  23452             fields[0] = LOW_MDL_ACTIONf;
  23453             num_fields = 1;
  23454             break;
  23455 
  23456         case bcmOAMActionLowMdlFwd:
  23457             fields[0] = LOW_MDL_ACTIONf;
  23458             num_fields = 1;
  23459             break;
  23460 
  23461         case bcmOAMActionLowMdlCcmFwdAsRegularCcm:
  23462             /* Not supported in Saber2 */
  23463             do_nothing = 1;
  23464             break;
  23465 
  23466         case bcmOAMActionLowMdlProcessInInternalOamEngine:
  23467             fields[0] = LOW_MDL_ACTIONf;
  23468             num_fields = 1;
  23469             break;
  23470 
  23471         /* UC station hit miss actions */
  23472 
  23473         case bcmOAMActionMyStationMissCopyToCpu:
  23474             fields[0] = UC_MY_STATION_MISS_COPYTO_CPUf;
  23475             num_fields = 1;
  23476             break;
  23477 
  23478         case bcmOAMActionMyStationMissDrop:
  23479             fields[0] = UC_MY_STATION_MISS_ACTIONf;
  23480             num_fields = 1;
  23481             break;
  23482 
  23483         case bcmOAMActionMyStationMissFwdAsData:
  23484             fields[0] = UC_MY_STATION_MISS_ACTIONf;
  23485             num_fields = 1;
  23486             break;
  23487         
  23488         case bcmOAMActionMyStationMissFwd:
  23489             fields[0] = UC_MY_STATION_MISS_ACTIONf;
  23490             num_fields = 1;
  23491             break;
  23492 
  23493         case bcmOAMActionL2StationMissProcessInInternalOamEngine:
  23494             fields[0] = UC_MY_STATION_MISS_ACTIONf;
  23495             num_fields = 1;
  23496             break;
  23497         
  23498         /* Misc actions */
  23499         case bcmOAMActionSLMEnable:
  23500             /* Not supported in Saber2 */
  23501             do_nothing = 1;
  23502             break;
  23503 
  23504         case bcmOAMActionSampleTimeStamp:
  23505             fields[0] = EQUAL_MDL_SAMPLE_TIMESTAMPf;
  23506             num_fields = 1;
  23507             break;
  23508         case bcmOAMActionSampleLmCounter:
  23509             fields[0] = EQUAL_MDL_SAMPLE_LM_COUNTERf;
  23510             num_fields = 1;
  23511             break;
  23512         
  23513         default:
  23514             do_nothing = 1;
  23515             break;
  23516     }
  23517     if(!do_nothing){
  23518         for(index = 0; index < num_fields; index++){
  23519             soc_mem_field32_set(unit, mem, actual_entry, fields[index], 
  23520                                                            value);
  23521         }
  23522     }
  23523     return (BCM_E_NONE);
  23524 }
  23525 
  23526 /*
  23527  * Function:
  23528  *     _bcm_sb2_oam_resolve_dglp
  23529  * Purpose:
  23530  *   Add an dglp profile entry 
  23531  * Parameters:
  23532  *     unit        - (IN) BCM device number
  23533  *     mem         - (IN) dglp profile memory - ing/egr
  23534  *     dglp        - (IN) DGLP value
  23535  *     profile     - (OUT) Pointer to the dglp profile table index.
  23536  *     olp_enable  - (OUT) Pointer to field indicating whether olp is enabled on
  23537  *                         the port. 
  23538  * Returns:
  23539  *      BCM_E_XXX
  23540  */
  23541 int
  23542 _bcm_sb2_oam_resolve_dglp(int unit, soc_mem_t mem, uint32 dglp, 
  23543                           uint32 *profile_index, int *olp_enable) 
  23544 { 
  23545     int rv = BCM_E_NONE;
  23546     egr_olp_dgpp_config_entry_t *buf;
  23547     egr_olp_dgpp_config_entry_t *entry;
  23548     egr_oam_dglp_profile_entry_t egr_dglp_profile_entry;
  23549     ing_oam_dglp_profile_entry_t ing_dglp_profile_entry;
  23550     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  23551     int         index_max = 0;
  23552     int         index = 0;
  23553     uint32      configured_dglp = 0;
  23554     void        *entries[1];
  23555     void        *profile_entry;
  23556     soc_mem_t   profile_mem;
  23557     soc_profile_mem_t profile_ptr;
  23558     int         entry_mem_size = 0;
  23559 
  23560     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  23561 
  23562     if (mem == EGR_OAM_OPCODE_CONTROL_PROFILEm) {
  23563         profile_entry = (void *)&egr_dglp_profile_entry;
  23564         profile_mem = EGR_OAM_DGLP_PROFILEm;
  23565         profile_ptr = oc->egr_oam_dglp_profile;
  23566     } else {
  23567         profile_entry = (void *)&ing_dglp_profile_entry;
  23568         profile_mem = OAM_DGLP_PROFILEm;
  23569         profile_ptr = oc->ing_oam_dglp_profile;
  23570     }
  23571     /* Check whether this DGLP is already configured as  OLP port */ 
  23572     entry_mem_size = sizeof(egr_olp_dgpp_config_entry_t);
  23573     /* Allocate buffer to store the DMAed table entries. */
  23574     index_max = soc_mem_index_max(unit, EGR_OLP_DGPP_CONFIGm);
  23575     buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1),
  23576                               "OLP dglp config table entry buffer");
  23577     if (NULL == buf) {
  23578         return (BCM_E_MEMORY);
  23579     }
  23580     /* Initialize the entry buffer. */
  23581     sal_memset(buf, 0, sizeof(entry_mem_size) * (index_max + 1));
  23582 
  23583     /* Read the table entries into the buffer. */
  23584     rv = soc_mem_read_range(unit, EGR_OLP_DGPP_CONFIGm, MEM_BLOCK_ALL,
  23585                             0, index_max, buf);
  23586     if (BCM_FAILURE(rv)) {
  23587         if (buf) {
  23588             soc_cm_sfree(unit, buf);
  23589         }
  23590         return rv;
  23591     }
  23592 
  23593     /* Iterate over the table entries. */
  23594     for (index = 0; index <= index_max; index++) {
  23595         entry = soc_mem_table_idx_to_pointer
  23596                     (unit, EGR_OLP_DGPP_CONFIGm, egr_olp_dgpp_config_entry_t *,
  23597                      buf, index);
  23598 
  23599         soc_mem_field_get(unit, EGR_OLP_DGPP_CONFIGm, 
  23600                           (uint32 *)entry, DGLPf, &configured_dglp);
  23601         if (dglp == configured_dglp) {
  23602             *olp_enable = 1;
  23603             break;
  23604         }
  23605     }
  23606     if (buf) {
  23607         soc_cm_sfree(unit, buf);
  23608     }
  23609     /* Add entry to dglp profile table.  */
  23610     soc_mem_field32_set(unit, profile_mem, profile_entry, DGLPf, dglp);
  23611     entries[0] = profile_entry;
  23612 
  23613     rv = soc_profile_mem_add(unit, &profile_ptr,
  23614                              (void *)entries, 1, profile_index);
  23615     if (BCM_FAILURE(rv)) {
  23616         LOG_ERROR(BSL_LS_BCM_OAM,
  23617                   (BSL_META_U(unit,
  23618                               "OAM(unit %d) DGLP profile table is full - %s.\n"),
  23619                    unit, bcm_errmsg(rv)));
  23620         return rv;
  23621     }
  23622     return (BCM_E_NONE);
  23623 } 
  23624 
  23625 /*
  23626  * Function:
  23627  *     _bcm_sb2_ma_index_entry_modify
  23628  * Purpose:
  23629  *    Set dglp profile pointer index in the MA index table entry 
  23630  * Parameters:
  23631  *     unit        - (IN) BCM device number
  23632  *     index       - (IN) MA index table index
  23633  *     mem         - (IN) MA index memory - ing/egr
  23634  *     profile_index- (IN)DGLP profile index
  23635  *     olp_enable  - (IN) indicates whether olp is enabled for this entry
  23636  *     dglp_prt    - (OUT) Pointer to dglp1/2 profile.  
  23637  * Returns:
  23638  *      BCM_E_XXX
  23639  */
  23640 int 
  23641 _bcm_sb2_ma_index_entry_modify(int unit, int index, soc_mem_t mem, 
  23642                                int profile_index, int olp_enable, int *dglp_ptr)
  23643 {
  23644     int  rv = BCM_E_NONE;
  23645     ma_index_entry_t     ma_idx_entry;     /* MA_INDEX table entry buffer.    */
  23646     egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer.*/
  23647     void *entry;
  23648 
  23649     if (mem == EGR_MA_INDEXm) {
  23650         entry = (void *)&egr_ma_idx_entry;
  23651     } else {
  23652         entry = (void *)&ma_idx_entry;
  23653     }
  23654     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry);
  23655     if (BCM_FAILURE(rv)) {
  23656         LOG_ERROR(BSL_LS_BCM_OAM,
  23657                   (BSL_META_U(unit,
  23658                               "OAM(unit %d) Error: MA index table entry  read failed  "
  23659                               "%s.\n"), unit,  bcm_errmsg(rv)));
  23660         return (rv);
  23661     }
  23662     if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  23663                                  DGLP1_PROFILE_PTRf)){
  23664         
  23665          soc_mem_field32_set(unit, mem, entry, 
  23666                              DGLP1_PROFILE_PTRf, profile_index);
  23667          if (olp_enable) {
  23668              soc_mem_field32_set(unit, mem, entry, DGLP1_OLP_HDR_ADDf, 1);
  23669          }
  23670          *dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR;
  23671     } else if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 
  23672                                  DGLP2_PROFILE_PTRf)){
  23673         
  23674          soc_mem_field32_set(unit, mem, entry, 
  23675                              DGLP2_PROFILE_PTRf, profile_index);
  23676          if (olp_enable) {
  23677              soc_mem_field32_set(unit, mem, entry, DGLP2_OLP_HDR_ADDf, 1);
  23678          }
  23679          *dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR;
  23680     }
  23681     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, entry));
  23682     return (BCM_E_NONE);
  23683 }
  23684 
  23685 /*
  23686  * Function:
  23687  *     _sb2_oam_counter_control_set
  23688  * Purpose:
  23689  *    Enable/disable LM counter for a particular opcode 
  23690  * Parameters:
  23691  *     unit        - (IN) BCM device number
  23692  *     opcode_i    - (IN) OAM opcode for which counter needs 
  23693  *                        to be enabled/disabled 
  23694  *     value       - (IN) Counter enable/disable
  23695  * Returns:
  23696  *      BCM_E_XXX
  23697  */
  23698 int
  23699 _sb2_oam_counter_control_set(int unit, int opcode_i, int value)
  23700 {
  23701     int rv = BCM_E_NONE;
  23702     egr_lm_counter_control_entry_t  egr_ctr;
  23703     lm_counter_control_entry_t      ing_ctr;
  23704 
  23705     rv = soc_mem_read(unit, ING_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY,
  23706                       opcode_i, &ing_ctr);
  23707     if (BCM_FAILURE(rv)) {
  23708         LOG_ERROR(BSL_LS_BCM_OAM,
  23709                   (BSL_META_U(unit,
  23710                               "OAM(unit %d) Error: Counter control table entry  read "
  23711                               "failed  %s.\n"), unit, bcm_errmsg(rv)));
  23712         return (rv);
  23713     }
  23714     soc_ING_LM_COUNTER_CONTROLm_field32_set(unit, &ing_ctr, COUNT_ENABLEf, value);
  23715     rv = soc_mem_write(unit, ING_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 
  23716                        opcode_i, &ing_ctr);
  23717     if (BCM_FAILURE(rv)) {
  23718         LOG_ERROR(BSL_LS_BCM_OAM,
  23719                   (BSL_META_U(unit,
  23720                               "OAM(unit %d) Error: Counter control table entry  wtite "
  23721                               "failed  %s.\n"), unit, bcm_errmsg(rv)));
  23722         return (rv);
  23723     }
  23724     rv = soc_mem_read(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY,
  23725                       opcode_i, &egr_ctr);
  23726     if (BCM_FAILURE(rv)) {
  23727         LOG_ERROR(BSL_LS_BCM_OAM,
  23728                   (BSL_META_U(unit,
  23729                               "OAM(unit %d) Error: Counter control table entry  read "
  23730                               "failed  %s.\n"), unit, bcm_errmsg(rv)));
  23731         return (rv);
  23732     }
  23733     soc_EGR_LM_COUNTER_CONTROLm_field32_set(unit, &egr_ctr, 
  23734                                             COUNT_ENABLEf, value);
  23735     rv = soc_mem_write(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 
  23736                        opcode_i, &ing_ctr);
  23737     if (BCM_FAILURE(rv)) {
  23738         LOG_ERROR(BSL_LS_BCM_OAM,
  23739                   (BSL_META_U(unit,
  23740                               "OAM(unit %d) Error: Counter control table entry  wtite "
  23741                               "failed  %s.\n"), unit, bcm_errmsg(rv)));
  23742         return (rv);
  23743     }
  23744     return rv;
  23745 }
  23746 
  23747 /*
  23748  * Function:
  23749  *     _bcm_sb2_oam_convert_action_to_opcode_entry
  23750  * Purpose:
  23751  *    Convert endpoint action to opcode profile entry action 
  23752  * Parameters:
  23753  *     unit        - (IN) BCM device number
  23754  *     action      - (IN) Pointer to endpoint action
  23755  *     ep_id       - (IN) Endpoint id
  23756  *     profile     - (IN) Opcode profile table entry
  23757  * Returns:
  23758  *      BCM_E_XXX
  23759  */
  23760 int 
  23761 _bcm_sb2_oam_convert_action_to_opcode_entry(int unit,
  23762                                             bcm_oam_endpoint_action_t *action, 
  23763                                             bcm_oam_endpoint_t ep_id,
  23764                                             void *profile,
  23765                                             uint8  *opcode_profile_changed)
  23766 {
  23767     int rv = BCM_E_NONE;
  23768     int action_i = 0;
  23769     int opcode_i = 0;
  23770     int break_the_loop = 0;
  23771     int profile_index = _BCM_OAM_INVALID_INDEX;
  23772     int olp_enable = 0;
  23773     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  23774     _bcm_oam_hash_data_t *h_data_p;  /* Pointer to endpoint hash data.    */
  23775     soc_mem_t     mem = OAM_OPCODE_CONTROL_PROFILEm;
  23776     soc_mem_t     ma_index_mem = MA_INDEXm;
  23777     int           dglp_ptr = 0;
  23778     int           skip_ma_index_modify = 0;
  23779     int           value = 0;        
  23780     bcm_module_t  module_id;
  23781     bcm_port_t    port_id;
  23782     bcm_trunk_t   trunk_id = BCM_TRUNK_INVALID;
  23783     int           local_id;
  23784     uint32        dglp = 0;
  23785     int           reset = 0;
  23786 
  23787     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  23788 
  23789     h_data_p = &oc->oam_hash_data[ep_id];
  23790     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  23791         ma_index_mem = EGR_MA_INDEXm;
  23792         mem = EGR_OAM_OPCODE_CONTROL_PROFILEm;
  23793     }
  23794 
  23795     reset = (action->flags & BCM_OAM_ENDPOINT_ACTION_DISABLE)?1:0;
  23796 
  23797 
  23798     for (action_i = 0; action_i < bcmOAMActionCount; action_i++) {
  23799         if (BCM_OAM_ACTION_GET(*action, action_i)) {
  23800             for (opcode_i = 0; opcode_i <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST; 
  23801                                                                 opcode_i++) {
  23802                 if (BCM_OAM_OPCODE_GET(*action, opcode_i)) {
  23803                     switch (action_i) {
  23804                         case bcmOAMActionCountEnable:
  23805                             if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  23806                                 rv = _bcm_sb2_mpls_lmdm_ach_type_counter_enable(unit, opcode_i, !reset);
  23807                             } else {
  23808                                 rv = _sb2_oam_counter_control_set(unit, opcode_i, !reset);
  23809                             }
  23810                             if (BCM_FAILURE(rv)) {
  23811                                LOG_ERROR(BSL_LS_BCM_OAM,
  23812                                          (BSL_META_U(unit,
  23813                                                      "OAM(unit %d) Error:Counter control "
  23814                                                      "set - %s.\n"), unit, bcm_errmsg(rv)));
  23815                                 return (rv);
  23816                             }
  23817                             break;
  23818 
  23819                         case bcmOAMActionDrop:
  23820                         case bcmOAMActionUcDrop:             
  23821                         case bcmOAMActionMcDrop:                
  23822                         case bcmOAMActionLowMdlDrop:        
  23823                         case bcmOAMActionMyStationMissDrop:
  23824                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 
  23825                                              action_i, mem, opcode_i, 
  23826                                              reset?0:_BCM_SB2_OAM_OC_PROF_DROP,
  23827                                              profile); 
  23828                             *opcode_profile_changed = 1;
  23829                             break;
  23830 
  23831                         case bcmOAMActionCopyToCpu:             
  23832                         case bcmOAMActionUcCopyToCpu:       
  23833                         case bcmOAMActionMcCopyToCpu:          
  23834                         case bcmOAMActionLowMdlCopyToCpu:  
  23835                         case bcmOAMActionMyStationMissCopyToCpu:
  23836                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 
  23837                                            action_i, mem, opcode_i,
  23838                                             !reset, profile);
  23839                             *opcode_profile_changed = 1;
  23840                             break;
  23841 
  23842                         case bcmOAMActionFwdAsData:             
  23843                             if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 
  23844                                 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p,
  23845                                         action_i, mem, opcode_i,
  23846                                         /* Need not check reset in this case
  23847                                            since this is default case */
  23848                                         _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING,
  23849                                         profile);
  23850                                break_the_loop = 1;
  23851                             }
  23852                             *opcode_profile_changed = 1;
  23853                             break;
  23854 
  23855                         case bcmOAMActionFwd:      
  23856                         case bcmOAMActionUcFwd:       
  23857                         case bcmOAMActionMcFwd:   
  23858                         case bcmOAMActionLowMdlFwd:
  23859                         case bcmOAMActionMyStationMissFwd:
  23860                             /* forward packets to DGLP1 or DGLP2 */
  23861                             /* Dont bother about dglp related info if
  23862                              * reset is set
  23863                              */
  23864                             if (!skip_ma_index_modify && !reset) {
  23865                                 SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit,
  23866                                              action->destination, &module_id, 
  23867                                              &port_id, &trunk_id, &local_id));
  23868                                 if (BCM_GPORT_IS_TRUNK(action->destination) && 
  23869                                              (trunk_id != BCM_TRUNK_INVALID)) {
  23870                                     /* Set LAG ID indicator bit */
  23871                                     dglp |= (1 << DGLP_LAG_ID_INDICATOR_SHIFT_BITS); 
  23872                                 }
  23873                                 dglp |= ((module_id << DGLP_MODULE_ID_SHIFT_BITS) + port_id); 
  23874 
  23875                                 if (dglp == h_data_p->dglp1) {
  23876                                     skip_ma_index_modify = 1;
  23877                                     dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR;
  23878                                     value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1;
  23879                                 } else if (dglp == h_data_p->dglp2) {
  23880                                     skip_ma_index_modify = 1;
  23881                                     dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR;
  23882                                     value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2;
  23883                                 /* if both dglp1 and dglp2 are already set, 
  23884                                    return error */
  23885                                 } else if ((h_data_p->dglp1 > 0) && 
  23886                                            (h_data_p->dglp2 > 0)) {
  23887                                     LOG_ERROR(BSL_LS_BCM_OAM,
  23888                                               (BSL_META_U(unit,
  23889                                                           "OAM(unit %d) Error: Invalid action"
  23890                                                           "destination - %s.\n"), unit, bcm_errmsg(rv)));
  23891                                     return BCM_E_PARAM;
  23892                                 }
  23893                                 if (!skip_ma_index_modify) {
  23894                                     rv = _bcm_sb2_oam_resolve_dglp(unit, mem, 
  23895                                                  dglp, (uint32 *)&profile_index,
  23896                                                  &olp_enable); 
  23897                                     if (BCM_FAILURE(rv)) {
  23898                                        LOG_ERROR(BSL_LS_BCM_OAM,
  23899                                                  (BSL_META_U(unit,
  23900                                                              "OAM(unit %d) Error: Gport  "
  23901                                                              "to dglp-%s\n"), unit, bcm_errmsg(rv)));
  23902                                        return (rv);
  23903                                     }
  23904                                     if (profile_index != _BCM_OAM_INVALID_INDEX) {
  23905                                         /* modify MA_INDEX table entry */       
  23906                                         rv = _bcm_sb2_ma_index_entry_modify(unit,
  23907                                                    h_data_p->local_rx_index, 
  23908                                                    ma_index_mem, profile_index, 
  23909                                                    olp_enable, &dglp_ptr);
  23910                                         if (BCM_FAILURE(rv)) {
  23911                                             return rv;
  23912                                         }
  23913                                         if (dglp_ptr == 
  23914                                                    _BCM_OAM_DGLP1_PROFILE_PTR) {
  23915                                             h_data_p->dglp1 = dglp;
  23916                                             h_data_p->dglp1_profile_index = 
  23917                                                                   profile_index;
  23918                                             value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1;
  23919                                         } else {
  23920                                             h_data_p->dglp2 = dglp;
  23921                                             h_data_p->dglp2_profile_index = 
  23922                                                                   profile_index;
  23923                                             value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2;
  23924                                         }
  23925                                         skip_ma_index_modify = 1; 
  23926                                     }
  23927                                 }
  23928                             }
  23929                             if ((!reset) && (dglp_ptr == 0)) {
  23930                                 break;
  23931                             }
  23932                             /* Opcode control value is to bet set to 2 for 
  23933                                DGLP1 and 3 for DGLP2 */
  23934                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, action_i, 
  23935                                            mem, opcode_i, reset?0:value, profile); 
  23936                             *opcode_profile_changed = 1;
  23937                             break;
  23938 
  23939                         case bcmOAMActionUcFwdAsData:      
  23940                         case bcmOAMActionMcFwdAsData:         
  23941                         case bcmOAMActionLowMdlFwdAsData:  
  23942                         case bcmOAMActionMyStationMissFwdAsData:
  23943                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 
  23944                                       action_i, mem, opcode_i, 
  23945                                       /* Need not check reset in this case
  23946                                          since this is default case */
  23947                                       _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING, 
  23948                                       profile); 
  23949                             *opcode_profile_changed = 1;
  23950                             break;
  23951 
  23952                         case bcmOAMActionProcessInHw:           
  23953                         case bcmOAMActionLowMdlProcessInInternalOamEngine:
  23954                         case bcmOAMActionL2StationMissProcessInInternalOamEngine:
  23955                         case bcmOAMActionMCProcessInInternalOamEngine:
  23956                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p,
  23957                                       action_i, mem, opcode_i, 
  23958                                       reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE,
  23959                                       profile); 
  23960                             break_the_loop = 1;
  23961                             *opcode_profile_changed = 1;
  23962                             /* TBD - When CCM processing is done in HW, MA_PTR
  23963                                value in MA_INDEX table should be less than 2k. 
  23964                                If not, we should return error */
  23965                             break;
  23966                         case bcmOAMActionL2StationHitProcessInInternalOamEngine:
  23967                             if((opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) ||
  23968                                (opcode_i == _BCM_OAM_OPCODE_TYPE_LBR)){
  23969                                 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p,
  23970                                         action_i, mem, opcode_i, 
  23971                                         reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE,
  23972                                         profile); 
  23973                             } else if(opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) {
  23974                                 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p,
  23975                                         action_i, mem, opcode_i, 
  23976                                         reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE,
  23977                                         profile); 
  23978                             }
  23979                             break_the_loop = 1;
  23980                             *opcode_profile_changed = 1;
  23981                             break;
  23982                         case bcmOAMActionLowMdlCcmFwdAsRegularCcm:
  23983                             /* Not supported in SB2 */
  23984                             break;
  23985 
  23986                         case bcmOAMActionSampleLmCounter:
  23987                             if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  23988                                 if ((opcode_i == bcmOamMplsLmDmOpcodeTypeIlm) ||
  23989                                      (opcode_i == bcmOamMplsLmDmOpcodeTypeIlmPlusDm)
  23990                                      ) {
  23991                                     /* ILM opcodes are NOT expected to
  23992                                        sample LM counters */
  23993                                     return BCM_E_PARAM;
  23994                                 }
  23995                             }
  23996                             /* Fall thru */
  23997                         case bcmOAMActionSampleTimeStamp:
  23998                             rv = _sb2_oam_opcode_control_field_set(unit, h_data_p,
  23999                                       action_i, mem, opcode_i,
  24000                                       !reset, profile);
  24001                             *opcode_profile_changed = 1;
  24002                             break;
  24003 
  24004 
  24005                         default:
  24006                             break;
  24007                     }
  24008                 }
  24009                 if (break_the_loop) { 
  24010                     dglp_ptr = 0;
  24011                     break_the_loop = 0;
  24012                     olp_enable = 0;
  24013                     profile_index = _BCM_OAM_INVALID_INDEX;
  24014                     break;   
  24015                 }
  24016             }
  24017         }
  24018     }
  24019     return rv;
  24020 }
  24021 
  24022 /*
  24023  * Function:
  24024  *     _bcm_sb2_oam_flex_drop_get
  24025  * Purpose:
  24026  *     Query the value of the device-wide OAM control.
  24027  * Parameters:
  24028  *     unit        - (IN) BCM device number
  24029  *     type        - (IN) OAM control type
  24030  *     arg         - (OUT) A pointer to value of the control 
  24031  * Returns:
  24032  *      BCM_E_XXX
  24033  */
  24034 int _bcm_sb2_oam_flex_drop_get(int unit, bcm_oam_control_type_t type,
  24035                                      uint64  *arg) 
  24036 {
  24037    uint32 rval_32;
  24038    soc_reg_t  reg = 0;
  24039    uint32     is_64bit_reg = 0; 
  24040    int        rv = BCM_E_NONE;
  24041 
  24042    switch(type) {
  24043        case bcmOamControlFlexibleDropPort:
  24044            reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 
  24045            break;
  24046 
  24047        case bcmOamControlFlexibleDropCVlan:
  24048            reg = OAM_C_INTERFACE_DROP_CONTROLr; 
  24049            break;
  24050 
  24051        case bcmOamControlFlexibleDropSVlan:
  24052            reg = OAM_S_INTERFACE_DROP_CONTROLr; 
  24053            break;
  24054 
  24055        case bcmOamControlFlexibleDropCPlusSVlan:
  24056            reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 
  24057            break;
  24058 
  24059        case bcmOamControlFlexibleDropVP:
  24060            reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 
  24061            break;
  24062 
  24063        case bcmOamControlFlexibleDropEgressPort:
  24064            reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 
  24065            is_64bit_reg = 1;
  24066            break;
  24067 
  24068        case bcmOamControlFlexibleDropEgressCVlan:
  24069            reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 
  24070            is_64bit_reg = 1;
  24071            break;
  24072 
  24073        case bcmOamControlFlexibleDropEgressSVlan:
  24074            reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 
  24075            is_64bit_reg = 1;
  24076            break;
  24077 
  24078        case bcmOamControlFlexibleDropEgressCPlusSVlan:
  24079            reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 
  24080            is_64bit_reg = 1;
  24081            break;
  24082 
  24083        case bcmOamControlFlexibleDropEgressVP:
  24084            reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 
  24085            is_64bit_reg = 1;
  24086            break;
  24087 
  24088        case bcmOamControlFlexibleDropPasssiveSap:
  24089            reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  24090            break;
  24091 
  24092        case bcmOamControlFlexibleDropEgressPasssiveSap:
  24093            reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  24094            break;
  24095 
  24096        default:
  24097            return (BCM_E_UNAVAIL); 
  24098            break;
  24099     }
  24100     if (is_64bit_reg == 0) {
  24101         rv = soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval_32);
  24102         if(BCM_SUCCESS(rv)) {
  24103            COMPILER_64_SET(*arg, 0, rval_32);
  24104         }
  24105     } else {
  24106         rv = soc_reg64_get(unit, reg, REG_PORT_ANY, 0, arg);
  24107     }
  24108     return rv;
  24109 }
  24110 
  24111 /*
  24112  * Function:
  24113  *     _bcm_sb2_oam_flex_drop_get
  24114  * Purpose:
  24115  *     Query the value of the device-wide OAM control.
  24116  * Parameters:
  24117  *     unit        - (IN) BCM device number
  24118  *     type        - (IN) OAM control type
  24119  *     arg         - (IN) value to be set for the control 
  24120  * Returns:
  24121  *      BCM_E_XXX
  24122  */
  24123 int _bcm_sb2_oam_flex_drop_set(int unit, bcm_oam_control_type_t type,
  24124                                uint64  arg) 
  24125 {
  24126    uint32 rval_32;
  24127    soc_reg_t  reg = 0;
  24128    uint32     is_64bit_reg = 0; 
  24129    int        rv = BCM_E_NONE;
  24130 
  24131    switch(type) {
  24132        case bcmOamControlFlexibleDropPort:
  24133            reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 
  24134            break;
  24135 
  24136        case bcmOamControlFlexibleDropCVlan:
  24137            reg = OAM_C_INTERFACE_DROP_CONTROLr; 
  24138            break;
  24139 
  24140        case bcmOamControlFlexibleDropSVlan:
  24141            reg = OAM_S_INTERFACE_DROP_CONTROLr; 
  24142            break;
  24143 
  24144        case bcmOamControlFlexibleDropCPlusSVlan:
  24145            reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 
  24146            break;
  24147 
  24148        case bcmOamControlFlexibleDropVP:
  24149            reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 
  24150            break;
  24151 
  24152        case bcmOamControlFlexibleDropEgressPort:
  24153            reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 
  24154            is_64bit_reg = 1;
  24155            break;
  24156 
  24157        case bcmOamControlFlexibleDropEgressCVlan:
  24158            reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 
  24159            is_64bit_reg = 1;
  24160            break;
  24161 
  24162        case bcmOamControlFlexibleDropEgressSVlan:
  24163            reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 
  24164            is_64bit_reg = 1;
  24165            break;
  24166 
  24167        case bcmOamControlFlexibleDropEgressCPlusSVlan:
  24168            reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 
  24169            is_64bit_reg = 1;
  24170            break;
  24171 
  24172        case bcmOamControlFlexibleDropEgressVP:
  24173            reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 
  24174            is_64bit_reg = 1;
  24175            break;
  24176 
  24177        case bcmOamControlFlexibleDropPasssiveSap:
  24178            reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  24179            break;
  24180 
  24181        case bcmOamControlFlexibleDropEgressPasssiveSap:
  24182            reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 
  24183            break;
  24184 
  24185        default:
  24186            return (BCM_E_UNAVAIL); 
  24187            break;
  24188     }
  24189     if (is_64bit_reg == 0) {
  24190         COMPILER_64_TO_32_LO(rval_32, arg); 
  24191         rv = soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval_32);
  24192     } else {
  24193         rv = soc_reg64_set(unit, reg, REG_PORT_ANY, 0, arg);
  24194     }
  24195     return rv;
  24196 }
  24197 /*
  24198  * Function:
  24199  *     bcm_sb2_oam_control_get
  24200  * Purpose:
  24201  *     Query the value of the device-wide OAM control.
  24202  * Parameters:
  24203  *     unit        - (IN) BCM device number
  24204  *     type        - (IN) OAM control type
  24205  *     arg         - (OUT) A pointer to value of the control 
  24206  * Returns:
  24207  *      BCM_E_XXX
  24208  */
  24209 int bcm_sb2_oam_control_get(int unit, bcm_oam_control_type_t type,
  24210                                      uint64  *arg) 
  24211 {
  24212     int        rv = BCM_E_NONE;
  24213 
  24214     switch(type) {
  24215         case bcmOamControlFlexibleDropPort:
  24216         case bcmOamControlFlexibleDropCVlan:
  24217         case bcmOamControlFlexibleDropSVlan:
  24218         case bcmOamControlFlexibleDropCPlusSVlan:
  24219         case bcmOamControlFlexibleDropVP:
  24220         case bcmOamControlFlexibleDropEgressPort:
  24221         case bcmOamControlFlexibleDropEgressCVlan:
  24222         case bcmOamControlFlexibleDropEgressSVlan:
  24223         case bcmOamControlFlexibleDropEgressCPlusSVlan:
  24224         case bcmOamControlFlexibleDropEgressVP:
  24225         case bcmOamControlFlexibleDropPasssiveSap:
  24226         case bcmOamControlFlexibleDropEgressPasssiveSap:
  24227             rv = _bcm_sb2_oam_flex_drop_get(unit, type, arg);
  24228             break; 
  24229         default:
  24230             rv = BCM_E_UNAVAIL; 
  24231             break;
  24232     }
  24233     return rv;
  24234 }
  24235 
  24236 /* Enables of counting MPLS LM DM packets with unknown ach */
  24237 int 
  24238 _bcm_sb2_oam_unknown_ach_count_enable(int unit)
  24239 {
  24240     uint32 rval = 0;
  24241     soc_reg_field_set(unit, MPLS_UNKNOWN_CONTROL_PACKET_COUNTER_CONTROLr, &rval, 
  24242                   COUNT_ENABLEf, 1);
  24243     SOC_IF_ERROR_RETURN(
  24244          WRITE_MPLS_UNKNOWN_CONTROL_PACKET_COUNTER_CONTROLr(unit, rval));
  24245     return BCM_E_NONE;
  24246 }
  24247 
  24248 /*
  24249  * Function:
  24250  *     bcm_sb2_oam_control_set
  24251  * Purpose:
  24252  *     Set the value of the device-wide OAM control.
  24253  * Parameters:
  24254  *     unit        - (IN) BCM device number
  24255  *     type        - (IN) OAM control type
  24256  *     arg         - (IN) value to be set for control 
  24257  * Returns:
  24258  *      BCM_E_XXX
  24259  */
  24260 int bcm_sb2_oam_control_set(int unit, bcm_oam_control_type_t type,
  24261                                      uint64  arg) 
  24262 {
  24263     int        rv = BCM_E_NONE;
  24264     switch(type) {
  24265         case bcmOamControlFlexibleDropPort:
  24266         case bcmOamControlFlexibleDropCVlan:
  24267         case bcmOamControlFlexibleDropSVlan:
  24268         case bcmOamControlFlexibleDropCPlusSVlan:
  24269         case bcmOamControlFlexibleDropVP:
  24270         case bcmOamControlFlexibleDropEgressPort:
  24271         case bcmOamControlFlexibleDropEgressCVlan:
  24272         case bcmOamControlFlexibleDropEgressSVlan:
  24273         case bcmOamControlFlexibleDropEgressCPlusSVlan:
  24274         case bcmOamControlFlexibleDropEgressVP:
  24275         case bcmOamControlFlexibleDropPasssiveSap:
  24276         case bcmOamControlFlexibleDropEgressPasssiveSap:
  24277             rv = _bcm_sb2_oam_flex_drop_set(unit, type, arg);
  24278             break;
  24279         case bcmOamControlUnknownAchCount:
  24280             rv = _bcm_sb2_oam_unknown_ach_count_enable(unit);
  24281             break; 
  24282         default:
  24283             rv = BCM_E_UNAVAIL; 
  24284             break;
  24285     }
  24286     return rv;
  24287 }
  24288 
  24289 /*
  24290  * Function:
  24291  *     bcm_sb2_oam_upmep_cosq_set
  24292  * Purpose:
  24293  *     Set the value of the device-wide UP MEP PDU type CPU queue.
  24294  * Parameters:
  24295  *     unit        - (IN) BCM device number
  24296  *     upmep_pdu_type        - (IN) UP MEP PDU type
  24297  *     cosq        - (IN) value to be set for CPU queue
  24298  * Returns:
  24299  *      BCM_E_XXX
  24300  */
  24301 int bcm_sb2_oam_upmep_cosq_set(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type,
  24302                                bcm_cos_queue_t cosq)
  24303 {
  24304     int        rv = BCM_E_NONE;
  24305     uint64 cpu_control_2_64;
  24306     uint64 write_val;
  24307 
  24308     SOC_IF_ERROR_RETURN(
  24309             READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64));
  24310     switch(upmep_pdu_type) {
  24311         case bcmOamUpmepPduTypeCcm:
  24312             COMPILER_64_SET(write_val, 0, cosq);
  24313             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  24314                     OAM_CCM_SLOWPATH_CPU_COSf, write_val);
  24315             break;
  24316         case bcmOamUpmepPduTypeLmDm:
  24317             COMPILER_64_SET(write_val, 0, cosq);
  24318             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  24319                     OAM_LMDM_CPU_COSf, write_val);
  24320             break;
  24321         case bcmOamUpmepPduTypeSlowpath:
  24322             COMPILER_64_SET(write_val, 0, cosq);
  24323             soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64,
  24324                     OAM_SLOWPATH_CPU_COSf, write_val);
  24325             break;
  24326         case bcmOamUpmepPduTypeCount :
  24327             rv = BCM_E_PARAM;
  24328             break;
  24329         default:
  24330             rv = BCM_E_UNAVAIL;
  24331             break;
  24332     }
  24333     if (rv == BCM_E_NONE) {
  24334         SOC_IF_ERROR_RETURN(
  24335                 WRITE_EGR_CPU_CONTROL_2_64r(unit, cpu_control_2_64));
  24336     }
  24337     return rv;
  24338 }
  24339 
  24340 /*
  24341  * Function:
  24342  *     bcm_sb2_oam_upmep_cosq_get
  24343  * Purpose:
  24344  *     Query the value of the device-wide UP MEP PDU type CPU queue.
  24345  * Parameters:
  24346  *     unit        - (IN) BCM device number
  24347  *     upmep_pdu_type        - (IN) UP MEP PDU type
  24348  *     cosq        - (OUT) pointer to CPU queue to be get
  24349  * Returns:
  24350  *      BCM_E_XXX
  24351  */
  24352 int bcm_sb2_oam_upmep_cosq_get(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type,
  24353                                bcm_cos_queue_t *cosq)
  24354 {
  24355    int        rv = BCM_E_NONE;
  24356     uint64 cpu_control_2_64;
  24357 
  24358     SOC_IF_ERROR_RETURN(
  24359             READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64));
  24360     switch(upmep_pdu_type) {
  24361         case bcmOamUpmepPduTypeCcm:
  24362             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  24363             cpu_control_2_64, OAM_CCM_SLOWPATH_CPU_COSf);
  24364             break;
  24365         case bcmOamUpmepPduTypeLmDm:
  24366             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  24367             cpu_control_2_64, OAM_LMDM_CPU_COSf);
  24368             break;
  24369         case bcmOamUpmepPduTypeSlowpath:
  24370             *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r,
  24371             cpu_control_2_64, OAM_SLOWPATH_CPU_COSf);
  24372             break;
  24373         case bcmOamUpmepPduTypeCount :
  24374             rv = BCM_E_PARAM;
  24375             break;
  24376         default:
  24377             rv = BCM_E_UNAVAIL;
  24378             break;
  24379     }
  24380     return rv;
  24381 }
  24382 
  24383 int
  24384 bcm_sb2_oam_reg_from_lookup_type_get(bcm_oam_lookup_type_t type)
  24385 {
  24386     switch(type) {
  24387         case bcmOamLookupTypePort:
  24388             return OAM_PORT_INTERFACE_DROP_CONTROL_64r;
  24389             break;
  24390 
  24391         case bcmOamLookupTypeInnerVlan:
  24392             return OAM_C_INTERFACE_DROP_CONTROL_64r;
  24393             break;
  24394 
  24395         case bcmOamLookupTypeOuterVlan:
  24396             return OAM_S_INTERFACE_DROP_CONTROL_64r;
  24397             break;
  24398 
  24399         case bcmOamLookupTypeOuterPlusInnerVlan:
  24400             return OAM_S_C_INTERFACE_DROP_CONTROL_64r;
  24401             break;
  24402 
  24403         case bcmOamLookupTypeVirtualPort:
  24404             return INVALIDr;
  24405             break;
  24406 
  24407         case bcmOamLookupTypeEgressPort:
  24408             return EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r;
  24409             break;
  24410 
  24411         case bcmOamLookupTypeEgressInnerVlan:
  24412             return EGR_OAM_C_INTERFACE_DROP_CONTROL_64r;
  24413             break;
  24414 
  24415         case bcmOamLookupTypeEgressOuterVlan:
  24416             return EGR_OAM_S_INTERFACE_DROP_CONTROL_64r;
  24417             break;
  24418 
  24419         case bcmOamLookupTypeEgressOuterPlusInnerVlan:
  24420             return EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r;
  24421             break;
  24422 
  24423         case bcmOamLookupTypeEgressVirtualPort:
  24424             return INVALIDr;
  24425             break;
  24426 
  24427         case bcmOamLookupTypeOuterVlanPassive:
  24428             return OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr;
  24429             break;
  24430 
  24431         case bcmOamLookupTypeEgressOuterVlanPassive:
  24432             return EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr;
  24433             break;
  24434 
  24435         case bcmOamLookupTypeMplsSection:
  24436             return OAM_SECTION_INTERFACE_DROP_CONTROL_64r;
  24437             break;
  24438         case bcmOamLookupTypeMplsLsp:
  24439             return OAM_LSP_INTERFACE_DROP_CONTROL_64r;
  24440             break;
  24441         case bcmOamLookupTypeMplsPw:
  24442             return OAM_PW_INTERFACE_DROP_CONTROL_64r;
  24443             break;
  24444         case bcmOamLookupTypeEgressMplsSection:
  24445             return EGR_OAM_SECTION_INTERFACE_DROP_CONTROL_64r;
  24446             break;
  24447         case bcmOamLookupTypeEgressMplsLsp:
  24448             return EGR_OAM_LSP_INTERFACE_DROP_CONTROL_64r;
  24449             break;
  24450         case bcmOamLookupTypeEgressMplsPw:
  24451             return EGR_OAM_PW_INTERFACE_DROP_CONTROL_64r;
  24452             break;
  24453         default:
  24454             return INVALIDr;
  24455             break;
  24456     }
  24457     /* not reached */
  24458     return INVALIDr;
  24459 }
  24460 
  24461 /* Disc drop vectors */
  24462 #define CONTROL_FRAME_DROP        0x1
  24463 #define FLOW_CONTROL_MESSAGE_DROP 0x40
  24464 #define MACSA_EQUALS_DA_DROP      0x100
  24465 #define AMT_CONTROL_PACKET_DROP   0x800
  24466 #define UNKNOWN_SUBTENDING_PORT_DROP 0x20000 
  24467 
  24468 /* Vlan drop vectors */
  24469 #define ENIFILTER_DROP    0x2
  24470 #define INVALID_TPID_DROP 0x4
  24471 
  24472 /* MPLS drop control vectors */
  24473 #define MPLS_LABEL_MISS_DROP 0x1
  24474 #define MPLS_INVALID_PAYLOAD_DROP 0x4
  24475 #define MPLS_TTL_CHECK_FAIL_DROP 0x8
  24476 
  24477 
  24478 /* EGR drop control vectors */
  24479 #define TTL_DROP 0x8
  24480 #define STG_BLOCK_DROP 0x20
  24481 #define STG_DISABLE_DROP 0x1000
  24482 #define IPMC_L2_SELF_PORT 0x40
  24483 #define PURGE_PKT 0x80
  24484 #define AGED_PKT 0x100
  24485 #define BAD_TDIP 0x200
  24486 #define VLAN_NOT_FOUND 0x800
  24487 #define PARITY_ERR_DROP 0x10000
  24488 #define SPLIT_HORIZON 0x200000
  24489 #define SOURCE_VIRTUAL_PORT_REMOVAL 0x400000
  24490 #define NONUCAST_PRUNE_DROP 0x1000000
  24491 
  24492 #define _BCM_SET_DISC_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap)
  24493 #define _BCM_SET_VLAN_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap)
  24494 #define _BCM_SET_EGR_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap)
  24495 #define _BCM_SET_MPLS_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap)
  24496 
  24497 
  24498 int
  24499 bcm_sb2_oam_drop_field_condition_set(int unit, soc_reg_t reg, bcm_oam_condition_t condition, int enable)
  24500 {
  24501     uint32 arg = 0;
  24502     soc_field_t field = INVALIDf;
  24503     uint64 reg_val;
  24504     uint32 field_val = 0;
  24505     int set_arg = 0; /* Set the argument value directly */
  24506 
  24507     switch (condition) {
  24508         case bcmOamConditionPFCDrop:
  24509             _BCM_SET_DISC_DROP_CTRL_BIT(arg, CONTROL_FRAME_DROP);
  24510             field = DISC_DROP_VECTOR_CTRLf;
  24511             break;
  24512         case bcmOamConditionFlowControlDrop:
  24513             _BCM_SET_DISC_DROP_CTRL_BIT(arg, FLOW_CONTROL_MESSAGE_DROP);
  24514             field = DISC_DROP_VECTOR_CTRLf;
  24515             break;
  24516         case bcmOamConditionMacsaEqualsMacdaDrop:
  24517             _BCM_SET_DISC_DROP_CTRL_BIT(arg, MACSA_EQUALS_DA_DROP);
  24518             field = DISC_DROP_VECTOR_CTRLf;
  24519             break;
  24520         case bcmOamConditionAutoMulticastTunnelControlPacketDrop:
  24521             _BCM_SET_DISC_DROP_CTRL_BIT(arg, AMT_CONTROL_PACKET_DROP);
  24522             field = DISC_DROP_VECTOR_CTRLf;
  24523             break;
  24524         case bcmOamConditionUnknownSubportErrorDrop:
  24525             _BCM_SET_DISC_DROP_CTRL_BIT(arg, UNKNOWN_SUBTENDING_PORT_DROP);
  24526             field = DISC_DROP_VECTOR_CTRLf;
  24527             break;
  24528         case bcmOamConditionSubportPktTagDrop:
  24529             field = INVALIDf;
  24530             break;
  24531         case bcmOamConditionNoSubportPktTagDrop:
  24532             field = INVALIDf;
  24533             break;
  24534         case bcmOamConditionIngressFilterDrop:
  24535             _BCM_SET_VLAN_DROP_CTRL_BIT(arg, ENIFILTER_DROP);
  24536             field = VLAN_DROP_VECTOR_CTRLf;
  24537             break;
  24538         case bcmOamConditionEgressFilterDrop:
  24539             field = INVALIDf;
  24540             break;
  24541         case bcmOamConditionInvalidTpidDrop:
  24542             _BCM_SET_VLAN_DROP_CTRL_BIT(arg, INVALID_TPID_DROP);
  24543             field = VLAN_DROP_VECTOR_CTRLf;
  24544             break;
  24545         case bcmOamConditionOamMetadataHeaderErrorDrop:
  24546             field = OLP_ERROR_DROP_CTRLf;
  24547             arg = enable?1:0;
  24548             set_arg = 1;
  24549             break;
  24550         case bcmOamConditionFieldLookupDrop:
  24551             field = VFP_DROP_CTRLf;
  24552             arg = enable?1:0;
  24553             set_arg = 1;
  24554             break;
  24555         case bcmOamConditionSATDrop:
  24556             field = SAT_DN_SAMP_RX_DROP_CTRLf;
  24557             arg = enable?1:0;
  24558             set_arg = 1;
  24559             break;
  24560         case bcmOamConditionVlanTranslateIngressMissDrop:
  24561             field = CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf;
  24562             arg = enable?1:0;
  24563             set_arg = 1;
  24564             break;
  24565         case bcmOamConditionVlanTranslateEgressMissDrop:
  24566             field = CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf;
  24567             arg = enable?1:0;
  24568             set_arg = 1;
  24569             break;
  24570         case bcmOamConditionMplsLabelLookupMissDrop:
  24571             _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_LABEL_MISS_DROP);
  24572             field = MPLS_DROP_VECTOR_CTRLf;
  24573             break;
  24574         case bcmOamConditionMplsInvalidActionDrop:
  24575             _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_LABEL_MISS_DROP);
  24576             field = MPLS_DROP_VECTOR_CTRLf;
  24577             break;
  24578         case bcmOamConditionMplsInvalidPayloadDrop:
  24579             _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_INVALID_PAYLOAD_DROP);
  24580             field = MPLS_DROP_VECTOR_CTRLf;
  24581             break;
  24582         case bcmOamConditionMplsTtlErrorDrop:
  24583             _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_TTL_CHECK_FAIL_DROP);
  24584             field = MPLS_DROP_VECTOR_CTRLf;
  24585             break;
  24586         case bcmOamConditionStgNotInForwardDrop:
  24587             field = SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf;
  24588             arg = enable?1:0;
  24589             set_arg = 1;
  24590             break;
  24591         case bcmOamConditionEgressTtlErrorDrop:
  24592             _BCM_SET_EGR_DROP_CTRL_BIT(arg, TTL_DROP);
  24593             field = EGR_DROP_VECTOR_CTRLf;
  24594             break;
  24595         case bcmOamConditionEgressStgBlockedDrop:
  24596             _BCM_SET_EGR_DROP_CTRL_BIT(arg, STG_BLOCK_DROP);
  24597             field = EGR_DROP_VECTOR_CTRLf;
  24598             break;
  24599         case bcmOamConditionEgressStgDisabledDrop:
  24600             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24601                         STG_DISABLE_DROP);
  24602             field = EGR_DROP_VECTOR_CTRLf;
  24603             break;
  24604         case bcmOamConditionEgressIPMCSameVlanPruneDrop:
  24605             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24606                         IPMC_L2_SELF_PORT);
  24607             field = EGR_DROP_VECTOR_CTRLf;
  24608             break;
  24609         case bcmOamConditionEgressMMUErrorDrop:
  24610             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24611                         PURGE_PKT | AGED_PKT);
  24612             field = EGR_DROP_VECTOR_CTRLf;
  24613             break;
  24614         case bcmOamConditionEgressBadTdipDrop:
  24615             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24616                         BAD_TDIP);
  24617             field = EGR_DROP_VECTOR_CTRLf;
  24618             break;
  24619         case bcmOamConditionEgressUnknownVlanDrop:
  24620             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24621                         VLAN_NOT_FOUND);
  24622             field = EGR_DROP_VECTOR_CTRLf;
  24623             break;
  24624         case bcmOamConditionEgressCompositeErrorDrop:
  24625             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24626                         PARITY_ERR_DROP);
  24627             field = EGR_DROP_VECTOR_CTRLf;
  24628             break;
  24629         case bcmOamConditionEgressSplitHorizonDrop:
  24630             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24631                         SPLIT_HORIZON);
  24632             field = EGR_DROP_VECTOR_CTRLf;
  24633             break;
  24634         case bcmOamConditionEgressSVPRemovalDrop:
  24635             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24636                         SOURCE_VIRTUAL_PORT_REMOVAL);
  24637             field = EGR_DROP_VECTOR_CTRLf;
  24638             break;
  24639         case bcmOamConditionEgressNonUCPruneDrop:
  24640             _BCM_SET_EGR_DROP_CTRL_BIT(arg, 
  24641                         NONUCAST_PRUNE_DROP);
  24642             field = EGR_DROP_VECTOR_CTRLf;
  24643             break;
  24644         default:
  24645             return BCM_E_PARAM;
  24646             break;
  24647     }
  24648     /* Validate condition type */
  24649     if (field == INVALIDf) {
  24650         return BCM_E_PARAM;
  24651     }
  24652 
  24653     /* Validate lookup and condition combination */
  24654     if (!soc_reg_field_valid(unit, reg, field)) {
  24655         return BCM_E_PARAM;
  24656     }
  24657 
  24658     COMPILER_64_ZERO(reg_val);
  24659 
  24660     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg,
  24661                     REG_PORT_ANY, 0, &reg_val));
  24662     /* Read the prev value */
  24663     field_val = soc_reg64_field32_get(unit, reg, reg_val, field);
  24664 
  24665     /* Modify it */
  24666     if (!set_arg) {
  24667         if (enable) {
  24668             field_val |= arg;
  24669         } else {
  24670             field_val &= ~arg;
  24671         }
  24672     } else {
  24673         field_val = arg;
  24674     }
  24675 
  24676     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg,
  24677                              REG_PORT_ANY, field, field_val));
  24678     return BCM_E_NONE;
  24679 }
  24680 
  24681 int
  24682 bcm_sb2_oam_lookup_enable_set(
  24683         int unit,
  24684         bcm_oam_lookup_type_t type,
  24685         bcm_oam_condition_t condition,
  24686         int enable)
  24687 {
  24688     soc_reg_t reg = INVALIDr;
  24689 
  24690     reg = bcm_sb2_oam_reg_from_lookup_type_get(type);
  24691     /* Validate lookup type */
  24692     if (reg == INVALIDr) {
  24693         return BCM_E_PARAM;
  24694     }
  24695 
  24696     return bcm_sb2_oam_drop_field_condition_set(unit, reg, condition, enable);
  24697 }
  24698 
  24699 int
  24700 bcm_sb2_oam_lookup_enable_multi_set(
  24701         int unit,
  24702         bcm_oam_lookup_types_t type,
  24703         bcm_oam_conditions_t conditions,
  24704         int enable)
  24705 {
  24706     bcm_oam_lookup_type_t lookup;
  24707     bcm_oam_condition_t condition;
  24708 
  24709     for (lookup = 0; lookup  < bcmOamLookupTypeCount; lookup++) {
  24710         if (BCM_OAM_LOOKUP_TYPE_GET(type, lookup)) {
  24711             for (condition = 0; condition < bcmOamConditionCount; condition++) {
  24712                 if (BCM_OAM_CONDITION_GET(conditions, condition)) {
  24713                     BCM_IF_ERROR_RETURN(bcm_sb2_oam_lookup_enable_set(unit, lookup, condition, enable));
  24714                 } 
  24715             }
  24716         }
  24717     }
  24718     return BCM_E_NONE;
  24719 }
  24720 
  24721 int
  24722 bcm_sb2_oam_lookup_enable_get(
  24723         int unit,
  24724         bcm_oam_lookup_type_t type,
  24725         bcm_oam_conditions_t *condition)
  24726 {
  24727     return BCM_E_NONE;
  24728 }
  24729 
  24730 #if defined(INCLUDE_BHH)
  24731 /*
  24732  * Function:
  24733  *      _bcm_sb2_oam_bhh_encap_data_dump
  24734  * Purpose:
  24735  *      Dumps buffer contents.
  24736  * Parameters:
  24737  *      buffer  - (IN) Buffer to dump data.
  24738  *      length  - (IN) Length of buffer.
  24739  * Returns:
  24740  *      None
  24741  */
  24742 void
  24743 _bcm_sb2_oam_bhh_encap_data_dump(uint8 *buffer, int length)
  24744 {
  24745     int i;
  24746 
  24747     LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length));
  24748 
  24749     for (i = 0; i < length; i++) {
  24750         if ((i % 16) == 0) {
  24751             LOG_CLI((BSL_META("\n")));
  24752         }
  24753         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  24754     }
  24755 
  24756     LOG_CLI((BSL_META("\n")));
  24757     return;
  24758 }
  24759 #endif /* defined(INCLUDE_BHH) */
  24760 
  24761 #if defined(INCLUDE_ETH_LM_DM)
  24762 /*
  24763  * Function:
  24764  *      _bcm_sb2_oam_eth_l2_encap_data_dump
  24765  * Purpose:
  24766  *      Dumps buffer contents.
  24767  * Parameters:
  24768  *      buffer  - (IN) Buffer to dump data.
  24769  *      length  - (IN) Length of buffer.
  24770  * Returns:
  24771  *      None
  24772  */
  24773 void
  24774 _bcm_sb2_oam_eth_l2_encap_data_dump(uint8 *buffer, int length)
  24775 {
  24776     int i;
  24777 
  24778     LOG_CLI((BSL_META("\nETH_LM_DM L2  encapsulation (length=%d):\n"), length));
  24779 
  24780     for (i = 0; i < length; i++) {
  24781         if ((i % 16) == 0) {
  24782             LOG_CLI((BSL_META("\n")));
  24783         }
  24784         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  24785     }
  24786 
  24787     LOG_CLI((BSL_META("\n")));
  24788     return;
  24789 }
  24790 
  24791 
  24792 #endif /* (INCLUDE_ETH_LM_DM) */
  24793 
  24794 /*
  24795  * Function:
  24796  *      _bcm_sb2_oam_olp_l2_encap_data_dump
  24797  * Purpose:
  24798  *      Dumps buffer contents.
  24799  * Parameters:
  24800  *      buffer  - (IN) Buffer to dump data.
  24801  *      length  - (IN) Length of buffer.
  24802  * Returns:
  24803  *      None
  24804  */
  24805 void
  24806 _bcm_sb2_oam_olp_l2_encap_data_dump(uint8 *buffer, int length)
  24807 {
  24808     int i;
  24809 
  24810     LOG_CLI((BSL_META("\nETH_LM_DM OLP L2 encapsulation (length=%d):\n"), length));
  24811 
  24812     for (i = 0; i < length; i++) {
  24813         if ((i % 16) == 0) {
  24814             LOG_CLI((BSL_META("\n")));
  24815         }
  24816         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  24817     }
  24818 
  24819     LOG_CLI((BSL_META("\n")));
  24820     return;
  24821 }
  24822 
  24823 
  24824 /*
  24825  * Function:
  24826  *      _bcm_sb2_oam_olp_tx_encap_data_dump
  24827  * Purpose:
  24828  *      Dumps buffer contents.
  24829  * Parameters:
  24830  *      buffer  - (IN) Buffer to dump data.
  24831  *      length  - (IN) Length of buffer.
  24832  * Returns:
  24833  *      None
  24834  */
  24835 void
  24836 _bcm_sb2_oam_olp_tx_encap_data_dump(uint8 *buffer, int length)
  24837 {
  24838     int i;
  24839 
  24840     LOG_CLI((BSL_META("\nETH_LM_DM OLP TX encapsulation (length=%d):\n"), length));
  24841 
  24842     for (i = 0; i < length; i++) {
  24843         if ((i % 16) == 0) {
  24844             LOG_CLI((BSL_META("\n")));
  24845         }
  24846         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  24847     }
  24848 
  24849     LOG_CLI((BSL_META("\n")));
  24850     return;
  24851 }
  24852 
  24853 #if defined(INCLUDE_BHH)
  24854 /*
  24855  * Function:
  24856  *      bcm_sb2_oam_mpls_tp_channel_type_tx_get
  24857  * Purpose:
  24858  *      Get MPLS TP(BHH) ACH Channel type
  24859  * Parameters:
  24860  *      unit                (IN)  BCM device number
  24861  *      channel_type        (IN)  Channel type is ignored in XGS devices
  24862  *      Value               (OUT) User define MPLS TP(BHH) ACH channel type
  24863  *
  24864  * Returns:
  24865  *      BCM_E_NONE          No error
  24866  *      BCM_E_XXXX          Error
  24867  */
  24868 int
  24869 bcm_sb2_oam_mpls_tp_channel_type_tx_get(int unit,
  24870                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  24871                                         int *value)
  24872 {
  24873     *value = sb2_oam_mpls_tp_ach_channel_type;
  24874     return BCM_E_NONE;
  24875 }
  24876 
  24877 /*
  24878  * Function:
  24879  *      bcm_sb2_oam_mpls_tp_channel_type_tx_set
  24880  * Purpose:
  24881  *      Update MPLS TP(BHH) ACH Channel type with user defined value
  24882  * Parameters:
  24883  *      unit                (IN) BCM device number
  24884  *      channel_type        (IN) Channel type is ignored in XGS devices
  24885  *      Value               (IN) User define MPLS TP(BHH) ACH channel type
  24886  *
  24887  * Returns:
  24888  *      BCM_E_NONE          No error
  24889  *      BCM_E_XXXX          Error
  24890  */
  24891 int
  24892 bcm_sb2_oam_mpls_tp_channel_type_tx_set(int unit,
  24893                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  24894                                         int value)
  24895 {
  24896     uint8               *buffer, *buffer_ptr;
  24897     uint16              buffer_len, reply_len;
  24898     int                 rv = BCM_E_NONE;
  24899     int                 index = 0;
  24900     soc_mem_t           mem = MPLS_OAM_ACH_TYPE_CONFIGm;
  24901     uint32              *msg;
  24902     _bcm_oam_control_t  *oc;
  24903 
  24904     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  24905     _BCM_OAM_LOCK(oc);
  24906 
  24907     if (oc->ukernel_not_ready) {
  24908         _BCM_OAM_UNLOCK(oc);
  24909         return BCM_E_INIT;
  24910     }
  24911 
  24912     if ((value != SHR_BHH_ACH_CHANNEL_TYPE) &&
  24913         (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) {
  24914         _BCM_OAM_UNLOCK(oc);
  24915         return BCM_E_CONFIG;
  24916     }
  24917 
  24918     sb2_oam_mpls_tp_ach_channel_type = value;
  24919     soc_mem_field32_modify(unit, mem, index, ACH_TYPEf, value);
  24920     msg = (uint32 *)&sb2_oam_mpls_tp_ach_channel_type;
  24921 
  24922     /* Pack control message data into DMA buffer */
  24923     buffer     = oc->dma_buffer;
  24924     buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg);
  24925     buffer_len = buffer_ptr - buffer;
  24926 
  24927     rv = _bcm_sb2_oam_bhh_msg_send_receive(
  24928                                            unit,
  24929                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE,
  24930                                            buffer_len, 0,
  24931                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY,
  24932                                            &reply_len);
  24933 
  24934     if (BCM_FAILURE(rv)) {
  24935         _BCM_OAM_UNLOCK(oc);
  24936         return (rv);
  24937     }
  24938 
  24939     _BCM_OAM_UNLOCK(oc);
  24940     return BCM_E_NONE;
  24941 }
  24942 
  24943 STATIC int
  24944 _bcm_sb2_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach)
  24945 {
  24946     sal_memset(ach, 0, sizeof(*ach));
  24947 
  24948     ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE;
  24949     ach->version  = SHR_BHH_ACH_VERSION;
  24950     ach->reserved = 0;
  24951 
  24952     ach->channel_type = sb2_oam_mpls_tp_ach_channel_type;
  24953 
  24954     return (BCM_E_NONE);
  24955 }
  24956 
  24957 STATIC int
  24958 _bcm_sb2_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
  24959                            _mpls_label_t *mpls)
  24960 {
  24961     sal_memset(mpls, 0, sizeof(*mpls));
  24962 
  24963     mpls->label = label;
  24964     mpls->exp   = exp & 0x07;
  24965     mpls->s     = s;
  24966     if(ttl)
  24967         mpls->ttl   = ttl;
  24968     else
  24969         mpls->ttl   = _BHH_MPLS_DFLT_TTL;
  24970 
  24971     return (BCM_E_NONE);
  24972 }
  24973 
  24974 STATIC int
  24975 _bcm_sb2_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp)
  24976 {
  24977     return _bcm_sb2_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL,
  24978                                       oam_exp, 1, 1, mpls);
  24979 }
  24980 
  24981 STATIC int
  24982 _bcm_sb2_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  24983                                  uint32 packet_flags, int max_count,
  24984                                  _mpls_label_t *mpls, int *mpls_count,
  24985                                  bcm_if_t *l3_intf_id, uint8 oam_exp,
  24986                                  uint8 oam_ttl)
  24987 {
  24988     int count = 0;
  24989     bcm_l3_egress_t l3_egress;
  24990     bcm_mpls_port_t mpls_port;
  24991     bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS];
  24992     bcm_mpls_egress_label_t tmp_label;
  24993     int label_count;
  24994     int i = 0;
  24995 
  24996      /* Get L3 objects */
  24997     bcm_l3_egress_t_init(&l3_egress);
  24998     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  24999         return (BCM_E_PARAM);
  25000     }
  25001 
  25002     /* Look for a tunnel associated with this interface */
  25003     if (BCM_SUCCESS
  25004         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
  25005                                            _BHH_MPLS_MAX_LABELS,
  25006                                            label_array, &label_count))) {
  25007         /* We need to swap the labels configured in tunnel initiator as
  25008          * it returns labels in reverse order than how it should be in pkt.
  25009          */
  25010         for (i = 0; i < (label_count / 2); i++) {
  25011             sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label));
  25012             sal_memcpy(&label_array[i], &label_array[label_count - 1 - i],
  25013                        sizeof(tmp_label));
  25014             sal_memcpy(&label_array[label_count - 1 - i], &tmp_label,
  25015                        sizeof(tmp_label));
  25016         }
  25017 
  25018         /* Add VRL Label */
  25019         if (BHH_EP_LSP_TYPE(h_data_p)) {
  25020                 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
  25021                     (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID)  &&
  25022                     (label_count < _BHH_MPLS_MAX_LABELS)) {
  25023                 label_array[label_count].label = l3_egress.mpls_label;
  25024                 label_array[label_count].exp = l3_egress.mpls_exp;
  25025                 label_array[label_count].ttl = l3_egress.mpls_ttl;
  25026                 label_count++;
  25027             }
  25028             /* Traverse through Label stack and match on control label, this
  25029              * label should be the one just above GAL in the label stack, any
  25030              * following labels should not be added.
  25031              */
  25032             for (i = 0;  i < label_count; i++) {
  25033                 if (label_array[i].label == h_data_p->egr_label) {
  25034                     label_array[i].exp = oam_exp;
  25035                     if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  25036                         oam_ttl) {
  25037                         label_array[i].ttl = oam_ttl;
  25038                     }
  25039                     label_count = i + 1;
  25040                     break;
  25041                 }
  25042             }
  25043         }
  25044     }
  25045 
  25046     /* MPLS Router Alert */
  25047     if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  25048         /* Ignore overrun error as RAL is only added for PW MEPs and so overrun
  25049          * condition will not exist.
  25050          */
  25051         /* coverity[overrun-local] */
  25052         label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL;
  25053         label_array[label_count].exp = 0;
  25054         label_array[label_count].ttl = 0;
  25055         label_count++;
  25056     }
  25057 
  25058     /* Use GPORT to resolve interface */
  25059     if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
  25060         /* Get mpls port and label info */
  25061         bcm_mpls_port_t_init(&mpls_port);
  25062         mpls_port.mpls_port_id = h_data_p->gport;
  25063         if (BCM_FAILURE
  25064             (bcm_esw_mpls_port_get(unit, h_data_p->vpn,
  25065                                    &mpls_port))) {
  25066             return (BCM_E_PARAM);
  25067         }
  25068         label_array[label_count].label = mpls_port.egress_label.label;
  25069         /* Take the user provided exp, if the user passed the PW label */
  25070         if (h_data_p->egr_label == mpls_port.egress_label.label) {
  25071             label_array[label_count].exp = oam_exp;
  25072             if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  25073                 oam_ttl) {
  25074                 label_array[label_count].ttl = oam_ttl;
  25075             }
  25076         } else {
  25077             label_array[label_count].exp = mpls_port.egress_label.exp;
  25078             label_array[label_count].ttl = mpls_port.egress_label.ttl;
  25079         }
  25080 
  25081         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  25082             h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  25083             label_array[label_count].ttl = 1;
  25084         }
  25085         label_count++;
  25086     }
  25087 
  25088     for (i=0;  i < label_count; i++) {
  25089         _bcm_sb2_oam_bhh_mpls_label_get(label_array[i].label,
  25090                                         label_array[i].exp,
  25091                                         0,
  25092                                         label_array[i].ttl,
  25093                                         &mpls[count++]);
  25094     }
  25095 
  25096     /* Set Bottom of Stack if there is no GAL label */
  25097     if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) {
  25098         mpls[count-1].s = 1;
  25099     }
  25100 
  25101     *mpls_count = count;
  25102 
  25103     return (BCM_E_NONE);
  25104 
  25105 }
  25106 
  25107 STATIC int
  25108 _bcm_sb2_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  25109                                 bcm_port_t port, uint16 etype,
  25110                                 _l2_header_t *l2, uint8 *lm_pdu_counter_offset)
  25111 {
  25112     uint16 tpid;
  25113     bcm_l3_egress_t l3_egress;
  25114     bcm_l3_intf_t l3_intf;
  25115     bcm_vlan_control_vlan_t vc;
  25116     int tpid_select;
  25117     bcm_pbmp_t pbmp, ubmp;
  25118 
  25119     sal_memset(l2, 0, sizeof(*l2));
  25120 
  25121     if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  25122         /* Get L3 interfaces */
  25123         bcm_l3_egress_t_init(&l3_egress);
  25124         bcm_l3_intf_t_init(&l3_intf);
  25125 
  25126         if (BCM_FAILURE
  25127                 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  25128             return (BCM_E_PARAM);
  25129         }
  25130 
  25131         l3_intf.l3a_intf_id = l3_egress.intf;
  25132         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  25133             return (BCM_E_PARAM);
  25134         }
  25135 
  25136         /* Get TPID */
  25137         BCM_IF_ERROR_RETURN(
  25138                        bcm_esw_vlan_control_port_get(unit,
  25139                                                      port,
  25140                                                      bcmVlanPortOuterTpidSelect,
  25141                                                      &tpid_select));
  25142         if (tpid_select == BCM_PORT_OUTER_TPID) {
  25143             BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
  25144         } else {
  25145             BCM_IF_ERROR_RETURN(
  25146                      bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
  25147             tpid = vc.outer_tpid;
  25148         }
  25149 
  25150         sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
  25151         sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
  25152         *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH;
  25153         l2->vlan_tag.tpid     = tpid;
  25154         l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  25155         l2->vlan_tag.tci.cfi  = 0;
  25156         l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
  25157         *lm_pdu_counter_offset += 4;
  25158 
  25159         BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
  25160                                                   l2->vlan_tag.tci.vid,
  25161                                                   &pbmp,
  25162                                                   &ubmp));
  25163         if (BCM_PBMP_MEMBER(ubmp, port)) {
  25164             l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
  25165             *lm_pdu_counter_offset -= 4;
  25166         }
  25167 
  25168         if (l3_intf.l3a_inner_vlan != 0) {
  25169             BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
  25170             l2->vlan_tag_inner.tpid     = tpid;
  25171             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  25172             l2->vlan_tag_inner.tci.cfi  = 0;
  25173             l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
  25174             *lm_pdu_counter_offset += 4;
  25175         }
  25176     }else {
  25177         sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH);
  25178         sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH);
  25179         *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH;
  25180         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) ||
  25181            (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
  25182            (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
  25183             if (h_data_p->vlan != 0) {
  25184                 l2->vlan_tag.tpid     = h_data_p->outer_tpid;
  25185                 l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  25186                 l2->vlan_tag.tci.cfi  = 0;
  25187                 l2->vlan_tag.tci.vid  = h_data_p->vlan;
  25188                 *lm_pdu_counter_offset += 4;
  25189             }
  25190         }
  25191         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
  25192            (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
  25193             l2->vlan_tag_inner.tpid     = h_data_p->inner_tpid;
  25194             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  25195             l2->vlan_tag_inner.tci.cfi  = 0;
  25196             l2->vlan_tag_inner.tci.vid  = h_data_p->inner_vlan;
  25197             *lm_pdu_counter_offset += 4;
  25198         }
  25199         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
  25200     }
  25201     l2->etype             = etype;
  25202     *lm_pdu_counter_offset += 2;
  25203 
  25204     return (BCM_E_NONE);
  25205 }
  25206 #endif /* (INCLUDE_BHH) */
  25207 
  25208 
  25209 #if defined(INCLUDE_ETH_LM_DM)
  25210 /* Create L2 header for ETH_LM_DM OAM packet */
  25211 STATIC int
  25212 _bcm_sb2_oam_eth_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  25213                                 bcm_port_t port, uint16 etype,	
  25214                                 _eth_l2_header_t *l2,
  25215                                 uint8   pkt_pri)
  25216 {
  25217     uint8 outer_pri = 0, inner_pri = 0;
  25218 
  25219     switch(h_data_p->oam_domain) {
  25220 
  25221         case _BCM_OAM_DOMAIN_CVLAN:
  25222             outer_pri = h_data_p->vlan_pri; 
  25223             inner_pri = pkt_pri;
  25224             break;
  25225 
  25226         case _BCM_OAM_DOMAIN_SVLAN:
  25227             outer_pri = pkt_pri;
  25228             inner_pri = 0;
  25229             break;
  25230 
  25231         case _BCM_OAM_DOMAIN_S_PLUS_CVLAN:
  25232             outer_pri = pkt_pri;
  25233             inner_pri = h_data_p->inner_vlan_pri;
  25234             break;
  25235 
  25236         case _BCM_OAM_DOMAIN_PORT:
  25237             outer_pri = 0;
  25238             inner_pri = 0;
  25239             break;
  25240 
  25241         default:
  25242             /* ETH LM/DM is not supported for other domains */
  25243             return BCM_E_UNAVAIL;
  25244     }
  25245     
  25246     memcpy(l2->src_mac, h_data_p->src_mac_address, sizeof(bcm_mac_t));
  25247 
  25248     if (h_data_p->outer_tpid) {
  25249         l2->vlan_tag.tpid     = h_data_p->outer_tpid;
  25250      }else {
  25251         l2->vlan_tag.tpid     = BCM_OAM_DEFAULT_TPID;
  25252     }
  25253     l2->vlan_tag.tci.prio = outer_pri;
  25254     l2->vlan_tag.tci.cfi  = 0;
  25255     l2->vlan_tag.tci.vid  = h_data_p->vlan;
  25256 
  25257    if (h_data_p->inner_tpid) {
  25258         l2->inner_vlan_tag.tpid     = h_data_p->inner_tpid;
  25259      }else {
  25260         l2->inner_vlan_tag.tpid     = BCM_OAM_DEFAULT_TPID;
  25261     }
  25262     l2->inner_vlan_tag.tci.prio = inner_pri;
  25263     l2->inner_vlan_tag.tci.cfi  = 0;
  25264     l2->inner_vlan_tag.tci.vid  = h_data_p->inner_vlan;
  25265     l2->etype                   = etype;
  25266 
  25267     return (BCM_E_NONE);
  25268 }
  25269 
  25270 /*
  25271  * Function:
  25272  *      _bcm_sb2_oam_bhh_appl_callback
  25273  * Purpose:
  25274  *      Update FW BHH appl state
  25275  * Parameters:
  25276  *      unit  - (IN) Unit number.
  25277  *      uC    - (IN) core number.
  25278  *      stage - (IN) core reset stage.
  25279  *      user_data - (IN) data pointer.
  25280  * Returns:
  25281  *      BCM_E_XXX
  25282  * Notes:
  25283  */
  25284 
  25285 int _bcm_sb2_oam_eth_lm_dm_appl_callback(int unit,
  25286         int uC,
  25287         soc_cmic_uc_shutdown_stage_t stage,
  25288         void *user_data) {
  25289     _bcm_oam_control_t *oc;
  25290 
  25291     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  25292     _BCM_OAM_LOCK(oc);
  25293     oc->eth_lm_dm_ukernel_not_ready = 1;
  25294 
  25295     _BCM_OAM_UNLOCK(oc);
  25296 
  25297     return BCM_E_NONE;
  25298 }
  25299 
  25300 #endif
  25301 
  25302 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_BHH)
  25303 /* Create OLP-L2 header for ETH_LM_DM Tx OAM packet */
  25304 STATIC int
  25305 _bcm_sb2_oam_olp_l2_header_get(int unit, int cpu_dglp, soc_olp_l2_hdr_t *l2)
  25306 {
  25307     uint16			tpid;
  25308     uint16			vlanId;
  25309     uint16 			ethertype;
  25310     egr_olp_config_entry_t    	eolp_cfg;
  25311     uint64                    iarb_olp_cfg;
  25312     uint64                    iarb_olp_cfg_1;
  25313     bcm_mac_t olp_mac;
  25314     bcm_mac_t xgs_mac;
  25315     int index;
  25316     lmep_entry_t lmep_entry;
  25317     int rv;
  25318 
  25319     memset(l2, 0, sizeof(soc_olp_l2_hdr_t));
  25320     sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
  25321     sal_memset(&eolp_cfg, 0, sizeof(egr_olp_config_entry_t));
  25322 
  25323     rv = _bcm_switch_olp_dglp_get(unit, cpu_dglp, &olp_mac, &index);
  25324     if (BCM_FAILURE(rv)) {
  25325         LOG_ERROR(BSL_LS_BCM_OAM,
  25326                 (BSL_META_U(unit,
  25327                             "OAM(unit %d) Error: READ_EGR_OLP_DGPP_CONFIG table read failed"
  25328                             " %s.\n"), unit , bcm_errmsg(rv)));
  25329         return (rv);
  25330     }
  25331 
  25332     /* Get MAC DA of OLP*/												
  25333     rv = READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY,
  25334             0, &eolp_cfg);
  25335     if (BCM_FAILURE(rv)) {
  25336         LOG_ERROR(BSL_LS_BCM_OAM,
  25337                 (BSL_META_U(unit,
  25338                             "OAM(unit %d) Error: EGR_OLP_DGPP_CONFIG table read failed"
  25339                             " %s.\n"), unit, bcm_errmsg(rv)));
  25340         return (rv);
  25341     }										
  25342     soc_mem_mac_addr_get(unit ,EGR_OLP_CONFIGm,  &eolp_cfg,
  25343             MACSAf, xgs_mac);
  25344 
  25345     /* Get TPID of OLP*/
  25346     rv = READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY,
  25347             0, &eolp_cfg);
  25348     if (BCM_FAILURE(rv)) {
  25349         LOG_ERROR(BSL_LS_BCM_OAM,
  25350                 (BSL_META_U(unit,
  25351                             "OAM(unit %d) Error: READ_EGR_OLP_CONFIG table read failed"
  25352                             " %s.\n"), unit, bcm_errmsg(rv)));
  25353         return (rv);
  25354     }	
  25355     tpid  = soc_mem_field32_get(unit, EGR_OLP_CONFIGm, &eolp_cfg,
  25356             VLAN_TPIDf);
  25357     if (BCM_FAILURE(rv)) {
  25358         LOG_ERROR(BSL_LS_BCM_OAM,
  25359                 (BSL_META_U(unit,
  25360                             "OAM(unit %d) Error: READ_EGR_OLP_CONFIG table read failed"
  25361                             " %s.\n"), unit, bcm_errmsg(rv)));
  25362         return (rv);
  25363     }
  25364     /* Get hardware table entry information.  */
  25365     rv = READ_IARB_OLP_CONFIGr(unit, &iarb_olp_cfg);
  25366     if (BCM_FAILURE(rv)) {
  25367         LOG_ERROR(BSL_LS_BCM_OAM,
  25368                 (BSL_META_U(unit,
  25369                             "OAM(unit %d) Error: IARB_OLP_CONFIG register read failed"
  25370                             " %s.\n"), unit , bcm_errmsg(rv)));
  25371         return (rv);
  25372     }
  25373     ethertype = soc_reg64_field_get(unit, IARB_OLP_CONFIGr,
  25374             iarb_olp_cfg, ETHERTYPEf);
  25375 
  25376     rv = READ_IARB_OLP_CONFIG_1r(unit, &iarb_olp_cfg_1);
  25377     if (BCM_FAILURE(rv)) {
  25378         LOG_ERROR(BSL_LS_BCM_OAM,
  25379                 (BSL_META_U(unit,
  25380                             "OAM(unit %d) Error: READ_EGR_OLP_CONFIG_1 table read failed"
  25381                             " %s.\n"), unit , bcm_errmsg(rv)));
  25382         return (rv);
  25383     }
  25384     vlanId = soc_reg64_field_get(unit, IARB_OLP_CONFIG_1r,
  25385             iarb_olp_cfg_1, VLAN_IDf);
  25386 
  25387     memcpy(l2->dst_mac, xgs_mac, sizeof(bcm_mac_t));
  25388     memcpy(l2->src_mac, olp_mac, sizeof(bcm_mac_t));	
  25389     l2->tpid	= tpid;
  25390     l2->vlan	= vlanId;
  25391     l2->etherType = ethertype;
  25392 
  25393     return (BCM_E_NONE);
  25394 }
  25395 #endif /* INCLUDE_ETH_LM_DM || INCLUDE_MPLS_LM_DM || INCLUDE_BHH */
  25396 
  25397 #if defined(INCLUDE_BHH)
  25398 STATIC uint8 *
  25399 _bcm_sb2_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach)
  25400 {
  25401     uint32  tmp;
  25402 
  25403     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
  25404         (ach->reserved << 16) | ach->channel_type;
  25405 
  25406     _BHH_ENCAP_PACK_U32(buffer, tmp);
  25407 
  25408     return (buffer);
  25409 }
  25410 
  25411 STATIC uint8 *
  25412 _bcm_sb2_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls)
  25413 {
  25414     uint32  tmp;
  25415 
  25416     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
  25417         ((mpls->s & 0x1) << 8) | mpls->ttl;
  25418     _BHH_ENCAP_PACK_U32(buffer, tmp);
  25419 
  25420     return (buffer);
  25421 }
  25422 
  25423 STATIC uint8 *
  25424 _bcm_sb2_oam_bhh_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls)
  25425 {
  25426      uint32  tmp;
  25427 
  25428     _SHR_UNPACK_U32(buffer, tmp);
  25429     mpls->label = (tmp >> 12) & 0xfffff;
  25430     mpls->exp = (tmp >> 9) & 0x7;
  25431     mpls->s = (tmp >> 8) & 0x1;
  25432     mpls->ttl = tmp & 0xffff;
  25433 
  25434     return (buffer);
  25435 }
  25436 
  25437 STATIC uint8 *
  25438 _bcm_sb2_oam_bhh_l2_header_pack(bcm_oam_endpoint_type_t type, 
  25439                                 uint8 *buffer, _l2_header_t *l2)
  25440 {
  25441     uint32  tmp;
  25442     int     i;
  25443 
  25444     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  25445         _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
  25446     }
  25447 
  25448     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  25449         _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
  25450     }
  25451 
  25452     /* Vlan Tag tpid = 0 indicates untagged */
  25453     if (0 != l2->vlan_tag.tpid) {
  25454         tmp =  (l2->vlan_tag.tpid            << 16) |
  25455               ((l2->vlan_tag.tci.prio & 0x7) << 13) |
  25456               ((l2->vlan_tag.tci.cfi  & 0x1) << 12) |
  25457                (l2->vlan_tag.tci.vid  & 0xfff);
  25458         _BHH_ENCAP_PACK_U32(buffer, tmp);
  25459     }
  25460 
  25461     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
  25462     if (0 != l2->vlan_tag_inner.tpid) {
  25463         tmp = (l2->vlan_tag_inner.tpid            << 16) |
  25464              ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) |
  25465              ((l2->vlan_tag_inner.tci.cfi  & 0x1) << 12) |
  25466               (l2->vlan_tag_inner.tci.vid  & 0xfff);
  25467         _BHH_ENCAP_PACK_U32(buffer, tmp);
  25468     }
  25469     _BHH_ENCAP_PACK_U16(buffer, l2->etype);
  25470 
  25471     return (buffer);
  25472 }
  25473 #endif
  25474 
  25475 #if defined(INCLUDE_ETH_LM_DM)
  25476 STATIC uint8 *
  25477 _bcm_sb2_oam_eth_l2_header_pack(uint8 *buffer, _eth_l2_header_t *l2)
  25478 {
  25479     uint32  tmp;
  25480     int     i;
  25481 
  25482     for (i = 0; i < _ETH_LM_DM_MAC_ADDR_LENGTH; i++) {
  25483         _ETH_LM_DM_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
  25484     }
  25485 
  25486     for (i = 0; i < _ETH_LM_DM_MAC_ADDR_LENGTH; i++) {
  25487         _ETH_LM_DM_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
  25488     }
  25489 
  25490     /* Outer vlan Tag */
  25491     if(l2->vlan_tag.tci.vid) {
  25492     tmp = (l2->vlan_tag.tpid << 16) | ((l2->vlan_tag.tci.prio & 0x7) << 13) |
  25493         ((l2->vlan_tag.tci.cfi & 0x1) << 12) | (l2->vlan_tag.tci.vid & 0xfff);
  25494     _ETH_LM_DM_ENCAP_PACK_U32(buffer, tmp);
  25495     }
  25496 
  25497     /* Inner Vlan Tag */
  25498     if(l2->inner_vlan_tag.tci.vid) {
  25499     tmp = (l2->inner_vlan_tag.tpid << 16) | ((l2->inner_vlan_tag.tci.prio & 0x7) << 13) |
  25500         ((l2->inner_vlan_tag.tci.cfi & 0x1) << 12) | (l2->inner_vlan_tag.tci.vid & 0xfff);
  25501     _ETH_LM_DM_ENCAP_PACK_U32(buffer, tmp);
  25502     }
  25503 
  25504     _ETH_LM_DM_ENCAP_PACK_U16(buffer, l2->etype);
  25505 
  25506     return (buffer);
  25507 }
  25508 #endif
  25509 
  25510 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_BHH)
  25511 STATIC uint8 *
  25512 _bcm_sb2_oam_olp_l2_header_pack(uint8 *buffer, soc_olp_l2_hdr_t *l2)
  25513 {
  25514     
  25515     int     i;
  25516 
  25517     for (i = 0; i < 6; i++) {
  25518         _SHR_PACK_U8(buffer, l2->dst_mac[i]);
  25519     }
  25520 
  25521     for (i = 0; i < 6; i++) {
  25522         _SHR_PACK_U8(buffer, l2->src_mac[i]);
  25523     }
  25524 
  25525     /* Vlan tpid */
  25526     _SHR_PACK_U16(buffer, l2->tpid);
  25527 
  25528     /* Vlan Id */
  25529     _SHR_PACK_U16(buffer, l2->vlan);
  25530 
  25531     /* Ethertype */
  25532     _SHR_PACK_U16(buffer, l2->etherType);
  25533 
  25534     return (buffer);
  25535 }
  25536 
  25537 STATIC uint8 *_bcm_sb2_oam_olp_l2_header_unpack(uint8 *buffer, soc_olp_l2_hdr_t *l2)
  25538 {
  25539     int     i;
  25540 
  25541     for (i = 0; i < 6; i++) {
  25542         _SHR_UNPACK_U8(buffer, l2->dst_mac[i]);
  25543     }
  25544 
  25545     for (i = 0; i < 6; i++) {
  25546         _SHR_UNPACK_U8(buffer, l2->src_mac[i]);
  25547     }
  25548 
  25549     /* Vlan tpid */
  25550     _SHR_UNPACK_U16(buffer, l2->tpid);
  25551 
  25552     /* Vlan Id */
  25553     _SHR_UNPACK_U16(buffer, l2->vlan);
  25554 
  25555     /* Ethertype */
  25556     _SHR_UNPACK_U16(buffer, l2->etherType);
  25557 
  25558     return (buffer);
  25559 }
  25560 
  25561 STATIC int
  25562 _bcm_sb2_oam_olp_tx_header_decap(int        unit,
  25563                                  uint8      *encap_data,
  25564                                  uint8      *counter_size,
  25565                                  uint32     *counter_base_id,
  25566                                  uint32     *counter_offset,
  25567                                  uint8      *counter_action,
  25568                                  uint32     *counter_lm_counter_byte_offset,
  25569                                  uint8      *ts_mode,
  25570                                  uint8      *lm_pdu_counter_offset,
  25571                                  bcm_cos_t  *int_pri)
  25572 {
  25573     soc_olp_tx_hdr_t olp_oam_header;
  25574     int i = 0, action[BCM_OAM_LM_COUNTER_MAX];
  25575     uint8 oam_replacement_offset;
  25576 
  25577     /* NULL pointer */
  25578     if(!encap_data) {
  25579         return BCM_E_MEMORY;
  25580     }
  25581 
  25582     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
  25583     encap_data = shr_olp_tx_header_unpack(encap_data, &olp_oam_header);
  25584 
  25585     action[i] = SOC_OLP_TX_CTR1_ACTION_GET(&olp_oam_header);
  25586     if ((action[i] == 1) || (action[i] == 2)) {
  25587         /* We do a mod 8 since we always allocate counters in chunks of 8 */
  25588         counter_offset[i] = SOC_OLP_TX_CTR1_ID_GET(&olp_oam_header) % 8;
  25589         counter_base_id[i] =
  25590             SOC_OLP_TX_CTR1_ID_GET(&olp_oam_header) - counter_offset[i];
  25591 
  25592         if(counter_action) {
  25593             counter_action[i]= action[i];
  25594         }
  25595         if(counter_lm_counter_byte_offset) {
  25596             counter_lm_counter_byte_offset[i] = 
  25597                 SOC_OLP_TX_CTR1_OFF_LM_GET(&olp_oam_header);
  25598         }
  25599 
  25600         i++;
  25601     }
  25602     action[i] = SOC_OLP_TX_CTR2_ACTION_GET(&olp_oam_header);
  25603     if ((action[i] == 1) || (action[i] == 2)) {
  25604         /* We do a mod 8 since we always allocate counters in chunks of 8 */
  25605         counter_offset[i] = SOC_OLP_TX_CTR2_ID_GET(&olp_oam_header) % 8;
  25606         /* Encode pool number = 1 in base id as well */
  25607         counter_base_id[i] =
  25608             (SOC_OLP_TX_CTR2_ID_GET(&olp_oam_header) - counter_offset[i]) | (1 << 24);
  25609 
  25610         if(counter_action) {
  25611             counter_action[i]= action[i];
  25612         }
  25613 
  25614         if(counter_lm_counter_byte_offset) {
  25615             counter_lm_counter_byte_offset[i] =
  25616                 SOC_OLP_TX_CTR2_OFF_LM_GET(&olp_oam_header);
  25617         }
  25618 
  25619         i++;
  25620     }
  25621     action[i] = SOC_OLP_TX_CTR3_ACTION_GET(&olp_oam_header);
  25622     if ((action[i] == 1) || (action[i] == 2)) {
  25623         /* We do a mod 8 since we always allocate counters in chunks of 8 */
  25624         counter_offset[i] = SOC_OLP_TX_CTR3_ID_GET(&olp_oam_header) % 8;
  25625         /* Encode pool number = 1 in base id as well */
  25626         counter_base_id[i] =
  25627             (SOC_OLP_TX_CTR3_ID_GET(&olp_oam_header) - counter_offset[i]) | (2 << 24);
  25628 
  25629         if(counter_action) {
  25630             counter_action[i]= action[i];
  25631         } 
  25632  
  25633         if(counter_lm_counter_byte_offset) {
  25634             counter_lm_counter_byte_offset[i] =
  25635                 SOC_OLP_TX_CTR2_OFF_LM_GET(&olp_oam_header);
  25636         }
  25637 
  25638         i++;
  25639     }
  25640  
  25641     *counter_size = i;
  25642     
  25643     if(ts_mode) {
  25644         *ts_mode = SOC_OLP_TX_TIMESTAMP_ACTION_GET(&olp_oam_header);
  25645     }
  25646 
  25647     oam_replacement_offset = SOC_OLP_TX_OAM_OFFSET_GET(&olp_oam_header);
  25648 
  25649     if (oam_replacement_offset && lm_pdu_counter_offset) {
  25650         *lm_pdu_counter_offset = (oam_replacement_offset << 1) + 14;
  25651     }
  25652 
  25653     if(int_pri) {
  25654         *int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_header);
  25655     }
  25656     return BCM_E_NONE;
  25657 }
  25658 
  25659 STATIC uint8 *
  25660 _bcm_sb2_oam_olp_l2_header_decap (int unit,
  25661                                   uint8             *encap_data,
  25662                                   soc_olp_l2_hdr_t  *olp_l2_header)
  25663 {
  25664     uint8 *buffer;
  25665     sal_memset(olp_l2_header, 0, sizeof(soc_olp_l2_hdr_t));
  25666     buffer = _bcm_sb2_oam_olp_l2_header_unpack(encap_data, olp_l2_header);
  25667     return buffer;
  25668 }
  25669 
  25670 
  25671 STATIC int
  25672 _bcm_sb2_oam_olp_encap_header_decap(int unit,
  25673                                  uint8      *encap_data,
  25674                                  uint8      *counter_size,
  25675                                  uint32     *counter_base_id,
  25676                                  uint32     *counter_offset,
  25677                                  uint8      *counter_action,
  25678                                  uint8      *ts_mode,
  25679                                  uint8      *lm_pdu_counter_offset,
  25680                                  bcm_cos_t  *int_pri,
  25681                                  uint32     *counter_lm_counter_byte_offset)
  25682 {
  25683     soc_olp_l2_hdr_t olp_l2_header;
  25684     int rv;
  25685 
  25686     /* NULL pointer */
  25687     if(!encap_data) {
  25688         return BCM_E_MEMORY;
  25689     }
  25690     
  25691     encap_data = _bcm_sb2_oam_olp_l2_header_decap(unit, encap_data, &olp_l2_header);
  25692 
  25693     rv = _bcm_sb2_oam_olp_tx_header_decap(unit,
  25694                                         encap_data,
  25695                                         counter_size,
  25696                                         counter_base_id,
  25697                                         counter_offset,
  25698                                         counter_action,
  25699                                         counter_lm_counter_byte_offset,
  25700                                         ts_mode,
  25701                                         lm_pdu_counter_offset,
  25702                                         int_pri);
  25703     if(rv != BCM_E_NONE) {
  25704         return rv;
  25705     }
  25706 
  25707     return BCM_E_NONE;
  25708 }
  25709 
  25710 
  25711 /*
  25712  * Function:
  25713  *      _bcm_sb2_bhh_oam_olp_tx_header_create
  25714  * Purpose:
  25715  *      Adds OLP Tx header packet to encapsulation.
  25716  * Parameters:
  25717  *      unit            - (IN) Unit number.
  25718  *      mod             - (IN) module Id.
  25719  *      port_id         - (IN) port Id.
  25720  *      ts_mode         - (IN) Timestamp type for DM PDU.
  25721  *      lm_pdu_counter_offset - (IN) Counter offset in LM PDU.
  25722  *      encap_data      - (OUT) Buffer returning MPLS OAM encapsulation.
  25723  *      encap_length    - (OUT) Buffer length which contains 
  25724  *                              MPLS OAM encapsulation length.
  25725  *      int_pri         - (IN) INT_PRI of OAM message.
  25726  * Returns:
  25727  *      BCM_E_XXX
  25728  * Notes:
  25729  *      The returning MPLS OAM encapsulation buffer includes 
  25730  *      OLP TX header.
  25731  */
  25732 
  25733 STATIC int
  25734 _bcm_sb2_bhh_oam_olp_tx_header_create(int unit,
  25735                                  bcm_module_t mod, bcm_port_t port_id,
  25736                                  uint8 counter_size,
  25737                                  uint32  *counter_base_id,
  25738                                  uint32  *counter_offset,
  25739                                  int     *counter_action,
  25740                                  uint32  *counter_byte_offset,
  25741                                  uint8   ts_mode,
  25742                                  uint8 lm_pdu_counter_offset,
  25743                                  uint8  *encap_data,
  25744                                  uint16 *encap_length,
  25745                                  bcm_cos_t int_pri)
  25746 {
  25747     int rv = 0, i;
  25748     soc_olp_l2_hdr_t olp_l2_header;
  25749     soc_olp_tx_hdr_t olp_oam_header;
  25750     uint8 *buffer_p = encap_data;
  25751     int my_mod_id = 0;
  25752     int cpu_dglp = 0; 
  25753     int cpu_port = 0;
  25754     uint8 ctr_pool = 0;
  25755 
  25756     sal_memset(&olp_l2_header, 0, sizeof(olp_l2_header));
  25757 
  25758     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id));
  25759     cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port);
  25760     /* Get OLP L2 Header for CPU port */
  25761     rv = _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header);
  25762     if (BCM_FAILURE(rv)) {
  25763         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  25764                         "OLP Header get failed.\n")));
  25765         return (rv);
  25766     }
  25767 
  25768     buffer_p = _bcm_sb2_oam_olp_l2_header_pack(buffer_p, &olp_l2_header);
  25769 
  25770     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
  25771     /* Set Port number */
  25772     SOC_OLP_TX_PORT(&olp_oam_header) = port_id;
  25773     SOC_OLP_TX_MODID(&olp_oam_header) = mod;
  25774     SOC_OLP_TX_PRI(&olp_oam_header) = int_pri;
  25775 
  25776     for (i=0; i< counter_size; i++) {
  25777 
  25778         ctr_pool =  (counter_base_id[i] & 0xFF000000) >> 24;
  25779         if (ctr_pool == 0) {
  25780             SOC_OLP_TX_CTR1_ID(&olp_oam_header) =
  25781                 (counter_base_id[i] & 0x00FFFFFF) + 
  25782                 counter_offset[i]; 
  25783                 
  25784             SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) =
  25785                                        counter_action[i];
  25786             /* Counter location is Egress */
  25787             SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1;
  25788         }
  25789         if (ctr_pool == 1) {
  25790             SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header,
  25791                 (counter_base_id[i] & 0x00FFFFFF) + 
  25792                 counter_offset[i] 
  25793                 );
  25794             SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) =
  25795                                        counter_action[i];
  25796             SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1;
  25797         }
  25798         if (ctr_pool == 2) {
  25799             SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header,
  25800                 (counter_base_id[i] & 0x00FFFFFF) + 
  25801                 counter_offset[i] 
  25802                );
  25803             SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) =
  25804                                        counter_action[i];
  25805             SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1;
  25806         }
  25807     }
  25808     if(lm_pdu_counter_offset){
  25809         /* COUNTER OFFSET in OLP Header =
  25810          * (L2 Encap + Counter field offset in MPLS OAM Header - 14)/2 
  25811          */
  25812         SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) =
  25813             (lm_pdu_counter_offset - 14) >> 1;
  25814     }
  25815 
  25816     SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = ts_mode;
  25817 
  25818     /* Pack OLP OAM Encap */
  25819     buffer_p = shr_olp_tx_header_pack(buffer_p, &olp_oam_header);
  25820     *encap_length += (buffer_p - encap_data);
  25821 
  25822     return rv;
  25823 }
  25824 #endif /* INCLUDE_ETH_LM_DM || INCLUDE_MPLS_LM_DM || INCLUDE_BHH*/
  25825 
  25826 #if defined(INCLUDE_BHH)
  25827 /*
  25828  * Function:
  25829  *      _bcm_sb2_oam_bhh_encap_build_pack
  25830  * Purpose:
  25831  *      Builds and packs the BHH packet encapsulation for a given
  25832  *      BHH tunnel type.
  25833  * Parameters:
  25834  *      unit            - (IN) Unit number.
  25835  *      port            - (IN) Port.
  25836  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  25837  *      packet_flags    - (IN) Flags for building packet.
  25838  *      buffer          - (OUT) Buffer returning BHH encapsulation.
  25839  * Returns:
  25840  *      BCM_E_XXX
  25841  * Notes:
  25842  *      The returning BHH encapsulation includes only all the
  25843  *      encapsulation headers/labels and does not include
  25844  *      the BHH control packet.
  25845  */
  25846 STATIC int
  25847 _bcm_sb2_oam_bhh_encap_build_pack(int unit, bcm_module_t mod, bcm_port_t port,
  25848                                   _bcm_oam_hash_data_t *h_data_p,
  25849                                   uint32 packet_flags, uint8 *buffer,
  25850                                   uint16 *encap_length,
  25851                                   _bhh_oam_lm_dm_info_t *counter_info,
  25852                                   bcm_cos_t  int_pri, uint8 oam_exp,
  25853                                   uint8 oam_ttl)
  25854 {
  25855     uint8          *cur_ptr = buffer;
  25856     uint16         etype = 0;
  25857     bcm_if_t       l3_intf_id = -1;
  25858     _ach_header_t  ach;
  25859     _mpls_label_t  mpls_gal;
  25860     _mpls_label_t  mpls_labels[_BHH_MPLS_MAX_LABELS];
  25861     int            mpls_count = 0;
  25862     _l2_header_t   l2;
  25863     int i;
  25864 
  25865 
  25866     /*
  25867      * Get necessary headers/labels information.
  25868      *
  25869      * Following order is important since some headers/labels
  25870      * may depend on previous header/label information.
  25871      */
  25872     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  25873         BCM_IF_ERROR_RETURN
  25874             (_bcm_sb2_oam_bhh_ach_header_get(packet_flags, &ach));
  25875         counter_info->oam_replacement_offset += 4;
  25876     }
  25877 
  25878     if (packet_flags & _BHH_ENCAP_PKT_GAL) {
  25879         if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) {
  25880             BCM_IF_ERROR_RETURN
  25881                 (_bcm_sb2_oam_bhh_mpls_gal_label_get(&mpls_gal, oam_exp));
  25882         } else {
  25883             BCM_IF_ERROR_RETURN
  25884                 (_bcm_sb2_oam_bhh_mpls_gal_label_get(&mpls_gal, 0));
  25885         }
  25886         counter_info->oam_replacement_offset += 4;
  25887     }
  25888 
  25889     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  25890         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
  25891         BCM_IF_ERROR_RETURN
  25892             (_bcm_sb2_oam_bhh_mpls_labels_get(unit, h_data_p, packet_flags,
  25893                                               _BHH_MPLS_MAX_LABELS, mpls_labels,
  25894                                               &mpls_count, &l3_intf_id,
  25895                                               oam_exp, oam_ttl));
  25896         counter_info->oam_replacement_offset += (mpls_count *4);
  25897     }
  25898 
  25899     /* Always build L2 Header */
  25900     BCM_IF_ERROR_RETURN
  25901         (_bcm_sb2_oam_bhh_l2_header_get(unit, 
  25902                                        h_data_p,
  25903                                        port, 
  25904                                        etype, 
  25905                                        &l2,
  25906                                        &counter_info->oam_replacement_offset));
  25907     /*
  25908      * Pack header/labels into given buffer (network packet format).
  25909      *
  25910      * Following packing order must be followed to correctly
  25911      * build the packet encapsulation.
  25912      */
  25913     cur_ptr = buffer;
  25914 
  25915     if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 
  25916         _bcm_sb2_bhh_oam_olp_tx_header_create(unit, mod, port,
  25917                 counter_info->counter_size,
  25918                 counter_info->counter_base_id,
  25919                 counter_info->counter_offset,
  25920                 counter_info->counter_action,
  25921                 counter_info->byte_count_offset,
  25922                 counter_info->ts_mode, 
  25923                 counter_info->oam_replacement_offset,
  25924                 buffer,
  25925                 encap_length, int_pri);
  25926 
  25927         cur_ptr = buffer + *encap_length;
  25928     }
  25929 
  25930     /* L2 Header is always present */
  25931     cur_ptr = _bcm_sb2_oam_bhh_l2_header_pack(h_data_p->type, cur_ptr, &l2);
  25932 
  25933     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  25934         for (i = 0;i < mpls_count;i++) {
  25935             cur_ptr = _bcm_sb2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]);
  25936         }
  25937     }
  25938 
  25939     if (packet_flags & _BHH_ENCAP_PKT_GAL) {    
  25940         cur_ptr = _bcm_sb2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal);
  25941     }
  25942 
  25943     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  25944         cur_ptr = _bcm_sb2_oam_bhh_ach_header_pack(cur_ptr, &ach);
  25945     }
  25946 
  25947 
  25948     /* Set BHH encapsulation length */
  25949     *encap_length = cur_ptr - buffer;
  25950 
  25951     return (BCM_E_NONE);
  25952 }
  25953 
  25954 #endif /* (INCLUDE_BHH) */
  25955 
  25956 #if defined(INCLUDE_ETH_LM_DM)
  25957 /*
  25958  * Function:
  25959  *      _bcm_sb2_oam_eth_l2_encap_build_pack
  25960  * Purpose:
  25961  *      Builds and packs the ETH L2 packet encapsulation for a given
  25962  *      LM/DM PACKET.
  25963  * Parameters:
  25964  *      unit            - (IN) Unit number.
  25965  *      port            - (IN) Port.
  25966  *      h_data_p        - (IN/OUT) Pointer to hash_data structure.
  25967  *      buffer          - (OUT) Buffer returning ETH L2 encapsulation.
  25968  *      buffer_len      - (OUT) Length of ETH L2 encapsulation formed.
  25969  * Returns:
  25970  *      BCM_E_XXX
  25971  * Notes:
  25972  *      The returning ETH L2 encapsulation includes only all the
  25973  *      encapsulation headers and does not include
  25974  *      the ETH_LM_DM control packet.
  25975  */
  25976 STATIC int
  25977 _bcm_sb2_oam_eth_l2_encap_build_pack(int unit, bcm_port_t port,
  25978                              _bcm_oam_hash_data_t *h_data_p,
  25979                              uint8 *buffer,
  25980                              uint32 *encap_length,
  25981                              uint8  pkt_pri)
  25982 {
  25983     uint8          *cur_ptr = buffer;
  25984     uint16         etype = 0;
  25985     _eth_l2_header_t   l2;
  25986 
  25987     etype = SHR_ETH_LM_DM_L2_ETYPE_OAM;
  25988 
  25989 
  25990     /* Always build L2 Header */
  25991     BCM_IF_ERROR_RETURN
  25992         (_bcm_sb2_oam_eth_l2_header_get(unit, 
  25993                                        h_data_p,
  25994                                        port, 
  25995                                        etype, 
  25996                                        &l2,
  25997                                        pkt_pri));
  25998 
  25999     /*
  26000      * Pack header into given buffer (network packet format).
  26001      *
  26002      * Following packing order must be followed to correctly
  26003      * build the packet encapsulation.
  26004      */
  26005     cur_ptr = buffer;
  26006 
  26007     /* L2 Header is always present */
  26008     cur_ptr = _bcm_sb2_oam_eth_l2_header_pack(cur_ptr, &l2);
  26009 
  26010     /* Set  ETH-L2 encapsulation length */
  26011     *encap_length = cur_ptr - buffer;
  26012 
  26013     return (BCM_E_NONE);
  26014 }
  26015 
  26016 /*
  26017  * Function:
  26018  *      _bcm_sb2_oam_olp_l2_encap_build_pack
  26019  * Purpose:
  26020  *      Builds and packs the OLP L2 packet encapsulation for a given
  26021  *      ETH_LM_DM control packet.
  26022  * Parameters:
  26023  *      unit            - (IN) Unit number.
  26024  *      cpu_dglp        - (IN) DGLP Port for the olp.
  26025  *      buffer          - (OUT) Buffer returning OLP L2 encapsulation.
  26026  *      encap_len       - (OUT) Pointer to length of OLP L2 encapsulation.
  26027  * Returns:
  26028  *      BCM_E_XXX
  26029  * Notes:
  26030  *      The returning OLP L2 encapsulation includes only OLP L2 header
  26031  *      for the ETH_LM_DM control packet
  26032  */
  26033 STATIC int
  26034 _bcm_sb2_oam_olp_l2_encap_build_pack(int unit,
  26035                              int cpu_dglp, 
  26036                              uint8 *buffer,
  26037                              uint32 *encap_length)
  26038 {
  26039     uint8          *cur_ptr = buffer;
  26040     _olp_l2_header_t   l2;
  26041 
  26042 
  26043     /* Build OLP L2 Header */
  26044     BCM_IF_ERROR_RETURN
  26045         (_bcm_sb2_oam_olp_l2_header_get(unit,
  26046                                         cpu_dglp, 
  26047                                         &l2));
  26048 
  26049     /*
  26050      * Pack header into given buffer (network packet format).
  26051      *
  26052      * Following packing order must be followed to correctly
  26053      * build the packet encapsulation.
  26054      */
  26055     cur_ptr = buffer;
  26056 
  26057     /* L2 Header is always present */
  26058     cur_ptr = _bcm_sb2_oam_olp_l2_header_pack(cur_ptr, &l2);
  26059 
  26060     /* Set OLP L2 encapsulation length */
  26061     *encap_length = cur_ptr - buffer;
  26062 
  26063     return (BCM_E_NONE);
  26064 }
  26065 #endif /*(INCLUDE_ETH_LM_DM) */
  26066 
  26067 #if defined(INCLUDE_BHH)
  26068 STATIC void
  26069 _bcm_sb2_oam_bhh_get_egress_label_from_encap(_bcm_oam_hash_data_t *h_data_p,
  26070                                              uint8 *encap_data,
  26071                                              uint16 encap_length,
  26072                                              _mpls_label_t *label)
  26073 {
  26074     uint16        oam_label_offset = 0;
  26075 
  26076     if(!encap_length) {
  26077         LOG_CLI((BSL_META("\nEncapsulation (length=%d):\n"), encap_length));
  26078         return;
  26079     }
  26080 
  26081     if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
  26082         /* Go back ACH and GAL */
  26083         oam_label_offset = encap_length -
  26084                            (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH);
  26085     } else if (BHH_EP_LSP_TYPE(h_data_p)) {
  26086         /* Go back ACH + GAL + OAM label */
  26087         oam_label_offset = encap_length -
  26088                           (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2));
  26089     } else { /* PW */
  26090         if (h_data_p->vccv_type == bcmOamBhhVccvGal13) {
  26091             /* Go back ACH + GAL + PW label */
  26092             oam_label_offset = encap_length -
  26093                           (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2));
  26094         } else {
  26095             /* Go back ACH and PW label */
  26096             oam_label_offset = encap_length -
  26097                                (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH);
  26098         }
  26099     }
  26100 
  26101     _bcm_sb2_oam_bhh_mpls_label_unpack(&(encap_data[oam_label_offset]), label);
  26102 }
  26103 
  26104 /*
  26105  * Function:
  26106  *      _bcm_sb2_oam_bhh_encap_create
  26107  * Purpose:
  26108  *      Creates a BHH packet encapsulation.
  26109  * Parameters:
  26110  *      unit            - (IN) Unit number.
  26111  *      port_id         - (IN) Port.
  26112  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  26113  *      encap_data      - (OUT) Buffer returning BHH encapsulation.
  26114  * Returns:
  26115  *      BCM_E_XXX
  26116  * Notes:
  26117  *      The returning BHH encapsulation buffer includes all the
  26118  *      corresponding headers/labels EXCEPT for the BHH control packet.
  26119  */
  26120 STATIC int
  26121 _bcm_sb2_oam_bhh_encap_create(int unit, bcm_module_t mod, bcm_port_t port_id,
  26122                               _bcm_oam_hash_data_t *h_data_p, uint8 *encap_data,
  26123                               uint8  *encap_type, uint16 *encap_length,
  26124                               _bhh_oam_lm_dm_info_t *counter_info,
  26125                               bcm_cos_t int_pri, uint8 oam_exp, uint8 oam_ttl)
  26126 {
  26127     uint32 packet_flags;
  26128     _bcm_oam_control_t *oc;
  26129 
  26130     /* Get device OAM control structure handle. */
  26131     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  26132 
  26133 
  26134     packet_flags = 0;
  26135 
  26136     /*
  26137      * Get BHH encapsulation packet format flags
  26138      *
  26139      * Also, perform the following for each BHH tunnel type:
  26140      * - Check for valid parameter values
  26141      * - Set specific values required by the BHH tunnel definition 
  26142      *   (e.g. such as ttl=1,...)
  26143      */
  26144     switch (h_data_p->type) {
  26145     case bcmOAMEndpointTypeBHHMPLS:
  26146         packet_flags |=
  26147             (_BHH_ENCAP_PKT_MPLS |
  26148              _BHH_ENCAP_PKT_GAL |
  26149              _BHH_ENCAP_PKT_G_ACH);
  26150         break;
  26151 
  26152     case bcmOAMEndpointTypeBHHMPLSVccv:
  26153         switch(h_data_p->vccv_type) {
  26154 
  26155         case bcmOamBhhVccvChannelAch:
  26156             packet_flags |=
  26157                 (_BHH_ENCAP_PKT_MPLS |
  26158                  _BHH_ENCAP_PKT_PW |
  26159                  _BHH_ENCAP_PKT_G_ACH);
  26160         break;
  26161 
  26162         case bcmOamBhhVccvRouterAlert:
  26163             packet_flags |=
  26164                 (_BHH_ENCAP_PKT_MPLS |
  26165                  _BHH_ENCAP_PKT_PW |
  26166                  _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT |
  26167                  _BHH_ENCAP_PKT_G_ACH); 
  26168             break;
  26169 
  26170         case bcmOamBhhVccvTtl:
  26171             packet_flags |=
  26172                 (_BHH_ENCAP_PKT_MPLS |
  26173                  _BHH_ENCAP_PKT_PW |
  26174                  _BHH_ENCAP_PKT_G_ACH); 
  26175             break;
  26176 
  26177     case bcmOamBhhVccvGal13:
  26178             packet_flags |=
  26179                 (_BHH_ENCAP_PKT_MPLS |
  26180                  _BHH_ENCAP_PKT_PW |
  26181                  _BHH_ENCAP_PKT_GAL  |
  26182                  _BHH_ENCAP_PKT_G_ACH);
  26183             break;
  26184 
  26185     default:
  26186         return (BCM_E_PARAM);
  26187         break;
  26188     }
  26189         break;
  26190 
  26191     case bcmOAMEndpointTypeBhhSection:
  26192     case bcmOAMEndpointTypeBhhSectionInnervlan:
  26193     case bcmOAMEndpointTypeBhhSectionOuterVlan:
  26194     case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
  26195         packet_flags |=
  26196             (_BHH_ENCAP_PKT_GAL |
  26197              _BHH_ENCAP_PKT_G_ACH);
  26198         break;
  26199     default:
  26200         return (BCM_E_PARAM);
  26201     }
  26202 
  26203     /* Build header/labels and pack in buffer */
  26204     BCM_IF_ERROR_RETURN
  26205         (_bcm_sb2_oam_bhh_encap_build_pack(unit, mod, port_id, h_data_p,
  26206                                            packet_flags, encap_data,
  26207                                            encap_length, counter_info, int_pri,
  26208                                            oam_exp, oam_ttl));
  26209 
  26210     /* Set encap type (indicates uC side that checksum is required) */
  26211     *encap_type = SHR_BHH_ENCAP_TYPE_RAW;
  26212 
  26213 #ifdef _BHH_DEBUG_DUMP
  26214     _bcm_sb2_oam_bhh_encap_data_dump(encap_data, *encap_length);
  26215 #endif
  26216 
  26217     if (*encap_length > oc->bhh_max_encap_length) {
  26218         LOG_ERROR(BSL_LS_BCM_OAM,
  26219                 (BSL_META_U(unit,
  26220                 "OAM(unit %d) Error: Encap length greater than max,"
  26221                 "encap_length=%u max=%u\n"),
  26222                  unit, *encap_length, oc->bhh_max_encap_length));
  26223         return BCM_E_CONFIG;
  26224     }
  26225 
  26226     return (BCM_E_NONE);
  26227 }
  26228 
  26229 #endif /* (INCLUDE_BHH) */
  26230 
  26231 #if defined(INCLUDE_ETH_LM_DM)
  26232 /*
  26233  * Function:
  26234  *      _bcm_sb2_oam_eth_encap_create
  26235  * Purpose:
  26236  *      Creates a ETH_LM/DM packet encapsulation.
  26237  * Parameters:
  26238  *      unit            - (IN) Unit number.
  26239  *      port_id         - (IN) Port.
  26240  *      encap_data      - (OUT) Buffer returning BHH encapsulation.
  26241  * Returns:
  26242  *      BCM_E_XXX
  26243  * Notes:
  26244  *      The returning ETH and OLP L2 encapsulation buffer includes all the
  26245  *      corresponding headers ETH_LM_DM control packet.
  26246  */
  26247 STATIC int
  26248 _bcm_sb2_oam_eth_olp_encap_create(int unit, bcm_port_t port_id,
  26249         int dglp,
  26250         _bcm_oam_hash_data_t *h_data_p,
  26251         uint8 *encap_data,
  26252         uint32	*eth_l2_encap_length,
  26253         uint32 *olp_l2_encap_length,
  26254         uint8  pkt_pri)
  26255 {
  26256 
  26257     uint8 *eth_l2_encap;
  26258     /*
  26259      * Get ETH ans OLP L2 encapsulation header and put them
  26260      * into the buffer contiguously though while copying in
  26261      * Tx packet they will be copied seperately to contain
  26262      * OLP Tx header
  26263      */   
  26264 
  26265     /* Build OLP L2 header and pack in buffer */
  26266     BCM_IF_ERROR_RETURN
  26267         (_bcm_sb2_oam_olp_l2_encap_build_pack(unit,
  26268                                       dglp,  
  26269                                       encap_data,
  26270                                       olp_l2_encap_length));
  26271 
  26272     eth_l2_encap = encap_data + *olp_l2_encap_length;
  26273 
  26274     /* Build ETH L2 header and pack in buffer */
  26275     BCM_IF_ERROR_RETURN
  26276         (_bcm_sb2_oam_eth_l2_encap_build_pack(unit, port_id,
  26277                                       h_data_p, 
  26278                                       eth_l2_encap,
  26279                                       eth_l2_encap_length,
  26280                                       pkt_pri));
  26281 
  26282      h_data_p->eth_l2_encap_length = *eth_l2_encap_length;
  26283 #ifdef _ETH_LM_DM_DEBUG_DUMP
  26284     _bcm_sb2_oam_eth_l2_encap_data_dump(encap_data, *eth_l2_encap_length);
  26285     _bcm_sb2_oam_olp_l2_encap_data_dump(olp_l2_encap, *olp_l2_encap_length);
  26286 #endif
  26287 
  26288     return (BCM_E_NONE);
  26289 }
  26290 /*
  26291  * Function:
  26292  *     _bcm_sb2_oam_loss_olp_tx_encap_create 
  26293  * Purpose:
  26294  *      Creates a OLP Tx header for LM control packet.
  26295  * Parameters:
  26296  *      unit            - (IN) Unit number.
  26297  *      h_data_p        - (IN) Pointer to hash data structure
  26298  *      olp_encap_data  - (OUT) Pointer to OLP Tx header
  26299  *      olp_encap_length- (OUT) Pointer to length of OLP Tx header
  26300  *      loss_p          - pointer to provided loss structure
  26301  *      port_id         - (IN) Port.
  26302  *      module_id       - (IN) Module id
  26303  *      mep_type        - (IN) MEP type - down or up.
  26304  * Returns:
  26305  *      BCM_E_XXX
  26306  * Notes:
  26307  *      The returning OLP Tx header has all the fields required for LM
  26308  *      packet.
  26309  */
  26310 STATIC int
  26311 _bcm_sb2_oam_loss_olp_tx_encap_create(int unit, 
  26312                          _bcm_oam_hash_data_t *h_data_p,
  26313                          uint8	*olp_encap_data,
  26314                          uint32 *olp_encap_length,
  26315                          bcm_oam_loss_t *loss_p,
  26316                          bcm_port_t port_id,
  26317                          bcm_module_t  module_id,
  26318                          uint8  mep_type)
  26319 {
  26320     olp_tx_hdr_t olp_tx_hdr;
  26321     uint8 *data_temp;
  26322     uint32 counter_pool = 0; 
  26323     int i;    
  26324     data_temp = olp_encap_data;
  26325 
  26326     memset(&olp_tx_hdr, 0, sizeof(olp_tx_hdr_t));
  26327     /* OLP Tx header int_pri field is of 4-bits*/
  26328     SOC_OLP_TX_PRI(&olp_tx_hdr) = (loss_p->int_pri & 0xf); 
  26329     SOC_OLP_TX_HDR_STYPE(&olp_tx_hdr) = mep_type; /* D-MEP = 0, U-MEp =1*/
  26330     SOC_OLP_TX_PORT(&olp_tx_hdr) = (uint16)((port_id & 0xff) | ((module_id & 0xff)<<8));
  26331     
  26332     if (!(loss_p->flags & BCM_OAM_LOSS_SLM)) { 
  26333         /*
  26334          * SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26335          * SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = h_data_p->tx_ctr;
  26336          * SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 2;                 
  26337          */
  26338 
  26339         /* Set Counter indexes */
  26340         for (i=0; i< loss_p->lm_counter_size; i++) {
  26341 
  26342             /* Counter pool index is 8 bit MSB of 24 bit counter base index */
  26343             counter_pool = (loss_p->lm_counter_base_id[i] & 0xFF000000) >> 24; 
  26344 
  26345             if (counter_pool == 0) {
  26346                 SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = 
  26347                     (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 
  26348                     loss_p->lm_counter_offset[i];
  26349 
  26350                 SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 
  26351                     loss_p->lm_counter_action[i];
  26352 
  26353                 /* D-MEP(IP) = 0, U-MEP(EP) =1*/
  26354                 SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26355             } 
  26356 
  26357             if (counter_pool == 1) {
  26358                 SOC_OLP_TX_CTR2_ID_SET(&olp_tx_hdr,
  26359                         (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 
  26360                         loss_p->lm_counter_offset[i]); 
  26361 
  26362                 SOC_OLP_TX_CTR2_ACTION(&olp_tx_hdr) = 
  26363                     loss_p->lm_counter_action[i];
  26364 
  26365                 SOC_OLP_TX_CTR2_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26366             }
  26367 
  26368             if (counter_pool == 2) {
  26369                 SOC_OLP_TX_CTR3_ID_SET(&olp_tx_hdr, 
  26370                         (loss_p->lm_counter_base_id[i] & 0x00FFFFFFFF) +
  26371                         loss_p->lm_counter_offset[i]);
  26372 
  26373                 SOC_OLP_TX_CTR3_ACTION(&olp_tx_hdr) = 
  26374                     loss_p->lm_counter_action[i];
  26375 
  26376                 SOC_OLP_TX_CTR3_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26377             }
  26378         }
  26379 
  26380         SOC_OLP_TX_OAM_OFFSET(&olp_tx_hdr) = (h_data_p->eth_l2_encap_length +
  26381                 sizeof(shr_eth_lm_dm_header_t) - ETH_LM_DM_RPL_OFFSET_START) >> 
  26382             ETH_LM_DM_RPL_OFFSET_DIVIDER_BY_SHIFT;   
  26383 
  26384     }    
  26385 
  26386     /* Pack the OLP Tx header into the Tx buffer*/
  26387     data_temp = shr_olp_tx_header_pack(data_temp, &olp_tx_hdr);
  26388 
  26389     /* Get the size of OLP Tx buffer*/
  26390     *olp_encap_length = data_temp - olp_encap_data;
  26391 
  26392     /* Check the length of created OLP Tx header */
  26393     if(*olp_encap_length != SHR_ETH_LM_DM_OLP_TX_HDR_LENGTH) {
  26394         return (BCM_E_PARAM);
  26395     }
  26396 
  26397 #ifdef _ETH_LM_DM_DEBUG_DUMP
  26398     _bcm_sb2_oam_olp_tx_encap_data_dump(olp_encap_data, *olp_encap_length);
  26399 #endif
  26400 
  26401     return (BCM_E_NONE);
  26402 }
  26403 
  26404 /*
  26405  * Function:
  26406  *     _bcm_sb2_oam_delay_olp_tx_encap_create 
  26407  * Purpose:
  26408  *      Creates a OLP Tx header for DM packet.
  26409  * Parameters:
  26410  *      unit            - (IN) Unit number.
  26411  *      h_data_p        - (IN) Pointer to hash data structure
  26412  *      olp_encap_data  - (OUT) Pointer to OLP Tx header
  26413  *      olp_encap_length- (OUT) Pointer to length of OLP Tx header
  26414  *      delay_p         - (IN) Pointer to provided delay structure
  26415  *      port_id         - (IN) Port.
  26416  *      module_id       - (IN) Module id
  26417  *      mep_type        - (IN) MEP type - down or up.
  26418  *      dm_format       - (IN) DM format - PTP or NTP.
  26419  * Returns:
  26420  *      BCM_E_XXX
  26421  * Notes:
  26422  *      The returning OLP Tx header has all the fields required for DM
  26423  *      packet.
  26424  */
  26425 STATIC int
  26426 _bcm_sb2_oam_delay_olp_tx_encap_create(int unit, 
  26427                          _bcm_oam_hash_data_t *h_data_p,
  26428                          uint8	*olp_encap_data,
  26429                          uint32 *olp_encap_length,
  26430                          bcm_oam_delay_t *delay_p,
  26431                          bcm_port_t port_id,
  26432                          bcm_module_t  module_id,
  26433                         uint8  mep_type,
  26434                          uint8  dm_format)
  26435 {
  26436     olp_tx_hdr_t olp_tx_hdr;
  26437     uint8 *data_temp;
  26438     uint32 counter_pool = 0; 
  26439     int i; 
  26440     data_temp = olp_encap_data;
  26441 
  26442     memset(&olp_tx_hdr, 0, sizeof(olp_tx_hdr_t));
  26443 
  26444     /* OLP Tx header int_pri field is of 4-bits*/
  26445     SOC_OLP_TX_PRI(&olp_tx_hdr) = (delay_p->int_pri & 0xf);
  26446 
  26447     SOC_OLP_TX_HDR_STYPE(&olp_tx_hdr) = mep_type; /* D-MEP = 0, U-MEp =1*/
  26448     SOC_OLP_TX_PORT(&olp_tx_hdr) = (uint16)((port_id & 0xff) | ((module_id & 0xff)<<8));
  26449 
  26450     /* Set Counter indexes */
  26451     for (i=0; i< delay_p->dm_tx_update_lm_counter_size; i++) {
  26452 
  26453         /* Counter pool index is 8 bit MSB of 24 bit counter base index */
  26454         counter_pool = (delay_p->dm_tx_update_lm_counter_base_id[i] & 0xFF000000) >> 24; 
  26455 
  26456         if (counter_pool == 0) {
  26457             SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = 
  26458                 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 
  26459                 delay_p->dm_tx_update_lm_counter_offset[i]; 
  26460 
  26461             SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 
  26462                 bcmOamCounterActionIncrement;
  26463             /* Counter location is Egress(1) for DownMEP(0) 
  26464              * and Ingress(0) for Up-MEP(1). */
  26465             SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type;
  26466         } 
  26467 
  26468         if (counter_pool == 1) {
  26469             SOC_OLP_TX_CTR2_ID_SET(&olp_tx_hdr,
  26470                     (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 
  26471                     delay_p->dm_tx_update_lm_counter_offset[i]); 
  26472 
  26473             SOC_OLP_TX_CTR2_ACTION(&olp_tx_hdr) = 
  26474                 bcmOamCounterActionIncrement;
  26475             SOC_OLP_TX_CTR2_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26476         }
  26477 
  26478         if (counter_pool == 2) {
  26479             SOC_OLP_TX_CTR3_ID_SET(&olp_tx_hdr, 
  26480                     (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFFFF) +
  26481                     delay_p->dm_tx_update_lm_counter_offset[i]);
  26482 
  26483             SOC_OLP_TX_CTR3_ACTION(&olp_tx_hdr) = 
  26484                 bcmOamCounterActionIncrement;
  26485             SOC_OLP_TX_CTR3_LOCATION(&olp_tx_hdr) = ~mep_type; 
  26486         }
  26487     }
  26488     
  26489     SOC_OLP_TX_OAM_OFFSET(&olp_tx_hdr) = (h_data_p->eth_l2_encap_length +
  26490         sizeof(shr_eth_lm_dm_header_t) -
  26491         ETH_LM_DM_RPL_OFFSET_START) >> ETH_LM_DM_RPL_OFFSET_DIVIDER_BY_SHIFT;   
  26492     
  26493     SOC_OLP_TX_TIMESTAMP_ACTION(&olp_tx_hdr) = dm_format;
  26494 
  26495     /* Pack the OLP Tx header into the Tx buffer*/
  26496     data_temp = shr_olp_tx_header_pack(data_temp, &olp_tx_hdr);
  26497 
  26498     /* Get the size of OLP Tx buffer*/
  26499     *olp_encap_length = data_temp - olp_encap_data;
  26500 
  26501     /* Check the length of created OLP Tx header */
  26502     if(*olp_encap_length != SHR_ETH_LM_DM_OLP_TX_HDR_LENGTH) {
  26503         return (BCM_E_PARAM);
  26504     }
  26505 
  26506 #ifdef _ETH_LM_DM_DEBUG_DUMP
  26507     _bcm_sb2_oam_olp_tx_encap_data_dump(olp_encap_data, *olp_encap_length);
  26508 #endif
  26509 
  26510     return (BCM_E_NONE);
  26511 }
  26512 #endif /* (INCLUDE_ETH_LM_DM) */
  26513 
  26514 #if defined(INCLUDE_BHH)
  26515 
  26516 /*
  26517  * Function:
  26518  *      bcm_sb2_oam_bhh_endpoint_ccm_ctr_update
  26519  * Purpose:
  26520  *      Update CCM CTR params
  26521  * Parameters:
  26522  *      unit - (IN) Unit number.
  26523  * Returns:
  26524  *      BCM_E_XXX
  26525  * Notes:
  26526  */
  26527 STATIC int
  26528 bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(int unit,
  26529                                         bcm_oam_endpoint_info_t *ep_info)
  26530 {
  26531     _bcm_oam_hash_data_t         *h_data_p;
  26532     _bcm_oam_control_t           *oc;
  26533     _bhh_oam_lm_dm_info_t         counter_info;
  26534     bhh_sdk_msg_session_update_t  msg;
  26535     uint8                         encap_type;
  26536     uint8                        *buffer, *buffer_ptr;
  26537     uint16                        buffer_len, reply_len;
  26538     bcm_module_t                  module_id;         /* Module ID                    */
  26539     bcm_port_t                    port_id;
  26540     bcm_trunk_t                   trunk_id;
  26541     int                           local_id;
  26542     int                           i;
  26543     int                           rv = BCM_E_NONE;
  26544     uint32                        msg_flags = 0;
  26545     uint8                         proactive_lm_enable = 0;
  26546 
  26547     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  26548     if (oc->ukernel_not_ready) {
  26549         return BCM_E_NONE;
  26550     }
  26551     if (!BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  26552         /* BTE does not support OLP */
  26553         return BCM_E_NONE;
  26554     }
  26555     if(ep_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  26556         return BCM_E_NONE;
  26557     }
  26558 
  26559     /* Validate endpoint index value. */
  26560     if((ep_info->id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) ||
  26561        (ep_info->id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)
  26562                          + oc->bhh_endpoint_count))) {
  26563         return (BCM_E_PARAM);
  26564     }
  26565 
  26566     h_data_p =  &oc->oam_hash_data[ep_info->id];
  26567     if (0 == h_data_p->in_use) {
  26568         return (BCM_E_NOT_FOUND);
  26569     }
  26570 
  26571     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, h_data_p->gport,
  26572                                                &module_id, &port_id, &trunk_id,
  26573                                                &local_id));
  26574 
  26575     sal_memset(&counter_info, 0, sizeof(counter_info));
  26576     counter_info.counter_size = ep_info->ccm_tx_update_lm_counter_size;
  26577     for (i = 0; i < ep_info->ccm_tx_update_lm_counter_size; i++) {
  26578         counter_info.counter_base_id[i] =
  26579                                    ep_info->ccm_tx_update_lm_counter_base_id[i];
  26580         counter_info.counter_offset[i] =
  26581                                     ep_info->ccm_tx_update_lm_counter_offset[i];
  26582         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
  26583         counter_info.byte_count_offset[i] = 0;
  26584         if (ep_info->ccm_tx_update_lm_counter_action[i] ==
  26585                 bcmOamCounterActionSample) {
  26586             if (SOC_IS_METROLITE (unit)) {
  26587                 if ((h_data_p->period == BCM_OAM_ENDPOINT_CCM_PERIOD_3MS) ||
  26588                     (h_data_p->period == BCM_OAM_ENDPOINT_CCM_PERIOD_10MS)) {
  26589                     LOG_ERROR(BSL_LS_BCM_OAM,
  26590                             (BSL_META_U(unit,
  26591                                         "BHH(unit %d)Error: Proactive LM is "
  26592                                         "not supported with CCM interval <100ms"
  26593                                         " (EP=%d)\n"), unit, ep_info->id));
  26594                     return (BCM_E_PARAM);
  26595                 }
  26596                 counter_info.counter_action[i] = bcmOamCounterActionSample;
  26597                 proactive_lm_enable = 1;
  26598             } else {
  26599                 LOG_ERROR(BSL_LS_BCM_OAM,
  26600                         (BSL_META_U(unit,
  26601                                     "BHH(unit %d)Error: Saber2 does not"
  26602                                     " support Proactive LM (EP=%d)\n"),
  26603                          unit, ep_info->id));
  26604                 return (BCM_E_PARAM);
  26605             }
  26606         }
  26607     }
  26608     if (proactive_lm_enable) {
  26609         msg_flags |= SHR_BHH_SESSION_UPDATE_PROACTIVE_LM_ENABLE;
  26610         h_data_p->int_flags |= _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM;
  26611     } else if ( h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) {
  26612         msg_flags |= SHR_BHH_SESSION_UPDATE_PROACTIVE_LM_DISABLE;
  26613         h_data_p->int_flags &= ~(_BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM);
  26614     }
  26615     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
  26616     counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU;
  26617 
  26618     sal_memset(&msg, 0, sizeof(msg));
  26619 
  26620     msg_flags |= SHR_BHH_SESSION_UPDATE_ENCAP;
  26621     msg.flags = msg_flags;
  26622     msg.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_info->id);
  26623     msg.msg_type = BHH_CCM_MSG;
  26624     rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
  26625                                        msg.encap_data, &encap_type,
  26626                                        &(msg.encap_length), &counter_info,
  26627                                        h_data_p->int_pri,
  26628                                        h_data_p->egr_label_exp,
  26629                                        h_data_p->egr_label_ttl);
  26630     if (BCM_FAILURE(rv)) {
  26631         return rv;
  26632     }
  26633 
  26634     /* Pack control message data into DMA buffer */
  26635     buffer     = oc->dma_buffer;
  26636     buffer_ptr = bhh_sdk_msg_ctrl_session_update_pack(buffer, &msg);
  26637     buffer_len = buffer_ptr - buffer;
  26638 
  26639 
  26640     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  26641                                            MOS_MSG_SUBCLASS_BHH_SESS_UPDATE,
  26642                                            buffer_len, 0,
  26643                                            MOS_MSG_SUBCLASS_BHH_SESS_UPDATE_REPLY,
  26644                                            &reply_len);
  26645     if (BCM_FAILURE(rv) || (reply_len != 0)) {
  26646         return (BCM_E_INTERNAL);
  26647     }
  26648     return BCM_E_NONE;
  26649 }
  26650 
  26651 /*
  26652  * Function:
  26653  *      _bcm_sb2_oam_bhh_appl_callback
  26654  * Purpose:
  26655  *      Update FW BHH appl state
  26656  * Parameters:
  26657  *      unit  - (IN) Unit number.
  26658  *      uC    - (IN) core number.
  26659  *      stage - (IN) core reset stage.
  26660  *      user_data - (IN) data pointer.
  26661  * Returns:
  26662  *      BCM_E_XXX
  26663  * Notes:
  26664  */
  26665 
  26666 int _bcm_sb2_oam_bhh_appl_callback(int unit,
  26667                                     int uC,
  26668                                     soc_cmic_uc_shutdown_stage_t stage,
  26669                                     void *user_data) {
  26670     _bcm_oam_control_t *oc;
  26671 
  26672     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  26673     _BCM_OAM_LOCK(oc);
  26674     oc->ukernel_not_ready = 1;
  26675 
  26676     _BCM_OAM_UNLOCK(oc);
  26677 
  26678     return BCM_E_NONE;
  26679 }
  26680 
  26681 /*
  26682  * Function:
  26683  *      bcm_sb2_oam_bhh_endpoint_create
  26684  * Purpose:
  26685  *      Initialize the HW for BHH packet processing.
  26686  *      Configure:
  26687  *      - Copy to CPU BHH error packets
  26688  *      - CPU COS Queue for BHH packets
  26689  *      - RX DMA channel
  26690  * Parameters:
  26691  *      unit - (IN) Unit number.
  26692  * Returns:
  26693  *      BCM_E_XXX
  26694  * Notes:
  26695  */
  26696 int
  26697 bcm_sb2_oam_bhh_endpoint_create(int unit, 
  26698                                 bcm_oam_endpoint_info_t *endpoint_info,
  26699                                 _bcm_oam_hash_key_t  *hash_key)
  26700 {
  26701     _bcm_oam_control_t *oc;
  26702     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
  26703     _bcm_oam_group_data_t *group_p;         /* Pointer to group data.       */
  26704     int                  ep_req_index;      /* Requested endpoint index.    */
  26705     int                  rv = BCM_E_NONE;   /* Operation return status.     */
  26706     int                  is_remote = 0;     /* Remote endpoint status.      */
  26707     int                  is_replace;
  26708     int                  is_local = 0;         
  26709     uint32               sglp = 0;          /* Source global logical port.  */
  26710     uint32               dglp = 0;          /* Dest global logical port.    */
  26711     bcm_module_t         module_id;         /* Module ID                    */
  26712     bcm_port_t           port_id;
  26713     bcm_trunk_t          trunk_id;
  26714     int                  local_id;
  26715     uint32               svp = 0;           /* Source virtual port          */
  26716     bcm_port_t           src_pp_port = 0;   /* Source pp port.              */
  26717     bcm_port_t           dst_pp_port = 0;   /* Dest pp port.                */
  26718     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
  26719     bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create;
  26720     uint8 *buffer, *buffer_ptr;
  26721     uint16 buffer_len, reply_len;
  26722     int encap = 0;
  26723     uint32 session_flags;
  26724     int bhh_pool_ep_idx = 0;
  26725     int is_vp_valid = 0;
  26726     bcm_trunk_member_t   trunk_member;
  26727     _bhh_oam_lm_dm_info_t counter_info;
  26728     int i = 0;
  26729     uint16 encap_length = 0;
  26730     uint8 group_sw_rdi = 0;
  26731 
  26732     LOG_DEBUG(BSL_LS_BCM_OAM,
  26733               (BSL_META_U(unit,
  26734                           "BHH(unit %d) Info: bcm_sb2_oam_bhh_endpoint_create"
  26735                            "Endpoint ID=%d.\n"), unit, endpoint_info->id));
  26736 
  26737     _BCM_OAM_BHH_IS_VALID(unit);
  26738 
  26739     /* Validate input parameter. */
  26740     if (NULL == endpoint_info) {
  26741         return (BCM_E_PARAM);
  26742     }
  26743 
  26744     /* Lock already taken by the calling routine. */
  26745     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  26746 
  26747 
  26748     /* Get MEP remote endpoint status. */
  26749     is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  26750 
  26751     is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0);
  26752 
  26753     /* Perform BHH specific validation checks */
  26754     /* BHH EP can only be at the MAX Level */
  26755     if ( endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) {
  26756         LOG_ERROR(BSL_LS_BCM_OAM,
  26757                   (BSL_META_U(unit,
  26758                               "OAM(unit %d) Error: EP Level should be equal to %d\n"),
  26759                    unit, _BCM_OAM_EP_LEVEL_MAX));
  26760         return (BCM_E_PARAM);
  26761     }
  26762 
  26763     /*Validate CCM period */
  26764     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_period_validate
  26765                         (endpoint_info->ccm_period));
  26766 
  26767     /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */
  26768     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  26769         if((endpoint_info->id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) ||
  26770            (endpoint_info->id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) 
  26771                                   + oc->bhh_endpoint_count))) {
  26772             return (BCM_E_PARAM);
  26773         }
  26774      }
  26775 
  26776     /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */
  26777     if (is_remote) {
  26778         if((endpoint_info->local_id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) ||
  26779            (endpoint_info->local_id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)
  26780                                         + oc->bhh_endpoint_count))) {
  26781             return (BCM_E_PARAM);
  26782         }
  26783     }
  26784 
  26785     /* Validate if the gport is an MPLS port for PW MEP */
  26786     if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  26787         if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(endpoint_info->gport)) {
  26788             return BCM_E_PARAM;
  26789         }
  26790     }
  26791 
  26792     if (is_replace) {
  26793         hash_data = &oc->oam_hash_data[endpoint_info->id];
  26794         if (!hash_data->in_use) {
  26795             return (BCM_E_NOT_FOUND);
  26796         }
  26797 
  26798         /* Delete original and recreate new EP */
  26799         rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint_info->id);
  26800         if (BCM_FAILURE(rv)) {
  26801             LOG_ERROR(BSL_LS_BCM_OAM,
  26802                       (BSL_META_U(unit,
  26803                                   "OAM(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"),
  26804                        unit, endpoint_info->id, bcm_errmsg(rv)));
  26805             return (rv);
  26806         }
  26807     }
  26808 
  26809     /*
  26810        BHH API have been using L3_EGRESS type in 
  26811        bcm_oam_endpoint_info_t.intf field. 
  26812        However for supporting LM/DM on Saber2 this should be DVP_EGRESS type for PW,
  26813        only CCM will work with L3_EGRESS type, retaining the old type for 
  26814        backward compatibility
  26815     */
  26816     if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){
  26817         if ((!BHH_EP_LSP_TYPE(endpoint_info)) && (endpoint_info->flags & 
  26818             (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 
  26819              BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) { 
  26820             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) {
  26821                 LOG_ERROR(BSL_LS_BCM_OAM,
  26822                         (BSL_META_U(unit,
  26823                                     "OAM(unit %d) Error: bcm_oam_endpoint_info_t.intf type"
  26824                                     " not valid. It should be DVP_EGRESS type for LM/DM support.\n"),
  26825                          unit));
  26826                 return (BCM_E_PARAM);
  26827             }
  26828         } else {
  26829             if ( !BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) & 
  26830                     !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) ) { 
  26831                 LOG_ERROR(BSL_LS_BCM_OAM,
  26832                         (BSL_META_U(unit,
  26833                                     "OAM(unit %d) Error: bcm_oam_endpoint_info_t.intf type"
  26834                                     " not valid. It should be DVP_EGRESS or L3_EGRESS type.\n"),
  26835                          unit));
  26836                 return (BCM_E_PARAM);
  26837             }
  26838         }
  26839     }
  26840     /* Now that we passed the validation checks
  26841      * Create a new endpoint with the requested ID. */
  26842     if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) {
  26843 
  26844         hash_data = &oc->oam_hash_data[endpoint_info->id];
  26845 
  26846         if (!is_replace && hash_data->in_use) {
  26847             return (BCM_E_EXISTS);
  26848         }
  26849 
  26850         ep_req_index = endpoint_info->id;
  26851         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  26852 
  26853         if(BCM_FAILURE(rv)) {
  26854             LOG_ERROR(BSL_LS_BCM_OAM,
  26855                       (BSL_META_U(unit,
  26856                                   "BHH(unit %d) Error: Endpoint check (EP=%d) - %s.\n"),
  26857                        unit, endpoint_info->id, bcm_errmsg(rv)));
  26858             return (rv);
  26859         }
  26860 
  26861         if(!is_replace) {
  26862             rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx,
  26863                                      bhh_pool_ep_idx);
  26864             if (BCM_FAILURE(rv)) {
  26865                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  26866                 LOG_ERROR(BSL_LS_BCM_OAM,
  26867                           (BSL_META_U(unit,
  26868                                       "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"),
  26869                            unit, endpoint_info->id, bcm_errmsg(rv)));
  26870                 return (rv);
  26871             }
  26872         }
  26873     } else {
  26874 
  26875         /* BHH uses local and remote same index */
  26876         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  26877             ep_req_index = endpoint_info->local_id;
  26878             bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  26879         }
  26880         else {
  26881             /* Allocate the next available endpoint index. */
  26882             rv = shr_idxres_list_alloc(oc->bhh_pool,
  26883                                    (shr_idxres_element_t *)&bhh_pool_ep_idx);
  26884             if (BCM_FAILURE(rv)) {
  26885                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
  26886                 LOG_ERROR(BSL_LS_BCM_OAM,
  26887                           (BSL_META_U(unit,
  26888                                       "BHH(unit %d) Error: Endpoint alloc failed - %s.\n"),
  26889                            unit, bcm_errmsg(rv)));
  26890                 return (rv);
  26891             }
  26892             /* Set the allocated endpoint id value. */
  26893             ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx);
  26894         }
  26895         endpoint_info->id =  ep_req_index;
  26896     }
  26897 
  26898     /* Get the hash data pointer where the data is to be stored. */
  26899     hash_data = &oc->oam_hash_data[ep_req_index];
  26900     group_p = &oc->group_info[endpoint_info->group];
  26901 
  26902     if (is_remote) {
  26903 
  26904         if (!hash_data->in_use) {
  26905             return (BCM_E_NOT_FOUND);
  26906         } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) {
  26907             return (BCM_E_EXISTS);
  26908         }
  26909         if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)){
  26910             /*
  26911              * Now that both ends are provisioned the uKernel can be 
  26912              * configured.
  26913              */
  26914             msg_rmep_create.sess_id = bhh_pool_ep_idx;
  26915             msg_rmep_create.flags = 0;
  26916             msg_rmep_create.enable = 1;
  26917             msg_rmep_create.remote_mep_id = endpoint_info->name;
  26918             msg_rmep_create.period = _sb2_ccm_intervals[
  26919                 _bcm_sb2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  26920 
  26921             /* Pack control message data into DMA buffer */
  26922             buffer     = oc->dma_buffer;
  26923             buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer,
  26924                                                            &msg_rmep_create);
  26925             buffer_len = buffer_ptr - buffer;
  26926 
  26927             /* Send BHH Session Update message to uC */
  26928             rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  26929                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE,
  26930                     buffer_len, 0,
  26931                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY,
  26932                     &reply_len);
  26933             if (BCM_FAILURE(rv) || (reply_len != 0)) {
  26934                 LOG_ERROR(BSL_LS_BCM_OAM,
  26935                         (BSL_META_U(unit,
  26936                                     "BHH(unit %d) Error: Endpoint create " 
  26937                                     "(EP=%d) - %s.\n"),
  26938                          unit, endpoint_info->id, bcm_errmsg(rv)));
  26939                 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  26940                 return (BCM_E_INTERNAL);
  26941             }
  26942         }
  26943     } else {
  26944         /* Resolve given endpoint gport value to SGLP and DGLP values. */
  26945         rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, 
  26946                             &dglp, &src_pp_port, &dst_pp_port, &svp, &trunk_id,
  26947                             &is_vp_valid, &trunk_member);
  26948         if (BCM_FAILURE(rv)) {
  26949             LOG_ERROR(BSL_LS_BCM_OAM,
  26950                       (BSL_META_U(unit,
  26951                                   "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  26952                        unit, endpoint_info->id, bcm_errmsg(rv)));
  26953             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  26954             return (rv);
  26955         }
  26956 
  26957         /* Clear the hash data element contents before storing the values */
  26958         _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  26959         hash_data->oam_domain = _BCM_SB2_OAM_DOMAIN_BHH;
  26960         hash_data->type = endpoint_info->type;
  26961         hash_data->ep_id = endpoint_info->id;
  26962         hash_data->group_index = endpoint_info->group;
  26963         hash_data->level = endpoint_info->level;
  26964         hash_data->vlan = endpoint_info->vlan;
  26965         hash_data->inner_vlan = endpoint_info->inner_vlan;
  26966         hash_data->outer_tpid = endpoint_info->outer_tpid;
  26967         hash_data->inner_tpid = endpoint_info->inner_tpid;
  26968         hash_data->vlan_pri = endpoint_info->pkt_pri;
  26969         hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri;
  26970         hash_data->gport = endpoint_info->gport;
  26971         hash_data->sglp = sglp;
  26972         hash_data->dglp = dglp;
  26973         hash_data->src_pp_port = src_pp_port;
  26974         hash_data->dst_pp_port = dst_pp_port;
  26975         hash_data->flags = endpoint_info->flags;
  26976         hash_data->flags2 = endpoint_info->flags2;
  26977         hash_data->int_pri = endpoint_info->int_pri;
  26978         hash_data->period = endpoint_info->ccm_period;
  26979         hash_data->vccv_type = endpoint_info->vccv_type;
  26980         hash_data->vpn  = endpoint_info->vpn;
  26981         hash_data->name      = endpoint_info->name;
  26982         hash_data->egress_if = endpoint_info->intf_id;
  26983         hash_data->cpu_qid   = endpoint_info->cpu_qid;
  26984         hash_data->label     = endpoint_info->mpls_label;
  26985         hash_data->gport     = endpoint_info->gport;
  26986         hash_data->local_tx_enabled = 0;
  26987         hash_data->local_rx_enabled = 1;
  26988         hash_data->ts_format = endpoint_info->timestamp_format;
  26989         hash_data->trunk_index = endpoint_info->trunk_index;
  26990         hash_data->egr_label = endpoint_info->egress_label.label;
  26991         hash_data->egr_label_exp = endpoint_info->egress_label.exp;
  26992         hash_data->egr_label_ttl = endpoint_info->egress_label.ttl;
  26993         sal_memcpy(hash_data->dst_mac_address,
  26994                 endpoint_info->dst_mac_address, _BHH_MAC_ADDR_LENGTH);
  26995         sal_memcpy(hash_data->src_mac_address,
  26996                 endpoint_info->src_mac_address, _BHH_MAC_ADDR_LENGTH);
  26997         hash_data->trunk_id = trunk_id;
  26998         if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  26999             rv = _bcm_sb2_oam_mpls_lmdm_pw_svp_get(unit,
  27000                     hash_data->label, hash_data->sglp,
  27001                     &(hash_data->vp));
  27002             if (BCM_FAILURE(rv)) {
  27003                 /* Return endpoint index to MEP pool. */
  27004                 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
  27005                 LOG_ERROR(BSL_LS_BCM_OAM,
  27006                         (BSL_META_U(unit,
  27007                                     "OAM(unit %d) Error: svp get(EP=%d) - %s.\n"),
  27008                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27009                 return (rv);
  27010             }
  27011         }
  27012         /* Initialize hardware index as invalid indices. */
  27013         hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
  27014         hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
  27015         hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
  27016         hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX;
  27017         hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX;
  27018         hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX;
  27019         hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX;
  27020         hash_data->profile_index = _BCM_OAM_INVALID_INDEX;
  27021         hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX;
  27022         hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX;
  27023         hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  27024         hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  27025         hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX;
  27026         hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX;
  27027         hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  27028         hash_data->in_use = 1;
  27029 
  27030         /* Now that we have reserved the EP index, We can reserve MA INDEX */
  27031         rv =  _bcm_sb2_oam_downmep_rx_endpoint_reserve(unit, endpoint_info);
  27032         if (BCM_FAILURE(rv)) {
  27033             /* Return endpoint index to MEP pool. */
  27034             shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
  27035             LOG_ERROR(BSL_LS_BCM_OAM,
  27036                       (BSL_META_U(unit,
  27037                                   "OAM(unit %d) Error: EP MA INDEX alloc"
  27038                                   "failed EP:%d %s.\n"), unit, endpoint_info->id,
  27039                        bcm_errmsg(rv)));
  27040             return (rv);
  27041         }
  27042 
  27043         if (oc->ukernel_not_ready == 0)  {
  27044             /* Copy VPN and group id for warm boot recovery*/
  27045             oc->bhh_ep_vpn[bhh_pool_ep_idx] = hash_data->vpn;
  27046             oc->bhh_ep_grp_id[bhh_pool_ep_idx] = hash_data->group_index;
  27047             SHR_BITSET(oc->bhh_ma_index_in_use, hash_data->ma_base_index);
  27048         }
  27049 
  27050         rv = _bcm_sb2_oam_local_rx_mep_hw_set(unit, endpoint_info);
  27051         if (BCM_FAILURE(rv)) {
  27052             LOG_ERROR(BSL_LS_BCM_OAM,
  27053                       (BSL_META_U(unit,
  27054                                   "OAM(unit %d) Error: Rx config failed for EP=%d %s.\n"),
  27055                        unit, endpoint_info->id, bcm_errmsg(rv)));
  27056             _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27057             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  27058             return (rv);
  27059         }
  27060         /* BHH Section OAM */
  27061         if (BHH_EP_MPLS_SECTION_TYPE(hash_data)) {
  27062             rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, hash_data);
  27063             if (BCM_FAILURE(rv)) {
  27064                 LOG_ERROR(BSL_LS_BCM_OAM,
  27065                         (BSL_META_U(unit,
  27066                                     "OAM(unit %d) Error: Port table update for "
  27067                                     "section OAM(EP=%d) - %s.\n"),
  27068                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27069                 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27070                 return (rv);
  27071             }
  27072             rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, hash_data);
  27073             if (BCM_FAILURE(rv)) {
  27074                 LOG_ERROR(BSL_LS_BCM_OAM,
  27075                         (BSL_META_U(unit,
  27076                                     "OAM(unit %d) Error: EGR Port table update for "
  27077                                     "section OAM(EP=%d) - %s.\n"),
  27078                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27079                 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27080                 return (rv);
  27081             }
  27082         }else {
  27083             if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) {
  27084                 /* For RX part enable BHH OAM for the label. */
  27085 
  27086                 /* First check if the label is in l3 tunnel table and enable
  27087                  * BHH OAM if true.  */
  27088                 rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit,
  27089                         hash_data, 1);
  27090                 if (rv == BCM_E_NOT_FOUND) {
  27091                     /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 
  27092                      * table */
  27093                     rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit,
  27094                             hash_data, 1);
  27095                     if (BCM_FAILURE(rv)) {
  27096                         LOG_ERROR(BSL_LS_BCM_OAM,
  27097                                 (BSL_META_U(unit,
  27098                                             "OAM(unit %d) Error: MPLS table "
  27099                                              "update failed (EP=%d) - %s.\n"),
  27100                                              unit, endpoint_info->id, 
  27101                                              bcm_errmsg(rv)));
  27102                         _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key,
  27103                                                       hash_data);
  27104                         return (rv);
  27105                     }
  27106                 } else if (rv != BCM_E_NONE) {
  27107                     LOG_ERROR(BSL_LS_BCM_OAM,
  27108                             (BSL_META_U(unit,
  27109                                         "OAM(unit %d) Error: L3 tunnel table "
  27110                                          "update failed (EP=%d) - %s.\n"),
  27111                                          unit, endpoint_info->id, 
  27112                                          bcm_errmsg(rv)));
  27113                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27114                     return (rv);
  27115                 }
  27116                 /* For TX part enable BHH OAM for the egress intf.
  27117                  *                and write the mepid in egr_l3_next_hop table */
  27118                 rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit,
  27119                         hash_data, 1);
  27120                 if (BCM_FAILURE(rv)) {
  27121                     LOG_ERROR(BSL_LS_BCM_OAM,
  27122                             (BSL_META_U(unit,
  27123                                         "OAM(unit %d) Error: EGR_L3_NEXT_HOP "
  27124                                         "table update failed (EP=%d) - %s.\n"),
  27125                                         unit, endpoint_info->id, 
  27126                                         bcm_errmsg(rv)));
  27127                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27128                     return (rv);
  27129                 }
  27130             } else if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  27131                 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit,
  27132                         hash_data, 1);
  27133                 if (BCM_FAILURE(rv)) {
  27134                     LOG_ERROR(BSL_LS_BCM_OAM,
  27135                             (BSL_META_U(unit,
  27136                                         "OAM(unit %d) Error: MPLS LSP table update "
  27137                                         "failed (EP=%d) - %s.\n"),
  27138                                         unit, endpoint_info->id, 
  27139                                         bcm_errmsg(rv)));
  27140                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27141                     return (rv);
  27142                 }
  27143                 /* For TX part enable BHH OAM for the egress dvp.
  27144  */
  27145                 rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, hash_data, 1);
  27146                 if (BCM_FAILURE(rv)) {
  27147                     LOG_ERROR(BSL_LS_BCM_OAM,
  27148                             (BSL_META_U(unit,
  27149                                         "OAM(unit %d) Error: EGR_L3_NEXT_HOP "
  27150                                         "table update failed (EP=%d) - %s.\n"),
  27151                                         unit, endpoint_info->id, 
  27152                                         bcm_errmsg(rv)));
  27153                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27154                     return (rv);
  27155                 }
  27156 
  27157             }
  27158         }
  27159         encap = 1;
  27160 
  27161         if (BCM_TRUNK_INVALID != trunk_id) {
  27162             endpoint_info->gport = trunk_member.gport;
  27163             hash_data->resolved_trunk_gport = trunk_member.gport;
  27164         }
  27165         /* Create or Update */
  27166         session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE;
  27167 
  27168         /* Set Endpoint config entry */
  27169         hash_data->bhh_endpoint_index = ep_req_index;
  27170 
  27171         sal_memset(&counter_info, 0, sizeof(counter_info));
  27172         counter_info.counter_size = 
  27173                                   endpoint_info->ccm_tx_update_lm_counter_size;
  27174         for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
  27175         {
  27176             counter_info.counter_base_id[i] = 
  27177                              endpoint_info->ccm_tx_update_lm_counter_base_id[i];
  27178             counter_info.counter_offset[i] = 
  27179                              endpoint_info->ccm_tx_update_lm_counter_offset[i];
  27180             counter_info.counter_action[i] = bcmOamCounterActionIncrement;
  27181             counter_info.byte_count_offset[i] = 0;
  27182         }
  27183         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
  27184         counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU;
  27185 
  27186         if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  27187 
  27188             /* Get the Trunk, Port and Modid info for this Gport */
  27189             rv = _bcm_esw_gport_resolve(unit,
  27190                     endpoint_info->gport, &module_id, &port_id, &trunk_id, &local_id);
  27191 
  27192             if (BCM_FAILURE(rv)) {
  27193                 LOG_ERROR(BSL_LS_BCM_OAM,
  27194                         (BSL_META_U(unit,
  27195                                     "BHH(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  27196                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27197                 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27198                 return (rv);
  27199             }
  27200             /* Get local port used for TX BHH packet */
  27201             rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
  27202             if(BCM_FAILURE(rv)) {
  27203                 LOG_ERROR(BSL_LS_BCM_OAM,
  27204                         (BSL_META_U(unit,
  27205                                     "BHH(unit %d) Error: local port for "
  27206                                     "BHH TX failed(ep=%d) - %s.\n"),
  27207                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27208                 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27209                 return (rv);
  27210             }
  27211 
  27212             if (!is_local) {    /* HG port */
  27213                 rv = bcm_esw_stk_modport_get(unit, module_id, &port_id);
  27214                 if(BCM_FAILURE(rv)) {
  27215                     LOG_ERROR(BSL_LS_BCM_OAM,
  27216                             (BSL_META_U(unit,
  27217                                         "BHH(unit %d) Error: HG port get failed "
  27218                                         "(EP=%d) - %s.\n"),
  27219                              unit, endpoint_info->id, bcm_errmsg(rv)));
  27220                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27221                     return (rv);
  27222                 }
  27223             }
  27224             /* Set control message data */
  27225             sal_memset(&msg_sess, 0, sizeof(msg_sess));
  27226             /*
  27227              * Set the BHH encapsulation data
  27228              *
  27229              * The function _bcm_sb2_oam_bhh_encap_create() is called first
  27230              * since this sets some fields in 'hash_data' which are
  27231              * used in the message.
  27232              */
  27233             if (encap) {
  27234                 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id,
  27235                         port_id,
  27236                         hash_data,
  27237                         msg_sess.encap_data,
  27238                         &msg_sess.encap_type,
  27239                         &encap_length,
  27240                         &counter_info, hash_data->int_pri,
  27241                         hash_data->egr_label_exp,
  27242                         hash_data->egr_label_ttl);
  27243 
  27244                 if(BCM_FAILURE(rv))
  27245                 {
  27246                     LOG_ERROR(BSL_LS_BCM_OAM,
  27247                               (BSL_META_U(unit,
  27248                                           "BHH(unit %d) Error: Encap create failed "
  27249                                           "(EP=%d) - %s.\n"),
  27250                                unit, endpoint_info->id, bcm_errmsg(rv)));
  27251                     _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27252                     return (rv);
  27253                 }
  27254             }
  27255             msg_sess.encap_length = encap_length;
  27256 
  27257             /*
  27258              * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM,
  27259              * all others modes must be specified via a config flag.
  27260  */
  27261             if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK)
  27262                 session_flags |= SHR_BHH_SESS_SET_F_LB;
  27263             else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)
  27264                 session_flags |= SHR_BHH_SESS_SET_F_DM;
  27265             else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
  27266                 session_flags |= SHR_BHH_SESS_SET_F_LM;
  27267             else
  27268                 session_flags |= SHR_BHH_SESS_SET_F_CCM;
  27269 
  27270             if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
  27271                 session_flags |= SHR_BHH_SESS_SET_F_MIP;
  27272 
  27273             _bcm_sb2_oam_get_group_sw_rdi (unit, endpoint_info->group,
  27274                     &group_sw_rdi);
  27275             if (group_sw_rdi) {
  27276                 session_flags |= SHR_BHH_SESS_SET_F_RDI;
  27277             }
  27278             /*if (!local_tx_enabled)
  27279               session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/
  27280 
  27281             msg_sess.sess_id = bhh_pool_ep_idx;
  27282             msg_sess.flags   = session_flags;
  27283 
  27284             msg_sess.mel     = hash_data->level;
  27285             msg_sess.mep_id  = hash_data->name;
  27286             sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
  27287 
  27288             msg_sess.period = _sb2_ccm_intervals[
  27289                 _bcm_sb2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  27290 
  27291             msg_sess.if_num  = endpoint_info->intf_id;
  27292             msg_sess.tx_port = port_id;
  27293             msg_sess.tx_cos  = endpoint_info->int_pri;
  27294             msg_sess.tx_pri  = endpoint_info->pkt_pri;
  27295             msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri;
  27296             msg_sess.lm_counter_index = hash_data->tx_ctr;
  27297 
  27298             msg_sess.mpls_label = endpoint_info->mpls_label;
  27299 
  27300             switch (endpoint_info->type) {
  27301             case bcmOAMEndpointTypeBHHMPLS:
  27302                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP;
  27303                 msg_sess.priority   = endpoint_info->mpls_exp;
  27304                 break;
  27305 
  27306             case bcmOAMEndpointTypeBHHMPLSVccv:
  27307                 switch(endpoint_info->vccv_type) {
  27308 
  27309                 case bcmOamBhhVccvChannelAch:
  27310                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1;
  27311                     msg_sess.priority   = endpoint_info->mpls_exp;
  27312                     break;
  27313 
  27314                 case bcmOamBhhVccvRouterAlert:
  27315                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2;
  27316                     msg_sess.priority   = endpoint_info->mpls_exp;
  27317                     break;
  27318 
  27319                 case bcmOamBhhVccvTtl:
  27320                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3;
  27321                     msg_sess.priority   = endpoint_info->mpls_exp;
  27322                     break;
  27323 
  27324                 case bcmOamBhhVccvGal13:
  27325                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4;
  27326                     msg_sess.priority   = endpoint_info->mpls_exp;
  27327                     break;
  27328 
  27329                 default:
  27330                     return BCM_E_PARAM;
  27331                     break;
  27332                 }
  27333                 break;
  27334 
  27335             case bcmOAMEndpointTypeBhhSection:
  27336                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION;
  27337                 msg_sess.priority   = 0;
  27338                 break;
  27339             case bcmOAMEndpointTypeBhhSectionInnervlan:
  27340                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN;
  27341                 msg_sess.priority   = endpoint_info->inner_pkt_pri;
  27342                 break;
  27343             case bcmOAMEndpointTypeBhhSectionOuterVlan:
  27344                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN;
  27345                 msg_sess.priority   = endpoint_info->pkt_pri;
  27346                 break;
  27347             case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
  27348                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN;
  27349                 msg_sess.priority   = endpoint_info->pkt_pri;
  27350                 break;
  27351 
  27352             default:
  27353                 return BCM_E_PARAM;
  27354             }
  27355 
  27356             /* Pack control message data into DMA buffer */
  27357             buffer     = oc->dma_buffer;
  27358             buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  27359             buffer_len = buffer_ptr - buffer;
  27360 
  27361             /* Send BHH Session Update message to uC */
  27362             rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  27363                     MOS_MSG_SUBCLASS_BHH_SESS_SET,
  27364                     buffer_len, 0,
  27365                     MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
  27366                     &reply_len);
  27367             if (BCM_FAILURE(rv) || (reply_len != 0)) {
  27368                 LOG_ERROR(BSL_LS_BCM_OAM,
  27369                         (BSL_META_U(unit,
  27370                                     "BHH(unit %d) Error: Session SET failed "
  27371                                     "(EP=%d) - %s.\n"),
  27372                          unit, endpoint_info->id, bcm_errmsg(rv)));
  27373                 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27374                 return (rv);
  27375             }
  27376         }
  27377 
  27378         if (!is_replace) {
  27379             rv = _bcm_sb2_oam_group_ep_list_add(unit, endpoint_info->group,
  27380                                                 endpoint_info->id);
  27381         }
  27382         if (BCM_FAILURE(rv)) {
  27383             LOG_ERROR(BSL_LS_BCM_OAM,
  27384                       (BSL_META_U(unit,
  27385                                   "OAM(unit %d) Error: Tx config failed for EP=%d %s.\n"),
  27386                        unit, endpoint_info->id, bcm_errmsg(rv)));
  27387             _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27388             return (rv);
  27389         }
  27390         rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data);
  27391         if (BCM_FAILURE(rv)) {
  27392             LOG_ERROR(BSL_LS_BCM_OAM,
  27393                     (BSL_META_U(unit,
  27394                                 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -"
  27395                                 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv)));
  27396             _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27397             return (rv);
  27398         }
  27399 
  27400         /* hash collision */
  27401         rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
  27402         if (BCM_FAILURE(rv)) {
  27403             LOG_ERROR(BSL_LS_BCM_OAM,
  27404                     (BSL_META_U(unit,
  27405                                 "OAM(unit %d) Error: Hash table insert failed EP=%d %s.\n"),
  27406                      unit, endpoint_info->id, bcm_errmsg(rv)));
  27407             _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data);
  27408             return (rv);
  27409         }
  27410     }
  27411     hash_data->in_use = 1;
  27412 
  27413 #ifdef BCM_WARM_BOOT_SUPPORT
  27414     SOC_CONTROL_LOCK(unit);
  27415     SOC_CONTROL(unit)->scache_dirty = 1;
  27416     SOC_CONTROL_UNLOCK(unit);
  27417 #endif
  27418 
  27419     return (rv);
  27420 }
  27421 
  27422 /*
  27423  * Function:
  27424  *      _bcm_sb2_oam_bhh_hw_init
  27425  * Purpose:
  27426  *      Initialize the HW for BHH packet processing.
  27427  *      Configure:
  27428  *      - Copy to CPU BHH error packets
  27429  *      - CPU COS Queue for BHH packets
  27430  *      - RX DMA channel
  27431  * Parameters:
  27432  *      unit - (IN) Unit number.
  27433  * Returns:
  27434  *      BCM_E_XXX
  27435  * Notes:
  27436  */
  27437 STATIC int
  27438 _bcm_sb2_oam_bhh_hw_init(int unit)
  27439 {
  27440     int rv = BCM_E_NONE;
  27441     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  27442     uint32 val=0; 
  27443     int index;
  27444     int ach_error_index;
  27445     int bhh_lb_index;
  27446     int invalid_error_index;
  27447     int cosq_map_size;
  27448     bcm_rx_reasons_t reasons, reasons_mask;
  27449     uint8 int_prio, int_prio_mask;
  27450     uint32 packet_type, packet_type_mask;
  27451     bcm_cos_queue_t cosq;
  27452     bcm_rx_chan_t chan_id;
  27453     int num_cosq = 0;
  27454     int min_cosq, max_cosq;
  27455     int i;
  27456 
  27457     /* Get OAM Control Structure. */
  27458     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  27459 
  27460     _BCM_OAM_LOCK(oc);
  27461 
  27462     /*
  27463      * Send BHH lookup failure packet to CPU
  27464      * Configure CPU_CONTROL_M register
  27465      * Field BHH_SESSION_NOT_FOUND_TO_CPU
  27466      */
  27467     rv = READ_CPU_CONTROL_Mr(unit, &val);
  27468     if(BCM_FAILURE(rv)) {
  27469         LOG_ERROR(BSL_LS_BCM_OAM,
  27470                   (BSL_META_U(unit,
  27471                               "BHH(unit %d) Error:hw init. Read CPU Control Reg %s.\n"),
  27472                    unit, bcm_errmsg(rv)));
  27473         _BCM_OAM_UNLOCK(oc);
  27474         return (rv);
  27475     }
  27476 
  27477     /* Steer lookup failure packet to CPU */
  27478     soc_reg_field_set(unit, CPU_CONTROL_Mr, &val,
  27479                       MPLS_CTRL_PACKET_SESSION_NOT_FOUND_TO_CPUf, 1);
  27480 
  27481     rv = WRITE_CPU_CONTROL_Mr(unit, val);
  27482     if(BCM_FAILURE(rv)) {
  27483         LOG_ERROR(BSL_LS_BCM_OAM,
  27484                   (BSL_META_U(unit,
  27485                               "BHH(unit %d) Error:hw init. Write CPU_CONTROL_M Reg %s.\n"),
  27486                    unit, bcm_errmsg(rv)));
  27487         _BCM_OAM_UNLOCK(oc);
  27488         return (rv);
  27489     }
  27490 
  27491     if(oc->ukernel_not_ready == 0){
  27492         /* 
  27493          * Get COSQ for BHH
  27494          */
  27495         min_cosq = 0;
  27496         for (i = 0; i < SOC_CMCS_NUM(unit); i++) {
  27497             num_cosq = NUM_CPU_ARM_COSQ(unit, i);
  27498             if (i == oc->uc_num + 1) {
  27499                 break;
  27500             }
  27501             min_cosq += num_cosq;
  27502         }
  27503         max_cosq = min_cosq + num_cosq - 1;
  27504 
  27505         if(max_cosq < min_cosq) {
  27506             LOG_ERROR(BSL_LS_BCM_OAM,
  27507                       (BSL_META_U(unit,
  27508                                   "BHH(unit %d) Error: "
  27509                                   "No BHH COS Queue available from uC%d - %s\n"),
  27510                        unit, oc->uc_num, bcm_errmsg(BCM_E_CONFIG)));
  27511             _BCM_OAM_UNLOCK(oc);
  27512             return (BCM_E_CONFIG);
  27513         }
  27514 
  27515         /* check user configured COSq */
  27516         if (oc->cpu_cosq != BHH_COSQ_INVALID) {
  27517             if ((oc->cpu_cosq < min_cosq) ||
  27518                 (oc->cpu_cosq > max_cosq)) {
  27519                 _BCM_OAM_UNLOCK(oc);
  27520                 return (BCM_E_CONFIG);
  27521             }
  27522             min_cosq = max_cosq = oc->cpu_cosq;
  27523         }
  27524 
  27525         /*
  27526          * Assign RX DMA channel to CPU COS Queue
  27527          * (This is the RX channel to listen on for BHH packets).
  27528          *
  27529          * DMA channels (12) are assigned 4 per processor:
  27530          * (see /src/bcm/common/rx.c)
  27531          *   channels 0..3  --> PCI host
  27532          *   channels 4..7  --> uController 0
  27533          *   chnanels 8..11 --> uController 1
  27534          *
  27535          * The uControllers designate the 4 local DMA channels as follows:
  27536          *   local channel  0     --> TX
  27537          *   local channel  1..3  --> RX
  27538          *
  27539          * Each uController application needs to use a different
  27540          * RX DMA channel to listen on.
  27541          */
  27542         chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) +
  27543             oc->rx_channel;
  27544 
  27545         for (i = max_cosq; i >= min_cosq; i--) {
  27546             rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
  27547             if(BCM_SUCCESS(rv)) {
  27548                 oc->cpu_cosq = i;
  27549                 break;
  27550             }
  27551         }
  27552 
  27553         if (i < min_cosq) {
  27554             rv = BCM_E_RESOURCE;
  27555             LOG_ERROR(BSL_LS_BCM_OAM,
  27556                       (BSL_META_U(unit,
  27557                                   "BHH(unit %d) Error: hw init."
  27558                                   " queue channel set %s.\n"),
  27559                        unit, bcm_errmsg(rv)));
  27560             _BCM_OAM_UNLOCK(oc);
  27561             return (rv);
  27562         }
  27563 
  27564         /*
  27565          * Direct BHH packets to designated CPU COS Queue...or more accurately
  27566          * BFD error packets.
  27567          *
  27568          * Reasons:
  27569          *   - bcmRxReasonBFD:               BFD error
  27570          *   - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH
  27571          * NOTE:
  27572          *     The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be
  27573          *     used to select different CPU COS queue. Currently,
  27574          *     all priorities are mapped into the same CPU COS Queue.
  27575          */
  27576 
  27577         /* Find available entries in CPU COS queue map table */
  27578         ach_error_index    = -1;   /* COSQ map index for error packets */
  27579         invalid_error_index    = -1;   /* COSQ map index for error packets */
  27580         bhh_lb_index    = -1;   /* COSQ map index for LB packets */
  27581         rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  27582         if(BCM_FAILURE(rv)) {
  27583             LOG_ERROR(BSL_LS_BCM_OAM,
  27584                       (BSL_META_U(unit,
  27585                                   "BHH(unit %d) Error:hw init. cosq maps size %s.\n"),
  27586                        unit, bcm_errmsg(rv)));
  27587             _BCM_OAM_UNLOCK(oc);
  27588             return (rv);
  27589         }
  27590     
  27591         for (index = 0; index < cosq_map_size; index++) {
  27592             rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  27593                                              &reasons, &reasons_mask,
  27594                                              &int_prio, &int_prio_mask,
  27595                                              &packet_type, &packet_type_mask,
  27596                                              &cosq);
  27597             if (rv == BCM_E_NOT_FOUND) {
  27598                 /* Assign first available index */
  27599                 rv = BCM_E_NONE;
  27600                 if (ach_error_index == -1) {
  27601                     ach_error_index = index;
  27602                 } else if (invalid_error_index == -1) {
  27603                     invalid_error_index = index;
  27604                 } else if (bhh_lb_index == -1) {
  27605                     bhh_lb_index = index;
  27606                     break;
  27607                 }
  27608             }
  27609             if (BCM_FAILURE(rv)) {
  27610                 LOG_ERROR(BSL_LS_BCM_OAM,
  27611                           (BSL_META_U(unit,
  27612                                       "BHH(unit %d) Error:hw init. cosq maps get %s.\n"),
  27613                            unit, bcm_errmsg(rv)));
  27614                 _BCM_OAM_UNLOCK(oc);
  27615                 return (rv);
  27616             }
  27617         }
  27618 
  27619         if (ach_error_index == -1 || invalid_error_index == -1) {
  27620             LOG_ERROR(BSL_LS_BCM_OAM,
  27621                       (BSL_META_U(unit,
  27622                                   "BHH(unit %d) Error:hw init. ACH error %s.\n"),
  27623                        unit, bcm_errmsg(rv)));
  27624             _BCM_OAM_UNLOCK(oc);
  27625             return (BCM_E_FULL);
  27626         }
  27627 
  27628         /* Set CPU COS Queue mapping */
  27629         BCM_RX_REASON_CLEAR_ALL(reasons);
  27630         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);         /* BHH Packet     */
  27631         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMCCMSlowpath); /*OAM Slowpath CCM*/
  27632 
  27633         rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index,
  27634                                          reasons, reasons,
  27635                                          0, 0, /* Any Internal Prio */  
  27636                                          0, 0, /* Any packet type   */
  27637                                          oc->cpu_cosq);
  27638         if(BCM_FAILURE(rv)) {
  27639             LOG_ERROR(BSL_LS_BCM_OAM,
  27640                       (BSL_META_U(unit,
  27641                                   "BHH(unit %d) Error:hw init. cosq map set %s.\n"),
  27642                        unit, bcm_errmsg(rv)));
  27643             _BCM_OAM_UNLOCK(oc);
  27644             return (rv);
  27645         }
  27646         oc->cpu_cosq_ach_error_index = ach_error_index;
  27647 
  27648         BCM_RX_REASON_CLEAR_ALL(reasons);
  27649         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);         /* BHH Packet     */
  27650         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMSlowpath); /*OAM Slowpath CCM*/
  27651 
  27652         rv = bcm_esw_rx_cosq_mapping_set(unit, bhh_lb_index,
  27653                                          reasons, reasons,
  27654                                          0, 0, /* Any Internal Prio */  
  27655                                          0, 0, /* Any packet type   */
  27656                                          oc->cpu_cosq);
  27657         if(BCM_FAILURE(rv)) {
  27658             LOG_ERROR(BSL_LS_BCM_OAM,
  27659                       (BSL_META_U(unit,
  27660                                   "BHH(unit %d) Error:hw init. cosq map set for"
  27661                                   " Loopback %s.\n"),
  27662                        unit, bcm_errmsg(rv)));
  27663             _BCM_OAM_UNLOCK(oc);
  27664             return (rv);
  27665         }
  27666         oc->bhh_lb_index = bhh_lb_index;
  27667 
  27668         BCM_RX_REASON_CLEAR_ALL(reasons);
  27669         BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM);      /* BHH Packet         */
  27670         BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM Slowpath(LB/LBR)*/
  27671 
  27672         rv = bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index,
  27673                                          reasons, reasons,
  27674                                          0, 0, /* Any Internal Prio */  
  27675                                          0, 0, /* Any packet type */
  27676                                          oc->cpu_cosq);
  27677         if(BCM_FAILURE(rv)) {
  27678             LOG_ERROR(BSL_LS_BCM_OAM,
  27679                       (BSL_META_U(unit,
  27680                                   "BHH(unit %d) Error:hw init. cosq map set %s.\n"),
  27681                        unit, bcm_errmsg(rv)));
  27682             _BCM_OAM_UNLOCK(oc);
  27683             return (rv);
  27684         }
  27685         oc->cpu_cosq_invalid_error_index = invalid_error_index;
  27686     }
  27687 
  27688     _BCM_OAM_UNLOCK(oc);
  27689     return (rv);
  27690 }
  27691 #endif /*(INCLUDE_BHH) */
  27692 
  27693 #if defined(INCLUDE_ETH_LM_DM)
  27694 /*
  27695  * Function:
  27696  *      _bcm_sb2_oam_eth_lm_dm_hw_init
  27697  * Purpose:
  27698  *      Initialize the HW for ETH_LM_DM packet processing.
  27699  *      Configure:
  27700  *      - Copy to CPU ETH_LM_DM error packets
  27701  *      - CPU COS Queue for ETH_LM_DM packets
  27702  *      - RX DMA channel
  27703  * Parameters:
  27704  *      unit - (IN) Unit number.
  27705  * Returns:
  27706  *      BCM_E_XXX
  27707  * Notes:
  27708  */
  27709 STATIC int
  27710 _bcm_sb2_oam_eth_lm_dm_hw_init(int unit)
  27711 {
  27712     int rv = BCM_E_NONE;
  27713     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  27714     int index;
  27715     int eth_lm_dm_index;
  27716     int cosq_map_size;
  27717     bcm_rx_reasons_t reasons, reasons_mask;
  27718     uint8 int_prio, int_prio_mask;
  27719     uint32 packet_type, packet_type_mask;
  27720     bcm_cos_queue_t cosq;
  27721     int eth_lm_dm_cosq;
  27722     /* Get OAM Control Structure. */
  27723     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  27724 
  27725     if(!oc->eth_lm_dm_ukernel_not_ready) {
  27726     
  27727     _BCM_OAM_LOCK(oc);
  27728     
  27729     eth_lm_dm_cosq = oc->eth_lm_dm_cpu_cosq;
  27730     /*
  27731      * Assign RX DMA channel to CPU COS Queue
  27732      * (This is the RX channel to listen on for ETH_LM_DM packets).
  27733      *
  27734      * DMA channels (12) are assigned 4 per processor:
  27735      * (see /src/bcm/common/rx.c)
  27736      *   channels 0..3  --> PCI host
  27737      *   channels 4..7  --> uController 0
  27738      *   chnanels 8..11 --> uController 1
  27739      *
  27740      * The uControllers designate the 4 local DMA channels as follows:
  27741      *   local channel  0     --> TX
  27742      *   local channel  1..3  --> RX
  27743      *
  27744      * Each uController application needs to use a different
  27745      * RX DMA channel to listen on.
  27746      */
  27747 
  27748     rv = _bcm_common_rx_queue_channel_set(unit,
  27749                                           eth_lm_dm_cosq,
  27750                                           oc->eth_lm_dm_rx_channel);
  27751     if(!BCM_SUCCESS(rv)) {
  27752         LOG_ERROR(BSL_LS_BCM_OAM,
  27753                 (BSL_META_U(unit,
  27754                             "ETH_LM_DM(unit %d) Error: hw init."
  27755                             " queue channel set %s.\n"),
  27756                  unit, bcm_errmsg(rv)));
  27757         _BCM_OAM_UNLOCK(oc);
  27758         return (rv);
  27759 
  27760     }
  27761 
  27762     /*
  27763      * Direct ETH_LM_DM packets to designated CPU COS Queue.
  27764      *
  27765      * Reasons:
  27766      *   - bcmRxReasonOAMLMDM: ETH_LM_DM packet breason code
  27767      */
  27768 
  27769     /* Find available entries in CPU COS queue map table */
  27770     eth_lm_dm_index    = -1;   /* COSQ map index for error packets */
  27771     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  27772     if(BCM_FAILURE(rv)) {
  27773         LOG_ERROR(BSL_LS_BCM_OAM,
  27774                   (BSL_META_U(unit,
  27775                               "ETH_LM_DM(unit %d) Error:hw init. cosq maps size %s.\n"),
  27776                    unit, bcm_errmsg(rv)));
  27777         _BCM_OAM_UNLOCK(oc);
  27778         return (rv);
  27779     }
  27780     
  27781     for (index = 0; index < cosq_map_size; index++) {
  27782         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  27783                                          &reasons, &reasons_mask,
  27784                                          &int_prio, &int_prio_mask,
  27785                                          &packet_type, &packet_type_mask,
  27786                                          &cosq);
  27787         if (rv == BCM_E_NOT_FOUND) {
  27788             /* Assign first available index */
  27789             rv = BCM_E_NONE;
  27790             if (eth_lm_dm_index == -1) {
  27791                 eth_lm_dm_index = index;
  27792                 break;
  27793             }
  27794         }
  27795         if (BCM_FAILURE(rv)) {
  27796             LOG_ERROR(BSL_LS_BCM_OAM,
  27797                       (BSL_META_U(unit,
  27798                                   "ETH_LM_DM(unit %d) Error:hw init. cosq maps get %s.\n"),
  27799                        unit, bcm_errmsg(rv)));
  27800             _BCM_OAM_UNLOCK(oc);
  27801             return (rv);
  27802         }
  27803     }
  27804 
  27805     if (eth_lm_dm_index == -1) {
  27806         LOG_ERROR(BSL_LS_BCM_OAM,
  27807                   (BSL_META_U(unit,
  27808                               "ETH_LM_DM(unit %d) Error:hw init. map_index error %s.\n"),
  27809                    unit, bcm_errmsg(rv)));
  27810         _BCM_OAM_UNLOCK(oc);
  27811         return (BCM_E_FULL);
  27812     }
  27813 
  27814     BCM_RX_REASON_CLEAR_ALL(reasons);
  27815     BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM LM/DM*/
  27816 
  27817     rv = bcm_esw_rx_cosq_mapping_set(unit, eth_lm_dm_index,
  27818                                      reasons, reasons,
  27819                                      0, 0, /* Any Internal Prio */  
  27820                                      0, 0, /* Any packet type */
  27821                                      oc->eth_lm_dm_cpu_cosq);
  27822     if(BCM_FAILURE(rv)) {
  27823         LOG_ERROR(BSL_LS_BCM_OAM,
  27824                   (BSL_META_U(unit,
  27825                               "ETH_LM_DM(unit %d) Error:hw init. cosq map set %s.\n"),
  27826                    unit, bcm_errmsg(rv)));
  27827         _BCM_OAM_UNLOCK(oc);
  27828         return (rv);
  27829     }
  27830     oc->eth_lm_dm_cosq_index = eth_lm_dm_index;
  27831 
  27832     /* For sending the LM/DM packet to cos-mapping of BTE running ETH LM/DM for UP-MEP*/
  27833     rv = soc_reg_field32_modify(unit, EGR_CPU_CONTROL_2_64r, REG_PORT_ANY,
  27834                                 OAM_LMDM_CPU_COSf, oc->eth_lm_dm_cpu_cosq);
  27835     if (SOC_FAILURE(rv)) {
  27836         _BCM_OAM_UNLOCK(oc);
  27837         return rv;
  27838     }
  27839 
  27840 
  27841     _BCM_OAM_UNLOCK(oc);
  27842 }
  27843     return (rv);
  27844 }
  27845 
  27846 
  27847 STATIC int
  27848 _bcm_sb2_eth_lm_dm_loss_delete (int unit,
  27849         _bcm_oam_control_t   *oc,
  27850         _bcm_oam_hash_data_t *h_data_p)
  27851 {
  27852     int rv = BCM_E_NONE;
  27853     uint8 *buffer, *buffer_ptr;
  27854     uint16 buffer_len, reply_len;
  27855     int sess_id = 0;
  27856 
  27857     shr_eth_lm_dm_msg_ctrl_loss_delete_t msg;
  27858 
  27859     sess_id = h_data_p->lm_dm_uc_session_id;
  27860 
  27861     /* Validate session id. */
  27862     rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id);
  27863     if ((BCM_E_EXISTS != rv)) {
  27864         /* Invalid session id */
  27865         LOG_ERROR(BSL_LS_BCM_OAM,
  27866                 (BSL_META_U(unit,
  27867                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  27868                  unit, h_data_p->ep_id, bcm_errmsg(rv)));
  27869         return (rv);
  27870     }
  27871     
  27872     if (oc->eth_lm_dm_ukernel_not_ready == 1) {
  27873         rv = BCM_E_INIT;
  27874         return rv;
  27875 
  27876     }
  27877     
  27878     msg.sess_id = sess_id;
  27879 
  27880     /* Pack control message data into DMA buffer */
  27881     buffer     = oc->eth_lm_dm_dma_buffer;
  27882     buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_delete_pack(buffer, &msg);
  27883     buffer_len = buffer_ptr - buffer;
  27884 
  27885     /* Send ETH LM/DM loss delete message to uC */
  27886     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  27887             MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_DELETE,
  27888             buffer_len, 0,
  27889             MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY,
  27890             &reply_len);
  27891 
  27892     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  27893         rv =  BCM_E_INTERNAL;
  27894     }
  27895 
  27896     /* Delete DM instance from internal flags*/
  27897     h_data_p->lm_dm_int_flag  &= ~_ETH_LM_DM_F_LM_IS_SET;
  27898 
  27899     /* If DM is also not running then delete session from BTE */
  27900     if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET)) {
  27901 
  27902         rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  27903                 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE,
  27904                 sess_id, 0,
  27905                 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE_REPLY,
  27906                 &reply_len);
  27907 
  27908         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  27909             rv =  BCM_E_INTERNAL;
  27910         }
  27911         shr_idxres_list_free(oc->eth_lm_dm_pool,
  27912                 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id);
  27913 
  27914         oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0;
  27915         h_data_p->lm_dm_uc_session_id = 0;
  27916         h_data_p->lm_dm_int_flag = 0;
  27917 
  27918     }
  27919 
  27920     return rv;
  27921 }
  27922 
  27923 STATIC int
  27924 _bcm_sb2_eth_lm_dm_delay_delete (int unit,
  27925         _bcm_oam_control_t   *oc,
  27926         _bcm_oam_hash_data_t *h_data_p)
  27927 {
  27928     int rv = BCM_E_NONE;
  27929     uint8 *buffer, *buffer_ptr;
  27930     uint16 buffer_len, reply_len;
  27931     int sess_id = 0;
  27932 
  27933     shr_eth_lm_dm_msg_ctrl_delay_delete_t msg;
  27934 
  27935     sess_id = h_data_p->lm_dm_uc_session_id;
  27936 
  27937     /* Validate session id. */
  27938     rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id);
  27939     if ((BCM_E_EXISTS != rv)) {
  27940         /* Invalid session id */
  27941         LOG_ERROR(BSL_LS_BCM_OAM,
  27942                 (BSL_META_U(unit,
  27943                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  27944                  unit, h_data_p->ep_id, bcm_errmsg(rv)));
  27945         return (rv);
  27946     }
  27947 
  27948     if (oc->eth_lm_dm_ukernel_not_ready == 1) {
  27949         rv = BCM_E_INIT;
  27950         return rv;
  27951     }
  27952     
  27953 
  27954     msg.sess_id = sess_id;
  27955 
  27956     /* Pack control message data into DMA buffer */
  27957     buffer     = oc->eth_lm_dm_dma_buffer;
  27958     buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_delete_pack(buffer, &msg);
  27959     buffer_len = buffer_ptr - buffer;
  27960 
  27961     /* Send ETH LM/DM delay delete message to uC */
  27962     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  27963             MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_DELETE,
  27964             buffer_len, 0,
  27965             MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY,
  27966             &reply_len);
  27967 
  27968     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  27969         rv =  BCM_E_INTERNAL;
  27970         return rv;
  27971     }
  27972 
  27973     /* Delete DM instance from internal flags*/
  27974     h_data_p->lm_dm_int_flag &= ~_ETH_LM_DM_F_DM_IS_SET;
  27975 
  27976     /* If LM is also not running then delete session from BTE */
  27977     if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET)) {
  27978 
  27979         rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  27980                 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE,
  27981                 sess_id, 0,
  27982                 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE_REPLY,
  27983                 &reply_len);
  27984 
  27985         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  27986             rv =  BCM_E_INTERNAL;
  27987             return rv;
  27988         }
  27989 
  27990         shr_idxres_list_free(oc->eth_lm_dm_pool,
  27991                 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id);
  27992 
  27993         oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0;
  27994         h_data_p->lm_dm_uc_session_id = 0;
  27995         h_data_p->lm_dm_int_flag = 0;
  27996     }
  27997     
  27998     return rv;
  27999 }
  28000 #endif /*(INCLUDE_ETH_LM_DM) */
  28001 
  28002 #if defined(INCLUDE_MPLS_LM_DM)
  28003 /*
  28004  * Function:
  28005  *      _bcm_sb2_oam_mpls_lm_dm_hw_init
  28006  * Purpose:
  28007  *      Initialize the HW for MPLS_LM_DM packet processing.
  28008  *      Configure:
  28009  *      - Copy to CPU MPLS_LM_DM error packets
  28010  *      - CPU COS Queue for MPLS_LM_DM packets
  28011  *      - RX DMA channel
  28012  * Parameters:
  28013  *      unit - (IN) Unit number.
  28014  * Returns:
  28015  *      BCM_E_XXX
  28016  * Notes:
  28017  */
  28018 STATIC int
  28019 _bcm_sb2_oam_mpls_lm_dm_hw_init(int unit)
  28020 {
  28021     int rv = BCM_E_NONE;
  28022     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  28023     int index;
  28024     int mpls_lm_dm_index;
  28025     int cosq_map_size;
  28026     bcm_rx_reasons_t reasons, reasons_mask;
  28027     uint8 int_prio, int_prio_mask;
  28028     uint32 packet_type, packet_type_mask;
  28029     bcm_cos_queue_t cosq;
  28030     bcm_rx_chan_t chan_id;
  28031     /* Get OAM Control Structure. */
  28032     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  28033 
  28034     _BCM_OAM_LOCK(oc);
  28035     chan_id = oc->mpls_lm_dm_rx_channel;
  28036     cosq = MPLS_LM_DM_CPU_COS; 
  28037     rv = _bcm_common_rx_queue_channel_set(unit, cosq, chan_id);
  28038     if (BCM_FAILURE(rv)) {
  28039         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM" 
  28040         " Error: cos to channel map set failed %s.\n"), bcm_errmsg(rv)));
  28041          _BCM_OAM_UNLOCK(oc);
  28042          return (rv);
  28043     }
  28044     oc->mpls_lm_dm_cpu_cosq = cosq;
  28045 
  28046     /*
  28047      * Direct MPLS_LM_DM packets to designated CPU COS Queue.
  28048      *
  28049      * Reasons:
  28050      *   - bcmRxReasonOAMLMDM: MPLS_LM_DM packet breason code
  28051      */
  28052 
  28053     /* Find available entries in CPU COS queue map table */
  28054     mpls_lm_dm_index    = -1;   /* COSQ map index for error packets */
  28055     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  28056     if(BCM_FAILURE(rv)) {
  28057         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 
  28058         " Error:hw init. cos map size get %s.\n"), unit, bcm_errmsg(rv)));
  28059         _BCM_OAM_UNLOCK(oc);
  28060         return (rv);
  28061     }
  28062     
  28063     for (index = 0; index < cosq_map_size; index++) {
  28064         rv = bcm_esw_rx_cosq_mapping_get(unit, index, &reasons, 
  28065                 &reasons_mask, &int_prio, &int_prio_mask, &packet_type, 
  28066                 &packet_type_mask, &cosq);
  28067         
  28068         if (rv == BCM_E_NOT_FOUND) {
  28069             /* Assign first available index */
  28070             rv = BCM_E_NONE;
  28071             if (mpls_lm_dm_index == -1) {
  28072                 mpls_lm_dm_index = index;
  28073                 break;
  28074             }
  28075         }
  28076         if (BCM_FAILURE(rv)) {
  28077             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 
  28078             " Error:hw init. cosq map get %s.\n"), unit, bcm_errmsg(rv)));
  28079             _BCM_OAM_UNLOCK(oc);
  28080             return (rv);
  28081         }
  28082     }
  28083 
  28084     if (mpls_lm_dm_index == -1) {
  28085         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)"
  28086         " Error:hw init. map_index error %s.\n"), unit, bcm_errmsg(rv)));
  28087         _BCM_OAM_UNLOCK(oc);
  28088         return (BCM_E_FULL);
  28089     }
  28090 
  28091     BCM_RX_REASON_CLEAR_ALL(reasons);
  28092     BCM_RX_REASON_SET(reasons, bcmRxReasonOAMMplsLmDm); /* MPLS_LM_DM */
  28093 
  28094     rv = bcm_esw_rx_cosq_mapping_set(unit, mpls_lm_dm_index,
  28095                                      reasons, reasons,
  28096                                      0, 0, /* Any Internal Prio */  
  28097                                      0, 0, /* Any packet type */
  28098                                      oc->mpls_lm_dm_cpu_cosq);
  28099     if(BCM_FAILURE(rv)) {
  28100         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 
  28101         " Error:hw init. cosq map set %s.\n"), unit, bcm_errmsg(rv)));
  28102         _BCM_OAM_UNLOCK(oc);
  28103         return (rv);
  28104     }
  28105     oc->mpls_lm_dm_cosq_index = mpls_lm_dm_index;
  28106 
  28107     _BCM_OAM_UNLOCK(oc);
  28108     return (rv);
  28109 }
  28110 
  28111  #if defined(BCM_METROLITE_SUPPORT)
  28112 /*
  28113  * Function:
  28114  *      _bcm_ml_oam_mpls_lm_dm_hw_init
  28115  * Purpose:
  28116  *      Initialize the HW for MPLS_LM_DM packet processing.
  28117  *      Configure:
  28118  *      - Copy to CPU MPLS_LM_DM error packets
  28119  *      - CPU COS Queue for MPLS_LM_DM packets
  28120  *      - RX DMA channel
  28121  * Parameters:
  28122  *      unit - (IN) Unit number.
  28123  * Returns:
  28124  *      BCM_E_XXX
  28125  * Notes:
  28126  */
  28127 STATIC int
  28128 _bcm_ml_oam_mpls_lm_dm_hw_init(int unit)
  28129 {
  28130     int rv = BCM_E_NONE;
  28131     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  28132     int index;
  28133     int mpls_lm_dm_index;
  28134     int cosq_map_size;
  28135     bcm_rx_reasons_t reasons, reasons_mask;
  28136     uint8 int_prio, int_prio_mask;
  28137     uint32 packet_type, packet_type_mask;
  28138     bcm_cos_queue_t cosq;
  28139     bcm_rx_chan_t chan_id;
  28140     int i, min_cosq, max_cosq, num_cosq = 0;
  28141     /* Get OAM Control Structure. */
  28142     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  28143 
  28144     _BCM_OAM_LOCK(oc);
  28145 
  28146     /* Get valid range of COS queues for uC where BFD is loaded */
  28147     min_cosq = 0;
  28148     for (i = 0; i < SOC_CMCS_NUM(unit); i++) {
  28149         num_cosq = NUM_CPU_ARM_COSQ(unit, i);
  28150         if (i == oc->mpls_lm_dm_uc_num + 1) {
  28151             break;
  28152         }
  28153         min_cosq += num_cosq;
  28154     }
  28155     max_cosq = min_cosq + num_cosq - 1;
  28156 
  28157     /* Check that there is at least one COS queue assigned to the CMC */
  28158     if (max_cosq < min_cosq) {
  28159         LOG_ERROR(BSL_LS_BCM_COMMON,
  28160                   (BSL_META_U(unit,
  28161                               "ERROR: No MPLS LM/DM COS Queue available from uC%d\n"),
  28162                    oc->mpls_lm_dm_uc_num));
  28163         _BCM_OAM_UNLOCK(oc);
  28164         return BCM_E_CONFIG;
  28165     }
  28166 
  28167     chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->mpls_lm_dm_uc_num))) +
  28168               MPLS_LM_DM_RX_CHANNEL_UC_VIEW;
  28169 
  28170     for (i = max_cosq; i >= min_cosq; i--) {
  28171             rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
  28172             if(BCM_SUCCESS(rv)) {
  28173                 oc->mpls_lm_dm_cpu_cosq = i;
  28174                 break;
  28175             }
  28176         }
  28177 
  28178         if (i < min_cosq) {
  28179             rv = BCM_E_RESOURCE;
  28180             LOG_ERROR(BSL_LS_BCM_OAM,
  28181                       (BSL_META_U(unit,
  28182                                   "BHH(unit %d) Error: hw init."
  28183                                   " queue channel set %s.\n"),
  28184                        unit, bcm_errmsg(rv)));
  28185             _BCM_OAM_UNLOCK(oc);
  28186             return (rv);
  28187         }
  28188 
  28189     /*
  28190      * Direct MPLS_LM_DM packets to designated CPU COS Queue.
  28191      *
  28192      * Reasons:
  28193      *   - bcmRxReasonOAMLMDM: MPLS_LM_DM packet breason code
  28194      */
  28195 
  28196     /* Find available entries in CPU COS queue map table */
  28197     mpls_lm_dm_index    = -1;   /* COSQ map index for error packets */
  28198     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  28199     if(BCM_FAILURE(rv)) {
  28200         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)"
  28201         " Error:hw init. cos map size get %s.\n"), unit, bcm_errmsg(rv)));
  28202         _BCM_OAM_UNLOCK(oc);
  28203         return (rv);
  28204     }
  28205 
  28206     for (index = 0; index < cosq_map_size; index++) {
  28207         rv = bcm_esw_rx_cosq_mapping_get(unit, index, &reasons,
  28208                 &reasons_mask, &int_prio, &int_prio_mask, &packet_type,
  28209                 &packet_type_mask, &cosq);
  28210 
  28211         if (rv == BCM_E_NOT_FOUND) {
  28212             /* Assign first available index */
  28213             rv = BCM_E_NONE;
  28214             if (mpls_lm_dm_index == -1) {
  28215                 mpls_lm_dm_index = index;
  28216                 break;
  28217             }
  28218         }
  28219         if (BCM_FAILURE(rv)) {
  28220             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)"
  28221             " Error:hw init. cosq map get %s.\n"), unit, bcm_errmsg(rv)));
  28222             _BCM_OAM_UNLOCK(oc);
  28223             return (rv);
  28224         }
  28225     }
  28226 
  28227     if (mpls_lm_dm_index == -1) {
  28228         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)"
  28229         " Error:hw init. map_index error %s.\n"), unit, bcm_errmsg(rv)));
  28230         _BCM_OAM_UNLOCK(oc);
  28231         return (BCM_E_FULL);
  28232     }
  28233 
  28234     BCM_RX_REASON_CLEAR_ALL(reasons);
  28235     BCM_RX_REASON_SET(reasons, bcmRxReasonOAMMplsLmDm); /* MPLS_LM_DM */
  28236 
  28237     rv = bcm_esw_rx_cosq_mapping_set(unit, mpls_lm_dm_index,
  28238                                      reasons, reasons,
  28239                                      0, 0, /* Any Internal Prio */
  28240                                      0, 0, /* Any packet type */
  28241                                      oc->mpls_lm_dm_cpu_cosq);
  28242     if(BCM_FAILURE(rv)) {
  28243         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)"
  28244         " Error:hw init. cosq map set %s.\n"), unit, bcm_errmsg(rv)));
  28245         _BCM_OAM_UNLOCK(oc);
  28246         return (rv);
  28247     }
  28248     oc->mpls_lm_dm_cosq_index = mpls_lm_dm_index;
  28249 
  28250     _BCM_OAM_UNLOCK(oc);
  28251     return (rv);
  28252 }
  28253 
  28254 #endif /* BCM_METROLITE_SUPPORT */
  28255 /*
  28256  * Function:
  28257  *      _bcm_sb2_oam_mpls_lm_dm_msg_send_receive
  28258  * Purpose:
  28259  *      Sends given MPLS_LM_DM control message to the uController.
  28260  *      Receives and verifies expected reply.
  28261  *      Performs DMA operation if required.
  28262  * Parameters:
  28263  *      unit        - (IN) Unit number.
  28264  *      s_subclass  - (IN) MPLS message subclass.
  28265  *      s_len       - (IN) Value for 'len' field in message struct.
  28266  *                         Length of buffer to flush if DMA send is required.
  28267  *      s_data      - (IN) Value for 'data' field in message struct.
  28268  *                         Ignored if message requires a DMA send/receive
  28269  *                         operation.
  28270  *      r_subclass  - (IN) Expected reply message subclass.
  28271  *      r_len       - (OUT) Returns value in 'len' reply message field.
  28272  * Returns:
  28273  *      BCM_E_XXX
  28274  * Notes:
  28275  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  28276  *       can take any arbitrary data.
  28277  *
  28278  *     MPLS_LM_DM Long Control message:
  28279  *     - MPLS_LM_DM control messages that require send/receive of information
  28280  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  28281  *       use DMA operations to exchange information (long control message).
  28282  *
  28283  *     - MPLS_LM_DM convention for long control messages for
  28284  *        'mos_msg_data_t' fields:
  28285  *          'len'    size of the DMA buffer to send to uController
  28286  *          'data'   physical DMA memory address to send or receive
  28287  *
  28288  *      DMA Operations:
  28289  *      - DMA read/write operation is performed when a long MPLS_LM_DM control
  28290  *        message is involved.
  28291  *
  28292  *      - Messages that require DMA operation (long control message)
  28293  *        is indicated by MOS_MSG_DMA_MSG().
  28294  *
  28295  *      - Callers must 'pack' and 'unpack' corresponding information into/from
  28296  *        DMA buffer indicated by OAM_INFO(unit)->mpls_lm_dm_dma_buffer.
  28297  */
  28298 STATIC int
  28299 _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(int unit, 
  28300     uint8 s_subclass, uint16 s_len, uint32 s_data, uint8 r_subclass, 
  28301     uint16 *r_len)
  28302 {
  28303     int rv;
  28304     _bcm_oam_control_t *oc;
  28305     mos_msg_data_t send, reply;
  28306     uint8 *dma_buffer;
  28307     int dma_buffer_len;
  28308     uint32 uc_rv;
  28309 
  28310     /* Lock already taken by the calling routine. */
  28311     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  28312 
  28313     sal_memset(&send, 0, sizeof(send));
  28314     sal_memset(&reply, 0, sizeof(reply));
  28315     send.s.mclass = MOS_MSG_CLASS_MPLS_LM_DM;
  28316     send.s.subclass = s_subclass;
  28317     send.s.len = bcm_htons(s_len);
  28318 
  28319     /*
  28320      * Set 'data' to DMA buffer address if a DMA operation is
  28321      * required for send or receive.
  28322      */
  28323     dma_buffer = oc->mpls_lm_dm_dma_buffer;
  28324     dma_buffer_len = oc->mpls_lm_dm_dma_buffer_len;
  28325     if (MOS_MSG_DMA_MSG(s_subclass) ||
  28326         MOS_MSG_DMA_MSG(r_subclass)) {
  28327         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  28328     } else {
  28329         send.s.data = bcm_htonl(s_data);
  28330     }
  28331 
  28332     /* Flush DMA memory */
  28333     if (MOS_MSG_DMA_MSG(s_subclass)) {
  28334         soc_cm_sflush(unit, dma_buffer, s_len);
  28335     }
  28336 
  28337     /* Invalidate DMA memory to read */
  28338     if (MOS_MSG_DMA_MSG(r_subclass)) {
  28339         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  28340     }
  28341 
  28342     rv = soc_cmic_uc_msg_send_receive(unit, oc->mpls_lm_dm_uc_num,
  28343                                       &send, &reply,
  28344                                       _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS);
  28345 
  28346     /* Check reply class, subclass */
  28347     if ((rv != SOC_E_NONE) ||
  28348         (reply.s.mclass != MOS_MSG_CLASS_MPLS_LM_DM) ||
  28349         (reply.s.subclass != r_subclass)) {
  28350         return (BCM_E_INTERNAL);
  28351     }
  28352 
  28353     /* Convert MPLS_LM_DM uController error code to BCM */
  28354     uc_rv = bcm_ntohl(reply.s.data);
  28355     switch(uc_rv) {
  28356     case SHR_MPLS_LM_DM_UC_E_NONE:
  28357         rv = BCM_E_NONE;
  28358         break;
  28359     case SHR_MPLS_LM_DM_UC_E_INTERNAL:
  28360         rv = BCM_E_INTERNAL;
  28361         break;
  28362     case SHR_MPLS_LM_DM_UC_E_MEMORY:
  28363         rv = BCM_E_MEMORY;
  28364         break;
  28365     case SHR_MPLS_LM_DM_UC_E_PARAM:
  28366         rv = BCM_E_PARAM;
  28367         break;
  28368     case SHR_MPLS_LM_DM_UC_E_RESOURCE:
  28369         rv = BCM_E_RESOURCE;
  28370         break;
  28371     case SHR_MPLS_LM_DM_UC_E_EXISTS:
  28372         rv = BCM_E_EXISTS;
  28373         break;
  28374     case SHR_MPLS_LM_DM_UC_E_NOT_FOUND:
  28375         rv = BCM_E_NOT_FOUND;
  28376         break;
  28377     case SHR_MPLS_LM_DM_UC_E_INIT:
  28378         rv = BCM_E_INIT;
  28379         break;
  28380     case SHR_MPLS_LM_DM_UC_E_UNAVAIL:
  28381         rv = BCM_E_UNAVAIL;
  28382         break;
  28383     default:
  28384         rv = BCM_E_INTERNAL;
  28385         break;
  28386     }
  28387         
  28388     *r_len = bcm_ntohs(reply.s.len);
  28389 
  28390     return (rv);
  28391 }
  28392 
  28393 STATIC uint8 *
  28394 _bcm_sb2_oam_mpls_lm_dm_ach_header_pack(uint8 *buffer, 
  28395                                                           _ach_header_t *ach)
  28396 {
  28397     uint32  tmp;
  28398 
  28399     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
  28400         (ach->reserved << 16) | ach->channel_type;
  28401 
  28402     _SHR_PACK_U32(buffer, tmp);
  28403 
  28404     return (buffer);
  28405 }
  28406 
  28407 STATIC uint8 *
  28408 _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(uint8 *buffer, 
  28409                                                         _mpls_label_t *mpls)
  28410 {
  28411     uint32  tmp;
  28412 
  28413     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
  28414         ((mpls->s & 0x1) << 8) | mpls->ttl;
  28415     _SHR_PACK_U32(buffer, tmp);
  28416 
  28417     return (buffer);
  28418 }
  28419 
  28420 STATIC uint8 *
  28421 _bcm_sb2_oam_mpls_lm_dm_l2_header_pack(
  28422     bcm_oam_endpoint_type_t type, uint8 *buffer, _l2_header_t *l2)
  28423 {
  28424     uint32  tmp;
  28425     int     i;
  28426 
  28427     for (i = 0; i < 6; i++) {
  28428         _SHR_PACK_U8(buffer, l2->dst_mac[i]);
  28429     }
  28430 
  28431     for (i = 0; i < 6; i++) {
  28432         _SHR_PACK_U8(buffer, l2->src_mac[i]);
  28433     }
  28434 
  28435     /* Vlan Tag tpid = 0 indicates untagged */
  28436     if (0 != l2->vlan_tag.tpid) {
  28437         tmp =  (l2->vlan_tag.tpid             << 16) |
  28438               ((l2->vlan_tag.tci.prio & 0x7)  << 13) |
  28439               ((l2->vlan_tag.tci.cfi  & 0x1)  << 12) |
  28440                (l2->vlan_tag.tci.vid  & 0xfff);
  28441         _SHR_PACK_U32(buffer, tmp);
  28442     }
  28443 
  28444     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
  28445     if (0 != l2->vlan_tag_inner.tpid) {
  28446         tmp = (l2->vlan_tag_inner.tpid             << 16) |
  28447              ((l2->vlan_tag_inner.tci.prio & 0x7)  << 13) |
  28448              ((l2->vlan_tag_inner.tci.cfi  & 0x1)  << 12) |
  28449               (l2->vlan_tag_inner.tci.vid  & 0xfff);
  28450         _SHR_PACK_U32(buffer, tmp);
  28451     }
  28452 
  28453     _SHR_PACK_U16(buffer, l2->etype);
  28454 
  28455     return (buffer);
  28456 }
  28457 
  28458 STATIC int
  28459 _bcm_sb2_oam_mpls_lm_dm_ach_header_get(uint32 packet_flags, 
  28460     _ach_header_t *ach)
  28461 {
  28462     sal_memset(ach, 0, sizeof(*ach));
  28463 
  28464     ach->f_nibble = SHR_MPLS_LM_DM_ACH_FIRST_NIBBLE;
  28465     ach->version  = SHR_MPLS_LM_DM_ACH_VERSION;
  28466     ach->reserved = 0;
  28467 
  28468     ach->channel_type = (packet_flags & _MPLS_LM_DM_ACH_TYPE_MASK);
  28469 
  28470     return (BCM_E_NONE);
  28471 }
  28472 
  28473 STATIC int
  28474 _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(uint32 label, uint8 exp, 
  28475     uint8 s, uint8 ttl, _mpls_label_t *mpls)
  28476 {
  28477     sal_memset(mpls, 0, sizeof(*mpls));
  28478 
  28479     mpls->label = label;
  28480     mpls->exp   = exp;
  28481     mpls->s     = s;
  28482     if(ttl)
  28483         mpls->ttl   = ttl;
  28484     else
  28485         mpls->ttl   = _MPLS_LM_DM_MPLS_DFLT_TTL;
  28486 
  28487     return (BCM_E_NONE);
  28488 }
  28489 
  28490 STATIC int
  28491 _bcm_sb2_oam_mpls_lm_dm_mpls_gal_label_get(_mpls_label_t *mpls)
  28492 {
  28493     return _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(SHR_MPLS_LM_DM_MPLS_GAL_LABEL,
  28494                                                   0, 1, 1, mpls);
  28495 }
  28496 
  28497 STATIC int
  28498 _bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get(
  28499     _mpls_label_t *mpls)
  28500 {
  28501     return _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(
  28502                 SHR_MPLS_LM_DM_MPLS_ROUTER_ALERT_LABEL, 0, 0, 0, mpls);
  28503 }
  28504 
  28505 STATIC int
  28506 _bcm_sb2_oam_mpls_lm_dm_mpls_labels_get(int unit, 
  28507     _bcm_oam_hash_data_t *h_data_p, uint32 packet_flags, int max_count, 
  28508     _mpls_label_t *pw_label, _mpls_label_t *mpls, int *mpls_count, 
  28509     bcm_if_t *l3_intf_id)
  28510 {
  28511     int count = 0;
  28512     bcm_l3_egress_t l3_egress;
  28513     bcm_mpls_port_t mpls_port;
  28514     bcm_mpls_egress_label_t label_array[_MPLS_LM_DM_MPLS_MAX_LABELS];
  28515     bcm_mpls_egress_label_t tmp_label;
  28516     int label_count = 0;
  28517     int i = 0;
  28518 
  28519      /* Get L3 objects */
  28520     bcm_l3_egress_t_init(&l3_egress);
  28521     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  28522         return (BCM_E_PARAM);
  28523     }
  28524 
  28525     /* Look for a tunnel associated with this interface */
  28526     if (BCM_SUCCESS
  28527         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
  28528                                            _MPLS_LM_DM_MPLS_MAX_LABELS,
  28529                                            label_array, &label_count))) {
  28530         /* We need to sawp the if 2 labels configured in tunnel initiator as
  28531            label in 2nd element should be put first during pkt construction */
  28532         if (label_count == 2) {
  28533             sal_memcpy(&tmp_label, &label_array[0], sizeof(tmp_label));
  28534             sal_memcpy(&label_array[0], &label_array[1], sizeof(tmp_label));
  28535             sal_memcpy(&label_array[1], &tmp_label, sizeof(tmp_label));
  28536         }
  28537 
  28538         /* Add VRL Label */
  28539         if MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) {
  28540             if ( (l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
  28541                  (label_count < _MPLS_LM_DM_MPLS_MAX_LABELS) ) {
  28542                 label_array[label_count].label = l3_egress.mpls_label;
  28543                 label_array[label_count].exp = l3_egress.mpls_exp;
  28544                 label_array[label_count].ttl = l3_egress.mpls_ttl;
  28545                 label_count++;
  28546             }
  28547 
  28548             /* Traverse through Label stack and match on control label, this
  28549                label should be the one just above GAL in the label stack, any
  28550                following labels should not be added */
  28551             for (i=0; i<label_count; i++) {
  28552                 if (label_array[i].label == h_data_p->egr_label) {
  28553                     if (h_data_p->egr_label_exp != 0) {
  28554                         /* Set the EXP for control Label */
  28555                         label_array[i].exp = h_data_p->egr_label_exp;
  28556                     }
  28557                     if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  28558                         (h_data_p->egr_label_ttl != 0)) {
  28559                         /* Set the TTL for control Label */
  28560                         label_array[i].ttl = h_data_p->egr_label_ttl;
  28561                     }
  28562                     label_count = i+1;
  28563                     break;
  28564                 }
  28565             }
  28566 
  28567         }
  28568 
  28569         for (i = 0; (i < label_count) && (count < max_count); i++) {
  28570             _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(label_array[i].label,
  28571                                        label_array[i].exp,
  28572                                        0,
  28573                                        label_array[i].ttl,
  28574                                        &mpls[count++]);
  28575         }
  28576     }
  28577 
  28578 
  28579         /* MPLS Router Alert */
  28580     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  28581         _bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get(&mpls[count++]);
  28582     }
  28583 
  28584     /* Use GPORT to resolve interface */
  28585     if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
  28586         /* Get mpls port and label info */
  28587         bcm_mpls_port_t_init(&mpls_port);
  28588         mpls_port.mpls_port_id = h_data_p->gport;
  28589         if (BCM_FAILURE
  28590             (bcm_esw_mpls_port_get(unit, h_data_p->vpn,
  28591                                    &mpls_port))) {
  28592             return (BCM_E_PARAM);
  28593         } else {
  28594             if (h_data_p->type == bcmOAMEndpointTypeMplsLmDmPw &&
  28595                 h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  28596                 mpls_port.egress_label.ttl = 0x1;
  28597             }
  28598 
  28599             _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(mpls_port.egress_label.label,
  28600                 mpls_port.egress_label.exp, 0, mpls_port.egress_label.ttl, 
  28601                 &mpls[count++]);
  28602         }
  28603     }
  28604 
  28605     /* Set Bottom of Stack if there is no GAL label */
  28606     if (!(packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL)) {
  28607         mpls[count-1].s = 1;
  28608     }
  28609 
  28610     *mpls_count = count;
  28611 
  28612     return (BCM_E_NONE);
  28613 
  28614 }
  28615 
  28616 STATIC int
  28617 _bcm_sb2_oam_mpls_lm_dm_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  28618                                 bcm_port_t port, uint16 etype,
  28619                                 _l2_header_t *l2)
  28620 {
  28621     uint16 tpid;
  28622     bcm_l3_egress_t l3_egress;
  28623     bcm_l3_intf_t l3_intf;
  28624     bcm_vlan_control_vlan_t vc;
  28625     int tpid_select;
  28626     bcm_pbmp_t pbmp, ubmp;
  28627     bcm_port_t local_port;
  28628 
  28629     sal_memset(l2, 0, sizeof(*l2));
  28630 
  28631     if (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
  28632         /* Get L3 interfaces */
  28633         bcm_l3_egress_t_init(&l3_egress);
  28634         bcm_l3_intf_t_init(&l3_intf);
  28635 
  28636         if (BCM_FAILURE
  28637                 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  28638             return (BCM_E_PARAM);
  28639         }
  28640 
  28641         l3_intf.l3a_intf_id = l3_egress.intf;
  28642         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  28643             return (BCM_E_PARAM);
  28644         }
  28645 
  28646         /* Get TPID */
  28647         BCM_IF_ERROR_RETURN(
  28648                        bcm_esw_vlan_control_port_get(unit,
  28649                                                      port,
  28650                                                      bcmVlanPortOuterTpidSelect,
  28651                                                      &tpid_select));
  28652         if (tpid_select == BCM_PORT_OUTER_TPID) {
  28653             BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
  28654         } else {
  28655             BCM_IF_ERROR_RETURN(
  28656                      bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
  28657             tpid = vc.outer_tpid;
  28658         }
  28659 
  28660         sal_memcpy(l2->dst_mac, l3_egress.mac_addr, sizeof(bcm_mac_t));
  28661         sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, sizeof(bcm_mac_t));
  28662         l2->vlan_tag.tpid     = tpid;
  28663         l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  28664         l2->vlan_tag.tci.cfi  = 0;
  28665         l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
  28666 
  28667         BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
  28668                                                   l2->vlan_tag.tci.vid,
  28669                                                   &pbmp,
  28670                                                   &ubmp));
  28671 
  28672         if (BCM_E_NONE == bcm_esw_port_local_get(unit, port, &local_port)) {
  28673             if (BCM_PBMP_MEMBER(ubmp, local_port)) {
  28674                 l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
  28675             }
  28676         }
  28677 
  28678         if (l3_intf.l3a_inner_vlan != 0) {
  28679             BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
  28680             l2->vlan_tag_inner.tpid     = tpid;
  28681             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  28682             l2->vlan_tag_inner.tci.cfi  = 0;
  28683             l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
  28684         }
  28685 
  28686     }else {
  28687         sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, sizeof(bcm_mac_t));
  28688         sal_memcpy(l2->src_mac, h_data_p->src_mac_address, sizeof(bcm_mac_t));
  28689         if((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) ||
  28690            (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) ||
  28691            (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)) {
  28692             l2->vlan_tag.tpid     = h_data_p->outer_tpid;
  28693             l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  28694             l2->vlan_tag.tci.cfi  = 0;
  28695             l2->vlan_tag.tci.vid  = h_data_p->vlan;
  28696         }
  28697         if((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) ||
  28698            (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)){
  28699             l2->vlan_tag_inner.tpid     = h_data_p->inner_tpid;
  28700             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  28701             l2->vlan_tag_inner.tci.cfi  = 0;
  28702             l2->vlan_tag_inner.tci.vid  = h_data_p->inner_vlan;
  28703         }
  28704         etype = SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST;
  28705     }
  28706     l2->etype = etype;
  28707 
  28708     return (BCM_E_NONE);
  28709 }
  28710 
  28711 /*
  28712  * Function:
  28713  *      _bcm_sb2_oam_mpls_lm_dm_encap_build_pack
  28714  * Purpose:
  28715  *      Builds and packs the MPLS_LM_DM packet encapsulation for a given
  28716  *      MPLS_LM_DM tunnel type.
  28717  * Parameters:
  28718  *      unit            - (IN) Unit number.
  28719  *      port            - (IN) Port.
  28720  *      endpoint_config - (IN/OUT) Pointer to MPLS_LM_DM endpoint structure.
  28721  *      packet_flags    - (IN) Flags for building packet.
  28722  *      buffer          - (OUT) Buffer returning BHH encapsulation.
  28723  * Returns:
  28724  *      BCM_E_XXX
  28725  * Notes:
  28726  *      The returning MPLS_LM_DM encapsulation includes only all the
  28727  *      encapsulation headers/labels and does not include
  28728  *      the MPLS_LM_DM control packet.
  28729  */
  28730 STATIC int
  28731 _bcm_sb2_oam_mpls_lm_dm_encap_build_pack(int unit, 
  28732     bcm_port_t port, _bcm_oam_hash_data_t *h_data_p, uint32 packet_flags,
  28733     uint8 *buffer, uint16 *encap_length)
  28734 {
  28735     uint8          *cur_ptr = buffer;
  28736     uint16         etype = 0;
  28737     bcm_if_t       l3_intf_id = -1;
  28738     _ach_header_t  ach;
  28739     _mpls_label_t  mpls_gal;
  28740     _mpls_label_t  mpls_r_alert;
  28741     _mpls_label_t  mpls_labels[_MPLS_LM_DM_MPLS_MAX_LABELS];
  28742     _mpls_label_t  pw_label;
  28743     int            mpls_count = 0;
  28744     _l2_header_t   l2;
  28745     int i;
  28746 
  28747 
  28748     /*
  28749      * Get necessary headers/labels information.
  28750      *
  28751      * Following order is important since some headers/labels
  28752      * may depend on previous header/label information.
  28753      */
  28754     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_G_ACH) {
  28755         BCM_IF_ERROR_RETURN
  28756         (_bcm_sb2_oam_mpls_lm_dm_ach_header_get(packet_flags, &ach));
  28757     }
  28758 
  28759     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) {
  28760         BCM_IF_ERROR_RETURN
  28761         (_bcm_sb2_oam_mpls_lm_dm_mpls_gal_label_get(&mpls_gal));
  28762     }
  28763 
  28764     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  28765         BCM_IF_ERROR_RETURN
  28766         (_bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get(&mpls_r_alert));
  28767     }
  28768 
  28769     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) {
  28770         etype = SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST;
  28771         BCM_IF_ERROR_RETURN
  28772         (_bcm_sb2_oam_mpls_lm_dm_mpls_labels_get(unit, h_data_p, packet_flags,
  28773             _MPLS_LM_DM_MPLS_MAX_LABELS, &pw_label, mpls_labels, &mpls_count, 
  28774             &l3_intf_id));
  28775     }
  28776 
  28777     /* Always build L2 Header */
  28778     BCM_IF_ERROR_RETURN
  28779         (_bcm_sb2_oam_mpls_lm_dm_l2_header_get(unit, h_data_p, port, etype, 
  28780                                                &l2));
  28781 
  28782     /*
  28783      * Pack header/labels into given buffer (network packet format).
  28784      *
  28785      * Following packing order must be followed to correctly
  28786      * build the packet encapsulation.
  28787      */
  28788     cur_ptr = buffer;
  28789 
  28790     /* L2 Header is always present */
  28791     cur_ptr = _bcm_sb2_oam_mpls_lm_dm_l2_header_pack(h_data_p->type, cur_ptr, 
  28792                                                      &l2);
  28793 
  28794     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) {
  28795         for (i = 0;i < mpls_count;i++) {
  28796             cur_ptr = _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(cur_ptr, 
  28797                                                               &mpls_labels[i]);
  28798         }
  28799     }
  28800 
  28801     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) {    
  28802         cur_ptr = _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(cur_ptr, &mpls_gal);
  28803     }
  28804 
  28805     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_G_ACH) {
  28806         cur_ptr = _bcm_sb2_oam_mpls_lm_dm_ach_header_pack(cur_ptr, &ach);
  28807     }
  28808 
  28809 
  28810     /* Set MPLS_LM_DM encapsulation length */
  28811     *encap_length = cur_ptr - buffer;
  28812 
  28813     return (BCM_E_NONE);
  28814 }
  28815 
  28816 #ifdef _MPLS_LM_DM_DEBUG_DUMP
  28817 void
  28818 _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(uint8 *buffer, int length)
  28819 {
  28820     int i;
  28821 
  28822     LOG_CLI((BSL_META("\nEncapsulation (length=%d):\n"), length));
  28823 
  28824     for (i = 0; i < length; i++) {
  28825         if ((i % 16) == 0) {
  28826             LOG_CLI((BSL_META("\n")));
  28827         }
  28828         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  28829     }
  28830 
  28831     LOG_CLI((BSL_META("\n")));
  28832     return;
  28833 }
  28834 #endif
  28835 
  28836 /*
  28837  * Function:
  28838  *      _bcm_sb2_oam_mpls_lm_dm_encap_create
  28839  * Purpose:
  28840  *      Creates a MPLS_LM_DM packet encapsulation.
  28841  * Parameters:
  28842  *      unit            - (IN) Unit number.
  28843  *      port_id         - (IN) Port.
  28844  *      endpoint_config - (IN/OUT) Pointer to MPLS_LM_DM endpoint structure.
  28845  *      encap_data      - (OUT) Buffer returning MPLS_LM_DM encapsulation.
  28846  * Returns:
  28847  *      BCM_E_XXX
  28848  * Notes:
  28849  *      The returning MPLS_LM_DM encapsulation buffer includes all the
  28850  *      corresponding headers/labels EXCEPT for the MPLS_LM_DM control packet.
  28851  */
  28852 STATIC int
  28853 _bcm_sb2_oam_mpls_lm_dm_encap_create(int unit,  _bcm_oam_hash_data_t *h_data_p,
  28854     bcm_port_t port, uint8 *encap_data, uint16 *encap_length, uint32 packet_flags)
  28855 {
  28856     
  28857     /*
  28858      * Get MPLS_LM_DM encapsulation packet format flags
  28859      *
  28860      * Also, perform the following for each MPLS_LM_DM tunnel type:
  28861      * - Check for valid parameter values
  28862      * - Set specific values required by the MPLS_LM_DM tunnel definition 
  28863      *   (e.g. such as ttl=1,...)
  28864      */
  28865     switch (h_data_p->type) {
  28866     case bcmOAMEndpointTypeMplsLmDmLsp:
  28867         packet_flags |=
  28868             (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP |
  28869              _MPLS_LM_DM_ENCAP_PKT_GAL |
  28870              _MPLS_LM_DM_ENCAP_PKT_G_ACH);
  28871         break;
  28872 
  28873     case bcmOAMEndpointTypeMplsLmDmPw:
  28874         switch(h_data_p->vccv_type) {
  28875 
  28876         case bcmOamBhhVccvChannelAch:
  28877             packet_flags |=
  28878                 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP |
  28879                  _MPLS_LM_DM_ENCAP_PKT_PW |
  28880                  _MPLS_LM_DM_ENCAP_PKT_G_ACH);
  28881         break;
  28882 
  28883         case bcmOamBhhVccvRouterAlert:
  28884             packet_flags |=
  28885                 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP |
  28886                  _MPLS_LM_DM_ENCAP_PKT_PW |
  28887                  _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT |
  28888                  _MPLS_LM_DM_ENCAP_PKT_G_ACH); 
  28889             break;
  28890 
  28891         case bcmOamBhhVccvTtl:
  28892             packet_flags |=
  28893                 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP |
  28894                  _MPLS_LM_DM_ENCAP_PKT_PW |
  28895                  _MPLS_LM_DM_ENCAP_PKT_G_ACH); 
  28896             break;
  28897 
  28898         case bcmOamBhhVccvGal13:
  28899             packet_flags |=
  28900                 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP |
  28901                  _MPLS_LM_DM_ENCAP_PKT_PW |
  28902                  _MPLS_LM_DM_ENCAP_PKT_GAL  |
  28903                  _MPLS_LM_DM_ENCAP_PKT_G_ACH);
  28904             break;
  28905 
  28906     default:
  28907         return (BCM_E_PARAM);
  28908         break;
  28909     }
  28910         break;
  28911 
  28912     case bcmOAMEndpointTypeMplsLmDmSectionPort:
  28913     case bcmOAMEndpointTypeMplsLmDmSectionInnervlan:
  28914     case bcmOAMEndpointTypeMplsLmDmSectionOuterVlan:
  28915     case bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan:
  28916         packet_flags |=
  28917             (_MPLS_LM_DM_ENCAP_PKT_GAL |
  28918              _MPLS_LM_DM_ENCAP_PKT_G_ACH);
  28919         break;
  28920     default:
  28921         return (BCM_E_PARAM);
  28922     }
  28923 
  28924     /* Build header/labels and pack in buffer */
  28925     BCM_IF_ERROR_RETURN
  28926         (_bcm_sb2_oam_mpls_lm_dm_encap_build_pack(unit, port, 
  28927                             h_data_p, packet_flags, encap_data, encap_length));
  28928                    
  28929 #ifdef _MPLS_LM_DM_DEBUG_DUMP
  28930     _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(encap_data, *encap_length);
  28931 #endif
  28932 
  28933 
  28934     return (BCM_E_NONE);
  28935 }
  28936 
  28937 /*
  28938  * Function:
  28939  *     _bcm_sb2_mpls_lm_dm_get_tx_gport
  28940  * Purpose:
  28941  *        Get the port where pkts need to be sent
  28942  * Parameters:
  28943  *     unit - Device unit number
  28944  * Returns:
  28945  *     None
  28946  */
  28947 STATIC int
  28948 _bcm_sb2_mpls_lm_dm_get_tx_gport(int unit, _bcm_oam_hash_data_t *h_data_p,
  28949                                  bcm_gport_t *tx_gport)
  28950 {
  28951 
  28952     bcm_gport_t         gport;
  28953     bcm_trunk_t         trunk;
  28954     bcm_l3_egress_t     l3_egress;
  28955     bcm_trunk_info_t    trunk_info;
  28956     bcm_trunk_member_t *member_array = NULL;
  28957     int                 member_count = 0;
  28958     int                 rv = BCM_E_NONE;
  28959 
  28960     if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) {
  28961         gport = h_data_p->gport;
  28962     } else {
  28963         bcm_l3_egress_t_init(&l3_egress);
  28964         BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, h_data_p->egress_if,
  28965                                                   &l3_egress));
  28966 
  28967         if (l3_egress.flags & BCM_L3_TGID) {
  28968             BCM_GPORT_TRUNK_SET(gport, l3_egress.trunk);
  28969         } else {
  28970             BCM_GPORT_MODPORT_SET(gport, l3_egress.module, l3_egress.port);
  28971         }
  28972     }
  28973 
  28974     if (BCM_GPORT_IS_TRUNK(gport)) {
  28975         trunk = BCM_GPORT_TRUNK_GET(gport);
  28976         BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, trunk, NULL, 0,
  28977                                               NULL, &member_count));
  28978         if (0 == member_count) {
  28979             /* No members have been added to the trunk group yet */
  28980             return BCM_E_PARAM;
  28981         }
  28982         /* Check if the input trunk_index is valid. */
  28983         if (h_data_p->trunk_index >= member_count) {
  28984             return BCM_E_PARAM;
  28985         }
  28986 
  28987         _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
  28988                        sizeof(bcm_trunk_member_t) * member_count,
  28989                        "Trunk info");
  28990         if (NULL == member_array) {
  28991             return (BCM_E_MEMORY);
  28992         }
  28993 
  28994         /* Get Trunk Info for the Trunk ID. */
  28995         rv = bcm_esw_trunk_get(unit, trunk, &trunk_info, member_count,
  28996                                member_array, &member_count);
  28997         if (BCM_FAILURE(rv)) {
  28998             sal_free(member_array);
  28999             return (rv);
  29000         }
  29001 
  29002         *tx_gport = member_array[h_data_p->trunk_index].gport;
  29003         sal_free(member_array);
  29004     } else {
  29005         *tx_gport = gport;
  29006     }
  29007 
  29008     return BCM_E_NONE;
  29009 }
  29010 
  29011 STATIC int
  29012 _bcm_sb2_mpls_lm_dm_loss_add(int unit, _bcm_oam_hash_data_t *h_data_p, 
  29013     bcm_oam_loss_t *loss_p) 
  29014 {
  29015     _bcm_oam_control_t *oc = NULL;
  29016     uint8 *buffer_p = NULL;
  29017     uint8 *buffer_after_pack_p = NULL;
  29018     uint16 buffer_len = 0;
  29019     uint16 reply_len = 0;
  29020     uint32 session_id;
  29021     soc_olp_l2_hdr_t olp_l2_header;
  29022     soc_olp_tx_hdr_t olp_oam_header;
  29023     mpls_lm_dm_sdk_msg_ctrl_loss_add_t loss_add_msg;
  29024     int my_mod_id = 0;
  29025     int cpu_dglp = 0; 
  29026     int cpu_port = 0;
  29027     int rv = 0;
  29028     uint32 packet_flags = 0;
  29029     uint32 counter_pool = 0; 
  29030     int i;
  29031     bcm_gport_t gport;
  29032     bcm_oam_endpoint_info_t ep_info;
  29033 
  29034     /* Get OAM control pointer */
  29035     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29036 
  29037     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id));
  29038 
  29039     /* Initialize the Message structure */
  29040     sal_memset(&loss_add_msg, 0, sizeof(loss_add_msg));
  29041 
  29042     /* Validation Checks */
  29043     /* ----------------- */
  29044     /* Check if loss already added */
  29045     if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) {
  29046         return BCM_E_EXISTS;
  29047     }
  29048     /* Check for combined mode */
  29049     if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  29050         if (loss_p->flags & BCM_OAM_LOSS_SLM) {
  29051             /* User wants to configure ILM+DM */
  29052             /* User can set 0 or more counters */ 
  29053             if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) ||
  29054                  (loss_p->lm_counter_size < 0) ) {
  29055                 return BCM_E_PARAM;
  29056             }
  29057             packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM;
  29058             loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM;
  29059         } else {
  29060             /* User wants to configure DLM+DM */
  29061             /* User must set atleast one counter action */ 
  29062             if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) ||
  29063                  (loss_p->lm_counter_size <= 0) ) {
  29064                 return BCM_E_PARAM;
  29065             }
  29066             packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DLM_DM;
  29067             loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM;
  29068         }
  29069         loss_add_msg.flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED;
  29070     } else {
  29071 
  29072         if (loss_p->flags & BCM_OAM_LOSS_SLM) {
  29073             /* User wants to configure ILM */
  29074             /* User can set 0 or more counters */
  29075             if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) ||
  29076                  (loss_p->lm_counter_size < 0) ) {
  29077                 return BCM_E_PARAM;
  29078             }
  29079             /* Set the ACH type in the packet flags for Pkt Encap construction */
  29080             packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_ILM;
  29081             loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM;
  29082             
  29083         } else {
  29084             /* User wants to configure DLM */
  29085             /* User must set atleast one counter action */ 
  29086             if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) ||
  29087                  (loss_p->lm_counter_size <= 0) ) {
  29088                 return BCM_E_PARAM;
  29089             }
  29090             packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DLM;
  29091             loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM;
  29092             
  29093         }
  29094     }
  29095     /* Active or Passive mode */
  29096     if (!(loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)) {
  29097         loss_add_msg.flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG;
  29098     }
  29099     
  29100     /* Single or dual ended mode */
  29101     if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) {
  29102         loss_add_msg.flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG;
  29103     }
  29104 
  29105     /* Get byte or frame count, counter size if not SLM */
  29106     if (!(loss_p->flags & BCM_OAM_LOSS_SLM)) {
  29107         rv = bcm_sb2_oam_endpoint_get(unit, loss_p->id, &ep_info);
  29108         if (BCM_FAILURE(rv)) {
  29109             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29110                 " EP info get failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29111                 bcm_errmsg(rv)));
  29112             return (rv);
  29113         }
  29114         if (ep_info.lm_ctr_type == bcmOamLmCounterTypeByte) {
  29115             loss_add_msg.flags |= SHR_MPLS_LM_DM_BYTE_COUNT_FLAG;
  29116 
  29117             if (ep_info.lm_ctr_sample_size == bcmOamLmCounterSize64Bit) {
  29118                 if (loss_add_msg.flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  29119                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM "
  29120                     "(unit %d) Error: Combined mode not supported with 64-bit "
  29121                     "counter\n"), unit));
  29122 
  29123                     return BCM_E_PARAM;
  29124                 }
  29125                 loss_add_msg.flags |= SHR_MPLS_LM_DM_64_BIT_FLAG;
  29126             }
  29127         }
  29128     }
  29129 
  29130     /* Reserve and program session Id for this EP */
  29131     /* ------------------------------------------ */
  29132     if (h_data_p->lm_dm_uc_session_id == 0 ) {
  29133         rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool, 
  29134                                    (shr_idxres_element_t *)&session_id);
  29135 
  29136         if (BCM_FAILURE(rv)) {
  29137             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29138                 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 
  29139                 bcm_errmsg(rv)));
  29140             return (rv);
  29141         }
  29142 
  29143         /* Program the session Id in the H/w table */
  29144         rv = soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 
  29145                                     MA_PTRf, session_id);
  29146         if (BCM_FAILURE(rv)) {
  29147             shr_idxres_list_free(oc->mpls_lm_dm_pool, 
  29148                                  (shr_idxres_element_t)session_id);
  29149             return (rv);
  29150         }
  29151         h_data_p->lm_dm_uc_session_id = session_id;
  29152     } else {
  29153         session_id = h_data_p->lm_dm_uc_session_id;
  29154     }
  29155 
  29156     /* Set the session Id in the message structure */
  29157     loss_add_msg.sess_id = session_id;
  29158     
  29159     /* Set the periodicity */
  29160     loss_add_msg.period = loss_p->period;
  29161 
  29162     rv = _bcm_sb2_mpls_lm_dm_get_tx_gport(unit, h_data_p, &gport);
  29163     
  29164     /* Create L2 Encap */
  29165     /* --------------- */
  29166     rv = _bcm_sb2_oam_mpls_lm_dm_encap_create(unit, h_data_p, gport, 
  29167             loss_add_msg.l2_encap_data, &(loss_add_msg.l2_encap_length),
  29168             packet_flags);
  29169     if (BCM_FAILURE(rv)) {
  29170         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29171             " L2 Encap create failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29172             bcm_errmsg(rv)));
  29173         return (rv);
  29174     }    
  29175 
  29176 
  29177     /* Creare OLP L2 Encap & Pack */
  29178     /* -------------------------- */
  29179     cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port);
  29180     _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header);
  29181     /* Pack OLP L2 Encap */
  29182     buffer_p = _bcm_sb2_oam_olp_l2_header_pack(loss_add_msg.olp_encap_data, 
  29183                                                &olp_l2_header);
  29184 
  29185     /* Create OLP OAM Encap & Pack */
  29186     /* --------------------------- */
  29187     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
  29188     /* Set Port number */
  29189     SOC_OLP_TX_PORT(&olp_oam_header)  = BCM_GPORT_MODPORT_PORT_GET(gport);
  29190     SOC_OLP_TX_MODID(&olp_oam_header) = BCM_GPORT_MODPORT_MODID_GET(gport);
  29191 
  29192 
  29193     /* Set Counter indexes */
  29194     loss_add_msg.ctr_size = loss_p->lm_counter_size;
  29195     for (i=0; i< loss_p->lm_counter_size; i++) {
  29196 
  29197         /* Store base id and offset to uKernel for retrieval during get */
  29198         loss_add_msg.ctr_base_id[i] = loss_p->lm_counter_base_id[i];
  29199         loss_add_msg.ctr_offset[i] = loss_p->lm_counter_offset[i];
  29200         loss_add_msg.ctr_action[i] = loss_p->lm_counter_action[i];
  29201         loss_add_msg.ctr_byte_offset[i] = loss_p->lm_counter_byte_offset[i];
  29202 
  29203         /* Counter pool index is 8 bit MSB of 24 bit counter base index */
  29204         counter_pool = (loss_p->lm_counter_base_id[i] & 0xFF000000) >> 24; 
  29205     
  29206         if (counter_pool == 0) {
  29207             SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 
  29208                 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 
  29209                 loss_p->lm_counter_offset[i]; 
  29210             SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 
  29211                                                 loss_p->lm_counter_action[i];
  29212             /* Counter location is Egress */
  29213             SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1;
  29214             SOC_OLP_TX_CTR1_OFF_LM(&olp_oam_header) =
  29215                                         loss_p->lm_counter_byte_offset[i] >> 1;
  29216 
  29217         } 
  29218         if (counter_pool == 1) {
  29219             SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header,
  29220                 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 
  29221                 loss_p->lm_counter_offset[i]); 
  29222             SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 
  29223                                                 loss_p->lm_counter_action[i];
  29224             SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 
  29225             SOC_OLP_TX_CTR2_OFF_LM(&olp_oam_header) =
  29226                                         loss_p->lm_counter_byte_offset[i] >> 1;
  29227         }
  29228         if (counter_pool == 2) {
  29229             SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 
  29230                 (loss_p->lm_counter_base_id[i] & 0x00FFFFFFFF) +
  29231                 loss_p->lm_counter_offset[i]);
  29232             SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 
  29233                                                 loss_p->lm_counter_action[i];
  29234             SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 
  29235             SOC_OLP_TX_CTR3_OFF_LM(&olp_oam_header) =
  29236                                         loss_p->lm_counter_byte_offset[i] >> 1;
  29237         }
  29238     }
  29239 
  29240     /* COUNTER OFFSET in OLP Header = 
  29241      * (L2 Encap + Counter field offset in MPLS_LM_DM OAM Header - 14)/2 
  29242      */
  29243     SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 
  29244         ((loss_add_msg.l2_encap_length + 20) - 14) >> 1;
  29245 
  29246     /* Pack OLP OAM Encap */
  29247     shr_olp_tx_header_pack(buffer_p, &olp_oam_header);
  29248 
  29249 #ifdef _MPLS_LM_DM_DEBUG_DUMP
  29250     _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(loss_add_msg.olp_encap_data, 
  29251                                                         MPLS_LM_DM_OLP_HDR_LEN);
  29252 #endif
  29253     
  29254 
  29255     /* Send Loss Add message */
  29256     /* --------------------- */
  29257     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29258     buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_loss_add_pack(buffer_p, 
  29259                                                                 &loss_add_msg);
  29260     buffer_len = buffer_after_pack_p - buffer_p;
  29261     
  29262     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29263             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD, buffer_len, 0, 
  29264             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD_REPLY,
  29265             &reply_len);
  29266             
  29267     if (BCM_FAILURE(rv)|| (reply_len != 0)) {
  29268         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29269             " Loss Add Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29270             bcm_errmsg(rv)));
  29271         return (rv);
  29272     }    
  29273     
  29274     /* Store the session Id in hash data */
  29275     h_data_p->lm_dm_uc_session_id = session_id;
  29276     oc->mpls_lm_dm_sess_id_ep_id[session_id] = h_data_p->ep_id;
  29277 
  29278     /* Set the packet type in hash data */
  29279     if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  29280         if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) {
  29281             /* Both Loss & Delay have been added */
  29282             (loss_p->flags & BCM_OAM_LOSS_SLM ) ? 
  29283                 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM) :
  29284                 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM);
  29285         } 
  29286     } else {
  29287         (loss_p->flags & BCM_OAM_LOSS_SLM ) ? 
  29288             (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM) :
  29289             (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM);
  29290     }
  29291     h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_LOSS_ADDED;
  29292     loss_p->pm_id = h_data_p->lm_dm_uc_session_id;
  29293     return rv;    
  29294 }
  29295 
  29296 STATIC int
  29297 _bcm_sb2_mpls_lm_dm_delay_add(int unit, _bcm_oam_hash_data_t *h_data_p, 
  29298     bcm_oam_delay_t *delay_p) 
  29299 {
  29300     _bcm_oam_control_t *oc = NULL;
  29301     uint8 *buffer_p = NULL;
  29302     uint8 *buffer_after_pack_p = NULL;
  29303     uint16 buffer_len = 0;
  29304     uint16 reply_len = 0;
  29305     uint32 session_id;
  29306     soc_olp_l2_hdr_t olp_l2_header;
  29307     soc_olp_tx_hdr_t olp_oam_header;
  29308     mpls_lm_dm_sdk_msg_ctrl_delay_add_t delay_add_msg;
  29309     int my_mod_id = 0;
  29310     int cpu_dglp = 0; 
  29311     int cpu_port = 0;
  29312     int rv = 0;
  29313     uint32 packet_flags = 0;
  29314     int skip_l2_encap = 0;
  29315     bcm_gport_t gport;
  29316     uint32 counter_pool = 0; 
  29317     int i;
  29318 
  29319     /* Get OAM control pointer */
  29320     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29321 
  29322     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id));
  29323 
  29324     /* Initialize the Message structure */
  29325     sal_memset(&delay_add_msg, 0, sizeof(delay_add_msg));
  29326 
  29327     /* Validation Checks */
  29328     /* ----------------- */
  29329     /* Check if the DM is already enabled for this EP */
  29330     if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) {
  29331         return BCM_E_EXISTS;
  29332     }
  29333     /* Check if combined mode, in combined mode loss add will determine the ACH
  29334        Header */ 
  29335     if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  29336         skip_l2_encap = 1;
  29337         delay_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED;
  29338     } else {
  29339         /* Set the ACH type in the packet flags for Pkt Encap construction */
  29340         packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DM;
  29341         delay_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM;
  29342     }
  29343     
  29344     /* Active or Passive mode */
  29345     if (!(delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)) {
  29346         delay_add_msg.flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG;
  29347     }
  29348     
  29349     /* Single or dual ended mode */
  29350     if (!(delay_p->flags & BCM_OAM_DELAY_ONE_WAY)) {
  29351         delay_add_msg.flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG;
  29352     }
  29353     
  29354     /* Reserve and program session Id for this EP */
  29355     /* ------------------------------------------ */
  29356     if (h_data_p->lm_dm_uc_session_id == 0 ) {
  29357         rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool, 
  29358                                    (shr_idxres_element_t *)&session_id);
  29359         if (BCM_FAILURE(rv)) {
  29360             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29361                 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 
  29362                 bcm_errmsg(rv)));
  29363             return (rv);
  29364         }
  29365 
  29366         /* Program the session Id in the H/w table */
  29367         rv = soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 
  29368                                     MA_PTRf, session_id);
  29369         if (BCM_FAILURE(rv)) {
  29370             shr_idxres_list_free(oc->mpls_lm_dm_pool, 
  29371                                  (shr_idxres_element_t)session_id);
  29372             return (rv);
  29373         }
  29374         h_data_p->lm_dm_uc_session_id = session_id;
  29375     } else {
  29376         session_id = h_data_p->lm_dm_uc_session_id;
  29377     }
  29378 
  29379     /* Set the session Id in the message structure */
  29380     delay_add_msg.sess_id = session_id;
  29381 
  29382     /* Set the periodicity */
  29383     delay_add_msg.period = delay_p->period;
  29384 
  29385     /* Set timestamp format */
  29386     delay_add_msg.dm_format = delay_p->timestamp_format;
  29387 
  29388     rv = _bcm_sb2_mpls_lm_dm_get_tx_gport(unit, h_data_p, &gport);
  29389 
  29390     /* Create L2 Encap */
  29391     /* --------------- */
  29392     if (!(skip_l2_encap)) {
  29393         rv = _bcm_sb2_oam_mpls_lm_dm_encap_create(unit, h_data_p, gport, 
  29394                 delay_add_msg.l2_encap_data, &(delay_add_msg.l2_encap_length),
  29395                 packet_flags);
  29396         if (BCM_FAILURE(rv)) {
  29397             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29398                 " L2 Encap create failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29399                 bcm_errmsg(rv)));
  29400             return (rv);
  29401         }
  29402     }    
  29403 
  29404 
  29405     /* Creare OLP L2 Encap & Pack */
  29406     /* -------------------------- */
  29407     cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port);
  29408     _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header);
  29409     /* Pack OLP L2 Encap */
  29410     buffer_p = _bcm_sb2_oam_olp_l2_header_pack(delay_add_msg.olp_encap_data, 
  29411                                                &olp_l2_header);
  29412 
  29413     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
  29414     /* Set Port number */
  29415     SOC_OLP_TX_PORT(&olp_oam_header)  = BCM_GPORT_MODPORT_PORT_GET(gport);
  29416     SOC_OLP_TX_MODID(&olp_oam_header) = BCM_GPORT_MODPORT_MODID_GET(gport);
  29417 
  29418     /* Set Sample timestamp action */
  29419     SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = 
  29420         ((delay_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 2:1);
  29421 
  29422     /* Set Counter indexes */
  29423     for (i=0; i< delay_p->dm_tx_update_lm_counter_size; i++) {
  29424 
  29425         /* Counter pool index is 8 bit MSB of 24 bit counter base index */
  29426         counter_pool = (delay_p->dm_tx_update_lm_counter_base_id[i] & 0xFF000000) >> 24; 
  29427  
  29428         if (counter_pool == 0) {
  29429             SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 
  29430                 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 
  29431                 delay_p->dm_tx_update_lm_counter_offset[i]; 
  29432  
  29433             SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 
  29434                                                 bcmOamCounterActionIncrement;
  29435             /* Counter location is Egress */
  29436             SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1;
  29437             SOC_OLP_TX_CTR1_OFF_LM(&olp_oam_header) =
  29438                                         delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1;
  29439 
  29440         } 
  29441         if (counter_pool == 1) {
  29442             SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header,
  29443                 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 
  29444                 delay_p->dm_tx_update_lm_counter_offset[i]); 
  29445             SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 
  29446                                                 bcmOamCounterActionIncrement;
  29447             SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 
  29448             SOC_OLP_TX_CTR2_OFF_LM(&olp_oam_header) =
  29449                                         delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1;
  29450         }
  29451         if (counter_pool == 2) {
  29452             SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 
  29453                 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFFFF) +
  29454                 delay_p->dm_tx_update_lm_counter_offset[i]);
  29455             SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 
  29456                                                 bcmOamCounterActionIncrement;
  29457             SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 
  29458             SOC_OLP_TX_CTR3_OFF_LM(&olp_oam_header) =
  29459                                         delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1;
  29460         }
  29461     }
  29462 
  29463     /* TIMESTAMP OFFSET in OLP Header = 
  29464      * (L2 Encap + Timestamp field offset in MPLS_LM_DM OAM Header - 14)/2 
  29465      */
  29466     SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 
  29467         ((delay_add_msg.l2_encap_length + 12 ) - 14) >> 1;
  29468 
  29469     /* Pack OLP OAM Encap */
  29470     shr_olp_tx_header_pack(buffer_p, &olp_oam_header);
  29471 
  29472 #ifdef _MPLS_LM_DM_DEBUG_DUMP
  29473     _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(delay_add_msg.olp_encap_data, 
  29474                                                         MPLS_LM_DM_OLP_HDR_LEN);
  29475 #endif
  29476     
  29477 
  29478     /* Send Delay Add message */
  29479     /* --------------------- */
  29480     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29481     buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_delay_add_pack(buffer_p,
  29482                                                                  &delay_add_msg);
  29483     buffer_len = buffer_after_pack_p - buffer_p;
  29484     
  29485     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29486             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD, buffer_len, 0, 
  29487             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD_REPLY,
  29488             &reply_len);
  29489             
  29490     if (BCM_FAILURE(rv)|| (reply_len != 0)) {
  29491         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29492             " Delay Add Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29493             bcm_errmsg(rv)));
  29494         return (rv);
  29495     }    
  29496     
  29497     /* Store the session Id in hash data */
  29498     h_data_p->lm_dm_uc_session_id = session_id;
  29499     oc->mpls_lm_dm_sess_id_ep_id[session_id] = h_data_p->ep_id;
  29500 
  29501     /* Set the packet type in hash data */
  29502     h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM;
  29503     h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_DELAY_ADDED;
  29504 
  29505     delay_p->pm_id = h_data_p->lm_dm_uc_session_id;
  29506 
  29507     return rv;    
  29508 }
  29509 
  29510 STATIC int
  29511 _bcm_sb2_mpls_lm_dm_delay_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
  29512 {
  29513     _bcm_oam_control_t *oc = NULL;
  29514     uint8 *buffer_p = NULL;
  29515     uint8 *buffer_after_pack_p = NULL;
  29516     uint16 buffer_len = 0;
  29517     uint16 reply_len = 0;
  29518     shr_mpls_lm_dm_msg_ctrl_delay_delete_t delay_del_msg;
  29519     int rv = 0;
  29520 
  29521     /* Get OAM control pointer */
  29522     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29523 
  29524     /* uKernel ready check*/
  29525     if (!oc->mpls_lm_dm_ukernel_ready) {
  29526         rv = BCM_E_INIT;
  29527         return rv;
  29528 
  29529     }
  29530 
  29531     /* Validation Checks */
  29532     /* ----------------- */
  29533     /* Check if the DM is enabled for this EP */
  29534     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  29535         return BCM_E_NOT_FOUND;
  29536     }
  29537 
  29538     /* Initialize the Message structure */
  29539     sal_memset(&delay_del_msg, 0, sizeof(delay_del_msg));
  29540     delay_del_msg.sess_id = h_data_p->lm_dm_uc_session_id;
  29541 
  29542     /* Send Delay del message */
  29543     /* ---------------------- */
  29544     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29545     buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_delay_delete_pack(buffer_p, 
  29546                                                                 &delay_del_msg);
  29547     buffer_len = buffer_after_pack_p - buffer_p;
  29548     
  29549     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29550             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE, buffer_len, 0, 
  29551             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY,
  29552             &reply_len);
  29553             
  29554     if (BCM_FAILURE(rv)|| (reply_len != 0)) {
  29555         return (rv);
  29556     }    
  29557 
  29558     /* Clear the packet type in hash data */
  29559     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM);
  29560     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_DELAY_ADDED);
  29561 
  29562     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  29563         h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED);
  29564     }
  29565 
  29566     /* Free the session Id in hash data */
  29567     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  29568             shr_idxres_list_free(oc->mpls_lm_dm_pool, 
  29569                     (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id);
  29570         oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0;
  29571         h_data_p->lm_dm_uc_session_id = 0;
  29572         soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index,   
  29573                                                         MA_PTRf, 0);
  29574     }
  29575 
  29576     return rv;    
  29577 }
  29578 
  29579 STATIC int
  29580 _bcm_sb2_mpls_lm_dm_loss_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
  29581 {
  29582     _bcm_oam_control_t *oc = NULL;
  29583     uint8 *buffer_p = NULL;
  29584     uint8 *buffer_after_pack_p = NULL;
  29585     uint16 buffer_len = 0;
  29586     uint16 reply_len = 0;
  29587     shr_mpls_lm_dm_msg_ctrl_loss_delete_t loss_del_msg;
  29588     int rv = 0;
  29589 
  29590     /* Get OAM control pointer */
  29591     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29592 
  29593     /* uKernel ready check*/
  29594     if (!oc->mpls_lm_dm_ukernel_ready) {
  29595         rv = BCM_E_INIT;
  29596         return rv;
  29597 
  29598     }
  29599 
  29600     /* Validation Checks */
  29601     /* ----------------- */
  29602     /* Check if the LM is enabled for this EP */
  29603     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  29604         return BCM_E_NOT_FOUND;
  29605     }
  29606 
  29607     /* Initialize the Message structure */
  29608     sal_memset(&loss_del_msg, 0, sizeof(loss_del_msg));
  29609     loss_del_msg.sess_id = h_data_p->lm_dm_uc_session_id;
  29610 
  29611     /* Send Delay del message */
  29612     /* ---------------------- */
  29613     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29614     buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_delete_pack(buffer_p, 
  29615                                                                 &loss_del_msg);
  29616     buffer_len = buffer_after_pack_p - buffer_p;
  29617     
  29618     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29619             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE, buffer_len, 0, 
  29620             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY,
  29621             &reply_len);
  29622             
  29623     if (BCM_FAILURE(rv)|| (reply_len != 0)) {
  29624         return (rv);
  29625     }    
  29626 
  29627     /* Clear the packet type in hash data (if set) */
  29628     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM);
  29629     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM);
  29630     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM);
  29631     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM);
  29632     h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_LOSS_ADDED);
  29633 
  29634     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  29635         h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED);
  29636     }
  29637 
  29638     /* Free the session Id in hash data */
  29639     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  29640         shr_idxres_list_free(oc->mpls_lm_dm_pool, 
  29641                     (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id);
  29642         oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0;
  29643         h_data_p->lm_dm_uc_session_id = 0;
  29644         soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index,   
  29645                                                         MA_PTRf, 0);
  29646     }
  29647 
  29648     return rv;    
  29649 }
  29650 
  29651 STATIC int
  29652 _bcm_sb2_mpls_lm_dm_loss_get(int unit, _bcm_oam_hash_data_t *h_data_p, 
  29653     bcm_oam_loss_t *loss_p) 
  29654 {
  29655     _bcm_oam_control_t *oc = NULL;
  29656     uint8 *buffer_p = NULL;
  29657     uint8 *buffer_after_pack_p = NULL;
  29658     uint16 buffer_len = 0;
  29659     uint16 reply_len = 0;
  29660     shr_mpls_lm_dm_msg_ctrl_loss_get_t loss_get_req;
  29661     shr_mpls_lm_dm_msg_ctrl_loss_data_t loss_get_rsp;
  29662     int rv = 0;
  29663     int i = 0;
  29664 
  29665     /* Get OAM control pointer */
  29666     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29667 
  29668     /* Validation Checks */
  29669     /* ----------------- */
  29670     /* Check if the LM is enabled for this EP */
  29671     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  29672         return BCM_E_NOT_FOUND;
  29673     }
  29674     
  29675     sal_memset(&loss_get_req, 0, sizeof(loss_get_req));
  29676     loss_get_req.sess_id = h_data_p->lm_dm_uc_session_id;
  29677 
  29678     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29679     buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_get_pack(buffer_p, 
  29680                                                                 &loss_get_req);
  29681     buffer_len = buffer_after_pack_p - buffer_p;
  29682 
  29683     /* Send Loss GET request */
  29684     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29685             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET, buffer_len, 0,
  29686             MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET_REPLY,
  29687             &reply_len);
  29688 
  29689     if (BCM_FAILURE(rv)) {
  29690         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29691             " Loss get Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29692             bcm_errmsg(rv)));
  29693         return (rv);
  29694     }
  29695     
  29696 
  29697     /* Initialize the receive Message structure */
  29698     sal_memset(&loss_get_rsp, 0, sizeof(loss_get_rsp));
  29699 
  29700     /* Unpack loss get data   */
  29701     /* ---------------------- */
  29702     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29703     buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_data_unpack(buffer_p, 
  29704                                                                 &loss_get_rsp);
  29705     buffer_len = buffer_after_pack_p - buffer_p;
  29706     
  29707     if (reply_len != buffer_len) {
  29708         rv =  BCM_E_INTERNAL;
  29709     }
  29710 
  29711     if (loss_get_rsp.flags & (SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM |
  29712                               SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM ) ) {
  29713         loss_p->flags |= BCM_OAM_LOSS_SLM;
  29714     }
  29715     if (!(loss_get_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) {
  29716         loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  29717         
  29718     }
  29719     if (loss_get_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG) {
  29720        loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 
  29721     }
  29722     if (loss_get_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  29723        loss_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY;
  29724     }
  29725     
  29726     loss_p->period = loss_get_rsp.period;
  29727     loss_p->loss_threshold = loss_get_rsp.loss_threshold;             
  29728     loss_p->rx_oam_packets = loss_get_rsp.rx_oam_packets;          
  29729     loss_p->tx_oam_packets = loss_get_rsp.tx_oam_packets;          
  29730     loss_p->int_pri = loss_get_rsp.int_pri;
  29731     loss_p->pkt_pri = loss_get_rsp.pkt_pri;
  29732 
  29733     loss_p->lm_counter_size = loss_get_rsp.ctr_size;
  29734 
  29735     for (i=0; i<loss_p->lm_counter_size; i++) {
  29736         loss_p->lm_counter_base_id[i] = loss_get_rsp.ctr_base_id[i];
  29737         loss_p->lm_counter_offset[i] = loss_get_rsp.ctr_offset[i];
  29738         loss_p->lm_counter_action[i] = loss_get_rsp.ctr_action[i];
  29739         loss_p->lm_counter_byte_offset[i] = loss_get_rsp.ctr_byte_offset[i];
  29740     }
  29741 
  29742     if (loss_get_rsp.flags & SHR_MPLS_LM_DM_BYTE_COUNT_FLAG) {
  29743         loss_p->loss_nearend_byte = loss_get_rsp.loss_nearend;
  29744         loss_p->loss_farend_byte = loss_get_rsp.loss_farend;
  29745         loss_p->tx_nearend_byte = loss_get_rsp.tx_nearend;
  29746         loss_p->rx_nearend_byte = loss_get_rsp.rx_nearend;
  29747         loss_p->tx_farend_byte = loss_get_rsp.tx_farend;
  29748         loss_p->rx_farend_byte = loss_get_rsp.rx_farend;
  29749         if (loss_get_rsp.flags & SHR_MPLS_LM_DM_64_BIT_FLAG) {
  29750             loss_p->loss_nearend_byte_upper = loss_get_rsp.loss_nearend_upper;
  29751             loss_p->loss_farend_byte_upper = loss_get_rsp.loss_farend_upper;
  29752             loss_p->tx_nearend_byte_upper = loss_get_rsp.tx_nearend_upper;
  29753             loss_p->rx_nearend_byte_upper = loss_get_rsp.rx_nearend_upper;
  29754             loss_p->tx_farend_byte_upper = loss_get_rsp.tx_farend_upper;
  29755             loss_p->rx_farend_byte_upper = loss_get_rsp.rx_farend_upper;
  29756         }
  29757     } else {
  29758         loss_p->loss_nearend = loss_get_rsp.loss_nearend;
  29759         loss_p->loss_farend = loss_get_rsp.loss_farend;
  29760         loss_p->tx_nearend = loss_get_rsp.tx_nearend;
  29761         loss_p->rx_nearend = loss_get_rsp.rx_nearend;
  29762         loss_p->tx_farend = loss_get_rsp.tx_farend;
  29763         loss_p->rx_farend = loss_get_rsp.rx_farend;
  29764     }
  29765     loss_p->pm_id = h_data_p->lm_dm_uc_session_id;
  29766     
  29767     return rv;    
  29768 }
  29769 
  29770 STATIC int
  29771 _bcm_sb2_mpls_lm_dm_delay_get(int unit, _bcm_oam_hash_data_t *h_data_p, 
  29772     bcm_oam_delay_t *delay_p) 
  29773 {
  29774     _bcm_oam_control_t *oc = NULL;
  29775     uint8 *buffer_p = NULL;
  29776     uint8 *buffer_after_pack_p = NULL;
  29777     uint16 buffer_len = 0;
  29778     uint16 reply_len = 0;
  29779     shr_mpls_lm_dm_msg_ctrl_delay_get_t delay_get_req;
  29780     mpls_lm_dm_sdk_msg_ctrl_delay_data_t delay_get_rsp;
  29781     int rv = 0;
  29782 
  29783     /* Get OAM control pointer */
  29784     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29785 
  29786     /* Validation Checks */
  29787     /* ----------------- */
  29788     /* Check if the LM is enabled for this EP */
  29789     if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  29790         return BCM_E_NOT_FOUND;
  29791     }
  29792     
  29793     sal_memset(&delay_get_req, 0, sizeof(delay_get_req));
  29794     delay_get_req.sess_id = h_data_p->lm_dm_uc_session_id;
  29795 
  29796     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29797     buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_delay_get_pack(buffer_p, 
  29798                                                                 &delay_get_req);
  29799     buffer_len = buffer_after_pack_p - buffer_p;
  29800 
  29801     /* Send Loss GET request */
  29802     rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 
  29803             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET, buffer_len, 0,
  29804             MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET_REPLY,
  29805             &reply_len);
  29806 
  29807     if (BCM_FAILURE(rv)) {
  29808         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  29809             " Loss get Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  29810             bcm_errmsg(rv)));
  29811         return (rv);
  29812     }
  29813     
  29814 
  29815     /* Initialize the receive Message structure */
  29816     sal_memset(&delay_get_rsp, 0, sizeof(delay_get_rsp));
  29817 
  29818     /* Unpack delay get data   */
  29819     /* ---------------------- */
  29820     buffer_p = oc->mpls_lm_dm_dma_buffer;
  29821     buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_delay_data_unpack(buffer_p, 
  29822                                                                 &delay_get_rsp);
  29823     buffer_len = buffer_after_pack_p - buffer_p;
  29824     
  29825     if (reply_len != buffer_len) {
  29826         rv =  BCM_E_INTERNAL;
  29827     }
  29828 
  29829     if (delay_get_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  29830        delay_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY;
  29831     } else {
  29832         if (!(delay_get_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) {
  29833             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  29834         }
  29835         if (!(delay_get_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG)) {
  29836             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  29837         }
  29838     }
  29839 
  29840     delay_p->period = delay_get_rsp.period;
  29841     delay_p->timestamp_format = delay_get_rsp.dm_format;             
  29842     rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 
  29843             delay_get_rsp.delay_seconds, delay_get_rsp.delay_nanoseconds);
  29844     if(BCM_SUCCESS(rv)) {
  29845         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 
  29846             delay_get_rsp.txf_seconds, delay_get_rsp.txf_nanoseconds);
  29847     }
  29848     if(BCM_SUCCESS(rv)) {
  29849         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 
  29850             delay_get_rsp.rxf_seconds, delay_get_rsp.rxf_nanoseconds);
  29851     }
  29852     if(BCM_SUCCESS(rv)) {
  29853         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 
  29854             delay_get_rsp.txb_seconds, delay_get_rsp.txb_nanoseconds);
  29855     }
  29856     if(BCM_SUCCESS(rv)) {
  29857         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 
  29858             delay_get_rsp.rxb_seconds, delay_get_rsp.rxb_nanoseconds);
  29859     }
  29860     delay_p->rx_oam_packets = delay_get_rsp.rx_oam_packets;
  29861     delay_p->tx_oam_packets = delay_get_rsp.tx_oam_packets;
  29862     delay_p->int_pri = delay_get_rsp.int_pri;
  29863     delay_p->pkt_pri = delay_get_rsp.pkt_pri;
  29864 
  29865     delay_p->pm_id = h_data_p->lm_dm_uc_session_id;
  29866     
  29867     if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 
  29868                     delay_get_rsp.olp_tx_hdr,
  29869                     &delay_p->dm_tx_update_lm_counter_size, 
  29870                     delay_p->dm_tx_update_lm_counter_base_id,
  29871                     delay_p->dm_tx_update_lm_counter_offset,
  29872                     NULL,
  29873                     delay_p->dm_tx_update_lm_counter_byte_offset,
  29874                     NULL,
  29875                     NULL,
  29876                     NULL))) {
  29877         _BCM_OAM_UNLOCK(oc);
  29878         return (BCM_E_INTERNAL);
  29879     }
  29880     
  29881     return rv;    
  29882 }
  29883 
  29884 /*
  29885  * Function:
  29886  *      _bcm_sb2_oam_mpls_lm_dm_appl_callback
  29887  * Purpose:
  29888  *      Update FW MPLS LM/DM appl state
  29889  * Parameters:
  29890  *      unit  - (IN) Unit number.
  29891  *      uC    - (IN) core number.
  29892  *      stage - (IN) core reset stage.
  29893  *      user_data - (IN) data pointer.
  29894  * Returns:
  29895  *      BCM_E_XXX
  29896  * Notes:
  29897  */
  29898 
  29899 int _bcm_sb2_oam_mpls_lm_dm_appl_callback(int unit,
  29900         int uC,
  29901         soc_cmic_uc_shutdown_stage_t stage,
  29902         void *user_data) {
  29903     _bcm_oam_control_t *oc;
  29904 
  29905     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29906     _BCM_OAM_LOCK(oc);
  29907     oc->mpls_lm_dm_ukernel_ready = 0;
  29908 
  29909     _BCM_OAM_UNLOCK(oc);
  29910 
  29911     return BCM_E_NONE;
  29912 }
  29913 
  29914 /*
  29915  * Function:
  29916  *      _bcm_sb2_mpls_lm_dm_event_mask_set
  29917  * Purpose:
  29918  *      Set the MPLS_LM_DM Events mask.
  29919  *      Events are set per BHH module.
  29920  * Parameters:
  29921  *      unit        - (IN) Unit number.
  29922  * Returns:
  29923  *      BCM_E_NONE Operation completed successfully
  29924  *      BCM_E_XXX  Operation failed
  29925  * Notes:
  29926  */
  29927 STATIC int
  29928 _bcm_sb2_mpls_lm_dm_event_mask_set(int unit)
  29929 {
  29930     _bcm_oam_control_t *oc;
  29931     _bcm_oam_event_handler_t *event_handler_p;
  29932     uint16 reply_len;
  29933     int rv = BCM_E_NONE;
  29934 
  29935     /* Lock already taken by the calling routine. */
  29936     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  29937 
  29938     /* Get event mask from all callbacks */
  29939     for (event_handler_p = oc->event_handler_list_p;
  29940             event_handler_p != NULL;
  29941             event_handler_p = event_handler_p->next_p) {
  29942 
  29943         /* Update MPLS_LM_DM event mask in uKernel */
  29944         if (SHR_BITGET(event_handler_p->event_types.w,
  29945                        bcmOAMEventMplsLmDmPmCounterRollover)) {
  29946             /* Send MPLS_LM_DM Event Mask message to uC */
  29947             rv = _bcm_sb2_oam_pm_msg_send_receive(unit,
  29948                             MOS_MSG_CLASS_MPLS_LM_DM,
  29949                             MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET,
  29950                             0, MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER,
  29951                             MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET_REPLY,
  29952                             &reply_len);
  29953             if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  29954                 rv = BCM_E_INTERNAL;
  29955             }
  29956             return (rv);
  29957         }
  29958     }
  29959     return (rv);
  29960 }
  29961 #endif /*(INCLUDE_MPLS_LM_DM) */
  29962 
  29963 
  29964 
  29965 #if defined(INCLUDE_BHH)
  29966 /*
  29967  * Function:
  29968  *      _bcm_sb2_oam_bhh_msg_send_receive
  29969  * Purpose:
  29970  *      Sends given BHH control message to the uController.
  29971  *      Receives and verifies expected reply.
  29972  *      Performs DMA operation if required.
  29973  * Parameters:
  29974  *      unit        - (IN) Unit number.
  29975  *      s_subclass  - (IN) BHH message subclass.
  29976  *      s_len       - (IN) Value for 'len' field in message struct.
  29977  *                         Length of buffer to flush if DMA send is required.
  29978  *      s_data      - (IN) Value for 'data' field in message struct.
  29979  *                         Ignored if message requires a DMA send/receive
  29980  *                         operation.
  29981  *      r_subclass  - (IN) Expected reply message subclass.
  29982  *      r_len       - (OUT) Returns value in 'len' reply message field.
  29983  * Returns:
  29984  *      BCM_E_XXX
  29985  * Notes:
  29986  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  29987  *       can take any arbitrary data.
  29988  *
  29989  *     BHH Long Control message:
  29990  *     - BHH control messages that require send/receive of information
  29991  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  29992  *       use DMA operations to exchange information (long control message).
  29993  *
  29994  *     - BHH convention for long control messages for
  29995  *        'mos_msg_data_t' fields:
  29996  *          'len'    size of the DMA buffer to send to uController
  29997  *          'data'   physical DMA memory address to send or receive
  29998  *
  29999  *      DMA Operations:
  30000  *      - DMA read/write operation is performed when a long BHH control
  30001  *        message is involved.
  30002  *
  30003  *      - Messages that require DMA operation (long control message)
  30004  *        is indicated by MOS_MSG_DMA_MSG().
  30005  *
  30006  *      - Callers must 'pack' and 'unpack' corresponding information
  30007  *        into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer.
  30008  */
  30009 STATIC int
  30010 _bcm_sb2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
  30011                                     uint16 s_len, uint32 s_data,
  30012                                     uint8 r_subclass, uint16 *r_len)
  30013 {
  30014     int rv;
  30015     _bcm_oam_control_t *oc;
  30016     mos_msg_data_t send, reply;
  30017     uint8 *dma_buffer;
  30018     int dma_buffer_len;
  30019     uint32 uc_rv;
  30020 
  30021     /* Lock already taken by the calling routine. */
  30022     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30023 
  30024     sal_memset(&send, 0, sizeof(send));
  30025     sal_memset(&reply, 0, sizeof(reply));
  30026     send.s.mclass = MOS_MSG_CLASS_BHH;
  30027     send.s.subclass = s_subclass;
  30028     send.s.len = bcm_htons(s_len);
  30029 
  30030     /*
  30031      * Set 'data' to DMA buffer address if a DMA operation is
  30032      * required for send or receive.
  30033      */
  30034     dma_buffer = oc->dma_buffer;
  30035     dma_buffer_len = oc->dma_buffer_len;
  30036     if (MOS_MSG_DMA_MSG(s_subclass) ||
  30037         MOS_MSG_DMA_MSG(r_subclass)) {
  30038         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  30039     } else {
  30040         send.s.data = bcm_htonl(s_data);
  30041     }
  30042 
  30043     /* Flush DMA memory */
  30044     if (MOS_MSG_DMA_MSG(s_subclass)) {
  30045         soc_cm_sflush(unit, dma_buffer, s_len);
  30046     }
  30047 
  30048     /* Invalidate DMA memory to read */
  30049     if (MOS_MSG_DMA_MSG(r_subclass)) {
  30050         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  30051     }
  30052 
  30053     rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num,
  30054                                       &send, &reply,
  30055                                       _BHH_UC_MSG_TIMEOUT_USECS);
  30056 
  30057     /* Check reply class, subclass */
  30058     if (rv != SOC_E_NONE) {
  30059         return (BCM_E_INTERNAL);
  30060     }
  30061 
  30062     /* Convert BHH uController error code to BCM */
  30063     uc_rv = bcm_ntohl(reply.s.data);
  30064     switch(uc_rv) {
  30065     case SHR_BHH_UC_E_NONE:
  30066         rv = BCM_E_NONE;
  30067         break;
  30068     case SHR_BHH_UC_E_INTERNAL:
  30069         rv = BCM_E_INTERNAL;
  30070         break;
  30071     case SHR_BHH_UC_E_MEMORY:
  30072         rv = BCM_E_MEMORY;
  30073         break;
  30074     case SHR_BHH_UC_E_PARAM:
  30075         rv = BCM_E_PARAM;
  30076         break;
  30077     case SHR_BHH_UC_E_RESOURCE:
  30078         rv = BCM_E_RESOURCE;
  30079         break;
  30080     case SHR_BHH_UC_E_EXISTS:
  30081         rv = BCM_E_EXISTS;
  30082         break;
  30083     case SHR_BHH_UC_E_NOT_FOUND:
  30084         rv = BCM_E_NOT_FOUND;
  30085         break;
  30086     case SHR_BHH_UC_E_INIT:
  30087         rv = BCM_E_INIT;
  30088         break;
  30089     case SHR_BHH_UC_E_UNAVAIL:
  30090         rv = BCM_E_UNAVAIL;
  30091         break;
  30092     default:
  30093         rv = BCM_E_INTERNAL;
  30094         break;
  30095     }
  30096         
  30097     *r_len = bcm_ntohs(reply.s.len);
  30098     /*Check reply class and subclass*/
  30099     if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_BHH) ||
  30100         (reply.s.subclass != r_subclass)))
  30101     {
  30102         return BCM_E_INTERNAL;
  30103     }
  30104 
  30105     return (rv);
  30106 }
  30107 #endif /*(INCLUDE_BHH) */
  30108 
  30109 #if defined(INCLUDE_ETH_LM_DM)
  30110 /*
  30111  * Function:
  30112  *      _bcm_sb2_oam_eth_lm_dm_msg_send_receive
  30113  * Purpose:
  30114  *      Sends given ETH_LM_DM control message to the uController.
  30115  *      Receives and verifies expected reply.
  30116  *      Performs DMA operation if required.
  30117  * Parameters:
  30118  *      unit        - (IN) Unit number.
  30119  *      s_subclass  - (IN) BHH message subclass.
  30120  *      s_len       - (IN) Value for 'len' field in message struct.
  30121  *                         Length of buffer to flush if DMA send is required.
  30122  *      s_data      - (IN) Value for 'data' field in message struct.
  30123  *                         Ignored if message requires a DMA send/receive
  30124  *                         operation.
  30125  *      r_subclass  - (IN) Expected reply message subclass.
  30126  *      r_len       - (OUT) Returns value in 'len' reply message field.
  30127  * Returns:
  30128  *      BCM_E_XXX
  30129  * Notes:
  30130  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  30131  *       can take any arbitrary data.
  30132  *
  30133  *     ETH_LM_DM Long Control message:
  30134  *     - ETH_LM_DM control messages that require send/receive of information
  30135  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  30136  *       use DMA operations to exchange information (long control message).
  30137  *
  30138  *     - ETH_LM_DM convention for long control messages for
  30139  *        'mos_msg_data_t' fields:
  30140  *          'len'    size of the DMA buffer to send to uController
  30141  *          'data'   physical DMA memory address to send or receive
  30142  *
  30143  *      DMA Operations:
  30144  *      - DMA read/write operation is performed when a long ETH_LM_DM control
  30145  *        message is involved.
  30146  *
  30147  *      - Messages that require DMA operation (long control message)
  30148  *        is indicated by MOS_MSG_DMA_MSG().
  30149  *
  30150  *      - Callers must 'pack' and 'unpack' corresponding information
  30151  *        into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer.
  30152  */
  30153 STATIC int
  30154 _bcm_sb2_oam_eth_lm_dm_msg_send_receive(int unit, uint8 s_subclass,
  30155                                     uint16 s_len, uint32 s_data,
  30156                                     uint8 r_subclass, uint16 *r_len)
  30157 {
  30158     int rv;
  30159     _bcm_oam_control_t *oc;
  30160     mos_msg_data_t send, reply;
  30161     uint8 *dma_buffer;
  30162     int dma_buffer_len;
  30163     uint32 uc_rv;
  30164 
  30165     /* Lock already taken by the calling routine. */
  30166     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30167 
  30168     sal_memset(&send, 0, sizeof(send));
  30169     sal_memset(&reply, 0, sizeof(reply));
  30170     send.s.mclass = MOS_MSG_CLASS_ETH_LM_DM;
  30171     send.s.subclass = s_subclass;
  30172     send.s.len = bcm_htons(s_len);
  30173 
  30174     /*
  30175      * Set 'data' to DMA buffer address if a DMA operation is
  30176      * required for send or receive.
  30177      */
  30178     dma_buffer = oc->eth_lm_dm_dma_buffer;
  30179     dma_buffer_len = oc->eth_lm_dm_dma_buffer_len;
  30180     if (MOS_MSG_DMA_MSG(s_subclass) ||
  30181         MOS_MSG_DMA_MSG(r_subclass)) {
  30182         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  30183     } else {
  30184         send.s.data = bcm_htonl(s_data);
  30185     }
  30186 
  30187     /* Flush DMA memory */
  30188     if (MOS_MSG_DMA_MSG(s_subclass)) {
  30189         soc_cm_sflush(unit, dma_buffer, s_len);
  30190     }
  30191 
  30192     /* Invalidate DMA memory to read */
  30193     if (MOS_MSG_DMA_MSG(r_subclass)) {
  30194         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  30195     }
  30196 
  30197     rv = soc_cmic_uc_msg_send_receive(unit, oc->eth_lm_dm_uc_num,
  30198                                       &send, &reply,
  30199                                       _ETH_LM_DM_UC_MSG_TIMEOUT_USECS);
  30200 
  30201     /* Check reply class, subclass */
  30202     if ((rv != SOC_E_NONE) ||
  30203         (reply.s.mclass != MOS_MSG_CLASS_ETH_LM_DM) ||
  30204         (reply.s.subclass != r_subclass)) {
  30205         return (BCM_E_INTERNAL);
  30206     }
  30207 
  30208     /* Convert ETH_LM_DM uController error code to BCM */
  30209     uc_rv = bcm_ntohl(reply.s.data);
  30210     switch(uc_rv) {
  30211     case SHR_ETH_LM_DM_UC_E_NONE:
  30212         rv = BCM_E_NONE;
  30213         break;
  30214     case SHR_ETH_LM_DM_UC_E_INTERNAL:
  30215         rv = BCM_E_INTERNAL;
  30216         break;
  30217     case SHR_ETH_LM_DM_UC_E_MEMORY:
  30218         rv = BCM_E_MEMORY;
  30219         break;
  30220     case SHR_ETH_LM_DM_UC_E_PARAM:
  30221         rv = BCM_E_PARAM;
  30222         break;
  30223     case SHR_ETH_LM_DM_UC_E_RESOURCE:
  30224         rv = BCM_E_RESOURCE;
  30225         break;
  30226     case SHR_ETH_LM_DM_UC_E_EXISTS:
  30227         rv = BCM_E_EXISTS;
  30228         break;
  30229     case SHR_ETH_LM_DM_UC_E_NOT_FOUND:
  30230         rv = BCM_E_NOT_FOUND;
  30231         break;
  30232     case SHR_ETH_LM_DM_UC_E_INIT:
  30233         rv = BCM_E_INIT;
  30234         break;
  30235     default:
  30236         rv = BCM_E_INTERNAL;
  30237         break;
  30238     }
  30239         
  30240     *r_len = bcm_ntohs(reply.s.len);
  30241 
  30242     return (rv);
  30243 }
  30244 
  30245 /*
  30246  * Function:
  30247  *      _bcm_sb2_eth_lm_dm_event_mask_set
  30248  * Purpose:
  30249  *      Set the ETH_LM_DM Events mask.
  30250  *      Events are set per BHH module.
  30251  * Parameters:
  30252  *      unit        - (IN) Unit number.
  30253  * Returns:
  30254  *      BCM_E_NONE Operation completed successfully
  30255  *      BCM_E_XXX  Operation failed
  30256  * Notes:
  30257  */
  30258 STATIC int
  30259 _bcm_sb2_eth_lm_dm_event_mask_set(int unit)
  30260 {
  30261     _bcm_oam_control_t *oc;
  30262     _bcm_oam_event_handler_t *event_handler_p;
  30263     uint16 reply_len;
  30264     int rv = BCM_E_NONE;
  30265 
  30266     /* Lock already taken by the calling routine. */
  30267     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30268 
  30269     /* Get event mask from all callbacks */
  30270     for (event_handler_p = oc->event_handler_list_p;
  30271          event_handler_p != NULL;
  30272          event_handler_p = event_handler_p->next_p) {
  30273 
  30274         /* Update ETH_LM_DM event mask in uKernel */
  30275         if (SHR_BITGET(event_handler_p->event_types.w,
  30276                        bcmOAMEventEthLmDmPmCounterRollover)) {
  30277             /* Send ETH_LM_DM Event Mask message to uC */
  30278             rv = _bcm_sb2_oam_pm_msg_send_receive (unit,
  30279                                    MOS_MSG_CLASS_ETH_LM_DM,
  30280                                    MOS_MSG_SUBCLASS_ETH_LM_DM_EVENT_MASK_SET,
  30281                                    0, ETH_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER,
  30282                                    MOS_MSG_SUBCLASS_ETH_LM_DM_EVENT_MASK_SET_REPLY,
  30283                                    &reply_len);
  30284             if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  30285                 rv = BCM_E_INTERNAL;
  30286             }
  30287             return (rv);
  30288         }
  30289     }
  30290     return (rv);
  30291 }
  30292 
  30293 #endif /*(INCLUDE_ETH_LM_DM) */
  30294 
  30295 
  30296 #if defined(INCLUDE_BHH)
  30297 /*
  30298  * Function:
  30299  *      _bcm_sb2_oam_bhh_callback_thread
  30300  * Purpose:
  30301  *      Thread to listen for event messages from uController.
  30302  * Parameters:
  30303  *      param - Pointer to BFD info structure.
  30304  * Returns:
  30305  *      None
  30306  */
  30307 STATIC void
  30308 _bcm_sb2_oam_bhh_callback_thread(void *param)
  30309 {
  30310     int rv;
  30311     _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param;
  30312     bcm_oam_event_types_t events;
  30313     bcm_oam_event_type_t event_type;
  30314     bhh_msg_event_t event_msg;
  30315     int sess_id;
  30316     uint32 event_mask;
  30317     _bcm_oam_event_handler_t *event_handler_p;
  30318     _bcm_oam_hash_data_t *h_data_p;
  30319     int ep_id = 0;
  30320     char thread_name[SAL_THREAD_NAME_MAX_LEN];
  30321     uint8 msg_subclass = 0;
  30322 
  30323     thread_name[0] = 0;
  30324     sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name));
  30325 
  30326     while (1) {
  30327         /* Wait on notifications from uController */
  30328         rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num,
  30329                                      MOS_MSG_CLASS_BHH_EVENT, &event_msg,
  30330                                      sal_sem_FOREVER);
  30331         if (BCM_FAILURE(rv)) {
  30332             break;  /*  Thread exit */
  30333         }
  30334 
  30335         event_handler_p = oc->event_handler_list_p;
  30336         /* Get data from event message */
  30337         sess_id = (int)bcm_ntohs(event_msg.s.len);
  30338         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id);
  30339 
  30340         msg_subclass = event_msg.s.subclass;
  30341 
  30342         if (msg_subclass == _BHH_EVENT_OAM_PM_EVENT) {
  30343             /* Call PM message handling function and continue */
  30344             _bcm_sb2_oam_pm_event_msg_handle(oc, &event_msg);
  30345             continue;
  30346         }
  30347         if (sess_id < 0 ||
  30348             sess_id >= oc->ep_count) {
  30349             LOG_CLI((BSL_META_U(oc->unit,
  30350                                 "%s: Invalid sess_id:%d \n"), FUNCTION_NAME(), sess_id));
  30351             continue;
  30352         }
  30353 
  30354         /* Check endpoint status. */
  30355         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  30356         if ((BCM_E_EXISTS != rv)) {
  30357             /* Endpoint not in use. */
  30358             LOG_ERROR(BSL_LS_BCM_OAM,
  30359                       (BSL_META("OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  30360                        oc->unit, ep_id, bcm_errmsg(rv)));
  30361             continue;
  30362         }
  30363         h_data_p = &oc->oam_hash_data[ep_id];
  30364         event_mask = bcm_ntohl(event_msg.s.data);
  30365 
  30366         /* Set events */
  30367         sal_memset(&events, 0, sizeof(events));
  30368 
  30369         if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) {
  30370             LOG_DEBUG(BSL_LS_BCM_OAM,
  30371                       (BSL_META_U(oc->unit,
  30372                                 "****** OAM BHH LB Timeout ******\n")));
  30373 
  30374             if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) {
  30375                 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout);
  30376             }
  30377         }
  30378         if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) {
  30379             LOG_DEBUG(BSL_LS_BCM_OAM,
  30380                       (BSL_META_U(oc->unit,
  30381                                "****** OAM BHH LB Discovery Update ******\n")));
  30382             if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) {
  30383                 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate);
  30384             }
  30385         }
  30386         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) {
  30387             LOG_DEBUG(BSL_LS_BCM_OAM,
  30388                       (BSL_META_U(oc->unit,
  30389                                 "****** OAM BHH CCM Timeout ******\n")));
  30390             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) {
  30391                 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout);
  30392             }
  30393         }
  30394         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) {
  30395             LOG_DEBUG(BSL_LS_BCM_OAM,
  30396                       (BSL_META_U(oc->unit,
  30397                                 "****** OAM BHH CCM Timeout Clear ******\n")));
  30398             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) {
  30399                 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear);
  30400             }
  30401         }
  30402         if (event_mask & BHH_BTE_EVENT_STATE) {
  30403             LOG_DEBUG(BSL_LS_BCM_OAM,
  30404                       (BSL_META_U(oc->unit,
  30405                                 "****** OAM BHH State ******\n")));
  30406             if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) {
  30407                 SHR_BITSET(events.w, bcmOAMEventBHHCCMState);
  30408             }
  30409         }
  30410         if (event_mask & BHH_BTE_EVENT_CCM_RDI) {
  30411             LOG_DEBUG(BSL_LS_BCM_OAM,
  30412                       (BSL_META_U(oc->unit,
  30413                                   "****** OAM BHH CCM RDI ******\n")));
  30414             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) {
  30415                 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi);
  30416             }
  30417         }
  30418         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) {
  30419             LOG_DEBUG(BSL_LS_BCM_OAM,
  30420                       (BSL_META_U(oc->unit,
  30421                             "****** OAM BHH CCM  Unknown MEG LEVEL ******\n")));
  30422             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) {
  30423                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel);
  30424             }
  30425         }
  30426         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) {
  30427             LOG_DEBUG(BSL_LS_BCM_OAM,
  30428                       (BSL_META_U(oc->unit,
  30429                                "****** OAM BHH CCM  Unknown MEG ID ******\n")));
  30430             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) {
  30431                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId);
  30432             }
  30433         }
  30434         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) {
  30435             LOG_DEBUG(BSL_LS_BCM_OAM,
  30436                       (BSL_META_U(oc->unit,
  30437                                 "****** OAM BHH CCM  Unknown MEP ID ******\n")));
  30438             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) {
  30439                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId);
  30440             }
  30441         }
  30442         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) {
  30443             LOG_DEBUG(BSL_LS_BCM_OAM,
  30444                       (BSL_META_U(oc->unit,
  30445                                 "****** OAM BHH CCM  Unknown Period ******\n")));
  30446             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) {
  30447                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod);
  30448             }
  30449         }
  30450         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) {
  30451             LOG_DEBUG(BSL_LS_BCM_OAM,
  30452                       (BSL_META_U(oc->unit,
  30453                               "****** OAM BHH CCM  Unknown Priority ******\n")));
  30454             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) {
  30455                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority);
  30456             }
  30457         }
  30458         if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) {
  30459             LOG_DEBUG(BSL_LS_BCM_OAM,
  30460                       (BSL_META_U(oc->unit,
  30461                                   "****** OAM BHH CCM  RDI Clear ******\n")));
  30462             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) {
  30463                 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear);
  30464             }
  30465         }
  30466         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) {
  30467             LOG_DEBUG(BSL_LS_BCM_OAM,
  30468                       (BSL_META_U(oc->unit,
  30469                        "****** OAM BHH CCM  Unknown MEG Level Clear ******\n")));
  30470             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) {
  30471                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear);
  30472             }
  30473         }
  30474         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) {
  30475             LOG_DEBUG(BSL_LS_BCM_OAM,
  30476                       (BSL_META_U(oc->unit,
  30477                           "****** OAM BHH CCM  Unknown MEG ID Clear ******\n")));
  30478             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) {
  30479                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear);
  30480             }
  30481         }
  30482         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) {
  30483             LOG_DEBUG(BSL_LS_BCM_OAM,
  30484                       (BSL_META_U(oc->unit,
  30485                           "****** OAM BHH CCM  Unknown MEP ID Clear ******\n")));
  30486             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) {
  30487                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear);
  30488             }
  30489         }
  30490         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) {
  30491             LOG_DEBUG(BSL_LS_BCM_OAM,
  30492                       (BSL_META_U(oc->unit,
  30493                           "****** OAM BHH CCM  Unknown Period Clear ******\n")));
  30494             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) {
  30495                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear);
  30496             }
  30497         }
  30498         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) {
  30499             LOG_DEBUG(BSL_LS_BCM_OAM,
  30500                       (BSL_META_U(oc->unit,
  30501                         "****** OAM BHH CCM  Unknown Priority Clear ******\n")));
  30502             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) {
  30503                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear);
  30504             }
  30505         }
  30506         if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
  30507             LOG_DEBUG(BSL_LS_BCM_OAM,
  30508                       (BSL_META_U(oc->unit,
  30509                                 "****** OAM PM BHH Counter Rollover ******\n")));
  30510 
  30511             if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) {
  30512                 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover);
  30513             }
  30514         }
  30515         if (event_mask & BHH_BTE_EVENT_CSF_LOS) {
  30516             LOG_DEBUG(BSL_LS_BCM_OAM,
  30517                       (BSL_META_U(oc->unit,
  30518                                   "****** OAM BHH CSF LOS ******\n")));
  30519 
  30520             if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) {
  30521                 SHR_BITSET(events.w, bcmOAMEventCsfLos);
  30522             }
  30523         }
  30524         if (event_mask & BHH_BTE_EVENT_CSF_FDI) {
  30525             LOG_DEBUG(BSL_LS_BCM_OAM,
  30526                       (BSL_META_U(oc->unit,
  30527                                   "****** OAM BHH CSF FDI ******\n")));
  30528 
  30529             if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) {
  30530                 SHR_BITSET(events.w, bcmOAMEventCsfFdi);
  30531             }
  30532         }
  30533         if (event_mask & BHH_BTE_EVENT_CSF_RDI) {
  30534             LOG_DEBUG(BSL_LS_BCM_OAM,
  30535                       (BSL_META_U(oc->unit,
  30536                                   "****** OAM BHH CSF RDI ******\n")));
  30537 
  30538             if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) {
  30539                 SHR_BITSET(events.w, bcmOAMEventCsfRdi);
  30540             }
  30541         }
  30542         if (event_mask & BHH_BTE_EVENT_CSF_DCI) {
  30543             LOG_DEBUG(BSL_LS_BCM_OAM,
  30544                       (BSL_META_U(oc->unit,
  30545                                   "****** OAM BHH CSF DCI ******\n")));
  30546 
  30547             if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) {
  30548                 SHR_BITSET(events.w, bcmOAMEventCsfDci);
  30549             }
  30550         }
  30551         /* Loop over registered callbacks,
  30552          * If any match the events field, then invoke
  30553          */
  30554         for (event_handler_p = oc->event_handler_list_p;
  30555              event_handler_p != NULL;
  30556              event_handler_p = event_handler_p->next_p) {
  30557             for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) {
  30558                 if (SHR_BITGET(events.w, event_type)) {
  30559                     if (SHR_BITGET(event_handler_p->event_types.w,
  30560                                    event_type)) {
  30561                         event_handler_p->cb(oc->unit,
  30562                                         0,
  30563                                         event_type,
  30564                                         h_data_p->group_index, /* Group index */
  30565                                         ep_id, /* Endpoint index */
  30566                                         event_handler_p->user_data);
  30567                     }
  30568                 }
  30569             }
  30570         }
  30571     }
  30572 
  30573     oc->event_thread_id   = NULL;
  30574     LOG_VERBOSE(BSL_LS_BCM_OAM,
  30575               (BSL_META_U(oc->unit,
  30576                           "Thread Exit:%s\n"), thread_name));
  30577     sal_thread_exit(0);
  30578 }
  30579 
  30580 /* BHH Event Handler */
  30581 typedef struct _event_handler_s {
  30582     struct _event_handler_s *next;
  30583     bcm_oam_event_types_t event_types;
  30584     bcm_oam_event_cb cb;
  30585     void *user_data;
  30586 } _event_handler_t;
  30587 
  30588 /*
  30589  * Function:
  30590  *      _bcm_sb2_oam_bhh_event_mask_set
  30591  * Purpose:
  30592  *      Set the BHH Events mask.
  30593  *      Events are set per BHH module.
  30594  * Parameters:
  30595  *      unit        - (IN) Unit number.
  30596  * Returns:
  30597  *      BCM_E_NONE Operation completed successfully
  30598  *      BCM_E_XXX  Operation failed
  30599  * Notes:
  30600  */
  30601 STATIC int
  30602 _bcm_sb2_oam_bhh_event_mask_set(int unit)
  30603 {
  30604     _bcm_oam_control_t *oc;
  30605     _bcm_oam_event_handler_t *event_handler_p;
  30606     uint32 event_mask = 0;
  30607     uint16 reply_len;
  30608     int rv = BCM_E_NONE;
  30609 
  30610     /* Lock already taken by the calling routine. */
  30611     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30612 
  30613     /* Get event mask from all callbacks */
  30614     for (event_handler_p = oc->event_handler_list_p;
  30615          event_handler_p != NULL;
  30616          event_handler_p = event_handler_p->next_p) {
  30617 
  30618         if (SHR_BITGET(event_handler_p->event_types.w,
  30619                        bcmOAMEventBHHLBTimeout)) {
  30620             event_mask |= BHH_BTE_EVENT_LB_TIMEOUT;
  30621         }
  30622         if (SHR_BITGET(event_handler_p->event_types.w,
  30623                        bcmOAMEventBHHLBDiscoveryUpdate)) {
  30624             event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE;
  30625         }
  30626         if (SHR_BITGET(event_handler_p->event_types.w,
  30627                        bcmOAMEventBHHCCMTimeout)) {
  30628             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT;
  30629         }
  30630         if (SHR_BITGET(event_handler_p->event_types.w,
  30631                        bcmOAMEventBHHCCMTimeoutClear)) {
  30632             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR;
  30633         }
  30634         if (SHR_BITGET(event_handler_p->event_types.w,
  30635                        bcmOAMEventBHHCCMState)) {
  30636             event_mask |= BHH_BTE_EVENT_STATE;
  30637         }
  30638         if (SHR_BITGET(event_handler_p->event_types.w,
  30639                        bcmOAMEventBHHCCMRdi)) {
  30640             event_mask |= BHH_BTE_EVENT_CCM_RDI;
  30641         }
  30642         if (SHR_BITGET(event_handler_p->event_types.w,
  30643                        bcmOAMEventBHHCCMUnknownMegLevel)) {
  30644             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL;
  30645         }
  30646         if (SHR_BITGET(event_handler_p->event_types.w,
  30647                        bcmOAMEventBHHCCMUnknownMegId)) {
  30648             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID;
  30649         }
  30650         if (SHR_BITGET(event_handler_p->event_types.w,
  30651                        bcmOAMEventBHHCCMUnknownMepId)) {
  30652             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID;
  30653         }
  30654         if (SHR_BITGET(event_handler_p->event_types.w,
  30655                        bcmOAMEventBHHCCMUnknownPeriod)) {
  30656             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD;
  30657         }
  30658         if (SHR_BITGET(event_handler_p->event_types.w,
  30659                        bcmOAMEventBHHCCMUnknownPriority)) {
  30660             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY;
  30661         }
  30662         if (SHR_BITGET(event_handler_p->event_types.w,
  30663                        bcmOAMEventBHHCCMRdiClear)) {
  30664             event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR;
  30665         }
  30666         if (SHR_BITGET(event_handler_p->event_types.w,
  30667                        bcmOAMEventBHHCCMUnknownMegLevelClear)) {
  30668             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR;
  30669         }
  30670         if (SHR_BITGET(event_handler_p->event_types.w,
  30671                        bcmOAMEventBHHCCMUnknownMegIdClear)) {
  30672             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR;
  30673         }
  30674         if (SHR_BITGET(event_handler_p->event_types.w,
  30675                        bcmOAMEventBHHCCMUnknownMepIdClear)) {
  30676             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR;
  30677         }
  30678         if (SHR_BITGET(event_handler_p->event_types.w,
  30679                        bcmOAMEventBHHCCMUnknownPeriodClear)) {
  30680             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR;
  30681         }
  30682         if (SHR_BITGET(event_handler_p->event_types.w,
  30683                        bcmOAMEventBHHCCMUnknownPriorityClear)) {
  30684             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR;
  30685         }
  30686         if (SHR_BITGET(event_handler_p->event_types.w,
  30687                        bcmOAMEventBhhPmCounterRollover)) {
  30688             event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER;
  30689         }
  30690         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) {
  30691             event_mask |= BHH_BTE_EVENT_CSF_LOS;
  30692         }
  30693         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) {
  30694             event_mask |= BHH_BTE_EVENT_CSF_FDI;
  30695         }
  30696         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) {
  30697             event_mask |= BHH_BTE_EVENT_CSF_RDI;
  30698         }
  30699         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) {
  30700             event_mask |= BHH_BTE_EVENT_CSF_DCI;
  30701         }
  30702     }
  30703 
  30704     /* Update BHH event mask in uKernel */
  30705     if (event_mask != oc->event_mask) {
  30706         /* Send BHH Event Mask message to uC */
  30707         rv = _bcm_sb2_oam_bhh_msg_send_receive
  30708                 (unit,
  30709                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET,
  30710                  0, event_mask,
  30711                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY,
  30712                  &reply_len);
  30713 
  30714         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  30715             rv = BCM_E_INTERNAL;
  30716         }
  30717     }
  30718 
  30719     oc->event_mask = event_mask;
  30720 
  30721     return (rv);
  30722 }
  30723 
  30724 /*
  30725  * Function:
  30726  *     bcm_sb2_oam_loopback_add
  30727  * Purpose:
  30728  *     
  30729  * Parameters:
  30730  *     unit - Device unit number
  30731  * Returns:
  30732  *     None
  30733  */
  30734 int
  30735 bcm_sb2_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p)
  30736 {
  30737     _bcm_oam_control_t *oc;
  30738     _bcm_oam_hash_data_t *h_data_p;
  30739     int rv = BCM_E_NONE;
  30740     bhh_sdk_msg_ctrl_loopback_add_t msg;
  30741     uint8 *buffer, *buffer_ptr;
  30742     uint16 buffer_len, reply_len;
  30743     uint32 flags = 0;
  30744     int sess_id = 0, i = 0;
  30745     _bhh_oam_lm_dm_info_t counter_info;
  30746     bcm_module_t         module_id;
  30747     bcm_port_t           port_id;
  30748     bcm_trunk_t          trunk_id;
  30749     int                  local_id;
  30750     uint8                encap_type;
  30751 
  30752     /* Get OAM Control Structure. */
  30753     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30754 
  30755     _BCM_OAM_LOCK(oc);
  30756 
  30757     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  30758 
  30759     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  30760 
  30761     /* Check endpoint status. */
  30762     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  30763     if ((BCM_E_EXISTS != rv)) {
  30764         /* Endpoint not in use. */
  30765         LOG_ERROR(BSL_LS_BCM_OAM,
  30766                   (BSL_META_U(unit,
  30767                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  30768                    unit, loopback_p->id, bcm_errmsg(rv)));
  30769         _BCM_OAM_UNLOCK(oc);
  30770         return (rv);
  30771     }
  30772 
  30773     h_data_p = &oc->oam_hash_data[loopback_p->id];
  30774 
  30775     rv = _bcm_sb2_oam_period_validate(loopback_p->period);
  30776     if (BCM_FAILURE(rv)) {
  30777         LOG_ERROR(BSL_LS_BCM_OAM,
  30778                   (BSL_META_U(unit,
  30779                               "OAM(unit %d) Error: Invalid period : %d\n"),
  30780                    unit, loopback_p->period));
  30781         _BCM_OAM_UNLOCK(oc);
  30782         return (rv);
  30783     }
  30784 
  30785     sal_memset(&counter_info, 0, sizeof(counter_info));
  30786     counter_info.counter_size = loopback_p->lb_tx_update_lm_counter_size; 
  30787     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
  30788     {
  30789         counter_info.counter_base_id[i] = 
  30790         loopback_p->lb_tx_update_lm_counter_base_id[i];
  30791         counter_info.counter_offset[i] = 
  30792         loopback_p->lb_tx_update_lm_counter_offset[i];
  30793         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
  30794         counter_info.byte_count_offset[i] = 0;
  30795     }
  30796     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
  30797 
  30798     /*
  30799      * Only BHH is supported
  30800      */
  30801     if (BHH_EP_TYPE(h_data_p)) {
  30802 
  30803         /*
  30804          * Convert host space flags to uKernel space flags
  30805          */
  30806 
  30807         if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) {
  30808             flags |= BCM_BHH_TX_ENABLE;
  30809         }
  30810 
  30811         if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) {
  30812             flags |= BCM_BHH_INC_REQUESTING_MEP_TLV;
  30813         }
  30814 
  30815         if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  30816             flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  30817         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  30818             flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  30819         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) {
  30820             flags |= BCM_BHH_LBM_ICC_MEP_TLV;
  30821         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) {
  30822             flags |= BCM_BHH_LBM_ICC_MIP_TLV;
  30823         } else {
  30824             flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */
  30825         }
  30826 
  30827         if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) {
  30828             flags |= BCM_BHH_LBR_ICC_MEP_TLV;
  30829         } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) {
  30830             flags |= BCM_BHH_LBR_ICC_MIP_TLV;
  30831         }
  30832 
  30833         sal_memset(&msg, 0, sizeof(msg));
  30834         msg.flags   = flags;
  30835         msg.sess_id = sess_id;
  30836         msg.int_pri = loopback_p->int_pri;
  30837         msg.pkt_pri = loopback_p->pkt_pri;
  30838 
  30839         /*
  30840          * Set period
  30841          */
  30842         msg.period  = _sb2_ccm_intervals[
  30843                              _bcm_sb2_oam_ccm_msecs_to_hw_encode(
  30844                                                                  loopback_p->period)];
  30845 
  30846         /*
  30847          * Check TTL
  30848          */
  30849         if (loopback_p->ttl == 0 || loopback_p->ttl > 255) {
  30850             _BCM_OAM_UNLOCK(oc);
  30851             return BCM_E_PARAM;
  30852         }
  30853 
  30854         /* Check for default usage of int_pri */
  30855         if (loopback_p->int_pri == -1) {
  30856             loopback_p->int_pri = 7; /*Use default */
  30857         }
  30858         /* Check for default usage of pkt_pri */
  30859         if (loopback_p->pkt_pri == 0xff) {
  30860             loopback_p->pkt_pri = 7; /*Use default */
  30861         }
  30862         if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) ||
  30863             (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  30864              h_data_p->vccv_type == bcmOamBhhVccvTtl)) {
  30865 
  30866             msg.ttl = 1; /* Only TTL 1 is valid */
  30867         } else {
  30868             msg.ttl = loopback_p->ttl;
  30869         }
  30870 
  30871         if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
  30872             rv = _bcm_esw_gport_resolve(unit,
  30873                     h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
  30874         } else {
  30875             rv = _bcm_esw_gport_resolve(unit,
  30876                     h_data_p->resolved_trunk_gport, &module_id, &port_id, 
  30877                     &trunk_id, &local_id);
  30878         }
  30879 
  30880         /*
  30881          * Set the BHH encapsulation data
  30882          *
  30883          * The function _bcm_sb2_oam_bhh_encap_create() is called first
  30884          * since this sets some fields in 'hash_data' which are
  30885          * used in the message.
  30886          */
  30887         rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
  30888                                            msg.encap_data, &encap_type,
  30889                                            &msg.encap_length, &counter_info,
  30890                                            loopback_p->int_pri,
  30891                                            loopback_p->pkt_pri,
  30892                                            loopback_p->ttl);
  30893         if(BCM_FAILURE(rv))
  30894         {
  30895             LOG_ERROR(BSL_LS_BCM_OAM,
  30896                     (BSL_META_U(unit,
  30897                                 "BHH(unit %d) Error: Encap create failed "
  30898                                 " - %s.\n"),
  30899                      unit, bcm_errmsg(rv)));
  30900             _BCM_OAM_UNLOCK(oc);
  30901             return (rv);
  30902         }
  30903 
  30904         /* Pack control message data into DMA buffer */
  30905         buffer     = oc->dma_buffer;
  30906         buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg);
  30907         buffer_len = buffer_ptr - buffer;
  30908 
  30909         /* Send BHH Session Update message to uC */
  30910         rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  30911                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD,
  30912                                         buffer_len, 0,
  30913                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY,
  30914                                         &reply_len);
  30915 
  30916         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  30917             rv =  BCM_E_INTERNAL;
  30918         }
  30919     }
  30920     else {
  30921         rv = BCM_E_UNAVAIL;
  30922     }
  30923 
  30924     _BCM_OAM_UNLOCK(oc);
  30925     return (rv);
  30926 }
  30927 
  30928 /*
  30929  * Function:
  30930  *     bcm_sb2_oam_loopback_get
  30931  * Purpose:
  30932  *     
  30933  * Parameters:
  30934  *     unit - Device unit number
  30935  * Returns:
  30936  *     None
  30937  */
  30938 int
  30939 bcm_sb2_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p)
  30940 {
  30941     _bcm_oam_control_t *oc;
  30942     int rv = BCM_E_NONE;
  30943     bhh_sdk_msg_ctrl_loopback_get_t msg;
  30944     _bcm_oam_hash_data_t *h_data_p;
  30945     uint8 *buffer, *buffer_ptr;
  30946     uint16 buffer_len, reply_len;
  30947     int sess_id = 0;
  30948     uint8   ts_mode;
  30949     uint8 lm_pdu_counter_offset = 0;
  30950     uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX];
  30951     _mpls_label_t label;
  30952 
  30953 
  30954     /* Get OAM Control Structure. */
  30955     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  30956 
  30957     _BCM_OAM_LOCK(oc);
  30958 
  30959     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  30960 
  30961     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  30962 
  30963     /* Check endpoint status. */
  30964     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  30965     if ((BCM_E_EXISTS != rv)) {
  30966         /* Endpoint not in use. */
  30967         LOG_ERROR(BSL_LS_BCM_OAM,
  30968                   (BSL_META_U(unit,
  30969                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  30970                    unit, loopback_p->id, bcm_errmsg(rv)));
  30971         _BCM_OAM_UNLOCK(oc);
  30972         return (rv);
  30973     }
  30974 
  30975     h_data_p = &oc->oam_hash_data[loopback_p->id];
  30976 
  30977     /*
  30978      * Only BHH is supported
  30979      */
  30980     if (BHH_EP_TYPE(h_data_p)) {
  30981 
  30982         sal_memset(&msg, 0, sizeof(msg));
  30983         /* Send BHH Session Update message to uC */
  30984         rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  30985                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET,
  30986                                         sess_id, 0,
  30987                                         MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY,
  30988                                         &reply_len);
  30989         if(BCM_FAILURE(rv)) {
  30990             LOG_ERROR(BSL_LS_BCM_OAM,
  30991                       (BSL_META_U(unit,
  30992                                   "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  30993                        unit, loopback_p->id, bcm_errmsg(rv)));
  30994             _BCM_OAM_UNLOCK(oc);
  30995             return (rv);
  30996         }
  30997 
  30998         /* Pack control message data into DMA buffer */
  30999         buffer     = oc->dma_buffer;
  31000         buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg);
  31001         buffer_len = buffer_ptr - buffer;
  31002 
  31003 
  31004         if (reply_len != buffer_len) {
  31005             rv =  BCM_E_INTERNAL;
  31006         } else {
  31007             /*
  31008              * Convert kernel space flags to host space flags
  31009              */
  31010             if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) {
  31011                 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV;
  31012             }
  31013 
  31014             if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  31015                 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  31016             } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  31017                 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  31018             } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) {
  31019                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV;
  31020             } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) {
  31021                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV;
  31022             }
  31023 
  31024             if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) {
  31025                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV;
  31026             } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) {
  31027                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV;
  31028             }
  31029 
  31030             if (msg.flags & BCM_BHH_TX_ENABLE) {
  31031                 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE;
  31032             }
  31033 
  31034             loopback_p->period                  = msg.period;
  31035             loopback_p->ttl                     = msg.ttl;
  31036             loopback_p->discovered_me.flags     = msg.discovery_flags;
  31037             loopback_p->discovered_me.name      = msg.discovery_id;
  31038             loopback_p->discovered_me.ttl       = msg.discovery_ttl;
  31039             loopback_p->rx_count                = msg.rx_count;
  31040             loopback_p->tx_count                = msg.tx_count;
  31041             loopback_p->drop_count              = msg.drop_count;
  31042             loopback_p->unexpected_response     = msg.unexpected_response;
  31043             loopback_p->out_of_sequence         = msg.out_of_sequence;
  31044             loopback_p->local_mipid_missmatch   = msg.local_mipid_missmatch;
  31045             loopback_p->remote_mipid_missmatch  = msg.remote_mipid_missmatch;
  31046             loopback_p->invalid_target_mep_tlv  = msg.invalid_target_mep_tlv;
  31047             loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype;
  31048             loopback_p->invalid_tlv_offset      = msg.invalid_tlv_offset;
  31049             if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  31050                 /* If this feature is valid, then encap_data is valid */
  31051                 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 
  31052                                 msg.encap_data,
  31053                                 &(loopback_p->lb_tx_update_lm_counter_size), 
  31054                                 loopback_p->lb_tx_update_lm_counter_base_id,
  31055                                 loopback_p->lb_tx_update_lm_counter_offset,
  31056                                 lm_counter_action,
  31057                                 &ts_mode,
  31058                                 &lm_pdu_counter_offset,
  31059                                 &(loopback_p->int_pri),
  31060                                 NULL)))
  31061                 {
  31062                     _BCM_OAM_UNLOCK(oc);
  31063                     return (BCM_E_INTERNAL);
  31064                 }
  31065                 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p,
  31066                                                              msg.encap_data,
  31067                                                              msg.encap_length,
  31068                                                              &label);
  31069                 loopback_p->pkt_pri = label.exp;
  31070                 loopback_p->ttl = label.ttl;
  31071             }
  31072 
  31073             rv = BCM_E_NONE;
  31074         }
  31075     }
  31076     else {
  31077         rv = BCM_E_UNAVAIL;
  31078     }
  31079 
  31080     _BCM_OAM_UNLOCK(oc);
  31081 
  31082     return (rv);
  31083 }
  31084 
  31085 /*
  31086  * Function:
  31087  *     bcm_sb2_oam_loopback_delete
  31088  * Purpose:
  31089  *     
  31090  * Parameters:
  31091  *     unit - Device unit number
  31092  * Returns:
  31093  *     None
  31094  */
  31095 int
  31096 bcm_sb2_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p)
  31097 {
  31098     _bcm_oam_control_t *oc;
  31099     int rv = BCM_E_NONE;
  31100     shr_bhh_msg_ctrl_loopback_delete_t msg;
  31101     uint8 *buffer, *buffer_ptr;
  31102     uint16 buffer_len, reply_len;
  31103     int sess_id = 0;
  31104     _bcm_oam_hash_data_t *h_data_p;
  31105 
  31106     /* Get OAM Control Structure. */
  31107     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  31108 
  31109     _BCM_OAM_LOCK(oc);
  31110 
  31111     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  31112 
  31113     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  31114 
  31115     /* Check endpoint status. */
  31116     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  31117     if ((BCM_E_EXISTS != rv)) {
  31118         /* Endpoint not in use. */
  31119         LOG_ERROR(BSL_LS_BCM_OAM,
  31120                   (BSL_META_U(unit,
  31121                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31122                    unit, loopback_p->id, bcm_errmsg(rv)));
  31123         _BCM_OAM_UNLOCK(oc);
  31124         return (rv);
  31125     }
  31126 
  31127     h_data_p = &oc->oam_hash_data[loopback_p->id];
  31128 
  31129     /*
  31130      * Only BHH is supported
  31131      */
  31132     if (BHH_EP_TYPE(h_data_p)) {
  31133 
  31134         msg.sess_id = sess_id;
  31135 
  31136         /* Pack control message data into DMA buffer */
  31137         buffer     = oc->dma_buffer;
  31138         buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg);
  31139         buffer_len = buffer_ptr - buffer;
  31140 
  31141         /* Send BHH Session Update message to uC */
  31142         rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  31143                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE,
  31144                       buffer_len, 0,
  31145                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY,
  31146                       &reply_len);
  31147 
  31148         if(BCM_SUCCESS(rv) && (reply_len != 0))
  31149             rv =  BCM_E_INTERNAL;
  31150     }
  31151     else {
  31152         _BCM_OAM_UNLOCK(oc);
  31153         return BCM_E_UNAVAIL;
  31154     }
  31155 
  31156     _BCM_OAM_UNLOCK(oc);
  31157 
  31158     return (rv);
  31159 }
  31160 
  31161 /*
  31162  * Function:
  31163  *      bcm_sb2_oam_csf_add
  31164  * Purpose:
  31165  *      Start CSF PDU transmission
  31166  * Parameters:
  31167  *      unit    - (IN)    Unit number.
  31168  *      csf_ptr - (INOUT) CSF object
  31169  * Returns:
  31170  *      BCM_E_XXX
  31171  * Notes:
  31172  */
  31173 int bcm_sb2_oam_csf_add(int unit, bcm_oam_csf_t *csf_p)
  31174 {
  31175     _bcm_oam_control_t         *oc;
  31176     _bcm_oam_hash_data_t       *h_data_p;
  31177     bhh_sdk_msg_ctrl_csf_add_t  msg;
  31178     uint8                      *buffer, *buffer_ptr;
  31179     uint16                      buffer_len, reply_len;
  31180     _bhh_oam_lm_dm_info_t       counter_info;
  31181     bcm_module_t                module_id;
  31182     bcm_port_t                  port_id;
  31183     bcm_trunk_t                 trunk_id;
  31184     int                         local_id;
  31185     uint8                       encap_type;
  31186     int                         sess_id = 0;
  31187     int                         i;
  31188     int                         rv = BCM_E_NONE;
  31189 
  31190     /* Get OAM Control Structure. */
  31191     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  31192     _BCM_OAM_LOCK(oc);
  31193 
  31194     if (oc->ukernel_not_ready) {
  31195         _BCM_OAM_UNLOCK(oc);
  31196         return BCM_E_INIT;
  31197     }
  31198 
  31199     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  31200     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  31201 
  31202     /* Check endpoint status. */
  31203     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  31204     if ((BCM_E_EXISTS != rv)) {
  31205         /* Endpoint not in use. */
  31206         LOG_ERROR(BSL_LS_BCM_OAM,
  31207                   (BSL_META_U(unit,
  31208                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31209                    unit, csf_p->id, bcm_errmsg(rv)));
  31210         _BCM_OAM_UNLOCK(oc);
  31211         return (rv);
  31212     }
  31213 
  31214     if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) &&
  31215         (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) {
  31216         /* Only 1S and 1M are supported */
  31217         _BCM_OAM_UNLOCK(oc);
  31218         return BCM_E_PARAM;
  31219     }
  31220 
  31221     h_data_p = &oc->oam_hash_data[csf_p->id];
  31222     /*
  31223      * Only BHH is supported
  31224      */
  31225     if (!BHH_EP_TYPE(h_data_p)) {
  31226         _BCM_OAM_UNLOCK(oc);
  31227         return BCM_E_UNAVAIL;
  31228     }
  31229 
  31230     sal_memset(&counter_info, 0, sizeof(counter_info));
  31231     counter_info.counter_size = csf_p->csf_tx_update_lm_counter_size;
  31232     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) {
  31233         counter_info.counter_base_id[i] =
  31234                        csf_p->csf_tx_update_lm_counter_base_id[i];
  31235         counter_info.counter_offset[i] =
  31236                        csf_p->csf_tx_update_lm_counter_offset[i];
  31237         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
  31238     }
  31239     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
  31240 
  31241     sal_memset(&msg, 0, sizeof(msg));
  31242     msg.sess_id = sess_id;
  31243     msg.int_pri = csf_p->int_pri;
  31244     msg.pkt_pri = csf_p->pkt_pri;
  31245 
  31246     switch(csf_p->type) {
  31247         case BCM_OAM_CSF_LOS:
  31248             msg.type = SHR_CSF_TYPE_LOS;
  31249             break;
  31250 
  31251         case BCM_OAM_CSF_FDI:
  31252             msg.type = SHR_CSF_TYPE_FDI;
  31253             break;
  31254 
  31255         case BCM_OAM_CSF_RDI:
  31256             msg.type = SHR_CSF_TYPE_RDI;
  31257             break;
  31258 
  31259         case BCM_OAM_CSF_DCI:
  31260             msg.type = SHR_CSF_TYPE_DCI;
  31261             break;
  31262 
  31263         default:
  31264             _BCM_OAM_UNLOCK(oc);
  31265             return BCM_E_PARAM;
  31266     }
  31267 
  31268     /*
  31269      * Set period
  31270      */
  31271     msg.period  = csf_p->period;
  31272 
  31273     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
  31274         rv = _bcm_esw_gport_resolve(unit, h_data_p->gport,
  31275                                     &module_id, &port_id,
  31276                                     &trunk_id, &local_id);
  31277     } else {
  31278         rv = _bcm_esw_gport_resolve(unit,
  31279                                     h_data_p->resolved_trunk_gport,
  31280                                     &module_id, &port_id,
  31281                                     &trunk_id, &local_id);
  31282     }
  31283     if (rv != BCM_E_NONE) {
  31284         _BCM_OAM_UNLOCK(oc);
  31285         return rv;
  31286     }
  31287 
  31288     /*
  31289      * Set the BHH encapsulation data
  31290  */
  31291     rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
  31292                                        msg.encap_data, &encap_type,
  31293                                        &msg.encap_length, &counter_info,
  31294                                        csf_p->int_pri, csf_p->pkt_pri,
  31295                                        h_data_p->egr_label_ttl);
  31296     if(BCM_FAILURE(rv)) {
  31297         LOG_ERROR(BSL_LS_BCM_OAM,
  31298                   (BSL_META_U(unit,
  31299                               "BHH(unit %d) Error: Encap create failed "
  31300                               " - %s.\n"),
  31301                    unit, bcm_errmsg(rv)));
  31302         _BCM_OAM_UNLOCK(oc);
  31303         return rv;
  31304     }
  31305 
  31306     /* Pack control message data into DMA buffer */
  31307     buffer     = oc->dma_buffer;
  31308     buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg);
  31309     buffer_len = buffer_ptr - buffer;
  31310 
  31311     /* Send BHH Session Update message to uC */
  31312     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  31313                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD,
  31314                                            buffer_len, 0,
  31315                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY,
  31316                                            &reply_len);
  31317 
  31318     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  31319         rv =  BCM_E_INTERNAL;
  31320     }
  31321 
  31322     _BCM_OAM_UNLOCK(oc);
  31323     return rv;
  31324 }
  31325 
  31326 /*
  31327  * Function:
  31328  *      bcm_sb2_oam_csf_get
  31329  * Purpose:
  31330  *      Get CSF info
  31331  * Parameters:
  31332  *      unit    - (IN)  Unit number.
  31333  *      csf_ptr - (OUT) CSF object
  31334  * Returns:
  31335  *      BCM_E_XXX
  31336  * Notes:
  31337  */
  31338 int bcm_sb2_oam_csf_get(int unit, bcm_oam_csf_t *csf_p)
  31339 {
  31340     _bcm_oam_control_t          *oc;
  31341     bhh_sdk_msg_ctrl_csf_get_t   msg;
  31342     _bcm_oam_hash_data_t        *h_data_p;
  31343     uint8                       *buffer, *buffer_ptr;
  31344     uint16                       buffer_len, reply_len;
  31345     uint8                        ts_mode;
  31346     uint8                        lm_pdu_counter_offset = 0;
  31347     uint8                        lm_counter_action[BCM_OAM_LM_COUNTER_MAX];
  31348     _mpls_label_t                label;
  31349     int                          sess_id = 0;
  31350     int                          rv = BCM_E_NONE;
  31351 
  31352 
  31353     /* Get OAM Control Structure. */
  31354     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  31355     _BCM_OAM_LOCK(oc);
  31356 
  31357     if (oc->ukernel_not_ready) {
  31358         _BCM_OAM_UNLOCK(oc);
  31359         return BCM_E_INIT;
  31360     }
  31361 
  31362     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  31363     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  31364 
  31365     /* Check endpoint status. */
  31366     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  31367     if ((BCM_E_EXISTS != rv)) {
  31368         /* Endpoint not in use. */
  31369         LOG_ERROR(BSL_LS_BCM_OAM,
  31370                   (BSL_META_U(unit,
  31371                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31372                    unit, csf_p->id, bcm_errmsg(rv)));
  31373         _BCM_OAM_UNLOCK(oc);
  31374         return (rv);
  31375     }
  31376 
  31377     h_data_p = &oc->oam_hash_data[csf_p->id];
  31378 
  31379     if (!BHH_EP_TYPE(h_data_p)) {
  31380         _BCM_OAM_UNLOCK(oc);
  31381         return BCM_E_UNAVAIL;
  31382     }
  31383 
  31384 
  31385     sal_memset(&msg, 0, sizeof(msg));
  31386 
  31387     /* Send BHH Session Update message to uC */
  31388     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  31389                                            MOS_MSG_SUBCLASS_BHH_CSF_GET,
  31390                                            sess_id, 0,
  31391                                            MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY,
  31392                                            &reply_len);
  31393     if(BCM_FAILURE(rv)) {
  31394         LOG_ERROR(BSL_LS_BCM_OAM,
  31395                   (BSL_META_U(unit,
  31396                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31397                    unit, csf_p->id, bcm_errmsg(rv)));
  31398         _BCM_OAM_UNLOCK(oc);
  31399         return (rv);
  31400     }
  31401 
  31402     /* Pack control message data into DMA buffer */
  31403     buffer     = oc->dma_buffer;
  31404     buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg);
  31405     buffer_len = buffer_ptr - buffer;
  31406 
  31407 
  31408     if (reply_len != buffer_len) {
  31409         _BCM_OAM_UNLOCK(oc);
  31410         return BCM_E_INTERNAL;
  31411     }
  31412 
  31413     switch(msg.type) {
  31414         case SHR_CSF_TYPE_LOS:
  31415             csf_p->type = BCM_OAM_CSF_LOS;
  31416             break;
  31417 
  31418         case SHR_CSF_TYPE_FDI:
  31419             csf_p->type = BCM_OAM_CSF_FDI;
  31420             break;
  31421 
  31422         case SHR_CSF_TYPE_RDI:
  31423             csf_p->type = BCM_OAM_CSF_RDI;
  31424             break;
  31425 
  31426         case SHR_CSF_TYPE_DCI:
  31427             csf_p->type = BCM_OAM_CSF_DCI;
  31428             break;
  31429 
  31430         default:
  31431             _BCM_OAM_UNLOCK(oc);
  31432             return BCM_E_INTERNAL;
  31433     }
  31434 
  31435     csf_p->period = msg.period;
  31436     csf_p->flags  = msg.flags;
  31437 
  31438     rv = _bcm_sb2_oam_olp_encap_header_decap(unit, msg.encap_data,
  31439                                           &(csf_p->csf_tx_update_lm_counter_size),
  31440                                           csf_p->csf_tx_update_lm_counter_base_id,
  31441                                           csf_p->csf_tx_update_lm_counter_offset,
  31442                                           lm_counter_action, &ts_mode,
  31443                                           &lm_pdu_counter_offset,
  31444                                           &(csf_p->int_pri),
  31445                                           NULL);
  31446     if (rv != BCM_E_NONE) {
  31447         _BCM_OAM_UNLOCK(oc);
  31448         return rv;
  31449     }
  31450 
  31451     _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, msg.encap_data,
  31452                                                  msg.encap_length, &label);
  31453     csf_p->pkt_pri = label.exp;
  31454 
  31455     _BCM_OAM_UNLOCK(oc);
  31456     return BCM_E_NONE;
  31457 
  31458 }
  31459 
  31460 /*
  31461  * Function:
  31462  *      bcm_sb2_oam_csf_delete
  31463  * Purpose:
  31464  *      Stop CSF PDU transmission
  31465  * Parameters:
  31466  *      unit    - (IN  Unit number.
  31467  *      csf_ptr - (IN) CSF object
  31468  * Returns:
  31469  *      BCM_E_XXX
  31470  * Notes:
  31471  */
  31472 int bcm_sb2_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p)
  31473 {
  31474     _bcm_oam_control_t   *oc;
  31475     _bcm_oam_hash_data_t *h_data_p;
  31476     uint16                reply_len;
  31477     int                   sess_id;
  31478     int                   rv = BCM_E_NONE;
  31479 
  31480     /* Get OAM Control Structure. */
  31481     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  31482     _BCM_OAM_LOCK(oc);
  31483 
  31484     if (oc->ukernel_not_ready) {
  31485         _BCM_OAM_UNLOCK(oc);
  31486         return BCM_E_INIT;
  31487     }
  31488 
  31489     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  31490     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  31491 
  31492     /* Check endpoint status. */
  31493     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  31494     if ((BCM_E_EXISTS != rv)) {
  31495         /* Endpoint not in use. */
  31496         LOG_ERROR(BSL_LS_BCM_OAM,
  31497                   (BSL_META_U(unit,
  31498                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31499                    unit, csf_p->id, bcm_errmsg(rv)));
  31500         _BCM_OAM_UNLOCK(oc);
  31501         return (rv);
  31502     }
  31503 
  31504     h_data_p = &oc->oam_hash_data[csf_p->id];
  31505 
  31506     if (!BHH_EP_TYPE(h_data_p)) {
  31507         _BCM_OAM_UNLOCK(oc);
  31508         return BCM_E_UNAVAIL;
  31509     }
  31510 
  31511     /* Send BHH Session Update message to uC */
  31512     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  31513                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE,
  31514                                            sess_id, 0,
  31515                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY,
  31516                                            &reply_len);
  31517 
  31518     _BCM_OAM_UNLOCK(oc);
  31519     return (rv);
  31520 }
  31521 
  31522 #endif /*(INCLUDE_BHH)*/
  31523 
  31524 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM)
  31525 /*
  31526  * Function:
  31527  *     bcm_sb2_oam_loss_add
  31528  * Purpose:
  31529  *        Loss Measurement add     
  31530  * Parameters:
  31531  *     unit - Device unit number
  31532  * Returns:
  31533  *     None
  31534  */
  31535 int
  31536 bcm_sb2_oam_loss_add(int unit, bcm_oam_loss_t *loss_p)
  31537 {
  31538     _bcm_oam_control_t *oc;
  31539     _bcm_oam_hash_data_t *h_data_p;
  31540     int rv = BCM_E_NONE; 
  31541 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM)
  31542     uint8 *buffer, *buffer_ptr;
  31543     uint16 buffer_len, reply_len;
  31544     uint32 flags = 0;
  31545     int sess_id = 0;
  31546 #endif
  31547 #if defined(INCLUDE_BHH)
  31548     _bhh_oam_lm_dm_info_t counter_info;
  31549     bcm_module_t         module_id;
  31550     bcm_port_t           port_id;
  31551     bcm_trunk_t          trunk_id;
  31552     int                  local_id, i = 0;
  31553     uint8                encap_type;
  31554 #endif
  31555 
  31556     /* Get OAM Control Structure. */
  31557     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  31558     _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id);
  31559     _BCM_OAM_LOCK(oc);
  31560 
  31561 
  31562     h_data_p = &oc->oam_hash_data[loss_p->id];
  31563 
  31564     if (!(h_data_p->in_use)) {
  31565         /* Endpoint not in use. */
  31566         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  31567             "Endpoint EP=%d not configured.\n"), unit, loss_p->id));
  31568         _BCM_OAM_UNLOCK(oc);
  31569         return BCM_E_NOT_FOUND;
  31570     }
  31571 #if defined(INCLUDE_MPLS_LM_DM)
  31572     /* Check if EP type is MPLS_LM_DM, call respective routine */
  31573     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  31574         if (oc->mpls_lm_dm_ukernel_ready) {
  31575             rv = _bcm_sb2_mpls_lm_dm_loss_add(unit, h_data_p, loss_p);
  31576             _BCM_OAM_UNLOCK(oc);
  31577             return rv;
  31578         } else {
  31579             _BCM_OAM_UNLOCK(oc);
  31580             return BCM_E_UNAVAIL;
  31581         }
  31582     }
  31583 #endif
  31584     /*
  31585      *  BHH and ETH LM/DM is supported
  31586      */
  31587     if (BHH_EP_TYPE(h_data_p)) {	
  31588 
  31589 #if defined (INCLUDE_BHH)
  31590     bhh_sdk_msg_ctrl_loss_add_t msg;
  31591 
  31592     if (oc->ukernel_not_ready) {
  31593         _BCM_OAM_UNLOCK(oc);
  31594         return BCM_E_INIT;
  31595     }
  31596 
  31597     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  31598 
  31599     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  31600     
  31601     /* Check endpoint status. */
  31602     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  31603     if ((BCM_E_EXISTS != rv)) {
  31604         /* Endpoint not in use. */
  31605         LOG_ERROR(BSL_LS_BCM_OAM,
  31606                   (BSL_META_U(unit,
  31607                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  31608                    unit, loss_p->id, bcm_errmsg(rv)));
  31609         _BCM_OAM_UNLOCK(oc);
  31610         return (rv);
  31611     }
  31612     if (h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) {
  31613         LOG_ERROR(BSL_LS_BCM_OAM,
  31614                   (BSL_META_U(unit,
  31615                               "OAM(unit %d) Error: Proactive LM is enabled "
  31616                               " on Endpoint EP=%d \n"), unit, loss_p->id));
  31617         _BCM_OAM_UNLOCK(oc);
  31618         return BCM_E_PARAM;
  31619     }
  31620     if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  31621         _BCM_OAM_UNLOCK(oc);
  31622         return BCM_E_PARAM;
  31623     }
  31624 
  31625     /*
  31626      * Convert host space flags to uKernel space flags
  31627      */
  31628     if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) {
  31629         flags |= BCM_BHH_LM_SINGLE_ENDED;
  31630     }
  31631 
  31632     if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) {
  31633         flags |= BCM_BHH_LM_TX_ENABLE;
  31634     }
  31635 
  31636     if (loss_p->flags & BCM_OAM_LOSS_SLM) {
  31637         flags |= BCM_BHH_LM_SLM;
  31638     }
  31639 
  31640     rv = _bcm_sb2_oam_period_validate(loss_p->period);
  31641     if (BCM_FAILURE(rv)) {
  31642         LOG_ERROR(BSL_LS_BCM_OAM,
  31643                   (BSL_META_U(unit,
  31644                               "OAM(unit %d) Error: Invalid period : %d\n"),
  31645                    unit, loss_p->period));
  31646         _BCM_OAM_UNLOCK(oc);
  31647         return rv;
  31648     }
  31649     sal_memset(&counter_info, 0, sizeof(counter_info));
  31650     counter_info.counter_size = loss_p->lm_counter_size;
  31651     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
  31652     {
  31653         counter_info.counter_base_id[i] = loss_p->lm_counter_base_id[i];
  31654         counter_info.counter_offset[i] = loss_p->lm_counter_offset[i];
  31655         counter_info.counter_action[i] = loss_p->lm_counter_action[i];
  31656         counter_info.byte_count_offset[i] = 0;
  31657     }
  31658     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
  31659     counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH;
  31660 
  31661     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
  31662         rv = _bcm_esw_gport_resolve(unit,
  31663                 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
  31664     } else {
  31665         rv = _bcm_esw_gport_resolve(unit,
  31666                 h_data_p->resolved_trunk_gport, &module_id, &port_id, 
  31667                 &trunk_id, &local_id);
  31668         
  31669     } 
  31670     sal_memset(&msg, 0, sizeof(msg));
  31671     msg.flags   = flags;
  31672     msg.sess_id = sess_id;
  31673 
  31674     /*
  31675      * Set period
  31676      */
  31677 	msg.period  = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(loss_p->period)];
  31678     msg.int_pri = loss_p->int_pri;
  31679     msg.pkt_pri = loss_p->pkt_pri;
  31680 
  31681     rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
  31682                                        msg.encap_data, &encap_type,
  31683                                        &msg.encap_length, &counter_info,
  31684                                        loss_p->int_pri, loss_p->pkt_pri,
  31685                                        h_data_p->egr_label_ttl);
  31686 
  31687     if(BCM_FAILURE(rv))
  31688     {
  31689         LOG_ERROR(BSL_LS_BCM_OAM,
  31690                 (BSL_META_U(unit,
  31691                             "BHH(unit %d) Error: Encap create failed "
  31692                             "- %s.\n"),
  31693                  unit, bcm_errmsg(rv)));
  31694         _BCM_OAM_UNLOCK(oc);
  31695         return (rv);
  31696     }
  31697 
  31698     /* Pack control message data into DMA buffer */
  31699     buffer     = oc->dma_buffer;
  31700     buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg);
  31701     buffer_len = buffer_ptr - buffer;
  31702 
  31703 
  31704     /* Send BHH Session Update message to uC */
  31705     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  31706                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD,
  31707                       buffer_len, 0,
  31708                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY,
  31709                       &reply_len);
  31710 
  31711     loss_p->pm_id = sess_id;
  31712 
  31713     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
  31714         rv =  BCM_E_INTERNAL;
  31715 #endif        
  31716     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  31717 #if defined(INCLUDE_ETH_LM_DM)    
  31718 	shr_eth_lm_dm_msg_ctrl_loss_add_t msg;
  31719     bcm_port_t           port_id;
  31720     bcm_module_t         module_id;
  31721     int                  local_id; 
  31722     bcm_trunk_t          trunk_id;
  31723     uint8                mep_type;
  31724     uint32               session_flags = 0;
  31725     shr_eth_lm_dm_msg_ctrl_sess_set_t msg_sess;
  31726     int                  cpu_modid;
  31727     bcm_port_t           cpu_port;
  31728     int                  cpu_dglp;
  31729     uint32             olp_l2_encap_length;
  31730 
  31731 
  31732     if (1 == oc->eth_lm_dm_ukernel_not_ready) {
  31733         LOG_ERROR(BSL_LS_BCM_OAM,
  31734                 (BSL_META_U(unit,
  31735                 "ETH_LM_DM(unit %d) Error: BTE(ukernel) not ready\n"),
  31736                  unit));
  31737         _BCM_OAM_UNLOCK(oc);
  31738         return (BCM_E_INIT);
  31739     }
  31740 
  31741     if (!(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
  31742         LOG_ERROR(BSL_LS_BCM_OAM,
  31743                   (BSL_META_U(unit,
  31744                    "ETH_LM_DM(unit %d) Error: loss measurement not available (EP=%d)\n"),
  31745                    unit, loss_p->id));
  31746         _BCM_OAM_UNLOCK(oc);
  31747         return BCM_E_UNAVAIL;
  31748 
  31749     }
  31750 
  31751    /* Get the Trunk, Port and Mod-id info for this G-port */
  31752     rv = _bcm_esw_gport_resolve(unit,
  31753             h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
  31754 
  31755     if (BCM_FAILURE(rv)) {
  31756         LOG_ERROR(BSL_LS_BCM_OAM,
  31757                 (BSL_META_U(unit,
  31758                 "ETH_LM_DM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  31759                 unit, loss_p->id, bcm_errmsg(rv)));
  31760         _BCM_OAM_UNLOCK(oc);
  31761         return (rv);
  31762     }
  31763 
  31764     /* Reserve and program session Id for this EP */
  31765     /* ------------------------------------------ */
  31766     if (h_data_p->lm_dm_uc_session_id == 0 ) {
  31767         rv = shr_idxres_list_alloc(oc->eth_lm_dm_pool,
  31768                                    (shr_idxres_element_t *)&sess_id);
  31769 
  31770         if (BCM_FAILURE(rv)) {
  31771             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "ETH_LM_DM (unit %d) Error:"
  31772                 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  31773                 bcm_errmsg(rv)));
  31774             _BCM_OAM_UNLOCK(oc);
  31775             return (rv);
  31776         }
  31777         h_data_p->lm_dm_uc_session_id = sess_id;
  31778     } else {
  31779         sess_id = h_data_p->lm_dm_uc_session_id;
  31780     }
  31781     oc->eth_lm_dm_sess_id_ep_id[sess_id] = h_data_p->ep_id;
  31782 
  31783    /* Set end-point type(dir) from the hash data flag*/
  31784     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  31785         mep_type = 1;
  31786     } else {
  31787         mep_type = 0;
  31788     }
  31789 
  31790     /* Get the cpu_dglp from cpu_modid and cpu_port*/
  31791     rv = bcm_esw_stk_my_modid_get(unit, &cpu_modid);
  31792     if (BCM_FAILURE(rv)) {
  31793         LOG_ERROR(BSL_LS_BCM_OAM,
  31794                 (BSL_META_U(unit,
  31795                             "OAM(unit %d) Error: MODID get failed - %s.\n"),
  31796                  unit, bcm_errmsg(rv)));
  31797         _BCM_OAM_UNLOCK(oc);
  31798         return (rv);
  31799     }
  31800     cpu_port = 0;
  31801     cpu_dglp = ((cpu_modid << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port);
  31802 
  31803     rv = _bcm_sb2_oam_eth_olp_encap_create(unit,
  31804                                            port_id,
  31805                                            cpu_dglp,
  31806                                            h_data_p,
  31807                                            msg_sess.encap_data,
  31808                                            &msg_sess.eth_l2_encap_length,
  31809                                            &olp_l2_encap_length,
  31810                                            loss_p->pkt_pri);
  31811     if (BCM_FAILURE(rv)) {
  31812         LOG_ERROR(BSL_LS_BCM_OAM,
  31813                   (BSL_META_U(unit,
  31814                    "ETH_LM_DM(unit %d) Error: encap create (EP=%d) - %s.\n"),
  31815                    unit, loss_p->id, bcm_errmsg(rv)));
  31816         _BCM_OAM_UNLOCK(oc);
  31817         return (rv);
  31818     }
  31819 
  31820 
  31821     msg_sess.sess_id = sess_id;
  31822     msg_sess.mep_id = h_data_p->ep_id;
  31823 
  31824     /* Set end-point type(dir) in session set message*/
  31825     msg_sess.mep_type = mep_type;
  31826     msg_sess.mel     = h_data_p->level;
  31827     msg_sess.vlan_id = h_data_p->inner_vlan;
  31828     msg_sess.outer_vlan_id = h_data_p->vlan;
  31829     msg_sess.lm_counter_index = h_data_p->tx_ctr;
  31830     msg_sess.group_id = h_data_p->group_index;
  31831     msg_sess.tx_port = port_id;
  31832 
  31833     /* Create or Update */
  31834     if (!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_SESSION_IS_SET)) {
  31835         session_flags = SHR_ETH_LM_DM_SESS_SET_F_CREATE;
  31836     }
  31837     session_flags |= SHR_ETH_LM_DM_SESS_SET_F_LM;
  31838 
  31839     if (h_data_p->lm_dm_int_flag & SHR_ETH_LM_DM_SESS_SET_F_DM) {
  31840         session_flags |= SHR_ETH_LM_DM_SESS_SET_F_DM;
  31841     }
  31842 
  31843 
  31844     msg_sess.flags = session_flags;
  31845 
  31846     /* Pack control message data into DMA buffer */
  31847     buffer     = oc->eth_lm_dm_dma_buffer;
  31848     buffer_ptr = shr_eth_lm_dm_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  31849     buffer_len = buffer_ptr - buffer;
  31850 
  31851     /* Send ETH LM/DM session set message to uC */
  31852     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  31853                                       MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET,
  31854                                       buffer_len, 0,
  31855                                       MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET_REPLY,
  31856                                       &reply_len);
  31857 
  31858     if(BCM_FAILURE(rv)) {
  31859         LOG_ERROR(BSL_LS_BCM_OAM,
  31860                   (BSL_META_U(unit,
  31861                         "OAM(unit %d) Error Session set: Endpoint EP=%d %s.\n"),
  31862                    unit, loss_p->id, bcm_errmsg(rv)));
  31863         _BCM_OAM_UNLOCK(oc);
  31864         return (rv);
  31865     }
  31866 
  31867     /* Session has been set in the endpoint */
  31868     h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_SESSION_IS_SET;
  31869 
  31870     /*
  31871      * Convert host space flags to uKernel space flags
  31872      */
  31873     if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) {
  31874         flags |= BCM_ETH_LM_SINGLE_ENDED;
  31875     }
  31876 
  31877     if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) {
  31878         flags |= BCM_ETH_LM_TX_ENABLE;
  31879     }
  31880 
  31881     if (loss_p->flags & BCM_OAM_LOSS_SLM) {
  31882         flags |= BCM_ETH_LM_SLM;
  31883     }
  31884 
  31885     if (loss_p->flags & BCM_OAM_LOSS_UPDATE) {
  31886         flags |= BCM_ETH_LM_UPDATE;
  31887     }
  31888 
  31889     msg.flags   = flags;
  31890     msg.sess_id = sess_id;
  31891     msg.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + loss_p->int_pri;
  31892     msg.period  =
  31893         _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(loss_p->period)];
  31894     msg.tx_cos = loss_p->int_pri;
  31895     msg.tx_pri = loss_p->pkt_pri;
  31896 
  31897     /* MAC-DA of loss_add struture is put into the L2 encap of Loss Tx control pkt*/
  31898     memcpy(msg.dst_mac, loss_p->peer_da_mac_address, sizeof(bcm_mac_t));
  31899 
  31900     msg.remote_mep_id = loss_p->remote_id;
  31901 
  31902     /* Put OLP_TX header in loss add structure */
  31903     rv = _bcm_sb2_oam_loss_olp_tx_encap_create(unit,
  31904                                                h_data_p,
  31905                                                msg.olp_tx_hdr,
  31906                                                &msg.olp_tx_hdr_length,
  31907                                                loss_p,
  31908                                                port_id,
  31909                                                module_id,
  31910                                                mep_type);
  31911 
  31912     /* Pack control message data into DMA buffer */
  31913     buffer     = oc->eth_lm_dm_dma_buffer;
  31914     buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_add_pack(buffer, &msg);
  31915     buffer_len = buffer_ptr - buffer;
  31916 
  31917     /* Send ETH LM/DM loss add message to uC */
  31918     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  31919                           MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_ADD,
  31920                           buffer_len, 0,
  31921                           MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_ADD_REPLY,
  31922                           &reply_len);
  31923 
  31924     h_data_p->lm_dm_int_flag |=  _ETH_LM_DM_F_LM_IS_SET;
  31925     
  31926     loss_p->pm_id = h_data_p->lm_dm_uc_session_id;
  31927 
  31928     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  31929         rv =  BCM_E_INTERNAL;
  31930     }
  31931 #endif
  31932     }
  31933     else {
  31934         _BCM_OAM_UNLOCK(oc);
  31935         return BCM_E_UNAVAIL;
  31936     }
  31937 
  31938     _BCM_OAM_UNLOCK(oc);
  31939     return (rv);
  31940 }
  31941 
  31942 int
  31943 bcm_sb2_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns)
  31944 {
  31945     int rv = BCM_E_NONE;
  31946 
  31947     if (bts != NULL) {
  31948         /* if both seconds and nanoseconds are negative or both positive,
  31949          * then the ucode's subtraction is ok.
  31950          * if seconds and nanoseconds have different signs, then "borrow"
  31951          * 1000000000 nanoseconds from seconds.
  31952          */
  31953         if ((sec < 0) && (ns > 0)) {
  31954             ns -= 1000000000;
  31955             sec += 1;
  31956         } else if ((sec > 0) && (ns < 0)) {
  31957             ns += 1000000000;
  31958             sec -= 1;
  31959         }
  31960 
  31961         if (ns < 0) {
  31962             /* if still negative, then something else is wrong.
  31963              * the nanoseconds field is the difference between two
  31964              * (non-negative) time-stamps.
  31965              */
  31966             rv = BCM_E_INTERNAL;
  31967         }
  31968 
  31969         /* if seconds is negative then set the bts is-negative flag,
  31970          * and use the absolute value of seconds & nanoseconds.
  31971          */
  31972         bts->isnegative  = (sec < 0 ? 1 : 0);
  31973         bts->seconds     = BCM_OAM_ABS(sec);
  31974         bts->nanoseconds = BCM_OAM_ABS(ns);
  31975     } else {
  31976         rv = BCM_E_INTERNAL;
  31977     }
  31978 
  31979     return rv;
  31980 }
  31981 
  31982 #ifdef _SABER2_DEBUG
  31983 /* d (difference) = m (minuend) - s (subtrahend) */
  31984 int
  31985 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s)
  31986 {
  31987     int rv = BCM_E_NONE;
  31988     int32 d_ns = 0;
  31989     int32 d_s = 0;
  31990 
  31991     if ((d != NULL) && (m != NULL) && (s != NULL)) {
  31992         /* subtract the nanoseconds first, then borrow is necessary. */
  31993         d_ns = m->nanoseconds - s->nanoseconds;
  31994         if (d_ns < 0) {
  31995             m->seconds = m->seconds - 1;
  31996             d_ns = 1000000000 + d_ns;
  31997         }
  31998         if (d_ns < 0) {
  31999             /* if still negative, then error */
  32000             rv = BCM_E_INTERNAL;
  32001             d_ns = abs(d_ns);
  32002         }
  32003         d->nanoseconds = d_ns;
  32004 
  32005         /* subtract the seconds next, check for negative. */
  32006         d_s = m->seconds - s->seconds;
  32007         if (d_s < 0) {
  32008             d->isnegative = TRUE;
  32009             d_s = abs(d_s);
  32010         } else {
  32011             d->isnegative = FALSE;
  32012         }
  32013         d->seconds = d_s;
  32014 
  32015     } else {
  32016         rv = BCM_E_INTERNAL;
  32017     }
  32018 
  32019     return rv;
  32020 }
  32021 #endif
  32022 
  32023 /*
  32024  * Function:
  32025  *     bcm_sb2_oam_loss_get
  32026  * Purpose:
  32027  *     Loss Measurement get
  32028  * Parameters:
  32029  *     unit - Device unit number
  32030  * Returns:
  32031  *     None
  32032  */
  32033 int
  32034 bcm_sb2_oam_loss_get(int unit, bcm_oam_loss_t *loss_p)
  32035 {
  32036     _bcm_oam_control_t *oc;
  32037     int rv = BCM_E_NONE;
  32038     _bcm_oam_hash_data_t *h_data_p;
  32039 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM)
  32040     uint8 *buffer, *buffer_ptr;
  32041     uint16 buffer_len, reply_len;
  32042     int sess_id = 0;
  32043 #endif
  32044 #if defined(INCLUDE_BHH)
  32045     uint8   ts_mode;
  32046     uint8   lm_pdu_counter_offset = 0;
  32047     uint8   counter_size = 0;
  32048     bcm_cos_t int_pri = 0;
  32049     _mpls_label_t label;
  32050     uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX];
  32051     int i;
  32052 #endif
  32053 
  32054     /* Get OAM Control Structure. */
  32055     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  32056     _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id);
  32057     _BCM_OAM_LOCK(oc);
  32058 
  32059     h_data_p = &oc->oam_hash_data[loss_p->id];
  32060     if (!(h_data_p->in_use)) {
  32061         /* Endpoint not in use. */
  32062         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  32063             "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv)));
  32064         _BCM_OAM_UNLOCK(oc);
  32065         return BCM_E_NOT_FOUND;
  32066     }
  32067 
  32068 #if defined(INCLUDE_MPLS_LM_DM)
  32069     /* Check if EP type is MPLS_LM_DM, call respective routine */
  32070     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  32071         if (oc->mpls_lm_dm_ukernel_ready) {
  32072             rv = _bcm_sb2_mpls_lm_dm_loss_get(unit, h_data_p, loss_p);
  32073             _BCM_OAM_UNLOCK(oc);
  32074             return rv;
  32075         } else {
  32076             _BCM_OAM_UNLOCK(oc);
  32077             return BCM_E_UNAVAIL;
  32078         }
  32079     }
  32080 #endif
  32081 
  32082     /*
  32083      * Only BHH is supported
  32084      */
  32085     if (BHH_EP_TYPE(h_data_p)) {
  32086 #if defined(INCLUDE_BHH)
  32087     bhh_sdk_msg_ctrl_loss_get_t msg;	
  32088 
  32089     if (oc->ukernel_not_ready) {
  32090         _BCM_OAM_UNLOCK(oc);
  32091         return BCM_E_INIT;
  32092     }
  32093 
  32094     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  32095 
  32096     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  32097 
  32098     /* Check endpoint status. */
  32099     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  32100     if ((BCM_E_EXISTS != rv)) {
  32101         /* Endpoint not in use. */
  32102         LOG_ERROR(BSL_LS_BCM_OAM,
  32103                   (BSL_META_U(unit,
  32104                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32105                    unit, loss_p->id, bcm_errmsg(rv)));
  32106         _BCM_OAM_UNLOCK(oc);
  32107         return (rv);
  32108     }
  32109 
  32110     sal_memset(&msg, 0, sizeof(msg));
  32111     /* Send BHH Session Update message to uC */
  32112     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  32113                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET,
  32114                       sess_id, 0,
  32115                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY,
  32116                       &reply_len);
  32117     if(BCM_FAILURE(rv)) {
  32118         LOG_ERROR(BSL_LS_BCM_OAM,
  32119                   (BSL_META_U(unit,
  32120                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32121                    unit, loss_p->id, bcm_errmsg(rv)));
  32122         _BCM_OAM_UNLOCK(oc);
  32123         return (rv);
  32124     }
  32125 
  32126     /* Pack control message data into DMA buffer */
  32127     buffer     = oc->dma_buffer;
  32128     buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg);
  32129     buffer_len = buffer_ptr - buffer;
  32130 
  32131     if (reply_len != buffer_len) {
  32132         rv =  BCM_E_INTERNAL;
  32133     } else {
  32134         /*
  32135          * Convert kernel space flags to host space flags
  32136          */
  32137         if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) {
  32138             loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
  32139         }
  32140 
  32141         if (msg.flags & BCM_BHH_LM_TX_ENABLE) {
  32142             loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  32143         }
  32144 
  32145         if (msg.flags & BCM_BHH_LM_SLM) {
  32146             loss_p->flags |= BCM_OAM_LOSS_SLM;
  32147         }
  32148 
  32149         if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  32150             /* If this feature is valid, then encap_data is valid */
  32151             if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 
  32152                             msg.encap_data,
  32153                             &counter_size, 
  32154                             loss_p->lm_counter_base_id,
  32155                             loss_p->lm_counter_offset,
  32156                             lm_counter_action,
  32157                             &ts_mode,
  32158                             &lm_pdu_counter_offset,
  32159                             &int_pri,
  32160                             NULL)))
  32161             {
  32162                 _BCM_OAM_UNLOCK(oc);
  32163                 return (BCM_E_INTERNAL);
  32164             }
  32165             loss_p->lm_counter_size = counter_size;
  32166             for (i = 0; i < loss_p->lm_counter_size; i++) {
  32167                 loss_p->lm_counter_action[i] = lm_counter_action[i];
  32168             }
  32169             _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p,
  32170                                                          msg.encap_data,
  32171                                                          msg.encap_length,
  32172                                                          &label);
  32173             loss_p->pkt_pri = label.exp;
  32174         }
  32175 
  32176         loss_p->period = msg.period;
  32177         loss_p->loss_threshold = msg.loss_threshold;             
  32178         loss_p->loss_nearend = msg.loss_nearend;               
  32179         loss_p->loss_farend = msg.loss_farend;    
  32180         loss_p->tx_nearend = msg.tx_nearend;            
  32181         loss_p->rx_nearend = msg.rx_nearend;              
  32182         loss_p->tx_farend = msg.tx_farend;               
  32183         loss_p->rx_farend = msg.rx_farend;               
  32184         loss_p->rx_oam_packets = msg.rx_oam_packets;          
  32185         loss_p->tx_oam_packets = msg.tx_oam_packets;          
  32186         loss_p->int_pri = int_pri;
  32187         loss_p->pm_id = sess_id;
  32188         rv = BCM_E_NONE;
  32189     }
  32190 #endif    
  32191     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  32192 #if defined(INCLUDE_ETH_LM_DM)	
  32193 	shr_eth_lm_dm_msg_ctrl_loss_get_t msg;
  32194 
  32195     sess_id = h_data_p->lm_dm_uc_session_id;
  32196 
  32197     /* Validate session id. */
  32198     rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id);
  32199     if ((BCM_E_EXISTS != rv)) {
  32200         /* Invalid session id */
  32201         LOG_ERROR(BSL_LS_BCM_OAM,
  32202                   (BSL_META_U(unit,
  32203                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32204                    unit, loss_p->id, bcm_errmsg(rv)));
  32205         _BCM_OAM_UNLOCK(oc);
  32206         return (rv);
  32207     }
  32208 
  32209 	/* Send ETH_LM_DM Session get message to uC */
  32210     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  32211                       MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_GET,
  32212                       sess_id, 0,
  32213                       MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_GET_REPLY,
  32214                       &reply_len);
  32215     if(BCM_FAILURE(rv)) {
  32216         LOG_ERROR(BSL_LS_BCM_OAM,
  32217                   (BSL_META_U(unit,
  32218                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32219                    unit, loss_p->id, bcm_errmsg(rv)));
  32220         _BCM_OAM_UNLOCK(oc);
  32221         return (rv);
  32222     }
  32223 	
  32224 	/* Pack control message data into DMA buffer */
  32225     buffer     = oc->eth_lm_dm_dma_buffer;
  32226     buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_get_unpack(buffer, &msg);
  32227     buffer_len = buffer_ptr - buffer;
  32228 
  32229     if (reply_len != buffer_len) {
  32230         rv =  BCM_E_INTERNAL;
  32231     } else {
  32232         uint8 counter_size;
  32233         uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX];
  32234         int i;
  32235         /*
  32236          * Convert kernel space flags to host space flags
  32237          */
  32238         if (msg.flags & BCM_ETH_LM_SINGLE_ENDED) {
  32239             loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
  32240         }
  32241 
  32242         if (msg.flags & BCM_ETH_LM_TX_ENABLE) {
  32243             loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  32244         }
  32245         
  32246         if (msg.flags & BCM_ETH_LM_SLM) {
  32247             loss_p->flags |= BCM_OAM_LOSS_SLM;
  32248         }
  32249 
  32250         if (msg.flags & BCM_ETH_LM_UPDATE) {
  32251             loss_p->flags |= BCM_OAM_LOSS_UPDATE;
  32252         }
  32253 
  32254         loss_p->period = msg.period;
  32255         loss_p->loss_threshold = msg.loss_threshold;             
  32256         loss_p->loss_nearend = msg.loss_nearend;               
  32257         loss_p->loss_farend = msg.loss_farend;    
  32258         loss_p->tx_nearend = msg.tx_nearend;            
  32259         loss_p->rx_nearend = msg.rx_nearend;              
  32260         loss_p->tx_farend = msg.tx_farend;               
  32261         loss_p->rx_farend = msg.rx_farend;               
  32262         loss_p->rx_oam_packets = msg.rx_oam_packets;          
  32263         loss_p->tx_oam_packets = msg.tx_oam_packets;          
  32264         loss_p->int_pri = msg.tx_cos;
  32265         loss_p->pkt_pri = msg.tx_pri;       
  32266 		memcpy(loss_p->peer_da_mac_address, msg.dst_mac, sizeof(bcm_mac_t));
  32267         loss_p->remote_id = msg.remote_mep_id;
  32268         loss_p->pm_id = h_data_p->lm_dm_uc_session_id;
  32269 
  32270         if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 
  32271                         msg.olp_tx_hdr,
  32272                         &counter_size,
  32273                         loss_p->lm_counter_base_id,
  32274                         loss_p->lm_counter_offset,
  32275                         lm_counter_action,
  32276                         NULL,
  32277                         NULL,
  32278                         NULL,
  32279                         NULL))) {
  32280             _BCM_OAM_UNLOCK(oc);
  32281             return (BCM_E_INTERNAL);
  32282         }
  32283 
  32284         loss_p->lm_counter_size = (uint32)counter_size; 
  32285         for (i = 0; i < loss_p->lm_counter_size; i++) {
  32286             loss_p->lm_counter_action[i] = (int)lm_counter_action[i];
  32287         }    
  32288     }
  32289 #endif    
  32290 	} else {
  32291         _BCM_OAM_UNLOCK(oc);
  32292         return BCM_E_UNAVAIL;
  32293     }
  32294 
  32295     _BCM_OAM_UNLOCK(oc);
  32296 
  32297     return (rv);
  32298 }
  32299 
  32300 /*
  32301  * Function:
  32302  *     bcm_sb2_oam_loss_delete
  32303  * Purpose:
  32304  *    Loss Measurement Delete 
  32305  * Parameters:
  32306  *     unit - Device unit number
  32307  * Returns:
  32308  *     None
  32309  */
  32310 int
  32311 bcm_sb2_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p)
  32312 {
  32313     _bcm_oam_control_t *oc;
  32314     int rv = BCM_E_NONE;
  32315     _bcm_oam_hash_data_t *h_data_p;
  32316 #if defined(INCLUDE_BHH) 
  32317     uint8 *buffer, *buffer_ptr;
  32318     uint16 buffer_len, reply_len;
  32319     int sess_id = 0;
  32320 #endif
  32321 
  32322     /* Get OAM Control Structure. */
  32323     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  32324     _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id);
  32325     _BCM_OAM_LOCK(oc);
  32326 
  32327     h_data_p = &oc->oam_hash_data[loss_p->id];
  32328     if (!(h_data_p->in_use)) {
  32329         /* Endpoint not in use. */
  32330         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  32331             "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv)));
  32332         _BCM_OAM_UNLOCK(oc);
  32333         return BCM_E_NOT_FOUND;
  32334     }
  32335 
  32336 #if defined(INCLUDE_MPLS_LM_DM)
  32337     /* Check if EP type is MPLS_LM_DM, call respective routine */
  32338     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  32339         if (oc->mpls_lm_dm_ukernel_ready) {
  32340             rv = _bcm_sb2_mpls_lm_dm_loss_delete(unit, h_data_p);
  32341             _BCM_OAM_UNLOCK(oc);
  32342             return rv;
  32343         } else {
  32344             _BCM_OAM_UNLOCK(oc);
  32345             return BCM_E_UNAVAIL;
  32346         }
  32347     }
  32348 #endif
  32349 
  32350     /*
  32351      * Only BHH is supported
  32352      */
  32353     if (BHH_EP_TYPE(h_data_p)) {
  32354 #if defined(INCLUDE_BHH)
  32355         shr_bhh_msg_ctrl_loss_delete_t msg;
  32356 
  32357         if (oc->ukernel_not_ready) {
  32358             _BCM_OAM_UNLOCK(oc);
  32359             return BCM_E_INIT;
  32360         }
  32361 
  32362         BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  32363 		
  32364         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  32365 		
  32366 		/* Check endpoint status. */
  32367         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  32368         if ((BCM_E_EXISTS != rv)) {
  32369             /* Endpoint not in use. */
  32370             LOG_ERROR(BSL_LS_BCM_OAM,
  32371                     (BSL_META_U(unit,
  32372                                 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32373                      unit, loss_p->id, bcm_errmsg(rv)));
  32374             _BCM_OAM_UNLOCK(oc);
  32375             return (rv);
  32376         }
  32377 		
  32378         h_data_p = &oc->oam_hash_data[loss_p->id];
  32379 	
  32380         if (h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) {
  32381             LOG_ERROR(BSL_LS_BCM_OAM,
  32382                     (BSL_META_U(unit,
  32383                                 "OAM(unit %d) Error: Proactive LM is enabled "
  32384                                 " No on demand LM on EP=%d \n"),
  32385                                 unit, loss_p->id));
  32386             _BCM_OAM_UNLOCK(oc); 
  32387             return BCM_E_NOT_FOUND;
  32388         }	
  32389         msg.sess_id = sess_id;
  32390 
  32391         /* Pack control message data into DMA buffer */
  32392         buffer     = oc->dma_buffer;
  32393         buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg);
  32394         buffer_len = buffer_ptr - buffer;
  32395 
  32396         /* Send BHH Session Update message to uC */
  32397         rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  32398                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE,
  32399                       buffer_len, 0,
  32400                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY,
  32401                       &reply_len);
  32402 
  32403         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  32404             rv =  BCM_E_INTERNAL;
  32405         }
  32406 #endif            
  32407     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  32408 #if defined(INCLUDE_ETH_LM_DM)	
  32409         if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET) {
  32410             rv = _bcm_sb2_eth_lm_dm_loss_delete(unit, oc, h_data_p);
  32411             _BCM_OAM_UNLOCK(oc);
  32412             return rv;
  32413         } else {
  32414             _BCM_OAM_UNLOCK(oc);
  32415             return BCM_E_EMPTY;
  32416         }
  32417 #endif
  32418 	} else {
  32419         _BCM_OAM_UNLOCK(oc);
  32420         return BCM_E_UNAVAIL;
  32421     }
  32422 
  32423     _BCM_OAM_UNLOCK(oc);
  32424 
  32425     return (rv);
  32426 }
  32427 
  32428 /*
  32429  * Function:
  32430  *     bcm_sb2_oam_delay_add
  32431  * Purpose:
  32432  *     Delay Measurement add     
  32433  * Parameters:
  32434  *     unit - Device unit number
  32435  * Returns:
  32436  *     None
  32437  */
  32438 int
  32439 bcm_sb2_oam_delay_add(int unit, bcm_oam_delay_t *delay_p)
  32440 {
  32441     _bcm_oam_control_t *oc;
  32442     _bcm_oam_hash_data_t *h_data_p;
  32443     int rv = BCM_E_NONE;
  32444 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM)
  32445     uint8 *buffer, *buffer_ptr;
  32446     uint16 buffer_len, reply_len;
  32447     uint32 flags = 0;
  32448     int sess_id = 0;
  32449 #endif
  32450 #if defined(INCLUDE_BHH) 
  32451     _bhh_oam_lm_dm_info_t counter_info;
  32452     bcm_module_t         module_id;
  32453     bcm_port_t           port_id;
  32454     bcm_trunk_t          trunk_id;
  32455     int                  local_id, i = 0;
  32456     uint8                encap_type;
  32457 #endif
  32458 
  32459     /* Get OAM Control Structure. */
  32460     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  32461     _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id);
  32462     _BCM_OAM_LOCK(oc);
  32463 
  32464     h_data_p = &oc->oam_hash_data[delay_p->id];
  32465     if (!(h_data_p->in_use)) {
  32466         /* Endpoint not in use. */
  32467         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  32468             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
  32469         _BCM_OAM_UNLOCK(oc);
  32470         return BCM_E_NOT_FOUND;
  32471     }
  32472 
  32473 #if defined(INCLUDE_MPLS_LM_DM)
  32474     /* Check if EP type is MPLS_LM_DM, call respective routine */
  32475     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  32476         if (oc->mpls_lm_dm_ukernel_ready) {
  32477             rv = _bcm_sb2_mpls_lm_dm_delay_add(unit, h_data_p, delay_p);
  32478             _BCM_OAM_UNLOCK(oc);
  32479             return rv;
  32480         } else {
  32481             _BCM_OAM_UNLOCK(oc);
  32482             return BCM_E_UNAVAIL;
  32483         }
  32484     }
  32485 #endif
  32486     /*
  32487      * Only BHH is supported
  32488      */
  32489     if (BHH_EP_TYPE(h_data_p)) {
  32490 #if defined(INCLUDE_BHH)
  32491 
  32492     if (oc->ukernel_not_ready) {
  32493         _BCM_OAM_UNLOCK(oc);
  32494         return BCM_E_INIT;
  32495     }
  32496 
  32497     rv = _bcm_sb2_oam_period_validate(delay_p->period);
  32498     if (BCM_FAILURE(rv)) {
  32499         LOG_ERROR(BSL_LS_BCM_OAM,
  32500                   (BSL_META_U(unit,
  32501                               "OAM(unit %d) Error: Invalid period : %d\n"),
  32502                    unit, delay_p->period));
  32503         _BCM_OAM_UNLOCK(oc);
  32504         return (rv);
  32505     }
  32506 
  32507     sal_memset(&counter_info, 0, sizeof(counter_info));
  32508     counter_info.counter_size = delay_p->dm_tx_update_lm_counter_size;
  32509     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
  32510     {
  32511         counter_info.counter_base_id[i] = 
  32512         delay_p->dm_tx_update_lm_counter_base_id[i];
  32513         counter_info.counter_offset[i] = 
  32514         delay_p->dm_tx_update_lm_counter_offset[i];
  32515         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
  32516         counter_info.byte_count_offset[i] = 0;
  32517     }
  32518     counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH;
  32519     bhh_sdk_msg_ctrl_delay_add_t msg;		
  32520     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  32521 
  32522     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  32523 
  32524     /* Check endpoint status. */
  32525     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  32526     if ((BCM_E_EXISTS != rv)) {
  32527         /* Endpoint not in use. */
  32528         LOG_ERROR(BSL_LS_BCM_OAM,
  32529                   (BSL_META_U(unit,
  32530                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32531                    unit, delay_p->id, bcm_errmsg(rv)));
  32532         _BCM_OAM_UNLOCK(oc);
  32533         return (rv);
  32534     }
  32535 
  32536     if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) {
  32537         _BCM_OAM_UNLOCK(oc);
  32538         return BCM_E_PARAM;
  32539     }
  32540 
  32541     /*
  32542      * Convert host space flags to uKernel space flags
  32543      */
  32544     if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) {
  32545         flags |= BCM_BHH_DM_ONE_WAY;
  32546     }
  32547 
  32548     if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) {
  32549         flags |= BCM_BHH_DM_TX_ENABLE;
  32550     }
  32551 
  32552     sal_memset(&msg, 0, sizeof(msg));
  32553     msg.flags   = flags;
  32554     msg.sess_id = sess_id;
  32555 
  32556     h_data_p->ts_format = delay_p->timestamp_format;
  32557 
  32558     if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) {
  32559         msg.dm_format = BCM_BHH_DM_TYPE_PTP;
  32560         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_PTP;
  32561     } else {
  32562         msg.dm_format = BCM_BHH_DM_TYPE_NTP;
  32563         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NTP;
  32564     }
  32565     /*
  32566      * Set period
  32567      */
  32568     msg.period  = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(delay_p->period)];
  32569     msg.int_pri = delay_p->int_pri;
  32570     msg.pkt_pri = delay_p->pkt_pri;
  32571 
  32572     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
  32573         rv = _bcm_esw_gport_resolve(unit,
  32574                 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
  32575     } else {
  32576         rv = _bcm_esw_gport_resolve(unit,
  32577                 h_data_p->resolved_trunk_gport, &module_id, &port_id, 
  32578                 &trunk_id, &local_id);
  32579     }
  32580     /*
  32581      * Set the BHH encapsulation data
  32582      *
  32583      * The function _bcm_sb2_oam_bhh_encap_create() is called first
  32584      * since this sets some fields in 'hash_data' which are
  32585      * used in the message.
  32586      */
  32587     rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
  32588                                        msg.encap_data, &encap_type,
  32589                                        &msg.encap_length, &counter_info,
  32590                                        delay_p->int_pri, delay_p->pkt_pri,
  32591                                        h_data_p->egr_label_ttl);
  32592     if(BCM_FAILURE(rv))
  32593     {
  32594         LOG_ERROR(BSL_LS_BCM_OAM,
  32595                 (BSL_META_U(unit,
  32596                             "BHH(unit %d) Error: Encap create failed "
  32597                             " - %s.\n"),
  32598                  unit, bcm_errmsg(rv)));
  32599         _BCM_OAM_UNLOCK(oc);
  32600         return (rv);
  32601     }
  32602 
  32603     /* Only Data tlv is supported */
  32604     for (i = 0; i < BCM_OAM_MAX_NUM_TLVS_FOR_DM; i++) {
  32605         if (delay_p->tlvs[i].tlv_type == bcmOamTlvTypeData) {
  32606 
  32607             msg.data_tlv_len = delay_p->tlvs[i].tlv_length;
  32608         }
  32609     }
  32610 
  32611     /* Pack control message data into DMA buffer */
  32612     buffer     = oc->dma_buffer;
  32613     buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg);
  32614     buffer_len = buffer_ptr - buffer;
  32615 
  32616     /* Send BHH Session Update message to uC */
  32617     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  32618                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD,
  32619                       buffer_len, 0,
  32620                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY,
  32621                       &reply_len);
  32622 
  32623     delay_p->pm_id = sess_id;
  32624 
  32625     if(BCM_SUCCESS(rv) && (reply_len != 0)) { 
  32626         rv =  BCM_E_INTERNAL;
  32627     }
  32628 #endif
  32629     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  32630 #if defined(INCLUDE_ETH_LM_DM)
  32631     shr_eth_lm_dm_msg_ctrl_delay_add_t msg;
  32632     bcm_port_t           port_id;
  32633     bcm_module_t         module_id;
  32634     int                  local_id;
  32635     bcm_trunk_t          trunk_id;
  32636     uint8                mep_type;
  32637     uint8                dm_format;
  32638     shr_eth_lm_dm_msg_ctrl_sess_set_t msg_sess;
  32639     int                  cpu_modid;
  32640     bcm_port_t           cpu_port;
  32641     int                  cpu_dglp;
  32642     uint32               olp_l2_encap_length;
  32643     int                  session_flags = 0;
  32644 
  32645 
  32646     if (1 == oc->eth_lm_dm_ukernel_not_ready) {
  32647         LOG_ERROR(BSL_LS_BCM_OAM,
  32648                 (BSL_META_U(unit,
  32649                 "ETH_LM_DM(unit %d) Error: BTE(ukernel) not ready.\n"),
  32650                  unit));
  32651         _BCM_OAM_UNLOCK(oc);
  32652         return (BCM_E_INIT);
  32653     }
  32654 
  32655    /* Get the Trunk, Port and Mod-id info for this G-port */
  32656     rv = _bcm_esw_gport_resolve(unit,
  32657             h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
  32658 
  32659     if (BCM_FAILURE(rv)) {
  32660         LOG_ERROR(BSL_LS_BCM_OAM,
  32661                 (BSL_META_U(unit,
  32662                 "ETH_LM_DM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
  32663                 unit, delay_p->id, bcm_errmsg(rv)));
  32664         _BCM_OAM_UNLOCK(oc);
  32665         return (rv);
  32666     }
  32667 
  32668     /* Reserve and program session Id for this EP */
  32669     /* ------------------------------------------ */
  32670     if (h_data_p->lm_dm_uc_session_id == 0 ) {
  32671         rv = shr_idxres_list_alloc(oc->eth_lm_dm_pool,
  32672                                    (shr_idxres_element_t *)&sess_id);
  32673 
  32674         if (BCM_FAILURE(rv)) {
  32675             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "ETH_LM_DM (unit %d) Error:"
  32676                 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id,
  32677                 bcm_errmsg(rv)));
  32678             _BCM_OAM_UNLOCK(oc);
  32679             return (rv);
  32680         }
  32681         h_data_p->lm_dm_uc_session_id = sess_id;
  32682     } else {
  32683         sess_id = h_data_p->lm_dm_uc_session_id;
  32684     }
  32685     oc->eth_lm_dm_sess_id_ep_id[sess_id] = h_data_p->ep_id;
  32686 
  32687     /* Set end-point type(dir) from the hash data flag*/
  32688     if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  32689         mep_type = 1;
  32690     } else {
  32691         mep_type = 0;
  32692     }
  32693 
  32694     if (delay_p->timestamp_format == bcmOAMTimestampFormatNTP) {
  32695         dm_format = BCM_ETH_LM_DM_RPL_TYPE_NTP_DM;
  32696     } else if (delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) {
  32697         dm_format = BCM_ETH_LM_DM_RPL_TYPE_PTP_DM;
  32698     } else {
  32699         _BCM_OAM_UNLOCK(oc);
  32700         return BCM_E_PARAM;
  32701     }
  32702 
  32703     /* Get the cpu_dglp from cpu_modid and cpu_port*/
  32704     rv = bcm_esw_stk_my_modid_get(unit, &cpu_modid);
  32705     if (BCM_FAILURE(rv)) {
  32706         LOG_ERROR(BSL_LS_BCM_OAM,
  32707                 (BSL_META_U(unit,
  32708                             "OAM(unit %d) Error: MODID get failed - %s.\n"),
  32709                  unit, bcm_errmsg(rv)));
  32710         _BCM_OAM_UNLOCK(oc);
  32711         return (rv);
  32712     }
  32713     cpu_port = 0;
  32714     cpu_dglp = ((cpu_modid << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port);
  32715 
  32716     rv = _bcm_sb2_oam_eth_olp_encap_create(unit,
  32717                                            port_id,
  32718                                            cpu_dglp,
  32719                                            h_data_p,
  32720                                            msg_sess.encap_data,
  32721                                            &msg_sess.eth_l2_encap_length,
  32722                                            &olp_l2_encap_length,
  32723                                            delay_p->pkt_pri);
  32724 
  32725 
  32726     if (BCM_FAILURE(rv)) {
  32727         LOG_ERROR(BSL_LS_BCM_OAM,
  32728                   (BSL_META_U(unit,
  32729                    "ETH_LM_DM(unit %d) Error: encap create (EP=%d) - %s.\n"),
  32730                    unit, delay_p->id, bcm_errmsg(rv)));
  32731         _BCM_OAM_UNLOCK(oc);
  32732         return (rv);
  32733     }
  32734 
  32735     msg_sess.sess_id = sess_id;
  32736     msg_sess.mep_id = h_data_p->ep_id;
  32737 
  32738     /* Set end-point type(dir) in session set message*/ 
  32739     msg_sess.mep_type = mep_type;
  32740 
  32741     msg_sess.mel     = h_data_p->level;
  32742     msg_sess.vlan_id = h_data_p->inner_vlan;
  32743     msg_sess.outer_vlan_id = h_data_p->vlan;
  32744     msg_sess.lm_counter_index = h_data_p->tx_ctr;
  32745     msg_sess.group_id = h_data_p->group_index;
  32746     msg_sess.tx_port = port_id;
  32747 
  32748     /* Check if session is already created in uKernel */
  32749     if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_SESSION_IS_SET)) {
  32750             session_flags = SHR_ETH_LM_DM_SESS_SET_F_CREATE;
  32751     }
  32752     if (h_data_p->lm_dm_int_flag & SHR_ETH_LM_DM_SESS_SET_F_LM) {
  32753         session_flags |= SHR_ETH_LM_DM_SESS_SET_F_LM;
  32754     }
  32755 
  32756     session_flags |= SHR_ETH_LM_DM_SESS_SET_F_DM;
  32757 
  32758     msg_sess.flags = session_flags;
  32759     /* Pack control message data into DMA buffer */
  32760     buffer     = oc->eth_lm_dm_dma_buffer;
  32761     buffer_ptr = shr_eth_lm_dm_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  32762     buffer_len = buffer_ptr - buffer;
  32763 
  32764     /* Send BHH Session Update message to uC */
  32765     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  32766                                       MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET,
  32767                                       buffer_len, 0,
  32768                                       MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET_REPLY,
  32769                                       &reply_len);
  32770 
  32771     if(BCM_FAILURE(rv)) {
  32772         LOG_ERROR(BSL_LS_BCM_OAM,
  32773                   (BSL_META_U(unit,
  32774                    "OAM(unit %d) Error Session set: Endpoint EP=%d %s.\n"),
  32775                    unit, delay_p->id, bcm_errmsg(rv)));
  32776         _BCM_OAM_UNLOCK(oc);
  32777         return (rv);
  32778     }
  32779 
  32780     /* Session has been set in the endpoint */
  32781     h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_SESSION_IS_SET;
  32782 
  32783 
  32784     msg.period  = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(delay_p->period)];
  32785     /*
  32786      * Convert host space flags to uKernel space flags
  32787      */
  32788     if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) {
  32789         flags |= BCM_ETH_DM_ONE_WAY;
  32790     }
  32791 
  32792     if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) {
  32793         flags |= BCM_ETH_DM_TX_ENABLE;
  32794     } else {
  32795         msg.period = BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED;
  32796     }
  32797     
  32798     if (delay_p->flags & BCM_OAM_DELAY_UPDATE) {
  32799         flags |= BCM_ETH_DM_UPDATE;
  32800     }
  32801 
  32802     msg.flags   = flags;
  32803     msg.sess_id = sess_id;
  32804     msg.dm_format = dm_format;
  32805 
  32806     /* Pkt TX params */
  32807     msg.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + delay_p->int_pri;
  32808     msg.tx_cos = delay_p->int_pri;
  32809     msg.tx_pri = delay_p->pkt_pri;
  32810 
  32811     /* MAC-DA of delay_add struture is put into the L2 encap of Loss Tx control pkt*/ 
  32812     memcpy(msg.dst_mac, delay_p->peer_da_mac_address, sizeof(bcm_mac_t));
  32813 
  32814     msg.remote_mep_id = delay_p->remote_id;
  32815 
  32816     /* Put OLP_TX header in loss add structure */
  32817     rv = _bcm_sb2_oam_delay_olp_tx_encap_create(unit,
  32818                                             h_data_p,
  32819                                             msg.olp_tx_hdr,
  32820                                             &msg.olp_tx_hdr_length,
  32821                                             delay_p,
  32822                                             port_id,
  32823                                             module_id,
  32824                                             mep_type,
  32825                                             dm_format);
  32826 
  32827 
  32828     /* Pack control message data into DMA buffer */
  32829     buffer     = oc->eth_lm_dm_dma_buffer;
  32830     buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_add_pack(buffer, &msg);
  32831     buffer_len = buffer_ptr - buffer;
  32832 
  32833     /* Send BHH Session Update message to uC */
  32834     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  32835                       MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_ADD,
  32836                       buffer_len, 0,
  32837                       MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_ADD_REPLY,
  32838                       &reply_len);
  32839 
  32840     h_data_p->lm_dm_int_flag |=  _ETH_LM_DM_F_DM_IS_SET;
  32841     
  32842     delay_p->pm_id = h_data_p->lm_dm_uc_session_id;
  32843 
  32844     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  32845         rv =  BCM_E_INTERNAL;
  32846     }
  32847 #endif
  32848     } else {
  32849         _BCM_OAM_UNLOCK(oc);
  32850         return BCM_E_UNAVAIL;
  32851     }
  32852 
  32853     _BCM_OAM_UNLOCK(oc);
  32854     return (rv);
  32855 }
  32856 
  32857 /*
  32858  * Function:
  32859  *     bcm_sb2_oam_delay_get
  32860  * Purpose:
  32861  *     Delay Measurements get 
  32862  * Parameters:
  32863  *     unit - Device unit number
  32864  * Returns:
  32865  *     None
  32866  */
  32867 int
  32868 bcm_sb2_oam_delay_get(int unit, bcm_oam_delay_t *delay_p)
  32869 {
  32870     _bcm_oam_control_t *oc;
  32871     int rv = BCM_E_NONE;
  32872     _bcm_oam_hash_data_t *h_data_p;
  32873 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM)
  32874     uint8 *buffer, *buffer_ptr;
  32875     uint16 buffer_len, reply_len;
  32876     int sess_id = 0;
  32877 #endif
  32878 #if defined(INCLUDE_BHH)
  32879     uint8   ts_mode;
  32880     uint8 lm_pdu_counter_offset = 0;
  32881     uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX];
  32882     bcm_cos_t int_pri = 0;
  32883     _mpls_label_t label;
  32884 #endif
  32885 
  32886     /* Get OAM Control Structure. */
  32887     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  32888     _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id);
  32889     _BCM_OAM_LOCK(oc);
  32890 
  32891     h_data_p = &oc->oam_hash_data[delay_p->id];
  32892     if (!(h_data_p->in_use)) {
  32893         /* Endpoint not in use. */
  32894         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  32895             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
  32896         _BCM_OAM_UNLOCK(oc);
  32897         return BCM_E_NOT_FOUND;
  32898     }
  32899 
  32900 #if defined(INCLUDE_MPLS_LM_DM)
  32901     /* Check if EP type is MPLS_LM_DM, call respective routine */
  32902     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  32903         if (oc->mpls_lm_dm_ukernel_ready) {
  32904             rv = _bcm_sb2_mpls_lm_dm_delay_get(unit, h_data_p, delay_p);
  32905             _BCM_OAM_UNLOCK(oc);
  32906             return rv;
  32907         } else {
  32908             _BCM_OAM_UNLOCK(oc);
  32909             return BCM_E_UNAVAIL;
  32910         }
  32911     }
  32912 #endif
  32913 
  32914     /*
  32915      * Only BHH is supported
  32916      */
  32917     if (BHH_EP_TYPE(h_data_p)) {
  32918 #if defined(INCLUDE_BHH)
  32919     bhh_sdk_msg_ctrl_delay_get_t msg;
  32920 
  32921     if (oc->ukernel_not_ready) {
  32922         _BCM_OAM_UNLOCK(oc);
  32923         return BCM_E_INIT;
  32924     }
  32925 
  32926     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  32927 
  32928     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  32929 
  32930     /* Check endpoint status. */
  32931     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  32932     if ((BCM_E_EXISTS != rv)) {
  32933         /* Endpoint not in use. */
  32934         LOG_ERROR(BSL_LS_BCM_OAM,
  32935                   (BSL_META_U(unit,
  32936                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32937                    unit, delay_p->id, bcm_errmsg(rv)));
  32938         _BCM_OAM_UNLOCK(oc);
  32939         return (rv);
  32940     }
  32941 
  32942     sal_memset(&msg, 0, sizeof(msg));
  32943     /* Send BHH Session Update message to uC */
  32944     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  32945                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET,
  32946                       sess_id, 0,
  32947                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY,
  32948                       &reply_len);
  32949     if(BCM_FAILURE(rv)) {
  32950         LOG_ERROR(BSL_LS_BCM_OAM,
  32951                   (BSL_META_U(unit,
  32952                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  32953                    unit, delay_p->id, bcm_errmsg(rv)));
  32954         _BCM_OAM_UNLOCK(oc);
  32955         return (rv);
  32956     }
  32957 
  32958     /* Pack control message data into DMA buffer */
  32959     buffer     = oc->dma_buffer;
  32960     buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg);
  32961     buffer_len = buffer_ptr - buffer;
  32962 
  32963 
  32964     if (reply_len != buffer_len) {
  32965         rv =  BCM_E_INTERNAL;
  32966     } else {
  32967         /*
  32968          * Convert kernel space flags to host space flags
  32969          */
  32970         if (msg.flags & BCM_BHH_DM_ONE_WAY) {
  32971             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  32972         }
  32973 
  32974         if (msg.flags & BCM_BHH_DM_TX_ENABLE) {
  32975             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  32976         }
  32977 
  32978         delay_p->period = msg.period;
  32979 
  32980         if(msg.dm_format == BCM_BHH_DM_TYPE_PTP)
  32981             delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1;
  32982         else
  32983             delay_p->timestamp_format = bcmOAMTimestampFormatNTP;
  32984 
  32985         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 
  32986                                        msg.delay_seconds, msg.delay_nanoseconds);
  32987         if(BCM_SUCCESS(rv)) {
  32988             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 
  32989                                        msg.txf_seconds, msg.txf_nanoseconds);
  32990         }
  32991         if(BCM_SUCCESS(rv)) {
  32992             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 
  32993                                        msg.rxf_seconds, msg.rxf_nanoseconds);
  32994         }
  32995         if(BCM_SUCCESS(rv)) {
  32996             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 
  32997                                        msg.txb_seconds, msg.txb_nanoseconds);
  32998         }
  32999         if(BCM_SUCCESS(rv)) {
  33000             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 
  33001                                        msg.rxb_seconds, msg.rxb_nanoseconds);
  33002         }
  33003 
  33004         if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) {
  33005             /* If this feature is valid, then encap_data is valid */
  33006             if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 
  33007                             msg.encap_data,
  33008                             &(delay_p->dm_tx_update_lm_counter_size), 
  33009                             delay_p->dm_tx_update_lm_counter_base_id,
  33010                             delay_p->dm_tx_update_lm_counter_offset,
  33011                             lm_counter_action,
  33012                             &ts_mode,
  33013                             &lm_pdu_counter_offset,
  33014                             &int_pri,
  33015                             NULL)))
  33016             {
  33017                 _BCM_OAM_UNLOCK(oc);
  33018                 return (BCM_E_INTERNAL);
  33019             }
  33020             _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p,
  33021                                                          msg.encap_data,
  33022                                                          msg.encap_length,
  33023                                                          &label);
  33024             delay_p->pkt_pri = label.exp;
  33025         }
  33026 
  33027         delay_p->rx_oam_packets = msg.rx_oam_packets;
  33028         delay_p->tx_oam_packets = msg.tx_oam_packets;
  33029         delay_p->int_pri = int_pri;
  33030         delay_p->pm_id = sess_id;
  33031         if (msg.data_tlv_len) {
  33032             delay_p->tlvs[0].tlv_type = bcmOamTlvTypeData;
  33033             delay_p->tlvs[0].tlv_length = msg.data_tlv_len;
  33034         }
  33035         rv = BCM_E_NONE;       
  33036     }
  33037 #endif    
  33038     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  33039 #if defined(INCLUDE_ETH_LM_DM)    
  33040 	shr_eth_lm_dm_msg_ctrl_delay_get_t msg;
  33041 
  33042     sess_id = h_data_p->lm_dm_uc_session_id;
  33043 
  33044     /* Validate session id. */
  33045     rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id);
  33046     if ((BCM_E_EXISTS != rv)) {
  33047         /* Invalid session id */
  33048         LOG_ERROR(BSL_LS_BCM_OAM,
  33049                   (BSL_META_U(unit,
  33050                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  33051                    unit, delay_p->id, bcm_errmsg(rv)));
  33052         _BCM_OAM_UNLOCK(oc);
  33053         return (rv);
  33054     }
  33055 
  33056     /* Send ETH_LM_DM Delay get message to uC */
  33057     rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit,
  33058                       MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_GET,
  33059                       sess_id, 0,
  33060                       MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_GET_REPLY,
  33061                       &reply_len);
  33062     
  33063     if(BCM_FAILURE(rv)) {
  33064         LOG_ERROR(BSL_LS_BCM_OAM,
  33065                   (BSL_META_U(unit,
  33066                               "OAM(unit %d) Error Delay Get: Endpoint EP=%d %s.\n"),
  33067                    unit, delay_p->id, bcm_errmsg(rv)));
  33068         _BCM_OAM_UNLOCK(oc);
  33069         return (rv);
  33070     }
  33071 	
  33072     /* Pack control message data into DMA buffer */
  33073     buffer     = oc->eth_lm_dm_dma_buffer;
  33074     buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_get_unpack(buffer, &msg);
  33075     buffer_len = buffer_ptr - buffer;
  33076 
  33077     if (reply_len != buffer_len) {
  33078         rv =  BCM_E_INTERNAL;
  33079     } else {
  33080          /*
  33081          * Convert kernel space flags to host space flags
  33082          */
  33083         if (msg.flags & BCM_ETH_DM_ONE_WAY) {
  33084             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  33085         }
  33086 
  33087         if (msg.flags & BCM_ETH_DM_TX_ENABLE) {
  33088             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  33089         }
  33090 
  33091         if (msg.flags & BCM_ETH_DM_UPDATE) {
  33092             delay_p->flags |= BCM_OAM_DELAY_UPDATE;
  33093         }
  33094 
  33095         delay_p->period = msg.period;
  33096 
  33097         if(msg.dm_format == BCM_ETH_LM_DM_RPL_TYPE_PTP_DM) {
  33098             delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1;
  33099         } else {
  33100             delay_p->timestamp_format = bcmOAMTimestampFormatNTP;
  33101         }
  33102 
  33103         rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 
  33104                                        msg.delay_seconds, msg.delay_nanoseconds);
  33105         if(BCM_SUCCESS(rv)) {
  33106             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 
  33107                                        msg.txf_seconds, msg.txf_nanoseconds);
  33108         }
  33109         if(BCM_SUCCESS(rv)) {
  33110             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 
  33111                                        msg.rxf_seconds, msg.rxf_nanoseconds);
  33112         }
  33113         if(BCM_SUCCESS(rv)) {
  33114             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 
  33115                                        msg.txb_seconds, msg.txb_nanoseconds);
  33116         }
  33117         if(BCM_SUCCESS(rv)) {
  33118             rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 
  33119                                        msg.rxb_seconds, msg.rxb_nanoseconds);
  33120         }
  33121         delay_p->rx_oam_packets = msg.rx_oam_packets;
  33122         delay_p->tx_oam_packets = msg.tx_oam_packets;
  33123         delay_p->int_pri = msg.tx_cos;
  33124         delay_p->pkt_pri = msg.tx_pri;
  33125         memcpy(delay_p->peer_da_mac_address, msg.dst_mac, sizeof(bcm_mac_t));
  33126         delay_p->remote_id = msg.remote_mep_id;
  33127         delay_p->pm_id = h_data_p->lm_dm_uc_session_id;
  33128         
  33129         if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 
  33130                         msg.olp_tx_hdr,
  33131                         &delay_p->dm_tx_update_lm_counter_size, 
  33132                         delay_p->dm_tx_update_lm_counter_base_id,
  33133                         delay_p->dm_tx_update_lm_counter_offset,
  33134                         NULL,
  33135                         NULL,
  33136                         NULL,
  33137                         NULL,
  33138                         NULL))) {
  33139             _BCM_OAM_UNLOCK(oc);
  33140             return (BCM_E_INTERNAL);
  33141         }
  33142         
  33143         rv = BCM_E_NONE;       
  33144 		
  33145 	}
  33146 #endif    
  33147 	}
  33148     else {
  33149         _BCM_OAM_UNLOCK(oc);
  33150         return BCM_E_UNAVAIL;
  33151     }
  33152 
  33153     _BCM_OAM_UNLOCK(oc);
  33154 
  33155     return (rv);
  33156 }
  33157 
  33158 /*
  33159  * Function:
  33160  *     bcm_sb2_oam_delay_delete
  33161  * Purpose:
  33162  *     Delay Measurement Delete 
  33163  * Parameters:
  33164  *     unit - Device unit number
  33165  * Returns:
  33166  *     None
  33167 */
  33168 int
  33169 bcm_sb2_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p)
  33170 {
  33171     _bcm_oam_control_t *oc;
  33172     int rv = BCM_E_NONE;
  33173     _bcm_oam_hash_data_t *h_data_p;
  33174 #if defined(INCLUDE_BHH) 
  33175     uint8 *buffer, *buffer_ptr;
  33176     uint16 buffer_len, reply_len;
  33177     int sess_id = 0;
  33178 #endif
  33179 
  33180     /* Get OAM Control Structure. */
  33181     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  33182     _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id);
  33183     _BCM_OAM_LOCK(oc);
  33184 
  33185     h_data_p = &oc->oam_hash_data[delay_p->id];
  33186 
  33187     if (!(h_data_p->in_use)) {
  33188         /* Endpoint not in use. */
  33189         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  33190             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
  33191         _BCM_OAM_UNLOCK(oc);
  33192         return BCM_E_NOT_FOUND;
  33193     }
  33194 
  33195 #if defined(INCLUDE_MPLS_LM_DM)
  33196     /* Check if EP type is MPLS_LM_DM, call respective routine */
  33197     if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) {
  33198         if (oc->mpls_lm_dm_ukernel_ready) {
  33199             rv = _bcm_sb2_mpls_lm_dm_delay_delete(unit, h_data_p);
  33200             _BCM_OAM_UNLOCK(oc);
  33201             return rv;
  33202         } else {
  33203             _BCM_OAM_UNLOCK(oc);
  33204             return BCM_E_UNAVAIL;
  33205         }
  33206     }
  33207 #endif
  33208 
  33209     /*
  33210      * Only BHH is supported
  33211      */
  33212     if (BHH_EP_TYPE(h_data_p)) {
  33213 #if defined(INCLUDE_BHH)		
  33214         shr_bhh_msg_ctrl_delay_delete_t msg;
  33215 
  33216         if (oc->ukernel_not_ready) {
  33217             _BCM_OAM_UNLOCK(oc);
  33218             return BCM_E_INIT;
  33219         }
  33220 
  33221         BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  33222 		
  33223         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  33224 		
  33225         /* Check endpoint status. */
  33226         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  33227         if ((BCM_E_EXISTS != rv)) {
  33228             /* Endpoint not in use. */
  33229             LOG_ERROR(BSL_LS_BCM_OAM,
  33230                     (BSL_META_U(unit,
  33231                                 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  33232                      unit, delay_p->id, bcm_errmsg(rv)));
  33233             _BCM_OAM_UNLOCK(oc);
  33234             return (rv);
  33235         }
  33236 
  33237         msg.sess_id = sess_id;
  33238 
  33239         /* Pack control message data into DMA buffer */
  33240         buffer     = oc->dma_buffer;
  33241         buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg);
  33242         buffer_len = buffer_ptr - buffer;
  33243 
  33244         /* Send BHH Session Update message to uC */
  33245         rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  33246                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE,
  33247                       buffer_len, 0,
  33248                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY,
  33249                       &reply_len);
  33250 
  33251         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  33252             rv =  BCM_E_INTERNAL;
  33253         }
  33254 #endif            
  33255     } else if (h_data_p->type == bcmOAMEndpointTypeEthernet){
  33256 #if defined(INCLUDE_ETH_LM_DM)        
  33257         if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET) {
  33258             rv = _bcm_sb2_eth_lm_dm_delay_delete(unit, oc, h_data_p);
  33259             _BCM_OAM_UNLOCK(oc);
  33260             return rv;
  33261         } else {
  33262             _BCM_OAM_UNLOCK(oc);
  33263             return BCM_E_EMPTY;
  33264         }        
  33265 #endif
  33266 	} else {
  33267         _BCM_OAM_UNLOCK(oc);
  33268         return BCM_E_UNAVAIL;
  33269     }
  33270 
  33271     _BCM_OAM_UNLOCK(oc);
  33272 
  33273     return (rv);
  33274 }
  33275 #endif /* (INCLUDE_BHH || INCLUDE_ETH_LM_DM ) || MPLS_LM_DM */
  33276 void _bcm_sb2_lm_dm_data_collection_modes_init(int unit)
  33277 {
  33278     _bcm_oam_control_t   *oc = NULL; /* Pointer to control structure.    */
  33279     int rv = BCM_E_NONE;
  33280 
  33281     rv = _bcm_sb2_oam_control_get(unit, &oc);
  33282 
  33283     if (BCM_FAILURE(rv)) {
  33284         LOG_ERROR(BSL_LS_BCM_OAM,
  33285                 (BSL_META_U(unit,
  33286                             "OAM(unit %d) Error: Oam control get failed "
  33287                             "- %s.\n"), unit, bcm_errmsg(rv)));
  33288         return;
  33289     }
  33290 #if defined (INCLUDE_ETH_LM_DM)
  33291     oc->pm_eth_lmdm_data_collection_mode = soc_property_get(unit, 
  33292             spn_ETH_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
  33293 #endif
  33294 #if defined (INCLUDE_BHH)
  33295     oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit,
  33296             spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
  33297 #endif
  33298 #if defined (INCLUDE_MPLS_LM_DM)
  33299     oc->pm_mpls_lmdm_data_collection_mode = soc_property_get(unit,
  33300             spn_MPLS_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
  33301 #endif
  33302 }
  33303 
  33304 int _bcm_sb2_oam_pm_init(int unit)
  33305 {
  33306     /* Profile data structure initialization */
  33307     _bcm_oam_pm_profile_control_t *pmc = NULL;
  33308     int rv = BCM_E_NONE;
  33309     _bcm_oam_control_t *oc = NULL;
  33310 
  33311     rv = _bcm_sb2_oam_control_get(unit, &oc);
  33312 
  33313     if (BCM_FAILURE(rv)) {
  33314         LOG_ERROR(BSL_LS_BCM_OAM,
  33315                 (BSL_META_U(unit,
  33316                             "OAM(unit %d) Error: Oam control get failed "
  33317                             "- %s.\n"), unit, bcm_errmsg(rv)));
  33318         return BCM_E_INIT;
  33319     }
  33320    
  33321     _BCM_OAM_LOCK(oc);
  33322     
  33323     _bcm_sb2_lm_dm_data_collection_modes_init(unit);
  33324     /* Allocate profiles only if one of them has processed stats 
  33325      * collection enabled 
  33326      */
  33327     if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 
  33328         (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
  33329         (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
  33330         _BCM_OAM_ALLOC(pmc, _bcm_oam_pm_profile_control_t, 
  33331                 sizeof (_bcm_oam_pm_profile_control_t),
  33332                 "OAM PM profile control");
  33333         if (!pmc) {
  33334             _BCM_OAM_UNLOCK(oc);
  33335             return BCM_E_MEMORY;
  33336         }
  33337 
  33338         pm_profile_control[unit] = pmc;
  33339     }
  33340     /*
  33341      * Allocate DMA buffers and raw data buffers.
  33342      *
  33343      * 1) DMA buffer will be used to send and receive 'long' messages
  33344      * between SDK Host and uController (BTE).
  33345      *
  33346      *
  33347      * 2) Allocate RAW data buffers which is provided
  33348      * to Application during PM event callback
  33349      */
  33350 #if defined (INCLUDE_BHH)
  33351     /* DMA buffer */
  33352     if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
  33353         oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
  33354         oc->pm_bhh_dma_buffer = soc_cm_salloc(unit, oc->pm_bhh_dma_buffer_len,
  33355                                               "PM DMA buffer");
  33356         if (!oc->pm_bhh_dma_buffer) {
  33357             _BCM_OAM_UNLOCK(oc);
  33358             return (BCM_E_MEMORY);
  33359         }
  33360         sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len);
  33361         if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  33362             /* Raw data buffers */
  33363             oc->pm_bhh_raw_data_num_buffers = soc_property_get(unit,
  33364                                                 spn_BHH_PM_RAW_DATA_BUFFERS, 4);
  33365         }
  33366         /* For first time, when we write this will be incremented to zero index */
  33367         PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = -1;
  33368         PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = -1;
  33369         /* Initially all the buffers are free */
  33370         NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS;
  33371     }
  33372 #endif
  33373 
  33374 #if defined (INCLUDE_MPLS_LM_DM)
  33375     /* DMA buffer */
  33376     if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
  33377         oc->pm_mpls_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
  33378         oc->pm_mpls_lm_dm_dma_buffer = soc_cm_salloc(unit,
  33379                                                oc->pm_mpls_lm_dm_dma_buffer_len,
  33380                                                "PM DMA buffer");
  33381         if (!oc->pm_mpls_lm_dm_dma_buffer) {
  33382             _BCM_OAM_UNLOCK(oc);
  33383             return (BCM_E_MEMORY);
  33384         }
  33385         sal_memset(oc->pm_mpls_lm_dm_dma_buffer, 0,
  33386                    oc->pm_mpls_lm_dm_dma_buffer_len);
  33387         if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  33388             /* Raw data buffers */
  33389             oc->pm_mpls_lm_dm_raw_data_num_buffers = soc_property_get(unit,
  33390                                           spn_MPLS_LMDM_PM_RAW_DATA_BUFFERS, 4);
  33391         }
  33392         /* For first time, when we write this will be incremented to zero index */
  33393         PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1;
  33394         PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1;
  33395         /* Initially all the buffers are free */
  33396         NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS;
  33397     }
  33398 #endif
  33399 
  33400 #if defined (INCLUDE_ETH_LM_DM)
  33401     /* DMA buffer */
  33402     if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
  33403         oc->pm_eth_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
  33404         oc->pm_eth_lm_dm_dma_buffer = soc_cm_salloc(unit,
  33405                                                 oc->pm_eth_lm_dm_dma_buffer_len,
  33406                                                 "PM DMA buffer");
  33407         if (!oc->pm_eth_lm_dm_dma_buffer) {
  33408             _BCM_OAM_UNLOCK(oc);
  33409             return (BCM_E_MEMORY);
  33410         }
  33411         sal_memset(oc->pm_eth_lm_dm_dma_buffer, 0,
  33412                    oc->pm_eth_lm_dm_dma_buffer_len);
  33413         if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  33414             /* Raw data buffers */
  33415             oc->pm_eth_lm_dm_raw_data_num_buffers = soc_property_get(unit,
  33416                                            spn_ETH_LMDM_PM_RAW_DATA_BUFFERS, 4);
  33417         }
  33418         /* For first time, when we write this will be incremented to zero index */
  33419         PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = -1;
  33420         PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = -1;
  33421         /* Initially all the buffers are free */
  33422         NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS;
  33423     }
  33424 #endif
  33425 
  33426     _BCM_OAM_UNLOCK(oc);
  33427 
  33428     return BCM_E_NONE;
  33429 }
  33430 
  33431 uint8* _bcm_oam_pm_dma_buffer_from_endpoint_type_get(int unit, _bcm_oam_hash_data_t *h_data_p)
  33432 {
  33433     _bcm_oam_control_t *oc = NULL;
  33434     int rv = BCM_E_NONE;
  33435 
  33436     rv = _bcm_sb2_oam_control_get(unit, &oc);
  33437     if (BCM_FAILURE(rv)) {
  33438         return NULL;
  33439     }
  33440 
  33441     if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  33442 #if defined (INCLUDE_ETH_LM_DM)
  33443         return oc->pm_eth_lm_dm_dma_buffer;
  33444 #else
  33445         return NULL;
  33446 #endif
  33447     } else if (BHH_EP_TYPE(h_data_p)) {
  33448 #if defined (INCLUDE_BHH)
  33449         return oc->pm_bhh_dma_buffer;
  33450 #else
  33451         return NULL;
  33452 #endif
  33453     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  33454 #if defined (INCLUDE_MPLS_LM_DM)
  33455         return oc->pm_mpls_lm_dm_dma_buffer;
  33456 #else
  33457         return NULL;
  33458 #endif
  33459     }
  33460     return NULL; 
  33461 }
  33462 
  33463 int _bcm_oam_pm_dma_buffer_and_len_from_class_get(int unit,
  33464                                                   uint8 class, 
  33465                                                   uint8 **buffer,
  33466                                                   int *buffer_len)
  33467 {
  33468     _bcm_oam_control_t *oc = NULL;
  33469     int rv = BCM_E_NONE;
  33470 
  33471     rv = _bcm_sb2_oam_control_get(unit, &oc);
  33472     if (BCM_FAILURE(rv)) {
  33473         return rv;
  33474     }
  33475     switch(class) {
  33476         case MOS_MSG_CLASS_BHH:
  33477 #if defined (INCLUDE_BHH)
  33478             *buffer = oc->pm_bhh_dma_buffer;
  33479             *buffer_len = oc->pm_bhh_dma_buffer_len;
  33480             return BCM_E_NONE;
  33481 #else
  33482             return BCM_E_PARAM;
  33483 #endif
  33484             break; 
  33485         case MOS_MSG_CLASS_MPLS_LM_DM:
  33486 #if defined (INCLUDE_MPLS_LM_DM)
  33487             *buffer = oc->pm_mpls_lm_dm_dma_buffer;
  33488             *buffer_len = oc->pm_mpls_lm_dm_dma_buffer_len;
  33489             return BCM_E_NONE;
  33490 #else
  33491             return BCM_E_PARAM;
  33492 #endif
  33493             break; 
  33494         case MOS_MSG_CLASS_ETH_LM_DM:
  33495 #if defined (INCLUDE_ETH_LM_DM)
  33496             *buffer = oc->pm_eth_lm_dm_dma_buffer;
  33497             *buffer_len = oc->pm_eth_lm_dm_dma_buffer_len;
  33498             return BCM_E_NONE;
  33499 #else
  33500             return BCM_E_PARAM;
  33501 #endif
  33502             break; 
  33503         default:
  33504             return BCM_E_PARAM;
  33505             break;
  33506     }
  33507     return BCM_E_NONE;
  33508 }
  33509 
  33510 uint8* _bcm_sb2_oam_pm_dma_buffer_get(int unit, bcm_oam_event_type_t event_type)
  33511 {
  33512     _bcm_oam_control_t *oc = NULL;
  33513     int rv = BCM_E_NONE;
  33514 
  33515     rv = _bcm_sb2_oam_control_get(unit, &oc);
  33516     if (BCM_FAILURE(rv)) {
  33517         return NULL;
  33518     }
  33519     switch(event_type) {
  33520         case bcmOAMEventBHHRawData:
  33521 #if defined (INCLUDE_BHH)
  33522             return oc->pm_bhh_dma_buffer;
  33523 #else
  33524             return NULL;
  33525 #endif
  33526             break; 
  33527         case bcmOAMEventEthLmDmRawData:
  33528 #if defined (INCLUDE_ETH_LM_DM)
  33529             return oc->pm_eth_lm_dm_dma_buffer;
  33530 #else
  33531             return NULL;
  33532 #endif
  33533             break; 
  33534         case bcmOAMEventMplsLmDmRawData:
  33535 #if defined (INCLUDE_MPLS_LM_DM)
  33536             return oc->pm_mpls_lm_dm_dma_buffer;
  33537 #else
  33538             return NULL;
  33539 #endif
  33540             break; 
  33541         default:
  33542             return NULL;
  33543             break;
  33544     }
  33545     return NULL;
  33546 }
  33547 
  33548 /*
  33549  * Function:
  33550  *      _bcm_sb2_oam_pm_msg_send_receive
  33551  * Purpose:
  33552  *      Sends given PM control message to the uController.
  33553  *      Receives and verifies expected reply.
  33554  *      Performs DMA operation if required.
  33555  * Parameters:
  33556  *      unit        - (IN) Unit number.
  33557  *      s_class     - (IN) PM message class.
  33558  *      s_len       - (IN) Value for 'len' field in message struct.
  33559  *                         Length of buffer to flush if DMA send is required.
  33560  *      s_data      - (IN) Value for 'data' field in message struct.
  33561  *                         Ignored if message requires a DMA send/receive
  33562  *                         operation.
  33563  *      r_subclass  - (IN) Expected reply message subclass.
  33564  *      r_len       - (OUT) Returns value in 'len' reply message field.
  33565  * Returns:
  33566  *      BCM_E_XXX
  33567  * Notes:
  33568  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  33569  *       can take any arbitrary data.
  33570  *
  33571  *     PM Long Control message:
  33572  *     - PM control messages that require send/receive of information
  33573  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  33574  *       use DMA operations to exchange information (long control message).
  33575  *
  33576  *     - PM convention for long control messages for
  33577  *        'mos_msg_data_t' fields:
  33578  *          'len'    size of the DMA buffer to send to uController
  33579  *          'data'   physical DMA memory address to send or receive
  33580  *
  33581  *      DMA Operations:
  33582  *      - DMA read/write operation is performed when a long BHH control
  33583  *        message is involved.
  33584  *
  33585  *      - Messages that require DMA operation (long control message)
  33586  *        is indicated by MOS_MSG_DMA_MSG().
  33587  *
  33588  *      - Callers must 'pack' and 'unpack' corresponding information
  33589  *        into/from DMA buffer indicated by dma_buffer.
  33590  */
  33591 STATIC int
  33592 _bcm_sb2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass,
  33593                                     uint16 s_len, uint32 s_data,
  33594                                     uint8 r_subclass, uint16 *r_len)
  33595 {
  33596     int rv = BCM_E_NONE;
  33597     _bcm_oam_control_t *oc;
  33598     mos_msg_data_t send, reply;
  33599     uint8 *dma_buffer = NULL;
  33600     int dma_buffer_len = 0;
  33601     uint32 uc_rv;
  33602     int uc_num;
  33603 
  33604     /* Lock already taken by the calling routine. */
  33605     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  33606 
  33607     sal_memset(&send, 0, sizeof(send));
  33608     sal_memset(&reply, 0, sizeof(reply));
  33609     send.s.mclass = s_class;
  33610     send.s.subclass = s_subclass;
  33611     send.s.len = bcm_htons(s_len);
  33612 
  33613     /*
  33614      * Set 'data' to DMA buffer address if a DMA operation is
  33615      * required for send or receive.
  33616      */
  33617 
  33618     BCM_IF_ERROR_RETURN(_bcm_oam_pm_dma_buffer_and_len_from_class_get(
  33619                                                         unit, s_class,
  33620                                                         &dma_buffer, 
  33621                                                         &dma_buffer_len));
  33622 
  33623     if (MOS_MSG_DMA_MSG(s_subclass) ||
  33624         MOS_MSG_DMA_MSG(r_subclass)) {
  33625         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  33626     } else {
  33627         send.s.data = bcm_htonl(s_data);
  33628     }
  33629 
  33630     /* Flush DMA memory */
  33631     if (MOS_MSG_DMA_MSG(s_subclass)) {
  33632         soc_cm_sflush(unit, dma_buffer, s_len);
  33633     }
  33634 
  33635     /* Invalidate DMA memory to read */
  33636     if (MOS_MSG_DMA_MSG(r_subclass)) {
  33637         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  33638     }
  33639 
  33640     switch (s_class) {
  33641 #if defined (INCLUDE_BHH)
  33642         case MOS_MSG_CLASS_BHH:
  33643             uc_num = oc->uc_num;
  33644             break;
  33645 #endif
  33646 #if defined (INCLUDE_ETH_LM_DM)
  33647         case MOS_MSG_CLASS_ETH_LM_DM:
  33648             uc_num = oc->eth_lm_dm_uc_num;
  33649             break;
  33650 #endif
  33651 #if defined (INCLUDE_MPLS_LM_DM)
  33652         case MOS_MSG_CLASS_MPLS_LM_DM:
  33653             uc_num = oc->mpls_lm_dm_uc_num;
  33654             break;
  33655 #endif
  33656         default:
  33657             return BCM_E_PARAM;
  33658             break;
  33659     }
  33660 
  33661     /* coverity[unreachable] */
  33662     rv = soc_cmic_uc_msg_send_receive(unit, uc_num,
  33663                                       &send, &reply,
  33664                                       _PM_UC_MSG_TIMEOUT_USECS);
  33665 
  33666     /* Check reply class, subclass */
  33667     if ((rv != SOC_E_NONE) ||
  33668         (reply.s.mclass != s_class) || /* We can expect the same class that was sent */
  33669         (reply.s.subclass != r_subclass)) {
  33670         return (BCM_E_INTERNAL);
  33671     }
  33672 
  33673     /* Convert OAM PM uController error code to BCM */
  33674     uc_rv = bcm_ntohl(reply.s.data);
  33675     switch(uc_rv) {
  33676     case SHR_OAM_PM_UC_E_NONE:
  33677         rv = BCM_E_NONE;
  33678         break;
  33679     case SHR_OAM_PM_UC_E_INTERNAL:
  33680         rv = BCM_E_INTERNAL;
  33681         break;
  33682     case SHR_OAM_PM_UC_E_MEMORY:
  33683         rv = BCM_E_MEMORY;
  33684         break;
  33685     case SHR_OAM_PM_UC_E_PARAM:
  33686         rv = BCM_E_PARAM;
  33687         break;
  33688     case SHR_OAM_PM_UC_E_RESOURCE:
  33689         rv = BCM_E_RESOURCE;
  33690         break;
  33691     case SHR_OAM_PM_UC_E_EXISTS:
  33692         rv = BCM_E_EXISTS;
  33693         break;
  33694     case SHR_OAM_PM_UC_E_NOT_FOUND:
  33695         rv = BCM_E_NOT_FOUND;
  33696         break;
  33697     case SHR_OAM_PM_UC_E_UNAVAIL:
  33698         rv = BCM_E_UNAVAIL;
  33699         break;
  33700     case SHR_OAM_PM_UC_E_VERSION:
  33701         rv = BCM_E_CONFIG;
  33702         break;
  33703     case SHR_OAM_PM_UC_E_INIT:
  33704         rv = BCM_E_INIT;
  33705         break;
  33706     default:
  33707         rv = BCM_E_INTERNAL;
  33708         break;
  33709     }
  33710         
  33711     *r_len = bcm_ntohs(reply.s.len);
  33712 
  33713     return (rv);
  33714 }
  33715 
  33716 int _bcm_sb2_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1, 
  33717                                 bcm_oam_pm_profile_info_t *profile_info2)
  33718 {
  33719     if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges,
  33720                      BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) {
  33721         /* Match */
  33722         return 1;
  33723     }
  33724     return 0;
  33725 }
  33726 
  33727 int _bcm_sb2_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info)
  33728 {
  33729     int id = 0;
  33730     _bcm_oam_pm_profile_control_t *pmc = NULL; 
  33731 
  33732     pmc = pm_profile_control[unit];
  33733     
  33734     if (!pmc) {
  33735         return 0; 
  33736     }
  33737 
  33738     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  33739         if (_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id)) { /* If a profile is in use */
  33740             if (_bcm_sb2_pm_profile_compare(
  33741                                          _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, id), 
  33742                                             profile_info)) {
  33743                 return 1;
  33744             }
  33745         }
  33746     }
  33747     return 0;
  33748 }
  33749 
  33750 int 
  33751 _bcm_sb2_find_free_pm_profile_id(int unit, int *pm_profile_id)
  33752 {
  33753     int id = 0;
  33754     _bcm_oam_pm_profile_control_t *pmc = NULL; 
  33755 
  33756     pmc = pm_profile_control[unit];
  33757     
  33758     if (!pmc) {
  33759         return BCM_E_INIT; 
  33760     }
  33761 
  33762     /* return the lowest un used id */
  33763     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  33764         if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id))) { /* If a profile is not in use */
  33765             *pm_profile_id = id; /* Assign it and return */
  33766             return BCM_E_NONE;
  33767         }
  33768     }
  33769     return BCM_E_RESOURCE;
  33770 }
  33771 
  33772 int
  33773 _bcm_sb2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all) 
  33774 {
  33775     _bcm_oam_pm_profile_control_t *pmc; 
  33776 
  33777     pmc = pm_profile_control[unit];
  33778     
  33779     if (!pmc) {
  33780         return BCM_E_INIT; 
  33781     }
  33782 
  33783     /* Check it only if it is a delete for a particular profile */
  33784     if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) {
  33785         /* It is not in use. Return error */
  33786         return BCM_E_NOT_FOUND;
  33787     }
  33788     /* Zero out that profile */
  33789     sal_memset(_BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0, 
  33790                 sizeof(bcm_oam_pm_profile_info_t));
  33791     /* Mark it un used */
  33792     _BCM_SB2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id);
  33793 
  33794     return BCM_E_NONE;
  33795 }
  33796 
  33797 int
  33798 bcm_sb2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id)
  33799 {
  33800     if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) {
  33801         return BCM_E_PARAM;
  33802     }
  33803     return _bcm_sb2_oam_pm_profile_delete(unit, profile_id, 0);
  33804 }
  33805 
  33806 int
  33807 bcm_sb2_oam_pm_profile_delete_all(int unit)
  33808 {
  33809     int id;
  33810     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
  33811         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_pm_profile_delete(unit, id, 1));
  33812     } 
  33813     return BCM_E_NONE;
  33814 }
  33815 
  33816 int 
  33817 bcm_sb2_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info)
  33818 {
  33819     _bcm_oam_pm_profile_control_t *pmc = NULL;
  33820     bcm_oam_pm_profile_info_t     *profile_ptr = NULL;
  33821     int pm_profile_id = 0;
  33822 
  33823     pmc = pm_profile_control[unit];
  33824 
  33825     if (!pmc) {
  33826         return BCM_E_INIT; 
  33827     }
  33828 
  33829     if (_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
  33830         if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_info->id))) {
  33831             return BCM_E_PARAM;
  33832         }
  33833     }
  33834 
  33835     if (_BCM_SB2_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) {
  33836         if (!(_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) {
  33837             /* replace needs the id to be present */
  33838             return BCM_E_PARAM;
  33839         }
  33840 
  33841         if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) {
  33842             /* Trying to replace a non-existent PM profile */
  33843             return BCM_E_NOT_FOUND;
  33844         }
  33845 
  33846         /* Delete the previous profile. */
  33847         BCM_IF_ERROR_RETURN(bcm_sb2_oam_pm_profile_delete(unit,
  33848                                              profile_info->id));
  33849     }
  33850 
  33851     if (_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
  33852         if (_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) {
  33853             /* That profile id is in use. */
  33854             return BCM_E_EXISTS;
  33855         }
  33856         /* Else use that as the id */
  33857         pm_profile_id = profile_info->id;
  33858     } else { 
  33859         BCM_IF_ERROR_RETURN(_bcm_sb2_find_free_pm_profile_id(unit, 
  33860                                                     &pm_profile_id));
  33861     }
  33862 
  33863     /* Check if such a profile already exists. */
  33864     if (_bcm_sb2_pm_profile_exists(unit, profile_info)) {
  33865         
  33866         return BCM_E_EXISTS;
  33867     }
  33868 
  33869     /* Copy it to local profile information */ 
  33870     profile_ptr = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id);
  33871     sal_memcpy(profile_ptr, profile_info, 
  33872                 sizeof(bcm_oam_pm_profile_info_t));
  33873     
  33874     /* Update the id in the profile */
  33875     profile_ptr->id = profile_info->id =  pm_profile_id;
  33876 
  33877     /* Current flags have only transient meaning, so clear them */
  33878     profile_ptr->flags = 0;
  33879 
  33880     /* Mark that profile used */
  33881     _BCM_SB2_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id);
  33882     
  33883     return BCM_E_NONE;
  33884 }
  33885 
  33886 int
  33887 bcm_sb2_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info)
  33888 {
  33889     _bcm_oam_pm_profile_control_t *pmc;
  33890     int profile_id = profile_info->id; 
  33891 
  33892     pmc = pm_profile_control[unit];
  33893     
  33894     if (!pmc) {
  33895         return BCM_E_INIT; 
  33896     }
  33897 
  33898     if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) {
  33899         return BCM_E_PARAM;
  33900     }
  33901 
  33902     if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  33903         /* It is not in use. Return error */
  33904         return BCM_E_NOT_FOUND;
  33905     }
  33906 
  33907     /* Copy the profile to the profile structure passed */
  33908     sal_memcpy(profile_info, _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id),
  33909                sizeof(bcm_oam_pm_profile_info_t));
  33910 
  33911     return BCM_E_NONE;  
  33912 }
  33913 
  33914 int bcm_sb2_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id,
  33915                               bcm_oam_pm_profile_t profile_id)
  33916 {
  33917     _bcm_oam_pm_profile_control_t *pmc = NULL;
  33918     bcm_oam_pm_profile_info_t *profile_info = NULL;
  33919     _bcm_oam_control_t *oc = NULL;
  33920     _bcm_oam_hash_data_t *h_data_p = NULL;
  33921     int rv = BCM_E_NONE;
  33922     shr_oam_pm_msg_ctrl_profile_attach_t msg_profile_attach;
  33923     uint8                    msg_class = 0;
  33924     uint16                   reply_len = 0;
  33925     uint8                    msg_subclass = 0;
  33926     uint8                    msg_reply_subclass = 0;
  33927     uint8 *buffer, *buffer_ptr;
  33928     uint16 buffer_len;
  33929 
  33930     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  33931     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  33932     _BCM_OAM_LOCK(oc);
  33933 
  33934     h_data_p =  &oc->oam_hash_data[endpoint_id];
  33935 
  33936     if (0 == h_data_p->in_use) {
  33937         LOG_ERROR(BSL_LS_BCM_OAM,
  33938                 (BSL_META_U(unit,
  33939                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  33940                  unit, endpoint_id));
  33941         _BCM_OAM_UNLOCK(oc);
  33942         return (BCM_E_NOT_FOUND);
  33943     }
  33944     pmc = pm_profile_control[unit];
  33945     
  33946     if (!pmc) {
  33947         _BCM_OAM_UNLOCK(oc);
  33948         return BCM_E_INIT; 
  33949     }
  33950 
  33951     if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) {
  33952         _BCM_OAM_UNLOCK(oc);
  33953         return BCM_E_PARAM;
  33954     }
  33955 
  33956     /* Check profile id exists or not */
  33957     if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  33958         /* It is not in use. Return error */
  33959         _BCM_OAM_UNLOCK(oc);
  33960         return BCM_E_NOT_FOUND;
  33961     }
  33962     /* Check if a profile id is already attached to this endpoint */
  33963     if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) {
  33964         _BCM_OAM_UNLOCK(oc);
  33965         return BCM_E_EXISTS;
  33966     }
  33967 
  33968     /* Check if delay measurement flag is present for the endpoint */
  33969     if (!(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) {
  33970         _BCM_OAM_UNLOCK(oc);
  33971         return BCM_E_PARAM;
  33972     }
  33973 
  33974     profile_info = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id);
  33975 
  33976     /* Send info to u-Kernel about the profile attached with the endpoint */
  33977     sal_memset(&msg_profile_attach, 0, sizeof(msg_profile_attach));
  33978 
  33979     if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  33980         msg_class = MOS_MSG_CLASS_ETH_LM_DM; 
  33981         msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_ATTACH;
  33982         msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_ATTACH_REPLY;
  33983 #if defined (INCLUDE_ETH_LM_DM)
  33984         msg_profile_attach.sess_id = h_data_p->lm_dm_uc_session_id;
  33985 #endif
  33986     } else if (BHH_EP_TYPE(h_data_p)) {
  33987         msg_class = MOS_MSG_CLASS_BHH;
  33988         msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH;
  33989         msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY;
  33990 #if defined (INCLUDE_BHH) 
  33991         msg_profile_attach.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  33992 #endif
  33993     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  33994         msg_class = MOS_MSG_CLASS_MPLS_LM_DM;
  33995         msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH;
  33996         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH_REPLY;
  33997 #if defined (INCLUDE_MPLS_LM_DM)
  33998         msg_profile_attach.sess_id = h_data_p->lm_dm_uc_session_id;
  33999 #endif
  34000     }
  34001    
  34002     msg_profile_attach.profile_id = profile_id;
  34003     msg_profile_attach.profile_flags = profile_info->flags;
  34004     sal_memcpy(&(msg_profile_attach.profile_edges), &(profile_info->bin_edges), 
  34005                (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES));
  34006 
  34007     /* Pack control message data into DMA buffer */
  34008     buffer = _bcm_oam_pm_dma_buffer_from_endpoint_type_get(unit, h_data_p);
  34009     buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg_profile_attach);
  34010     buffer_len = buffer_ptr - buffer;
  34011 
  34012 
  34013     rv = _bcm_sb2_oam_pm_msg_send_receive 
  34014         (unit, msg_class, 
  34015          msg_subclass,
  34016          buffer_len, 0, 
  34017          msg_reply_subclass,
  34018          &reply_len);
  34019 
  34020     if(BCM_FAILURE(rv)) {
  34021         _BCM_OAM_UNLOCK(oc);
  34022         return BCM_E_INTERNAL;
  34023     }
  34024 
  34025     /* Attach it to the endpoint */
  34026     h_data_p->pm_profile_attached = profile_id;
  34027 
  34028     _BCM_OAM_UNLOCK(oc);
  34029     return BCM_E_NONE;
  34030 }
  34031 
  34032 int bcm_sb2_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 
  34033                                   bcm_oam_pm_profile_t profile_id)
  34034 {
  34035     _bcm_oam_pm_profile_control_t *pmc = NULL;
  34036     _bcm_oam_control_t *oc = NULL;
  34037     _bcm_oam_hash_data_t *h_data_p = NULL;
  34038     int rv = BCM_E_NONE;
  34039     uint8                    msg_class = 0;
  34040     uint16                   reply_len = 0;
  34041     uint8                    msg_subclass = 0;
  34042     uint8                    msg_reply_subclass = 0;
  34043     uint16                   sess_id = 0;
  34044 
  34045     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34046     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  34047     _BCM_OAM_LOCK(oc);
  34048 
  34049     h_data_p =  &oc->oam_hash_data[endpoint_id];
  34050 
  34051     if (0 == h_data_p->in_use) {
  34052         LOG_ERROR(BSL_LS_BCM_OAM,
  34053                 (BSL_META_U(unit,
  34054                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  34055                  unit, endpoint_id));
  34056         _BCM_OAM_UNLOCK(oc);
  34057         return (BCM_E_NOT_FOUND);
  34058     }
  34059     pmc = pm_profile_control[unit];
  34060     
  34061     if (!pmc) {
  34062         _BCM_OAM_UNLOCK(oc);
  34063         return BCM_E_INIT; 
  34064     }
  34065 
  34066     if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) {
  34067         _BCM_OAM_UNLOCK(oc);
  34068         return BCM_E_PARAM;
  34069     }
  34070 
  34071     /* Check profile id exists or not */
  34072     if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  34073         /* It is not in use. Return error */
  34074         _BCM_OAM_UNLOCK(oc);
  34075         return BCM_E_NOT_FOUND;
  34076     }
  34077 
  34078     /* Check if the passed profile id is the one that is attached */
  34079     if (profile_id != h_data_p->pm_profile_attached) {
  34080         _BCM_OAM_UNLOCK(oc);
  34081         return BCM_E_PARAM;
  34082     }
  34083 
  34084     if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  34085         msg_class = MOS_MSG_CLASS_ETH_LM_DM; 
  34086         msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_DETACH;
  34087         msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_DETACH_REPLY;
  34088 #if defined (INCLUDE_ETH_LM_DM)
  34089         sess_id = h_data_p->lm_dm_uc_session_id;
  34090 #endif
  34091     } else if (BHH_EP_TYPE(h_data_p)) {
  34092         msg_class = MOS_MSG_CLASS_BHH;
  34093         msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH;
  34094         msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY;
  34095 #if defined (INCLUDE_BHH)
  34096         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  34097 #endif
  34098     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  34099         msg_class = MOS_MSG_CLASS_MPLS_LM_DM;
  34100         msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH;
  34101         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH_REPLY;
  34102 #if defined (INCLUDE_MPLS_LM_DM)
  34103         sess_id = h_data_p->lm_dm_uc_session_id;
  34104 #endif
  34105     }
  34106     rv = _bcm_sb2_oam_pm_msg_send_receive 
  34107         (unit, msg_class, 
  34108          msg_subclass,
  34109          sess_id, profile_id, 
  34110          msg_reply_subclass,
  34111          &reply_len);
  34112 
  34113     if(BCM_FAILURE(rv)) {
  34114         _BCM_OAM_UNLOCK(oc);
  34115         return BCM_E_INTERNAL;
  34116     }
  34117     /* Detach the profile from endpoint */
  34118     h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
  34119 
  34120     _BCM_OAM_UNLOCK(oc);
  34121     return BCM_E_NONE;
  34122 }
  34123 
  34124 
  34125 int bcm_sb2_oam_pm_profile_traverse(int unit, 
  34126                     bcm_oam_pm_profile_traverse_cb cb, void *user_data)
  34127 {
  34128     int                     rv = BCM_E_NONE;  /* Operation return status.          */
  34129     bcm_oam_pm_profile_info_t *profile_info = NULL;
  34130     _bcm_oam_pm_profile_control_t *pmc = NULL;
  34131     int profile_id;
  34132 
  34133     /* Validate input parameter. */
  34134     if (NULL == cb) {
  34135         return (BCM_E_PARAM);
  34136     }
  34137     pmc = pm_profile_control[unit];
  34138     
  34139     if (!pmc) {
  34140         return BCM_E_INIT; 
  34141     }
  34142 
  34143     for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) {
  34144         /* Check profile id is in use or not */
  34145         if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
  34146             /* Skip that profile id */
  34147             continue;
  34148         }
  34149         profile_info = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id);
  34150         rv = cb(unit, profile_info, user_data);
  34151         if (BCM_FAILURE(rv)) {
  34152             LOG_ERROR(BSL_LS_BCM_OAM,
  34153                       (BSL_META_U(unit,
  34154                                   "OAM(unit %d) Error: EP=%d callback failed - %s.\n"),
  34155                        unit, profile_id, bcm_errmsg(rv)));
  34156             return (rv);
  34157         }
  34158     }
  34159 
  34160     return (rv);
  34161 }
  34162 
  34163 void _bcm_sb2_oam_copy_stats_msg_to_stats_ptr(shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg,
  34164                                              bcm_oam_pm_stats_t *stats_ptr,
  34165                                              uint8 pm_stat_extra_elem_feature)
  34166 {
  34167     stats_ptr->far_loss_min = stats_msg->far_loss_min;
  34168     stats_ptr->far_tx_min = stats_msg->far_tx_min;   
  34169     stats_ptr->far_loss_max = stats_msg->far_loss_max; 
  34170     stats_ptr->far_tx_max = stats_msg->far_tx_max;
  34171     stats_ptr->far_loss = stats_msg->far_loss;
  34172     stats_ptr->near_loss_min = stats_msg->near_loss_min;
  34173     stats_ptr->near_tx_min = stats_msg->near_tx_min;  
  34174     stats_ptr->near_loss_max = stats_msg->near_loss_max;
  34175     stats_ptr->near_tx_max = stats_msg->near_tx_max;  
  34176     stats_ptr->near_loss = stats_msg->near_loss;    
  34177     stats_ptr->lm_tx_count = stats_msg->lm_tx_count;  
  34178     stats_ptr->DM_min = stats_msg->DM_min;       
  34179     stats_ptr->DM_max = stats_msg->DM_max;
  34180     if(stats_msg->dm_rx_count) {
  34181         stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count;
  34182     }
  34183     stats_ptr->dm_tx_count = stats_msg->dm_tx_count;  
  34184     stats_ptr->profile_id = stats_msg->profile_id;
  34185     sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters), sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1));
  34186     if(pm_stat_extra_elem_feature) {
  34187         stats_ptr->lm_rx_count = stats_msg->lm_rx_count;
  34188         stats_ptr->dm_rx_count = stats_msg->dm_rx_count;
  34189         stats_ptr->far_total_tx_pkt_count = stats_msg->far_total_tx_pkt_count;
  34190         stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count;
  34191     }
  34192 
  34193     if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) {
  34194         stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER;
  34195     }
  34196 }
  34197 
  34198 int bcm_sb2_oam_pm_stats_get(int unit,
  34199                             bcm_oam_endpoint_t endpoint_id, bcm_oam_pm_stats_t *stats_ptr)
  34200 {
  34201     _bcm_oam_pm_profile_control_t *pmc = NULL;
  34202     _bcm_oam_control_t *oc = NULL;
  34203     _bcm_oam_hash_data_t *h_data_p = NULL;
  34204     shr_oam_pm_msg_ctrl_pm_stats_get_t stats_msg;
  34205     int rv = BCM_E_NONE;
  34206     uint16 sess_id = 0;
  34207     uint8                    msg_class = 0;
  34208     uint16                   reply_len = 0;
  34209     uint8                    msg_subclass = 0;
  34210     uint8                    msg_reply_subclass = 0;
  34211     uint8                   *dma_buffer = NULL;
  34212     uint8                   pm_stat_extra_elem_feature = 0;
  34213 
  34214     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34215     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  34216     _BCM_OAM_LOCK(oc);
  34217 
  34218     /* Check endpoint status. */
  34219     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id);
  34220     if ((BCM_E_EXISTS != rv)) {
  34221         /* Endpoint not in use. */
  34222         LOG_ERROR(BSL_LS_BCM_OAM,
  34223                   (BSL_META_U(unit,
  34224                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  34225                    unit, endpoint_id, bcm_errmsg(rv)));
  34226         _BCM_OAM_UNLOCK(oc);
  34227         return (rv);
  34228     }
  34229 
  34230     h_data_p =  &oc->oam_hash_data[endpoint_id];
  34231 
  34232     if (0 == h_data_p->in_use) {
  34233         LOG_ERROR(BSL_LS_BCM_OAM,
  34234                 (BSL_META_U(unit,
  34235                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  34236                  unit, endpoint_id));
  34237         _BCM_OAM_UNLOCK(oc);
  34238         return (BCM_E_INTERNAL);
  34239     }
  34240     pmc = pm_profile_control[unit];
  34241 
  34242     if (!pmc) {
  34243         _BCM_OAM_UNLOCK(oc);
  34244         return BCM_E_INIT; 
  34245     }
  34246 
  34247     
  34248 
  34249     if (h_data_p->type == bcmOAMEndpointTypeEthernet) {
  34250         msg_class = MOS_MSG_CLASS_ETH_LM_DM; 
  34251         msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_STATS_GET;
  34252         msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_STATS_GET_REPLY;
  34253 #if defined (INCLUDE_ETH_LM_DM)
  34254         sess_id = h_data_p->lm_dm_uc_session_id;
  34255 
  34256         if (sess_id == 0) {
  34257             /* It is not in use. Return error */
  34258             _BCM_OAM_UNLOCK(oc);
  34259             return BCM_E_NOT_FOUND;
  34260         }
  34261 
  34262         pm_stat_extra_elem_feature = ETH_LM_DM_UC_FEATURE_CHECK(ETH_LM_DM_PM_STAT_EXTRA_ELEM);
  34263 #endif
  34264     } else if (BHH_EP_TYPE(h_data_p)) {
  34265         msg_class = MOS_MSG_CLASS_BHH;
  34266         msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET;
  34267         msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY;
  34268 #if defined (INCLUDE_BHH)
  34269         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
  34270         pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK(BHH_PM_STAT_EXTRA_ELEM);
  34271 #endif
  34272     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  34273         msg_class = MOS_MSG_CLASS_MPLS_LM_DM;
  34274         msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET;
  34275         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET_REPLY;
  34276 #if defined (INCLUDE_MPLS_LM_DM)
  34277         sess_id = h_data_p->lm_dm_uc_session_id;
  34278 
  34279         if (sess_id == 0) {
  34280             /* It is not in use. Return error */
  34281             _BCM_OAM_UNLOCK(oc);
  34282             return BCM_E_NOT_FOUND;
  34283         }
  34284 
  34285         pm_stat_extra_elem_feature = MPLS_LM_DM_UC_FEATURE_CHECK(MPLS_LM_DM_PM_STAT_EXTRA_ELEM);
  34286 #endif
  34287     }
  34288     dma_buffer = _bcm_oam_pm_dma_buffer_from_endpoint_type_get(unit, h_data_p);
  34289     rv = _bcm_sb2_oam_pm_msg_send_receive 
  34290         (unit, msg_class, 
  34291          msg_subclass,
  34292          /* Pass the buffer pointer in data and sess id in length fields.*/
  34293          sess_id, soc_cm_l2p(unit, dma_buffer),
  34294          msg_reply_subclass,
  34295          &reply_len);
  34296 
  34297     if(BCM_FAILURE(rv) || reply_len == 0) {
  34298         _BCM_OAM_UNLOCK(oc);
  34299         return BCM_E_INTERNAL;
  34300     }
  34301 
  34302     shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg, pm_stat_extra_elem_feature);
  34303 
  34304     _bcm_sb2_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr, pm_stat_extra_elem_feature);
  34305 
  34306     _BCM_OAM_UNLOCK(oc);
  34307     return BCM_E_NONE;
  34308 }
  34309 
  34310 
  34311 int
  34312 bcm_sb2_oam_pm_profile_attach_get(
  34313         int unit,
  34314         bcm_oam_endpoint_t endpoint_id,
  34315         bcm_oam_pm_profile_t *profile_id)
  34316 {
  34317     _bcm_oam_pm_profile_control_t *pmc = NULL;
  34318     _bcm_oam_control_t *oc = NULL;
  34319     _bcm_oam_hash_data_t *h_data_p = NULL;
  34320     int rv = BCM_E_NONE;
  34321 
  34322     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34323     _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id);
  34324     _BCM_OAM_LOCK(oc);
  34325 
  34326     /* Check endpoint status. */
  34327     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id);
  34328     if ((BCM_E_EXISTS != rv)) {
  34329         /* Endpoint not in use. */
  34330         LOG_ERROR(BSL_LS_BCM_OAM,
  34331                   (BSL_META_U(unit,
  34332                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  34333                    unit, endpoint_id, bcm_errmsg(rv)));
  34334         _BCM_OAM_UNLOCK(oc);
  34335         return (rv);
  34336     }
  34337 
  34338     h_data_p =  &oc->oam_hash_data[endpoint_id];
  34339 
  34340     if (0 == h_data_p->in_use) {
  34341         LOG_ERROR(BSL_LS_BCM_OAM,
  34342                 (BSL_META_U(unit,
  34343                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
  34344                  unit, endpoint_id));
  34345         _BCM_OAM_UNLOCK(oc);
  34346         return (BCM_E_INTERNAL);
  34347     }
  34348     pmc = pm_profile_control[unit];
  34349     
  34350     if (!pmc) {
  34351         _BCM_OAM_UNLOCK(oc);
  34352         return BCM_E_INIT; 
  34353     }
  34354 
  34355     /* Get the attached profile */
  34356     *profile_id = h_data_p->pm_profile_attached;
  34357 
  34358     if (*profile_id == _BCM_OAM_INVALID_INDEX) {
  34359         _BCM_OAM_UNLOCK(oc);
  34360         return BCM_E_NOT_FOUND;
  34361     } 
  34362     /* Check profile id is in use or not */
  34363     if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) {
  34364         /* It is not in use. Return error */
  34365         /* Ideally this should not happen */
  34366         _BCM_OAM_UNLOCK(oc);
  34367         return BCM_E_INTERNAL;
  34368     }
  34369 
  34370     _BCM_OAM_UNLOCK(oc);
  34371     return BCM_E_NONE;
  34372 }
  34373 
  34374 void
  34375 _bcm_sb2_write_dma_buffer_to_raw_buffer(int unit, uint8 *dma_buffer,
  34376                                         bcm_oam_pm_raw_data_t *raw_data, int write_index)
  34377 {
  34378     shr_oam_pm_msg_ctrl_raw_buffer_unpack(dma_buffer, 
  34379      (shr_oam_pm_msg_ctrl_raw_buffer_t *)(&(raw_data->raw_buffer[write_index])));
  34380 }
  34381 
  34382 int _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(bcm_oam_event_type_t event_type)
  34383 {
  34384     switch (event_type) {
  34385         case bcmOAMEventBHHRawData:
  34386             return _BCM_SB2_OAM_PM_BHH_EVENT_IDX;
  34387             break;
  34388         case bcmOAMEventEthLmDmRawData:
  34389             return _BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX;
  34390             break;
  34391         case bcmOAMEventMplsLmDmRawData:
  34392             return _BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX;
  34393             break;
  34394         default:
  34395             return -1;
  34396             break;
  34397     }
  34398     return -1;
  34399 }                                     
  34400 
  34401 void _bcm_sb2_update_num_free_buffers(_bcm_oam_control_t *oc, 
  34402                                       int event_idx, int read_idx,
  34403                                       int write_idx, int last_op)
  34404 {
  34405     /* Normal case */
  34406     if (read_idx < write_idx) {
  34407         SET_NUM_FREE_BUFFERS(event_idx,
  34408                 (BCM_OAM_MAX_PM_BUFFERS - (write_idx - read_idx)));
  34409     } else if (read_idx > write_idx) { 
  34410         /* rollover case */
  34411         SET_NUM_FREE_BUFFERS(event_idx,
  34412                 (read_idx - write_idx));
  34413     } else { /* read index = write index case */
  34414         if (last_op == 1) { 
  34415             /* Last operation was write, means write idx has caught
  34416                up with read_idx.
  34417                Just decrement the number of buffers by 1.
  34418                Ideally this would mean the num of free buffers would
  34419                become zero */
  34420             DECR_NUM_FREE_BUFFERS(event_idx);
  34421         }  else if (last_op == 0) {
  34422             /* Last operation was read, means read idx has caught
  34423                up with write idx.
  34424                Just increment the number of buffers by 1.
  34425                Ideally this would mean the num of free buffers would
  34426                have become max. */
  34427             INCR_NUM_FREE_BUFFERS(event_idx);
  34428         }
  34429     }
  34430 }
  34431 /* Returns 0 - Not updated or 1 - Updated */
  34432 int
  34433 _bcm_sb2_update_dma_buffer_into_raw_buffer(int unit, bcm_oam_event_type_t event_type, 
  34434                           uint8 *dma_buffer,bcm_oam_pm_raw_data_t *raw_data)
  34435 {
  34436     int rv = BCM_E_NONE;
  34437     int event_idx = -1;
  34438     _bcm_oam_control_t *oc;
  34439     int read_idx = -1;
  34440     int write_idx = -1;
  34441     
  34442     /* Get OAM Control Structure. */
  34443     rv = _bcm_sb2_oam_control_get(unit, &oc);
  34444     if (BCM_FAILURE(rv)) {
  34445         return FALSE;
  34446     }
  34447 
  34448     event_idx = _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(event_type);
  34449     if (event_idx == -1) {
  34450         return FALSE;
  34451     }
  34452 
  34453     if (NUM_FREE_BUFFERS(event_idx) > 0) {
  34454         PM_WRITE_DONE_INDEX(event_idx) = INCREMENT_PM_WRITE_DONE_INDEX(event_idx);
  34455         /* Writing at the incremented index */
  34456         _bcm_sb2_write_dma_buffer_to_raw_buffer(unit, dma_buffer, raw_data,
  34457                 PM_WRITE_DONE_INDEX(event_idx));
  34458     } else {
  34459         /* There are no free buffers. Do not update */
  34460         return FALSE;
  34461     }
  34462     read_idx = PM_READ_DONE_INDEX(event_idx);
  34463     write_idx = PM_WRITE_DONE_INDEX(event_idx); 
  34464 
  34465     /* 1 passed indicates last operation was write */
  34466     _bcm_sb2_update_num_free_buffers(oc, event_idx, read_idx, write_idx, 1);
  34467 
  34468     raw_data->read_index = PM_READ_DONE_INDEX(event_idx);
  34469     raw_data->write_index = PM_WRITE_DONE_INDEX(event_idx);
  34470 
  34471     return TRUE;
  34472 }
  34473 
  34474 int
  34475 bcm_sb2_oam_pm_raw_data_read_done(int unit,
  34476                                   bcm_oam_event_types_t event_types,
  34477                                   uint32 read_index)
  34478 {
  34479     bcm_oam_event_type_t event_type;
  34480     _bcm_oam_control_t *oc;
  34481     int event_idx = -1;
  34482 
  34483     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34484     /* Do sanity validation of event_types and read_index */
  34485     if (!(_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types))) {
  34486         return BCM_E_PARAM;
  34487     }
  34488 
  34489     if (!(VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(read_index))) {
  34490         return BCM_E_PARAM;
  34491     }
  34492 
  34493     for (event_type = bcmOAMEventBHHRawData; event_type <= bcmOAMEventMplsLmDmRawData; event_type++) { 
  34494         if (BCM_OAM_EVENT_TYPE_GET(event_types, event_type)) {
  34495             event_idx = _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(event_type);
  34496             if (event_idx == -1) {
  34497                 return BCM_E_PARAM;
  34498             }
  34499             PM_READ_DONE_INDEX(event_idx) = read_index;
  34500             /* 0 passed indicates last operation was read */
  34501             _bcm_sb2_update_num_free_buffers(oc, event_idx, read_index, 
  34502                                              PM_WRITE_DONE_INDEX(event_idx), 0);
  34503         }
  34504     }
  34505     return BCM_E_NONE;
  34506 }
  34507 
  34508 bcm_oam_pm_raw_data_t *_bcm_sb2_oam_pm_raw_data_info_get(int unit, 
  34509                                   bcm_oam_event_type_t event_type)
  34510 {
  34511     int rv = BCM_E_NONE;
  34512     _bcm_oam_control_t *oc;
  34513 
  34514     rv = _bcm_sb2_oam_control_get(unit, &oc);
  34515     if (BCM_FAILURE(rv)) {
  34516         return NULL;
  34517     }
  34518     switch (event_type) {
  34519         case bcmOAMEventBHHRawData:
  34520 #if defined (INCLUDE_BHH)
  34521             return &(oc->pm_bhh_raw_data_info); 
  34522 #else
  34523             return NULL;
  34524 #endif
  34525             break;
  34526         case bcmOAMEventEthLmDmRawData:
  34527 #if defined (INCLUDE_ETH_LM_DM)
  34528             return &(oc->pm_eth_lm_dm_raw_data_info); 
  34529 #else
  34530             return NULL;
  34531 #endif
  34532             break;
  34533         case bcmOAMEventMplsLmDmRawData:
  34534 #if defined (INCLUDE_MPLS_LM_DM)
  34535             return &(oc->pm_mpls_lm_dm_raw_data_info); 
  34536 #else
  34537             return NULL;
  34538 #endif
  34539             break;
  34540         default:
  34541             return NULL;
  34542             break;
  34543     }
  34544     return NULL;
  34545 }
  34546 
  34547 #if defined (INCLUDE_BHH) || defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM)
  34548 STATIC void _bcm_sb2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc,
  34549                                              mos_msg_data_t *event_msg)
  34550 {
  34551     bcm_oam_event_type_t event_type = 0;
  34552     _bcm_oam_pm_event_handler_t *pm_event_handler_p;
  34553     bcm_oam_pm_raw_data_t *raw_data = NULL;
  34554     uint8 *dma_buffer = NULL;
  34555     int is_updated = 0;
  34556 #if defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_ETH_LM_DM)
  34557     uint32       event_mask;
  34558     int          sess_id;
  34559     uint16       ep_id = 0;
  34560     _bcm_oam_hash_data_t *h_data_p = NULL;
  34561     bcm_oam_event_types_t events;
  34562     _bcm_oam_event_handler_t *event_handler_p;
  34563 #endif
  34564 
  34565     switch (event_msg->s.mclass) {
  34566         case MOS_MSG_CLASS_BHH_EVENT:
  34567             event_type = bcmOAMEventBHHRawData;
  34568             break;
  34569         case MOS_MSG_CLASS_ETH_LM_DM_EVENT:
  34570 #if defined (INCLUDE_ETH_LM_DM)
  34571             event_mask = bcm_ntohl(event_msg->s.data);
  34572             if (event_mask & ETH_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
  34573                 event_type = bcmOAMEventEthLmDmPmCounterRollover;
  34574                 sess_id = (int)bcm_ntohs(event_msg->s.len);
  34575                 ep_id = oc->eth_lm_dm_sess_id_ep_id[sess_id];
  34576                 h_data_p = &oc->oam_hash_data[ep_id];
  34577                 /* Set events */
  34578                 sal_memset(&events, 0, sizeof(events));
  34579                 LOG_DEBUG(BSL_LS_BCM_OAM,
  34580                           (BSL_META_U(oc->unit,
  34581                            "****** OAM PM ETH_LM_DM Counter Rollover ******\n")));
  34582                 if (oc->event_handler_cnt[bcmOAMEventEthLmDmPmCounterRollover] > 0) {
  34583                     SHR_BITSET(events.w, bcmOAMEventEthLmDmPmCounterRollover);
  34584                 }
  34585             } else {
  34586                 event_type = bcmOAMEventEthLmDmRawData;
  34587             }
  34588 #endif
  34589             break;
  34590         case MOS_MSG_CLASS_MPLS_LM_DM_EVENT:
  34591 #if defined (INCLUDE_MPLS_LM_DM)
  34592             event_mask = bcm_ntohl(event_msg->s.data);
  34593             if (event_mask & MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
  34594                 event_type = bcmOAMEventMplsLmDmPmCounterRollover;
  34595                 sess_id = (int)bcm_ntohs(event_msg->s.len);
  34596                 ep_id = oc->mpls_lm_dm_sess_id_ep_id[sess_id];
  34597                 h_data_p = &oc->oam_hash_data[ep_id];
  34598                 /* Set events */
  34599                 sal_memset(&events, 0, sizeof(events));
  34600                 LOG_DEBUG(BSL_LS_BCM_OAM,
  34601                           (BSL_META_U(oc->unit,
  34602                            "****** OAM PM MPLS_LM_DM Counter Rollover ******\n")));
  34603                 if (oc->event_handler_cnt[bcmOAMEventMplsLmDmPmCounterRollover] > 0) {
  34604                     SHR_BITSET(events.w, bcmOAMEventMplsLmDmPmCounterRollover);
  34605                 }
  34606             } else {
  34607                 event_type = bcmOAMEventMplsLmDmRawData;
  34608             }
  34609 #endif
  34610             break;
  34611         default:
  34612             LOG_ERROR(BSL_LS_BCM_OAM,
  34613                     (BSL_META(
  34614                               "OAM(unit %d) Error: %s called"
  34615                               "for unknown protocol"
  34616                               "- %d.\n"),
  34617                      oc->unit, FUNCTION_NAME(), event_msg->s.mclass));
  34618             return;
  34619             break;
  34620     }
  34621 
  34622     if (oc->pm_event_handler_cnt[event_type] < 0) {
  34623         LOG_ERROR(BSL_LS_BCM_OAM,
  34624                 (BSL_META(
  34625                           "OAM(unit %d) Error: Received notif for"
  34626                           "event without callback - %d.\n"),
  34627                  oc->unit, event_type));
  34628     }
  34629 
  34630     /* Loop over registered callbacks
  34631      */
  34632     if ((event_type == bcmOAMEventEthLmDmPmCounterRollover) ||
  34633         (event_type == bcmOAMEventMplsLmDmPmCounterRollover)) {
  34634 #if defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_ETH_LM_DM)
  34635         for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL;
  34636              event_handler_p = event_handler_p->next_p) {
  34637             if (SHR_BITGET(events.w, event_type)) {
  34638                 if (SHR_BITGET(event_handler_p->event_types.w, event_type)) {
  34639                     event_handler_p->cb(oc->unit,
  34640                                         0, event_type,
  34641                                         h_data_p->group_index,
  34642                                         ep_id,
  34643                                         event_handler_p->user_data);
  34644                 }
  34645             }
  34646         }
  34647 #endif
  34648     } else {
  34649         for (pm_event_handler_p = oc->pm_event_handler_list_p;
  34650                 pm_event_handler_p != NULL;
  34651                 pm_event_handler_p = pm_event_handler_p->next_p) {
  34652             if (SHR_BITGET(pm_event_handler_p->event_types.w,
  34653                            event_type)) {
  34654                 raw_data = _bcm_sb2_oam_pm_raw_data_info_get(oc->unit,
  34655                                                              event_type);
  34656                 dma_buffer = _bcm_sb2_oam_pm_dma_buffer_get(oc->unit,
  34657                                                             event_type);
  34658                 if (!raw_data) {
  34659                     /* Should not happen. This would mean you have received
  34660                      * a PM event for which you have not allocated buffers
  34661                      * itself.
  34662                      */
  34663                     LOG_ERROR(BSL_LS_BCM_OAM,
  34664                               (BSL_META_U(oc->unit,
  34665                                           "OAM(unit %d) Error: Oam raw data get failed "
  34666                                           "event - %d.\n"), oc->unit, event_type));
  34667                 }
  34668                 is_updated = _bcm_sb2_update_dma_buffer_into_raw_buffer(oc->unit,
  34669                                                                         event_type,
  34670                                                                         dma_buffer,
  34671                                                                         raw_data);
  34672                 if (is_updated) {
  34673                     pm_event_handler_p->cb(oc->unit,
  34674                                            event_type,
  34675                                            raw_data, /* The raw data */
  34676                                            pm_event_handler_p->user_data);
  34677                 } else {
  34678                     /* Oops ! The event is lost ! */
  34679                     LOG_WARN(BSL_LS_BCM_OAM,
  34680                             (BSL_META_U(oc->unit,
  34681                                         "OAM(unit %d) Error: PM event missed "
  34682                                         "event - %d.\n"), oc->unit, event_type));
  34683                 }
  34684             }
  34685         }
  34686     }
  34687     
  34688 }
  34689 #endif
  34690 #if defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 
  34691 /*
  34692  * Function:
  34693  *      _bcm_sb2_oam_pm_callback_thread_func
  34694  * Purpose:
  34695  *      Thread to listen for event messages from uController for PM events.
  34696  * Parameters:
  34697  *      oc - Pointer to oam control structures.
  34698  *      events - the set of events that we are listening.
  34699  * Returns:
  34700  *      None
  34701  */
  34702 STATIC void _bcm_oam_pm_callback_thread_func(_bcm_oam_control_t *oc, 
  34703                                         bcm_oam_event_types_t event_types)
  34704 {
  34705     int rv;
  34706     mos_msg_data_t event_msg;
  34707     char thread_name[SAL_THREAD_NAME_MAX_LEN];
  34708     sal_thread_t *pm_event_thread_id = NULL;
  34709     int          uc_num = -1;
  34710     uint8        msg_class = 0;
  34711 
  34712     if (BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventEthLmDmRawData) ||
  34713         BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventEthLmDmPmCounterRollover)) {
  34714         pm_event_thread_id = &(oc->eth_lm_dm_pm_event_thread_id);
  34715 #if defined (INCLUDE_ETH_LM_DM)
  34716         uc_num = oc->eth_lm_dm_uc_num;
  34717 #endif
  34718         msg_class = MOS_MSG_CLASS_ETH_LM_DM_EVENT;
  34719     } else if (BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmRawData) ||
  34720                BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmPmCounterRollover)) {
  34721         pm_event_thread_id = &(oc->mpls_lm_dm_pm_event_thread_id);
  34722 #if defined (INCLUDE_MPLS_LM_DM)
  34723         uc_num = oc->mpls_lm_dm_uc_num;
  34724 #endif
  34725         msg_class = MOS_MSG_CLASS_MPLS_LM_DM_EVENT;
  34726     } else {
  34727         /* No other event is currently handled here. return. */
  34728         LOG_ERROR(BSL_LS_BCM_OAM,
  34729                 (BSL_META_U(oc->unit,
  34730                             "OAM(unit %d) Error: %s called for unknown "
  34731                             "event.\n"), oc->unit, FUNCTION_NAME()));
  34732         return;
  34733     }
  34734 
  34735     thread_name[0] = 0;
  34736     sal_thread_name(*pm_event_thread_id, thread_name, sizeof (thread_name));
  34737 
  34738     while (1) {
  34739         /* Wait on notifications from uController */
  34740         rv = soc_cmic_uc_msg_receive(oc->unit, uc_num,
  34741                 msg_class, &event_msg,
  34742                 sal_sem_FOREVER);
  34743 
  34744         if (BCM_FAILURE(rv)) {
  34745             break;  /*  Thread exit */
  34746         } else {
  34747             if ((event_msg.s.subclass == _ETH_LM_DM_EVENT_OAM_PM_EVENT) ||
  34748                 (event_msg.s.subclass == _MPLS_LM_DM_EVENT_OAM_PM_EVENT)) {
  34749                 _bcm_sb2_oam_pm_event_msg_handle(oc, &event_msg);
  34750             } else {
  34751                 LOG_ERROR(BSL_LS_BCM_OAM,
  34752                         (BSL_META(
  34753                                   "OAM(unit %d) Error: Unknown PM event"
  34754                                   "- %d.\n"),
  34755                          oc->unit, event_msg.s.subclass));
  34756             }
  34757         }
  34758     }
  34759 
  34760     *pm_event_thread_id   = NULL;
  34761     LOG_ERROR(BSL_LS_BCM_OAM,
  34762               (BSL_META_U(oc->unit,
  34763                           "Thread Exit:%s\n"), thread_name));
  34764     sal_thread_exit(0);
  34765 }
  34766 #endif
  34767 
  34768 #if defined (INCLUDE_ETH_LM_DM)
  34769 STATIC void
  34770 _bcm_sb2_oam_pm_ethlmdm_callback_thread(void *param)
  34771 {
  34772     _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param;
  34773     bcm_oam_event_types_t event_types = {{0}};
  34774 
  34775     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEthLmDmRawData);
  34776     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEthLmDmPmCounterRollover);
  34777 
  34778     _bcm_oam_pm_callback_thread_func(oc, event_types);
  34779 }
  34780 #endif
  34781 #if defined (INCLUDE_MPLS_LM_DM)
  34782 STATIC void
  34783 _bcm_sb2_oam_pm_mplslmdm_callback_thread(void *param)
  34784 {
  34785     _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param;
  34786     bcm_oam_event_types_t event_types = {{0}};
  34787 
  34788     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmRawData);
  34789     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmPmCounterRollover);
  34790 
  34791     _bcm_oam_pm_callback_thread_func(oc, event_types);
  34792 }
  34793 #endif
  34794 
  34795 int 
  34796 bcm_sb2_oam_opcode_group_set(int unit, bcm_oam_protocol_type_t  proto,
  34797         bcm_oam_opcodes_t opcodes, uint8 opcode_group) {
  34798 
  34799     int                       rv = BCM_E_NONE;
  34800     _bcm_oam_control_t        *oc;        /* Pointer to OAM control structure. */
  34801     oam_opcode_group_entry_t  opcode_grp_entry;
  34802     int                       opcode_value;
  34803     int                       opcode_key = -1;
  34804     oam_opcode_control_profile_entry_t *opcode_entry = NULL; /* Opcode control 
  34805                                                          profile entry.  */
  34806     egr_oam_opcode_control_profile_entry_t *egr_opcode_entry = NULL;
  34807     void        *entries[1];   /* Profile entry. */
  34808 
  34809     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34810 
  34811     _BCM_OAM_LOCK(oc);
  34812 
  34813     if(opcode_group >= _BCM_SB2_OAM_NUM_OPCODE_GROUPS) {
  34814         _BCM_OAM_UNLOCK(oc);
  34815         return BCM_E_PARAM;
  34816     }
  34817 
  34818     for (opcode_value = 0; opcode_value <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST;
  34819             opcode_value++) {
  34820 
  34821         if(BCM_OAM_OPCODES_BITMAP_GET(opcodes,opcode_value)){
  34822 
  34823             /* Try to form the key( _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value))and 
  34824              * do a table lookup  to modify the the entries opcode */ 
  34825             switch(proto) {
  34826                 case bcmOamProtocolEth:
  34827                     opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value);
  34828                     break;
  34829 
  34830                 case bcmOamProtocolBhh :
  34831                     opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode_value);
  34832                     break;
  34833 
  34834                 case bcmOamProtocolMplsLmDm :
  34835                     opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode_value);
  34836                     break;
  34837 
  34838                 default:
  34839                     rv = BCM_E_PARAM;
  34840                     _BCM_OAM_UNLOCK(oc);
  34841                     return rv;
  34842 
  34843             }     
  34844         }     
  34845 
  34846         /* If opocde value is not preset in the opcodes bitmap then
  34847          * opcode_key will not be set. So go for next opocode value in the bitmap */
  34848 
  34849         if(opcode_key == -1) {
  34850             continue;
  34851         }
  34852 
  34853         rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY,
  34854                 opcode_key, &opcode_grp_entry);
  34855 
  34856         if (BCM_FAILURE(rv)) {
  34857             LOG_ERROR(BSL_LS_BCM_OAM,
  34858                     (BSL_META_U(unit,
  34859                                 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  read "
  34860                                 "failed  %s.\n"), unit, bcm_errmsg(rv)));
  34861             _BCM_OAM_UNLOCK(oc);
  34862             return rv; 
  34863         }                        
  34864 
  34865         soc_mem_field32_set(unit, OAM_OPCODE_GROUPm,
  34866                 &opcode_grp_entry, OPCODE_GROUPf, opcode_group);
  34867 
  34868         rv = soc_mem_write(unit, OAM_OPCODE_GROUPm,
  34869                 MEM_BLOCK_ALL, opcode_key, &opcode_grp_entry);
  34870 
  34871         if (BCM_FAILURE(rv)) {
  34872             LOG_ERROR(BSL_LS_BCM_OAM,
  34873                     (BSL_META_U(unit,
  34874                                 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  write "
  34875                                 "failed  %s.\n"), unit, bcm_errmsg(rv)));
  34876             _BCM_OAM_UNLOCK(oc);
  34877             return rv;
  34878         }
  34879 
  34880         rv = soc_mem_write(unit, EGR_OAM_OPCODE_GROUPm,
  34881                 MEM_BLOCK_ALL, opcode_key, &opcode_grp_entry);
  34882 
  34883         if (BCM_FAILURE(rv)) {
  34884             LOG_ERROR(BSL_LS_BCM_OAM,
  34885                     (BSL_META_U(unit,
  34886                                 "OAM(unit %d) Error: EGR_OAM_OPCODE_GROUP table entry  write "
  34887                                 "failed  %s.\n"), unit, bcm_errmsg(rv)));
  34888             _BCM_OAM_UNLOCK(oc);
  34889             return rv;
  34890         }
  34891     }
  34892 
  34893     opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, "opcode profile");
  34894     sal_memset(opcode_entry, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE);
  34895     rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, OAM_OPCODE_CONTROL_PROFILEm, opcode_entry);
  34896     if (BCM_FAILURE(rv)) {
  34897         LOG_ERROR(BSL_LS_BCM_OAM,
  34898                 (BSL_META_U(unit,
  34899                             "OAM(unit %d) Error: Opcode profile init failed "
  34900                             "  %s.\n"), unit, bcm_errmsg(rv)));
  34901         if(opcode_entry) {
  34902             sal_free(opcode_entry);
  34903         }
  34904         _BCM_OAM_UNLOCK(oc);
  34905         return (rv);
  34906     }
  34907     /* Add entry to profile table.  */
  34908     entries[0] = opcode_entry;
  34909     rv = soc_profile_mem_set(unit, &oc->oam_opcode_control_profile,
  34910             (void *)entries, _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX);
  34911     if (BCM_FAILURE(rv)) {
  34912         LOG_ERROR(BSL_LS_BCM_OAM,
  34913                 (BSL_META_U(unit,
  34914                             "OAM(unit %d) Opcode profile table is full - %s.\n"),
  34915                  unit, bcm_errmsg(rv)));
  34916         if(opcode_entry) {
  34917             sal_free(opcode_entry);
  34918         }
  34919         _BCM_OAM_UNLOCK(oc);
  34920         return rv;
  34921     }
  34922     if(opcode_entry) {
  34923         sal_free(opcode_entry);
  34924     }
  34925     
  34926     egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, "egr opcode profile");
  34927     /* Create default opcode control profile */
  34928     sal_memset(egr_opcode_entry, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE);
  34929     rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, EGR_OAM_OPCODE_CONTROL_PROFILEm, egr_opcode_entry);
  34930     if (BCM_FAILURE(rv)) {
  34931         LOG_ERROR(BSL_LS_BCM_OAM,
  34932                 (BSL_META_U(unit,
  34933                             "OAM(unit %d) Error: Opcode profile init failed "
  34934                             "  %s.\n"), unit, bcm_errmsg(rv)));
  34935         if(egr_opcode_entry) {
  34936             sal_free(egr_opcode_entry);
  34937         }
  34938         _BCM_OAM_UNLOCK(oc);
  34939         return (rv);
  34940     }
  34941     /* Add entry to profile table.  */
  34942     entries[0] = egr_opcode_entry;
  34943     rv = soc_profile_mem_set(unit, &oc->egr_oam_opcode_control_profile,
  34944             (void *)entries, _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX);
  34945     if (BCM_FAILURE(rv)) {
  34946         LOG_ERROR(BSL_LS_BCM_OAM,
  34947                 (BSL_META_U(unit,
  34948                             "OAM(unit %d) Egr Opcode profile table is full - %s.\n"),
  34949                  unit, bcm_errmsg(rv)));
  34950         if(egr_opcode_entry) {
  34951             sal_free(egr_opcode_entry);
  34952         }
  34953         _BCM_OAM_UNLOCK(oc);
  34954         return rv;
  34955     }
  34956     if(egr_opcode_entry) {
  34957         sal_free(egr_opcode_entry);
  34958     }
  34959 
  34960     _BCM_OAM_UNLOCK(oc);
  34961     return rv;
  34962 }
  34963 
  34964 int 
  34965 bcm_sb2_oam_opcode_group_get(int unit, bcm_oam_protocol_type_t  proto,
  34966         bcm_oam_opcode_t opcode, uint8 *opcode_group) {
  34967 
  34968     int                       rv = BCM_E_NONE;
  34969     _bcm_oam_control_t        *oc;        /* Pointer to OAM control structure. */
  34970     oam_opcode_group_entry_t  opcode_grp_entry;
  34971     int                       opcode_key = -1;
  34972 
  34973     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  34974 
  34975     _BCM_OAM_LOCK(oc);
  34976 
  34977     if(opcode >= bcmOamOpcodeMax) {
  34978         _BCM_OAM_UNLOCK(oc);
  34979         return BCM_E_PARAM;
  34980     }
  34981 
  34982     /* Try to form the key( _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value))and 
  34983      * do a table lookup  to get the the opcode group*/ 
  34984     switch(proto) {
  34985         case bcmOamProtocolEth:
  34986             opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode);
  34987             break;
  34988 
  34989         case bcmOamProtocolBhh :
  34990             opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode);
  34991             break;
  34992 
  34993         case bcmOamProtocolMplsLmDm :
  34994             opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode);
  34995             break;
  34996 
  34997         default:
  34998             rv = BCM_E_PARAM;
  34999              _BCM_OAM_UNLOCK(oc);
  35000             return rv;
  35001     }     
  35002 
  35003     rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY,
  35004             opcode_key, &opcode_grp_entry);
  35005 
  35006     if (BCM_FAILURE(rv)) {
  35007         LOG_ERROR(BSL_LS_BCM_OAM,
  35008                 (BSL_META_U(unit,
  35009                             "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry  read "
  35010                             "failed  %s.\n"), unit, bcm_errmsg(rv)));
  35011          _BCM_OAM_UNLOCK(oc);
  35012         return rv; 
  35013     }                        
  35014 
  35015     *opcode_group = soc_mem_field32_get(unit, OAM_OPCODE_GROUPm,
  35016             &opcode_grp_entry, OPCODE_GROUPf);
  35017 
  35018      _BCM_OAM_UNLOCK(oc);
  35019     return rv;
  35020 }
  35021 
  35022 
  35023 /*
  35024  * Function:
  35025  *      bcm_sb2_oam_endpoint_egress_intf_egress_attach 
  35026  * Purpose:
  35027  *      Attach Egress object pointed by egress_intf to a MPLS LSP endpoint 
  35028  *
  35029  * Parameters:
  35030  *      unit        (IN) BCM device number
  35031  *      ep_d        (IN) BHH endpoint ID 
  35032  *      egress_intf (IN) Egress object 
  35033  *
  35034  * Returns:
  35035  *      BCM_E_NONE          No error
  35036  *      BCM_E_XXXX          Error
  35037  */
  35038 
  35039 int bcm_sb2_oam_endpoint_egress_intf_egress_attach(int unit,
  35040         bcm_oam_endpoint_t ep_id,
  35041          bcm_if_t egress_intf)
  35042 {
  35043 
  35044     int rv = BCM_E_UNAVAIL;
  35045 #if defined(INCLUDE_L3)
  35046     _bcm_oam_hash_data_t *h_data_p = NULL;
  35047     _bcm_oam_control_t *oc = NULL;
  35048     uint32 egr_nh_index = 0;
  35049     egr_l3_next_hop_entry_t egr_nh_entry;
  35050     int found = 0;
  35051     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35052     bcm_l3_egress_t l3_egress;
  35053 
  35054     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35055     _BCM_OAM_EP_INDEX_VALIDATE(ep_id);
  35056 
  35057     _BCM_OAM_LOCK(oc);
  35058 
  35059     /* Check endpoint status. */
  35060     rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id);
  35061     if ((BCM_E_EXISTS != rv)) {
  35062         /* Endpoint not in use. */
  35063         LOG_ERROR(BSL_LS_BCM_OAM,
  35064                 (BSL_META_U(unit,
  35065                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35066                  unit, ep_id, bcm_errmsg(rv)));
  35067         _BCM_OAM_UNLOCK(oc);
  35068         return (rv);
  35069     }
  35070 
  35071     /* Check the Existed Egress Interface Status */
  35072     bcm_l3_egress_t_init(&l3_egress);
  35073     if (BCM_FAILURE
  35074             (bcm_esw_l3_egress_get(unit, egress_intf, &l3_egress))) {
  35075         _BCM_OAM_UNLOCK(oc);
  35076         return BCM_E_NOT_FOUND;
  35077     }
  35078 
  35079     h_data_p =  &oc->oam_hash_data[ep_id];
  35080     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35081         _BCM_OAM_UNLOCK(oc);
  35082         return (BCM_E_INTERNAL);
  35083     }
  35084     /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */
  35085     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35086         _BCM_OAM_UNLOCK(oc);
  35087         return BCM_E_PARAM;
  35088     }
  35089     
  35090     /* Run through the egress_if_list and check if the given egress interface 
  35091        already exists */
  35092     list_node = h_data_p->egress_if_list;
  35093     while (list_node != NULL) {
  35094         if (egress_intf == list_node->egress_if) {
  35095             found = 1;
  35096             break;
  35097         }
  35098         list_node = list_node->next;
  35099     }
  35100     if (found) {
  35101         _BCM_OAM_UNLOCK(oc);
  35102         return BCM_E_EXISTS;
  35103     }
  35104 
  35105     if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_intf)) {
  35106         egr_nh_index = egress_intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  35107     }
  35108     else if(BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_intf)) {
  35109         egr_nh_index = egress_intf - BCM_XGS3_EGRESS_IDX_MIN(unit);
  35110     } else {
  35111         _BCM_OAM_UNLOCK(oc);
  35112         return BCM_E_PARAM;
  35113     }
  35114 
  35115     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  35116     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
  35117             egr_nh_index, &egr_nh_entry);
  35118     if (BCM_FAILURE(rv)) {
  35119         _BCM_OAM_UNLOCK(oc);
  35120         return (rv);
  35121     }
  35122 
  35123     /* Depending on whether endpoint is BHH or MPLS LM/DM, write 1/2 in MPLS_OAM_DOWNMEP_ENABLE. */
  35124     if (BHH_EP_TYPE(h_data_p)) {
  35125 #if defined(INCLUDE_BHH)
  35126         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35127                                          MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35128                                          _BCM_SB2_MPLS_OAM_ENABLE_BHH);
  35129 
  35130         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35131                                          MPLS__MEPIDf,
  35132                                          BCM_OAM_BHH_GET_LSP_KEY(h_data_p));
  35133 #endif /* INCLUDE_BHH */
  35134     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  35135         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35136                                          MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35137                                          _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM);
  35138 
  35139         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35140                                          MPLS__MEPIDf,
  35141                                          h_data_p->name);
  35142     } else {
  35143         _BCM_OAM_UNLOCK(oc);
  35144         return BCM_E_PARAM;
  35145     }
  35146 
  35147     rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL,
  35148             egr_nh_index, &egr_nh_entry);
  35149     if (BCM_FAILURE(rv)) {
  35150         _BCM_OAM_UNLOCK(oc);
  35151         return (rv);
  35152     }
  35153     
  35154     /* Add the egress_if (encap_id) into the endpoint's egress_if_list */
  35155     _bcm_sb2_oam_endpoint_egress_intf_add(unit, h_data_p, egress_intf);
  35156 
  35157     _BCM_OAM_UNLOCK(oc);
  35158     rv = BCM_E_NONE;
  35159 
  35160 #endif
  35161     return rv;
  35162 }
  35163 
  35164 /*
  35165  * Function:
  35166  *      bcm_sb2_oam_endpoint_egress_intf_egress_detach 
  35167  * Purpose:
  35168  *      detach Egress object pointed by egress_intf from a MPLS LSP endpoint 
  35169  *
  35170  * Parameters:
  35171  *      unit        (IN) BCM device number
  35172  *      ep_d        (IN) BHH endpoint ID 
  35173  *      egress_intf (IN) Egress object 
  35174  *
  35175  * Returns:
  35176  *      BCM_E_NONE          No error
  35177  *      BCM_E_XXXX          Error
  35178  */
  35179 
  35180 int bcm_sb2_oam_endpoint_egress_intf_egress_detach(int unit,
  35181         bcm_oam_endpoint_t ep_id,
  35182          bcm_if_t egress_intf)
  35183 {
  35184     int rv = BCM_E_UNAVAIL;
  35185 #if defined(INCLUDE_L3)
  35186     _bcm_oam_hash_data_t *h_data_p = NULL;
  35187     _bcm_oam_control_t *oc = NULL;
  35188     uint32 egr_nh_index = 0;
  35189     egr_l3_next_hop_entry_t egr_nh_entry;
  35190     uint16 mepid;
  35191     int found = 0;
  35192     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35193 
  35194     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35195     _BCM_OAM_EP_INDEX_VALIDATE(ep_id);
  35196 
  35197     _BCM_OAM_LOCK(oc);
  35198 
  35199     /* Check endpoint status. */
  35200     rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id);
  35201     if ((BCM_E_EXISTS != rv)) {
  35202         /* Endpoint not in use. */
  35203         LOG_ERROR(BSL_LS_BCM_OAM,
  35204                 (BSL_META_U(unit,
  35205                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35206                  unit, ep_id, bcm_errmsg(rv)));
  35207         _BCM_OAM_UNLOCK(oc);
  35208         return (rv);
  35209     }
  35210 
  35211     h_data_p =  &oc->oam_hash_data[ep_id];
  35212     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35213         _BCM_OAM_UNLOCK(oc);
  35214         return (BCM_E_INTERNAL);
  35215     }
  35216 
  35217     /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. 
  35218        Else return E_PARAM */
  35219     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35220         _BCM_OAM_UNLOCK(oc);
  35221         return BCM_E_PARAM;
  35222     }
  35223     /* Run through the egress_if_list and check whether given egress interface 
  35224        is configured for this endpoint */
  35225     list_node = h_data_p->egress_if_list;
  35226     while (list_node != NULL) {
  35227         if (egress_intf == list_node->egress_if) {
  35228             found = 1;
  35229             break;
  35230         }
  35231         list_node = list_node->next;
  35232     }
  35233 
  35234     if (!found) {
  35235         _BCM_OAM_UNLOCK(oc);
  35236         return BCM_E_NOT_FOUND;
  35237     }
  35238 
  35239     if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_intf)) {
  35240         egr_nh_index = egress_intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  35241     }
  35242     else if(BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_intf)) {
  35243         egr_nh_index = egress_intf - BCM_XGS3_EGRESS_IDX_MIN(unit);
  35244     } else {
  35245         _BCM_OAM_UNLOCK(oc);
  35246         return BCM_E_PARAM;
  35247     }
  35248 
  35249     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  35250     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
  35251             egr_nh_index, &egr_nh_entry);
  35252     if (BCM_FAILURE(rv)) {
  35253         _BCM_OAM_UNLOCK(oc);
  35254         return (rv);
  35255     }
  35256     mepid = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
  35257             MPLS__MEPIDf);
  35258     if ((MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) &&
  35259         (h_data_p->name != mepid)) {
  35260         _BCM_OAM_UNLOCK(oc);
  35261         return BCM_E_NOT_FOUND;
  35262     }
  35263     /* Reset the MPLS_OAM_DOWNMEP_ENABLE field */
  35264     soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35265             MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35266             0);
  35267 
  35268     /* Reset the MEP_ID field in EGR_L3_NEXT_HOP */
  35269     soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35270             MPLS__MEPIDf,
  35271             0);
  35272 
  35273     rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL,
  35274             egr_nh_index, &egr_nh_entry);
  35275     if (BCM_FAILURE(rv)) {
  35276         _BCM_OAM_UNLOCK(oc);
  35277         return (rv);
  35278     }
  35279 
  35280     /* Delete the egress_if (encap_id) from the endpoint's egress_if_list */
  35281     _bcm_sb2_oam_endpoint_egress_intf_delete(unit, h_data_p, egress_intf);
  35282 
  35283     _BCM_OAM_UNLOCK(oc);
  35284     rv = BCM_E_NONE;
  35285 #endif
  35286     return rv; 
  35287 }
  35288 
  35289 /*
  35290  * Function:
  35291  *      bcm_sb2_oam_endpoint_egress_intf_egress_attach_get 
  35292  * Purpose:
  35293  *      Get the list of Egress interfaces attached to MPLS LSP endpoint 
  35294  *
  35295  * Parameters:
  35296  *      unit        (IN) BCM device number
  35297  *      ep_d        (IN) BHH endpoint ID 
  35298  *      size        (IN) Size of array of egress interfaces passed in the egress_intf parameter. 
  35299  *      egress_intf (OUT) Array of Egress object
  35300  *      count       (OUT) The actual count of Egress interfaces returned in the egress_intf array.
  35301  *
  35302  * Returns:
  35303  *      BCM_E_NONE          No error
  35304  *      BCM_E_XXXX          Error
  35305  */
  35306 
  35307 int bcm_sb2_oam_endpoint_egress_intf_egress_attach_get(int unit,
  35308         bcm_oam_endpoint_t ep_id,
  35309         int size,
  35310         bcm_if_t *egress_intf,
  35311         int *count)
  35312 {
  35313     int rv = BCM_E_UNAVAIL; 
  35314 #if defined(INCLUDE_L3)
  35315     _bcm_oam_hash_data_t *h_data_p = NULL;
  35316     _bcm_oam_control_t *oc = NULL;
  35317     int index = 0;
  35318     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35319 
  35320     /* Check input parameters. */
  35321     if(size <= 0) {
  35322         return BCM_E_PARAM;
  35323     }
  35324 
  35325     if (egress_intf == NULL || count == NULL) {
  35326         return BCM_E_PARAM;
  35327     }
  35328     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35329     _BCM_OAM_EP_INDEX_VALIDATE(ep_id);
  35330 
  35331     _BCM_OAM_LOCK(oc);
  35332 
  35333     /* Check endpoint status. */
  35334     rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id);
  35335     if ((BCM_E_EXISTS != rv)) {
  35336         /* Endpoint not in use. */
  35337         LOG_ERROR(BSL_LS_BCM_OAM,
  35338                 (BSL_META_U(unit,
  35339                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35340                  unit, ep_id, bcm_errmsg(rv)));
  35341         _BCM_OAM_UNLOCK(oc);
  35342         return (rv);
  35343     }
  35344 
  35345     h_data_p =  &oc->oam_hash_data[ep_id];
  35346     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35347         _BCM_OAM_UNLOCK(oc);
  35348         return (BCM_E_INTERNAL);
  35349     }
  35350 
  35351     /* Check if it is a LSP endpoint */
  35352     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35353         _BCM_OAM_UNLOCK(oc);
  35354         return BCM_E_PARAM;
  35355     }
  35356     /* Run through the egress_if_list and fill the egress gport and egress
  35357      * interfaces */
  35358     list_node = h_data_p->egress_if_list;
  35359     while (list_node != NULL) {
  35360         egress_intf[index] = list_node->egress_if;
  35361         index++;
  35362         if (index == size) {
  35363             break;
  35364         }
  35365         list_node = list_node->next;
  35366     }
  35367     *count = index;
  35368 
  35369     _BCM_OAM_UNLOCK(oc);
  35370     rv = BCM_E_NONE;
  35371 #endif
  35372     return rv;
  35373 }
  35374 
  35375 int bcm_sb2_oam_endpoint_gport_egress_attach(int unit,
  35376                                              bcm_oam_endpoint_t endpoint,
  35377                                              bcm_gport_t gport)
  35378 {
  35379 #if defined(INCLUDE_L3)
  35380     bcm_if_t egress_if;
  35381     _bcm_oam_hash_data_t *h_data_p = NULL;
  35382     _bcm_oam_control_t *oc = NULL;
  35383     uint32 egr_nh_index = 0;
  35384     egr_l3_next_hop_entry_t egr_nh_entry;
  35385     int rv = BCM_E_NONE;
  35386     int found = 0;
  35387     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35388 
  35389     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35390     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  35391 
  35392     _BCM_OAM_LOCK(oc);
  35393 
  35394     /* Check endpoint status. */
  35395     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint);
  35396     if ((BCM_E_EXISTS != rv)) {
  35397         /* Endpoint not in use. */
  35398         LOG_ERROR(BSL_LS_BCM_OAM,
  35399                 (BSL_META_U(unit,
  35400                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35401                  unit, endpoint, bcm_errmsg(rv)));
  35402         _BCM_OAM_UNLOCK(oc);
  35403         return (rv);
  35404     }
  35405 
  35406     h_data_p =  &oc->oam_hash_data[endpoint];
  35407     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35408         _BCM_OAM_UNLOCK(oc);
  35409         return (BCM_E_INTERNAL);
  35410     }
  35411 
  35412     /* Check if it is an MPLS port and of type VPWS. Else return E_PARAM */
  35413     if (!BCM_GPORT_IS_MPLS_PORT(gport)) {
  35414         _BCM_OAM_UNLOCK(oc);
  35415         return BCM_E_PARAM;
  35416     }
  35417     /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */
  35418     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35419         _BCM_OAM_UNLOCK(oc);
  35420         return BCM_E_PARAM;
  35421     }
  35422 
  35423     /* Run through the egress_if_list and check if the given egress gport
  35424        already exists */
  35425     list_node = h_data_p->egress_if_list;
  35426     while (list_node != NULL) {
  35427         if (gport == list_node->gport) {
  35428             found = 1;
  35429             break;
  35430         }
  35431         list_node = list_node->next;
  35432     }
  35433     
  35434     if (found) {
  35435         _BCM_OAM_UNLOCK(oc);
  35436         return BCM_E_EXISTS;
  35437     }
  35438 
  35439     /* Do a MPLS Port get and get the encap_id */
  35440     rv = _bcm_tr_mpls_vpws_egress_if_get(unit, gport, &egress_if);
  35441     if (BCM_FAILURE(rv)) {
  35442         _BCM_OAM_UNLOCK(oc);
  35443         return BCM_E_PARAM;
  35444     }
  35445 
  35446     /* Check the encap id is of dvp egress type */
  35447     if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_if)) {
  35448         _BCM_OAM_UNLOCK(oc);
  35449         return BCM_E_PARAM;
  35450     }
  35451     /* Find the EGR_L3_NEXT_HOP index from encap id. */
  35452     egr_nh_index = egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  35453     /* Write the endpoint.name/id as MEP_ID into EGR_L3_NEXT_HOP */
  35454     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  35455     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
  35456             egr_nh_index, &egr_nh_entry);
  35457     if (BCM_FAILURE(rv)) {
  35458         _BCM_OAM_UNLOCK(oc);
  35459         return (rv);
  35460     }
  35461 
  35462     /* Depending on whether endpoint is BHH or MPLS LM/DM, write 1/2 in MPLS_OAM_DOWNMEP_ENABLE. */
  35463     if (BHH_EP_TYPE(h_data_p)) {
  35464 #if defined(INCLUDE_BHH)
  35465         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35466                                          MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35467                                          _BCM_SB2_MPLS_OAM_ENABLE_BHH);
  35468 
  35469         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35470                                          MPLS__MEPIDf,
  35471                                          BCM_OAM_BHH_GET_LSP_KEY(h_data_p));
  35472 #endif /* INCLUDE_BHH */
  35473     } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) {
  35474         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35475                                          MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35476                                          _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM);
  35477 
  35478         soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35479                                          MPLS__MEPIDf,
  35480                                          h_data_p->name);
  35481     } else {
  35482         _BCM_OAM_UNLOCK(oc);
  35483         return BCM_E_PARAM;
  35484     }
  35485 
  35486 
  35487     rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL,
  35488             egr_nh_index, &egr_nh_entry);
  35489     if (BCM_FAILURE(rv)) {
  35490         _BCM_OAM_UNLOCK(oc);
  35491         return (rv);
  35492     }
  35493 
  35494     /* Add the gport and egress_if (encap_id) into the endpoint's egress_if_list */
  35495     _bcm_sb2_oam_endpoint_egress_interface_add(unit, h_data_p, egress_if, gport);
  35496 
  35497 
  35498     _BCM_OAM_UNLOCK(oc);
  35499     return BCM_E_NONE;
  35500 #else
  35501     return BCM_E_UNAVAIL;
  35502 #endif
  35503 }
  35504 
  35505 int bcm_sb2_oam_endpoint_gport_egress_attach_get(int unit,
  35506                                                  bcm_oam_endpoint_t endpoint,
  35507                                                  int size,
  35508                                                  bcm_gport_t *gport,
  35509                                                  int *num_gports)
  35510 {
  35511 #if defined(INCLUDE_L3)
  35512     _bcm_oam_hash_data_t *h_data_p = NULL;
  35513     _bcm_oam_control_t *oc = NULL;
  35514     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35515     int rv = BCM_E_NONE;
  35516     int index = 0;
  35517 
  35518     /* Check input parameters. */
  35519     if(size <= 0) {
  35520         return BCM_E_PARAM;
  35521     }
  35522 
  35523     if (gport == NULL || num_gports == NULL) {
  35524         return BCM_E_PARAM;
  35525     }
  35526     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35527     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  35528 
  35529     _BCM_OAM_LOCK(oc);
  35530 
  35531     /* Check endpoint status. */
  35532     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint);
  35533     if ((BCM_E_EXISTS != rv)) {
  35534         /* Endpoint not in use. */
  35535         LOG_ERROR(BSL_LS_BCM_OAM,
  35536                 (BSL_META_U(unit,
  35537                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35538                  unit, endpoint, bcm_errmsg(rv)));
  35539         _BCM_OAM_UNLOCK(oc);
  35540         return (rv);
  35541     }
  35542 
  35543     h_data_p =  &oc->oam_hash_data[endpoint];
  35544     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35545         _BCM_OAM_UNLOCK(oc);
  35546         return (BCM_E_INTERNAL);
  35547     }
  35548 
  35549     /* Check if it is a LSP endpoint */
  35550     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35551         _BCM_OAM_UNLOCK(oc);
  35552         return BCM_E_PARAM;
  35553     }
  35554     /* Run through the egress_if_list and fill the egress gport and egress
  35555      * interfaces */
  35556     list_node = h_data_p->egress_if_list;
  35557     while (list_node != NULL) {
  35558         gport[index] = list_node->gport;
  35559         index++;
  35560         if (index == size) {
  35561             break;
  35562         }
  35563         list_node = list_node->next;
  35564     }
  35565     *num_gports = index;
  35566 
  35567     _BCM_OAM_UNLOCK(oc);
  35568     return BCM_E_NONE;
  35569 #else
  35570     return BCM_E_UNAVAIL;
  35571 #endif
  35572 }
  35573 
  35574 int bcm_sb2_oam_endpoint_gport_egress_detach(int unit,
  35575                                              bcm_oam_endpoint_t endpoint,
  35576                                              bcm_gport_t gport)
  35577 {
  35578 #if defined(INCLUDE_L3)
  35579     bcm_if_t egress_if;
  35580     _bcm_oam_hash_data_t *h_data_p = NULL;
  35581     _bcm_oam_control_t *oc = NULL;
  35582     uint32 egr_nh_index = 0;
  35583     egr_l3_next_hop_entry_t egr_nh_entry;
  35584     int found = 0;
  35585     _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL;
  35586     int rv = BCM_E_NONE;
  35587 
  35588     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35589     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  35590 
  35591     _BCM_OAM_LOCK(oc);
  35592 
  35593     /* Check endpoint status. */
  35594     rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint);
  35595     if ((BCM_E_EXISTS != rv)) {
  35596         /* Endpoint not in use. */
  35597         LOG_ERROR(BSL_LS_BCM_OAM,
  35598                 (BSL_META_U(unit,
  35599                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  35600                  unit, endpoint, bcm_errmsg(rv)));
  35601         _BCM_OAM_UNLOCK(oc);
  35602         return (rv);
  35603     }
  35604 
  35605     h_data_p =  &oc->oam_hash_data[endpoint];
  35606     if ((NULL == h_data_p) || (h_data_p->in_use == 0)) {
  35607         _BCM_OAM_UNLOCK(oc);
  35608         return (BCM_E_INTERNAL);
  35609     }
  35610 
  35611     /* Check if it is an MPLS port and of type VPWS. Else return E_PARAM */
  35612     if (!BCM_GPORT_IS_MPLS_PORT(gport)) {
  35613         _BCM_OAM_UNLOCK(oc);
  35614         return BCM_E_PARAM;
  35615     }
  35616     /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */
  35617     if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) {
  35618         _BCM_OAM_UNLOCK(oc);
  35619         return BCM_E_PARAM;
  35620     }
  35621     /* Run through the egress_if_list and find the given egress gport 
  35622        and get the corresponding interface */
  35623     list_node = h_data_p->egress_if_list;
  35624     while (list_node != NULL) {
  35625         if (gport == list_node->gport) {
  35626             found = 1;
  35627             egress_if = list_node->egress_if;
  35628             break;
  35629         }
  35630         list_node = list_node->next;
  35631     }
  35632     
  35633     if (!found) {
  35634         _BCM_OAM_UNLOCK(oc);
  35635         return BCM_E_NOT_FOUND;
  35636     }
  35637 
  35638     /* Find the EGR_L3_NEXT_HOP index from encap id. */
  35639     egr_nh_index = egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  35640 
  35641     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
  35642     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
  35643             egr_nh_index, &egr_nh_entry);
  35644     if (BCM_FAILURE(rv)) {
  35645         _BCM_OAM_UNLOCK(oc);
  35646         return (rv);
  35647     }
  35648 
  35649     /* Reset the MPLS_OAM_DOWNMEP_ENABLE field */
  35650     soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35651             MPLS__MPLS_OAM_DOWNMEP_ENABLEf,
  35652             0);
  35653 
  35654     /* Reset the MEP_ID field in EGR_L3_NEXT_HOP */
  35655     soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry,
  35656             MPLS__MEPIDf,
  35657             0);
  35658 
  35659     rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL,
  35660             egr_nh_index, &egr_nh_entry);
  35661     if (BCM_FAILURE(rv)) {
  35662         _BCM_OAM_UNLOCK(oc);
  35663         return (rv);
  35664     }
  35665 
  35666     /* Delete the gport and egress_if (encap_id) from the endpoint's 
  35667        egress_if_list */
  35668     _bcm_sb2_oam_endpoint_egress_interface_delete(unit, h_data_p, 
  35669                                                   gport);
  35670     
  35671     _BCM_OAM_UNLOCK(oc);
  35672     return BCM_E_NONE;
  35673 #else
  35674     return BCM_E_UNAVAIL;
  35675 #endif
  35676 }
  35677 
  35678 /*
  35679  * Function:
  35680  *      _bcm_sb2_bhh_endpoint_faults_multi_get
  35681  * Purpose:
  35682  *      Function to get faults for multiple BHH endpoints
  35683  *      in a single call.
  35684  * Parameters:
  35685  *      unit                (IN) BCM device number
  35686  *      flags               (IN) Flags is kept unused as of now. 
  35687  *                                This is for any future enhancement
  35688  *      max_endpoints       (IN) Number of max endpoint for the protocol
  35689  *      faults              (OUT) Pointer to faults for all endpoints
  35690  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults, 
  35691  *                                filled by get API. 
  35692  *
  35693  * Returns:
  35694  *      BCM_E_NONE          No error
  35695  *      BCM_E_XXXX          Error
  35696  */
  35697 
  35698 #if defined (INCLUDE_BHH)
  35699 int _bcm_sb2_bhh_endpoint_faults_multi_get(
  35700         int unit,
  35701         uint32 flags,
  35702         uint32 max_endpoints,
  35703         bcm_oam_endpoint_fault_t *faults,
  35704         uint32 *endpoint_count)
  35705 {
  35706     int rv = BCM_E_NONE; 
  35707     _bcm_oam_control_t *oc = NULL;
  35708     bcm_oam_endpoint_fault_t *faults_temp = faults;
  35709     uint8 *buffer;
  35710     uint16 reply_len;
  35711     uint32 sess_count;
  35712     uint32 ep_id;
  35713     uint32 ep_count = 0;
  35714     uint32 faults_bitmap;
  35715     _bcm_oam_hash_data_t *h_data_p;      /* Pointer to endpoint hash data.    */
  35716 
  35717     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35718 
  35719     _BCM_OAM_LOCK(oc);
  35720 
  35721     if(max_endpoints != oc->bhh_endpoint_count) {
  35722         rv = BCM_E_PARAM;
  35723         _BCM_OAM_UNLOCK(oc);
  35724         return (rv);
  35725     }
  35726 
  35727     sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints));
  35728 
  35729     rv = _bcm_sb2_oam_bhh_msg_send_receive(unit,
  35730             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET,
  35731             0, 0,
  35732             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY,
  35733             &reply_len);
  35734 
  35735     if (BCM_FAILURE(rv)) {
  35736         LOG_ERROR(BSL_LS_BCM_OAM,
  35737                 (BSL_META_U(unit,
  35738                             "OAM(unit %d) Error: BHH uKernel msg failed for"
  35739                             "faults multi get %s.\n"), unit,
  35740                  bcm_errmsg(rv)));
  35741         _BCM_OAM_UNLOCK(oc);
  35742         return (rv);
  35743     }
  35744 
  35745     if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) {
  35746         rv = BCM_E_INTERNAL;
  35747         _BCM_OAM_UNLOCK(oc);
  35748         return (rv);
  35749     }
  35750     /* Unpack control message data into DMA buffer */
  35751     buffer = oc->dma_buffer;
  35752     for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++)
  35753     {
  35754         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  35755 
  35756         /* Validate endpoint index value. */
  35757         BCM_OAM_BHH_VALIDATE_EP(ep_id)
  35758 
  35759         h_data_p =  &oc->oam_hash_data[ep_id];
  35760         
  35761         /* If endpoint not in use, ignore and continue for next session_id).
  35762          * If session is running in hostCPU, skip and Go to ep_id.*/
  35763         if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  35764            continue; 
  35765         }
  35766 
  35767          _SHR_UNPACK_U32(buffer, faults_bitmap);
  35768 
  35769         faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  35770 
  35771         if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){
  35772             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  35773         }  
  35774         if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){
  35775             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  35776         }  
  35777         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  35778             faults_temp->faults |= 
  35779                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  35780         }  
  35781         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  35782             faults_temp->faults |= 
  35783                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  35784         }  
  35785         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  35786             faults_temp->faults |= 
  35787                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  35788         }  
  35789         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  35790             faults_temp->faults |= 
  35791                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  35792         }  
  35793         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  35794             faults_temp->faults |= 
  35795                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  35796         }
  35797 
  35798         ep_count++;
  35799         faults_temp++;
  35800 
  35801     }
  35802 
  35803     *endpoint_count = ep_count;
  35804     _BCM_OAM_UNLOCK(oc);
  35805     return (rv);
  35806 
  35807 }
  35808 #endif
  35809 
  35810 /*
  35811  * Function:
  35812  *      bcm_sb2_oam_endpoint_faults_multi_get
  35813  * Purpose:
  35814  *      Function to get faults for multiple endpoints per protocl
  35815  *      in a single call.
  35816  * Parameters:
  35817  *      unit                (IN) BCM device number
  35818  *      flags               (IN) Flags is kept unused as of now. 
  35819  *                               This is for any future enhancement
  35820  *      endpoint_protocol   (IN) Protocol type of the endpoints to retrieve faults
  35821  *      max_endpoints       (IN) Number of max endpoint for the protocol
  35822  *      faults              (OUT) Pointer to faults for all endpoints
  35823  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults, 
  35824  *                                by get API. 
  35825  *
  35826  * Returns:
  35827  *      BCM_E_NONE          No error
  35828  *      BCM_E_XXXX          Error
  35829  */
  35830 
  35831 int bcm_sb2_oam_endpoint_faults_multi_get(
  35832         int unit,
  35833         uint32 flags,
  35834         bcm_oam_protocol_type_t endpoint_protocol,
  35835         uint32 max_endpoints,
  35836         bcm_oam_endpoint_fault_t *faults,
  35837         uint32 *endpoint_count)
  35838 
  35839 {
  35840     int rv = BCM_E_NONE;
  35841 
  35842     if(!faults) {
  35843         rv = BCM_E_PARAM;
  35844         return (rv);
  35845     }
  35846 
  35847     switch(endpoint_protocol) {
  35848 
  35849 #if defined(INCLUDE_BHH)
  35850         case bcmOamProtocolBhh:
  35851             *endpoint_count = 0;
  35852             rv = _bcm_sb2_bhh_endpoint_faults_multi_get(
  35853                     unit,
  35854                     flags,
  35855                     max_endpoints,
  35856                     faults,
  35857                     endpoint_count);
  35858         break;
  35859 #endif        
  35860         default:
  35861             rv = BCM_E_UNAVAIL;
  35862             break;
  35863     }
  35864 
  35865     return rv;
  35866 
  35867 }
  35868 
  35869 /* This function assumes passed endpoint is a PORT MEP configured over trunk. */
  35870 int _bcm_sb2_oam_ep_trunk_ports_add_del_internal(int unit, _bcm_oam_hash_data_t *h_data_p, 
  35871                                     int max_ports, bcm_gport_t *port_arr, uint8 add)
  35872 {
  35873     _bcm_oam_hash_data_t old_hash_data;
  35874     bcm_oam_endpoint_info_t ep_info;
  35875     uint32 sglp = 0, dglp = 0;
  35876     bcm_port_t src_pp_port = 0, dst_pp_port = 0, pp_port = 0;
  35877     uint32 svp = 0;
  35878     int vp_valid = 0;
  35879     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  35880     bcm_trunk_member_t trunk_member;
  35881     int i, module_id = 0;
  35882     uint8 active_mdl = 0;
  35883     
  35884 
  35885     bcm_oam_endpoint_info_t_init(&ep_info);
  35886     /* **********************************************
  35887      *               SW configurations
  35888  */
  35889     /* Keep a copy of old hash data for comparisons.
  35890      */
  35891     sal_memcpy(&old_hash_data, h_data_p, sizeof(_bcm_oam_hash_data_t));
  35892 
  35893 
  35894     /* Call endpoint get to get the endpoint info */
  35895     BCM_IF_ERROR_RETURN(bcm_sb2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info));
  35896     /* First call endpoint gport resolve to correctly update new
  35897      * sglp, dglp, src_pp_port, dst_pp_port variables.
  35898      */
  35899     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_endpoint_gport_resolve(unit, &ep_info, &sglp, &dglp,
  35900                                                             &src_pp_port, &dst_pp_port, &svp,
  35901                                                             &trunk_id, &vp_valid, &trunk_member));
  35902                                                             
  35903     /* Update the h_data_p. */
  35904     h_data_p->sglp                 = sglp;
  35905     h_data_p->dglp                 = dglp;
  35906     h_data_p->src_pp_port          = src_pp_port;
  35907     h_data_p->dst_pp_port          = dst_pp_port;
  35908     h_data_p->resolved_trunk_gport = trunk_member.gport;
  35909 
  35910     /* ************************************************
  35911      *               HW configurations
  35912  */
  35913 
  35914     for (i = 0; i < max_ports; i++) {
  35915         BCM_IF_ERROR_RETURN
  35916             (_bcm_kt2_pp_port_to_modport_get(unit, port_arr[i],
  35917                                              &module_id, &pp_port));
  35918         if (add) {
  35919             /* _bcm_sb2_oam_trunk_port_mdl_config needs to be called so that
  35920              * new trunk members are programmed with MDL_BITMAP correctly.
  35921              */
  35922             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_stm_table_update(unit, module_id, pp_port, h_data_p));
  35923             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_update(unit, pp_port, 0, h_data_p, &active_mdl));
  35924         } else {
  35925             /* Delete the old ports' MDL BITMAP using _bcm_sb2_oam_port_mdl_update. And
  35926              * clear STM table if this is the last endpoint on this port.
  35927              */
  35928             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_update(unit, pp_port, 1, h_data_p, &active_mdl));
  35929             if (active_mdl == 0) {
  35930                 /* Setting index = -1 so that rx indexes are not freed up, since there are
  35931                  * other ports on the trunk on which this endpoint is placed.
  35932                  */
  35933                 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_stm_table_clear(unit, module_id, -1,
  35934                             pp_port, 
  35935                             h_data_p));
  35936             }
  35937         }
  35938     }
  35939     
  35940     if (h_data_p->dst_pp_port != old_hash_data.dst_pp_port) {
  35941         /* If dst_pp_port has changed, delete the old EGR_PORT MDL_PASSIVE BITMAP and
  35942          * program the new port's EGR_PORT MDL_PASSIVE_BITMAP.
  35943          */
  35944         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_passive_update(unit,1, &old_hash_data, 0));
  35945         BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_passive_update(unit, 0 /* not reset */,
  35946                                                                 h_data_p, active_mdl));
  35947         
  35948         if (ep_info.ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) {
  35949             /* If dst_pp_port has changed, modify the LMEP table to reflect new
  35950              * dst pp port and corresponding queue number.
  35951              */
  35952             BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lmep_down_modify_new_dest_port(unit, h_data_p));
  35953         }
  35954     }
  35955 
  35956     return BCM_E_NONE;
  35957 } 
  35958 
  35959 
  35960 int _bcm_sb2_oam_trunk_ports_add_del_internal(int unit, bcm_gport_t trunk_gport, 
  35961                                 int max_ports, bcm_gport_t *port_arr, uint8 add)
  35962 {
  35963     int rv = BCM_E_NONE;
  35964     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  35965     _bcm_oam_control_t  *oc = NULL;
  35966     _bcm_oam_hash_data_t *h_data_p = NULL;
  35967     int i;
  35968 
  35969 
  35970     /* Validate port array and max ports inputs */
  35971     if (port_arr == NULL || max_ports == 0) {
  35972         return BCM_E_PARAM;
  35973     }
  35974 
  35975     /* Check the gport is TRUNK */ 
  35976     if (!(BCM_GPORT_IS_TRUNK(trunk_gport))) {
  35977         return BCM_E_PARAM;
  35978     }
  35979 
  35980     /* Get Trunk ID value from Gport */
  35981     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  35982 
  35983     if (trunk_id == BCM_TRUNK_INVALID) {
  35984         return BCM_E_PARAM;
  35985     }
  35986 
  35987     /* Get OAM control structure */
  35988     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  35989     _BCM_OAM_LOCK(oc);
  35990 
  35991     for (i = 0; i < oc->ep_count; i++) {
  35992         h_data_p = &oc->oam_hash_data[i];
  35993         /* This API is supported only for PORT MEPs on Trunks */
  35994         if ((ETH_TYPE(h_data_p->type)) && 
  35995             (h_data_p->in_use) && 
  35996             (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) &&
  35997             (h_data_p->gport      == trunk_gport) &&
  35998             (h_data_p->trunk_id == trunk_id)) {
  35999             rv = _bcm_sb2_oam_ep_trunk_ports_add_del_internal(unit, h_data_p, max_ports, port_arr, add); 
  36000             if (BCM_FAILURE(rv)) {
  36001                 _BCM_OAM_UNLOCK(oc);
  36002                 return rv;
  36003             }
  36004         }
  36005     }
  36006     _BCM_OAM_UNLOCK(oc);
  36007     return rv;
  36008 }
  36009 
  36010 int bcm_sb2_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 
  36011                                 int max_ports, bcm_gport_t *port_arr)
  36012 {
  36013     return _bcm_sb2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 1);
  36014 }
  36015 int bcm_sb2_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 
  36016                                 int max_ports, bcm_gport_t *port_arr)
  36017 {
  36018     return _bcm_sb2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 0);
  36019 }
  36020 
  36021 /*
  36022  * Function:
  36023  *      bcm_ml_oam_opcodes_count_profile_create
  36024  * Purpose:
  36025  *      Create a new LM count profile for opcodes with all opcodes having counting disabled. 
  36026  *      The id of the profile created is returned in lm_count_profile variable.
  36027  * Parameters:
  36028  *      unit                (IN) BCM device number
  36029  *      lm_count_profile    (OUT) lm_count_profile id that will be returned by create API and 
  36030  *                                will be used for count_profile_set 
  36031  *
  36032  * Returns:
  36033  *      BCM_E_NONE          No error
  36034  *      BCM_E_XXXX          Error
  36035  */
  36036 #if defined(BCM_METROLITE_SUPPORT)
  36037 int bcm_ml_oam_opcodes_count_profile_create(
  36038         int unit,
  36039         uint8 *lm_count_profile)
  36040 
  36041 {
  36042     int rv = BCM_E_NONE;
  36043     _bcm_oam_control_t *oc = NULL;
  36044     void        *entries[1];   /* Profile entry. */
  36045     ing_lm_counter_control_entry_t *ing_lm_counter_control_entry;
  36046     egr_lm_counter_control_entry_t *egr_lm_counter_control_entry;
  36047     uint32 ing_lm_profile_index = -1;
  36048     uint32 egr_lm_profile_index = -1;
  36049 
  36050     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  36051 
  36052     _BCM_OAM_LOCK(oc);
  36053 
  36054     /* ING OAM LM count control profile */
  36055     ing_lm_counter_control_entry = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36056                                                 "ING OAM LM count control profile");
  36057     if(!ing_lm_counter_control_entry) {
  36058         _BCM_OAM_UNLOCK(oc);
  36059         rv = BCM_E_MEMORY;
  36060         return rv;
  36061     }    
  36062     
  36063     sal_memset(ing_lm_counter_control_entry, 0, 
  36064                             _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36065     /* Add entry to profile table.  */
  36066     entries[0] = ing_lm_counter_control_entry;
  36067     rv = soc_profile_mem_add(unit, &oc->ing_lm_counter_control_profile,
  36068             (void *)entries, 
  36069             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE,
  36070             &ing_lm_profile_index);
  36071    
  36072    if (BCM_FAILURE(rv)) {
  36073         LOG_ERROR(BSL_LS_BCM_OAM,
  36074                 (BSL_META_U(unit,
  36075                             "OAM(unit %d) ING OAM LM count control profile table is full - %s.\n"),
  36076                  unit, bcm_errmsg(rv)));
  36077         if(ing_lm_counter_control_entry) {
  36078             sal_free(ing_lm_counter_control_entry);
  36079         }
  36080         _BCM_OAM_UNLOCK(oc);
  36081         return rv;
  36082     }
  36083   
  36084    if(ing_lm_counter_control_entry) {
  36085        sal_free(ing_lm_counter_control_entry);
  36086    }
  36087 
  36088     /* EGR OAM LM count control profile */
  36089     egr_lm_counter_control_entry = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36090                                                 "EGR OAM LM count control profile");
  36091     if(!egr_lm_counter_control_entry) {
  36092         _BCM_OAM_UNLOCK(oc);
  36093         rv = BCM_E_MEMORY;
  36094         return rv;
  36095     }     
  36096     
  36097     sal_memset(egr_lm_counter_control_entry, 0, 
  36098                             _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36099     
  36100     /* Add entry to profile table.  */
  36101     entries[0] = egr_lm_counter_control_entry;
  36102     rv = soc_profile_mem_add(unit, &oc->egr_lm_counter_control_profile,
  36103             (void *)entries, 
  36104             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE,
  36105             &egr_lm_profile_index);
  36106     
  36107     if (BCM_FAILURE(rv)) {
  36108         LOG_ERROR(BSL_LS_BCM_OAM,
  36109                 (BSL_META_U(unit,
  36110                             "OAM(unit %d) EGR OAM LM count control profile table is full - %s.\n"),
  36111                  unit, bcm_errmsg(rv)));
  36112         if(egr_lm_counter_control_entry) {
  36113             sal_free(egr_lm_counter_control_entry);
  36114         }
  36115         _BCM_OAM_UNLOCK(oc);
  36116         return rv;
  36117     }
  36118     if(egr_lm_counter_control_entry) {
  36119         sal_free(egr_lm_counter_control_entry);
  36120     }
  36121 
  36122     /* The ingress and egress profile index should match as they are identical tables 
  36123      * But if one of them is mistakenly written before calling this API, It will prohibit
  36124      * different profile index for ingress and egress */
  36125 
  36126     if(egr_lm_profile_index != ing_lm_profile_index) {
  36127         rv = BCM_E_INTERNAL;
  36128         _BCM_OAM_UNLOCK(oc);
  36129         return rv;
  36130     }
  36131 
  36132     *lm_count_profile = _BCM_ML_OAM_GET_LM_COUNTER_CONTROL_PROFILE_PTR_FROM_INDEX(ing_lm_profile_index);
  36133 
  36134     _BCM_OAM_UNLOCK(oc);
  36135     return rv;
  36136 
  36137 }
  36138 
  36139 /*
  36140  * Function:
  36141  *      bcm_oam_opcodes_count_profile_set
  36142  * Purpose:
  36143  *      Enable/disable counting for the opcodes in the opcodes_bitmap 
  36144  *      in the profile pointed by lm_count_profile variable.
  36145  * Parameters:
  36146  *      unit                (IN) BCM device number
  36147  *      lm_count_profile    (IN) OAM lm count profile index 
  36148  *      count_enable        (IN) Setting count enable (1) or disable (0)
  36149  *      opcodes_bitmap      (IN) Opcode Bitmap for setting count for opcode packets
  36150  *
  36151  * Returns:
  36152  *      BCM_E_NONE          No error
  36153  *      BCM_E_XXXX          Error
  36154  */
  36155 
  36156 int 
  36157 bcm_ml_oam_opcodes_count_profile_set(
  36158         int unit, 
  36159         uint8 lm_count_profile, 
  36160         uint8 count_enable, 
  36161         bcm_oam_opcodes_t *opcodes_bitmap) 
  36162 {    
  36163     int            rv = BCM_E_NONE;  /* Operation return status.          */
  36164     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  36165     void                 *entries[1]; 
  36166     int                  opcode_i;
  36167     soc_profile_mem_t    *profile_mem_ptr;
  36168     ing_lm_counter_control_entry_t *ing_lm_counter_control_profile;
  36169     egr_lm_counter_control_entry_t *egr_lm_counter_control_profile;
  36170     
  36171     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  36172 
  36173     _BCM_OAM_LOCK(oc);
  36174 
  36175     /* Setting ING_LM_COUNTER_CONTROL prpofile */
  36176     profile_mem_ptr = &oc->ing_lm_counter_control_profile;
  36177     
  36178     ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36179                                                 "ING OAM LM count control profile");
  36180     if(!ing_lm_counter_control_profile) {
  36181         _BCM_OAM_UNLOCK(oc);
  36182         rv = BCM_E_MEMORY;
  36183         return rv;
  36184     }
  36185     sal_memset(ing_lm_counter_control_profile, 0, 
  36186                             _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36187 
  36188     entries[0] = ing_lm_counter_control_profile;
  36189     
  36190     /* Get the profile with the given index to get the current status 
  36191      * of the profile in HW */
  36192     rv = soc_profile_mem_get(unit, profile_mem_ptr,
  36193             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile),
  36194             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries);
  36195 
  36196     if (BCM_FAILURE(rv)) {
  36197         LOG_ERROR(BSL_LS_BCM_OAM,
  36198                 (BSL_META_U(unit,
  36199                     "OAM(unit %d) Error: ING OAM LM count control profile Get failed "
  36200                             "  %s.\n"), unit, bcm_errmsg(rv)));
  36201         if(ing_lm_counter_control_profile) {
  36202             sal_free(ing_lm_counter_control_profile);
  36203         }
  36204         _BCM_OAM_UNLOCK(oc);
  36205         return (rv);
  36206     }
  36207 
  36208     for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE;
  36209             opcode_i++) {
  36210         /* Set the count_enable for the opcodes in the bitmap */
  36211         if(BCM_OAM_OPCODES_BITMAP_GET(*opcodes_bitmap,opcode_i)){
  36212             
  36213             soc_mem_field32_set(unit, ING_LM_COUNTER_CONTROLm, 
  36214                                &ing_lm_counter_control_profile[opcode_i],COUNT_ENABLEf, count_enable);
  36215         }
  36216     }
  36217 
  36218     rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *) entries, 
  36219         _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile));
  36220     if (BCM_FAILURE(rv)) {
  36221         LOG_ERROR(BSL_LS_BCM_OAM,
  36222                 (BSL_META_U(unit,
  36223                             "OAM(unit %d) ING OAM LM count control profile Set failed - %s.\n"),
  36224                  unit, bcm_errmsg(rv)));
  36225         if(ing_lm_counter_control_profile) {
  36226             sal_free(ing_lm_counter_control_profile);
  36227         }     
  36228         _BCM_OAM_UNLOCK(oc);
  36229         return rv;
  36230     }
  36231     
  36232     if(ing_lm_counter_control_profile) {
  36233         sal_free(ing_lm_counter_control_profile);
  36234     }     
  36235     
  36236     /* Setting EGR_LM_COUNTER_CONTROL prpofile */
  36237     profile_mem_ptr = &oc->egr_lm_counter_control_profile;
  36238     
  36239     egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36240                                                 "EGR OAM LM count control profile");
  36241     if(!egr_lm_counter_control_profile) {
  36242         _BCM_OAM_UNLOCK(oc);
  36243         rv = BCM_E_MEMORY;
  36244         return rv;
  36245     }
  36246     sal_memset(egr_lm_counter_control_profile, 0, 
  36247                             _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36248 
  36249     entries[0] = egr_lm_counter_control_profile;
  36250 
  36251     /* Get the profile with the given index to get the current status 
  36252      * of the profile in HW */
  36253     rv = soc_profile_mem_get(unit, profile_mem_ptr,
  36254             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile),
  36255             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries);
  36256 
  36257     if (BCM_FAILURE(rv)) {
  36258         LOG_ERROR(BSL_LS_BCM_OAM,
  36259                 (BSL_META_U(unit,
  36260                     "OAM(unit %d) Error: EGR OAM LM count control profile Get failed "
  36261                             "  %s.\n"), unit, bcm_errmsg(rv)));
  36262         if(egr_lm_counter_control_profile) {
  36263             sal_free(egr_lm_counter_control_profile);
  36264         }
  36265         _BCM_OAM_UNLOCK(oc);
  36266         return (rv);
  36267     }
  36268 
  36269     for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE;
  36270             opcode_i++) {
  36271         /* Set the count_enable for the opcodes in the bitmap */
  36272         if(BCM_OAM_OPCODES_BITMAP_GET(*opcodes_bitmap,opcode_i)){
  36273             
  36274             soc_mem_field32_set(unit, EGR_LM_COUNTER_CONTROLm, 
  36275                                &egr_lm_counter_control_profile[opcode_i], COUNT_ENABLEf, count_enable);
  36276         }
  36277     }
  36278     
  36279     rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *)entries, 
  36280         _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile));
  36281     if (BCM_FAILURE(rv)) {
  36282         LOG_ERROR(BSL_LS_BCM_OAM,
  36283                 (BSL_META_U(unit,
  36284                             "OAM(unit %d) ING OAM LM count control profile Set failed - %s.\n"),
  36285                  unit, bcm_errmsg(rv)));
  36286         if(egr_lm_counter_control_profile) {
  36287             sal_free(egr_lm_counter_control_profile);
  36288         }     
  36289         _BCM_OAM_UNLOCK(oc);
  36290         return rv;
  36291     }
  36292     
  36293     if(egr_lm_counter_control_profile) {
  36294         sal_free(egr_lm_counter_control_profile);
  36295     }
  36296 
  36297     _BCM_OAM_UNLOCK(oc);
  36298     return rv;
  36299 }
  36300 
  36301 /*
  36302  * Function:
  36303  *      bcm_oam_opcodes_count_profile_get
  36304  * Purpose:
  36305  *      Enable/disable counting for the opcodes in the opcodes_bitmap 
  36306  *      in the profile pointed by lm_count_profile variable.
  36307  * Parameters:
  36308  *      unit                (IN) BCM device number
  36309  *      lm_count_profile    (IN) OAM lm count profile index 
  36310  *      count_enable        (IN) Given count enable (1) or disable (0)
  36311  *      opcodes_bitmap      (OUT) Opcode Bitmap for the given count_enable 
  36312  *                                  information with the given lm_count_profile
  36313  *
  36314  * Returns:
  36315  *      BCM_E_NONE          No error
  36316  *      BCM_E_XXXX          Error
  36317  */
  36318 int 
  36319 bcm_ml_oam_opcodes_count_profile_get(
  36320         int unit, 
  36321         uint8 lm_count_profile, 
  36322         uint8 count_enable, 
  36323         bcm_oam_opcodes_t *opcodes_bitmap) 
  36324 {    
  36325     int            rv = BCM_E_NONE;  /* Operation return status.          */
  36326     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  36327     void                 *entries[1]; 
  36328     int                  opcode_i;
  36329     soc_profile_mem_t    *profile_mem_ptr;
  36330     ing_lm_counter_control_entry_t *ing_lm_counter_control_profile;
  36331     egr_lm_counter_control_entry_t *egr_lm_counter_control_profile;
  36332     uint8 count_enable_get;
  36333 
  36334     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  36335 
  36336     _BCM_OAM_LOCK(oc);
  36337 
  36338     /* Setting ING_LM_COUNTER_CONTROL prpofile */
  36339     profile_mem_ptr = &oc->ing_lm_counter_control_profile;
  36340     
  36341     ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36342                                                 "ING OAM LM count control profile");
  36343     if(!ing_lm_counter_control_profile) {
  36344         _BCM_OAM_UNLOCK(oc);
  36345         rv = BCM_E_MEMORY;
  36346         return rv;
  36347     }
  36348     sal_memset(ing_lm_counter_control_profile, 0, 
  36349                             _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36350 
  36351     entries[0] = ing_lm_counter_control_profile;
  36352     
  36353     /* Get the profile with the given index to get the current status 
  36354      * of the profile in HW */
  36355     rv = soc_profile_mem_get(unit, profile_mem_ptr,
  36356             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile),
  36357             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries);
  36358 
  36359     if (BCM_FAILURE(rv)) {
  36360         LOG_ERROR(BSL_LS_BCM_OAM,
  36361                 (BSL_META_U(unit,
  36362                     "OAM(unit %d) Error: ING OAM LM count control profile Get failed "
  36363                             "  %s.\n"), unit, bcm_errmsg(rv)));
  36364         if(ing_lm_counter_control_profile) {
  36365             sal_free(ing_lm_counter_control_profile);
  36366         }
  36367         _BCM_OAM_UNLOCK(oc);
  36368         return (rv);
  36369     }
  36370     
  36371     /* Setting EGR_LM_COUNTER_CONTROL prpofile */
  36372     profile_mem_ptr = &oc->egr_lm_counter_control_profile;
  36373     
  36374     egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36375                                                 "EGR OAM LM count control profile");
  36376     if(!egr_lm_counter_control_profile) {
  36377         _BCM_OAM_UNLOCK(oc);
  36378         rv = BCM_E_MEMORY;
  36379         return rv;
  36380     }
  36381     sal_memset(egr_lm_counter_control_profile, 0, 
  36382                             _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36383 
  36384     entries[0] = egr_lm_counter_control_profile;
  36385 
  36386     /* Get the profile with the given index to get the current status 
  36387      * of the profile in HW */
  36388     rv = soc_profile_mem_get(unit, profile_mem_ptr,
  36389             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile),
  36390             _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries);
  36391 
  36392     if (BCM_FAILURE(rv)) {
  36393         LOG_ERROR(BSL_LS_BCM_OAM,
  36394                 (BSL_META_U(unit,
  36395                             "OAM(unit %d) Error: EGR OAM LM count control profile Get failed "
  36396                             "  %s.\n"), unit, bcm_errmsg(rv)));
  36397         if(ing_lm_counter_control_profile) {
  36398             sal_free(ing_lm_counter_control_profile);
  36399         }        
  36400 
  36401         if(egr_lm_counter_control_profile) {
  36402             sal_free(egr_lm_counter_control_profile);
  36403         }
  36404         _BCM_OAM_UNLOCK(oc);
  36405         return (rv);
  36406     }
  36407 
  36408     /* The prfoile entries for ingress and egress table should match */
  36409     if(sal_memcmp(ing_lm_counter_control_profile, egr_lm_counter_control_profile, 
  36410                 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE)) {
  36411 
  36412         rv = BCM_E_INTERNAL;
  36413         _BCM_OAM_UNLOCK(oc);
  36414         return (rv);
  36415     }
  36416 
  36417     for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE;
  36418             opcode_i++) {
  36419         /* Set the count_enable for the opcodes in the bitmap */
  36420         count_enable_get = soc_mem_field32_get(unit, EGR_LM_COUNTER_CONTROLm, 
  36421                                &egr_lm_counter_control_profile[opcode_i], COUNT_ENABLEf);
  36422  
  36423         if(count_enable == count_enable_get) {
  36424             BCM_OAM_OPCODES_BITMAP_SET(*opcodes_bitmap,opcode_i);
  36425         }
  36426     }
  36427 
  36428     if(ing_lm_counter_control_profile) {
  36429         sal_free(ing_lm_counter_control_profile);
  36430     }
  36431 
  36432     if(egr_lm_counter_control_profile) {
  36433         sal_free(egr_lm_counter_control_profile);
  36434     }
  36435     _BCM_OAM_UNLOCK(oc); 
  36436     return rv;
  36437 }
  36438 
  36439 /*
  36440  * Function:
  36441  *      bcm_ml_oam_opcodes_count_profile_delete 
  36442  * Purpose:
  36443  *      Delete the count profile with the id lm_count_profile 
  36444  * Parameters:
  36445  *      unit                (IN) BCM device number
  36446  *      lm_count_profile    (IN) Id of the lm_count_profile id that will be deleted
  36447  *
  36448  * Returns:
  36449  *      BCM_E_NONE          No error
  36450  *      BCM_E_XXXX          Error
  36451  */
  36452 int 
  36453 bcm_ml_oam_opcodes_count_profile_delete(
  36454         int unit, 
  36455         uint8 lm_count_profile) 
  36456 {    
  36457     int            rv = BCM_E_NONE;  /* Operation return status.          */
  36458     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
  36459     void                 *entries[1]; 
  36460     soc_profile_mem_t    *profile_mem_ptr;
  36461     ing_lm_counter_control_entry_t *ing_lm_counter_control_profile;
  36462     egr_lm_counter_control_entry_t *egr_lm_counter_control_profile;
  36463     
  36464     BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc));
  36465 
  36466     _BCM_OAM_LOCK(oc);
  36467 
  36468     /* Setting ING_LM_COUNTER_CONTROL prpofile */
  36469     profile_mem_ptr = &oc->ing_lm_counter_control_profile;
  36470     
  36471     ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36472                                                 "ING OAM LM count control profile");
  36473     if(!ing_lm_counter_control_profile) {
  36474         _BCM_OAM_UNLOCK(oc);
  36475         rv = BCM_E_MEMORY;
  36476         return rv;
  36477     }
  36478     sal_memset(ing_lm_counter_control_profile, 0, 
  36479                             _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36480 
  36481     entries[0] = ing_lm_counter_control_profile;
  36482     
  36483     rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *) entries, 
  36484             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile));
  36485     if (BCM_FAILURE(rv)) {
  36486         LOG_ERROR(BSL_LS_BCM_OAM,
  36487                 (BSL_META_U(unit,
  36488                             "OAM(unit %d) ING OAM LM count control profile Get failed - %s.\n"),
  36489                  unit, bcm_errmsg(rv)));
  36490         if(ing_lm_counter_control_profile) {
  36491             sal_free(ing_lm_counter_control_profile);
  36492         }     
  36493         _BCM_OAM_UNLOCK(oc);
  36494         return rv;
  36495     }
  36496     
  36497     if(ing_lm_counter_control_profile) {
  36498         sal_free(ing_lm_counter_control_profile);
  36499     }     
  36500     
  36501     /* Setting EGR_LM_COUNTER_CONTROL prpofile */
  36502     profile_mem_ptr = &oc->egr_lm_counter_control_profile;
  36503     
  36504     egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 
  36505                                                 "EGR OAM LM count control profile");
  36506     if(!egr_lm_counter_control_profile) {
  36507         _BCM_OAM_UNLOCK(oc);
  36508         rv = BCM_E_MEMORY;
  36509         return rv;
  36510     }
  36511     sal_memset(egr_lm_counter_control_profile, 0, 
  36512                             _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE);
  36513 
  36514     entries[0] = egr_lm_counter_control_profile;
  36515     
  36516     rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *)entries, 
  36517             _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile));
  36518     if (BCM_FAILURE(rv)) {
  36519         LOG_ERROR(BSL_LS_BCM_OAM,
  36520                 (BSL_META_U(unit,
  36521                             "OAM(unit %d) ING OAM LM count control profile Get failed - %s.\n"),
  36522                  unit, bcm_errmsg(rv)));
  36523         if(egr_lm_counter_control_profile) {
  36524             sal_free(egr_lm_counter_control_profile);
  36525         }     
  36526         _BCM_OAM_UNLOCK(oc);
  36527         return rv;
  36528     }
  36529     
  36530     if(egr_lm_counter_control_profile) {
  36531         sal_free(egr_lm_counter_control_profile);
  36532     }
  36533 
  36534     _BCM_OAM_UNLOCK(oc);
  36535     return rv;
  36536 }
  36537 #endif /* BCM_METROLITE_SUPPORT */
  36538 #endif /* BCM_SABER2_SUPPORT */